diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h @@ -28,6 +28,7 @@ Pointer64Anon, Page21, PageOffset12, + MoveWide16, GOTPage21, GOTPageOffset12, TLVPage21, @@ -72,6 +73,25 @@ return 0; } +// Returns whether the Instr is MOVK/MOVZ (imm16) with a zero immediate field +inline bool isMoveWideImm16(uint32_t Instr) { + constexpr uint32_t MoveWideImm16Mask = 0x5f9fffe0; + return (Instr & MoveWideImm16Mask) == 0x52800000; +} + +// Returns the amount the address operand of MOVK/MOVZ (imm16) +// should be shifted right by. +// +// The shift value is specfied in the assembly as LSL #. +inline unsigned getMoveWide16Shift(uint32_t Instr) { + if (isMoveWideImm16(Instr)) { + uint32_t ImplicitShift = (Instr >> 21) & 0b11; + return ImplicitShift << 4; + } + + return 0; +} + /// Apply fixup expression for edge to block content. inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) { using namespace support; @@ -152,6 +172,20 @@ *(ulittle32_t *)FixupPtr = FixedInstr; break; } + case MoveWide16: { + uint64_t TargetOffset = + (E.getTarget().getAddress() + E.getAddend()).getValue(); + + uint32_t RawInstr = *(ulittle32_t *)FixupPtr; + assert(isMoveWideImm16(RawInstr) && + "RawInstr isn't a MOVK/MOVZ instruction"); + + unsigned ImmShift = getMoveWide16Shift(RawInstr); + uint32_t Imm = (TargetOffset >> ImmShift) & 0xffff; + uint32_t FixedInstr = RawInstr | (Imm << 5); + *(ulittle32_t *)FixupPtr = FixedInstr; + break; + } case LDRLiteral19: { assert((FixupAddress.getValue() & 0x3) == 0 && "LDR is not 32-bit aligned"); assert(E.getAddend() == 0 && "LDRLiteral19 with non-zero addend"); diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp --- a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp @@ -38,6 +38,8 @@ return "Page21"; case PageOffset12: return "PageOffset12"; + case MoveWide16: + return "MoveWide16"; case GOTPage21: return "GOTPage21"; case GOTPageOffset12: