diff options
author | Alan Modra <amodra@gmail.com> | 2023-04-29 11:00:30 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2023-05-03 09:03:01 +0930 |
commit | e84ca83738a748d8afe53e74b9666e74ae708dcc (patch) | |
tree | 868ef87059cf3328927a705daecf5900abff0620 /bfd | |
parent | 59305ae6247e86f35bbe94ed1f9599af8f8e6f69 (diff) | |
download | binutils-gdb-e84ca83738a748d8afe53e74b9666e74ae708dcc.tar.gz |
_bfd_mips_elf_lo16_reloc vallo comment
This explains exactly why the high reloc adjustment is as it is,
replacing the rather nebulous existing comment. I've also changed the
expression from (lo+0x8000)&0xffff to (lo&0xffff)^0x8000 which better
matches part of the standard 16-bit sign extension (resulting in
exactly the same value), and hoisted the calculation out of the loop.
* elfxx-mips.c (_bfd_mips_elf_lo16_reloc): Expand vallo
comment. Hoist calculation out of loop.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/elfxx-mips.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index c9cd2f8099f..49355a42f7d 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -2624,7 +2624,21 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, _bfd_mips_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, false, location); - vallo = bfd_get_32 (abfd, location); + /* The high 16 bits of the addend are stored in the high insn, the + low 16 bits in the low insn, but there is a catch: You can't + just concatenate the high and low parts. The high part of the + addend is adjusted for the fact that the low part is sign + extended. For example, an addend of 0x38000 would have 0x0004 in + the high part and 0x8000 (=0xff..f8000) in the low part. + To extract the actual addend, calculate (a) + ((hi & 0xffff) << 16) + ((lo & 0xffff) ^ 0x8000) - 0x8000. + We will be applying (symbol + addend) & 0xffff to the low insn, + and we want to apply (b) (symbol + addend + 0x8000) >> 16 to the + high insn (the +0x8000 adjusting for when the applied low part is + negative). Substituting (a) into (b) and recognising that + (hi & 0xffff) is already in the high insn gives a high part + addend adjustment of (lo & 0xffff) ^ 0x8000. */ + vallo = (bfd_get_32 (abfd, location) & 0xffff) ^ 0x8000; _bfd_mips_elf_reloc_shuffle (abfd, reloc_entry->howto->type, false, location); @@ -2648,9 +2662,7 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, else if (hi->rel.howto->type == R_MICROMIPS_GOT16) hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MICROMIPS_HI16, false); - /* VALLO is a signed 16-bit number. Bias it by 0x8000 so that any - carry or borrow will induce a change of +1 or -1 in the high part. */ - hi->rel.addend += (vallo + 0x8000) & 0xffff; + hi->rel.addend += vallo; ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data, hi->input_section, output_bfd, |