forked from Imagelibrary/binutils-gdb
PowerPC TPREL16_HA/LO reloc optimization
In the TLS GD/LD to LE optimization, ld replaces a sequence like addi 3,2,x@got@tlsgd R_PPC64_GOT_TLSGD16 x bl __tls_get_addr(x@tlsgd) R_PPC64_TLSGD x R_PPC64_REL24 __tls_get_addr nop with addis 3,13,x@tprel@ha R_PPC64_TPREL16_HA x addi 3,3,x@tprel@l R_PPC64_TPREL16_LO x nop When the tprel offset is small, this can be further optimized to nop addi 3,13,x@tprel nop bfd/ * elf64-ppc.c (struct ppc_link_hash_table): Add do_tls_opt. (ppc64_elf_tls_optimize): Set it. (ppc64_elf_relocate_section): Nop addis on TPREL16_HA, and convert insn on TPREL16_LO and TPREL16_LO_DS relocs to use r13 when addis would add zero. * elf32-ppc.c (struct ppc_elf_link_hash_table): Add do_tls_opt. (ppc_elf_tls_optimize): Set it. (ppc_elf_relocate_section): Nop addis on TPREL16_HA, and convert insn on TPREL16_LO relocs to use r2 when addis would add zero. gold/ * powerpc.cc (Target_powerpc::Relocate::relocate): Nop addis on TPREL16_HA, and convert insn on TPREL16_LO and TPREL16_LO_DS relocs to use r2/r13 when addis would add zero. ld/ * testsuite/ld-powerpc/tls.s: Add calls with tls markers. * testsuite/ld-powerpc/tls32.s: Likewise. * testsuite/ld-powerpc/powerpc.exp: Run tls marker tests. * testsuite/ld-powerpc/tls.d: Adjust for TPREL16_HA/LO optimization. * testsuite/ld-powerpc/tlsexe.d: Likewise. * testsuite/ld-powerpc/tlsexetoc.d: Likewise. * testsuite/ld-powerpc/tlsld.d: Likewise. * testsuite/ld-powerpc/tlsmark.d: Likewise. * testsuite/ld-powerpc/tlsopt4.d: Likewise. * testsuite/ld-powerpc/tlstoc.d: Likewise.
This commit is contained in:
@@ -8974,6 +8974,38 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_POWERPC_TPREL16_HA:
|
||||
if (parameters->options().tls_optimize() && value + 0x8000 < 0x10000)
|
||||
{
|
||||
Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
|
||||
Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
|
||||
if ((insn & ((0x3f << 26) | 0x1f << 16))
|
||||
!= ((15u << 26) | ((size == 32 ? 2 : 13) << 16)))
|
||||
;
|
||||
else
|
||||
{
|
||||
elfcpp::Swap<32, big_endian>::writeval(iview, nop);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_PPC64_TPREL16_LO_DS:
|
||||
if (size == 32)
|
||||
// R_PPC_TLSGD, R_PPC_TLSLD
|
||||
break;
|
||||
// Fall through.
|
||||
case elfcpp::R_POWERPC_TPREL16_LO:
|
||||
if (parameters->options().tls_optimize() && value + 0x8000 < 0x10000)
|
||||
{
|
||||
Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
|
||||
Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
|
||||
insn &= ~(0x1f << 16);
|
||||
insn |= (size == 32 ? 2 : 13) << 16;
|
||||
elfcpp::Swap<32, big_endian>::writeval(iview, insn);
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_PPC64_ENTRY:
|
||||
value = (target->got_section()->output_section()->address()
|
||||
+ object->toc_base_offset());
|
||||
|
||||
Reference in New Issue
Block a user