diff options
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h | 7 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp | 119 |
2 files changed, 100 insertions, 26 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h index 24090ce7e25..3c418ef7f1e 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h @@ -23,9 +23,10 @@ typedef struct { #include "HexagonV4Encodings.h" -#define FINDV4BITMASK(INSN) findBitMask(*((uint32_t *)INSN), \ - insn_encodings_v4, \ - sizeof(insn_encodings_v4)/sizeof(Instruction)) +#define FINDV4BITMASK(INSN) \ + findBitMask((uint32_t) * ((llvm::support::ulittle32_t *) INSN), \ + insn_encodings_v4, \ + sizeof(insn_encodings_v4) / sizeof(Instruction)) /// \brief finds the scatter Bits that need to be used to apply relocations uint32_t findBitMask(uint32_t insn, Instruction *encodings, int32_t numInsns) { diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp index a064cfbe239..97f63a2acc1 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp @@ -19,25 +19,15 @@ using namespace elf; using namespace llvm::ELF; namespace { -/// \brief Word32_B22: 0x01ff3ffe : (S + A - P) >> 2 : Verify -int relocB22PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { - int32_t result = (uint32_t)(((S + A) - P)>>2); - if ((result < 0x200000) && (result > -0x200000)) { - result = lld::scatterBits<int32_t>(result, 0x01ff3ffe); - *reinterpret_cast<llvm::support::ulittle32_t *>(location) = result | - (uint32_t)*reinterpret_cast<llvm::support::ulittle32_t *>(location); - return 0; - } - return 1; -} - -/// \brief Word32_B15: 0x00df20fe : (S + A - P) >> 2 : Verify -int relocB15PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { - int32_t result = (uint32_t)(((S + A) - P)>>2); - if ((result < 0x8000) && (result > -0x8000)) { - result = lld::scatterBits<int32_t>(result, 0x00df20fe); - *reinterpret_cast<llvm::support::ulittle32_t *>(location) = result | - (uint32_t)*reinterpret_cast<llvm::support::ulittle32_t *>(location); +int relocBNPCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A, + int32_t nBits) { + int32_t result = (uint32_t)(((S + A) - P) >> 2); + int32_t range = 1 << nBits; + if (result < range && result > -range) { + result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location)); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); return 0; } return 1; @@ -64,10 +54,59 @@ int relocHI16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { /// \brief Word32: 0xffffffff : (S + A) : Truncate int reloc32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { uint32_t result = (uint32_t)(S + A); - *reinterpret_cast<llvm::support::ulittle32_t *>(location) = result | - (uint32_t)*reinterpret_cast<llvm::support::ulittle32_t *>(location); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); return 0; } + +int reloc32_6_X(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int64_t result = ((S + A) >> 6); + int64_t range = 1L << 32; + if (result > range) + return 1; + result = lld::scatterBits<int32_t>(result, 0xfff3fff); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; +} + +// R_HEX_B32_PCREL_X +int relocHexB32PCRELX(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int64_t result = ((S + A - P) >> 6); + result = lld::scatterBits<int32_t>(result, 0xfff3fff); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; +} + +// R_HEX_BN_PCREL_X +int relocHexBNPCRELX(uint8_t *location, uint64_t P, uint64_t S, uint64_t A, + int nbits) { + int32_t result = ((S + A - P) & 0x3f); + int32_t range = 1 << nbits; + if (result < range && result > -range) { + result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location)); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; + } + return 1; +} + +// R_HEX_N_X : Word32_U6 : (S + A) : Unsigned Truncate +int relocHex_N_X(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + uint32_t result = (S + A); + result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location)); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; +} + } // end anon namespace ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation( @@ -80,10 +119,13 @@ ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation( switch (ref.kind()) { case R_HEX_B22_PCREL: - relocB22PCREL(location, relocVAddress, targetVAddress, ref.addend()); + relocBNPCREL(location, relocVAddress, targetVAddress, ref.addend(), 21); break; case R_HEX_B15_PCREL: - relocB15PCREL(location, relocVAddress, targetVAddress, ref.addend()); + relocBNPCREL(location, relocVAddress, targetVAddress, ref.addend(), 14); + break; + case R_HEX_B9_PCREL: + relocBNPCREL(location, relocVAddress, targetVAddress, ref.addend(), 8); break; case R_HEX_LO16: relocLO16(location, relocVAddress, targetVAddress, ref.addend()); @@ -94,6 +136,37 @@ ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation( case R_HEX_32: reloc32(location, relocVAddress, targetVAddress, ref.addend()); break; + case R_HEX_32_6_X: + reloc32_6_X(location, relocVAddress, targetVAddress, ref.addend()); + break; + case R_HEX_B32_PCREL_X: + relocHexB32PCRELX(location, relocVAddress, targetVAddress, ref.addend()); + break; + case R_HEX_B22_PCREL_X: + relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 21); + break; + case R_HEX_B15_PCREL_X: + relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 14); + break; + case R_HEX_B13_PCREL_X: + relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 12); + break; + case R_HEX_B9_PCREL_X: + relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 8); + break; + case R_HEX_B7_PCREL_X: + relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 6); + break; + case R_HEX_16_X: + case R_HEX_12_X: + case R_HEX_11_X: + case R_HEX_10_X: + case R_HEX_9_X: + case R_HEX_8_X: + case R_HEX_7_X: + case R_HEX_6_X: + relocHex_N_X(location, relocVAddress, targetVAddress, ref.addend()); + break; case lld::Reference::kindLayoutAfter: case lld::Reference::kindLayoutBefore: case lld::Reference::kindInGroup: |