+2021-04-28  Jan Beulich  <jbeulich@suse.com>
+            H.J. Lu  <hjl.tools@gmail.com>
+
+       PR gas/27763
+       * config/tc-i386.c (output_jump): Also mark 2-byte relocs as
+       signed for XBEGIN. Also mark 4-byte relocs as signed for 64-bit.
+       (output_disp): Also mark 4-byte relocs as signed for 64-bit.
+       (md_estimate_size_before_relax): Move local variable fixP. Set
+       it from fix_new() return values. Mark 4-byte relocs as signed
+       for 64-bit.
+       * testsuite/gas/i386/pcrel64.s, testsuite/gas/i386/pcrel64.l,
+       * testsuite/gas/i386/x86-64-rip-2.s,
+       * testsuite/gas/i386/x86-64-rip-2.d,
+       * testsuite/gas/i386/x86-64-rip-inval-1.s,
+       * testsuite/gas/i386/x86-64-rip-inval-1.l,
+       * testsuite/gas/i386/x86-64-rip-inval-2.s,
+       * testsuite/gas/i386/x86-64-rip-inval-2.l: New.
+       * testsuite/gas/i386/i386.exp: Run new tests.
+
 2021-04-27  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/tc-i386.c (optimize_encoding): Add () to silence GCC 5.
 
   fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
                      i.op[0].disps, 1, jump_reloc);
 
-  /* All jumps handled here are signed, but don't use a signed limit
-     check for 32 and 16 bit jumps as we want to allow wrap around at
-     4G and 64k respectively.  */
-  if (size == 1)
-    fixP->fx_signed = 1;
+  /* All jumps handled here are signed, but don't unconditionally use a
+     signed limit check for 32 and 16 bit jumps as we want to allow wrap
+     around at 4G (outside of 64-bit mode) and 64k (except for XBEGIN)
+     respectively.  */
+  switch (size)
+    {
+    case 1:
+      fixP->fx_signed = 1;
+      break;
+
+    case 2:
+      if (i.tm.base_opcode == 0xc7f8)
+       fixP->fx_signed = 1;
+      break;
+
+    case 4:
+      if (flag_code == CODE_64BIT)
+       fixP->fx_signed = 1;
+      break;
+    }
 }
 
 static void
              fixP = fix_new_exp (frag_now, p - frag_now->fr_literal,
                                  size, i.op[n].disps, pcrel,
                                  reloc_type);
+
+             if (flag_code == CODE_64BIT && size == 4 && pcrel
+                 && !i.prefix[ADDR_PREFIX])
+               fixP->fx_signed = 1;
+
              /* Check for "call/jmp *mem", "mov mem, %reg",
                 "test %reg, mem" and "binop mem, %reg" where binop
                 is one of adc, add, and, cmp, or, sbb, sub, xor
       enum bfd_reloc_code_real reloc_type;
       unsigned char *opcode;
       int old_fr_fix;
+      fixS *fixP = NULL;
 
       if (fragP->fr_var != NO_RELOC)
        reloc_type = (enum bfd_reloc_code_real) fragP->fr_var;
          /* Make jmp (0xeb) a (d)word displacement jump.  */
          opcode[0] = 0xe9;
          fragP->fr_fix += size;
-         fix_new (fragP, old_fr_fix, size,
-                  fragP->fr_symbol,
-                  fragP->fr_offset, 1,
-                  reloc_type);
+         fixP = fix_new (fragP, old_fr_fix, size,
+                         fragP->fr_symbol,
+                         fragP->fr_offset, 1,
+                         reloc_type);
          break;
 
        case COND_JUMP86:
        case COND_JUMP:
          if (no_cond_jump_promotion && fragP->fr_var == NO_RELOC)
            {
-             fixS *fixP;
-
              fragP->fr_fix += 1;
              fixP = fix_new (fragP, old_fr_fix, 1,
                              fragP->fr_symbol,
          opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
          /* We've added an opcode byte.  */
          fragP->fr_fix += 1 + size;
-         fix_new (fragP, old_fr_fix + 1, size,
-                  fragP->fr_symbol,
-                  fragP->fr_offset, 1,
-                  reloc_type);
+         fixP = fix_new (fragP, old_fr_fix + 1, size,
+                         fragP->fr_symbol,
+                         fragP->fr_offset, 1,
+                         reloc_type);
          break;
 
        default:
          BAD_CASE (fragP->fr_subtype);
          break;
        }
+
+      /* All jumps handled here are signed, but don't unconditionally use a
+        signed limit check for 32 and 16 bit jumps as we want to allow wrap
+        around at 4G (outside of 64-bit mode) and 64k.  */
+      if (size == 4 && flag_code == CODE_64BIT)
+       fixP->fx_signed = 1;
+
       frag_wane (fragP);
       return fragP->fr_fix - old_fr_fix;
     }
 # if defined (TE_PE) || defined (TE_PEP)
     case bfd_target_coff_flavour:
       if (flag_code == CODE_64BIT)
