+
+ case R_PPC64_ENTRY:
+ relocation = TOCstart + htab->sec_info[input_section->id].toc_off;
+ if (!bfd_link_pic (info)
+ && !info->traditional_format
+ && relocation + 0x80008000 <= 0xffffffff)
+ {
+ unsigned int insn1, insn2;
+
+ insn1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ insn2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+ if ((insn1 & ~0xfffc) == LD_R2_0R12
+ && insn2 == ADD_R2_R2_R12)
+ {
+ bfd_put_32 (output_bfd,
+ LIS_R2 + PPC_HA (relocation),
+ contents + rel->r_offset);
+ bfd_put_32 (output_bfd,
+ ADDI_R2_R2 + PPC_LO (relocation),
+ contents + rel->r_offset + 4);
+ }
+ }
+ else
+ {
+ relocation -= (rel->r_offset
+ + input_section->output_offset
+ + input_section->output_section->vma);
+ if (relocation + 0x80008000 <= 0xffffffff)
+ {
+ unsigned int insn1, insn2;
+
+ insn1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ insn2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+ if ((insn1 & ~0xfffc) == LD_R2_0R12
+ && insn2 == ADD_R2_R2_R12)
+ {
+ bfd_put_32 (output_bfd,
+ ADDIS_R2_R12 + PPC_HA (relocation),
+ contents + rel->r_offset);
+ bfd_put_32 (output_bfd,
+ ADDI_R2_R2 + PPC_LO (relocation),
+ contents + rel->r_offset + 4);
+ }
+ }
+ }
+ break;
+
+ case R_PPC64_REL16_HA:
+ /* If we are generating a non-PIC executable, edit
+ . 0: addis 2,12,.TOC.-0b@ha
+ . addi 2,2,.TOC.-0b@l
+ used by ELFv2 global entry points to set up r2, to
+ . lis 2,.TOC.@ha
+ . addi 2,2,.TOC.@l
+ if .TOC. is in range. */
+ if (!bfd_link_pic (info)
+ && !info->traditional_format
+ && !htab->opd_abi
+ && rel->r_addend == d_offset
+ && h != NULL && &h->elf == htab->elf.hgot
+ && rel + 1 < relend
+ && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO)
+ && rel[1].r_offset == rel->r_offset + 4
+ && rel[1].r_addend == rel->r_addend + 4
+ && relocation + 0x80008000 <= 0xffffffff)
+ {
+ unsigned int insn1, insn2;
+ bfd_vma offset = rel->r_offset - d_offset;
+ insn1 = bfd_get_32 (output_bfd, contents + offset);
+ insn2 = bfd_get_32 (output_bfd, contents + offset + 4);
+ if ((insn1 & 0xffff0000) == ADDIS_R2_R12
+ && (insn2 & 0xffff0000) == ADDI_R2_R2)
+ {
+ r_type = R_PPC64_ADDR16_HA;
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ rel->r_addend -= d_offset;
+ rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_ADDR16_LO);
+ rel[1].r_addend -= d_offset + 4;
+ bfd_put_32 (output_bfd, LIS_R2, contents + offset);
+ }
+ }
+ break;