[PATCH 1/4] x86-64: Add R_X86_64_CODE_4_GOTPCRELX

H.J. Lu hjl.tools@gmail.com
Thu Dec 28 14:58:01 GMT 2023


For

	mov        name@GOTPCREL(%rip), %reg
	test       %reg, name@GOTPCREL(%rip)
	binop      name@GOTPCREL(%rip), %reg

where binop is one of adc, add, add, cmp, or, sbb, sub, xor instructions,
add

 # define R_X86_64_CODE_4_GOTPCRELX  43

if the instruction starts at 4 bytes before the relocation offset.  It
similar to R_X86_64_GOTPCRELX.  Linker can treat R_X86_64_CODE_4_GOTPCRELX
as R_X86_64_GOTPCREL or convert the above instructions to

	lea	name(%rip), %reg
	mov	$name, %reg
	test	$name, %reg
	binop	$name, %reg

if the instruction is encoded with the REX2 prefix when possible.

bfd/

	* elf64-x86-64.c (x86_64_elf_howto_table): Add
	R_X86_64_CODE_4_GOTPCRELX.
	(R_X86_64_standard): Updated.
	(x86_64_reloc_map): Add BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
	(elf_x86_64_convert_load_reloc): Handle R_X86_64_CODE_4_GOTPCRELX.
	(elf_x86_64_scan_relocs): Likewise.
	(elf_x86_64_relocate_section): Likewise.
	* reloc.c (bfd_reloc_code_real): Add
	BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
	* bfd-in2.h: Regenerated.
	* libbfd.h: Likewise.

gas/

	* write.h (fix): Add fx_tcbit3.  Change fx_unused to 1 bit.
	* config/tc-i386.c (tc_i386_fix_adjustable): Handle
	BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
	(tc_gen_reloc): Likewise.
	(output_disp): Set fixP->fx_tcbit3 for REX2 prefix.
	(i386_validate_fix): Generate BFD_RELOC_X86_64_CODE_4_GOTPCRELX
	if fixp->fx_tcbit3 is set.
	* config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Add
	BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
	(TC_FORCE_RELOCATION_ABS): Likewise.
	* testsuite/gas/i386/x86-64-gotpcrel.s: Add tests for
	R_X86_64_CODE_4_GOTPCRELX.
	* testsuite/gas/i386/x86-64-localpic.s: Likewise.
	* testsuite/gas/i386/x86-64-gotpcrel.d: Updated.
	* testsuite/gas/i386/x86-64-localpic.d: Likewise.
	* testsuite/gas/i386/ilp32/x86-64-localpic.d: Likewise.

include/

	* elf/x86-64.h (elf_x86_64_reloc_type): Add
	R_X86_64_CODE_4_GOTPCRELX.

ld/

	* testsuite/ld-x86-64/apx-load1.s: New file.
	* testsuite/ld-x86-64/apx-load1a.d: Likewise.
	* testsuite/ld-x86-64/apx-load1b.d: Likewise.
	* testsuite/ld-x86-64/apx-load1c.d: Likewise.
	* testsuite/ld-x86-64/apx-load1d.d: Likewise.
	* testsuite/ld-x86-64/x86-64.exp: Run apx-load1a, apx-load1b,
	apx-load1c and apx-load1d.
---
 bfd/bfd-in2.h                                 |  1 +
 bfd/elf64-x86-64.c                            | 73 ++++++++++++++-----
 bfd/libbfd.h                                  |  1 +
 bfd/reloc.c                                   |  2 +
 gas/config/tc-i386.c                          | 18 ++++-
 gas/config/tc-i386.h                          |  6 +-
 .../gas/i386/ilp32/x86-64-localpic.d          |  4 +-
 gas/testsuite/gas/i386/x86-64-gotpcrel.d      | 12 +++
 gas/testsuite/gas/i386/x86-64-gotpcrel.s      | 19 +++++
 gas/testsuite/gas/i386/x86-64-localpic.d      |  4 +-
 gas/testsuite/gas/i386/x86-64-localpic.s      |  2 +
 gas/write.h                                   |  3 +-
 include/elf/x86-64.h                          |  6 +-
 ld/testsuite/ld-x86-64/apx-load1.s            | 51 +++++++++++++
 ld/testsuite/ld-x86-64/apx-load1a.d           | 54 ++++++++++++++
 ld/testsuite/ld-x86-64/apx-load1b.d           | 55 ++++++++++++++
 ld/testsuite/ld-x86-64/apx-load1c.d           | 47 ++++++++++++
 ld/testsuite/ld-x86-64/apx-load1d.d           | 47 ++++++++++++
 ld/testsuite/ld-x86-64/x86-64.exp             |  4 +
 19 files changed, 382 insertions(+), 27 deletions(-)
 create mode 100644 ld/testsuite/ld-x86-64/apx-load1.s
 create mode 100644 ld/testsuite/ld-x86-64/apx-load1a.d
 create mode 100644 ld/testsuite/ld-x86-64/apx-load1b.d
 create mode 100644 ld/testsuite/ld-x86-64/apx-load1c.d
 create mode 100644 ld/testsuite/ld-x86-64/apx-load1d.d

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 782845926ea..96709da9170 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3891,6 +3891,7 @@ enum bfd_reloc_code_real
   BFD_RELOC_X86_64_PLT32_BND,
   BFD_RELOC_X86_64_GOTPCRELX,
   BFD_RELOC_X86_64_REX_GOTPCRELX,
+  BFD_RELOC_X86_64_CODE_4_GOTPCRELX,
 
   /* ns32k relocations.  */
   BFD_RELOC_NS32K_IMM_8,
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 3b7a8aeee11..a2d1b6f14b7 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -170,12 +170,15 @@ static reloc_howto_type x86_64_elf_howto_table[] =
   HOWTO(R_X86_64_REX_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_REX_GOTPCRELX", false, 0, 0xffffffff,
 	true),
+  HOWTO(R_X86_64_CODE_4_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed,
+	bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTPCRELX", false, 0, 0xffffffff,
+	true),
 
   /* We have a gap in the reloc numbers here.
      R_X86_64_standard counts the number up to this point, and
      R_X86_64_vt_offset is the value to subtract from a reloc type of
      R_X86_64_GNU_VT* to form an index into this table.  */
