This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] R_PPC64_PCREL_OPT


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=77486630b13e9e586b0a1556cba9876a0ede99da

commit 77486630b13e9e586b0a1556cba9876a0ede99da
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Sep 4 15:30:37 2019 +0930

    R_PPC64_PCREL_OPT
    
    The loads and stores handled in the second instruction of a sequence
    marked by R_PPC64_PCREL_OPT may be a prefix instruction.  For example:
     pld ra,symbol@got@pcrel
    0:
     pld rt,off(ra)
     .reloc 0b-8,R_PPC64_PCREL_OPT,(.-8)-(0b-8)
    can be optimised to
     pld rt,symbol+off@pcrel
     pnop
    
    	* elf64-ppc.c (xlate_pcrel_opt): Handle prefix loads and stores
    	in second instruction.
    	(ppc64_elf_relocate_section): Likewise.

Diff:
---
 bfd/ChangeLog                      |  6 +++++
 bfd/elf64-ppc.c                    | 51 +++++++++++++++++++++++++++++---------
 ld/ChangeLog                       |  6 +++++
 ld/testsuite/ld-powerpc/pcrelopt.d | 17 +++++++++----
 ld/testsuite/ld-powerpc/pcrelopt.s | 12 +++++++++
 5 files changed, 75 insertions(+), 17 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 319ba5a..7f587df 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,11 @@
 2019-09-05  Alan Modra  <amodra@gmail.com>
 
+	* elf64-ppc.c (xlate_pcrel_opt): Handle prefix loads and stores
+	in second instruction.
+	(ppc64_elf_relocate_section): Likewise.
+
+2019-09-05  Alan Modra  <amodra@gmail.com>
+
 	PR 24955
 	* libbfd-in.h (bfd_strdup): New inline function.
 	* archive.c (_bfd_get_elt_at_filepos): Use bfd_strdup.  Close
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index a5bd342..e39b6fa 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -8282,12 +8282,31 @@ ok_lo_toc_insn (unsigned int insn, enum elf_ppc64_reloc_type r_type)
 static bfd_boolean
 xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
 {
-  uint32_t insn2 = *pinsn2 >> 32;
-  uint64_t i1new;
+  uint64_t insn1 = *pinsn1;
+  uint64_t insn2 = *pinsn2;
   bfd_signed_vma off;
 
+  if ((insn2 & (63ULL << 58)) == 1ULL << 58)
+    {
+      /* Check that regs match.  */
+      if (((insn2 >> 16) & 31) != ((insn1 >> 21) & 31))
+	return FALSE;
+
+      /* P8LS or PMLS form, non-pcrel.  */
+      if ((insn2 & (-1ULL << 50) & ~(1ULL << 56)) != (1ULL << 58))
+	return FALSE;
+
+      *pinsn1 = (insn2 & ~(31 << 16) & ~0x3ffff0000ffffULL) | (1ULL << 52);
+      *pinsn2 = PNOP;
+      off = ((insn2 >> 16) & 0x3ffff0000ULL) | (insn2 & 0xffff);
+      *poff = (off ^ 0x200000000ULL) - 0x200000000ULL;
+      return TRUE;
+    }
+
+  insn2 >>= 32;
+
   /* Check that regs match.  */
-  if (((insn2 >> 16) & 31) != ((*pinsn1 >> 21) & 31))
+  if (((insn2 >> 16) & 31) != ((insn1 >> 21) & 31))
     return FALSE;
 
   switch ((insn2 >> 26) & 63)
@@ -8308,7 +8327,7 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
     case 54: /* stfd */
       /* These are the PMLS cases, where we just need to tack a prefix
 	 on the insn.  */
-      i1new = ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
+      insn1 = ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
 	       | (insn2 & ((63ULL << 26) | (31ULL << 21))));
       off = insn2 & 0xffff;
       break;
@@ -8316,7 +8335,7 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
     case 58: /* lwa, ld */
       if ((insn2 & 1) != 0)
 	return FALSE;
