llvm.org GIT mirror llvm / 0796b94
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357698 91177308-0d34-0410-b5e6-96231b3b80d8 Lewis Revill 1 year, 8 months ago
15 changed file(s) with 264 addition(s) and 35 deletion(s). Raw diff Collapse all Expand all
294294 VK == RISCVMCExpr::VK_RISCV_CALL_PLT);
295295 }
296296
297 bool isTPRelAddSymbol() const {
298 int64_t Imm;
299 RISCVMCExpr::VariantKind VK;
300 // Must be of 'immediate' type but not a constant.
301 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
302 return false;
303 return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) &&
304 VK == RISCVMCExpr::VK_RISCV_TPREL_ADD;
305 }
306
297307 bool isCSRSystemRegister() const { return isSystemRegister(); }
298308
299309 /// Return true if the operand is a valid for the fence instruction e.g.
488498 IsValid = isInt<12>(Imm);
489499 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
490500 VK == RISCVMCExpr::VK_RISCV_LO ||
491 VK == RISCVMCExpr::VK_RISCV_PCREL_LO);
501 VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
502 VK == RISCVMCExpr::VK_RISCV_TPREL_LO);
492503 }
493504
494505 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
514525 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
515526 if (!IsConstantImm) {
516527 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
517 return IsValid && VK == RISCVMCExpr::VK_RISCV_HI;
528 return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
529 VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
518530 } else {
519531 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
520 VK == RISCVMCExpr::VK_RISCV_HI);
532 VK == RISCVMCExpr::VK_RISCV_HI ||
533 VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
521534 }
522535 }
523536
871884 case Match_InvalidSImm12:
872885 return generateImmOutOfRangeError(
873886 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
874 "operand must be a symbol with %lo/%pcrel_lo modifier or an integer in "
875 "the range");
887 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
888 "integer in the range");
876889 case Match_InvalidSImm12Lsb0:
877890 return generateImmOutOfRangeError(
878891 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
883896 "immediate must be a multiple of 2 bytes in the range");
884897 case Match_InvalidUImm20LUI:
885898 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
886 "operand must be a symbol with %hi() "
887 "modifier or an integer in the range");
899 "operand must be a symbol with "
900 "%hi/%tprel_hi modifier or an integer in "
901 "the range");
888902 case Match_InvalidUImm20AUIPC:
889903 return generateImmOutOfRangeError(
890904 Operands, ErrorInfo, 0, (1 << 20) - 1,
918932 case Match_InvalidCallSymbol: {
919933 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
920934 return Error(ErrorLoc, "operand must be a bare symbol name");
935 }
936 case Match_InvalidTPRelAddSymbol: {
937 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
938 return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
921939 }
922940 }
923941
186186 return Value;
187187 case RISCV::fixup_riscv_lo12_i:
188188 case RISCV::fixup_riscv_pcrel_lo12_i:
189 case RISCV::fixup_riscv_tprel_lo12_i:
189190 return Value & 0xfff;
190191 case RISCV::fixup_riscv_lo12_s:
191192 case RISCV::fixup_riscv_pcrel_lo12_s:
193 case RISCV::fixup_riscv_tprel_lo12_s:
192194 return (((Value >> 5) & 0x7f) << 25) | ((Value & 0x1f) << 7);
193195 case RISCV::fixup_riscv_hi20:
194196 case RISCV::fixup_riscv_pcrel_hi20:
197 case RISCV::fixup_riscv_tprel_hi20:
195198 // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
196199 return ((Value + 0x800) >> 12) & 0xfffff;
197200 case RISCV::fixup_riscv_jal: {
104104 { "fixup_riscv_pcrel_lo12_i", 20, 12, MCFixupKindInfo::FKF_IsPCRel },
105105 { "fixup_riscv_pcrel_lo12_s", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
106106 { "fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
107 { "fixup_riscv_tprel_hi20", 12, 20, 0 },
108 { "fixup_riscv_tprel_lo12_i", 20, 12, 0 },
109 { "fixup_riscv_tprel_lo12_s", 0, 32, 0 },
110 { "fixup_riscv_tprel_add", 0, 0, 0 },
107111 { "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
108112 { "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
109113 { "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel },
8484 return ELF::R_RISCV_PCREL_LO12_S;
8585 case RISCV::fixup_riscv_got_hi20:
8686 return ELF::R_RISCV_GOT_HI20;
87 case RISCV::fixup_riscv_tprel_hi20:
88 return ELF::R_RISCV_TPREL_HI20;
89 case RISCV::fixup_riscv_tprel_lo12_i:
90 return ELF::R_RISCV_TPREL_LO12_I;
91 case RISCV::fixup_riscv_tprel_lo12_s:
92 return ELF::R_RISCV_TPREL_LO12_S;
93 case RISCV::fixup_riscv_tprel_add:
94 return ELF::R_RISCV_TPREL_ADD;
8795 case RISCV::fixup_riscv_jal:
8896 return ELF::R_RISCV_JAL;
8997 case RISCV::fixup_riscv_branch:
3636 // fixup_riscv_got_hi20 - 20-bit fixup corresponding to got_pcrel_hi(foo) for
3737 // instructions like auipc
3838 fixup_riscv_got_hi20,
39 // fixup_riscv_tprel_hi20 - 20-bit fixup corresponding to tprel_hi(foo) for
40 // instructions like lui
41 fixup_riscv_tprel_hi20,
42 // fixup_riscv_tprel_lo12_i - 12-bit fixup corresponding to tprel_lo(foo) for
43 // instructions like addi
44 fixup_riscv_tprel_lo12_i,
45 // fixup_riscv_tprel_lo12_s - 12-bit fixup corresponding to tprel_lo(foo) for
46 // the S-type store instructions
47 fixup_riscv_tprel_lo12_s,
48 // fixup_riscv_tprel_add - A fixup corresponding to %tprel_add(foo) for the
49 // add_tls instruction. Used to provide a hint to the linker.
50 fixup_riscv_tprel_add,
3951 // fixup_riscv_jal - 20-bit fixup for symbol references in the jal
4052 // instruction
4153 fixup_riscv_jal,
5555 SmallVectorImpl &Fixups,
5656 const MCSubtargetInfo &STI) const;
5757
58 void expandAddTPRel(const MCInst &MI, raw_ostream &OS,
59 SmallVectorImpl &Fixups,
60 const MCSubtargetInfo &STI) const;
61
5862 /// TableGen'erated function for getting the binary encoding for an
5963 /// instruction.
6064 uint64_t getBinaryCodeForInstr(const MCInst &MI,
119123 support::endian::write(OS, Binary, support::little);
120124 }
121125
126 // Expand PseudoAddTPRel to a simple ADD with the correct relocation.
127 void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI, raw_ostream &OS,
128 SmallVectorImpl &Fixups,
129 const MCSubtargetInfo &STI) const {
130 MCOperand DestReg = MI.getOperand(0);
131 MCOperand SrcReg = MI.getOperand(1);
132 MCOperand TPReg = MI.getOperand(2);
133 assert(TPReg.isReg() && TPReg.getReg() == RISCV::X4 &&
134 "Expected thread pointer as second input to TP-relative add");
135
136 MCOperand SrcSymbol = MI.getOperand(3);
137 assert(SrcSymbol.isExpr() &&
138 "Expected expression as third input to TP-relative add");
139
140 const RISCVMCExpr *Expr = dyn_cast(SrcSymbol.getExpr());
141 assert(Expr && Expr->getKind() == RISCVMCExpr::VK_RISCV_TPREL_ADD &&
142 "Expected tprel_add relocation on TP-relative symbol");
143
144 // Emit the correct tprel_add relocation for the symbol.
145 Fixups.push_back(MCFixup::create(
146 0, Expr, MCFixupKind(RISCV::fixup_riscv_tprel_add), MI.getLoc()));
147
148 // Emit fixup_riscv_relax for tprel_add where the relax feature is enabled.
149 if (STI.getFeatureBits()[RISCV::FeatureRelax]) {
150 const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
151 Fixups.push_back(MCFixup::create(
152 0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax), MI.getLoc()));
153 }
154
155 // Emit a normal ADD instruction with the given operands.
156 MCInst TmpInst = MCInstBuilder(RISCV::ADD)
157 .addOperand(DestReg)
158 .addOperand(SrcReg)
159 .addOperand(TPReg);
160 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
161 support::endian::write(OS, Binary, support::little);
162 }
163
122164 void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
123165 SmallVectorImpl &Fixups,
124166 const MCSubtargetInfo &STI) const {
130172 MI.getOpcode() == RISCV::PseudoTAIL) {
131173 expandFunctionCall(MI, OS, Fixups, STI);
132174 MCNumEmitted += 2;
175 return;
176 }
177
178 if (MI.getOpcode() == RISCV::PseudoAddTPRel) {
179 expandAddTPRel(MI, OS, Fixups, STI);
180 MCNumEmitted += 1;
133181 return;
134182 }
135183
207255 case RISCVMCExpr::VK_RISCV_None:
208256 case RISCVMCExpr::VK_RISCV_Invalid:
209257 llvm_unreachable("Unhandled fixup kind!");
258 case RISCVMCExpr::VK_RISCV_TPREL_ADD:
259 // tprel_add is only used to indicate that a relocation should be emitted
260 // for an add instruction used in TP-relative addressing. It should not be
261 // expanded as if representing an actual instruction operand and so to
262 // encounter it here is an error.
263 llvm_unreachable(
264 "VK_RISCV_TPREL_ADD should not represent an instruction operand");
210265 case RISCVMCExpr::VK_RISCV_LO:
211266 if (MIFrm == RISCVII::InstFormatI)
212267 FixupKind = RISCV::fixup_riscv_lo12_i;
236291 break;
237292 case RISCVMCExpr::VK_RISCV_GOT_HI:
238293 FixupKind = RISCV::fixup_riscv_got_hi20;
294 break;
295 case RISCVMCExpr::VK_RISCV_TPREL_LO:
296 if (MIFrm == RISCVII::InstFormatI)
297 FixupKind = RISCV::fixup_riscv_tprel_lo12_i;
298 else if (MIFrm == RISCVII::InstFormatS)
299 FixupKind = RISCV::fixup_riscv_tprel_lo12_s;
300 else
301 llvm_unreachable(
302 "VK_RISCV_TPREL_LO used with unexpected instruction format");
303 RelaxCandidate = true;
304 break;
305 case RISCVMCExpr::VK_RISCV_TPREL_HI:
306 FixupKind = RISCV::fixup_riscv_tprel_hi20;
307 RelaxCandidate = true;
239308 break;
240309 case RISCVMCExpr::VK_RISCV_CALL:
241310 FixupKind = RISCV::fixup_riscv_call;
1414 #include "MCTargetDesc/RISCVAsmBackend.h"
1515 #include "RISCV.h"
1616 #include "RISCVFixupKinds.h"
17 #include "llvm/BinaryFormat/ELF.h"
1718 #include "llvm/MC/MCAsmLayout.h"
1819 #include "llvm/MC/MCAssembler.h"
1920 #include "llvm/MC/MCContext.h"
161162 case VK_RISCV_PCREL_LO:
162163 case VK_RISCV_PCREL_HI:
163164 case VK_RISCV_GOT_HI:
165 case VK_RISCV_TPREL_LO:
166 case VK_RISCV_TPREL_HI:
167 case VK_RISCV_TPREL_ADD:
164168 return false;
165169 }
166170 }
179183 .Case("pcrel_lo", VK_RISCV_PCREL_LO)
180184 .Case("pcrel_hi", VK_RISCV_PCREL_HI)
181185 .Case("got_pcrel_hi", VK_RISCV_GOT_HI)
186 .Case("tprel_lo", VK_RISCV_TPREL_LO)
187 .Case("tprel_hi", VK_RISCV_TPREL_HI)
188 .Case("tprel_add", VK_RISCV_TPREL_ADD)
182189 .Default(VK_RISCV_Invalid);
183190 }
184191
196203 return "pcrel_hi";
197204 case VK_RISCV_GOT_HI:
198205 return "got_pcrel_hi";
199 }
206 case VK_RISCV_TPREL_LO:
207 return "tprel_lo";
208 case VK_RISCV_TPREL_HI:
209 return "tprel_hi";
210 case VK_RISCV_TPREL_ADD:
211 return "tprel_add";
212 }
213 }
214
215 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
216 switch (Expr->getKind()) {
217 case MCExpr::Target:
218 llvm_unreachable("Can't handle nested target expression");
219 break;
220 case MCExpr::Constant:
221 break;
222
223 case MCExpr::Binary: {
224 const MCBinaryExpr *BE = cast(Expr);
225 fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
226 fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
227 break;
228 }
229
230 case MCExpr::SymbolRef: {
231 // We're known to be under a TLS fixup, so any symbol should be
232 // modified. There should be only one.
233 const MCSymbolRefExpr &SymRef = *cast(Expr);
234 cast(SymRef.getSymbol()).setType(ELF::STT_TLS);
235 break;
236 }
237
238 case MCExpr::Unary:
239 fixELFSymbolsInTLSFixupsImpl(cast(Expr)->getSubExpr(), Asm);
240 break;
241 }
242 }
243
244 void RISCVMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
245 switch (getKind()) {
246 default:
247 return;
248 case VK_RISCV_TPREL_HI:
249 break;
250 }
251
252 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
200253 }
201254
202255 bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
203256 MCValue Value;
204257
205258 if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
206 Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_CALL ||
207 Kind == VK_RISCV_CALL_PLT)
259 Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI ||
260 Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD ||
261 Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT)
208262 return false;
209263
210264 if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
2828 VK_RISCV_PCREL_LO,
2929 VK_RISCV_PCREL_HI,
3030 VK_RISCV_GOT_HI,
31 VK_RISCV_TPREL_LO,
32 VK_RISCV_TPREL_HI,
33 VK_RISCV_TPREL_ADD,
3134 VK_RISCV_CALL,
3235 VK_RISCV_CALL_PLT,
3336 VK_RISCV_Invalid
6871 return getSubExpr()->findAssociatedFragment();
6972 }
7073
71 // There are no TLS RISCVMCExprs at the moment.
72 void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
74 void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
7375
7476 bool evaluateAsConstant(int64_t &Res) const;
7577
199199 // A bare symbol used in call/tail only.
200200 def call_symbol : Operand {
201201 let ParserMatchClass = CallSymbol;
202 }
203
204 def TPRelAddSymbol : AsmOperandClass {
205 let Name = "TPRelAddSymbol";
206 let RenderMethod = "addImmOperands";
207 let DiagnosticType = "InvalidTPRelAddSymbol";
208 let ParserMethod = "parseOperandWithModifier";
209 }
210
211 // A bare symbol with the %tprel_add variant.
212 def tprel_add_symbol : Operand {
213 let ParserMatchClass = TPRelAddSymbol;
202214 }
203215
204216 def CSRSystemRegister : AsmOperandClass {
764776 def : PatGprGpr, SRL>;
765777 def : PatGprGpr, SRA>;
766778
779 // This is a special case of the ADD instruction used to facilitate the use of a
780 // fourth operand to emit a relocation on a symbol relating to this instruction.
781 // The relocation does not affect any bits of the instruction itself but is used
782 // as a hint to the linker.
783 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in
784 def PseudoAddTPRel : Pseudo<(outs GPR:$rd),
785 (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [],
786 "add", "$rd, $rs1, $rs2, $src">;
787
767788 /// FrameIndex calculations
768789
769790 def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12),
2323 # INSTR: lui t1, %hi(foo+4)
2424 # FIXUP: fixup A - offset: 0, value: %hi(foo+4), kind: fixup_riscv_hi20
2525
26 lui t1, %tprel_hi(foo)
27 # RELOC: R_RISCV_TPREL_HI20 foo 0x0
28 # INSTR: lui t1, %tprel_hi(foo)
29 # FIXUP: fixup A - offset: 0, value: %tprel_hi(foo), kind: fixup_riscv_tprel_hi20
30
31 lui t1, %tprel_hi(foo+4)
32 # RELOC: R_RISCV_TPREL_HI20 foo 0x4
33 # INSTR: lui t1, %tprel_hi(foo+4)
34 # FIXUP: fixup A - offset: 0, value: %tprel_hi(foo+4), kind: fixup_riscv_tprel_hi20
35
2636 addi t1, t1, %lo(foo)
2737 # RELOC: R_RISCV_LO12_I foo 0x0
2838 # INSTR: addi t1, t1, %lo(foo)
3343 # INSTR: addi t1, t1, %lo(foo+4)
3444 # FIXUP: fixup A - offset: 0, value: %lo(foo+4), kind: fixup_riscv_lo12_i
3545
46 addi t1, t1, %tprel_lo(foo)
47 # RELOC: R_RISCV_TPREL_LO12_I foo 0x0
48 # INSTR: addi t1, t1, %tprel_lo(foo)
49 # FIXUP: fixup A - offset: 0, value: %tprel_lo(foo), kind: fixup_riscv_tprel_lo12_i
50
51 addi t1, t1, %tprel_lo(foo+4)
52 # RELOC: R_RISCV_TPREL_LO12_I foo 0x4
53 # INSTR: addi t1, t1, %tprel_lo(foo+4)
54 # FIXUP: fixup A - offset: 0, value: %tprel_lo(foo+4), kind: fixup_riscv_tprel_lo12_i
55
3656 sb t1, %lo(foo)(a2)
3757 # RELOC: R_RISCV_LO12_S foo 0x0
3858 # INSTR: sb t1, %lo(foo)(a2)
4262 # RELOC: R_RISCV_LO12_S foo 0x4
4363 # INSTR: sb t1, %lo(foo+4)(a2)
4464 # FIXUP: fixup A - offset: 0, value: %lo(foo+4), kind: fixup_riscv_lo12_s
65
66 sb t1, %tprel_lo(foo)(a2)
67 # RELOC: R_RISCV_TPREL_LO12_S foo 0x0
68 # INSTR: sb t1, %tprel_lo(foo)(a2)
69 # FIXUP: fixup A - offset: 0, value: %tprel_lo(foo), kind: fixup_riscv_tprel_lo12_s
70
71 sb t1, %tprel_lo(foo+4)(a2)
72 # RELOC: R_RISCV_TPREL_LO12_S foo 0x4
73 # INSTR: sb t1, %tprel_lo(foo+4)(a2)
74 # FIXUP: fixup A - offset: 0, value: %tprel_lo(foo+4), kind: fixup_riscv_tprel_lo12_s
4575
4676 .L0:
4777 auipc t1, %pcrel_hi(foo)
98128 # INSTR: sb t1, %pcrel_lo(.L2)(a2)
99129 # FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L2), kind: fixup_riscv_pcrel_lo12_s
100130
131 add t1, t1, tp, %tprel_add(foo)
132 # RELOC: R_RISCV_TPREL_ADD foo 0x0
133 # INSTR: add t1, t1, tp, %tprel_add(foo)
134 # FIXUP: fixup A - offset: 0, value: %tprel_add(foo), kind: fixup_riscv_tprel_add
135
101136 jal zero, foo
102137 # RELOC: R_RISCV_JAL
103138 # INSTR: jal zero, foo
11
22 # Out of range immediates
33 ## simm12
4 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]
5 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]
4 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]
5 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]
66
77 # Memory operand not formatted correctly
88 fld ft1, a0, -200 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
11
22 # Out of range immediates
33 ## simm12
4 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]
5 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]
4 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]
5 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]
66
77 # Memory operand not formatted correctly
88 flw ft1, a0, -200 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
1616 csrrci x0, 43, -90 # CHECK: :[[@LINE]]:16: error: immediate must be an integer in the range [0, 31]
1717
1818 ## simm12
19 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]
20 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]
19 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]
20 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]
2121
2222 ## uimm12
2323 csrrw a0, -1, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095]
3737 bgeu t0, t1, -13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
3838
3939 ## uimm20
40 lui a0, -1 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
41 lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
40 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]
41 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]
4242 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]
4343
4444 ## simm21_lsb0
6666 csrrci x0, 43, %pcrel_lo(d) # CHECK: :[[@LINE]]:16: error: immediate must be an integer in the range [0, 31]
6767
6868 ## simm12
69 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]
70 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]
71 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]
72 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]
73 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]
69 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]
70 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]
71 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]
72 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]
73 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]
7474
7575 ## uimm12
7676 csrrw a0, %lo(1), a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095]
103103 bgeu t0, t1, %pcrel_lo(d) # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
104104
105105 ## uimm20
106 lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
106 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]
107107 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]
108108
109109 ## simm21_lsb0
119119 # Bare symbol names when an operand modifier is required and unsupported
120120 # operand modifiers.
121121
122 lui a0, foo # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
123 lui a0, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
124 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]
125 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]
122 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]
123 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]
124 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]
125 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]
126126
127127 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]
128128 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]
129129 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]
130130 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]
131
132 # TP-relative symbol names require a %tprel_add modifier.
133 add a0, a0, tp, zero # CHECK: :[[@LINE]]:17: error: expected '%' for operand modifier
134 add a0, a0, tp, %hi(foo) # CHECK: :[[@LINE]]:17: error: operand must be a symbol with %tprel_add modifier
131135
132136 # Unrecognized operand modifier
133137 addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier
153157 sub t0, t2, 1 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction
154158
155159 # Too many operands
156 add ra, zero, zero, zero # CHECK: :[[@LINE]]:21: error: invalid operand for instruction
157160 sltiu s2, s3, 0x50, 0x60 # CHECK: :[[@LINE]]:21: error: invalid operand for instruction
158161
159162 # Memory operand not formatted correctly
66 sraiw a0, a0, -19 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
77
88 ## simm12
9 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]
10 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]
9 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]
10 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]
1111
1212 # Illegal operand modifier
1313 ## uimm5
1616 sraiw a0, a0, %hi(2) # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
1717
1818 ## simm12
19 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]
19 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]
2020 la x1, %hi(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
2121 la x1, %lo(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
2222
23 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]
23 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]
2424 sw a2, %lo(a_symbol), a3 # CHECK: :[[@LINE]]:23: error: invalid operand for instruction
2525 sw a2, %lo(a_symbol)(a4), a3 # CHECK: :[[@LINE]]:27: error: invalid operand for instruction
2626