mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 21:50:40 +00:00
Completed :lower16: / :upper16: support for movw / movt pairs on Darwin.
- Fixed :upper16: fix up routine. It should be shifting down the top 16 bits first. - Added support for Thumb2 :lower16: and :upper16: fix up. - Added :upper16: and :lower16: relocation support to mach-o object writer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123424 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b6436e5be1
commit
f3eb3bba16
@ -353,7 +353,10 @@ namespace macho {
|
|||||||
RIT_ARM_PreboundLazyPointer = 4,
|
RIT_ARM_PreboundLazyPointer = 4,
|
||||||
RIT_ARM_Branch24Bit = 5,
|
RIT_ARM_Branch24Bit = 5,
|
||||||
RIT_ARM_ThumbBranch22Bit = 6,
|
RIT_ARM_ThumbBranch22Bit = 6,
|
||||||
RIT_ARM_ThumbBranch32Bit = 7
|
RIT_ARM_ThumbBranch32Bit = 7,
|
||||||
|
RIT_ARM_Half = 8,
|
||||||
|
RIT_ARM_HalfDifference = 9
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace macho
|
} // end namespace macho
|
||||||
|
@ -1508,6 +1508,14 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
|
|||||||
case ARM::fixup_arm_movw_lo16_pcrel:
|
case ARM::fixup_arm_movw_lo16_pcrel:
|
||||||
Type = ELF::R_ARM_MOVW_PREL_NC;
|
Type = ELF::R_ARM_MOVW_PREL_NC;
|
||||||
break;
|
break;
|
||||||
|
case ARM::fixup_t2_movt_hi16:
|
||||||
|
case ARM::fixup_t2_movt_hi16_pcrel:
|
||||||
|
Type = ELF::R_ARM_THM_MOVT_PREL;
|
||||||
|
break;
|
||||||
|
case ARM::fixup_t2_movw_lo16:
|
||||||
|
case ARM::fixup_t2_movw_lo16_pcrel:
|
||||||
|
Type = ELF::R_ARM_THM_MOVW_PREL_NC;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch ((unsigned)Fixup.getKind()) {
|
switch ((unsigned)Fixup.getKind()) {
|
||||||
@ -1555,6 +1563,12 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
|
|||||||
case ARM::fixup_arm_movw_lo16:
|
case ARM::fixup_arm_movw_lo16:
|
||||||
Type = ELF::R_ARM_MOVW_ABS_NC;
|
Type = ELF::R_ARM_MOVW_ABS_NC;
|
||||||
break;
|
break;
|
||||||
|
case ARM::fixup_t2_movt_hi16:
|
||||||
|
Type = ELF::R_ARM_THM_MOVT_ABS;
|
||||||
|
break;
|
||||||
|
case ARM::fixup_t2_movw_lo16:
|
||||||
|
Type = ELF::R_ARM_THM_MOVW_ABS_NC;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,10 +656,10 @@ public:
|
|||||||
const MCAsmLayout &Layout,
|
const MCAsmLayout &Layout,
|
||||||
const MCFragment *Fragment,
|
const MCFragment *Fragment,
|
||||||
const MCFixup &Fixup, MCValue Target,
|
const MCFixup &Fixup, MCValue Target,
|
||||||
|
unsigned Log2Size,
|
||||||
uint64_t &FixedValue) {
|
uint64_t &FixedValue) {
|
||||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||||
unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
|
unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
|
||||||
unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
|
|
||||||
unsigned Type = macho::RIT_Vanilla;
|
unsigned Type = macho::RIT_Vanilla;
|
||||||
|
|
||||||
// See <reloc.h>.
|
// See <reloc.h>.
|
||||||
@ -720,10 +720,10 @@ public:
|
|||||||
const MCAsmLayout &Layout,
|
const MCAsmLayout &Layout,
|
||||||
const MCFragment *Fragment,
|
const MCFragment *Fragment,
|
||||||
const MCFixup &Fixup, MCValue Target,
|
const MCFixup &Fixup, MCValue Target,
|
||||||
|
unsigned Log2Size,
|
||||||
uint64_t &FixedValue) {
|
uint64_t &FixedValue) {
|
||||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||||
unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
|
unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
|
||||||
unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
|
|
||||||
unsigned Type = macho::RIT_Vanilla;
|
unsigned Type = macho::RIT_Vanilla;
|
||||||
|
|
||||||
// See <reloc.h>.
|
// See <reloc.h>.
|
||||||
@ -775,6 +775,100 @@ public:
|
|||||||
Relocations[Fragment->getParent()].push_back(MRE);
|
Relocations[Fragment->getParent()].push_back(MRE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RecordARMMovwMovtRelocation(const MCAssembler &Asm,
|
||||||
|
const MCAsmLayout &Layout,
|
||||||
|
const MCFragment *Fragment,
|
||||||
|
const MCFixup &Fixup, MCValue Target,
|
||||||
|
uint64_t &FixedValue) {
|
||||||
|
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||||
|
unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
|
||||||
|
unsigned Type = macho::RIT_ARM_Half;
|
||||||
|
|
||||||
|
// See <reloc.h>.
|
||||||
|
const MCSymbol *A = &Target.getSymA()->getSymbol();
|
||||||
|
MCSymbolData *A_SD = &Asm.getSymbolData(*A);
|
||||||
|
|
||||||
|
if (!A_SD->getFragment())
|
||||||
|
report_fatal_error("symbol '" + A->getName() +
|
||||||
|
"' can not be undefined in a subtraction expression");
|
||||||
|
|
||||||
|
uint32_t Value = getSymbolAddress(A_SD, Layout);
|
||||||
|
uint32_t Value2 = 0;
|
||||||
|
uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent());
|
||||||
|
FixedValue += SecAddr;
|
||||||
|
|
||||||
|
if (const MCSymbolRefExpr *B = Target.getSymB()) {
|
||||||
|
MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
|
||||||
|
|
||||||
|
if (!B_SD->getFragment())
|
||||||
|
report_fatal_error("symbol '" + B->getSymbol().getName() +
|
||||||
|
"' can not be undefined in a subtraction expression");
|
||||||
|
|
||||||
|
// Select the appropriate difference relocation type.
|
||||||
|
Type = macho::RIT_ARM_HalfDifference;
|
||||||
|
Value2 = getSymbolAddress(B_SD, Layout);
|
||||||
|
FixedValue -= getSectionAddress(B_SD->getFragment()->getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relocations are written out in reverse order, so the PAIR comes first.
|
||||||
|
// ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
|
||||||
|
//
|
||||||
|
// For these two r_type relocations they always have a pair following them
|
||||||
|
// and the r_length bits are used differently. The encoding of the
|
||||||
|
// r_length is as follows:
|
||||||
|
// low bit of r_length:
|
||||||
|
// 0 - :lower16: for movw instructions
|
||||||
|
// 1 - :upper16: for movt instructions
|
||||||
|
// high bit of r_length:
|
||||||
|
// 0 - arm instructions
|
||||||
|
// 1 - thumb instructions
|
||||||
|
// the other half of the relocated expression is in the following pair
|
||||||
|
// relocation entry in the the low 16 bits of r_address field.
|
||||||
|
unsigned ThumbBit = 0;
|
||||||
|
unsigned MovtBit = 0;
|
||||||
|
switch (Fixup.getKind()) {
|
||||||
|
default: break;
|
||||||
|
case ARM::fixup_arm_movt_hi16:
|
||||||
|
case ARM::fixup_arm_movt_hi16_pcrel:
|
||||||
|
MovtBit = 1;
|
||||||
|
break;
|
||||||
|
case ARM::fixup_t2_movt_hi16:
|
||||||
|
case ARM::fixup_t2_movt_hi16_pcrel:
|
||||||
|
MovtBit = 1;
|
||||||
|
// Fallthrough
|
||||||
|
case ARM::fixup_t2_movw_lo16:
|
||||||
|
case ARM::fixup_t2_movw_lo16_pcrel:
|
||||||
|
ThumbBit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (Type == macho::RIT_ARM_HalfDifference) {
|
||||||
|
uint32_t OtherHalf = MovtBit
|
||||||
|
? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);
|
||||||
|
|
||||||
|
macho::RelocationEntry MRE;
|
||||||
|
MRE.Word0 = ((OtherHalf << 0) |
|
||||||
|
(macho::RIT_Pair << 24) |
|
||||||
|
(MovtBit << 28) |
|
||||||
|
(ThumbBit << 29) |
|
||||||
|
(IsPCRel << 30) |
|
||||||
|
macho::RF_Scattered);
|
||||||
|
MRE.Word1 = Value2;
|
||||||
|
Relocations[Fragment->getParent()].push_back(MRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
macho::RelocationEntry MRE;
|
||||||
|
MRE.Word0 = ((FixupOffset << 0) |
|
||||||
|
(Type << 24) |
|
||||||
|
(MovtBit << 28) |
|
||||||
|
(ThumbBit << 29) |
|
||||||
|
(IsPCRel << 30) |
|
||||||
|
macho::RF_Scattered);
|
||||||
|
MRE.Word1 = Value;
|
||||||
|
Relocations[Fragment->getParent()].push_back(MRE);
|
||||||
|
}
|
||||||
|
|
||||||
void RecordTLVPRelocation(const MCAssembler &Asm,
|
void RecordTLVPRelocation(const MCAssembler &Asm,
|
||||||
const MCAsmLayout &Layout,
|
const MCAsmLayout &Layout,
|
||||||
const MCFragment *Fragment,
|
const MCFragment *Fragment,
|
||||||
@ -868,6 +962,24 @@ public:
|
|||||||
// Report as 'long', even though that is not quite accurate.
|
// Report as 'long', even though that is not quite accurate.
|
||||||
Log2Size = llvm::Log2_32(4);
|
Log2Size = llvm::Log2_32(4);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case ARM::fixup_arm_movt_hi16:
|
||||||
|
case ARM::fixup_arm_movt_hi16_pcrel:
|
||||||
|
case ARM::fixup_t2_movt_hi16:
|
||||||
|
case ARM::fixup_t2_movt_hi16_pcrel:
|
||||||
|
RelocType = unsigned(macho::RIT_ARM_HalfDifference);
|
||||||
|
// Report as 'long', even though that is not quite accurate.
|
||||||
|
Log2Size = llvm::Log2_32(4);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ARM::fixup_arm_movw_lo16:
|
||||||
|
case ARM::fixup_arm_movw_lo16_pcrel:
|
||||||
|
case ARM::fixup_t2_movw_lo16:
|
||||||
|
case ARM::fixup_t2_movw_lo16_pcrel:
|
||||||
|
RelocType = unsigned(macho::RIT_ARM_Half);
|
||||||
|
// Report as 'long', even though that is not quite accurate.
|
||||||
|
Log2Size = llvm::Log2_32(4);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||||
@ -884,9 +996,14 @@ public:
|
|||||||
// If this is a difference or a defined symbol plus an offset, then we need
|
// If this is a difference or a defined symbol plus an offset, then we need
|
||||||
// a scattered relocation entry. Differences always require scattered
|
// a scattered relocation entry. Differences always require scattered
|
||||||
// relocations.
|
// relocations.
|
||||||
if (Target.getSymB())
|
if (Target.getSymB()) {
|
||||||
return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup,
|
if (RelocType == macho::RIT_ARM_Half ||
|
||||||
Target, FixedValue);
|
RelocType == macho::RIT_ARM_HalfDifference)
|
||||||
|
return RecordARMMovwMovtRelocation(Asm, Layout, Fragment, Fixup,
|
||||||
|
Target, FixedValue);
|
||||||
|
return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup,
|
||||||
|
Target, Log2Size, FixedValue);
|
||||||
|
}
|
||||||
|
|
||||||
// Get the symbol data, if any.
|
// Get the symbol data, if any.
|
||||||
MCSymbolData *SD = 0;
|
MCSymbolData *SD = 0;
|
||||||
@ -902,8 +1019,8 @@ public:
|
|||||||
if (IsPCRel && RelocType == macho::RIT_Vanilla)
|
if (IsPCRel && RelocType == macho::RIT_Vanilla)
|
||||||
Offset += 1 << Log2Size;
|
Offset += 1 << Log2Size;
|
||||||
if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
|
if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
|
||||||
return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup,
|
return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup, Target,
|
||||||
Target, FixedValue);
|
Log2Size, FixedValue);
|
||||||
|
|
||||||
// See <reloc.h>.
|
// See <reloc.h>.
|
||||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||||
@ -986,7 +1103,7 @@ public:
|
|||||||
// Differences always require scattered relocations.
|
// Differences always require scattered relocations.
|
||||||
if (Target.getSymB())
|
if (Target.getSymB())
|
||||||
return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
|
return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
|
||||||
Target, FixedValue);
|
Target, Log2Size, FixedValue);
|
||||||
|
|
||||||
// Get the symbol data, if any.
|
// Get the symbol data, if any.
|
||||||
MCSymbolData *SD = 0;
|
MCSymbolData *SD = 0;
|
||||||
@ -1000,7 +1117,7 @@ public:
|
|||||||
Offset += 1 << Log2Size;
|
Offset += 1 << Log2Size;
|
||||||
if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
|
if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
|
||||||
return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
|
return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
|
||||||
Target, FixedValue);
|
Target, Log2Size, FixedValue);
|
||||||
|
|
||||||
// See <reloc.h>.
|
// See <reloc.h>.
|
||||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||||
|
@ -76,10 +76,15 @@ public:
|
|||||||
{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_arm_thumb_cp", 1, 8, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_arm_thumb_cp", 1, 8, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_arm_thumb_bcc", 1, 8, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_arm_thumb_bcc", 1, 8, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_arm_movt_hi16", 0, 16, 0 },
|
// movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19.
|
||||||
{ "fixup_arm_movw_lo16", 0, 16, 0 },
|
{ "fixup_arm_movt_hi16", 0, 20, 0 },
|
||||||
{ "fixup_arm_movt_hi16_pcrel", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_arm_movw_lo16", 0, 20, 0 },
|
||||||
{ "fixup_arm_movw_lo16_pcrel", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_t2_movt_hi16", 0, 20, 0 },
|
||||||
|
{ "fixup_t2_movw_lo16", 0, 20, 0 },
|
||||||
|
{ "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
|
{ "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
|
{ "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
|
{ "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Kind < FirstTargetFixupKind)
|
if (Kind < FirstTargetFixupKind)
|
||||||
@ -158,8 +163,10 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
|||||||
case FK_Data_4:
|
case FK_Data_4:
|
||||||
return Value;
|
return Value;
|
||||||
case ARM::fixup_arm_movt_hi16:
|
case ARM::fixup_arm_movt_hi16:
|
||||||
case ARM::fixup_arm_movw_lo16:
|
|
||||||
case ARM::fixup_arm_movt_hi16_pcrel:
|
case ARM::fixup_arm_movt_hi16_pcrel:
|
||||||
|
Value >>= 16;
|
||||||
|
// Fallthrough
|
||||||
|
case ARM::fixup_arm_movw_lo16:
|
||||||
case ARM::fixup_arm_movw_lo16_pcrel: {
|
case ARM::fixup_arm_movw_lo16_pcrel: {
|
||||||
unsigned Hi4 = (Value & 0xF000) >> 12;
|
unsigned Hi4 = (Value & 0xF000) >> 12;
|
||||||
unsigned Lo12 = Value & 0x0FFF;
|
unsigned Lo12 = Value & 0x0FFF;
|
||||||
@ -168,6 +175,26 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
|||||||
Value = (Hi4 << 16) | (Lo12);
|
Value = (Hi4 << 16) | (Lo12);
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
case ARM::fixup_t2_movt_hi16:
|
||||||
|
case ARM::fixup_t2_movt_hi16_pcrel:
|
||||||
|
Value >>= 16;
|
||||||
|
// Fallthrough
|
||||||
|
case ARM::fixup_t2_movw_lo16:
|
||||||
|
case ARM::fixup_t2_movw_lo16_pcrel: {
|
||||||
|
unsigned Hi4 = (Value & 0xF000) >> 12;
|
||||||
|
unsigned i = (Value & 0x800) >> 11;
|
||||||
|
unsigned Mid3 = (Value & 0x700) >> 8;
|
||||||
|
unsigned Lo8 = Value & 0x0FF;
|
||||||
|
// inst{19-16} = Hi4;
|
||||||
|
// inst{26} = i;
|
||||||
|
// inst{14-12} = Mid3;
|
||||||
|
// inst{7-0} = Lo8;
|
||||||
|
Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
|
||||||
|
|
||||||
|
uint64_t swapped = (Value & 0xFFFF0000) >> 16;
|
||||||
|
swapped |= (Value & 0x0000FFFF) << 16;
|
||||||
|
return swapped;
|
||||||
|
}
|
||||||
case ARM::fixup_arm_ldst_pcrel_12:
|
case ARM::fixup_arm_ldst_pcrel_12:
|
||||||
// ARM PC-relative values are offset by 8.
|
// ARM PC-relative values are offset by 8.
|
||||||
Value -= 4;
|
Value -= 4;
|
||||||
@ -438,6 +465,14 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
|
|||||||
case ARM::fixup_t2_adr_pcrel_12:
|
case ARM::fixup_t2_adr_pcrel_12:
|
||||||
case ARM::fixup_arm_thumb_bl:
|
case ARM::fixup_arm_thumb_bl:
|
||||||
case ARM::fixup_arm_thumb_blx:
|
case ARM::fixup_arm_thumb_blx:
|
||||||
|
case ARM::fixup_arm_movt_hi16:
|
||||||
|
case ARM::fixup_arm_movw_lo16:
|
||||||
|
case ARM::fixup_arm_movt_hi16_pcrel:
|
||||||
|
case ARM::fixup_arm_movw_lo16_pcrel:
|
||||||
|
case ARM::fixup_t2_movt_hi16:
|
||||||
|
case ARM::fixup_t2_movw_lo16:
|
||||||
|
case ARM::fixup_t2_movt_hi16_pcrel:
|
||||||
|
case ARM::fixup_t2_movw_lo16_pcrel:
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,9 +70,10 @@ enum Fixups {
|
|||||||
|
|
||||||
// The next two are for the movt/movw pair
|
// The next two are for the movt/movw pair
|
||||||
// the 16bit imm field are split into imm{15-12} and imm{11-0}
|
// the 16bit imm field are split into imm{15-12} and imm{11-0}
|
||||||
// Fixme: We need new ones for Thumb.
|
|
||||||
fixup_arm_movt_hi16, // :upper16:
|
fixup_arm_movt_hi16, // :upper16:
|
||||||
fixup_arm_movw_lo16, // :lower16:
|
fixup_arm_movw_lo16, // :lower16:
|
||||||
|
fixup_t2_movt_hi16, // :upper16:
|
||||||
|
fixup_t2_movw_lo16, // :lower16:
|
||||||
|
|
||||||
// It is possible to create an "immediate" that happens to be pcrel.
|
// It is possible to create an "immediate" that happens to be pcrel.
|
||||||
// movw r0, :lower16:Foo-(Bar+8) and movt r0, :upper16:Foo-(Bar+8)
|
// movw r0, :lower16:Foo-(Bar+8) and movt r0, :upper16:Foo-(Bar+8)
|
||||||
@ -80,6 +81,8 @@ enum Fixups {
|
|||||||
// Needed to support ELF::R_ARM_MOVT_PREL and ELF::R_ARM_MOVW_PREL_NC
|
// Needed to support ELF::R_ARM_MOVT_PREL and ELF::R_ARM_MOVW_PREL_NC
|
||||||
fixup_arm_movt_hi16_pcrel, // :upper16:
|
fixup_arm_movt_hi16_pcrel, // :upper16:
|
||||||
fixup_arm_movw_lo16_pcrel, // :lower16:
|
fixup_arm_movw_lo16_pcrel, // :lower16:
|
||||||
|
fixup_t2_movt_hi16_pcrel, // :upper16:
|
||||||
|
fixup_t2_movw_lo16_pcrel, // :lower16:
|
||||||
|
|
||||||
// Marker
|
// Marker
|
||||||
LastTargetFixupKind,
|
LastTargetFixupKind,
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "ARMFixupKinds.h"
|
#include "ARMFixupKinds.h"
|
||||||
#include "ARMInstrInfo.h"
|
#include "ARMInstrInfo.h"
|
||||||
#include "ARMMCExpr.h"
|
#include "ARMMCExpr.h"
|
||||||
|
#include "ARMSubtarget.h"
|
||||||
#include "llvm/MC/MCCodeEmitter.h"
|
#include "llvm/MC/MCCodeEmitter.h"
|
||||||
#include "llvm/MC/MCExpr.h"
|
#include "llvm/MC/MCExpr.h"
|
||||||
#include "llvm/MC/MCInst.h"
|
#include "llvm/MC/MCInst.h"
|
||||||
@ -33,11 +34,13 @@ class ARMMCCodeEmitter : public MCCodeEmitter {
|
|||||||
void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
|
void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
|
||||||
const TargetMachine &TM;
|
const TargetMachine &TM;
|
||||||
const TargetInstrInfo &TII;
|
const TargetInstrInfo &TII;
|
||||||
|
const ARMSubtarget *Subtarget;
|
||||||
MCContext &Ctx;
|
MCContext &Ctx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ARMMCCodeEmitter(TargetMachine &tm, MCContext &ctx)
|
ARMMCCodeEmitter(TargetMachine &tm, MCContext &ctx)
|
||||||
: TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) {
|
: TM(tm), TII(*TM.getInstrInfo()),
|
||||||
|
Subtarget(&TM.getSubtarget<ARMSubtarget>()), Ctx(ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
~ARMMCCodeEmitter() {}
|
~ARMMCCodeEmitter() {}
|
||||||
@ -306,8 +309,7 @@ MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &, TargetMachine &TM,
|
|||||||
/// Thumb2 mode.
|
/// Thumb2 mode.
|
||||||
unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
|
unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
|
||||||
unsigned EncodedValue) const {
|
unsigned EncodedValue) const {
|
||||||
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
|
if (Subtarget->isThumb2()) {
|
||||||
if (Subtarget.isThumb2()) {
|
|
||||||
// NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved
|
// NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved
|
||||||
// to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are
|
// to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are
|
||||||
// set to 1111.
|
// set to 1111.
|
||||||
@ -326,8 +328,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
|
|||||||
/// Thumb2 mode.
|
/// Thumb2 mode.
|
||||||
unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
|
unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
|
||||||
unsigned EncodedValue) const {
|
unsigned EncodedValue) const {
|
||||||
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
|
if (Subtarget->isThumb2()) {
|
||||||
if (Subtarget.isThumb2()) {
|
|
||||||
EncodedValue &= 0xF0FFFFFF;
|
EncodedValue &= 0xF0FFFFFF;
|
||||||
EncodedValue |= 0x09000000;
|
EncodedValue |= 0x09000000;
|
||||||
}
|
}
|
||||||
@ -340,8 +341,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
|
|||||||
/// Thumb2 mode.
|
/// Thumb2 mode.
|
||||||
unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
|
unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
|
||||||
unsigned EncodedValue) const {
|
unsigned EncodedValue) const {
|
||||||
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
|
if (Subtarget->isThumb2()) {
|
||||||
if (Subtarget.isThumb2()) {
|
|
||||||
EncodedValue &= 0x00FFFFFF;
|
EncodedValue &= 0x00FFFFFF;
|
||||||
EncodedValue |= 0xEE000000;
|
EncodedValue |= 0xEE000000;
|
||||||
}
|
}
|
||||||
@ -353,7 +353,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
|
|||||||
/// them to their Thumb2 form if we are currently in Thumb2 mode.
|
/// them to their Thumb2 form if we are currently in Thumb2 mode.
|
||||||
unsigned ARMMCCodeEmitter::
|
unsigned ARMMCCodeEmitter::
|
||||||
VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const {
|
VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const {
|
||||||
if (TM.getSubtarget<ARMSubtarget>().isThumb2()) {
|
if (Subtarget->isThumb2()) {
|
||||||
EncodedValue &= 0x0FFFFFFF;
|
EncodedValue &= 0x0FFFFFFF;
|
||||||
EncodedValue |= 0xE0000000;
|
EncodedValue |= 0xE0000000;
|
||||||
}
|
}
|
||||||
@ -477,8 +477,7 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
|
|||||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||||
// FIXME: This really, really shouldn't use TargetMachine. We don't want
|
// FIXME: This really, really shouldn't use TargetMachine. We don't want
|
||||||
// coupling between MC and TM anywhere we can help it.
|
// coupling between MC and TM anywhere we can help it.
|
||||||
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
|
if (Subtarget->isThumb2())
|
||||||
if (Subtarget.isThumb2())
|
|
||||||
return
|
return
|
||||||
::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups);
|
::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups);
|
||||||
return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_branch, Fixups);
|
return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_branch, Fixups);
|
||||||
@ -575,9 +574,8 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
|
|||||||
else
|
else
|
||||||
Expr = MO2.getExpr();
|
Expr = MO2.getExpr();
|
||||||
|
|
||||||
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
|
|
||||||
MCFixupKind Kind;
|
MCFixupKind Kind;
|
||||||
if (Subtarget.isThumb2())
|
if (Subtarget->isThumb2())
|
||||||
Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12);
|
Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12);
|
||||||
else
|
else
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12);
|
Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12);
|
||||||
@ -662,14 +660,24 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
|
|||||||
switch (ARM16Expr->getKind()) {
|
switch (ARM16Expr->getKind()) {
|
||||||
default: assert(0 && "Unsupported ARMFixup");
|
default: assert(0 && "Unsupported ARMFixup");
|
||||||
case ARMMCExpr::VK_ARM_HI16:
|
case ARMMCExpr::VK_ARM_HI16:
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_movt_hi16);
|
if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E))
|
||||||
if (EvaluateAsPCRel(E))
|
Kind = MCFixupKind(Subtarget->isThumb2()
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_movt_hi16_pcrel);
|
? ARM::fixup_t2_movt_hi16_pcrel
|
||||||
|
: ARM::fixup_arm_movt_hi16_pcrel);
|
||||||
|
else
|
||||||
|
Kind = MCFixupKind(Subtarget->isThumb2()
|
||||||
|
? ARM::fixup_t2_movt_hi16
|
||||||
|
: ARM::fixup_arm_movt_hi16);
|
||||||
break;
|
break;
|
||||||
case ARMMCExpr::VK_ARM_LO16:
|
case ARMMCExpr::VK_ARM_LO16:
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_movw_lo16);
|
if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E))
|
||||||
if (EvaluateAsPCRel(E))
|
Kind = MCFixupKind(Subtarget->isThumb2()
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_movw_lo16_pcrel);
|
? ARM::fixup_t2_movw_lo16_pcrel
|
||||||
|
: ARM::fixup_arm_movw_lo16_pcrel);
|
||||||
|
else
|
||||||
|
Kind = MCFixupKind(Subtarget->isThumb2()
|
||||||
|
? ARM::fixup_t2_movw_lo16
|
||||||
|
: ARM::fixup_arm_movw_lo16);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Fixups.push_back(MCFixup::Create(0, E, Kind));
|
Fixups.push_back(MCFixup::Create(0, E, Kind));
|
||||||
@ -841,8 +849,7 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
|
|||||||
assert(MO.isExpr() && "Unexpected machine operand type!");
|
assert(MO.isExpr() && "Unexpected machine operand type!");
|
||||||
const MCExpr *Expr = MO.getExpr();
|
const MCExpr *Expr = MO.getExpr();
|
||||||
MCFixupKind Kind;
|
MCFixupKind Kind;
|
||||||
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
|
if (Subtarget->isThumb2())
|
||||||
if (Subtarget.isThumb2())
|
|
||||||
Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
|
Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
|
||||||
else
|
else
|
||||||
Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
|
Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
|
||||||
@ -1151,7 +1158,6 @@ getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
|
|||||||
void ARMMCCodeEmitter::
|
void ARMMCCodeEmitter::
|
||||||
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||||
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
|
|
||||||
// Pseudo instructions don't get encoded.
|
// Pseudo instructions don't get encoded.
|
||||||
const TargetInstrDesc &Desc = TII.get(MI.getOpcode());
|
const TargetInstrDesc &Desc = TII.get(MI.getOpcode());
|
||||||
uint64_t TSFlags = Desc.TSFlags;
|
uint64_t TSFlags = Desc.TSFlags;
|
||||||
@ -1167,7 +1173,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|||||||
uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
|
uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
|
||||||
// Thumb 32-bit wide instructions need to emit the high order halfword
|
// Thumb 32-bit wide instructions need to emit the high order halfword
|
||||||
// first.
|
// first.
|
||||||
if (Subtarget.isThumb() && Size == 4) {
|
if (Subtarget->isThumb() && Size == 4) {
|
||||||
EmitConstant(Binary >> 16, 2, OS);
|
EmitConstant(Binary >> 16, 2, OS);
|
||||||
EmitConstant(Binary & 0xffff, 2, OS);
|
EmitConstant(Binary & 0xffff, 2, OS);
|
||||||
} else
|
} else
|
||||||
|
@ -25,7 +25,7 @@ barf: @ @barf
|
|||||||
@ OBJ-NEXT: 'sh_info', 0x00000000
|
@ OBJ-NEXT: 'sh_info', 0x00000000
|
||||||
@ OBJ-NEXT: 'sh_addralign', 0x00000004
|
@ OBJ-NEXT: 'sh_addralign', 0x00000004
|
||||||
@ OBJ-NEXT: 'sh_entsize', 0x00000000
|
@ OBJ-NEXT: 'sh_entsize', 0x00000000
|
||||||
@ OBJ-NEXT: '_section_data', 'f00f0fe3 ec0f4fe3'
|
@ OBJ-NEXT: '_section_data', 'f00f0fe3 ff0f4fe3'
|
||||||
|
|
||||||
@ OBJ: Relocation 0x00000000
|
@ OBJ: Relocation 0x00000000
|
||||||
@ OBJ-NEXT: 'r_offset', 0x00000000
|
@ OBJ-NEXT: 'r_offset', 0x00000000
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
@ RUN: llvm-mc %s -triple armv7-apple-darwin -show-encoding | FileCheck %s
|
@ RUN: llvm-mc %s -triple armv7-apple-darwin | FileCheck %s
|
||||||
|
@ RUN: llvm-mc %s -triple armv7-apple-darwin | FileCheck %s
|
||||||
|
|
||||||
_t:
|
_t:
|
||||||
movw r0, :lower16:(L_foo$non_lazy_ptr - (L1 + 8))
|
movw r0, :lower16:(L_foo$non_lazy_ptr - (L1 + 8))
|
||||||
movt r0, :upper16:(L_foo$non_lazy_ptr - (L1 + 8))
|
movt r0, :upper16:(L_foo$non_lazy_ptr - (L1 + 8))
|
||||||
L1:
|
L1:
|
||||||
|
|
||||||
@ CHECK: movw r0, :lower16:(L_foo$non_lazy_ptr-(L1+8)) @ encoding: [A,A,0x00,0xe3]
|
@ CHECK: movw r0, :lower16:(L_foo$non_lazy_ptr-(L1+8))
|
||||||
@ CHECK: @ fixup A - offset: 0, value: L_foo$non_lazy_ptr-(L1+8), kind: fixup_arm_movw_lo16_pcrel
|
@ CHECK: movt r0, :upper16:(L_foo$non_lazy_ptr-(L1+8))
|
||||||
@ CHECK: movt r0, :upper16:(L_foo$non_lazy_ptr-(L1+8)) @ encoding: [A,A,0x40,0xe3]
|
|
||||||
@ CHECK: @ fixup A - offset: 0, value: L_foo$non_lazy_ptr-(L1+8), kind: fixup_arm_movt_hi16_pcrel
|
|
||||||
|
|
||||||
.comm _foo,4,2
|
.comm _foo,4,2
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user