-      i1new = ((1ULL << 58) | (1ULL << 52)
+      insn1 = ((1ULL << 58) | (1ULL << 52)
 	       | (insn2 & 2 ? 41ULL << 26 : 57ULL << 26)
 	       | (insn2 & (31ULL << 21)));
       off = insn2 & 0xfffc;
@@ -8325,7 +8344,7 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
     case 57: /* lxsd, lxssp */
       if ((insn2 & 3) < 2)
 	return FALSE;
-      i1new = ((1ULL << 58) | (1ULL << 52)
+      insn1 = ((1ULL << 58) | (1ULL << 52)
 	       | ((40ULL | (insn2 & 3)) << 26)
 	       | (insn2 & (31ULL << 21)));
       off = insn2 & 0xfffc;
@@ -8336,14 +8355,14 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
 	return FALSE;
       else if ((insn2 & 3) >= 2)
 	{
-	  i1new = ((1ULL << 58) | (1ULL << 52)
+	  insn1 = ((1ULL << 58) | (1ULL << 52)
 		   | ((44ULL | (insn2 & 3)) << 26)
 		   | (insn2 & (31ULL << 21)));
 	  off = insn2 & 0xfffc;
 	}
       else
 	{
-	  i1new = ((1ULL << 58) | (1ULL << 52)
+	  insn1 = ((1ULL << 58) | (1ULL << 52)
 		   | ((50ULL | (insn2 & 4) | ((insn2 & 8) >> 3)) << 26)
 		   | (insn2 & (31ULL << 21)));
 	  off = insn2 & 0xfff0;
@@ -8351,7 +8370,7 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
       break;
 
     case 56: /* lq */
-      i1new = ((1ULL << 58) | (1ULL << 52)
+      insn1 = ((1ULL << 58) | (1ULL << 52)
 	       | (insn2 & ((63ULL << 26) | (31ULL << 21))));
       off = insn2 & 0xffff;
       break;
@@ -8359,14 +8378,14 @@ xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
     case 62: /* std, stq */
       if ((insn2 & 1) != 0)
 	return FALSE;
-      i1new = ((1ULL << 58) | (1ULL << 52)
+      insn1 = ((1ULL << 58) | (1ULL << 52)
 	       | ((insn2 & 2) == 0 ? 61ULL << 26 : 60ULL << 26)
 	       | (insn2 & (31ULL << 21)));
       off = insn2 & 0xfffc;
       break;
     }
 
-  *pinsn1 = i1new;
+  *pinsn1 = insn1;
   *pinsn2 = (uint64_t) NOP << 32;
   *poff = (off ^ 0x8000) - 0x8000;
   return TRUE;
@@ -15413,7 +15432,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 			  pinsn2 = bfd_get_32 (input_bfd, contents + off2);
 			  pinsn2 <<= 32;
 			  if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
-			    break;
+			    {
+			      if (off2 + 8 > input_section->size)
+				break;
+			      pinsn2 |= bfd_get_32 (input_bfd,
+						    contents + off2 + 4);
+			    }
 			  if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off))
 			    {
 			      addend += addend_off;
@@ -15424,6 +15448,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 					  contents + offset + 4);
 			      bfd_put_32 (input_bfd, pinsn2 >> 32,
 					  contents + off2);
+			      if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
+				bfd_put_32 (input_bfd, pinsn2,
+					    contents + off2 + 4);
 			    }
 			}
 		    }
diff --git a/ld/ChangeLog b/ld/ChangeLog
index b654eb9..0da9e25 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,9 @@
+2019-09-05  Alan Modra  <amodra@gmail.com>
+
+	* testsuite/ld-powerpc/pcrelopt.s,
+	* testsuite/ld-powerpc/pcrelopt.d: Test offset and prefix in
+	second instruction.
+
 2019-08-29  Alan Modra  <amodra@gmail.com>
 
 	PR ld/24406
diff --git a/ld/testsuite/ld-powerpc/pcrelopt.d b/ld/testsuite/ld-powerpc/pcrelopt.d
index 18fdb95..aeaa0cd 100644
--- a/ld/testsuite/ld-powerpc/pcrelopt.d
+++ b/ld/testsuite/ld-powerpc/pcrelopt.d
@@ -80,10 +80,17 @@ Disassembly of section \.text:
 .*:	(04 10 00 01|01 00 10 04) 	pstxv   vs0,66028
 .*:	(d8 00 01 ec|ec 01 00 d8) 
 .*:	(60 00 00 00|00 00 00 60) 	nop
-.*:	(04 10 00 01|01 00 10 04) 	pld     r9,66008
-.*:	(e5 20 01 d8|d8 01 20 e5) 
-.*:	(e8 09 00 00|00 00 09 e8) 	ld      r0,0\(r9\)
+.*:	(06 10 00 01|01 00 10 06) 	plbz    r3,70676
+.*:	(88 60 14 14|14 14 60 88) 
+.*:	(60 00 00 00|00 00 00 60) 	nop
 .*:	(60 00 00 00|00 00 00 60) 	nop
-.*:	(06 10 00 01|01 00 10 06) 	pla     r7,66000
-.*:	(38 e0 01 d0|d0 01 e0 38) 
+.*:	(04 10 12 35|35 12 10 04) 	plq     r4,305485896
+.*:	(e0 80 58 48|48 58 80 e0) 
+.*:	(07 00 00 00|00 00 00 07) 	pnop
+.*:	(00 00 00 00|00 00 00 00) 
+.*:	(04 10 00 01|01 00 10 04) 	pld     r9,65976
+.*:	(e5 20 01 b8|b8 01 20 e5) 
+.*:	(e8 09 00 00|00 00 09 e8) 	ld      r0,0\(r9\)
+.*:	(06 10 00 01|01 00 10 06) 	pla     r7,65972
+.*:	(38 e0 01 b4|b4 01 e0 38) 
 .*:	(88 c7 00 00|00 00 c7 88) 	lbz     r6,0\(r7\)
diff --git a/ld/testsuite/ld-powerpc/pcrelopt.s b/ld/testsuite/ld-powerpc/pcrelopt.s
index 78b0f51..715a52b 100644
--- a/ld/testsuite/ld-powerpc/pcrelopt.s
+++ b/ld/testsuite/ld-powerpc/pcrelopt.s
@@ -103,6 +103,18 @@ _start:
 		.reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8)
 0:	stxv 0,0(9)
 
+#offsets are allowed too
+	pld 9,sym@got@pcrel
+0:
+	lbz 3,0x1234(9)
+	.reloc 0b-8,R_PPC64_PCREL_OPT,(.-4)-(0b-8)
+
+#and prefix insns as the second insn
+	pld 9,sym@got@pcrel
+0:
+	plq 4,0x12345678(9)
+	.reloc 0b-8,R_PPC64_PCREL_OPT,(.-8)-(0b-8)
+
 # This should not optimize
 	.extern i
 	.type i,@object


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]