-#define R_X86_64_standard (R_X86_64_REX_GOTPCRELX + 1)
+#define R_X86_64_standard (R_X86_64_CODE_4_GOTPCRELX + 1)
 #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -244,6 +247,7 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
   { BFD_RELOC_X86_64_PLT32_BND,	R_X86_64_PLT32_BND, },
   { BFD_RELOC_X86_64_GOTPCRELX, R_X86_64_GOTPCRELX, },
   { BFD_RELOC_X86_64_REX_GOTPCRELX, R_X86_64_REX_GOTPCRELX, },
+  { BFD_RELOC_X86_64_CODE_4_GOTPCRELX, R_X86_64_CODE_4_GOTPCRELX, },
   { BFD_RELOC_VTABLE_INHERIT,	R_X86_64_GNU_VTINHERIT, },
   { BFD_RELOC_VTABLE_ENTRY,	R_X86_64_GNU_VTENTRY, },
 };
@@ -1586,7 +1590,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
   bfd_vma roff = irel->r_offset;
   bfd_vma abs_relocation;
 
-  if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2))
+  if (roff < (r_type == R_X86_64_CODE_4_GOTPCRELX
+	      ? 4 : (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2)))
     return true;
 
   raddend = irel->r_addend;
@@ -1597,8 +1602,18 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
   htab = elf_x86_hash_table (link_info, X86_64_ELF_DATA);
   is_pic = bfd_link_pic (link_info);
 
-  relocx = (r_type == R_X86_64_GOTPCRELX
-	    || r_type == R_X86_64_REX_GOTPCRELX);
+  if (r_type == R_X86_64_CODE_4_GOTPCRELX)
+    {
+      /* Skip if this isn't a REX2 instruction.  */
+      opcode = bfd_get_8 (abfd, contents + roff - 4);
+      if (opcode != 0xd5)
+	return true;
+
+      relocx = true;
+    }
+  else
+    relocx = (r_type == R_X86_64_GOTPCRELX
+	      || r_type == R_X86_64_REX_GOTPCRELX);
 
   /* TRUE if --no-relax is used.  */
   no_overflow = link_info->disable_target_specific_optimizations > 1;
@@ -1610,9 +1625,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
   /* Convert mov to lea since it has been done for a while.  */
   if (opcode != 0x8b)
     {
-      /* Only convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX
-	 for call, jmp or one of adc, add, and, cmp, or, sbb, sub,
-	 test, xor instructions.  */
+      /* Only convert R_X86_64_GOTPCRELX, R_X86_64_REX_GOTPCRELX
+	 and R_X86_64_CODE_4_GOTPCRELX for call, jmp or one of adc,
+	 add, and, cmp, or, sbb, sub, test, xor instructions.  */
       if (!relocx)
 	return true;
     }
@@ -1797,13 +1812,22 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
     }
   else
     {
-      unsigned int rex;
+      unsigned int rex = 0;
       unsigned int rex_mask = REX_R;
+      unsigned int rex2 = 0;
+      unsigned int rex2_mask = REX_R | REX_R << 4;
+      bool rex_w = false;
 
-      if (r_type == R_X86_64_REX_GOTPCRELX)
-	rex = bfd_get_8 (abfd, contents + roff - 3);
-      else
-	rex = 0;
+      if (r_type == R_X86_64_CODE_4_GOTPCRELX)
+	{
+	  rex2 = bfd_get_8 (abfd, contents + roff - 3);
+	  rex_w = (rex2 & REX_W) != 0;
+	}
+      else if (r_type == R_X86_64_REX_GOTPCRELX)
+	{
+	  rex = bfd_get_8 (abfd, contents + roff - 3);
+	  rex_w = (rex & REX_W) != 0;
+	}
 
       if (opcode == 0x8b)
 	{
@@ -1824,8 +1848,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
 	      opcode = 0xc7;
 	      modrm = bfd_get_8 (abfd, contents + roff - 1);
 	      modrm = 0xc0 | (modrm & 0x38) >> 3;
-	      if ((rex & REX_W) != 0
-		  && ABI_64_P (link_info->output_bfd))
+	      if (rex_w && ABI_64_P (link_info->output_bfd))
 		{
 		  /* Keep the REX_W bit in REX byte for LP64.  */
 		  r_type = R_X86_64_32S;
@@ -1837,8 +1860,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
 		     use R_X86_64_32 and clear the W bit to avoid
 		     sign-extend imm32 to imm64.  */
 		  r_type = R_X86_64_32;
-		  /* Clear the W bit in REX byte.  */
+		  /* Clear the W bit in REX byte and REX2 payload.  */
 		  rex_mask |= REX_W;
+		  rex2_mask |= REX_W;
 		  goto rewrite_modrm_rex;
 		}
 	    }
@@ -1867,7 +1891,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
 
 	  /* Use R_X86_64_32 with 32-bit operand to avoid relocation
 	     overflow when sign-extending imm32 to imm64.  */
-	  r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32;
+	  r_type = rex_w ? R_X86_64_32S : R_X86_64_32;
 
 	rewrite_modrm_rex:
 	  if (abs_relocation)
@@ -1893,6 +1917,13 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
 	      rex = (rex & ~rex_mask) | (rex & REX_R) >> 2;
 	      bfd_put_8 (abfd, rex, contents + roff - 3);
 	    }
+	  else if (rex2)
+	    {
+	      /* Move the R bits to the B bits in REX2 payload byte.  */
+	      rex2 = ((rex2 & ~rex2_mask)
+		      | (rex2 & (REX_R | REX_R << 4)) >> 2);
+	      bfd_put_8 (abfd, rex2, contents + roff - 3);
+	    }
 
 	  /* No addend for R_X86_64_32/R_X86_64_32S relocations.  */
 	  irel->r_addend = 0;
