diff options
author | Richard Henderson <rth@redhat.com> | 2001-09-09 20:42:11 +0000 |
---|---|---|
committer | Richard Henderson <rth@redhat.com> | 2001-09-09 20:42:11 +0000 |
commit | 1cd6895c5500ca8bdab8720e856fd4eba11589f0 (patch) | |
tree | babbd0acb90f34a193237d0748f3be7c82e94d47 /bfd | |
parent | 79bcdb567f930dd4e76f1353df489c31d1ec4283 (diff) | |
download | binutils-1cd6895c5500ca8bdab8720e856fd4eba11589f0.tar.gz binutils-1cd6895c5500ca8bdab8720e856fd4eba11589f0.tar.bz2 binutils-1cd6895c5500ca8bdab8720e856fd4eba11589f0.zip |
* elf64-alpha.c (elf64_alpha_relax_with_lituse): Nop out gpdisp
following a call to a near function.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 5 | ||||
-rw-r--r-- | bfd/elf64-alpha.c | 38 |
2 files changed, 35 insertions, 8 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c17ff62cc69..78f3649759f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2001-09-09 Richard Henderson <rth@redhat.com> + + * elf64-alpha.c (elf64_alpha_relax_with_lituse): Nop out gpdisp + following a call to a near function. + 2001-09-08 Richard Henderson <rth@redhat.com> * elf64-alpha.c (elf64_alpha_relocate_section): Soft fail diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index 9e22023f5d8..df0650bec41 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -1149,14 +1149,36 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend) else all_optimized = false; - /* ??? If target gp == current gp we can eliminate the gp reload. - This does depend on every place a gp could be reloaded will - be, which currently happens for all code produced by gcc, but - not necessarily by hand-coded assembly, or if sibling calls - are enabled in gcc. - - Perhaps conditionalize this on a flag being set in the target - object file's header, and have gcc set it? */ + /* Even if the target is not in range for a direct branch, + if we share a GP, we can eliminate the gp reload. */ + if (optdest) + { + Elf_Internal_Rela *gpdisp + = (elf64_alpha_find_reloc_at_ofs + (irel, irelend, urel->r_offset + 4, R_ALPHA_GPDISP)); + if (gpdisp) + { + bfd_byte *p_ldah = info->contents + gpdisp->r_offset; + bfd_byte *p_lda = p_ldah + gpdisp->r_addend; + unsigned int ldah = bfd_get_32 (info->abfd, p_ldah); + unsigned int lda = bfd_get_32 (info->abfd, p_lda); + + /* Verify that the instruction is "ldah $29,0($26)". + Consider a function that ends in a noreturn call, + and that the next function begins with an ldgp, + and that by accident there is no padding between. + In that case the insn would use $27 as the base. */ + if (ldah == 0x27ba0000 && lda == 0x23bd0000) + { + bfd_put_32 (info->abfd, INSN_UNOP, p_ldah); + bfd_put_32 (info->abfd, INSN_UNOP, p_lda); + + gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); + info->changed_contents = true; + info->changed_relocs = true; + } + } + } } break; } |