[SPARC][MC] Support more relocation types
This patch introduces support for %hix, %lox, %gdop_hix22, %gdop_lox10 and %gdop. An extra test is introduced to make sure the fixups are correctly applied. Reviewed By: dcederman Differential Revision: https://reviews.llvm.org/D102575
This commit is contained in:
@@ -55,6 +55,8 @@ class SparcOperand;
|
||||
class SparcAsmParser : public MCTargetAsmParser {
|
||||
MCAsmParser &Parser;
|
||||
|
||||
enum class TailRelocKind { Load_GOT, Add_TLS, Load_TLS, Call_TLS };
|
||||
|
||||
/// @name Auto-generated Match Functions
|
||||
/// {
|
||||
|
||||
@@ -83,6 +85,9 @@ class SparcAsmParser : public MCTargetAsmParser {
|
||||
|
||||
OperandMatchResultTy parseMembarTag(OperandVector &Operands);
|
||||
|
||||
template <TailRelocKind Kind>
|
||||
OperandMatchResultTy parseTailRelocSym(OperandVector &Operands);
|
||||
|
||||
template <unsigned N>
|
||||
OperandMatchResultTy parseShiftAmtImm(OperandVector &Operands);
|
||||
|
||||
@@ -113,6 +118,8 @@ class SparcAsmParser : public MCTargetAsmParser {
|
||||
bool expandSET(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions);
|
||||
|
||||
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
|
||||
|
||||
public:
|
||||
SparcAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
|
||||
const MCInstrInfo &MII,
|
||||
@@ -267,6 +274,7 @@ public:
|
||||
bool isMEMrr() const { return Kind == k_MemoryReg; }
|
||||
bool isMEMri() const { return Kind == k_MemoryImm; }
|
||||
bool isMembarTag() const { return Kind == k_Immediate; }
|
||||
bool isTailRelocSym() const { return Kind == k_Immediate; }
|
||||
|
||||
bool isCallTarget() const {
|
||||
if (!isImm())
|
||||
@@ -427,6 +435,11 @@ public:
|
||||
addExpr(Inst, getImm());
|
||||
}
|
||||
|
||||
void addTailRelocSymOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
addExpr(Inst, getImm());
|
||||
}
|
||||
|
||||
static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
|
||||
auto Op = std::make_unique<SparcOperand>(k_Token);
|
||||
Op->Tok.Data = Str.data();
|
||||
@@ -850,6 +863,98 @@ OperandMatchResultTy SparcAsmParser::parseShiftAmtImm(OperandVector &Operands) {
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
template <SparcAsmParser::TailRelocKind Kind>
|
||||
OperandMatchResultTy
|
||||
SparcAsmParser::parseTailRelocSym(OperandVector &Operands) {
|
||||
SMLoc S = getLoc();
|
||||
SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
|
||||
|
||||
auto MatchesKind = [](SparcMCExpr::VariantKind VK) -> bool {
|
||||
switch (Kind) {
|
||||
case TailRelocKind::Load_GOT:
|
||||
// Non-TLS relocations on ld (or ldx).
|
||||
// ld [%rr + %rr], %rr, %rel(sym)
|
||||
return VK == SparcMCExpr::VK_Sparc_GOTDATA_OP;
|
||||
case TailRelocKind::Add_TLS:
|
||||
// TLS relocations on add.
|
||||
// add %rr, %rr, %rr, %rel(sym)
|
||||
switch (VK) {
|
||||
case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
|
||||
case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
|
||||
case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
|
||||
case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case TailRelocKind::Load_TLS:
|
||||
// TLS relocations on ld (or ldx).
|
||||
// ld[x] %addr, %rr, %rel(sym)
|
||||
switch (VK) {
|
||||
case SparcMCExpr::VK_Sparc_TLS_IE_LD:
|
||||
case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case TailRelocKind::Call_TLS:
|
||||
// TLS relocations on call.
|
||||
// call sym, %rel(sym)
|
||||
switch (VK) {
|
||||
case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
|
||||
case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
llvm_unreachable("Unexpected kind parameter");
|
||||
}
|
||||
};
|
||||
|
||||
if (getLexer().getKind() != AsmToken::Percent) {
|
||||
Error(getLoc(), "expected '%' for operand modifier");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
const AsmToken Tok = Parser.getTok();
|
||||
getParser().Lex(); // Eat '%'
|
||||
|
||||
if (getLexer().getKind() != AsmToken::Identifier) {
|
||||
Error(getLoc(), "expected valid identifier for operand modifier");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
StringRef Name = getParser().getTok().getIdentifier();
|
||||
SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(Name);
|
||||
if (VK == SparcMCExpr::VK_Sparc_None) {
|
||||
Error(getLoc(), "invalid operand modifier");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
if (!MatchesKind(VK)) {
|
||||
// Did not match the specified set of relocation types, put '%' back.
|
||||
getLexer().UnLex(Tok);
|
||||
return MatchOperand_NoMatch;
|
||||
}
|
||||
|
||||
Parser.Lex(); // Eat the identifier.
|
||||
if (getLexer().getKind() != AsmToken::LParen) {
|
||||
Error(getLoc(), "expected '('");
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
getParser().Lex(); // Eat '('
|
||||
const MCExpr *SubExpr;
|
||||
if (getParser().parseParenExpression(SubExpr, E)) {
|
||||
return MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
const MCExpr *Val = adjustPICRelocation(VK, SubExpr);
|
||||
Operands.push_back(SparcOperand::CreateImm(Val, S, E));
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) {
|
||||
SMLoc S = Parser.getTok().getLoc();
|
||||
const MCExpr *EVal;
|
||||
@@ -1409,10 +1514,27 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
|
||||
StringRef name = Tok.getString();
|
||||
|
||||
SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name);
|
||||
|
||||
if (VK == SparcMCExpr::VK_Sparc_None)
|
||||
switch (VK) {
|
||||
case SparcMCExpr::VK_Sparc_None:
|
||||
Error(getLoc(), "invalid operand modifier");
|
||||
return false;
|
||||
|
||||
case SparcMCExpr::VK_Sparc_GOTDATA_OP:
|
||||
case SparcMCExpr::VK_Sparc_TLS_GD_ADD:
|
||||
case SparcMCExpr::VK_Sparc_TLS_GD_CALL:
|
||||
case SparcMCExpr::VK_Sparc_TLS_IE_ADD:
|
||||
case SparcMCExpr::VK_Sparc_TLS_IE_LD:
|
||||
case SparcMCExpr::VK_Sparc_TLS_IE_LDX:
|
||||
case SparcMCExpr::VK_Sparc_TLS_LDM_ADD:
|
||||
case SparcMCExpr::VK_Sparc_TLS_LDM_CALL:
|
||||
case SparcMCExpr::VK_Sparc_TLS_LDO_ADD:
|
||||
// These are special-cased at tablegen level.
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Parser.Lex(); // Eat the identifier.
|
||||
if (Parser.getTok().getKind() != AsmToken::LParen)
|
||||
return false;
|
||||
|
||||
@@ -47,6 +47,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
case Sparc::fixup_sparc_br16_14:
|
||||
return (Value >> 2) & 0x3fff;
|
||||
|
||||
case Sparc::fixup_sparc_hix22:
|
||||
return (~Value >> 10) & 0x3fffff;
|
||||
|
||||
case Sparc::fixup_sparc_pc22:
|
||||
case Sparc::fixup_sparc_got22:
|
||||
case Sparc::fixup_sparc_tls_gd_hi22:
|
||||
@@ -60,6 +63,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
case Sparc::fixup_sparc_13:
|
||||
return Value & 0x1fff;
|
||||
|
||||
case Sparc::fixup_sparc_lox10:
|
||||
return (Value & 0x3ff) | 0x1c00;
|
||||
|
||||
case Sparc::fixup_sparc_pc10:
|
||||
case Sparc::fixup_sparc_got10:
|
||||
case Sparc::fixup_sparc_tls_gd_lo10:
|
||||
@@ -98,6 +104,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
case Sparc::fixup_sparc_tls_ie_ld:
|
||||
case Sparc::fixup_sparc_tls_ie_ldx:
|
||||
case Sparc::fixup_sparc_tls_ie_add:
|
||||
case Sparc::fixup_sparc_gotdata_lox10:
|
||||
case Sparc::fixup_sparc_gotdata_hix22:
|
||||
case Sparc::fixup_sparc_gotdata_op:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -189,7 +198,12 @@ namespace {
|
||||
{ "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 }
|
||||
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 },
|
||||
{ "fixup_sparc_hix22", 10, 22, 0 },
|
||||
{ "fixup_sparc_lox10", 19, 13, 0 },
|
||||
{ "fixup_sparc_gotdata_hix22", 0, 0, 0 },
|
||||
{ "fixup_sparc_gotdata_lox10", 0, 0, 0 },
|
||||
{ "fixup_sparc_gotdata_op", 0, 0, 0 },
|
||||
};
|
||||
|
||||
const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
|
||||
@@ -231,7 +245,12 @@ namespace {
|
||||
{ "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 }
|
||||
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 },
|
||||
{ "fixup_sparc_hix22", 0, 22, 0 },
|
||||
{ "fixup_sparc_lox10", 0, 13, 0 },
|
||||
{ "fixup_sparc_gotdata_hix22", 0, 0, 0 },
|
||||
{ "fixup_sparc_gotdata_lox10", 0, 0, 0 },
|
||||
{ "fixup_sparc_gotdata_op", 0, 0, 0 },
|
||||
};
|
||||
|
||||
// Fixup kinds from .reloc directive are like R_SPARC_NONE. They do
|
||||
|
||||
@@ -112,6 +112,11 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx,
|
||||
case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD;
|
||||
case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22;
|
||||
case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10;
|
||||
case Sparc::fixup_sparc_hix22: return ELF::R_SPARC_HIX22;
|
||||
case Sparc::fixup_sparc_lox10: return ELF::R_SPARC_LOX10;
|
||||
case Sparc::fixup_sparc_gotdata_hix22: return ELF::R_SPARC_GOTDATA_HIX22;
|
||||
case Sparc::fixup_sparc_gotdata_lox10: return ELF::R_SPARC_GOTDATA_LOX10;
|
||||
case Sparc::fixup_sparc_gotdata_op: return ELF::R_SPARC_GOTDATA_OP;
|
||||
}
|
||||
|
||||
return ELF::R_SPARC_NONE;
|
||||
|
||||
@@ -95,6 +95,18 @@ namespace llvm {
|
||||
fixup_sparc_tls_le_hix22,
|
||||
fixup_sparc_tls_le_lox10,
|
||||
|
||||
/// 22-bit fixup corresponding to %hix(foo)
|
||||
fixup_sparc_hix22,
|
||||
/// 13-bit fixup corresponding to %lox(foo)
|
||||
fixup_sparc_lox10,
|
||||
|
||||
/// 22-bit fixup corresponding to %gdop_hix22(foo)
|
||||
fixup_sparc_gotdata_hix22,
|
||||
/// 13-bit fixup corresponding to %gdop_lox10(foo)
|
||||
fixup_sparc_gotdata_lox10,
|
||||
/// 32-bit fixup corresponding to %gdop(foo)
|
||||
fixup_sparc_gotdata_op,
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
|
||||
@@ -104,17 +104,21 @@ void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
support::endian::write(OS, Bits,
|
||||
Ctx.getAsmInfo()->isLittleEndian() ? support::little
|
||||
: support::big);
|
||||
unsigned tlsOpNo = 0;
|
||||
|
||||
// Some instructions have phantom operands that only contribute a fixup entry.
|
||||
unsigned SymOpNo = 0;
|
||||
switch (MI.getOpcode()) {
|
||||
default: break;
|
||||
case SP::TLS_CALL: tlsOpNo = 1; break;
|
||||
case SP::TLS_CALL: SymOpNo = 1; break;
|
||||
case SP::GDOP_LDrr:
|
||||
case SP::GDOP_LDXrr:
|
||||
case SP::TLS_ADDrr:
|
||||
case SP::TLS_ADDXrr:
|
||||
case SP::TLS_LDrr:
|
||||
case SP::TLS_LDXrr: tlsOpNo = 3; break;
|
||||
case SP::TLS_LDXrr: SymOpNo = 3; break;
|
||||
}
|
||||
if (tlsOpNo != 0) {
|
||||
const MCOperand &MO = MI.getOperand(tlsOpNo);
|
||||
if (SymOpNo != 0) {
|
||||
const MCOperand &MO = MI.getOperand(SymOpNo);
|
||||
uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
|
||||
assert(op == 0 && "Unexpected operand value!");
|
||||
(void)op; // suppress warning.
|
||||
|
||||
@@ -81,6 +81,11 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind)
|
||||
case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; return true;
|
||||
case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; return true;
|
||||
case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; return true;
|
||||
case VK_Sparc_HIX22: OS << "%hix("; return true;
|
||||
case VK_Sparc_LOX10: OS << "%lox("; return true;
|
||||
case VK_Sparc_GOTDATA_HIX22: OS << "%gdop_hix22("; return true;
|
||||
case VK_Sparc_GOTDATA_LOX10: OS << "%gdop_lox10("; return true;
|
||||
case VK_Sparc_GOTDATA_OP: OS << "%gdop("; return true;
|
||||
}
|
||||
llvm_unreachable("Unhandled SparcMCExpr::VariantKind");
|
||||
}
|
||||
@@ -120,6 +125,11 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name)
|
||||
.Case("tie_add", VK_Sparc_TLS_IE_ADD)
|
||||
.Case("tle_hix22", VK_Sparc_TLS_LE_HIX22)
|
||||
.Case("tle_lox10", VK_Sparc_TLS_LE_LOX10)
|
||||
.Case("hix", VK_Sparc_HIX22)
|
||||
.Case("lox", VK_Sparc_LOX10)
|
||||
.Case("gdop_hix22", VK_Sparc_GOTDATA_HIX22)
|
||||
.Case("gdop_lox10", VK_Sparc_GOTDATA_LOX10)
|
||||
.Case("gdop", VK_Sparc_GOTDATA_OP)
|
||||
.Default(VK_Sparc_None);
|
||||
}
|
||||
|
||||
@@ -160,6 +170,11 @@ Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) {
|
||||
case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add;
|
||||
case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22;
|
||||
case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10;
|
||||
case VK_Sparc_HIX22: return Sparc::fixup_sparc_hix22;
|
||||
case VK_Sparc_LOX10: return Sparc::fixup_sparc_lox10;
|
||||
case VK_Sparc_GOTDATA_HIX22: return Sparc::fixup_sparc_gotdata_hix22;
|
||||
case VK_Sparc_GOTDATA_LOX10: return Sparc::fixup_sparc_gotdata_lox10;
|
||||
case VK_Sparc_GOTDATA_OP: return Sparc::fixup_sparc_gotdata_op;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,12 @@ public:
|
||||
VK_Sparc_TLS_IE_LDX,
|
||||
VK_Sparc_TLS_IE_ADD,
|
||||
VK_Sparc_TLS_LE_HIX22,
|
||||
VK_Sparc_TLS_LE_LOX10
|
||||
VK_Sparc_TLS_LE_LOX10,
|
||||
VK_Sparc_HIX22,
|
||||
VK_Sparc_LOX10,
|
||||
VK_Sparc_GOTDATA_HIX22,
|
||||
VK_Sparc_GOTDATA_LOX10,
|
||||
VK_Sparc_GOTDATA_OP,
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@@ -1900,6 +1900,7 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case SPISD::TLS_LD: return "SPISD::TLS_LD";
|
||||
case SPISD::TLS_CALL: return "SPISD::TLS_CALL";
|
||||
case SPISD::TAIL_CALL: return "SPISD::TAIL_CALL";
|
||||
case SPISD::LOAD_GDOP: return "SPISD::LOAD_GDOP";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,9 @@ namespace llvm {
|
||||
|
||||
TLS_ADD, // For Thread Local Storage (TLS).
|
||||
TLS_LD,
|
||||
TLS_CALL
|
||||
TLS_CALL,
|
||||
|
||||
LOAD_GDOP, // Load operation w/ gdop relocation.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>;
|
||||
defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>;
|
||||
|
||||
def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd),
|
||||
(ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym),
|
||||
(ins I64Regs:$rs1, I64Regs:$rs2, TailRelocSymTLSAdd:$sym),
|
||||
"add $rs1, $rs2, $rd, $sym",
|
||||
[(set i64:$rd,
|
||||
(tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>;
|
||||
@@ -238,12 +238,20 @@ let Predicates = [Is64Bit] in {
|
||||
let DecoderMethod = "DecodeLoadInt" in
|
||||
defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>;
|
||||
|
||||
let mayLoad = 1, isAsmParserOnly = 1 in
|
||||
let mayLoad = 1, isAsmParserOnly = 1 in {
|
||||
def TLS_LDXrr : F3_1<3, 0b001011,
|
||||
(outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
|
||||
(outs IntRegs:$dst),
|
||||
(ins MEMrr:$addr, TailRelocSymTLSLoad:$sym),
|
||||
"ldx [$addr], $dst, $sym",
|
||||
[(set i64:$dst,
|
||||
(tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>;
|
||||
def GDOP_LDXrr : F3_1<3, 0b001011,
|
||||
(outs I64Regs:$dst),
|
||||
(ins MEMrr:$addr, TailRelocSymGOTLoad:$sym),
|
||||
"ldx [$addr], $dst, $sym",
|
||||
[(set i64:$dst,
|
||||
(load_gdop ADDRrr:$addr, tglobaladdr:$sym))]>;
|
||||
}
|
||||
|
||||
// Extending loads to i64.
|
||||
def : Pat<(i64 (zextloadi1 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>;
|
||||
|
||||
@@ -147,7 +147,29 @@ def MEMri : Operand<iPTR> {
|
||||
let ParserMatchClass = SparcMEMriAsmOperand;
|
||||
}
|
||||
|
||||
def TLSSym : Operand<iPTR>;
|
||||
// Represents a tail relocation operand for instructions such as add, ld, call.
|
||||
class SparcTailRelocSymAsmOperand<string Kind> : AsmOperandClass {
|
||||
let Name = "TailRelocSym" # Kind;
|
||||
let RenderMethod = "addTailRelocSymOperands";
|
||||
let PredicateMethod = "isTailRelocSym";
|
||||
let ParserMethod = "parseTailRelocSym<TailRelocKind::" # Kind # ">";
|
||||
}
|
||||
|
||||
def TailRelocSymGOTLoad : Operand<iPTR> {
|
||||
let ParserMatchClass = SparcTailRelocSymAsmOperand<"Load_GOT">;
|
||||
}
|
||||
|
||||
def TailRelocSymTLSAdd : Operand<iPTR> {
|
||||
let ParserMatchClass = SparcTailRelocSymAsmOperand<"Add_TLS">;
|
||||
}
|
||||
|
||||
def TailRelocSymTLSLoad : Operand<iPTR> {
|
||||
let ParserMatchClass = SparcTailRelocSymAsmOperand<"Load_TLS">;
|
||||
}
|
||||
|
||||
def TailRelocSymTLSCall : Operand<iPTR> {
|
||||
let ParserMatchClass = SparcTailRelocSymAsmOperand<"Call_TLS">;
|
||||
}
|
||||
|
||||
def SparcMembarTagAsmOperand : AsmOperandClass {
|
||||
let Name = "MembarTag";
|
||||
@@ -214,6 +236,9 @@ SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>;
|
||||
def SDTSPtlsld :
|
||||
SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
|
||||
|
||||
def SDTSPloadgdop :
|
||||
SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
|
||||
|
||||
def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>;
|
||||
def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>;
|
||||
def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
|
||||
@@ -265,6 +290,8 @@ def tlscall : SDNode<"SPISD::TLS_CALL", SDT_SPCall,
|
||||
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
|
||||
SDNPVariadic]>;
|
||||
|
||||
def load_gdop : SDNode<"SPISD::LOAD_GDOP", SDTSPloadgdop>;
|
||||
|
||||
def getPCX : Operand<iPTR> {
|
||||
let PrintMethod = "printGetPCX";
|
||||
}
|
||||
@@ -587,6 +614,15 @@ let DecoderMethod = "DecodeLoadFP" in
|
||||
}
|
||||
}
|
||||
|
||||
let mayLoad = 1, isAsmParserOnly = 1 in {
|
||||
def GDOP_LDrr : F3_1<3, 0b000000,
|
||||
(outs IntRegs:$dst),
|
||||
(ins MEMrr:$addr, TailRelocSymGOTLoad:$sym),
|
||||
"ld [$addr], $dst, $sym",
|
||||
[(set i32:$dst,
|
||||
(load_gdop ADDRrr:$addr, tglobaladdr:$sym))]>;
|
||||
}
|
||||
|
||||
// Section B.4 - Store Integer Instructions, p. 95
|
||||
let DecoderMethod = "DecodeStoreInt" in {
|
||||
defm STB : StoreA<"stb", 0b000101, 0b010101, truncstorei8, IntRegs, i32>;
|
||||
@@ -1369,21 +1405,24 @@ let Defs = [FCC0], rd = 0, isCodeGenOnly = 1 in {
|
||||
let isAsmParserOnly = 1 in {
|
||||
def TLS_ADDrr : F3_1<2, 0b000000,
|
||||
(outs IntRegs:$rd),
|
||||
(ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym),
|
||||
(ins IntRegs:$rs1, IntRegs:$rs2, TailRelocSymTLSAdd:$sym),
|
||||
"add $rs1, $rs2, $rd, $sym",
|
||||
[(set i32:$rd,
|
||||
(tlsadd i32:$rs1, i32:$rs2, tglobaltlsaddr:$sym))]>;
|
||||
|
||||
let mayLoad = 1 in
|
||||
let mayLoad = 1 in {
|
||||
def TLS_LDrr : F3_1<3, 0b000000,
|
||||
(outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
|
||||
(outs IntRegs:$dst),
|
||||
(ins MEMrr:$addr, TailRelocSymTLSLoad:$sym),
|
||||
"ld [$addr], $dst, $sym",
|
||||
[(set i32:$dst,
|
||||
(tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>;
|
||||
}
|
||||
|
||||
let Uses = [O6], isCall = 1, hasDelaySlot = 1 in
|
||||
def TLS_CALL : InstSP<(outs),
|
||||
(ins calltarget:$disp, TLSSym:$sym, variable_ops),
|
||||
(ins calltarget:$disp, TailRelocSymTLSCall:$sym,
|
||||
variable_ops),
|
||||
"call $disp, $sym",
|
||||
[(tlscall texternalsym:$disp, tglobaltlsaddr:$sym)],
|
||||
IIC_jmp_or_call> {
|
||||
|
||||
30
llvm/test/MC/Sparc/sparc-fixups.s
Normal file
30
llvm/test/MC/Sparc/sparc-fixups.s
Normal file
@@ -0,0 +1,30 @@
|
||||
! RUN: llvm-mc %s -arch=sparcv9 -filetype=obj | llvm-objdump -dr - | FileCheck %s
|
||||
.text
|
||||
|
||||
! Check that fixups are correctly applied.
|
||||
|
||||
.set sym, 0xfedcba98
|
||||
|
||||
! CHECK: sethi 4175662, %o0
|
||||
sethi %hi(sym), %o0
|
||||
! CHECK: xor %o0, 664, %o0
|
||||
xor %o0, %lo(sym), %o0
|
||||
|
||||
! CHECK: sethi 1019, %o0
|
||||
sethi %h44(sym), %o0
|
||||
! CHECK: or %o0, 459, %o0
|
||||
or %o0, %m44(sym), %o0
|
||||
! CHECK: ld [%o0+2712], %o0
|
||||
ld [%o0 + %l44(sym)], %o0
|
||||
|
||||
! CHECK: sethi 0, %o0
|
||||
sethi %hh(sym), %o0
|
||||
! CHECK: sethi 4175662, %o0
|
||||
sethi %lm(sym), %o0
|
||||
! CHECK: or %o0, 0, %o0
|
||||
or %o0, %hm(sym), %o0
|
||||
|
||||
! CHECK: sethi 18641, %o0
|
||||
sethi %hix(sym), %o0
|
||||
! CHECK: xor %o0, -360, %o0
|
||||
xor %o0, %lox(sym), %o0
|
||||
@@ -2,18 +2,24 @@
|
||||
! RUN: llvm-mc %s -arch=sparcv9 -filetype=obj | llvm-readobj -r - | FileCheck %s --check-prefix=CHECK-OBJ
|
||||
|
||||
! CHECK-OBJ: Format: elf64-sparc
|
||||
! CHECK-OBJ: Relocations [
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 foo
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_LO10 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HI22 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_H44 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_M44 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_L44 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HH22 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HM10 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_LM22 sym
|
||||
! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_13 sym
|
||||
! CHECK-ELF: ]
|
||||
! CHECK-OBJ: .rela.text {
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 foo
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_H44 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_M44 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_L44 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HH22 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HM10 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LM22 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_13 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_13 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HIX22 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LOX10 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOTDATA_HIX22 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOTDATA_LOX10 sym
|
||||
! CHECK-OBJ-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOTDATA_OP sym
|
||||
! CHECK-OBJ-NEXT: }
|
||||
|
||||
! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A]
|
||||
! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30
|
||||
@@ -59,6 +65,26 @@
|
||||
! CHECK-NEXT: ! fixup A - offset: 0, value: sym+4, kind: fixup_sparc_13
|
||||
or %g1, (sym+4), %g3
|
||||
|
||||
! CHECK: sethi %hix(sym), %g1 ! encoding: [0x03,0b00AAAAAA,A,A]
|
||||
! CHECK-NEXT: ! fixup A - offset: 0, value: %hix(sym), kind: fixup_sparc_hix22
|
||||
sethi %hix(sym), %g1
|
||||
|
||||
! CHECK: xor %g1, %lox(sym), %g1 ! encoding: [0x82,0x18,0b011AAAAA,A]
|
||||
! CHECK-NEXT: ! fixup A - offset: 0, value: %lox(sym), kind: fixup_sparc_lox10
|
||||
xor %g1, %lox(sym), %g1
|
||||
|
||||
! CHECK: sethi %gdop_hix22(sym), %l1 ! encoding: [0x23,0x00,0x00,0x00]
|
||||
! CHECK-NEXT: ! fixup A - offset: 0, value: %gdop_hix22(sym), kind: fixup_sparc_gotdata_hix22
|
||||
sethi %gdop_hix22(sym), %l1
|
||||
|
||||
! CHECK: or %l1, %gdop_lox10(sym), %l1 ! encoding: [0xa2,0x14,0x60,0x00]
|
||||
! CHECK-NEXT: ! fixup A - offset: 0, value: %gdop_lox10(sym), kind: fixup_sparc_gotdata_lox10
|
||||
or %l1, %gdop_lox10(sym), %l1
|
||||
|
||||
! CHECK: ldx [%l7+%l1], %l2, %gdop(sym) ! encoding: [0xe4,0x5d,0xc0,0x11]
|
||||
! CHECK-NEXT: ! fixup A - offset: 0, value: %gdop(sym), kind: fixup_sparc_gotdata_op
|
||||
ldx [%l7 + %l1], %l2, %gdop(sym)
|
||||
|
||||
! This test needs to placed last in the file
|
||||
! CHECK: .half a-.Ltmp0
|
||||
.half a - .
|
||||
|
||||
Reference in New Issue
Block a user