forked from OSchip/llvm-project
[RISCV] Support assembling TLS add and associated modifiers
This patch adds support in the MC layer for parsing and assembling the 4-operand add instruction needed for TLS addressing. This also involves parsing the %tprel_hi, %tprel_lo and %tprel_add operand modifiers. Differential Revision: https://reviews.llvm.org/D55341 llvm-svn: 357698
This commit is contained in:
parent
9f598ac706
commit
aa79a3fe8e
|
@ -295,6 +295,16 @@ public:
|
|||
VK == RISCVMCExpr::VK_RISCV_CALL_PLT);
|
||||
}
|
||||
|
||||
bool isTPRelAddSymbol() const {
|
||||
int64_t Imm;
|
||||
RISCVMCExpr::VariantKind VK;
|
||||
// Must be of 'immediate' type but not a constant.
|
||||
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
|
||||
return false;
|
||||
return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) &&
|
||||
VK == RISCVMCExpr::VK_RISCV_TPREL_ADD;
|
||||
}
|
||||
|
||||
bool isCSRSystemRegister() const { return isSystemRegister(); }
|
||||
|
||||
/// Return true if the operand is a valid for the fence instruction e.g.
|
||||
|
@ -489,7 +499,8 @@ public:
|
|||
IsValid = isInt<12>(Imm);
|
||||
return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
|
||||
VK == RISCVMCExpr::VK_RISCV_LO ||
|
||||
VK == RISCVMCExpr::VK_RISCV_PCREL_LO);
|
||||
VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
|
||||
VK == RISCVMCExpr::VK_RISCV_TPREL_LO);
|
||||
}
|
||||
|
||||
bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
|
||||
|
@ -515,10 +526,12 @@ public:
|
|||
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
|
||||
if (!IsConstantImm) {
|
||||
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
|
||||
return IsValid && VK == RISCVMCExpr::VK_RISCV_HI;
|
||||
return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
|
||||
VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
|
||||
} else {
|
||||
return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
|
||||
VK == RISCVMCExpr::VK_RISCV_HI);
|
||||
VK == RISCVMCExpr::VK_RISCV_HI ||
|
||||
VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -872,8 +885,8 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
|||
case Match_InvalidSImm12:
|
||||
return generateImmOutOfRangeError(
|
||||
Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
|
||||
"operand must be a symbol with %lo/%pcrel_lo modifier or an integer in "
|
||||
"the range");
|
||||
"operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
|
||||
"integer in the range");
|
||||
case Match_InvalidSImm12Lsb0:
|
||||
return generateImmOutOfRangeError(
|
||||
Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
|
||||
|
@ -884,8 +897,9 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
|||
"immediate must be a multiple of 2 bytes in the range");
|
||||
case Match_InvalidUImm20LUI:
|
||||
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
|
||||
"operand must be a symbol with %hi() "
|
||||
"modifier or an integer in the range");
|
||||
"operand must be a symbol with "
|
||||
"%hi/%tprel_hi modifier or an integer in "
|
||||
"the range");
|
||||
case Match_InvalidUImm20AUIPC:
|
||||
return generateImmOutOfRangeError(
|
||||
Operands, ErrorInfo, 0, (1 << 20) - 1,
|
||||
|
@ -920,6 +934,10 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
|||
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
|
||||
return Error(ErrorLoc, "operand must be a bare symbol name");
|
||||
}
|
||||
case Match_InvalidTPRelAddSymbol: {
|
||||
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
|
||||
return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("Unknown match type detected!");
|
||||
|
|
|
@ -187,12 +187,15 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
|
|||
return Value;
|
||||
case RISCV::fixup_riscv_lo12_i:
|
||||
case RISCV::fixup_riscv_pcrel_lo12_i:
|
||||
case RISCV::fixup_riscv_tprel_lo12_i:
|
||||
return Value & 0xfff;
|
||||
case RISCV::fixup_riscv_lo12_s:
|
||||
case RISCV::fixup_riscv_pcrel_lo12_s:
|
||||
case RISCV::fixup_riscv_tprel_lo12_s:
|
||||
return (((Value >> 5) & 0x7f) << 25) | ((Value & 0x1f) << 7);
|
||||
case RISCV::fixup_riscv_hi20:
|
||||
case RISCV::fixup_riscv_pcrel_hi20:
|
||||
case RISCV::fixup_riscv_tprel_hi20:
|
||||
// Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
|
||||
return ((Value + 0x800) >> 12) & 0xfffff;
|
||||
case RISCV::fixup_riscv_jal: {
|
||||
|
|
|
@ -105,6 +105,10 @@ public:
|
|||
{ "fixup_riscv_pcrel_lo12_i", 20, 12, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_pcrel_lo12_s", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_tprel_hi20", 12, 20, 0 },
|
||||
{ "fixup_riscv_tprel_lo12_i", 20, 12, 0 },
|
||||
{ "fixup_riscv_tprel_lo12_s", 0, 32, 0 },
|
||||
{ "fixup_riscv_tprel_add", 0, 0, 0 },
|
||||
{ "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel },
|
||||
|
|
|
@ -85,6 +85,14 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
|
|||
return ELF::R_RISCV_PCREL_LO12_S;
|
||||
case RISCV::fixup_riscv_got_hi20:
|
||||
return ELF::R_RISCV_GOT_HI20;
|
||||
case RISCV::fixup_riscv_tprel_hi20:
|
||||
return ELF::R_RISCV_TPREL_HI20;
|
||||
case RISCV::fixup_riscv_tprel_lo12_i:
|
||||
return ELF::R_RISCV_TPREL_LO12_I;
|
||||
case RISCV::fixup_riscv_tprel_lo12_s:
|
||||
return ELF::R_RISCV_TPREL_LO12_S;
|
||||
case RISCV::fixup_riscv_tprel_add:
|
||||
return ELF::R_RISCV_TPREL_ADD;
|
||||
case RISCV::fixup_riscv_jal:
|
||||
return ELF::R_RISCV_JAL;
|
||||
case RISCV::fixup_riscv_branch:
|
||||
|
|
|
@ -37,6 +37,18 @@ enum Fixups {
|
|||
// fixup_riscv_got_hi20 - 20-bit fixup corresponding to got_pcrel_hi(foo) for
|
||||
// instructions like auipc
|
||||
fixup_riscv_got_hi20,
|
||||
// fixup_riscv_tprel_hi20 - 20-bit fixup corresponding to tprel_hi(foo) for
|
||||
// instructions like lui
|
||||
fixup_riscv_tprel_hi20,
|
||||
// fixup_riscv_tprel_lo12_i - 12-bit fixup corresponding to tprel_lo(foo) for
|
||||
// instructions like addi
|
||||
fixup_riscv_tprel_lo12_i,
|
||||
// fixup_riscv_tprel_lo12_s - 12-bit fixup corresponding to tprel_lo(foo) for
|
||||
// the S-type store instructions
|
||||
fixup_riscv_tprel_lo12_s,
|
||||
// fixup_riscv_tprel_add - A fixup corresponding to %tprel_add(foo) for the
|
||||
// add_tls instruction. Used to provide a hint to the linker.
|
||||
fixup_riscv_tprel_add,
|
||||
// fixup_riscv_jal - 20-bit fixup for symbol references in the jal
|
||||
// instruction
|
||||
fixup_riscv_jal,
|
||||
|
|
|
@ -56,6 +56,10 @@ public:
|
|||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
void expandAddTPRel(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// TableGen'erated function for getting the binary encoding for an
|
||||
/// instruction.
|
||||
uint64_t getBinaryCodeForInstr(const MCInst &MI,
|
||||
|
@ -120,6 +124,44 @@ void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, raw_ostream &OS,
|
|||
support::endian::write(OS, Binary, support::little);
|
||||
}
|
||||
|
||||
// Expand PseudoAddTPRel to a simple ADD with the correct relocation.
|
||||
void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
MCOperand DestReg = MI.getOperand(0);
|
||||
MCOperand SrcReg = MI.getOperand(1);
|
||||
MCOperand TPReg = MI.getOperand(2);
|
||||
assert(TPReg.isReg() && TPReg.getReg() == RISCV::X4 &&
|
||||
"Expected thread pointer as second input to TP-relative add");
|
||||
|
||||
MCOperand SrcSymbol = MI.getOperand(3);
|
||||
assert(SrcSymbol.isExpr() &&
|
||||
"Expected expression as third input to TP-relative add");
|
||||
|
||||
const RISCVMCExpr *Expr = dyn_cast<RISCVMCExpr>(SrcSymbol.getExpr());
|
||||
assert(Expr && Expr->getKind() == RISCVMCExpr::VK_RISCV_TPREL_ADD &&
|
||||
"Expected tprel_add relocation on TP-relative symbol");
|
||||
|
||||
// Emit the correct tprel_add relocation for the symbol.
|
||||
Fixups.push_back(MCFixup::create(
|
||||
0, Expr, MCFixupKind(RISCV::fixup_riscv_tprel_add), MI.getLoc()));
|
||||
|
||||
// Emit fixup_riscv_relax for tprel_add where the relax feature is enabled.
|
||||
if (STI.getFeatureBits()[RISCV::FeatureRelax]) {
|
||||
const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
|
||||
Fixups.push_back(MCFixup::create(
|
||||
0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax), MI.getLoc()));
|
||||
}
|
||||
|
||||
// Emit a normal ADD instruction with the given operands.
|
||||
MCInst TmpInst = MCInstBuilder(RISCV::ADD)
|
||||
.addOperand(DestReg)
|
||||
.addOperand(SrcReg)
|
||||
.addOperand(TPReg);
|
||||
uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
|
||||
support::endian::write(OS, Binary, support::little);
|
||||
}
|
||||
|
||||
void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
|
@ -134,6 +176,12 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|||
return;
|
||||
}
|
||||
|
||||
if (MI.getOpcode() == RISCV::PseudoAddTPRel) {
|
||||
expandAddTPRel(MI, OS, Fixups, STI);
|
||||
MCNumEmitted += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Size) {
|
||||
default:
|
||||
llvm_unreachable("Unhandled encodeInstruction length!");
|
||||
|
@ -208,6 +256,13 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
|
|||
case RISCVMCExpr::VK_RISCV_None:
|
||||
case RISCVMCExpr::VK_RISCV_Invalid:
|
||||
llvm_unreachable("Unhandled fixup kind!");
|
||||
case RISCVMCExpr::VK_RISCV_TPREL_ADD:
|
||||
// tprel_add is only used to indicate that a relocation should be emitted
|
||||
// for an add instruction used in TP-relative addressing. It should not be
|
||||
// expanded as if representing an actual instruction operand and so to
|
||||
// encounter it here is an error.
|
||||
llvm_unreachable(
|
||||
"VK_RISCV_TPREL_ADD should not represent an instruction operand");
|
||||
case RISCVMCExpr::VK_RISCV_LO:
|
||||
if (MIFrm == RISCVII::InstFormatI)
|
||||
FixupKind = RISCV::fixup_riscv_lo12_i;
|
||||
|
@ -238,6 +293,20 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
|
|||
case RISCVMCExpr::VK_RISCV_GOT_HI:
|
||||
FixupKind = RISCV::fixup_riscv_got_hi20;
|
||||
break;
|
||||
case RISCVMCExpr::VK_RISCV_TPREL_LO:
|
||||
if (MIFrm == RISCVII::InstFormatI)
|
||||
FixupKind = RISCV::fixup_riscv_tprel_lo12_i;
|
||||
else if (MIFrm == RISCVII::InstFormatS)
|
||||
FixupKind = RISCV::fixup_riscv_tprel_lo12_s;
|
||||
else
|
||||
llvm_unreachable(
|
||||
"VK_RISCV_TPREL_LO used with unexpected instruction format");
|
||||
RelaxCandidate = true;
|
||||
break;
|
||||
case RISCVMCExpr::VK_RISCV_TPREL_HI:
|
||||
FixupKind = RISCV::fixup_riscv_tprel_hi20;
|
||||
RelaxCandidate = true;
|
||||
break;
|
||||
case RISCVMCExpr::VK_RISCV_CALL:
|
||||
FixupKind = RISCV::fixup_riscv_call;
|
||||
RelaxCandidate = true;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "MCTargetDesc/RISCVAsmBackend.h"
|
||||
#include "RISCV.h"
|
||||
#include "RISCVFixupKinds.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
|
@ -162,6 +163,9 @@ bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
|
|||
case VK_RISCV_PCREL_LO:
|
||||
case VK_RISCV_PCREL_HI:
|
||||
case VK_RISCV_GOT_HI:
|
||||
case VK_RISCV_TPREL_LO:
|
||||
case VK_RISCV_TPREL_HI:
|
||||
case VK_RISCV_TPREL_ADD:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -180,6 +184,9 @@ RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {
|
|||
.Case("pcrel_lo", VK_RISCV_PCREL_LO)
|
||||
.Case("pcrel_hi", VK_RISCV_PCREL_HI)
|
||||
.Case("got_pcrel_hi", VK_RISCV_GOT_HI)
|
||||
.Case("tprel_lo", VK_RISCV_TPREL_LO)
|
||||
.Case("tprel_hi", VK_RISCV_TPREL_HI)
|
||||
.Case("tprel_add", VK_RISCV_TPREL_ADD)
|
||||
.Default(VK_RISCV_Invalid);
|
||||
}
|
||||
|
||||
|
@ -197,15 +204,62 @@ StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {
|
|||
return "pcrel_hi";
|
||||
case VK_RISCV_GOT_HI:
|
||||
return "got_pcrel_hi";
|
||||
case VK_RISCV_TPREL_LO:
|
||||
return "tprel_lo";
|
||||
case VK_RISCV_TPREL_HI:
|
||||
return "tprel_hi";
|
||||
case VK_RISCV_TPREL_ADD:
|
||||
return "tprel_add";
|
||||
}
|
||||
}
|
||||
|
||||
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
|
||||
switch (Expr->getKind()) {
|
||||
case MCExpr::Target:
|
||||
llvm_unreachable("Can't handle nested target expression");
|
||||
break;
|
||||
case MCExpr::Constant:
|
||||
break;
|
||||
|
||||
case MCExpr::Binary: {
|
||||
const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
|
||||
fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
|
||||
fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
|
||||
break;
|
||||
}
|
||||
|
||||
case MCExpr::SymbolRef: {
|
||||
// We're known to be under a TLS fixup, so any symbol should be
|
||||
// modified. There should be only one.
|
||||
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
|
||||
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
|
||||
break;
|
||||
}
|
||||
|
||||
case MCExpr::Unary:
|
||||
fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
|
||||
switch (getKind()) {
|
||||
default:
|
||||
return;
|
||||
case VK_RISCV_TPREL_HI:
|
||||
break;
|
||||
}
|
||||
|
||||
fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
|
||||
}
|
||||
|
||||
bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
|
||||
MCValue Value;
|
||||
|
||||
if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
|
||||
Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_CALL ||
|
||||
Kind == VK_RISCV_CALL_PLT)
|
||||
Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI ||
|
||||
Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD ||
|
||||
Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT)
|
||||
return false;
|
||||
|
||||
if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
|
||||
|
|
|
@ -29,6 +29,9 @@ public:
|
|||
VK_RISCV_PCREL_LO,
|
||||
VK_RISCV_PCREL_HI,
|
||||
VK_RISCV_GOT_HI,
|
||||
VK_RISCV_TPREL_LO,
|
||||
VK_RISCV_TPREL_HI,
|
||||
VK_RISCV_TPREL_ADD,
|
||||
VK_RISCV_CALL,
|
||||
VK_RISCV_CALL_PLT,
|
||||
VK_RISCV_Invalid
|
||||
|
@ -69,8 +72,7 @@ public:
|
|||
return getSubExpr()->findAssociatedFragment();
|
||||
}
|
||||
|
||||
// There are no TLS RISCVMCExprs at the moment.
|
||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
|
||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
|
||||
|
||||
bool evaluateAsConstant(int64_t &Res) const;
|
||||
|
||||
|
|
|
@ -202,6 +202,18 @@ def call_symbol : Operand<XLenVT> {
|
|||
let ParserMatchClass = CallSymbol;
|
||||
}
|
||||
|
||||
def TPRelAddSymbol : AsmOperandClass {
|
||||
let Name = "TPRelAddSymbol";
|
||||
let RenderMethod = "addImmOperands";
|
||||
let DiagnosticType = "InvalidTPRelAddSymbol";
|
||||
let ParserMethod = "parseOperandWithModifier";
|
||||
}
|
||||
|
||||
// A bare symbol with the %tprel_add variant.
|
||||
def tprel_add_symbol : Operand<XLenVT> {
|
||||
let ParserMatchClass = TPRelAddSymbol;
|
||||
}
|
||||
|
||||
def CSRSystemRegister : AsmOperandClass {
|
||||
let Name = "CSRSystemRegister";
|
||||
let ParserMethod = "parseCSRSystemRegister";
|
||||
|
@ -765,6 +777,15 @@ def : PatGprGpr<shiftop<shl>, SLL>;
|
|||
def : PatGprGpr<shiftop<srl>, SRL>;
|
||||
def : PatGprGpr<shiftop<sra>, SRA>;
|
||||
|
||||
// This is a special case of the ADD instruction used to facilitate the use of a
|
||||
// fourth operand to emit a relocation on a symbol relating to this instruction.
|
||||
// The relocation does not affect any bits of the instruction itself but is used
|
||||
// as a hint to the linker.
|
||||
let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in
|
||||
def PseudoAddTPRel : Pseudo<(outs GPR:$rd),
|
||||
(ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [],
|
||||
"add", "$rd, $rs1, $rs2, $src">;
|
||||
|
||||
/// FrameIndex calculations
|
||||
|
||||
def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12),
|
||||
|
|
|
@ -24,6 +24,16 @@ lui t1, %hi(foo+4)
|
|||
# INSTR: lui t1, %hi(foo+4)
|
||||
# FIXUP: fixup A - offset: 0, value: %hi(foo+4), kind: fixup_riscv_hi20
|
||||
|
||||
lui t1, %tprel_hi(foo)
|
||||
# RELOC: R_RISCV_TPREL_HI20 foo 0x0
|
||||
# INSTR: lui t1, %tprel_hi(foo)
|
||||
# FIXUP: fixup A - offset: 0, value: %tprel_hi(foo), kind: fixup_riscv_tprel_hi20
|
||||
|
||||
lui t1, %tprel_hi(foo+4)
|
||||
# RELOC: R_RISCV_TPREL_HI20 foo 0x4
|
||||
# INSTR: lui t1, %tprel_hi(foo+4)
|
||||
# FIXUP: fixup A - offset: 0, value: %tprel_hi(foo+4), kind: fixup_riscv_tprel_hi20
|
||||
|
||||
addi t1, t1, %lo(foo)
|
||||
# RELOC: R_RISCV_LO12_I foo 0x0
|
||||
# INSTR: addi t1, t1, %lo(foo)
|
||||
|
@ -34,6 +44,16 @@ addi t1, t1, %lo(foo+4)
|
|||
# INSTR: addi t1, t1, %lo(foo+4)
|
||||
# FIXUP: fixup A - offset: 0, value: %lo(foo+4), kind: fixup_riscv_lo12_i
|
||||
|
||||
addi t1, t1, %tprel_lo(foo)
|
||||
# RELOC: R_RISCV_TPREL_LO12_I foo 0x0
|
||||
# INSTR: addi t1, t1, %tprel_lo(foo)
|
||||
# FIXUP: fixup A - offset: 0, value: %tprel_lo(foo), kind: fixup_riscv_tprel_lo12_i
|
||||
|
||||
addi t1, t1, %tprel_lo(foo+4)
|
||||
# RELOC: R_RISCV_TPREL_LO12_I foo 0x4
|
||||
# INSTR: addi t1, t1, %tprel_lo(foo+4)
|
||||
# FIXUP: fixup A - offset: 0, value: %tprel_lo(foo+4), kind: fixup_riscv_tprel_lo12_i
|
||||
|
||||
sb t1, %lo(foo)(a2)
|
||||
# RELOC: R_RISCV_LO12_S foo 0x0
|
||||
# INSTR: sb t1, %lo(foo)(a2)
|
||||
|
@ -44,6 +64,16 @@ sb t1, %lo(foo+4)(a2)
|
|||
# INSTR: sb t1, %lo(foo+4)(a2)
|
||||
# FIXUP: fixup A - offset: 0, value: %lo(foo+4), kind: fixup_riscv_lo12_s
|
||||
|
||||
sb t1, %tprel_lo(foo)(a2)
|
||||
# RELOC: R_RISCV_TPREL_LO12_S foo 0x0
|
||||
# INSTR: sb t1, %tprel_lo(foo)(a2)
|
||||
# FIXUP: fixup A - offset: 0, value: %tprel_lo(foo), kind: fixup_riscv_tprel_lo12_s
|
||||
|
||||
sb t1, %tprel_lo(foo+4)(a2)
|
||||
# RELOC: R_RISCV_TPREL_LO12_S foo 0x4
|
||||
# INSTR: sb t1, %tprel_lo(foo+4)(a2)
|
||||
# FIXUP: fixup A - offset: 0, value: %tprel_lo(foo+4), kind: fixup_riscv_tprel_lo12_s
|
||||
|
||||
.L0:
|
||||
auipc t1, %pcrel_hi(foo)
|
||||
# RELOC: R_RISCV_PCREL_HI20 foo 0x0
|
||||
|
@ -99,6 +129,11 @@ sb t1, %pcrel_lo(.L2)(a2)
|
|||
# INSTR: sb t1, %pcrel_lo(.L2)(a2)
|
||||
# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L2), kind: fixup_riscv_pcrel_lo12_s
|
||||
|
||||
add t1, t1, tp, %tprel_add(foo)
|
||||
# RELOC: R_RISCV_TPREL_ADD foo 0x0
|
||||
# INSTR: add t1, t1, tp, %tprel_add(foo)
|
||||
# FIXUP: fixup A - offset: 0, value: %tprel_add(foo), kind: fixup_riscv_tprel_add
|
||||
|
||||
jal zero, foo
|
||||
# RELOC: R_RISCV_JAL
|
||||
# INSTR: jal zero, foo
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
# Out of range immediates
|
||||
## simm12
|
||||
fld ft1, -2049(a0) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
fsd ft2, 2048(a1) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
fld ft1, -2049(a0) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
fsd ft2, 2048(a1) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
|
||||
# Memory operand not formatted correctly
|
||||
fld ft1, a0, -200 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
# Out of range immediates
|
||||
## simm12
|
||||
flw ft1, -2049(a0) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
fsw ft2, 2048(a1) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
flw ft1, -2049(a0) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
fsw ft2, 2048(a1) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
|
||||
# Memory operand not formatted correctly
|
||||
flw ft1, a0, -200 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
|
||||
|
|
|
@ -17,8 +17,8 @@ csrrsi t1, 999, 32 # CHECK: :[[@LINE]]:17: error: immediate must be an integer i
|
|||
csrrci x0, 43, -90 # CHECK: :[[@LINE]]:16: error: immediate must be an integer in the range [0, 31]
|
||||
|
||||
## simm12
|
||||
ori a0, a1, -2049 # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
andi ra, sp, 2048 # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
ori a0, a1, -2049 # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
andi ra, sp, 2048 # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
|
||||
## uimm12
|
||||
csrrw a0, -1, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095]
|
||||
|
@ -38,8 +38,8 @@ bltu t0, t1, 13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2
|
|||
bgeu t0, t1, -13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
|
||||
|
||||
## uimm20
|
||||
lui a0, -1 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
|
||||
lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
|
||||
lui a0, -1 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi modifier or an integer in the range [0, 1048575]
|
||||
lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi modifier or an integer in the range [0, 1048575]
|
||||
auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
|
||||
|
||||
## simm21_lsb0
|
||||
|
@ -67,11 +67,11 @@ csrrsi t1, 999, %pcrel_lo(4) # CHECK: :[[@LINE]]:17: error: immediate must be an
|
|||
csrrci x0, 43, %pcrel_lo(d) # CHECK: :[[@LINE]]:16: error: immediate must be an integer in the range [0, 31]
|
||||
|
||||
## simm12
|
||||
ori a0, a1, %hi(foo) # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
andi ra, sp, %pcrel_hi(123) # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
xori a2, a3, %hi(345) # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
add a1, a2, (a3) # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
add a1, a2, foo # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
ori a0, a1, %hi(foo) # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
andi ra, sp, %pcrel_hi(123) # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
xori a2, a3, %hi(345) # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
add a1, a2, (a3) # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
add a1, a2, foo # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
|
||||
## uimm12
|
||||
csrrw a0, %lo(1), a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095]
|
||||
|
@ -104,7 +104,7 @@ bltu t0, t1, %pcrel_lo(4) # CHECK: :[[@LINE]]:14: error: immediate must be a mul
|
|||
bgeu t0, t1, %pcrel_lo(d) # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
|
||||
|
||||
## uimm20
|
||||
lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
|
||||
lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi modifier or an integer in the range [0, 1048575]
|
||||
auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
|
||||
|
||||
## simm21_lsb0
|
||||
|
@ -120,16 +120,20 @@ jal gp, %pcrel_lo(d) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple
|
|||
# Bare symbol names when an operand modifier is required and unsupported
|
||||
# operand modifiers.
|
||||
|
||||
lui a0, foo # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
|
||||
lui a0, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
|
||||
lui a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
|
||||
lui a0, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
|
||||
lui a0, foo # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi modifier or an integer in the range [0, 1048575]
|
||||
lui a0, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi modifier or an integer in the range [0, 1048575]
|
||||
lui a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi modifier or an integer in the range [0, 1048575]
|
||||
lui a0, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi/%tprel_hi modifier or an integer in the range [0, 1048575]
|
||||
|
||||
auipc a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
|
||||
auipc a0, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
|
||||
auipc a0, %hi(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
|
||||
auipc a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
|
||||
|
||||
# TP-relative symbol names require a %tprel_add modifier.
|
||||
add a0, a0, tp, zero # CHECK: :[[@LINE]]:17: error: expected '%' for operand modifier
|
||||
add a0, a0, tp, %hi(foo) # CHECK: :[[@LINE]]:17: error: operand must be a symbol with %tprel_add modifier
|
||||
|
||||
# Unrecognized operand modifier
|
||||
addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier
|
||||
|
||||
|
@ -154,7 +158,6 @@ xori sp, 22, 220 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
|
|||
sub t0, t2, 1 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction
|
||||
|
||||
# Too many operands
|
||||
add ra, zero, zero, zero # CHECK: :[[@LINE]]:21: error: invalid operand for instruction
|
||||
sltiu s2, s3, 0x50, 0x60 # CHECK: :[[@LINE]]:21: error: invalid operand for instruction
|
||||
|
||||
# Memory operand not formatted correctly
|
||||
|
|
|
@ -7,8 +7,8 @@ srliw a0, a0, -1 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in
|
|||
sraiw a0, a0, -19 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
|
||||
|
||||
## simm12
|
||||
addiw a0, a1, -2049 # CHECK: :[[@LINE]]:15: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
ld ra, 2048(sp) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
addiw a0, a1, -2049 # CHECK: :[[@LINE]]:15: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
ld ra, 2048(sp) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
|
||||
# Illegal operand modifier
|
||||
## uimm5
|
||||
|
@ -17,4 +17,4 @@ srliw a0, a0, %lo(a) # CHECK: :[[@LINE]]:15: error: immediate must be an integer
|
|||
sraiw a0, a0, %hi(2) # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
|
||||
|
||||
## simm12
|
||||
addiw a0, a1, %hi(foo) # CHECK: :[[@LINE]]:15: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
addiw a0, a1, %hi(foo) # CHECK: :[[@LINE]]:15: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
|
|
|
@ -21,7 +21,7 @@ la x1, %lo(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol nam
|
|||
la x1, %hi(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
|
||||
la x1, %lo(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
|
||||
|
||||
sw a2, %hi(a_symbol), a3 # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo modifier or an integer in the range [-2048, 2047]
|
||||
sw a2, %hi(a_symbol), a3 # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
sw a2, %lo(a_symbol), a3 # CHECK: :[[@LINE]]:23: error: invalid operand for instruction
|
||||
sw a2, %lo(a_symbol)(a4), a3 # CHECK: :[[@LINE]]:27: error: invalid operand for instruction
|
||||
|
||||
|
|
Loading…
Reference in New Issue