-       return use_big_obj ? "pe-bigobj-x86-64" : "pe-x86-64";
-      else
-       return use_big_obj ? "pe-bigobj-i386" : "pe-i386";
+       {
+         object_64bit = 1;
+         return use_big_obj ? "pe-bigobj-x86-64" : "pe-x86-64";
+       }
+      return use_big_obj ? "pe-bigobj-i386" : "pe-i386";
 # elif defined (TE_GO32)
     case bfd_target_coff_flavour:
       return "coff-go32";
 
     } else {
       run_dump_test "x86-64-w64-pcrel"
     }
+    run_list_test "pcrel64" "-al"
     run_dump_test "x86-64-rip"
     run_dump_test "x86-64-rip-intel"
+    run_dump_test "x86-64-rip-2"
+    run_list_test "x86-64-rip-inval-1" "-al"
+    run_list_test "x86-64-rip-inval-2" "-al"
     run_dump_test "x86-64-stack"
     run_dump_test "x86-64-stack-intel"
     run_dump_test "x86-64-stack-suffix"
 
--- /dev/null
+.*: Assembler messages:
+.*:16: Error: .*
+.*:17: Error: .*
+.*:13: Error: .*
+.*:15: Error: .*
+.*:18: Error: .*
+.*:19: Error: .*
+.*:20: Error: .*
+GAS LISTING .*
+
+
+[      ]*[0-9]+[       ]+\.text
+[      ]*[0-9]+[       ]+\.code64
+[      ]*[0-9]+[       ]+pcrel:
+[      ]*[0-9]+ \?\?\?\? E8..8000[     ]+call  target
+[      ]*[0-9]+[       ]+00
+[      ]*[0-9]+ \?\?\?\? E9..8000[     ]+jmp   target
+[      ]*[0-9]+[       ]+00
+[      ]*[0-9]+ \?\?\?\? 0F84..80[     ]+jz    target
+[      ]*[0-9]+[       ]+0000
+[      ]*[0-9]+ \?\?\?\? C7F8..80[     ]+xbegin        target
+[      ]*[0-9]+[       ]+0000
+[      ]*[0-9]+ \?\?\?\? 8B05..80[     ]+mov   target\(%rip\), %eax
+[      ]*[0-9]+[       ]+0000
+[      ]*[0-9]+ \?\?\?\? 678B05..[     ]+mov   target\(%eip\), %eax
+[      ]*[0-9]+[       ]+800000
+[      ]*[0-9]+ \?\?\?\? 48C7C0..[     ]+mov   \$target-., %rax
+[      ]*[0-9]+[       ]+800000
+[      ]*[0-9]+ \?\?\?\? B8..8000[     ]+mov   \$target-., %eax
+[      ]*[0-9]+[       ]+00
+[      ]*[0-9]+[       ]*
+[      ]*[0-9]+ \?\?\?\? 66C7F8..[     ]+data16 xbegin target
+[      ]*[0-9]+[       ]+80
+[      ]*[0-9]+[       ]*
+[      ]*[0-9]+ \?\?\?\? E8...000[     ]+call  target\+0x7ffff000
+[      ]*[0-9]+[       ]+80
+[      ]*[0-9]+ \?\?\?\? E9000000[     ]+jmp   target\+0x7ffff000
+[      ]*[0-9]+[       ]+00
+[      ]*[0-9]+ \?\?\?\? 0F840000[     ]+jz    target\+0x7ffff000
+[      ]*[0-9]+[       ]+0000
+[      ]*[0-9]+ \?\?\?\? C7F8...0[     ]+xbegin        target\+0x7ffff000
+[      ]*[0-9]+[       ]+0080
+[      ]*[0-9]+ \?\?\?\? 8B05...0[     ]+mov   target\+0x7ffff000\(%rip\), %eax
+[      ]*[0-9]+[       ]+0080
+[      ]*[0-9]+ \?\?\?\? 48C7C0..[     ]+mov   \$target\+0x7ffff000-., %rax
+[      ]*[0-9]+[       ]+.00080
+[      ]*[0-9]+[       ]*
+[      ]*[0-9]+ \?\?\?\? 678B05..[     ]+mov   target\+0x7ffff000\(%eip\), %eax
+[      ]*[0-9]+[       ]+.00080
+[      ]*[0-9]+ \?\?\?\? B8...000[     ]+mov   \$target\+0x7ffff000-., %eax
+[      ]*[0-9]+[       ]+80
+[      ]*[0-9]+[       ]*
+[      ]*[0-9]+ \?\?\?\? CCCCCCCC[     ]+\.fill 0x8000, 1, 0xcc
+#pass
 
