Blame SOURCES/gdb-rhbz1125820-ppc64le-enablement-35of37.patch

2c2fa1
commit 397998fc32a34d3c8993ef46da45c3957a4dd402
2c2fa1
Author: Alan Modra <amodra@gmail.com>
2c2fa1
Date:   Tue Jun 3 10:55:29 2014 +0930
2c2fa1
2c2fa1
    Support fusion for ELFv2 stubs
2c2fa1
    
2c2fa1
    Power8 fuses addis,addi and addis,ld sequences when the target of the
2c2fa1
    addis is the same as the addi/ld.  Thus
2c2fa1
        addis r12,r2,xxx@ha
2c2fa1
        addi r12,r12,xxx@l / ld r12,xxx@l(r12)
2c2fa1
    is faster than
2c2fa1
        addis r11,r2,xxx@ha
2c2fa1
        addi r12,r11,xxx@l / ld r12,xxx@l(r11)
2c2fa1
    So use the form that allows fusion in plt call and branch stubs.
2c2fa1
    
2c2fa1
    bfd/
2c2fa1
    	* elf64-ppc.c (ADDIS_R12_R2): Define.
2c2fa1
    	(build_plt_stub): Support fusion on ELFv2 stub.
2c2fa1
    	(ppc_build_one_stub): Likewise for plt branch stubs.
2c2fa1
    gold/
2c2fa1
    	* powerpc.cc (addis_12_2): Define.
2c2fa1
    	(Stub_table::do_write): Support fusion on ELFv2 stubs.
2c2fa1
    ld/testsuite/
2c2fa1
    	* ld-powerpc/elfv2exe.d: Update for changed plt call stubs.
2c2fa1
    gdb/
2c2fa1
    	* ppc64-tdep.c (ppc64_standard_linkage8): New.
2c2fa1
    	(ppc64_skip_trampoline_code): Recognise ELFv2 stub supporting fusion.
2c2fa1
2c2fa1
Index: gdb-7.6.1/bfd/elf64-ppc.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/bfd/elf64-ppc.c
2c2fa1
+++ gdb-7.6.1/bfd/elf64-ppc.c
2c2fa1
@@ -175,6 +175,7 @@ static bfd_vma opd_entry_value
2c2fa1
 
2c2fa1
 #define LD_R2_0R1	0xe8410000	/* ld    %r2,0(%r1)      */
2c2fa1
 
2c2fa1
+#define ADDIS_R12_R2	0x3d820000	/* addis %r12,%r2,xxx@ha     */
2c2fa1
 #define ADDIS_R12_R12	0x3d8c0000	/* addis %r12,%r12,xxx@ha */
2c2fa1
 #define LD_R12_0R12	0xe98c0000	/* ld    %r12,xxx@l(%r12) */
2c2fa1
 
2c2fa1
@@ -9990,8 +9991,16 @@ build_plt_stub (struct ppc_link_hash_tab
2c2fa1
       if (ALWAYS_EMIT_R2SAVE
2c2fa1
 	  || stub_entry->stub_type == ppc_stub_plt_call_r2save)
2c2fa1
 	bfd_put_32 (obfd, STD_R2_0R1 + STK_TOC (htab), p),	p += 4;
2c2fa1
-      bfd_put_32 (obfd, ADDIS_R11_R2 | PPC_HA (offset), p),	p += 4;
2c2fa1
-      bfd_put_32 (obfd, LD_R12_0R11 | PPC_LO (offset), p),	p += 4;
2c2fa1
+      if (plt_load_toc)
2c2fa1
+	{
2c2fa1
+	  bfd_put_32 (obfd, ADDIS_R11_R2 | PPC_HA (offset), p),	p += 4;
2c2fa1
+	  bfd_put_32 (obfd, LD_R12_0R11 | PPC_LO (offset), p),	p += 4;
2c2fa1
+	}
2c2fa1
+      else
2c2fa1
+	{
2c2fa1
+	  bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p),	p += 4;
2c2fa1
+	  bfd_put_32 (obfd, LD_R12_0R12 | PPC_LO (offset), p),	p += 4;
2c2fa1
+	}
2c2fa1
       if (plt_load_toc
2c2fa1
 	  && PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
2c2fa1
 	{
2c2fa1
@@ -10410,9 +10419,9 @@ ppc_build_one_stub (struct bfd_hash_entr
2c2fa1
 	  if (PPC_HA (off) != 0)
2c2fa1
 	    {
2c2fa1
 	      size = 16;
2c2fa1
-	      bfd_put_32 (htab->stub_bfd, ADDIS_R11_R2 | PPC_HA (off), loc);
2c2fa1
+	      bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (off), loc);
2c2fa1
 	      loc += 4;
2c2fa1
-	      bfd_put_32 (htab->stub_bfd, LD_R12_0R11 | PPC_LO (off), loc);
2c2fa1
+	      bfd_put_32 (htab->stub_bfd, LD_R12_0R12 | PPC_LO (off), loc);
2c2fa1
 	    }
2c2fa1
 	  else
2c2fa1
 	    {
2c2fa1
@@ -10436,9 +10445,9 @@ ppc_build_one_stub (struct bfd_hash_entr
2c2fa1
 	  if (PPC_HA (off) != 0)
2c2fa1
 	    {
2c2fa1
 	      size += 4;
2c2fa1
-	      bfd_put_32 (htab->stub_bfd, ADDIS_R11_R2 | PPC_HA (off), loc);
2c2fa1
+	      bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (off), loc);
2c2fa1
 	      loc += 4;
2c2fa1
-	      bfd_put_32 (htab->stub_bfd, LD_R12_0R11 | PPC_LO (off), loc);
2c2fa1
+	      bfd_put_32 (htab->stub_bfd, LD_R12_0R12 | PPC_LO (off), loc);
2c2fa1
 	    }
2c2fa1
 	  else
2c2fa1
 	    bfd_put_32 (htab->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc);
2c2fa1
Index: gdb-7.6.1/gdb/ppc64-tdep.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/ppc64-tdep.c
2c2fa1
+++ gdb-7.6.1/gdb/ppc64-tdep.c
2c2fa1
@@ -303,6 +303,29 @@ static struct ppc_insn_pattern ppc64_sta
2c2fa1
     { 0, 0, 0 }
2c2fa1
   };
2c2fa1
 
2c2fa1
+/* ELFv2 PLT call stub to access PLT entries more than +/- 32k from r2,
2c2fa1
+   supporting fusion.  */
2c2fa1
+
2c2fa1
+static struct ppc_insn_pattern ppc64_standard_linkage8[] =
2c2fa1
+  {
2c2fa1
+    /* std r2, 24(r1) <optional> */
2c2fa1
+    { -1, insn_ds (62, 2, 1, 24, 0), 1 },
2c2fa1
+
2c2fa1
+    /* addis r12, r2, <any> */
2c2fa1
+    { insn_d (-1, -1, -1, 0), insn_d (15, 12, 2, 0), 0 },
2c2fa1
+
2c2fa1
+    /* ld r12, <any>(r12) */
2c2fa1
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 12, 0, 0), 0 },
2c2fa1
+
2c2fa1
+    /* mtctr r12 */
2c2fa1
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
2c2fa1
+
2c2fa1
+    /* bctr */
2c2fa1
+    { -1, 0x4e800420, 0 },
2c2fa1
+
2c2fa1
+    { 0, 0, 0 }
2c2fa1
+  };
2c2fa1
+
2c2fa1
 /* When the dynamic linker is doing lazy symbol resolution, the first
2c2fa1
    call to a function in another object will go like this:
2c2fa1
 
2c2fa1
@@ -437,10 +460,14 @@ ppc64_skip_trampoline_code (struct frame
2c2fa1
 				    ARRAY_SIZE (ppc64_standard_linkage4))),
2c2fa1
 			  MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage5),
2c2fa1
 				    ARRAY_SIZE (ppc64_standard_linkage6)),
2c2fa1
-			       ARRAY_SIZE (ppc64_standard_linkage7))) - 1];
2c2fa1
+			       MAX (ARRAY_SIZE (ppc64_standard_linkage7),
2c2fa1
+				    ARRAY_SIZE (ppc64_standard_linkage8))))
2c2fa1
+		     - 1];
2c2fa1
   CORE_ADDR target;
2c2fa1
 
2c2fa1
-  if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7, insns))
2c2fa1
+  if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8, insns))
2c2fa1
+    pc = ppc64_standard_linkage4_target (frame, pc, insns);
2c2fa1
+  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7, insns))
2c2fa1
     pc = ppc64_standard_linkage3_target (frame, pc, insns);
2c2fa1
   else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6, insns))
2c2fa1
     pc = ppc64_standard_linkage4_target (frame, pc, insns);