From a7c4979727e13498b8d4d85c72ddf65611c532a9 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 31 Aug 2015 17:55:14 +0930 Subject: Optimise PowerPC64 r2 adjusting stubs Sometimes these stubs don't need to change the low 16-bits of r2, so in that case omit a useless addi r2,r2,0 insn. Also, change the get_r2off error return from 0 to -1 since 0 is a valid return for ELFv2 -R objects. * elf64-ppc.c (get_r2off): Return -1 on error. (ppc_build_one_stub): Adjust for get_r2off change. Don't emit addi r2,r2,0 on r2off stubs when the low 16-bit delta is zero. (ppc_size_one_stub): Corresponding size changes for r2off stubs. Add condition in test for -R objects. --- bfd/ChangeLog | 8 ++++++++ bfd/elf64-ppc.c | 32 ++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 12 deletions(-) (limited to 'bfd') diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 58d2359..5742aa3 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,13 @@ 2015-08-31 Alan Modra + * elf64-ppc.c (get_r2off): Return -1 on error. + (ppc_build_one_stub): Adjust for get_r2off change. Don't emit + addi r2,r2,0 on r2off stubs when the low 16-bit delta is zero. + (ppc_size_one_stub): Corresponding size changes for r2off stubs. + Add condition in test for -R objects. + +2015-08-31 Alan Modra + * section.c (section_id): Make file scope. (bfd_get_next_section_id): New function. * elf64-ppc.c (struct map_stub): Remove toc_off field. Move decl. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index efa124e..810b227 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -10540,10 +10540,10 @@ get_r2off (struct bfd_link_info *info, info->callbacks->einfo (_("%P: cannot find opd entry toc for `%T'\n"), stub_entry->h->elf.root.root.string); bfd_set_error (bfd_error_bad_value); - return 0; + return (bfd_vma) -1; } if (!bfd_get_section_contents (opd->owner, opd, buf, opd_off + 8, 8)) - return 0; + return (bfd_vma) -1; r2off = bfd_get_64 (opd->owner, buf); r2off -= elf_gp (info->output_bfd); } @@ -10599,23 +10599,28 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) { bfd_vma r2off = get_r2off (info, stub_entry); - if (r2off == 0) + if (r2off == (bfd_vma) -1) { htab->stub_error = TRUE; return FALSE; } bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc); loc += 4; - size = 12; + size = 8; if (PPC_HA (r2off) != 0) { - size = 16; bfd_put_32 (htab->params->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); loc += 4; + size += 4; + } + if (PPC_LO (r2off) != 0) + { + bfd_put_32 (htab->params->stub_bfd, + ADDI_R2_R2 | PPC_LO (r2off), loc); + loc += 4; + size += 4; } - bfd_put_32 (htab->params->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); - loc += 4; off -= size - 4; } bfd_put_32 (htab->params->stub_bfd, B_DOT | (off & 0x3fffffc), loc); @@ -10796,7 +10801,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) { bfd_vma r2off = get_r2off (info, stub_entry); - if (r2off == 0 && htab->opd_abi) + if (r2off == (bfd_vma) -1) { htab->stub_error = TRUE; return FALSE; @@ -11062,14 +11067,16 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (stub_entry->stub_type == ppc_stub_long_branch_r2off) { r2off = get_r2off (info, stub_entry); - if (r2off == 0 && htab->opd_abi) + if (r2off == (bfd_vma) -1) { htab->stub_error = TRUE; return FALSE; } - size = 12; + size = 8; if (PPC_HA (r2off) != 0) - size = 16; + size += 4; + if (PPC_LO (r2off) != 0) + size += 4; off -= size - 4; } @@ -11079,7 +11086,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) Do the same for -R objects without function descriptors. */ if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off || (stub_entry->stub_type == ppc_stub_long_branch_r2off - && r2off == 0)) + && r2off == 0 + && htab->sec_info[stub_entry->target_section->id].toc_off == 0)) { struct ppc_branch_hash_entry *br_entry; -- cgit v1.1