[Sparc] Repair fixups in little endian mode.

Differential Revision: http://reviews.llvm.org/D9434

llvm-svn: 236324
This commit is contained in:
James Y Knight 2015-05-01 17:13:02 +00:00
parent b2b3ff1860
commit 35e04e84fa
2 changed files with 75 additions and 12 deletions

View File

@ -98,16 +98,23 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
namespace {
class SparcAsmBackend : public MCAsmBackend {
protected:
const Target &TheTarget;
bool IsLittleEndian;
bool Is64Bit;
public:
SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {}
SparcAsmBackend(const Target &T)
: MCAsmBackend(), TheTarget(T),
IsLittleEndian(StringRef(TheTarget.getName()) == "sparcel"),
Is64Bit(StringRef(TheTarget.getName()) == "sparcv9") {}
unsigned getNumFixupKinds() const override {
return Sparc::NumTargetFixupKinds;
}
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = {
const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = {
// name offset bits flags
{ "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel },
@ -146,12 +153,54 @@ namespace {
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 }
};
const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
// name offset bits flags
{ "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br16_2", 20, 2, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br16_14", 0, 14, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_hi22", 0, 22, 0 },
{ "fixup_sparc_lo10", 0, 10, 0 },
{ "fixup_sparc_h44", 0, 22, 0 },
{ "fixup_sparc_m44", 0, 10, 0 },
{ "fixup_sparc_l44", 0, 12, 0 },
{ "fixup_sparc_hh", 0, 22, 0 },
{ "fixup_sparc_hm", 0, 10, 0 },
{ "fixup_sparc_pc22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_pc10", 0, 10, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_got22", 0, 22, 0 },
{ "fixup_sparc_got10", 0, 10, 0 },
{ "fixup_sparc_wplt30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_tls_gd_hi22", 0, 22, 0 },
{ "fixup_sparc_tls_gd_lo10", 0, 10, 0 },
{ "fixup_sparc_tls_gd_add", 0, 0, 0 },
{ "fixup_sparc_tls_gd_call", 0, 0, 0 },
{ "fixup_sparc_tls_ldm_hi22", 0, 22, 0 },
{ "fixup_sparc_tls_ldm_lo10", 0, 10, 0 },
{ "fixup_sparc_tls_ldm_add", 0, 0, 0 },
{ "fixup_sparc_tls_ldm_call", 0, 0, 0 },
{ "fixup_sparc_tls_ldo_hix22", 0, 22, 0 },
{ "fixup_sparc_tls_ldo_lox10", 0, 10, 0 },
{ "fixup_sparc_tls_ldo_add", 0, 0, 0 },
{ "fixup_sparc_tls_ie_hi22", 0, 22, 0 },
{ "fixup_sparc_tls_ie_lo10", 0, 10, 0 },
{ "fixup_sparc_tls_ie_ld", 0, 0, 0 },
{ "fixup_sparc_tls_ie_ldx", 0, 0, 0 },
{ "fixup_sparc_tls_ie_add", 0, 0, 0 },
{ "fixup_sparc_tls_le_hix22", 0, 0, 0 },
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 }
};
if (Kind < FirstTargetFixupKind)
return MCAsmBackend::getFixupKindInfo(Kind);
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
"Invalid kind!");
return Infos[Kind - FirstTargetFixupKind];
if (IsLittleEndian)
return InfosLE[Kind - FirstTargetFixupKind];
return InfosBE[Kind - FirstTargetFixupKind];
}
void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
@ -215,11 +264,6 @@ namespace {
return true;
}
bool is64Bit() const { return StringRef(TheTarget.getName()) == "sparcv9"; }
bool isLittleEndian() const {
return StringRef(TheTarget.getName()) == "sparcel";
}
};
class ELFSparcAsmBackend : public SparcAsmBackend {
@ -239,14 +283,15 @@ namespace {
// For each byte of the fragment that the fixup touches, mask in the bits
// from the fixup value. The Value has been "split up" into the
// appropriate bitfields above.
for (unsigned i = 0; i != 4; ++i)
Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff);
for (unsigned i = 0; i != 4; ++i) {
unsigned Idx = IsLittleEndian ? i : 3 - i;
Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
}
}
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
return createSparcELFObjectWriter(OS, is64Bit(), isLittleEndian(), OSABI);
return createSparcELFObjectWriter(OS, Is64Bit, IsLittleEndian, OSABI);
}
};

View File

@ -0,0 +1,18 @@
! RUN: llvm-mc %s -arch=sparcel -show-encoding | FileCheck %s
! RUN: llvm-mc -arch=sparcel -filetype=obj < %s | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-OBJ
! CHECK-OBJ: .text:
.BB0:
! Ensure instructions are emitted in reversed byte order:
! CHECK: call %g1 ! encoding: [0x00,0x40,0xc0,0x9f]
! CHECK-OBJ: 0: 00 40 c0 9f call %g1
call %g1
! ...and that fixups are applied to the correct bytes.
! CHECK: ba .BB0 ! encoding: [A,A,0b10AAAAAA,0x10]
! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
! CHECK-OBJ: 4: ff ff bf 10 ba 4194303
ba .BB0