[lld][ELF][Hexagon] add more relocations

llvm-svn: 176277
This commit is contained in:
Shankar Easwaran 2013-02-28 18:29:23 +00:00
parent c32d513385
commit 8a2d1990d8
2 changed files with 100 additions and 26 deletions

View File

@ -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) {

View File

@ -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: