PowerPC TPREL16_HA/LO reloc optimization
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index 5b96a047e7225437c301c996b04aa57172578d6e..cf7c178c0ff9adf82f3b94cddcf7d5b3070e4657 100644 (file)
@@ -4120,6 +4120,9 @@ struct ppc_link_hash_table
   unsigned int second_toc_pass:1;
   unsigned int do_toc_opt:1;
 
+  /* Set if tls optimization is enabled.  */
+  unsigned int do_tls_opt:1;
+
   /* Set on error.  */
   unsigned int stub_error:1;
 
@@ -8925,6 +8928,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
 
   if (toc_ref != NULL)
     free (toc_ref);
+  htab->do_tls_opt = 1;
   return TRUE;
 }
 
@@ -15152,6 +15156,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       /* Multi-instruction sequences that access the TOC can be
         optimized, eg. addis ra,r2,0; addi rb,ra,x;
         to             nop;           addi rb,r2,x;  */
+      howto = ppc64_elf_howto_table[(int) r_type];
       switch (r_type)
        {
        default:
@@ -15213,10 +15218,37 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              bfd_put_32 (input_bfd, insn, p);
            }
          break;
+
+       case R_PPC64_TPREL16_HA:
+         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+           {
+             bfd_byte *p = contents + (rel->r_offset & ~3);
+             insn = bfd_get_32 (input_bfd, p);
+             if ((insn & ((0x3f << 26) | 0x1f << 16))
+                 != ((15u << 26) | (13 << 16)) /* addis rt,13,imm */)
+               /* xgettext:c-format */
+               info->callbacks->minfo
+                 (_("%H: warning: %s unexpected insn %#x.\n"),
+                  input_bfd, input_section, rel->r_offset, howto->name, insn);
+             else
+               bfd_put_32 (input_bfd, NOP, p);
+           }
+         break;
+
+       case R_PPC64_TPREL16_LO:
+       case R_PPC64_TPREL16_LO_DS:
+         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+           {
+             bfd_byte *p = contents + (rel->r_offset & ~3);
+             insn = bfd_get_32 (input_bfd, p);
+             insn &= ~(0x1f << 16);
+             insn |= 13 << 16;
+             bfd_put_32 (input_bfd, insn, p);
+           }
+         break;
        }
 
       /* Do any further special processing.  */
-      howto = ppc64_elf_howto_table[(int) r_type];
       switch (r_type)
        {
        default:
This page took 0.026988 seconds and 4 git commands to generate.