+/* Return true if symbol is defined statically. */
+
+static bfd_boolean
+is_static_defined (struct elf_link_hash_entry *h)
+{
+ return ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->root.u.def.section != NULL
+ && h->root.u.def.section->output_section != NULL);
+}
+
+/* If INSN is an opcode that may be used with an @tls operand, return
+ the transformed insn for TLS optimisation, otherwise return 0. If
+ REG is non-zero only match an insn with RB or RA equal to REG. */
+
+unsigned int
+_bfd_elf_ppc_at_tls_transform (unsigned int insn, unsigned int reg)
+{
+ unsigned int rtra;
+
+ if ((insn & (0x3f << 26)) != 31 << 26)
+ return 0;
+
+ if (reg == 0 || ((insn >> 11) & 0x1f) == reg)
+ rtra = insn & ((1 << 26) - (1 << 16));
+ else if (((insn >> 16) & 0x1f) == reg)
+ rtra = (insn & (0x1f << 21)) | ((insn & (0x1f << 11)) << 5);
+ else
+ return 0;
+
+ if ((insn & (0x3ff << 1)) == 266 << 1)
+ /* add -> addi. */
+ insn = 14 << 26;
+ else if ((insn & (0x1f << 1)) == 23 << 1
+ && ((insn & (0x1f << 6)) < 14 << 6
+ || ((insn & (0x1f << 6)) >= 16 << 6
+ && (insn & (0x1f << 6)) < 24 << 6)))
+ /* load and store indexed -> dform. */
+ insn = (32 | ((insn >> 6) & 0x1f)) << 26;
+ else if ((insn & (((0x1a << 5) | 0x1f) << 1)) == 21 << 1)
+ /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */
+ insn = ((58 | ((insn >> 6) & 4)) << 26) | ((insn >> 6) & 1);
+ else if ((insn & (((0x1f << 5) | 0x1f) << 1)) == 341 << 1)
+ /* lwax -> lwa. */
+ insn = (58 << 26) | 2;
+ else
+ return 0;
+ insn |= rtra;
+ return insn;
+}
+
+/* If INSN is an opcode that may be used with an @tprel operand, return
+ the transformed insn for an undefined weak symbol, ie. with the
+ thread pointer REG operand removed. Otherwise return 0. */
+
+unsigned int
+_bfd_elf_ppc_at_tprel_transform (unsigned int insn, unsigned int reg)
+{
+ if ((insn & (0x1f << 16)) == reg << 16
+ && ((insn & (0x3f << 26)) == 14u << 26 /* addi */
+ || (insn & (0x3f << 26)) == 15u << 26 /* addis */
+ || (insn & (0x3f << 26)) == 32u << 26 /* lwz */
+ || (insn & (0x3f << 26)) == 34u << 26 /* lbz */
+ || (insn & (0x3f << 26)) == 36u << 26 /* stw */
+ || (insn & (0x3f << 26)) == 38u << 26 /* stb */
+ || (insn & (0x3f << 26)) == 40u << 26 /* lhz */
+ || (insn & (0x3f << 26)) == 42u << 26 /* lha */
+ || (insn & (0x3f << 26)) == 44u << 26 /* sth */
+ || (insn & (0x3f << 26)) == 46u << 26 /* lmw */
+ || (insn & (0x3f << 26)) == 47u << 26 /* stmw */
+ || (insn & (0x3f << 26)) == 48u << 26 /* lfs */
+ || (insn & (0x3f << 26)) == 50u << 26 /* lfd */
+ || (insn & (0x3f << 26)) == 52u << 26 /* stfs */
+ || (insn & (0x3f << 26)) == 54u << 26 /* stfd */
+ || ((insn & (0x3f << 26)) == 58u << 26 /* lwa,ld,lmd */
+ && (insn & 3) != 1)
+ || ((insn & (0x3f << 26)) == 62u << 26 /* std, stmd */
+ && ((insn & 3) == 0 || (insn & 3) == 3))))
+ {
+ insn &= ~(0x1f << 16);
+ }
+ else if ((insn & (0x1f << 21)) == reg << 21
+ && ((insn & (0x3e << 26)) == 24u << 26 /* ori, oris */
+ || (insn & (0x3e << 26)) == 26u << 26 /* xori,xoris */
+ || (insn & (0x3e << 26)) == 28u << 26 /* andi,andis */))
+ {
+ insn &= ~(0x1f << 21);
+ insn |= (insn & (0x1f << 16)) << 5;
+ if ((insn & (0x3e << 26)) == 26 << 26 /* xori,xoris */)
+ insn -= 2 >> 26; /* convert to ori,oris */
+ }
+ else
+ insn = 0;
+ return insn;
+}
+