diff options
author | Fangrui Song <i@maskray.me> | 2023-02-27 16:19:13 -0800 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2023-02-27 16:19:13 -0800 |
commit | 7198c87f42f6c15d76b127c1c63530e9b4d5dd39 (patch) | |
tree | 023c183cf970df2ad707c3166de7b3cae72aea8e /lld/ELF | |
parent | d77f96a9e0c86a35f5d5986058b4dcce30113cca (diff) | |
download | llvm-7198c87f42f6c15d76b127c1c63530e9b4d5dd39.tar.gz |
[ELF][PPC64] Actually implement --no-power10-stubs
When a caller that does not use TOC calls a function, a call stub is needed if
the function may use TOC. --no-power10-stubs avoids PC-relative instructions in
the code sequence.
The --no-power10-stubs=no implementation added in D94627 is wrong.
First, the first instruction incorrectly uses `mflr 0` (instead of `mflr 12`).
Second, for the PLT case, it uses addis+addi with getVA instead of addis+ld with
getGotPltVA.
Diffstat (limited to 'lld/ELF')
-rw-r--r-- | lld/ELF/Thunks.cpp | 18 | ||||
-rw-r--r-- | lld/ELF/Thunks.h | 4 |
2 files changed, 11 insertions, 11 deletions
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp index ce35bb525835..ca0d34dce7dc 100644 --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -1089,13 +1089,17 @@ void PPC64R12SetupStub::writeTo(uint8_t *buf) { buf, (gotPlt ? PLD_R12_NO_DISP : PADDI_R12_NO_DISP) | imm); nextInstOffset = 8; } else { - uint32_t off = destination.getVA(addend) - getThunkTargetSym()->getVA() - 8; - write32(buf + 0, 0x7c0802a6); // mflr r12 - write32(buf + 4, 0x429f0005); // bcl 20,31,.+4 - write32(buf + 8, 0x7d6802a6); // mflr r11 - write32(buf + 12, 0x7d8803a6); // mtlr r12 - write32(buf + 16, 0x3d8b0000 | computeHiBits(off));// addis r12,r11,off@ha - write32(buf + 20, 0x398c0000 | (off & 0xffff)); // addi r12,r12,off@l + uint32_t off = offset - 8; + write32(buf + 0, 0x7d8802a6); // mflr 12 + write32(buf + 4, 0x429f0005); // bcl 20,31,.+4 + write32(buf + 8, 0x7d6802a6); // mflr 11 + write32(buf + 12, 0x7d8803a6); // mtlr 12 + write32(buf + 16, + 0x3d8b0000 | ((off + 0x8000) >> 16)); // addis 12,11,off@ha + if (gotPlt) + write32(buf + 20, 0xe98c0000 | (off & 0xffff)); // ld 12, off@l(12) + else + write32(buf + 20, 0x398c0000 | (off & 0xffff)); // addi 12,12,off@l nextInstOffset = 24; } write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12 diff --git a/lld/ELF/Thunks.h b/lld/ELF/Thunks.h index 86aaee15f93b..12ddf08cadc0 100644 --- a/lld/ELF/Thunks.h +++ b/lld/ELF/Thunks.h @@ -73,10 +73,6 @@ void writePPC32PltCallStub(uint8_t *buf, uint64_t gotPltVA, const InputFile *file, int64_t addend); void writePPC64LoadAndBranch(uint8_t *buf, int64_t offset); -static inline uint16_t computeHiBits(uint32_t toCompute) { - return (toCompute + 0x8000) >> 16; -} - } // namespace lld::elf #endif |