aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog6
-rw-r--r--gold/powerpc.cc32
2 files changed, 38 insertions, 0 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 9359493..2343215 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,9 @@
+2017-08-30 Alan Modra <amodra@gmail.com>
+
+ * 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.
+
2017-08-29 Alan Modra <amodra@gmail.com>
* options.h (tls_get_addr_optimize): New option.
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 7f3f025..ff116e3 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -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());