--- /dev/null
+       .text
+       .code64
+pcrel:
+       call    target
+       jmp     target
+       jz      target
+       xbegin  target
+       mov     target(%rip), %eax
+       mov     target(%eip), %eax
+       mov     $target-., %rax
+       mov     $target-., %eax
+
+       data16 xbegin target
+
+       call    target+0x7ffff000
+       jmp     target+0x7ffff000
+       jz      target+0x7ffff000
+       xbegin  target+0x7ffff000
+       mov     target+0x7ffff000(%rip), %eax
+       mov     $target+0x7ffff000-., %rax
+
+       mov     target+0x7ffff000(%eip), %eax
+       mov     $target+0x7ffff000-., %eax
+
+       .fill 0x8000, 1, 0xcc
+target:
+       ret
 
--- /dev/null
+#as: -J
+#objdump: -drw --syms
+#name: x86-64 rip addressing 2
+
+.*: +file format .*
+
+SYMBOL TABLE:
+0000000000000000 l       .text 0000000000000000 _start
+0000000080000006 l       .text 0000000000000000 test1
+ffffffff8000000e l       .text 0000000000000000 test2
+00000000f000000e l       .text 0000000000000000 test3
+ffffffff1000000e l       .text 0000000000000000 test4
+
+
+
+Disassembly of section .text:
+
+0000000000000000 <_start>:
+ +0:   48 8b 05 ff ff ff 7f    mov    0x7fffffff\(%rip\),%rax        # 80000006 <test1>
+ +7:   48 8b 05 00 00 00 80    mov    -0x80000000\(%rip\),%rax        # ffffffff8000000e <test2>
+#pass
 
--- /dev/null
+       .text
+_start:
+       movq test1(%rip), %rax
+       .set test1, . + 0x7fffffff
+
+       movq test2(%rip), %rax
+       .set test2, . - 0x80000000
+
+       .set test3, . + 0xf0000000
+       .set test4, . - 0xf0000000
 
--- /dev/null
+.*: Assembler messages:
+.*:3: Error:.* (0x)?ffffffff7fffffff .*
+GAS LISTING .*
+
+
+[      ]*1[    ]+\.text
+[      ]*2[    ]+_start:
+[      ]*3[    ]+\?\?\?\? 488B05FF             movq test1\(%rip\), %rax
+[      ]*3[    ]+FFFF7F
+[      ]*4[    ]+\.set test1, \. - 0x80000001
+#pass
 
--- /dev/null
+       .text
+_start:
+       movq test1(%rip), %rax
+       .set test1, . - 0x80000001
 
--- /dev/null
+.*: Assembler messages:
+.*:3: Error:.* (0x)?0*80000000 .*
+GAS LISTING .*
+
+
+[      ]*1[    ]+\.text
+[      ]*2[    ]+_start:
+[      ]*3[    ]+\?\?\?\? 488B0500             movq test1\(%rip\), %rax
+[      ]*3[    ]+000080
+[      ]*4[    ]+\.set test1, \. \+ 0x80000000
+#pass
 
--- /dev/null
+       .text
+_start:
+       movq test1(%rip), %rax
+       .set test1, . + 0x80000000