@@ -2058,7 +2089,8 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
       converted_reloc = false;
       if ((r_type == R_X86_64_GOTPCREL
 	   || r_type == R_X86_64_GOTPCRELX
-	   || r_type == R_X86_64_REX_GOTPCRELX)
+	   || r_type == R_X86_64_REX_GOTPCRELX
+	   || r_type == R_X86_64_CODE_4_GOTPCRELX)
 	  && (h == NULL || h->type != STT_GNU_IFUNC))
 	{
 	  Elf_Internal_Rela *irel = (Elf_Internal_Rela *) rel;
@@ -2108,6 +2140,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
 	case R_X86_64_GOTPCREL:
 	case R_X86_64_GOTPCRELX:
 	case R_X86_64_REX_GOTPCRELX:
+	case R_X86_64_CODE_4_GOTPCRELX:
 	case R_X86_64_TLSGD:
 	case R_X86_64_GOT64:
 	case R_X86_64_GOTPCREL64:
@@ -2710,6 +2743,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 	    case R_X86_64_GOTPCREL:
 	    case R_X86_64_GOTPCRELX:
 	    case R_X86_64_REX_GOTPCRELX:
+	    case R_X86_64_CODE_4_GOTPCRELX:
 	    case R_X86_64_GOTPCREL64:
 	      base_got = htab->elf.sgot;
 	      off = h->got.offset;
@@ -2935,6 +2969,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 	case R_X86_64_GOTPCREL:
 	case R_X86_64_GOTPCRELX:
 	case R_X86_64_REX_GOTPCRELX:
+	case R_X86_64_CODE_4_GOTPCRELX:
 	case R_X86_64_GOTPCREL64:
 	  /* Use global offset table entry as symbol value.  */
 	case R_X86_64_GOTPLT64:
@@ -3025,7 +3060,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 		      && !(sym->st_shndx == SHN_ABS
 			   && (r_type == R_X86_64_GOTPCREL
 			       || r_type == R_X86_64_GOTPCRELX
-			       || r_type == R_X86_64_REX_GOTPCRELX)))
+			       || r_type == R_X86_64_REX_GOTPCRELX
+			       || r_type == R_X86_64_CODE_4_GOTPCRELX)))
 		    relative_reloc = true;
 		}
 	    }
@@ -3063,6 +3099,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 	  if (r_type != R_X86_64_GOTPCREL
 	      && r_type != R_X86_64_GOTPCRELX
 	      && r_type != R_X86_64_REX_GOTPCRELX
+	      && r_type != R_X86_64_CODE_4_GOTPCRELX
 	      && r_type != R_X86_64_GOTPCREL64)
 	    relocation -= htab->elf.sgotplt->output_section->vma
 			  - htab->elf.sgotplt->output_offset;
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 8dab44110a6..8873fafdde9 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1460,6 +1460,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_X86_64_PLT32_BND",
   "BFD_RELOC_X86_64_GOTPCRELX",
   "BFD_RELOC_X86_64_REX_GOTPCRELX",
+  "BFD_RELOC_X86_64_CODE_4_GOTPCRELX",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 6fd0f1fb547..56d852d084f 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2475,6 +2475,8 @@ ENUMX
   BFD_RELOC_X86_64_GOTPCRELX
 ENUMX
   BFD_RELOC_X86_64_REX_GOTPCRELX
+ENUMX
+  BFD_RELOC_X86_64_CODE_4_GOTPCRELX
 ENUMDOC
   x86-64/elf relocations.
 
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index ee948a61b18..8d76446010b 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -3595,6 +3595,7 @@ tc_i386_fix_adjustable (fixS *fixP)
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX
       || fixP->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX
+      || fixP->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX
       || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD
       || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD
       || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
@@ -10856,6 +10857,10 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
 		  && !i.prefix[ADDR_PREFIX])
 		fixP->fx_signed = 1;
 
+	      /* Set fx_tcbit3 for REX2 prefix.  */
+	      if (is_apx_rex2_encoding ())
+		fixP->fx_tcbit3 = 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
@@ -15936,9 +15941,14 @@ i386_validate_fix (fixS *fixp)
 		abort ();
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
 	      if (fixp->fx_tcbit2)
-		fixp->fx_r_type = (fixp->fx_tcbit
-				   ? BFD_RELOC_X86_64_REX_GOTPCRELX
-				   : BFD_RELOC_X86_64_GOTPCRELX);
+		{
+		  if (fixp->fx_tcbit3)
+		    fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTPCRELX;
+		  else
+		    fixp->fx_r_type = (fixp->fx_tcbit
+				       ? BFD_RELOC_X86_64_REX_GOTPCRELX
+				       : BFD_RELOC_X86_64_GOTPCRELX);
+		}
 	      else
 #endif
 		fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
@@ -16042,6 +16052,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
     case BFD_RELOC_X86_64_GOTPCREL:
     case BFD_RELOC_X86_64_GOTPCRELX:
     case BFD_RELOC_X86_64_REX_GOTPCRELX:
+    case BFD_RELOC_X86_64_CODE_4_GOTPCRELX:
     case BFD_RELOC_386_PLT32:
     case BFD_RELOC_386_GOT32:
     case BFD_RELOC_386_GOT32X:
@@ -16200,6 +16211,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 	  case BFD_RELOC_X86_64_GOTPCREL:
 	  case BFD_RELOC_X86_64_GOTPCRELX:
 	  case BFD_RELOC_X86_64_REX_GOTPCRELX:
+	  case BFD_RELOC_X86_64_CODE_4_GOTPCRELX:
 	  case BFD_RELOC_X86_64_TLSGD:
 	  case BFD_RELOC_X86_64_TLSLD:
 	  case BFD_RELOC_X86_64_GOTTPOFF:
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index 3cb0c784819..44227a8376c 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -171,7 +171,8 @@ extern int tc_i386_fix_adjustable (struct fix *);
    || (FIX)->fx_r_type == BFD_RELOC_386_GOTPC			\
    || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL		\
    || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX		\
-   || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX)
+   || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX	\
+   || (FIX)->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX)
 
 #define TC_FORCE_RELOCATION_ABS(FIX)				\
   (TC_FORCE_RELOCATION (FIX)					\
@@ -179,7 +180,8 @@ extern int tc_i386_fix_adjustable (struct fix *);
    || (FIX)->fx_r_type == BFD_RELOC_386_GOT32X			\
    || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL		\
    || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX		\
-   || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX)
+   || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX	\
+   || (FIX)->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX)
 
 extern int i386_parse_name (char *, expressionS *, char *);
 #define md_parse_name(s, e, m, c) i386_parse_name (s, e, c)
diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d b/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d
index d0cc4e8efc9..57d4843a5b5 100644
--- a/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d
+++ b/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d
@@ -3,10 +3,12 @@
 #readelf: -rsW
 #name: x86-64 (ILP32) local PIC
 
-Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 2 entries:
+Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 4 entries:
  +Offset +Info +Type +Sym. Value +Symbol's Name \+ Addend
 [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4
 [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +bar - 4
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +foo - 4
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +bar - 4
 #...
  +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
  +[0-9]+: +fffffff0 +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +ABS +bar
diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel.d b/gas/testsuite/gas/i386/x86-64-gotpcrel.d
index 57792216e9a..12fadfbca4e 100644
--- a/gas/testsuite/gas/i386/x86-64-gotpcrel.d
+++ b/gas/testsuite/gas/i386/x86-64-gotpcrel.d
@@ -24,4 +24,16 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	ff 90 00 00 00 00    	call   \*0x0\(%rax\)	5a: R_X86_64_GOTPCREL	foo
 [ 	]*[a-f0-9]+:	ff 25 00 00 00 00    	jmp    \*0x0\(%rip\)        # 64 <_start\+0x64>	60: R_X86_64_GOTPCRELX	foo-0x4
 [ 	]*[a-f0-9]+:	ff a1 00 00 00 00    	jmp    \*0x0\(%rcx\)	66: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 18 c7 c0 00 00 00 00 	mov    \$0x0,%r16	6e: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 48 8b 24 25 00 00 00 00 	mov    0x0,%r20	77: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 48 8b 35 00 00 00 00 	mov    0x0\(%rip\),%r22        # 83 <_start\+0x83>	7f: R_X86_64_CODE_4_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	d5 59 8b b4 24 00 00 00 00 	mov    0x0\(%r28\),%r22	88: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 10 ff 90 00 00 00 00 	call   \*0x0\(%r16\)	90: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 11 ff a4 24 00 00 00 00 	jmp    \*0x0\(%r28\)	99: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 18 c7 c0 00 00 00 00 	mov    \$0x0,%r16	a1: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 48 8b 24 25 00 00 00 00 	mov    0x0,%r20	aa: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 48 8b 35 00 00 00 00 	mov    0x0\(%rip\),%r22        # b6 <_start\+0xb6>	b2: R_X86_64_CODE_4_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	d5 59 8b b4 24 00 00 00 00 	mov    0x0\(%r28\),%r22	bb: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 10 ff 90 00 00 00 00 	call   \*0x0\(%r16\)	c3: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	d5 11 ff a4 24 00 00 00 00 	jmp    \*0x0\(%r28\)	cc: R_X86_64_GOTPCREL	foo
 #pass
diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel.s b/gas/testsuite/gas/i386/x86-64-gotpcrel.s
index 981b14ff4df..91b1ca204c8 100644
--- a/gas/testsuite/gas/i386/x86-64-gotpcrel.s
+++ b/gas/testsuite/gas/i386/x86-64-gotpcrel.s
@@ -21,3 +21,22 @@ _start:
 	call	QWORD PTR [rax + foo@GOTPCREL]
 	jmp	QWORD PTR [rip + foo@GOTPCREL]
 	jmp	QWORD PTR [rcx + foo@GOTPCREL]
+
+	.att_syntax prefix
+	movq	$foo@GOTPCREL, %r16
+	movq	foo@GOTPCREL, %r20
+	movq	foo@GOTPCREL(%rip), %r22
+	movq	foo@GOTPCREL(%r28), %r22
+
+	call	*foo@GOTPCREL(%r16)
+	jmp	*foo@GOTPCREL(%r28)
+
+	.intel_syntax noprefix
+
+	mov	r16, offset foo@gotpcrel
+	mov	r20, QWORD PTR [foo@GOTPCREL]
+	mov	r22, QWORD PTR [rip + foo@GOTPCREL]
+	mov	r22, QWORD PTR [r28 + foo@GOTPCREL]
+
+	call	QWORD PTR [r16 + foo@GOTPCREL]
+	jmp	QWORD PTR [r28 + foo@GOTPCREL]
diff --git a/gas/testsuite/gas/i386/x86-64-localpic.d b/gas/testsuite/gas/i386/x86-64-localpic.d
index 62030d410ad..11eb57b30b7 100644
--- a/gas/testsuite/gas/i386/x86-64-localpic.d
+++ b/gas/testsuite/gas/i386/x86-64-localpic.d
@@ -2,10 +2,12 @@
 #readelf: -rsW
 #name: x86-64 local PIC
 
-Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 2 entries:
+Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 4 entries:
  +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
 [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4
 [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +bar - 4
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +foo - 4
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +bar - 4
 #...
  +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
  +[0-9]+: +0+fffffff0 +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +ABS +bar
diff --git a/gas/testsuite/gas/i386/x86-64-localpic.s b/gas/testsuite/gas/i386/x86-64-localpic.s
index beda94dc2f3..183dfb6293b 100644
--- a/gas/testsuite/gas/i386/x86-64-localpic.s
+++ b/gas/testsuite/gas/i386/x86-64-localpic.s
@@ -3,4 +3,6 @@ foo:
 	.quad 0
 	movq	foo@GOTPCREL(%rip), %rax
 	movq	bar@GOTPCREL(%rip), %rax
+	movq	foo@GOTPCREL(%rip), %r26
+	movq	bar@GOTPCREL(%rip), %r26
 	bar = 0xfffffff0
diff --git a/gas/write.h b/gas/write.h
index eb30a76bf85..fd0ab553b23 100644
--- a/gas/write.h
+++ b/gas/write.h
@@ -81,9 +81,10 @@ struct fix
   /* Some bits for the CPU specific code.  */
   unsigned fx_tcbit : 1;
   unsigned fx_tcbit2 : 1;
+  unsigned fx_tcbit3 : 1;
 
   /* Spare bits.  */
-  unsigned fx_unused : 2;
+  unsigned fx_unused : 1;
 
   bfd_reloc_code_real_type fx_r_type;
 
diff --git a/include/elf/x86-64.h b/include/elf/x86-64.h
index 1b87beef41a..30d1722cb73 100644
--- a/include/elf/x86-64.h
+++ b/include/elf/x86-64.h
@@ -77,11 +77,15 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type)
      RELOC_NUMBER (R_X86_64_PLT32_BND, 40)    /* 32 bit PLT address with
 						 BND prefix */
      /* Load from 32 bit signed pc relative offset to GOT entry without
-	REX prefix, relaxable.  */
+	REX nor REX2 prefixes, relaxable.  */
      RELOC_NUMBER (R_X86_64_GOTPCRELX, 41)
      /* Load from 32 bit signed pc relative offset to GOT entry with
 	REX prefix, relaxable.  */
      RELOC_NUMBER (R_X86_64_REX_GOTPCRELX, 42)
+     /* Load from 32 bit signed pc relative offset to GOT entry if the
+	instruction starts at 4 bytes before the relocation offset,
+	relaxable.  */
+     RELOC_NUMBER (R_X86_64_CODE_4_GOTPCRELX, 43)
      RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
      RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
 END_RELOC_NUMBERS (R_X86_64_max)
diff --git a/ld/testsuite/ld-x86-64/apx-load1.s b/ld/testsuite/ld-x86-64/apx-load1.s
new file mode 100644
index 00000000000..f5eac57d82e
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1.s
@@ -0,0 +1,51 @@
+	.data
+	.type	bar, @object
+bar:
+	.byte	1
+	.size	bar, .-bar
+	.globl	foo
+	.type	foo, @object
+foo:
+	.byte	1
+	.size	foo, .-foo
+	.text
+	.globl	_start
+	.type	_start, @function
+_start:
+	adcl	bar@GOTPCREL(%rip), %r16d
+	addl	bar@GOTPCREL(%rip), %r17d
+	andl	bar@GOTPCREL(%rip), %r18d
+	cmpl	bar@GOTPCREL(%rip), %r19d
+	orl	bar@GOTPCREL(%rip), %r20d
+	sbbl	bar@GOTPCREL(%rip), %r21d
+	subl	bar@GOTPCREL(%rip), %r22d
+	xorl	bar@GOTPCREL(%rip), %r23d
+	testl	%r24d, bar@GOTPCREL(%rip)
+	adcq	bar@GOTPCREL(%rip), %r16
+	addq	bar@GOTPCREL(%rip), %r17
+	andq	bar@GOTPCREL(%rip), %r18
+	cmpq	bar@GOTPCREL(%rip), %r19
+	orq	bar@GOTPCREL(%rip), %r20
+	sbbq	bar@GOTPCREL(%rip), %r21
+	subq	bar@GOTPCREL(%rip), %r22
+	xorq	bar@GOTPCREL(%rip), %r23
+	testq	%r24, bar@GOTPCREL(%rip)
+	adcl	foo@GOTPCREL(%rip), %r16d
+	addl	foo@GOTPCREL(%rip), %r17d
+	andl	foo@GOTPCREL(%rip), %r18d
+	cmpl	foo@GOTPCREL(%rip), %r19d
+	orl	foo@GOTPCREL(%rip), %r20d
+	sbbl	foo@GOTPCREL(%rip), %r21d
+	subl	foo@GOTPCREL(%rip), %r22d
+	xorl	foo@GOTPCREL(%rip), %r23d
+	testl	%r24d, foo@GOTPCREL(%rip)
+	adcq	foo@GOTPCREL(%rip), %r16
+	addq	foo@GOTPCREL(%rip), %r17
+	andq	foo@GOTPCREL(%rip), %r18
+	cmpq	foo@GOTPCREL(%rip), %r19
+	orq	foo@GOTPCREL(%rip), %r20
+	sbbq	foo@GOTPCREL(%rip), %r21
+	subq	foo@GOTPCREL(%rip), %r22
+	xorq	foo@GOTPCREL(%rip), %r23
+	testq	%r24, foo@GOTPCREL(%rip)
+	.size	_start, .-_start
diff --git a/ld/testsuite/ld-x86-64/apx-load1a.d b/ld/testsuite/ld-x86-64/apx-load1a.d
new file mode 100644
index 00000000000..162a2343ebe
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1a.d
@@ -0,0 +1,54 @@
+#source: apx-load1.s
+#as: --64 -mrelax-relocations=yes
+#ld: -melf_x86_64 -z max-page-size=0x200000 -z noseparate-code
+#objdump: -dw --sym
+
+.*: +file format .*
+
+SYMBOL TABLE:
+#...
+0+6001d0 l     O .data	0+1 bar
+#...
+0+6001d1 g     O .data	0+1 foo
+#...
+
+Disassembly of section .text:
+
+0+4000b0 <_start>:
+ +[a-f0-9]+:	d5 10 81 d0 d0 01 60 00 	adc    \$0x6001d0,%r16d
+ +[a-f0-9]+:	d5 10 81 c1 d0 01 60 00 	add    \$0x6001d0,%r17d
+ +[a-f0-9]+:	d5 10 81 e2 d0 01 60 00 	and    \$0x6001d0,%r18d
+ +[a-f0-9]+:	d5 10 81 fb d0 01 60 00 	cmp    \$0x6001d0,%r19d
+ +[a-f0-9]+:	d5 10 81 cc d0 01 60 00 	or     \$0x6001d0,%r20d
+ +[a-f0-9]+:	d5 10 81 dd d0 01 60 00 	sbb    \$0x6001d0,%r21d
+ +[a-f0-9]+:	d5 10 81 ee d0 01 60 00 	sub    \$0x6001d0,%r22d
+ +[a-f0-9]+:	d5 10 81 f7 d0 01 60 00 	xor    \$0x6001d0,%r23d
+ +[a-f0-9]+:	d5 11 f7 c0 d0 01 60 00 	test   \$0x6001d0,%r24d
+ +[a-f0-9]+:	d5 18 81 d0 d0 01 60 00 	adc    \$0x6001d0,%r16
+ +[a-f0-9]+:	d5 18 81 c1 d0 01 60 00 	add    \$0x6001d0,%r17
+ +[a-f0-9]+:	d5 18 81 e2 d0 01 60 00 	and    \$0x6001d0,%r18
+ +[a-f0-9]+:	d5 18 81 fb d0 01 60 00 	cmp    \$0x6001d0,%r19
+ +[a-f0-9]+:	d5 18 81 cc d0 01 60 00 	or     \$0x6001d0,%r20
+ +[a-f0-9]+:	d5 18 81 dd d0 01 60 00 	sbb    \$0x6001d0,%r21
+ +[a-f0-9]+:	d5 18 81 ee d0 01 60 00 	sub    \$0x6001d0,%r22
+ +[a-f0-9]+:	d5 18 81 f7 d0 01 60 00 	xor    \$0x6001d0,%r23
+ +[a-f0-9]+:	d5 19 f7 c0 d0 01 60 00 	test   \$0x6001d0,%r24
+ +[a-f0-9]+:	d5 10 81 d0 d1 01 60 00 	adc    \$0x6001d1,%r16d
+ +[a-f0-9]+:	d5 10 81 c1 d1 01 60 00 	add    \$0x6001d1,%r17d
+ +[a-f0-9]+:	d5 10 81 e2 d1 01 60 00 	and    \$0x6001d1,%r18d
+ +[a-f0-9]+:	d5 10 81 fb d1 01 60 00 	cmp    \$0x6001d1,%r19d
+ +[a-f0-9]+:	d5 10 81 cc d1 01 60 00 	or     \$0x6001d1,%r20d
+ +[a-f0-9]+:	d5 10 81 dd d1 01 60 00 	sbb    \$0x6001d1,%r21d
+ +[a-f0-9]+:	d5 10 81 ee d1 01 60 00 	sub    \$0x6001d1,%r22d
+ +[a-f0-9]+:	d5 10 81 f7 d1 01 60 00 	xor    \$0x6001d1,%r23d
+ +[a-f0-9]+:	d5 11 f7 c0 d1 01 60 00 	test   \$0x6001d1,%r24d
+ +[a-f0-9]+:	d5 18 81 d0 d1 01 60 00 	adc    \$0x6001d1,%r16
+ +[a-f0-9]+:	d5 18 81 c1 d1 01 60 00 	add    \$0x6001d1,%r17
+ +[a-f0-9]+:	d5 18 81 e2 d1 01 60 00 	and    \$0x6001d1,%r18
+ +[a-f0-9]+:	d5 18 81 fb d1 01 60 00 	cmp    \$0x6001d1,%r19
+ +[a-f0-9]+:	d5 18 81 cc d1 01 60 00 	or     \$0x6001d1,%r20
+ +[a-f0-9]+:	d5 18 81 dd d1 01 60 00 	sbb    \$0x6001d1,%r21
+ +[a-f0-9]+:	d5 18 81 ee d1 01 60 00 	sub    \$0x6001d1,%r22
+ +[a-f0-9]+:	d5 18 81 f7 d1 01 60 00 	xor    \$0x6001d1,%r23
+ +[a-f0-9]+:	d5 19 f7 c0 d1 01 60 00 	test   \$0x6001d1,%r24
+#pass
diff --git a/ld/testsuite/ld-x86-64/apx-load1b.d b/ld/testsuite/ld-x86-64/apx-load1b.d
new file mode 100644
index 00000000000..8c8962cad2d
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1b.d
@@ -0,0 +1,55 @@
+#source: apx-load1.s
+#as: --x32 -mrelax-relocations=yes
+#ld: -melf32_x86_64 -z max-page-size=0x200000 -z noseparate-code
+#objdump: -dw --sym
+
+.*: +file format .*
+
+SYMBOL TABLE:
+#...
+0+600194 l     O .data	0+1 bar
+#...
+0+600195 g     O .data	0+1 foo
+#...
+
+
+Disassembly of section .text:
+
+0+400074 <_start>:
+ +[a-f0-9]+:	d5 10 81 d0 94 01 60 00 	adc    \$0x600194,%r16d
+ +[a-f0-9]+:	d5 10 81 c1 94 01 60 00 	add    \$0x600194,%r17d
+ +[a-f0-9]+:	d5 10 81 e2 94 01 60 00 	and    \$0x600194,%r18d
+ +[a-f0-9]+:	d5 10 81 fb 94 01 60 00 	cmp    \$0x600194,%r19d
+ +[a-f0-9]+:	d5 10 81 cc 94 01 60 00 	or     \$0x600194,%r20d
+ +[a-f0-9]+:	d5 10 81 dd 94 01 60 00 	sbb    \$0x600194,%r21d
+ +[a-f0-9]+:	d5 10 81 ee 94 01 60 00 	sub    \$0x600194,%r22d
+ +[a-f0-9]+:	d5 10 81 f7 94 01 60 00 	xor    \$0x600194,%r23d
+ +[a-f0-9]+:	d5 11 f7 c0 94 01 60 00 	test   \$0x600194,%r24d
+ +[a-f0-9]+:	d5 18 81 d0 94 01 60 00 	adc    \$0x600194,%r16
+ +[a-f0-9]+:	d5 18 81 c1 94 01 60 00 	add    \$0x600194,%r17
+ +[a-f0-9]+:	d5 18 81 e2 94 01 60 00 	and    \$0x600194,%r18
+ +[a-f0-9]+:	d5 18 81 fb 94 01 60 00 	cmp    \$0x600194,%r19
+ +[a-f0-9]+:	d5 18 81 cc 94 01 60 00 	or     \$0x600194,%r20
+ +[a-f0-9]+:	d5 18 81 dd 94 01 60 00 	sbb    \$0x600194,%r21
+ +[a-f0-9]+:	d5 18 81 ee 94 01 60 00 	sub    \$0x600194,%r22
+ +[a-f0-9]+:	d5 18 81 f7 94 01 60 00 	xor    \$0x600194,%r23
+ +[a-f0-9]+:	d5 19 f7 c0 94 01 60 00 	test   \$0x600194,%r24
+ +[a-f0-9]+:	d5 10 81 d0 95 01 60 00 	adc    \$0x600195,%r16d
+ +[a-f0-9]+:	d5 10 81 c1 95 01 60 00 	add    \$0x600195,%r17d
+ +[a-f0-9]+:	d5 10 81 e2 95 01 60 00 	and    \$0x600195,%r18d
+ +[a-f0-9]+:	d5 10 81 fb 95 01 60 00 	cmp    \$0x600195,%r19d
+ +[a-f0-9]+:	d5 10 81 cc 95 01 60 00 	or     \$0x600195,%r20d
+ +[a-f0-9]+:	d5 10 81 dd 95 01 60 00 	sbb    \$0x600195,%r21d
+ +[a-f0-9]+:	d5 10 81 ee 95 01 60 00 	sub    \$0x600195,%r22d
+ +[a-f0-9]+:	d5 10 81 f7 95 01 60 00 	xor    \$0x600195,%r23d
+ +[a-f0-9]+:	d5 11 f7 c0 95 01 60 00 	test   \$0x600195,%r24d
+ +[a-f0-9]+:	d5 18 81 d0 95 01 60 00 	adc    \$0x600195,%r16
+ +[a-f0-9]+:	d5 18 81 c1 95 01 60 00 	add    \$0x600195,%r17
+ +[a-f0-9]+:	d5 18 81 e2 95 01 60 00 	and    \$0x600195,%r18
+ +[a-f0-9]+:	d5 18 81 fb 95 01 60 00 	cmp    \$0x600195,%r19
+ +[a-f0-9]+:	d5 18 81 cc 95 01 60 00 	or     \$0x600195,%r20
+ +[a-f0-9]+:	d5 18 81 dd 95 01 60 00 	sbb    \$0x600195,%r21
+ +[a-f0-9]+:	d5 18 81 ee 95 01 60 00 	sub    \$0x600195,%r22
+ +[a-f0-9]+:	d5 18 81 f7 95 01 60 00 	xor    \$0x600195,%r23
+ +[a-f0-9]+:	d5 19 f7 c0 95 01 60 00 	test   \$0x600195,%r24
+#pass
diff --git a/ld/testsuite/ld-x86-64/apx-load1c.d b/ld/testsuite/ld-x86-64/apx-load1c.d
new file mode 100644
index 00000000000..fdfe00cc61c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1c.d
@@ -0,0 +1,47 @@
+#source: apx-load1.s
+#as: --64
+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
+#objdump: -dw
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+188 <_start>:
+ +[a-f0-9]+:	d5 40 13 05 f8 01 20 00 	adc    0x2001f8\(%rip\),%r16d        # 200388 <.*>
+ +[a-f0-9]+:	d5 40 03 0d f0 01 20 00 	add    0x2001f0\(%rip\),%r17d        # 200388 <.*>
+ +[a-f0-9]+:	d5 40 23 15 e8 01 20 00 	and    0x2001e8\(%rip\),%r18d        # 200388 <.*>
+ +[a-f0-9]+:	d5 40 3b 1d e0 01 20 00 	cmp    0x2001e0\(%rip\),%r19d        # 200388 <.*>
+ +[a-f0-9]+:	d5 40 0b 25 d8 01 20 00 	or     0x2001d8\(%rip\),%r20d        # 200388 <.*>
+ +[a-f0-9]+:	d5 40 1b 2d d0 01 20 00 	sbb    0x2001d0\(%rip\),%r21d        # 200388 <.*>
+ +[a-f0-9]+:	d5 40 2b 35 c8 01 20 00 	sub    0x2001c8\(%rip\),%r22d        # 200388 <.*>
+ +[a-f0-9]+:	d5 40 33 3d c0 01 20 00 	xor    0x2001c0\(%rip\),%r23d        # 200388 <.*>
+ +[a-f0-9]+:	d5 44 85 05 b8 01 20 00 	test   %r24d,0x2001b8\(%rip\)        # 200388 <.*>
+ +[a-f0-9]+:	d5 48 13 05 b0 01 20 00 	adc    0x2001b0\(%rip\),%r16        # 200388 <.*>
+ +[a-f0-9]+:	d5 48 03 0d a8 01 20 00 	add    0x2001a8\(%rip\),%r17        # 200388 <.*>
+ +[a-f0-9]+:	d5 48 23 15 a0 01 20 00 	and    0x2001a0\(%rip\),%r18        # 200388 <.*>
+ +[a-f0-9]+:	d5 48 3b 1d 98 01 20 00 	cmp    0x200198\(%rip\),%r19        # 200388 <.*>
+ +[a-f0-9]+:	d5 48 0b 25 90 01 20 00 	or     0x200190\(%rip\),%r20        # 200388 <.*>
+ +[a-f0-9]+:	d5 48 1b 2d 88 01 20 00 	sbb    0x200188\(%rip\),%r21        # 200388 <.*>
+ +[a-f0-9]+:	d5 48 2b 35 80 01 20 00 	sub    0x200180\(%rip\),%r22        # 200388 <.*>
+ +[a-f0-9]+:	d5 48 33 3d 78 01 20 00 	xor    0x200178\(%rip\),%r23        # 200388 <.*>
+ +[a-f0-9]+:	d5 4c 85 05 70 01 20 00 	test   %r24,0x200170\(%rip\)        # 200388 <.*>
+ +[a-f0-9]+:	d5 40 13 05 70 01 20 00 	adc    0x200170\(%rip\),%r16d        # 200390 <.*>
+ +[a-f0-9]+:	d5 40 03 0d 68 01 20 00 	add    0x200168\(%rip\),%r17d        # 200390 <.*>
+ +[a-f0-9]+:	d5 40 23 15 60 01 20 00 	and    0x200160\(%rip\),%r18d        # 200390 <.*>
+ +[a-f0-9]+:	d5 40 3b 1d 58 01 20 00 	cmp    0x200158\(%rip\),%r19d        # 200390 <.*>
+ +[a-f0-9]+:	d5 40 0b 25 50 01 20 00 	or     0x200150\(%rip\),%r20d        # 200390 <.*>
+ +[a-f0-9]+:	d5 40 1b 2d 48 01 20 00 	sbb    0x200148\(%rip\),%r21d        # 200390 <.*>
+ +[a-f0-9]+:	d5 40 2b 35 40 01 20 00 	sub    0x200140\(%rip\),%r22d        # 200390 <.*>
+ +[a-f0-9]+:	d5 40 33 3d 38 01 20 00 	xor    0x200138\(%rip\),%r23d        # 200390 <.*>
+ +[a-f0-9]+:	d5 44 85 05 30 01 20 00 	test   %r24d,0x200130\(%rip\)        # 200390 <.*>
+ +[a-f0-9]+:	d5 48 13 05 28 01 20 00 	adc    0x200128\(%rip\),%r16        # 200390 <.*>
+ +[a-f0-9]+:	d5 48 03 0d 20 01 20 00 	add    0x200120\(%rip\),%r17        # 200390 <.*>
+ +[a-f0-9]+:	d5 48 23 15 18 01 20 00 	and    0x200118\(%rip\),%r18        # 200390 <.*>
+ +[a-f0-9]+:	d5 48 3b 1d 10 01 20 00 	cmp    0x200110\(%rip\),%r19        # 200390 <.*>
+ +[a-f0-9]+:	d5 48 0b 25 08 01 20 00 	or     0x200108\(%rip\),%r20        # 200390 <.*>
+ +[a-f0-9]+:	d5 48 1b 2d 00 01 20 00 	sbb    0x200100\(%rip\),%r21        # 200390 <.*>
+ +[a-f0-9]+:	d5 48 2b 35 f8 00 20 00 	sub    0x2000f8\(%rip\),%r22        # 200390 <.*>
+ +[a-f0-9]+:	d5 48 33 3d f0 00 20 00 	xor    0x2000f0\(%rip\),%r23        # 200390 <.*>
+ +[a-f0-9]+:	d5 4c 85 05 e8 00 20 00 	test   %r24,0x2000e8\(%rip\)        # 200390 <.*>
+#pass
diff --git a/ld/testsuite/ld-x86-64/apx-load1d.d b/ld/testsuite/ld-x86-64/apx-load1d.d
new file mode 100644
index 00000000000..4da967822ea
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1d.d
@@ -0,0 +1,47 @@
+#source: apx-load1.s
+#as: --x32
+#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
+#objdump: -dw
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+100 <_start>:
+ +[a-f0-9]+:	d5 40 13 05 88 01 20 00 	adc    0x200188\(%rip\),%r16d        # 200290 <.*>
+ +[a-f0-9]+:	d5 40 03 0d 80 01 20 00 	add    0x200180\(%rip\),%r17d        # 200290 <.*>
+ +[a-f0-9]+:	d5 40 23 15 78 01 20 00 	and    0x200178\(%rip\),%r18d        # 200290 <.*>
+ +[a-f0-9]+:	d5 40 3b 1d 70 01 20 00 	cmp    0x200170\(%rip\),%r19d        # 200290 <.*>
+ +[a-f0-9]+:	d5 40 0b 25 68 01 20 00 	or     0x200168\(%rip\),%r20d        # 200290 <.*>
+ +[a-f0-9]+:	d5 40 1b 2d 60 01 20 00 	sbb    0x200160\(%rip\),%r21d        # 200290 <.*>
+ +[a-f0-9]+:	d5 40 2b 35 58 01 20 00 	sub    0x200158\(%rip\),%r22d        # 200290 <.*>
+ +[a-f0-9]+:	d5 40 33 3d 50 01 20 00 	xor    0x200150\(%rip\),%r23d        # 200290 <.*>
+ +[a-f0-9]+:	d5 44 85 05 48 01 20 00 	test   %r24d,0x200148\(%rip\)        # 200290 <.*>
+ +[a-f0-9]+:	d5 48 13 05 40 01 20 00 	adc    0x200140\(%rip\),%r16        # 200290 <.*>
+ +[a-f0-9]+:	d5 48 03 0d 38 01 20 00 	add    0x200138\(%rip\),%r17        # 200290 <.*>
+ +[a-f0-9]+:	d5 48 23 15 30 01 20 00 	and    0x200130\(%rip\),%r18        # 200290 <.*>
+ +[a-f0-9]+:	d5 48 3b 1d 28 01 20 00 	cmp    0x200128\(%rip\),%r19        # 200290 <.*>
+ +[a-f0-9]+:	d5 48 0b 25 20 01 20 00 	or     0x200120\(%rip\),%r20        # 200290 <.*>
+ +[a-f0-9]+:	d5 48 1b 2d 18 01 20 00 	sbb    0x200118\(%rip\),%r21        # 200290 <.*>
+ +[a-f0-9]+:	d5 48 2b 35 10 01 20 00 	sub    0x200110\(%rip\),%r22        # 200290 <.*>
+ +[a-f0-9]+:	d5 48 33 3d 08 01 20 00 	xor    0x200108\(%rip\),%r23        # 200290 <.*>
+ +[a-f0-9]+:	d5 4c 85 05 00 01 20 00 	test   %r24,0x200100\(%rip\)        # 200290 <.*>
+ +[a-f0-9]+:	d5 40 13 05 00 01 20 00 	adc    0x200100\(%rip\),%r16d        # 200298 <.*>
+ +[a-f0-9]+:	d5 40 03 0d f8 00 20 00 	add    0x2000f8\(%rip\),%r17d        # 200298 <.*>
+ +[a-f0-9]+:	d5 40 23 15 f0 00 20 00 	and    0x2000f0\(%rip\),%r18d        # 200298 <.*>
+ +[a-f0-9]+:	d5 40 3b 1d e8 00 20 00 	cmp    0x2000e8\(%rip\),%r19d        # 200298 <.*>
+ +[a-f0-9]+:	d5 40 0b 25 e0 00 20 00 	or     0x2000e0\(%rip\),%r20d        # 200298 <.*>
+ +[a-f0-9]+:	d5 40 1b 2d d8 00 20 00 	sbb    0x2000d8\(%rip\),%r21d        # 200298 <.*>
+ +[a-f0-9]+:	d5 40 2b 35 d0 00 20 00 	sub    0x2000d0\(%rip\),%r22d        # 200298 <.*>
+ +[a-f0-9]+:	d5 40 33 3d c8 00 20 00 	xor    0x2000c8\(%rip\),%r23d        # 200298 <.*>
+ +[a-f0-9]+:	d5 44 85 05 c0 00 20 00 	test   %r24d,0x2000c0\(%rip\)        # 200298 <.*>
+ +[a-f0-9]+:	d5 48 13 05 b8 00 20 00 	adc    0x2000b8\(%rip\),%r16        # 200298 <.*>
+ +[a-f0-9]+:	d5 48 03 0d b0 00 20 00 	add    0x2000b0\(%rip\),%r17        # 200298 <.*>
+ +[a-f0-9]+:	d5 48 23 15 a8 00 20 00 	and    0x2000a8\(%rip\),%r18        # 200298 <.*>
+ +[a-f0-9]+:	d5 48 3b 1d a0 00 20 00 	cmp    0x2000a0\(%rip\),%r19        # 200298 <.*>
+ +[a-f0-9]+:	d5 48 0b 25 98 00 20 00 	or     0x200098\(%rip\),%r20        # 200298 <.*>
+ +[a-f0-9]+:	d5 48 1b 2d 90 00 20 00 	sbb    0x200090\(%rip\),%r21        # 200298 <.*>
+ +[a-f0-9]+:	d5 48 2b 35 88 00 20 00 	sub    0x200088\(%rip\),%r22        # 200298 <.*>
+ +[a-f0-9]+:	d5 48 33 3d 80 00 20 00 	xor    0x200080\(%rip\),%r23        # 200298 <.*>
+ +[a-f0-9]+:	d5 4c 85 05 78 00 20 00 	test   %r24,0x200078\(%rip\)        # 200298 <.*>
+#pass
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 95a2986265b..d5c5219222c 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -605,6 +605,10 @@ run_dump_test "load1a"
 run_dump_test "load1b"
 run_dump_test "load1c"
 run_dump_test "load1d"
+run_dump_test "apx-load1a"
+run_dump_test "apx-load1b"
+run_dump_test "apx-load1c"
+run_dump_test "apx-load1d"
 run_dump_test "load2"
 run_dump_test "call1a"
 run_dump_test "call1b"
-- 
2.43.0



More information about the Binutils mailing list