1//===-- RISCVAsmParser.cpp - Parse RISC-V assembly to MCInst instructions -===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "MCTargetDesc/RISCVAsmBackend.h"
10#include "MCTargetDesc/RISCVBaseInfo.h"
11#include "MCTargetDesc/RISCVInstPrinter.h"
12#include "MCTargetDesc/RISCVMCAsmInfo.h"
13#include "MCTargetDesc/RISCVMCTargetDesc.h"
14#include "MCTargetDesc/RISCVMatInt.h"
15#include "MCTargetDesc/RISCVTargetStreamer.h"
16#include "TargetInfo/RISCVTargetInfo.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallBitVector.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/Statistic.h"
21#include "llvm/ADT/StringExtras.h"
22#include "llvm/MC/MCAssembler.h"
23#include "llvm/MC/MCContext.h"
24#include "llvm/MC/MCExpr.h"
25#include "llvm/MC/MCInst.h"
26#include "llvm/MC/MCInstBuilder.h"
27#include "llvm/MC/MCInstrInfo.h"
28#include "llvm/MC/MCObjectFileInfo.h"
29#include "llvm/MC/MCParser/AsmLexer.h"
30#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
31#include "llvm/MC/MCParser/MCTargetAsmParser.h"
32#include "llvm/MC/MCRegisterInfo.h"
33#include "llvm/MC/MCStreamer.h"
34#include "llvm/MC/MCSubtargetInfo.h"
35#include "llvm/MC/MCValue.h"
36#include "llvm/MC/TargetRegistry.h"
37#include "llvm/Support/Casting.h"
38#include "llvm/Support/CommandLine.h"
39#include "llvm/Support/Compiler.h"
40#include "llvm/Support/MathExtras.h"
41#include "llvm/Support/RISCVAttributes.h"
42#include "llvm/TargetParser/RISCVISAInfo.h"
43
44#include <limits>
45#include <optional>
46
47using namespace llvm;
48
49#define DEBUG_TYPE "riscv-asm-parser"
50
51STATISTIC(RISCVNumInstrsCompressed,
52 "Number of RISC-V Compressed instructions emitted");
53
54static cl::opt<bool> AddBuildAttributes("riscv-add-build-attributes",
55 cl::init(Val: false));
56
57namespace llvm {
58extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
59} // namespace llvm
60
61namespace {
62struct RISCVOperand;
63
64struct ParserOptionsSet {
65 bool IsPicEnabled;
66};
67
68class RISCVAsmParser : public MCTargetAsmParser {
69 // This tracks the parsing of the 4 optional operands that make up the vtype
70 // portion of vset(i)vli instructions which are separated by commas.
71 enum class VTypeState {
72 SeenNothingYet,
73 SeenSew,
74 SeenLmul,
75 SeenTailPolicy,
76 SeenMaskPolicy,
77 };
78
79 SmallVector<FeatureBitset, 4> FeatureBitStack;
80
81 SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
82 ParserOptionsSet ParserOptions;
83
84 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
85 bool isRV64() const { return getSTI().hasFeature(Feature: RISCV::Feature64Bit); }
86 bool isRVE() const { return getSTI().hasFeature(Feature: RISCV::FeatureStdExtE); }
87 bool enableExperimentalExtension() const {
88 return getSTI().hasFeature(Feature: RISCV::Experimental);
89 }
90
91 RISCVTargetStreamer &getTargetStreamer() {
92 assert(getParser().getStreamer().getTargetStreamer() &&
93 "do not have a target streamer");
94 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
95 return static_cast<RISCVTargetStreamer &>(TS);
96 }
97
98 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
99 unsigned Kind) override;
100
101 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
102 int64_t Lower, int64_t Upper,
103 const Twine &Msg);
104 bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
105 const Twine &Msg);
106
107 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
108 OperandVector &Operands, MCStreamer &Out,
109 uint64_t &ErrorInfo,
110 bool MatchingInlineAsm) override;
111
112 MCRegister matchRegisterNameHelper(StringRef Name) const;
113 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
114 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
115 SMLoc &EndLoc) override;
116
117 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
118 SMLoc NameLoc, OperandVector &Operands) override;
119
120 ParseStatus parseDirective(AsmToken DirectiveID) override;
121
122 bool parseVTypeToken(const AsmToken &Tok, VTypeState &State, unsigned &Sew,
123 unsigned &Lmul, bool &Fractional, bool &TailAgnostic,
124 bool &MaskAgnostic, bool &AltFmt);
125 bool generateVTypeError(SMLoc ErrorLoc);
126
127 bool generateXSfmmVTypeError(SMLoc ErrorLoc);
128 // Helper to actually emit an instruction to the MCStreamer. Also, when
129 // possible, compression of the instruction is performed.
130 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
131
132 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
133 // synthesize the desired immediate value into the destination register.
134 void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
135
136 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
137 // helpers such as emitLoadLocalAddress and emitLoadAddress.
138 void emitAuipcInstPair(MCRegister DestReg, MCRegister TmpReg,
139 const MCExpr *Symbol, RISCV::Specifier VKHi,
140 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
141
142 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
143 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
144
145 // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
146 void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
147
148 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
149 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
150
151 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
152 // addressing.
153 void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
154
155 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
156 // addressing.
157 void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
158
159 // Helper to emit pseudo load/store instruction with a symbol.
160 void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
161 MCStreamer &Out, bool HasTmpReg);
162
163 // Helper to emit pseudo sign/zero extend instruction.
164 void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
165 SMLoc IDLoc, MCStreamer &Out);
166
167 // Helper to emit pseudo vmsge{u}.vx instruction.
168 void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
169
170 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
171 // Enforcing this using a restricted register class for the second input
172 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
173 // 'add' is an overloaded mnemonic.
174 bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
175
176 // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.
177 // Enforcing this using a restricted register class for the output
178 // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact
179 // 'jalr' is an overloaded mnemonic.
180 bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands);
181
182 // Check instruction constraints.
183 bool validateInstruction(MCInst &Inst, OperandVector &Operands);
184
185 /// Helper for processing MC instructions that have been successfully matched
186 /// by matchAndEmitInstruction. Modifications to the emitted instructions,
187 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
188 /// in this method.
189 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
190 MCStreamer &Out);
191
192// Auto-generated instruction matching functions
193#define GET_ASSEMBLER_HEADER
194#include "RISCVGenAsmMatcher.inc"
195
196 ParseStatus parseCSRSystemRegister(OperandVector &Operands);
197 ParseStatus parseFPImm(OperandVector &Operands);
198 ParseStatus parseExpression(OperandVector &Operands);
199 ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);
200 ParseStatus parseMemOpBaseReg(OperandVector &Operands);
201 ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);
202 ParseStatus parseOperandWithSpecifier(OperandVector &Operands);
203 ParseStatus parseBareSymbol(OperandVector &Operands);
204 ParseStatus parseCallSymbol(OperandVector &Operands);
205 ParseStatus parsePseudoJumpSymbol(OperandVector &Operands);
206 ParseStatus parseJALOffset(OperandVector &Operands);
207 ParseStatus parseVTypeI(OperandVector &Operands);
208 ParseStatus parseMaskReg(OperandVector &Operands);
209 ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);
210 ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);
211 ParseStatus parseGPRAsFPR(OperandVector &Operands);
212 ParseStatus parseGPRAsFPR64(OperandVector &Operands);
213 ParseStatus parseGPRPairAsFPR64(OperandVector &Operands);
214 template <bool IsRV64Inst> ParseStatus parseGPRPair(OperandVector &Operands);
215 ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);
216 ParseStatus parseFRMArg(OperandVector &Operands);
217 ParseStatus parseFenceArg(OperandVector &Operands);
218 ParseStatus parseRegList(OperandVector &Operands, bool MustIncludeS0 = false);
219 ParseStatus parseRegListS0(OperandVector &Operands) {
220 return parseRegList(Operands, /*MustIncludeS0=*/true);
221 }
222
223 ParseStatus parseRegReg(OperandVector &Operands);
224 ParseStatus parseXSfmmVType(OperandVector &Operands);
225 ParseStatus parseZcmpStackAdj(OperandVector &Operands,
226 bool ExpectNegative = false);
227 ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) {
228 return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true);
229 }
230
231 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
232 bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E);
233 bool parseDataExpr(const MCExpr *&Res) override;
234
235 bool parseDirectiveOption();
236 bool parseDirectiveAttribute();
237 bool parseDirectiveInsn(SMLoc L);
238 bool parseDirectiveVariantCC();
239
240 /// Helper to reset target features for a new arch string. It
241 /// also records the new arch string that is expanded by RISCVISAInfo
242 /// and reports error for invalid arch string.
243 bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
244 bool FromOptionDirective);
245
246 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
247 if (!(getSTI().hasFeature(Feature))) {
248 MCSubtargetInfo &STI = copySTI();
249 STI.ToggleFeature(FS: FeatureString);
250
251 // Update the C and Zce implications.
252 RISCV::updateCZceFeatureImplications(STI);
253
254 setAvailableFeatures(ComputeAvailableFeatures(FB: STI.getFeatureBits()));
255 }
256 }
257
258 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
259 if (getSTI().hasFeature(Feature)) {
260 MCSubtargetInfo &STI = copySTI();
261 setAvailableFeatures(
262 ComputeAvailableFeatures(FB: STI.ToggleFeature(FS: FeatureString)));
263 }
264 }
265
266 void pushFeatureBits() {
267 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
268 "These two stacks must be kept synchronized");
269 FeatureBitStack.push_back(Elt: getSTI().getFeatureBits());
270 ParserOptionsStack.push_back(Elt: ParserOptions);
271 }
272
273 bool popFeatureBits() {
274 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
275 "These two stacks must be kept synchronized");
276 if (FeatureBitStack.empty())
277 return true;
278
279 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
280 copySTI().setFeatureBits(FeatureBits);
281 setAvailableFeatures(ComputeAvailableFeatures(FB: FeatureBits));
282
283 ParserOptions = ParserOptionsStack.pop_back_val();
284
285 return false;
286 }
287
288 std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
289 std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
290 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;
291
292public:
293 enum RISCVMatchResultTy : unsigned {
294 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
295#define GET_OPERAND_DIAGNOSTIC_TYPES
296#include "RISCVGenAsmMatcher.inc"
297#undef GET_OPERAND_DIAGNOSTIC_TYPES
298 };
299
300 static bool classifySymbolRef(const MCExpr *Expr, RISCV::Specifier &Kind);
301 static bool isSymbolDiff(const MCExpr *Expr);
302
303 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
304 const MCInstrInfo &MII, const MCTargetOptions &Options)
305 : MCTargetAsmParser(Options, STI, MII) {
306 MCAsmParserExtension::Initialize(Parser);
307
308 Parser.addAliasForDirective(Directive: ".half", Alias: ".2byte");
309 Parser.addAliasForDirective(Directive: ".hword", Alias: ".2byte");
310 Parser.addAliasForDirective(Directive: ".word", Alias: ".4byte");
311 Parser.addAliasForDirective(Directive: ".dword", Alias: ".8byte");
312 setAvailableFeatures(ComputeAvailableFeatures(FB: STI.getFeatureBits()));
313
314 auto ABIName = StringRef(Options.ABIName);
315 if (ABIName.ends_with(Suffix: "f") && !getSTI().hasFeature(Feature: RISCV::FeatureStdExtF)) {
316 errs() << "Hard-float 'f' ABI can't be used for a target that "
317 "doesn't support the F instruction set extension (ignoring "
318 "target-abi)\n";
319 } else if (ABIName.ends_with(Suffix: "d") &&
320 !getSTI().hasFeature(Feature: RISCV::FeatureStdExtD)) {
321 errs() << "Hard-float 'd' ABI can't be used for a target that "
322 "doesn't support the D instruction set extension (ignoring "
323 "target-abi)\n";
324 }
325
326 // Use computeTargetABI to check if ABIName is valid. If invalid, output
327 // error message.
328 RISCVABI::computeTargetABI(TT: STI.getTargetTriple(), FeatureBits: STI.getFeatureBits(),
329 ABIName);
330
331 const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
332 ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
333
334 if (AddBuildAttributes)
335 getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);
336 }
337};
338
339/// RISCVOperand - Instances of this class represent a parsed machine
340/// instruction
341struct RISCVOperand final : public MCParsedAsmOperand {
342
343 enum class KindTy {
344 Token,
345 Register,
346 Expression,
347 FPImmediate,
348 SystemRegister,
349 VType,
350 FRM,
351 Fence,
352 RegList,
353 StackAdj,
354 RegReg,
355 } Kind;
356
357 struct RegOp {
358 MCRegister Reg;
359 bool IsGPRAsFPR;
360 };
361
362 struct ExprOp {
363 const MCExpr *Expr;
364 bool IsRV64;
365 };
366
367 struct FPImmOp {
368 uint64_t Val;
369 };
370
371 struct SysRegOp {
372 const char *Data;
373 unsigned Length;
374 unsigned Encoding;
375 // FIXME: Add the Encoding parsed fields as needed for checks,
376 // e.g.: read/write or user/supervisor/machine privileges.
377 };
378
379 struct VTypeOp {
380 unsigned Val;
381 };
382
383 struct FRMOp {
384 RISCVFPRndMode::RoundingMode FRM;
385 };
386
387 struct FenceOp {
388 unsigned Val;
389 };
390
391 struct RegListOp {
392 unsigned Encoding;
393 };
394
395 struct StackAdjOp {
396 unsigned Val;
397 };
398
399 struct RegRegOp {
400 MCRegister BaseReg;
401 MCRegister OffsetReg;
402 };
403
404 SMLoc StartLoc, EndLoc;
405 union {
406 StringRef Tok;
407 RegOp Reg;
408 ExprOp Expr;
409 FPImmOp FPImm;
410 SysRegOp SysReg;
411 VTypeOp VType;
412 FRMOp FRM;
413 FenceOp Fence;
414 RegListOp RegList;
415 StackAdjOp StackAdj;
416 RegRegOp RegReg;
417 };
418
419 RISCVOperand(KindTy K) : Kind(K) {}
420
421public:
422 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
423 Kind = o.Kind;
424 StartLoc = o.StartLoc;
425 EndLoc = o.EndLoc;
426 switch (Kind) {
427 case KindTy::Register:
428 Reg = o.Reg;
429 break;
430 case KindTy::Expression:
431 Expr = o.Expr;
432 break;
433 case KindTy::FPImmediate:
434 FPImm = o.FPImm;
435 break;
436 case KindTy::Token:
437 Tok = o.Tok;
438 break;
439 case KindTy::SystemRegister:
440 SysReg = o.SysReg;
441 break;
442 case KindTy::VType:
443 VType = o.VType;
444 break;
445 case KindTy::FRM:
446 FRM = o.FRM;
447 break;
448 case KindTy::Fence:
449 Fence = o.Fence;
450 break;
451 case KindTy::RegList:
452 RegList = o.RegList;
453 break;
454 case KindTy::StackAdj:
455 StackAdj = o.StackAdj;
456 break;
457 case KindTy::RegReg:
458 RegReg = o.RegReg;
459 break;
460 }
461 }
462
463 bool isToken() const override { return Kind == KindTy::Token; }
464 bool isReg() const override { return Kind == KindTy::Register; }
465 bool isExpr() const { return Kind == KindTy::Expression; }
466 bool isV0Reg() const {
467 return Kind == KindTy::Register && Reg.Reg == RISCV::V0;
468 }
469 bool isAnyReg() const {
470 return Kind == KindTy::Register &&
471 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg: Reg.Reg) ||
472 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg: Reg.Reg) ||
473 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg: Reg.Reg));
474 }
475 bool isAnyRegC() const {
476 return Kind == KindTy::Register &&
477 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(Reg: Reg.Reg) ||
478 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg: Reg.Reg));
479 }
480 bool isImm() const override { return isExpr(); }
481 bool isMem() const override { return false; }
482 bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
483 bool isRegReg() const { return Kind == KindTy::RegReg; }
484 bool isRegList() const { return Kind == KindTy::RegList; }
485 bool isRegListS0() const {
486 return Kind == KindTy::RegList && RegList.Encoding != RISCVZC::RA;
487 }
488 bool isStackAdj() const { return Kind == KindTy::StackAdj; }
489
490 bool isGPR() const {
491 return Kind == KindTy::Register &&
492 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg: Reg.Reg);
493 }
494
495 bool isGPRPair() const {
496 return Kind == KindTy::Register &&
497 RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(Reg: Reg.Reg);
498 }
499
500 bool isGPRPairC() const {
501 return Kind == KindTy::Register &&
502 RISCVMCRegisterClasses[RISCV::GPRPairCRegClassID].contains(Reg: Reg.Reg);
503 }
504
505 bool isGPRPairNoX0() const {
506 return Kind == KindTy::Register &&
507 RISCVMCRegisterClasses[RISCV::GPRPairNoX0RegClassID].contains(
508 Reg: Reg.Reg);
509 }
510
511 bool isGPRF16() const {
512 return Kind == KindTy::Register &&
513 RISCVMCRegisterClasses[RISCV::GPRF16RegClassID].contains(Reg: Reg.Reg);
514 }
515
516 bool isGPRF32() const {
517 return Kind == KindTy::Register &&
518 RISCVMCRegisterClasses[RISCV::GPRF32RegClassID].contains(Reg: Reg.Reg);
519 }
520
521 bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
522 bool isGPRAsFPR16() const { return isGPRF16() && Reg.IsGPRAsFPR; }
523 bool isGPRAsFPR32() const { return isGPRF32() && Reg.IsGPRAsFPR; }
524 bool isGPRPairAsFPR64() const { return isGPRPair() && Reg.IsGPRAsFPR; }
525
526 static bool evaluateConstantExpr(const MCExpr *Expr, int64_t &Imm) {
527 if (auto CE = dyn_cast<MCConstantExpr>(Val: Expr)) {
528 Imm = CE->getValue();
529 return true;
530 }
531
532 return false;
533 }
534
535 // True if operand is a symbol with no modifiers, or a constant with no
536 // modifiers and isShiftedInt<N-1, 1>(Op).
537 template <int N> bool isBareSimmNLsb0() const {
538 if (!isExpr())
539 return false;
540
541 int64_t Imm;
542 if (evaluateConstantExpr(Expr: getExpr(), Imm))
543 return isShiftedInt<N - 1, 1>(fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
544
545 RISCV::Specifier VK = RISCV::S_None;
546 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
547 VK == RISCV::S_None;
548 }
549
550 // True if operand is a symbol with no modifiers, or a constant with no
551 // modifiers and isInt<N>(Op).
552 template <int N> bool isBareSimmN() const {
553 if (!isExpr())
554 return false;
555
556 int64_t Imm;
557 if (evaluateConstantExpr(Expr: getExpr(), Imm))
558 return isInt<N>(fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
559
560 RISCV::Specifier VK = RISCV::S_None;
561 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
562 VK == RISCV::S_None;
563 }
564
565 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
566
567 bool isBareSymbol() const {
568 int64_t Imm;
569 // Must be of 'immediate' type but not a constant.
570 if (!isExpr() || evaluateConstantExpr(Expr: getExpr(), Imm))
571 return false;
572
573 RISCV::Specifier VK = RISCV::S_None;
574 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
575 VK == RISCV::S_None;
576 }
577
578 bool isCallSymbol() const {
579 int64_t Imm;
580 // Must be of 'immediate' type but not a constant.
581 if (!isExpr() || evaluateConstantExpr(Expr: getExpr(), Imm))
582 return false;
583
584 RISCV::Specifier VK = RISCV::S_None;
585 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
586 VK == RISCV::S_CALL_PLT;
587 }
588
589 bool isPseudoJumpSymbol() const {
590 int64_t Imm;
591 // Must be of 'immediate' type but not a constant.
592 if (!isExpr() || evaluateConstantExpr(Expr: getExpr(), Imm))
593 return false;
594
595 RISCV::Specifier VK = RISCV::S_None;
596 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
597 VK == RISCV::S_CALL_PLT;
598 }
599
600 bool isTPRelAddSymbol() const {
601 int64_t Imm;
602 // Must be of 'immediate' type but not a constant.
603 if (!isExpr() || evaluateConstantExpr(Expr: getExpr(), Imm))
604 return false;
605
606 RISCV::Specifier VK = RISCV::S_None;
607 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
608 VK == ELF::R_RISCV_TPREL_ADD;
609 }
610
611 bool isTLSDESCCallSymbol() const {
612 int64_t Imm;
613 // Must be of 'immediate' type but not a constant.
614 if (!isExpr() || evaluateConstantExpr(Expr: getExpr(), Imm))
615 return false;
616
617 RISCV::Specifier VK = RISCV::S_None;
618 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
619 VK == ELF::R_RISCV_TLSDESC_CALL;
620 }
621
622 bool isCSRSystemRegister() const { return isSystemRegister(); }
623
624 // If the last operand of the vsetvli/vsetvli instruction is a constant
625 // expression, KindTy is Immediate.
626 bool isVTypeI10() const {
627 if (Kind == KindTy::VType)
628 return true;
629 return isUImm<10>();
630 }
631 bool isVTypeI11() const {
632 if (Kind == KindTy::VType)
633 return true;
634 return isUImm<11>();
635 }
636
637 bool isXSfmmVType() const {
638 return Kind == KindTy::VType && RISCVVType::isValidXSfmmVType(VTypeI: VType.Val);
639 }
640
641 /// Return true if the operand is a valid for the fence instruction e.g.
642 /// ('iorw').
643 bool isFenceArg() const { return Kind == KindTy::Fence; }
644
645 /// Return true if the operand is a valid floating point rounding mode.
646 bool isFRMArg() const { return Kind == KindTy::FRM; }
647 bool isFRMArgLegacy() const { return Kind == KindTy::FRM; }
648 bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }
649
650 /// Return true if the operand is a valid fli.s floating-point immediate.
651 bool isLoadFPImm() const {
652 if (isExpr())
653 return isUImm5();
654 if (Kind != KindTy::FPImmediate)
655 return false;
656 int Idx = RISCVLoadFPImm::getLoadFPImm(
657 FPImm: APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
658 // Don't allow decimal version of the minimum value. It is a different value
659 // for each supported data type.
660 return Idx >= 0 && Idx != 1;
661 }
662
663 bool isImmXLenLI() const {
664 int64_t Imm;
665 if (!isExpr())
666 return false;
667 // Given only Imm, ensuring that the actually specified constant is either
668 // a signed or unsigned 64-bit number is unfortunately impossible.
669 if (evaluateConstantExpr(Expr: getExpr(), Imm))
670 return isRV64Expr() || (isInt<32>(x: Imm) || isUInt<32>(x: Imm));
671
672 return RISCVAsmParser::isSymbolDiff(Expr: getExpr());
673 }
674
675 bool isImmXLenLI_Restricted() const {
676 int64_t Imm;
677 if (!isExpr())
678 return false;
679 bool IsConstantImm = evaluateConstantExpr(Expr: getExpr(), Imm);
680 // 'la imm' supports constant immediates only.
681 return IsConstantImm &&
682 (isRV64Expr() || (isInt<32>(x: Imm) || isUInt<32>(x: Imm)));
683 }
684
685 template <unsigned N> bool isUImm() const {
686 int64_t Imm;
687 if (!isExpr())
688 return false;
689 bool IsConstantImm = evaluateConstantExpr(Expr: getExpr(), Imm);
690 return IsConstantImm && isUInt<N>(Imm);
691 }
692
693 template <unsigned N, unsigned S> bool isUImmShifted() const {
694 int64_t Imm;
695 if (!isExpr())
696 return false;
697 bool IsConstantImm = evaluateConstantExpr(Expr: getExpr(), Imm);
698 return IsConstantImm && isShiftedUInt<N, S>(Imm);
699 }
700
701 template <class Pred> bool isUImmPred(Pred p) const {
702 int64_t Imm;
703 if (!isExpr())
704 return false;
705 bool IsConstantImm = evaluateConstantExpr(Expr: getExpr(), Imm);
706 return IsConstantImm && p(Imm);
707 }
708
709 bool isUImmLog2XLen() const {
710 if (isExpr() && isRV64Expr())
711 return isUImm<6>();
712 return isUImm<5>();
713 }
714
715 bool isUImmLog2XLenNonZero() const {
716 if (isExpr() && isRV64Expr())
717 return isUImmPred(p: [](int64_t Imm) { return Imm != 0 && isUInt<6>(x: Imm); });
718 return isUImmPred(p: [](int64_t Imm) { return Imm != 0 && isUInt<5>(x: Imm); });
719 }
720
721 bool isUImmLog2XLenHalf() const {
722 if (isExpr() && isRV64Expr())
723 return isUImm<5>();
724 return isUImm<4>();
725 }
726
727 bool isUImm1() const { return isUImm<1>(); }
728 bool isUImm2() const { return isUImm<2>(); }
729 bool isUImm3() const { return isUImm<3>(); }
730 bool isUImm4() const { return isUImm<4>(); }
731 bool isUImm5() const { return isUImm<5>(); }
732 bool isUImm6() const { return isUImm<6>(); }
733 bool isUImm7() const { return isUImm<7>(); }
734 bool isUImm8() const { return isUImm<8>(); }
735 bool isUImm9() const { return isUImm<9>(); }
736 bool isUImm10() const { return isUImm<10>(); }
737 bool isUImm11() const { return isUImm<11>(); }
738 bool isUImm16() const { return isUImm<16>(); }
739 bool isUImm20() const { return isUImm<20>(); }
740 bool isUImm32() const { return isUImm<32>(); }
741 bool isUImm48() const { return isUImm<48>(); }
742 bool isUImm64() const { return isUImm<64>(); }
743
744 bool isUImm5NonZero() const {
745 return isUImmPred(p: [](int64_t Imm) { return Imm != 0 && isUInt<5>(x: Imm); });
746 }
747
748 bool isUImm5GT3() const {
749 return isUImmPred(p: [](int64_t Imm) { return isUInt<5>(x: Imm) && Imm > 3; });
750 }
751
752 bool isUImm5Plus1() const {
753 return isUImmPred(
754 p: [](int64_t Imm) { return Imm > 0 && isUInt<5>(x: Imm - 1); });
755 }
756
757 bool isUImm5GE6Plus1() const {
758 return isUImmPred(
759 p: [](int64_t Imm) { return Imm >= 6 && isUInt<5>(x: Imm - 1); });
760 }
761
762 bool isUImm5Slist() const {
763 return isUImmPred(p: [](int64_t Imm) {
764 return (Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
765 (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31);
766 });
767 }
768
769 bool isUImm8GE32() const {
770 return isUImmPred(p: [](int64_t Imm) { return isUInt<8>(x: Imm) && Imm >= 32; });
771 }
772
773 bool isRnumArg() const {
774 return isUImmPred(
775 p: [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(10); });
776 }
777
778 bool isRnumArg_0_7() const {
779 return isUImmPred(
780 p: [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(7); });
781 }
782
783 bool isRnumArg_1_10() const {
784 return isUImmPred(
785 p: [](int64_t Imm) { return Imm >= INT64_C(1) && Imm <= INT64_C(10); });
786 }
787
788 bool isRnumArg_2_14() const {
789 return isUImmPred(
790 p: [](int64_t Imm) { return Imm >= INT64_C(2) && Imm <= INT64_C(14); });
791 }
792
793 template <unsigned N> bool isSImm() const {
794 int64_t Imm;
795 if (!isExpr())
796 return false;
797 bool IsConstantImm = evaluateConstantExpr(Expr: getExpr(), Imm);
798 return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
799 }
800
801 template <class Pred> bool isSImmPred(Pred p) const {
802 int64_t Imm;
803 if (!isExpr())
804 return false;
805 bool IsConstantImm = evaluateConstantExpr(Expr: getExpr(), Imm);
806 return IsConstantImm && p(fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
807 }
808
809 bool isSImm5() const { return isSImm<5>(); }
810 bool isSImm6() const { return isSImm<6>(); }
811 bool isSImm10() const { return isSImm<10>(); }
812 bool isSImm11() const { return isSImm<11>(); }
813 bool isSImm12() const { return isSImm<12>(); }
814 bool isSImm16() const { return isSImm<16>(); }
815 bool isSImm26() const { return isSImm<26>(); }
816
817 bool isSImm5NonZero() const {
818 return isSImmPred(p: [](int64_t Imm) { return Imm != 0 && isInt<5>(x: Imm); });
819 }
820
821 bool isSImm6NonZero() const {
822 return isSImmPred(p: [](int64_t Imm) { return Imm != 0 && isInt<6>(x: Imm); });
823 }
824
825 bool isCLUIImm() const {
826 return isUImmPred(p: [](int64_t Imm) {
827 return (isUInt<5>(x: Imm) && Imm != 0) || (Imm >= 0xfffe0 && Imm <= 0xfffff);
828 });
829 }
830
831 bool isUImm2Lsb0() const { return isUImmShifted<1, 1>(); }
832
833 bool isUImm5Lsb0() const { return isUImmShifted<4, 1>(); }
834
835 bool isUImm6Lsb0() const { return isUImmShifted<5, 1>(); }
836
837 bool isUImm7Lsb00() const { return isUImmShifted<5, 2>(); }
838
839 bool isUImm7Lsb000() const { return isUImmShifted<4, 3>(); }
840
841 bool isUImm8Lsb00() const { return isUImmShifted<6, 2>(); }
842
843 bool isUImm8Lsb000() const { return isUImmShifted<5, 3>(); }
844
845 bool isUImm9Lsb000() const { return isUImmShifted<6, 3>(); }
846
847 bool isUImm14Lsb00() const { return isUImmShifted<12, 2>(); }
848
849 bool isUImm10Lsb00NonZero() const {
850 return isUImmPred(
851 p: [](int64_t Imm) { return isShiftedUInt<8, 2>(x: Imm) && (Imm != 0); });
852 }
853
854 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
855 // This allows writing 'addi a0, a0, 0xffffffff'.
856 static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
857 if (IsRV64Imm || !isUInt<32>(x: Imm))
858 return Imm;
859 return SignExtend64<32>(x: Imm);
860 }
861
862 bool isSImm12LO() const {
863 if (!isExpr())
864 return false;
865
866 int64_t Imm;
867 if (evaluateConstantExpr(Expr: getExpr(), Imm))
868 return isInt<12>(x: fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
869
870 RISCV::Specifier VK = RISCV::S_None;
871 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
872 (VK == RISCV::S_LO || VK == RISCV::S_PCREL_LO ||
873 VK == RISCV::S_TPREL_LO || VK == ELF::R_RISCV_TLSDESC_LOAD_LO12 ||
874 VK == ELF::R_RISCV_TLSDESC_ADD_LO12);
875 }
876
877 bool isSImm12Lsb00000() const {
878 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<7, 5>(x: Imm); });
879 }
880
881 bool isSImm10Lsb0000NonZero() const {
882 return isSImmPred(
883 p: [](int64_t Imm) { return Imm != 0 && isShiftedInt<6, 4>(x: Imm); });
884 }
885
886 bool isSImm16NonZero() const {
887 return isSImmPred(p: [](int64_t Imm) { return Imm != 0 && isInt<16>(x: Imm); });
888 }
889
890 bool isUImm16NonZero() const {
891 return isUImmPred(p: [](int64_t Imm) { return isUInt<16>(x: Imm) && Imm != 0; });
892 }
893
894 bool isSImm20LI() const {
895 if (!isExpr())
896 return false;
897
898 int64_t Imm;
899 if (evaluateConstantExpr(Expr: getExpr(), Imm))
900 return isInt<20>(x: fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
901
902 RISCV::Specifier VK = RISCV::S_None;
903 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
904 VK == RISCV::S_QC_ABS20;
905 }
906
907 bool isSImm8Unsigned() const { return isSImm<8>() || isUImm<8>(); }
908 bool isSImm10Unsigned() const { return isSImm<10>() || isUImm<10>(); }
909
910 bool isSImm10PLI_H() const {
911 return isSImm<10>() || isUImmPred(p: [](int64_t Imm) {
912 return isUInt<16>(x: Imm) && isInt<10>(x: SignExtend64<16>(x: Imm));
913 });
914 }
915 bool isSImm10PLI_W() const {
916 return isSImm<10>() || isUImmPred(p: [](int64_t Imm) {
917 return isUInt<32>(x: Imm) && isInt<10>(x: SignExtend64<32>(x: Imm));
918 });
919 }
920
921 bool isUImm20LUI() const {
922 if (!isExpr())
923 return false;
924
925 int64_t Imm;
926 if (evaluateConstantExpr(Expr: getExpr(), Imm))
927 return isUInt<20>(x: Imm);
928
929 RISCV::Specifier VK = RISCV::S_None;
930 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
931 (VK == ELF::R_RISCV_HI20 || VK == ELF::R_RISCV_TPREL_HI20);
932 }
933
934 bool isUImm20AUIPC() const {
935 if (!isExpr())
936 return false;
937
938 int64_t Imm;
939 if (evaluateConstantExpr(Expr: getExpr(), Imm))
940 return isUInt<20>(x: Imm);
941
942 RISCV::Specifier VK = RISCV::S_None;
943 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: VK) &&
944 (VK == RISCV::S_PCREL_HI || VK == RISCV::S_GOT_HI ||
945 VK == ELF::R_RISCV_TLS_GOT_HI20 || VK == ELF::R_RISCV_TLS_GD_HI20 ||
946 VK == ELF::R_RISCV_TLSDESC_HI20);
947 }
948
949 bool isImmZero() const {
950 return isUImmPred(p: [](int64_t Imm) { return 0 == Imm; });
951 }
952
953 bool isImmThree() const {
954 return isUImmPred(p: [](int64_t Imm) { return 3 == Imm; });
955 }
956
957 bool isImmFour() const {
958 return isUImmPred(p: [](int64_t Imm) { return 4 == Imm; });
959 }
960
961 bool isImm5Zibi() const {
962 return isUImmPred(
963 p: [](int64_t Imm) { return (Imm != 0 && isUInt<5>(x: Imm)) || Imm == -1; });
964 }
965
966 bool isSImm5Plus1() const {
967 return isSImmPred(
968 p: [](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(x: Imm - 1); });
969 }
970
971 bool isSImm18() const {
972 return isSImmPred(p: [](int64_t Imm) { return isInt<18>(x: Imm); });
973 }
974
975 bool isSImm18Lsb0() const {
976 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<17, 1>(x: Imm); });
977 }
978
979 bool isSImm19Lsb00() const {
980 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<17, 2>(x: Imm); });
981 }
982
983 bool isSImm20Lsb000() const {
984 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<17, 3>(x: Imm); });
985 }
986
987 bool isSImm32Lsb0() const {
988 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<31, 1>(x: Imm); });
989 }
990
991 /// getStartLoc - Gets location of the first token of this operand
992 SMLoc getStartLoc() const override { return StartLoc; }
993 /// getEndLoc - Gets location of the last token of this operand
994 SMLoc getEndLoc() const override { return EndLoc; }
995
996 /// True if this operand is for an RV64 instruction
997 bool isRV64Expr() const {
998 assert(Kind == KindTy::Expression && "Invalid type access!");
999 return Expr.IsRV64;
1000 }
1001
1002 MCRegister getReg() const override {
1003 assert(Kind == KindTy::Register && "Invalid type access!");
1004 return Reg.Reg;
1005 }
1006
1007 StringRef getSysReg() const {
1008 assert(Kind == KindTy::SystemRegister && "Invalid type access!");
1009 return StringRef(SysReg.Data, SysReg.Length);
1010 }
1011
1012 const MCExpr *getExpr() const {
1013 assert(Kind == KindTy::Expression && "Invalid type access!");
1014 return Expr.Expr;
1015 }
1016
1017 uint64_t getFPConst() const {
1018 assert(Kind == KindTy::FPImmediate && "Invalid type access!");
1019 return FPImm.Val;
1020 }
1021
1022 StringRef getToken() const {
1023 assert(Kind == KindTy::Token && "Invalid type access!");
1024 return Tok;
1025 }
1026
1027 unsigned getVType() const {
1028 assert(Kind == KindTy::VType && "Invalid type access!");
1029 return VType.Val;
1030 }
1031
1032 RISCVFPRndMode::RoundingMode getFRM() const {
1033 assert(Kind == KindTy::FRM && "Invalid type access!");
1034 return FRM.FRM;
1035 }
1036
1037 unsigned getFence() const {
1038 assert(Kind == KindTy::Fence && "Invalid type access!");
1039 return Fence.Val;
1040 }
1041
1042 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
1043 auto RegName = [](MCRegister Reg) {
1044 if (Reg)
1045 return RISCVInstPrinter::getRegisterName(Reg);
1046 else
1047 return "noreg";
1048 };
1049
1050 switch (Kind) {
1051 case KindTy::Expression:
1052 OS << "<imm: ";
1053 MAI.printExpr(OS, *Expr.Expr);
1054 OS << ' ' << (Expr.IsRV64 ? "rv64" : "rv32") << '>';
1055 break;
1056 case KindTy::FPImmediate:
1057 OS << "<fpimm: " << FPImm.Val << ">";
1058 break;
1059 case KindTy::Register:
1060 OS << "<reg: " << RegName(Reg.Reg) << " (" << Reg.Reg.id()
1061 << (Reg.IsGPRAsFPR ? ") GPRasFPR>" : ")>");
1062 break;
1063 case KindTy::Token:
1064 OS << "'" << getToken() << "'";
1065 break;
1066 case KindTy::SystemRegister:
1067 OS << "<sysreg: " << getSysReg() << " (" << SysReg.Encoding << ")>";
1068 break;
1069 case KindTy::VType:
1070 OS << "<vtype: ";
1071 RISCVVType::printVType(VType: getVType(), OS);
1072 OS << '>';
1073 break;
1074 case KindTy::FRM:
1075 OS << "<frm: ";
1076 roundingModeToString(RndMode: getFRM());
1077 OS << '>';
1078 break;
1079 case KindTy::Fence:
1080 OS << "<fence: ";
1081 OS << getFence();
1082 OS << '>';
1083 break;
1084 case KindTy::RegList:
1085 OS << "<reglist: ";
1086 RISCVZC::printRegList(RlistEncode: RegList.Encoding, OS);
1087 OS << '>';
1088 break;
1089 case KindTy::StackAdj:
1090 OS << "<stackadj: ";
1091 OS << StackAdj.Val;
1092 OS << '>';
1093 break;
1094 case KindTy::RegReg:
1095 OS << "<RegReg: BaseReg " << RegName(RegReg.BaseReg) << " OffsetReg "
1096 << RegName(RegReg.OffsetReg);
1097 break;
1098 }
1099 }
1100
1101 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
1102 auto Op = std::make_unique<RISCVOperand>(args: KindTy::Token);
1103 Op->Tok = Str;
1104 Op->StartLoc = S;
1105 Op->EndLoc = S;
1106 return Op;
1107 }
1108
1109 static std::unique_ptr<RISCVOperand>
1110 createReg(MCRegister Reg, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
1111 auto Op = std::make_unique<RISCVOperand>(args: KindTy::Register);
1112 Op->Reg.Reg = Reg;
1113 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1114 Op->StartLoc = S;
1115 Op->EndLoc = E;
1116 return Op;
1117 }
1118
1119 static std::unique_ptr<RISCVOperand> createExpr(const MCExpr *Val, SMLoc S,
1120 SMLoc E, bool IsRV64) {
1121 auto Op = std::make_unique<RISCVOperand>(args: KindTy::Expression);
1122 Op->Expr.Expr = Val;
1123 Op->Expr.IsRV64 = IsRV64;
1124 Op->StartLoc = S;
1125 Op->EndLoc = E;
1126 return Op;
1127 }
1128
1129 static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {
1130 auto Op = std::make_unique<RISCVOperand>(args: KindTy::FPImmediate);
1131 Op->FPImm.Val = Val;
1132 Op->StartLoc = S;
1133 Op->EndLoc = S;
1134 return Op;
1135 }
1136
1137 static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,
1138 unsigned Encoding) {
1139 auto Op = std::make_unique<RISCVOperand>(args: KindTy::SystemRegister);
1140 Op->SysReg.Data = Str.data();
1141 Op->SysReg.Length = Str.size();
1142 Op->SysReg.Encoding = Encoding;
1143 Op->StartLoc = S;
1144 Op->EndLoc = S;
1145 return Op;
1146 }
1147
1148 static std::unique_ptr<RISCVOperand>
1149 createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {
1150 auto Op = std::make_unique<RISCVOperand>(args: KindTy::FRM);
1151 Op->FRM.FRM = FRM;
1152 Op->StartLoc = S;
1153 Op->EndLoc = S;
1154 return Op;
1155 }
1156
1157 static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {
1158 auto Op = std::make_unique<RISCVOperand>(args: KindTy::Fence);
1159 Op->Fence.Val = Val;
1160 Op->StartLoc = S;
1161 Op->EndLoc = S;
1162 return Op;
1163 }
1164
1165 static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {
1166 auto Op = std::make_unique<RISCVOperand>(args: KindTy::VType);
1167 Op->VType.Val = VTypeI;
1168 Op->StartLoc = S;
1169 Op->EndLoc = S;
1170 return Op;
1171 }
1172
1173 static std::unique_ptr<RISCVOperand> createRegList(unsigned RlistEncode,
1174 SMLoc S) {
1175 auto Op = std::make_unique<RISCVOperand>(args: KindTy::RegList);
1176 Op->RegList.Encoding = RlistEncode;
1177 Op->StartLoc = S;
1178 return Op;
1179 }
1180
1181 static std::unique_ptr<RISCVOperand>
1182 createRegReg(MCRegister BaseReg, MCRegister OffsetReg, SMLoc S) {
1183 auto Op = std::make_unique<RISCVOperand>(args: KindTy::RegReg);
1184 Op->RegReg.BaseReg = BaseReg;
1185 Op->RegReg.OffsetReg = OffsetReg;
1186 Op->StartLoc = S;
1187 Op->EndLoc = S;
1188 return Op;
1189 }
1190
1191 static std::unique_ptr<RISCVOperand> createStackAdj(unsigned StackAdj, SMLoc S) {
1192 auto Op = std::make_unique<RISCVOperand>(args: KindTy::StackAdj);
1193 Op->StackAdj.Val = StackAdj;
1194 Op->StartLoc = S;
1195 return Op;
1196 }
1197
1198 static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
1199 assert(Expr && "Expr shouldn't be null!");
1200 int64_t Imm = 0;
1201 bool IsConstant = evaluateConstantExpr(Expr, Imm);
1202
1203 if (IsConstant)
1204 Inst.addOperand(
1205 Op: MCOperand::createImm(Val: fixImmediateForRV32(Imm, IsRV64Imm)));
1206 else
1207 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
1208 }
1209
1210 // Used by the TableGen Code
1211 void addRegOperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 1 && "Invalid number of operands!");
1213 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
1214 }
1215
1216 void addImmOperands(MCInst &Inst, unsigned N) const {
1217 assert(N == 1 && "Invalid number of operands!");
1218 addExpr(Inst, Expr: getExpr(), IsRV64Imm: isRV64Expr());
1219 }
1220
1221 void addSImm8UnsignedOperands(MCInst &Inst, unsigned N) const {
1222 assert(N == 1 && "Invalid number of operands!");
1223 int64_t Imm;
1224 [[maybe_unused]] bool IsConstant = evaluateConstantExpr(Expr: getExpr(), Imm);
1225 assert(IsConstant);
1226 Inst.addOperand(Op: MCOperand::createImm(Val: SignExtend64<8>(x: Imm)));
1227 }
1228
1229 void addSImm10UnsignedOperands(MCInst &Inst, unsigned N) const {
1230 assert(N == 1 && "Invalid number of operands!");
1231 int64_t Imm;
1232 [[maybe_unused]] bool IsConstant = evaluateConstantExpr(Expr: getExpr(), Imm);
1233 assert(IsConstant);
1234 Inst.addOperand(Op: MCOperand::createImm(Val: SignExtend64<10>(x: Imm)));
1235 }
1236
1237 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1238 assert(N == 1 && "Invalid number of operands!");
1239 if (isExpr()) {
1240 addExpr(Inst, Expr: getExpr(), IsRV64Imm: isRV64Expr());
1241 return;
1242 }
1243
1244 int Imm = RISCVLoadFPImm::getLoadFPImm(
1245 FPImm: APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1246 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
1247 }
1248
1249 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
1251 Inst.addOperand(Op: MCOperand::createImm(Val: Fence.Val));
1252 }
1253
1254 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
1256 Inst.addOperand(Op: MCOperand::createImm(Val: SysReg.Encoding));
1257 }
1258
1259 // Support non-canonical syntax:
1260 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
1261 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
1262 void addVTypeIOperands(MCInst &Inst, unsigned N) const {
1263 assert(N == 1 && "Invalid number of operands!");
1264 int64_t Imm = 0;
1265 if (Kind == KindTy::Expression) {
1266 [[maybe_unused]] bool IsConstantImm =
1267 evaluateConstantExpr(Expr: getExpr(), Imm);
1268 assert(IsConstantImm && "Invalid VTypeI Operand!");
1269 } else {
1270 Imm = getVType();
1271 }
1272 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
1273 }
1274
1275 void addRegListOperands(MCInst &Inst, unsigned N) const {
1276 assert(N == 1 && "Invalid number of operands!");
1277 Inst.addOperand(Op: MCOperand::createImm(Val: RegList.Encoding));
1278 }
1279
1280 void addRegRegOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 2 && "Invalid number of operands!");
1282 Inst.addOperand(Op: MCOperand::createReg(Reg: RegReg.BaseReg));
1283 Inst.addOperand(Op: MCOperand::createReg(Reg: RegReg.OffsetReg));
1284 }
1285
1286 void addStackAdjOperands(MCInst &Inst, unsigned N) const {
1287 assert(N == 1 && "Invalid number of operands!");
1288 Inst.addOperand(Op: MCOperand::createImm(Val: StackAdj.Val));
1289 }
1290
1291 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
1292 assert(N == 1 && "Invalid number of operands!");
1293 Inst.addOperand(Op: MCOperand::createImm(Val: getFRM()));
1294 }
1295};
1296} // end anonymous namespace.
1297
1298#define GET_REGISTER_MATCHER
1299#define GET_SUBTARGET_FEATURE_NAME
1300#define GET_MATCHER_IMPLEMENTATION
1301#define GET_MNEMONIC_SPELL_CHECKER
1302#include "RISCVGenAsmMatcher.inc"
1303
1304static MCRegister convertFPR64ToFPR16(MCRegister Reg) {
1305 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1306 return Reg - RISCV::F0_D + RISCV::F0_H;
1307}
1308
1309static MCRegister convertFPR64ToFPR32(MCRegister Reg) {
1310 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1311 return Reg - RISCV::F0_D + RISCV::F0_F;
1312}
1313
1314static MCRegister convertFPR64ToFPR128(MCRegister Reg) {
1315 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1316 return Reg - RISCV::F0_D + RISCV::F0_Q;
1317}
1318
1319static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
1320 unsigned Kind) {
1321 unsigned RegClassID;
1322 if (Kind == MCK_VRM2)
1323 RegClassID = RISCV::VRM2RegClassID;
1324 else if (Kind == MCK_VRM4)
1325 RegClassID = RISCV::VRM4RegClassID;
1326 else if (Kind == MCK_VRM8)
1327 RegClassID = RISCV::VRM8RegClassID;
1328 else
1329 return MCRegister();
1330 return RI.getMatchingSuperReg(Reg, SubIdx: RISCV::sub_vrm1_0,
1331 RC: &RISCVMCRegisterClasses[RegClassID]);
1332}
1333
1334static MCRegister convertFPR64ToFPR256(MCRegister Reg) {
1335 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1336 return Reg - RISCV::F0_D + RISCV::F0_Q2;
1337}
1338
1339unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1340 unsigned Kind) {
1341 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
1342 if (!Op.isReg())
1343 return Match_InvalidOperand;
1344
1345 MCRegister Reg = Op.getReg();
1346 bool IsRegFPR64 =
1347 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
1348 bool IsRegFPR64C =
1349 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1350 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1351
1352 if (IsRegFPR64 && Kind == MCK_FPR256) {
1353 Op.Reg.Reg = convertFPR64ToFPR256(Reg);
1354 return Match_Success;
1355 }
1356 if (IsRegFPR64 && Kind == MCK_FPR128) {
1357 Op.Reg.Reg = convertFPR64ToFPR128(Reg);
1358 return Match_Success;
1359 }
1360 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1361 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1362 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1363 (IsRegFPR64C && Kind == MCK_FPR32C)) {
1364 Op.Reg.Reg = convertFPR64ToFPR32(Reg);
1365 return Match_Success;
1366 }
1367 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1368 // register from FPR64 to FPR16 if necessary.
1369 if (IsRegFPR64 && Kind == MCK_FPR16) {
1370 Op.Reg.Reg = convertFPR64ToFPR16(Reg);
1371 return Match_Success;
1372 }
1373 if (Kind == MCK_GPRAsFPR16 && Op.isGPRAsFPR()) {
1374 Op.Reg.Reg = Reg - RISCV::X0 + RISCV::X0_H;
1375 return Match_Success;
1376 }
1377 if (Kind == MCK_GPRAsFPR32 && Op.isGPRAsFPR()) {
1378 Op.Reg.Reg = Reg - RISCV::X0 + RISCV::X0_W;
1379 return Match_Success;
1380 }
1381
1382 // There are some GPRF64AsFPR instructions that have no RV32 equivalent. We
1383 // reject them at parsing thinking we should match as GPRPairAsFPR for RV32.
1384 // So we explicitly accept them here for RV32 to allow the generic code to
1385 // report that the instruction requires RV64.
1386 if (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg) &&
1387 Kind == MCK_GPRF64AsFPR && STI->hasFeature(Feature: RISCV::FeatureStdExtZdinx) &&
1388 !isRV64())
1389 return Match_Success;
1390
1391 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1392 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1393 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1394 Op.Reg.Reg = convertVRToVRMx(RI: *getContext().getRegisterInfo(), Reg, Kind);
1395 if (!Op.Reg.Reg)
1396 return Match_InvalidOperand;
1397 return Match_Success;
1398 }
1399 return Match_InvalidOperand;
1400}
1401
1402bool RISCVAsmParser::generateImmOutOfRangeError(
1403 SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
1404 const Twine &Msg = "immediate must be an integer in the range") {
1405 return Error(L: ErrorLoc, Msg: Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1406}
1407
1408bool RISCVAsmParser::generateImmOutOfRangeError(
1409 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1410 const Twine &Msg = "immediate must be an integer in the range") {
1411 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1412 return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg);
1413}
1414
1415bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1416 OperandVector &Operands,
1417 MCStreamer &Out,
1418 uint64_t &ErrorInfo,
1419 bool MatchingInlineAsm) {
1420 MCInst Inst;
1421 FeatureBitset MissingFeatures;
1422
1423 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1424 matchingInlineAsm: MatchingInlineAsm);
1425 switch (Result) {
1426 default:
1427 break;
1428 case Match_Success:
1429 if (validateInstruction(Inst, Operands))
1430 return true;
1431 return processInstruction(Inst, IDLoc, Operands, Out);
1432 case Match_MissingFeature: {
1433 assert(MissingFeatures.any() && "Unknown missing features!");
1434 bool FirstFeature = true;
1435 std::string Msg = "instruction requires the following:";
1436 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1437 if (MissingFeatures[i]) {
1438 Msg += FirstFeature ? " " : ", ";
1439 Msg += getSubtargetFeatureName(Val: i);
1440 FirstFeature = false;
1441 }
1442 }
1443 return Error(L: IDLoc, Msg);
1444 }
1445 case Match_MnemonicFail: {
1446 FeatureBitset FBS = ComputeAvailableFeatures(FB: getSTI().getFeatureBits());
1447 std::string Suggestion = RISCVMnemonicSpellCheck(
1448 S: ((RISCVOperand &)*Operands[0]).getToken(), FBS, VariantID: 0);
1449 return Error(L: IDLoc, Msg: "unrecognized instruction mnemonic" + Suggestion);
1450 }
1451 case Match_InvalidOperand: {
1452 SMLoc ErrorLoc = IDLoc;
1453 if (ErrorInfo != ~0ULL) {
1454 if (ErrorInfo >= Operands.size())
1455 return Error(L: ErrorLoc, Msg: "too few operands for instruction");
1456
1457 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1458 if (ErrorLoc == SMLoc())
1459 ErrorLoc = IDLoc;
1460 }
1461 return Error(L: ErrorLoc, Msg: "invalid operand for instruction");
1462 }
1463 }
1464
1465 // Handle the case when the error message is of specific type
1466 // other than the generic Match_InvalidOperand, and the
1467 // corresponding operand is missing.
1468 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1469 SMLoc ErrorLoc = IDLoc;
1470 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1471 return Error(L: ErrorLoc, Msg: "too few operands for instruction");
1472 }
1473
1474 switch (Result) {
1475 default:
1476 break;
1477 case Match_InvalidImmXLenLI:
1478 if (isRV64()) {
1479 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1480 return Error(L: ErrorLoc, Msg: "operand must be a constant 64-bit integer");
1481 }
1482 return generateImmOutOfRangeError(Operands, ErrorInfo,
1483 Lower: std::numeric_limits<int32_t>::min(),
1484 Upper: std::numeric_limits<uint32_t>::max());
1485 case Match_InvalidImmXLenLI_Restricted:
1486 if (isRV64()) {
1487 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1488 return Error(L: ErrorLoc, Msg: "operand either must be a constant 64-bit integer "
1489 "or a bare symbol name");
1490 }
1491 return generateImmOutOfRangeError(
1492 Operands, ErrorInfo, Lower: std::numeric_limits<int32_t>::min(),
1493 Upper: std::numeric_limits<uint32_t>::max(),
1494 Msg: "operand either must be a bare symbol name or an immediate integer in "
1495 "the range");
1496 case Match_InvalidUImmLog2XLen:
1497 if (isRV64())
1498 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 6) - 1);
1499 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 5) - 1);
1500 case Match_InvalidUImmLog2XLenNonZero:
1501 if (isRV64())
1502 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 1, Upper: (1 << 6) - 1);
1503 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 1, Upper: (1 << 5) - 1);
1504 case Match_InvalidUImm1:
1505 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 1) - 1);
1506 case Match_InvalidUImm2:
1507 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 2) - 1);
1508 case Match_InvalidUImm2Lsb0:
1509 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: 2,
1510 Msg: "immediate must be one of");
1511 case Match_InvalidUImm3:
1512 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 3) - 1);
1513 case Match_InvalidUImm4:
1514 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 4) - 1);
1515 case Match_InvalidUImm5:
1516 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 5) - 1);
1517 case Match_InvalidUImm5NonZero:
1518 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 1, Upper: (1 << 5) - 1);
1519 case Match_InvalidUImm5GT3:
1520 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 4, Upper: (1 << 5) - 1);
1521 case Match_InvalidUImm5Plus1:
1522 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 1, Upper: (1 << 5));
1523 case Match_InvalidUImm5GE6Plus1:
1524 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 6, Upper: (1 << 5));
1525 case Match_InvalidUImm5Slist: {
1526 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1527 return Error(L: ErrorLoc,
1528 Msg: "immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31");
1529 }
1530 case Match_InvalidUImm6:
1531 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 6) - 1);
1532 case Match_InvalidUImm7:
1533 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 7) - 1);
1534 case Match_InvalidUImm8:
1535 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 8) - 1);
1536 case Match_InvalidUImm8GE32:
1537 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 32, Upper: (1 << 8) - 1);
1538 case Match_InvalidSImm5:
1539 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 4),
1540 Upper: (1 << 4) - 1);
1541 case Match_InvalidSImm5NonZero:
1542 return generateImmOutOfRangeError(
1543 Operands, ErrorInfo, Lower: -(1 << 4), Upper: (1 << 4) - 1,
1544 Msg: "immediate must be non-zero in the range");
1545 case Match_InvalidSImm6:
1546 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 5),
1547 Upper: (1 << 5) - 1);
1548 case Match_InvalidSImm6NonZero:
1549 return generateImmOutOfRangeError(
1550 Operands, ErrorInfo, Lower: -(1 << 5), Upper: (1 << 5) - 1,
1551 Msg: "immediate must be non-zero in the range");
1552 case Match_InvalidCLUIImm:
1553 return generateImmOutOfRangeError(
1554 Operands, ErrorInfo, Lower: 1, Upper: (1 << 5) - 1,
1555 Msg: "immediate must be in [0xfffe0, 0xfffff] or");
1556 case Match_InvalidUImm5Lsb0:
1557 return generateImmOutOfRangeError(
1558 Operands, ErrorInfo, Lower: 0, Upper: (1 << 5) - 2,
1559 Msg: "immediate must be a multiple of 2 bytes in the range");
1560 case Match_InvalidUImm6Lsb0:
1561 return generateImmOutOfRangeError(
1562 Operands, ErrorInfo, Lower: 0, Upper: (1 << 6) - 2,
1563 Msg: "immediate must be a multiple of 2 bytes in the range");
1564 case Match_InvalidUImm7Lsb00:
1565 return generateImmOutOfRangeError(
1566 Operands, ErrorInfo, Lower: 0, Upper: (1 << 7) - 4,
1567 Msg: "immediate must be a multiple of 4 bytes in the range");
1568 case Match_InvalidUImm8Lsb00:
1569 return generateImmOutOfRangeError(
1570 Operands, ErrorInfo, Lower: 0, Upper: (1 << 8) - 4,
1571 Msg: "immediate must be a multiple of 4 bytes in the range");
1572 case Match_InvalidUImm8Lsb000:
1573 return generateImmOutOfRangeError(
1574 Operands, ErrorInfo, Lower: 0, Upper: (1 << 8) - 8,
1575 Msg: "immediate must be a multiple of 8 bytes in the range");
1576 case Match_InvalidUImm9:
1577 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 9) - 1,
1578 Msg: "immediate offset must be in the range");
1579 case Match_InvalidBareSImm9Lsb0:
1580 return generateImmOutOfRangeError(
1581 Operands, ErrorInfo, Lower: -(1 << 8), Upper: (1 << 8) - 2,
1582 Msg: "immediate must be a multiple of 2 bytes in the range");
1583 case Match_InvalidUImm9Lsb000:
1584 return generateImmOutOfRangeError(
1585 Operands, ErrorInfo, Lower: 0, Upper: (1 << 9) - 8,
1586 Msg: "immediate must be a multiple of 8 bytes in the range");
1587 case Match_InvalidSImm8Unsigned:
1588 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 7),
1589 Upper: (1 << 8) - 1);
1590 case Match_InvalidSImm10:
1591 case Match_InvalidSImm10PLI_H:
1592 case Match_InvalidSImm10PLI_W:
1593 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 9),
1594 Upper: (1 << 9) - 1);
1595 case Match_InvalidSImm10Unsigned:
1596 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 9),
1597 Upper: (1 << 10) - 1);
1598 case Match_InvalidUImm10Lsb00NonZero:
1599 return generateImmOutOfRangeError(
1600 Operands, ErrorInfo, Lower: 4, Upper: (1 << 10) - 4,
1601 Msg: "immediate must be a multiple of 4 bytes in the range");
1602 case Match_InvalidSImm10Lsb0000NonZero:
1603 return generateImmOutOfRangeError(
1604 Operands, ErrorInfo, Lower: -(1 << 9), Upper: (1 << 9) - 16,
1605 Msg: "immediate must be a multiple of 16 bytes and non-zero in the range");
1606 case Match_InvalidSImm11:
1607 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 10),
1608 Upper: (1 << 10) - 1);
1609 case Match_InvalidBareSImm11Lsb0:
1610 return generateImmOutOfRangeError(
1611 Operands, ErrorInfo, Lower: -(1 << 10), Upper: (1 << 10) - 2,
1612 Msg: "immediate must be a multiple of 2 bytes in the range");
1613 case Match_InvalidUImm10:
1614 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 10) - 1);
1615 case Match_InvalidUImm11:
1616 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 11) - 1);
1617 case Match_InvalidUImm14Lsb00:
1618 return generateImmOutOfRangeError(
1619 Operands, ErrorInfo, Lower: 0, Upper: (1 << 14) - 4,
1620 Msg: "immediate must be a multiple of 4 bytes in the range");
1621 case Match_InvalidUImm16NonZero:
1622 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 1, Upper: (1 << 16) - 1);
1623 case Match_InvalidSImm12:
1624 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 11),
1625 Upper: (1 << 11) - 1);
1626 case Match_InvalidSImm12LO:
1627 return generateImmOutOfRangeError(
1628 Operands, ErrorInfo, Lower: -(1 << 11), Upper: (1 << 11) - 1,
1629 Msg: "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo specifier or an "
1630 "integer in the range");
1631 case Match_InvalidBareSImm12Lsb0:
1632 return generateImmOutOfRangeError(
1633 Operands, ErrorInfo, Lower: -(1 << 11), Upper: (1 << 11) - 2,
1634 Msg: "immediate must be a multiple of 2 bytes in the range");
1635 case Match_InvalidSImm12Lsb00000:
1636 return generateImmOutOfRangeError(
1637 Operands, ErrorInfo, Lower: -(1 << 11), Upper: (1 << 11) - 32,
1638 Msg: "immediate must be a multiple of 32 bytes in the range");
1639 case Match_InvalidBareSImm13Lsb0:
1640 return generateImmOutOfRangeError(
1641 Operands, ErrorInfo, Lower: -(1 << 12), Upper: (1 << 12) - 2,
1642 Msg: "immediate must be a multiple of 2 bytes in the range");
1643 case Match_InvalidSImm16:
1644 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 15),
1645 Upper: (1 << 15) - 1);
1646 case Match_InvalidSImm16NonZero:
1647 return generateImmOutOfRangeError(
1648 Operands, ErrorInfo, Lower: -(1 << 15), Upper: (1 << 15) - 1,
1649 Msg: "immediate must be non-zero in the range");
1650 case Match_InvalidSImm20LI:
1651 return generateImmOutOfRangeError(
1652 Operands, ErrorInfo, Lower: -(1 << 19), Upper: (1 << 19) - 1,
1653 Msg: "operand must be a symbol with a %qc.abs20 specifier or an integer "
1654 " in the range");
1655 case Match_InvalidUImm20LUI:
1656 return generateImmOutOfRangeError(
1657 Operands, ErrorInfo, Lower: 0, Upper: (1 << 20) - 1,
1658 Msg: "operand must be a symbol with "
1659 "%hi/%tprel_hi specifier or an integer in "
1660 "the range");
1661 case Match_InvalidUImm20:
1662 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 20) - 1);
1663 case Match_InvalidUImm20AUIPC:
1664 return generateImmOutOfRangeError(
1665 Operands, ErrorInfo, Lower: 0, Upper: (1 << 20) - 1,
1666 Msg: "operand must be a symbol with a "
1667 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi specifier "
1668 "or "
1669 "an integer in the range");
1670 case Match_InvalidBareSImm21Lsb0:
1671 return generateImmOutOfRangeError(
1672 Operands, ErrorInfo, Lower: -(1 << 20), Upper: (1 << 20) - 2,
1673 Msg: "immediate must be a multiple of 2 bytes in the range");
1674 case Match_InvalidCSRSystemRegister: {
1675 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: (1 << 12) - 1,
1676 Msg: "operand must be a valid system register "
1677 "name or an integer in the range");
1678 }
1679 case Match_InvalidImm5Zibi:
1680 return generateImmOutOfRangeError(
1681 Operands, ErrorInfo, Lower: -1, Upper: (1 << 5) - 1,
1682 Msg: "immediate must be non-zero in the range");
1683 case Match_InvalidVTypeI: {
1684 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1685 return generateVTypeError(ErrorLoc);
1686 }
1687 case Match_InvalidSImm5Plus1: {
1688 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 4) + 1,
1689 Upper: (1 << 4),
1690 Msg: "immediate must be in the range");
1691 }
1692 case Match_InvalidSImm18:
1693 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 17),
1694 Upper: (1 << 17) - 1);
1695 case Match_InvalidSImm18Lsb0:
1696 return generateImmOutOfRangeError(
1697 Operands, ErrorInfo, Lower: -(1 << 17), Upper: (1 << 17) - 2,
1698 Msg: "immediate must be a multiple of 2 bytes in the range");
1699 case Match_InvalidSImm19Lsb00:
1700 return generateImmOutOfRangeError(
1701 Operands, ErrorInfo, Lower: -(1 << 18), Upper: (1 << 18) - 4,
1702 Msg: "immediate must be a multiple of 4 bytes in the range");
1703 case Match_InvalidSImm20Lsb000:
1704 return generateImmOutOfRangeError(
1705 Operands, ErrorInfo, Lower: -(1 << 19), Upper: (1 << 19) - 8,
1706 Msg: "immediate must be a multiple of 8 bytes in the range");
1707 case Match_InvalidSImm26:
1708 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: -(1 << 25),
1709 Upper: (1 << 25) - 1);
1710 // HACK: See comment before `BareSymbolQC_E_LI` in RISCVInstrInfoXqci.td.
1711 case Match_InvalidBareSymbolQC_E_LI:
1712 [[fallthrough]];
1713 // END HACK
1714 case Match_InvalidBareSImm32:
1715 return generateImmOutOfRangeError(Operands, ErrorInfo,
1716 Lower: std::numeric_limits<int32_t>::min(),
1717 Upper: std::numeric_limits<uint32_t>::max());
1718 case Match_InvalidBareSImm32Lsb0:
1719 return generateImmOutOfRangeError(
1720 Operands, ErrorInfo, Lower: std::numeric_limits<int32_t>::min(),
1721 Upper: std::numeric_limits<int32_t>::max() - 1,
1722 Msg: "operand must be a multiple of 2 bytes in the range");
1723 case Match_InvalidRnumArg: {
1724 return generateImmOutOfRangeError(Operands, ErrorInfo, Lower: 0, Upper: 10);
1725 }
1726 case Match_InvalidStackAdj: {
1727 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1728 return Error(
1729 L: ErrorLoc,
1730 Msg: "stack adjustment is invalid for this instruction and register list");
1731 }
1732 }
1733
1734 if (const char *MatchDiag = getMatchKindDiag(MatchResult: (RISCVMatchResultTy)Result)) {
1735 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1736 return Error(L: ErrorLoc, Msg: MatchDiag);
1737 }
1738
1739 llvm_unreachable("Unknown match type detected!");
1740}
1741
1742// Attempts to match Name as a register (either using the default name or
1743// alternative ABI names), returning the matching register. Upon failure,
1744// returns a non-valid MCRegister. If IsRVE, then registers x16-x31 will be
1745// rejected.
1746MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {
1747 MCRegister Reg = MatchRegisterName(Name);
1748 // The 16-/32-/128- and 64-bit FPRs have the same asm name. Check
1749 // that the initial match always matches the 64-bit variant, and
1750 // not the 16/32/128-bit one.
1751 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
1752 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
1753 assert(!(Reg >= RISCV::F0_Q && Reg <= RISCV::F31_Q));
1754 // The default FPR register class is based on the tablegen enum ordering.
1755 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1756 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1757 static_assert(RISCV::F0_D < RISCV::F0_Q, "FPR matching must be updated");
1758 if (!Reg)
1759 Reg = MatchRegisterAltName(Name);
1760 if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1761 Reg = MCRegister();
1762 return Reg;
1763}
1764
1765bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1766 SMLoc &EndLoc) {
1767 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
1768 return Error(L: StartLoc, Msg: "invalid register name");
1769 return false;
1770}
1771
1772ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1773 SMLoc &EndLoc) {
1774 const AsmToken &Tok = getParser().getTok();
1775 StartLoc = Tok.getLoc();
1776 EndLoc = Tok.getEndLoc();
1777 StringRef Name = getLexer().getTok().getIdentifier();
1778
1779 Reg = matchRegisterNameHelper(Name);
1780 if (!Reg)
1781 return ParseStatus::NoMatch;
1782
1783 getParser().Lex(); // Eat identifier token.
1784 return ParseStatus::Success;
1785}
1786
1787ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
1788 bool AllowParens) {
1789 SMLoc FirstS = getLoc();
1790 bool HadParens = false;
1791 AsmToken LParen;
1792
1793 // If this is an LParen and a parenthesised register name is allowed, parse it
1794 // atomically.
1795 if (AllowParens && getLexer().is(K: AsmToken::LParen)) {
1796 AsmToken Buf[2];
1797 size_t ReadCount = getLexer().peekTokens(Buf);
1798 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1799 HadParens = true;
1800 LParen = getParser().getTok();
1801 getParser().Lex(); // Eat '('
1802 }
1803 }
1804
1805 switch (getLexer().getKind()) {
1806 default:
1807 if (HadParens)
1808 getLexer().UnLex(Token: LParen);
1809 return ParseStatus::NoMatch;
1810 case AsmToken::Identifier:
1811 StringRef Name = getLexer().getTok().getIdentifier();
1812 MCRegister Reg = matchRegisterNameHelper(Name);
1813
1814 if (!Reg) {
1815 if (HadParens)
1816 getLexer().UnLex(Token: LParen);
1817 return ParseStatus::NoMatch;
1818 }
1819 if (HadParens)
1820 Operands.push_back(Elt: RISCVOperand::createToken(Str: "(", S: FirstS));
1821 SMLoc S = getLoc();
1822 SMLoc E = getTok().getEndLoc();
1823 getLexer().Lex();
1824 Operands.push_back(Elt: RISCVOperand::createReg(Reg, S, E));
1825 }
1826
1827 if (HadParens) {
1828 getParser().Lex(); // Eat ')'
1829 Operands.push_back(Elt: RISCVOperand::createToken(Str: ")", S: getLoc()));
1830 }
1831
1832 return ParseStatus::Success;
1833}
1834
1835ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1836 SMLoc S = getLoc();
1837 SMLoc E;
1838 const MCExpr *Res;
1839
1840 switch (getLexer().getKind()) {
1841 default:
1842 return ParseStatus::NoMatch;
1843 case AsmToken::LParen:
1844 case AsmToken::Minus:
1845 case AsmToken::Plus:
1846 case AsmToken::Exclaim:
1847 case AsmToken::Tilde:
1848 case AsmToken::Integer:
1849 case AsmToken::String: {
1850 if (getParser().parseExpression(Res, EndLoc&: E))
1851 return ParseStatus::Failure;
1852
1853 auto *CE = dyn_cast<MCConstantExpr>(Val: Res);
1854 if (CE) {
1855 int64_t Imm = CE->getValue();
1856 if (isUInt<7>(x: Imm)) {
1857 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
1858 return ParseStatus::Success;
1859 }
1860 }
1861
1862 break;
1863 }
1864 case AsmToken::Identifier: {
1865 StringRef Identifier;
1866 if (getParser().parseIdentifier(Res&: Identifier))
1867 return ParseStatus::Failure;
1868
1869 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Name: Identifier);
1870 if (Opcode) {
1871 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1872 "Unexpected opcode");
1873 Res = MCConstantExpr::create(Value: Opcode->Value, Ctx&: getContext());
1874 E = SMLoc::getFromPointer(Ptr: S.getPointer() + Identifier.size());
1875 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
1876 return ParseStatus::Success;
1877 }
1878
1879 break;
1880 }
1881 case AsmToken::Percent:
1882 break;
1883 }
1884
1885 return generateImmOutOfRangeError(
1886 ErrorLoc: S, Lower: 0, Upper: 127,
1887 Msg: "opcode must be a valid opcode name or an immediate in the range");
1888}
1889
1890ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
1891 SMLoc S = getLoc();
1892 SMLoc E;
1893 const MCExpr *Res;
1894
1895 switch (getLexer().getKind()) {
1896 default:
1897 return ParseStatus::NoMatch;
1898 case AsmToken::LParen:
1899 case AsmToken::Minus:
1900 case AsmToken::Plus:
1901 case AsmToken::Exclaim:
1902 case AsmToken::Tilde:
1903 case AsmToken::Integer:
1904 case AsmToken::String: {
1905 if (getParser().parseExpression(Res, EndLoc&: E))
1906 return ParseStatus::Failure;
1907
1908 auto *CE = dyn_cast<MCConstantExpr>(Val: Res);
1909 if (CE) {
1910 int64_t Imm = CE->getValue();
1911 if (Imm >= 0 && Imm <= 2) {
1912 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
1913 return ParseStatus::Success;
1914 }
1915 }
1916
1917 break;
1918 }
1919 case AsmToken::Identifier: {
1920 StringRef Identifier;
1921 if (getParser().parseIdentifier(Res&: Identifier))
1922 return ParseStatus::Failure;
1923
1924 unsigned Opcode;
1925 if (Identifier == "C0")
1926 Opcode = 0;
1927 else if (Identifier == "C1")
1928 Opcode = 1;
1929 else if (Identifier == "C2")
1930 Opcode = 2;
1931 else
1932 break;
1933
1934 Res = MCConstantExpr::create(Value: Opcode, Ctx&: getContext());
1935 E = SMLoc::getFromPointer(Ptr: S.getPointer() + Identifier.size());
1936 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
1937 return ParseStatus::Success;
1938 }
1939 case AsmToken::Percent: {
1940 // Discard operand with modifier.
1941 break;
1942 }
1943 }
1944
1945 return generateImmOutOfRangeError(
1946 ErrorLoc: S, Lower: 0, Upper: 2,
1947 Msg: "opcode must be a valid opcode name or an immediate in the range");
1948}
1949
1950ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1951 SMLoc S = getLoc();
1952 const MCExpr *Res;
1953
1954 auto SysRegFromConstantInt = [this](const MCExpr *E, SMLoc S) {
1955 if (auto *CE = dyn_cast<MCConstantExpr>(Val: E)) {
1956 int64_t Imm = CE->getValue();
1957 if (isUInt<12>(x: Imm)) {
1958 auto Range = RISCVSysReg::lookupSysRegByEncoding(Encoding: Imm);
1959 // Accept an immediate representing a named Sys Reg if it satisfies the
1960 // the required features.
1961 for (auto &Reg : Range) {
1962 if (Reg.IsAltName || Reg.IsDeprecatedName)
1963 continue;
1964 if (Reg.haveRequiredFeatures(ActiveFeatures: STI->getFeatureBits()))
1965 return RISCVOperand::createSysReg(Str: Reg.Name, S, Encoding: Imm);
1966 }
1967 // Accept an immediate representing an un-named Sys Reg if the range is
1968 // valid, regardless of the required features.
1969 return RISCVOperand::createSysReg(Str: "", S, Encoding: Imm);
1970 }
1971 }
1972 return std::unique_ptr<RISCVOperand>();
1973 };
1974
1975 switch (getLexer().getKind()) {
1976 default:
1977 return ParseStatus::NoMatch;
1978 case AsmToken::LParen:
1979 case AsmToken::Minus:
1980 case AsmToken::Plus:
1981 case AsmToken::Exclaim:
1982 case AsmToken::Tilde:
1983 case AsmToken::Integer:
1984 case AsmToken::String: {
1985 if (getParser().parseExpression(Res))
1986 return ParseStatus::Failure;
1987
1988 if (auto SysOpnd = SysRegFromConstantInt(Res, S)) {
1989 Operands.push_back(Elt: std::move(SysOpnd));
1990 return ParseStatus::Success;
1991 }
1992
1993 return generateImmOutOfRangeError(ErrorLoc: S, Lower: 0, Upper: (1 << 12) - 1);
1994 }
1995 case AsmToken::Identifier: {
1996 StringRef Identifier;
1997 if (getParser().parseIdentifier(Res&: Identifier))
1998 return ParseStatus::Failure;
1999
2000 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Name: Identifier);
2001
2002 if (SysReg) {
2003 if (SysReg->IsDeprecatedName) {
2004 // Lookup the undeprecated name.
2005 auto Range = RISCVSysReg::lookupSysRegByEncoding(Encoding: SysReg->Encoding);
2006 for (auto &Reg : Range) {
2007 if (Reg.IsAltName || Reg.IsDeprecatedName)
2008 continue;
2009 Warning(L: S, Msg: "'" + Identifier + "' is a deprecated alias for '" +
2010 Reg.Name + "'");
2011 }
2012 }
2013
2014 // Accept a named Sys Reg if the required features are present.
2015 const auto &FeatureBits = getSTI().getFeatureBits();
2016 if (!SysReg->haveRequiredFeatures(ActiveFeatures: FeatureBits)) {
2017 const auto *Feature = llvm::find_if(Range: RISCVFeatureKV, P: [&](auto Feature) {
2018 return SysReg->FeaturesRequired[Feature.Value];
2019 });
2020 auto ErrorMsg = std::string("system register '") + SysReg->Name + "' ";
2021 if (SysReg->IsRV32Only && FeatureBits[RISCV::Feature64Bit]) {
2022 ErrorMsg += "is RV32 only";
2023 if (Feature != std::end(arr: RISCVFeatureKV))
2024 ErrorMsg += " and ";
2025 }
2026 if (Feature != std::end(arr: RISCVFeatureKV)) {
2027 ErrorMsg +=
2028 "requires '" + std::string(Feature->Key) + "' to be enabled";
2029 }
2030
2031 return Error(L: S, Msg: ErrorMsg);
2032 }
2033 Operands.push_back(
2034 Elt: RISCVOperand::createSysReg(Str: Identifier, S, Encoding: SysReg->Encoding));
2035 return ParseStatus::Success;
2036 }
2037
2038 // Accept a symbol name that evaluates to an absolute value.
2039 MCSymbol *Sym = getContext().lookupSymbol(Name: Identifier);
2040 if (Sym && Sym->isVariable()) {
2041 // Pass false for SetUsed, since redefining the value later does not
2042 // affect this instruction.
2043 if (auto SysOpnd = SysRegFromConstantInt(Sym->getVariableValue(), S)) {
2044 Operands.push_back(Elt: std::move(SysOpnd));
2045 return ParseStatus::Success;
2046 }
2047 }
2048
2049 return generateImmOutOfRangeError(ErrorLoc: S, Lower: 0, Upper: (1 << 12) - 1,
2050 Msg: "operand must be a valid system register "
2051 "name or an integer in the range");
2052 }
2053 case AsmToken::Percent: {
2054 // Discard operand with modifier.
2055 return generateImmOutOfRangeError(ErrorLoc: S, Lower: 0, Upper: (1 << 12) - 1);
2056 }
2057 }
2058
2059 return ParseStatus::NoMatch;
2060}
2061
2062ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
2063 SMLoc S = getLoc();
2064
2065 // Parse special floats (inf/nan/min) representation.
2066 if (getTok().is(K: AsmToken::Identifier)) {
2067 StringRef Identifier = getTok().getIdentifier();
2068 if (Identifier.compare_insensitive(RHS: "inf") == 0) {
2069 Operands.push_back(
2070 Elt: RISCVOperand::createExpr(Val: MCConstantExpr::create(Value: 30, Ctx&: getContext()), S,
2071 E: getTok().getEndLoc(), IsRV64: isRV64()));
2072 } else if (Identifier.compare_insensitive(RHS: "nan") == 0) {
2073 Operands.push_back(
2074 Elt: RISCVOperand::createExpr(Val: MCConstantExpr::create(Value: 31, Ctx&: getContext()), S,
2075 E: getTok().getEndLoc(), IsRV64: isRV64()));
2076 } else if (Identifier.compare_insensitive(RHS: "min") == 0) {
2077 Operands.push_back(
2078 Elt: RISCVOperand::createExpr(Val: MCConstantExpr::create(Value: 1, Ctx&: getContext()), S,
2079 E: getTok().getEndLoc(), IsRV64: isRV64()));
2080 } else {
2081 return TokError(Msg: "invalid floating point literal");
2082 }
2083
2084 Lex(); // Eat the token.
2085
2086 return ParseStatus::Success;
2087 }
2088
2089 // Handle negation, as that still comes through as a separate token.
2090 bool IsNegative = parseOptionalToken(T: AsmToken::Minus);
2091
2092 const AsmToken &Tok = getTok();
2093 if (!Tok.is(K: AsmToken::Real))
2094 return TokError(Msg: "invalid floating point immediate");
2095
2096 // Parse FP representation.
2097 APFloat RealVal(APFloat::IEEEdouble());
2098 auto StatusOrErr =
2099 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2100 if (errorToBool(Err: StatusOrErr.takeError()))
2101 return TokError(Msg: "invalid floating point representation");
2102
2103 if (IsNegative)
2104 RealVal.changeSign();
2105
2106 Operands.push_back(Elt: RISCVOperand::createFPImm(
2107 Val: RealVal.bitcastToAPInt().getZExtValue(), S));
2108
2109 Lex(); // Eat the token.
2110
2111 return ParseStatus::Success;
2112}
2113
2114ParseStatus RISCVAsmParser::parseExpression(OperandVector &Operands) {
2115 SMLoc S = getLoc();
2116 SMLoc E;
2117 const MCExpr *Res;
2118
2119 switch (getLexer().getKind()) {
2120 default:
2121 return ParseStatus::NoMatch;
2122 case AsmToken::LParen:
2123 case AsmToken::Dot:
2124 case AsmToken::Minus:
2125 case AsmToken::Plus:
2126 case AsmToken::Exclaim:
2127 case AsmToken::Tilde:
2128 case AsmToken::Integer:
2129 case AsmToken::String:
2130 case AsmToken::Identifier:
2131 if (getParser().parseExpression(Res, EndLoc&: E))
2132 return ParseStatus::Failure;
2133 break;
2134 case AsmToken::Percent:
2135 return parseOperandWithSpecifier(Operands);
2136 }
2137
2138 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2139 return ParseStatus::Success;
2140}
2141
2142ParseStatus RISCVAsmParser::parseOperandWithSpecifier(OperandVector &Operands) {
2143 SMLoc S = getLoc();
2144 SMLoc E;
2145
2146 if (parseToken(T: AsmToken::Percent, Msg: "expected '%' relocation specifier"))
2147 return ParseStatus::Failure;
2148 const MCExpr *Expr = nullptr;
2149 bool Failed = parseExprWithSpecifier(Res&: Expr, E);
2150 if (!Failed)
2151 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Expr, S, E, IsRV64: isRV64()));
2152 return Failed;
2153}
2154
2155bool RISCVAsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {
2156 SMLoc Loc = getLoc();
2157 if (getLexer().getKind() != AsmToken::Identifier)
2158 return TokError(Msg: "expected '%' relocation specifier");
2159 StringRef Identifier = getParser().getTok().getIdentifier();
2160 auto Spec = RISCV::parseSpecifierName(name: Identifier);
2161 if (!Spec)
2162 return TokError(Msg: "invalid relocation specifier");
2163
2164 getParser().Lex(); // Eat the identifier
2165 if (parseToken(T: AsmToken::LParen, Msg: "expected '('"))
2166 return true;
2167
2168 const MCExpr *SubExpr;
2169 if (getParser().parseParenExpression(Res&: SubExpr, EndLoc&: E))
2170 return true;
2171
2172 Res = MCSpecifierExpr::create(Expr: SubExpr, S: Spec, Ctx&: getContext(), Loc);
2173 return false;
2174}
2175
2176bool RISCVAsmParser::parseDataExpr(const MCExpr *&Res) {
2177 SMLoc E;
2178 if (parseOptionalToken(T: AsmToken::Percent))
2179 return parseExprWithSpecifier(Res, E);
2180 return getParser().parseExpression(Res);
2181}
2182
2183ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
2184 SMLoc S = getLoc();
2185 const MCExpr *Res;
2186
2187 if (getLexer().getKind() != AsmToken::Identifier)
2188 return ParseStatus::NoMatch;
2189
2190 StringRef Identifier;
2191 AsmToken Tok = getLexer().getTok();
2192
2193 if (getParser().parseIdentifier(Res&: Identifier))
2194 return ParseStatus::Failure;
2195
2196 SMLoc E = SMLoc::getFromPointer(Ptr: S.getPointer() + Identifier.size());
2197
2198 MCSymbol *Sym = getContext().getOrCreateSymbol(Name: Identifier);
2199
2200 if (Sym->isVariable()) {
2201 const MCExpr *V = Sym->getVariableValue();
2202 if (!isa<MCSymbolRefExpr>(Val: V)) {
2203 getLexer().UnLex(Token: Tok); // Put back if it's not a bare symbol.
2204 return ParseStatus::NoMatch;
2205 }
2206 Res = V;
2207 } else
2208 Res = MCSymbolRefExpr::create(Symbol: Sym, Ctx&: getContext());
2209
2210 MCBinaryExpr::Opcode Opcode;
2211 switch (getLexer().getKind()) {
2212 default:
2213 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2214 return ParseStatus::Success;
2215 case AsmToken::Plus:
2216 Opcode = MCBinaryExpr::Add;
2217 getLexer().Lex();
2218 break;
2219 case AsmToken::Minus:
2220 Opcode = MCBinaryExpr::Sub;
2221 getLexer().Lex();
2222 break;
2223 }
2224
2225 const MCExpr *Expr;
2226 if (getParser().parseExpression(Res&: Expr, EndLoc&: E))
2227 return ParseStatus::Failure;
2228 Res = MCBinaryExpr::create(Op: Opcode, LHS: Res, RHS: Expr, Ctx&: getContext());
2229 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2230 return ParseStatus::Success;
2231}
2232
2233ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
2234 SMLoc S = getLoc();
2235 const MCExpr *Res;
2236
2237 if (getLexer().getKind() != AsmToken::Identifier)
2238 return ParseStatus::NoMatch;
2239 std::string Identifier(getTok().getIdentifier());
2240
2241 if (getLexer().peekTok().is(K: AsmToken::At)) {
2242 Lex();
2243 Lex();
2244 StringRef PLT;
2245 SMLoc Loc = getLoc();
2246 if (getParser().parseIdentifier(Res&: PLT) || PLT != "plt")
2247 return Error(L: Loc, Msg: "@ (except the deprecated/ignored @plt) is disallowed");
2248 } else if (!getLexer().peekTok().is(K: AsmToken::EndOfStatement)) {
2249 // Avoid parsing the register in `call rd, foo` as a call symbol.
2250 return ParseStatus::NoMatch;
2251 } else {
2252 Lex();
2253 }
2254
2255 SMLoc E = SMLoc::getFromPointer(Ptr: S.getPointer() + Identifier.size());
2256 RISCV::Specifier Kind = RISCV::S_CALL_PLT;
2257
2258 MCSymbol *Sym = getContext().getOrCreateSymbol(Name: Identifier);
2259 Res = MCSymbolRefExpr::create(Symbol: Sym, Ctx&: getContext());
2260 Res = MCSpecifierExpr::create(Expr: Res, S: Kind, Ctx&: getContext());
2261 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2262 return ParseStatus::Success;
2263}
2264
2265ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
2266 SMLoc S = getLoc();
2267 SMLoc E;
2268 const MCExpr *Res;
2269
2270 if (getParser().parseExpression(Res, EndLoc&: E))
2271 return ParseStatus::Failure;
2272
2273 if (Res->getKind() != MCExpr::ExprKind::SymbolRef)
2274 return Error(L: S, Msg: "operand must be a valid jump target");
2275
2276 Res = MCSpecifierExpr::create(Expr: Res, S: RISCV::S_CALL_PLT, Ctx&: getContext());
2277 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2278 return ParseStatus::Success;
2279}
2280
2281ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
2282 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2283 // both being acceptable forms. When parsing `jal ra, foo` this function
2284 // will be called for the `ra` register operand in an attempt to match the
2285 // single-operand alias. parseJALOffset must fail for this case. It would
2286 // seem logical to try parse the operand using parseExpression and return
2287 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2288 // the second form rather than the first). We can't do this as there's no
2289 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2290 // is an identifier and is followed by a comma.
2291 if (getLexer().is(K: AsmToken::Identifier) &&
2292 getLexer().peekTok().is(K: AsmToken::Comma))
2293 return ParseStatus::NoMatch;
2294
2295 return parseExpression(Operands);
2296}
2297
2298bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,
2299 unsigned &Sew, unsigned &Lmul,
2300 bool &Fractional, bool &TailAgnostic,
2301 bool &MaskAgnostic, bool &AltFmt) {
2302 if (Tok.isNot(K: AsmToken::Identifier))
2303 return true;
2304
2305 StringRef Identifier = Tok.getIdentifier();
2306 if (State < VTypeState::SeenSew && Identifier.consume_front(Prefix: "e")) {
2307 if (Identifier.getAsInteger(Radix: 10, Result&: Sew)) {
2308 if (Identifier == "16alt") {
2309 AltFmt = true;
2310 Sew = 16;
2311 } else if (Identifier == "8alt") {
2312 AltFmt = true;
2313 Sew = 8;
2314 } else {
2315 return true;
2316 }
2317 }
2318 if (!RISCVVType::isValidSEW(SEW: Sew))
2319 return true;
2320
2321 State = VTypeState::SeenSew;
2322 return false;
2323 }
2324
2325 if (State < VTypeState::SeenLmul && Identifier.consume_front(Prefix: "m")) {
2326 // Might arrive here if lmul and tail policy unspecified, if so we're
2327 // parsing a MaskPolicy not an LMUL.
2328 if (Identifier == "a" || Identifier == "u") {
2329 MaskAgnostic = (Identifier == "a");
2330 State = VTypeState::SeenMaskPolicy;
2331 return false;
2332 }
2333
2334 Fractional = Identifier.consume_front(Prefix: "f");
2335 if (Identifier.getAsInteger(Radix: 10, Result&: Lmul))
2336 return true;
2337 if (!RISCVVType::isValidLMUL(LMUL: Lmul, Fractional))
2338 return true;
2339
2340 if (Fractional) {
2341 unsigned ELEN = STI->hasFeature(Feature: RISCV::FeatureStdExtZve64x) ? 64 : 32;
2342 unsigned MinLMUL = ELEN / 8;
2343 if (Lmul > MinLMUL)
2344 Warning(L: Tok.getLoc(),
2345 Msg: "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2346 Twine(MinLMUL) + " is reserved");
2347 }
2348
2349 State = VTypeState::SeenLmul;
2350 return false;
2351 }
2352
2353 if (State < VTypeState::SeenTailPolicy && Identifier.starts_with(Prefix: "t")) {
2354 if (Identifier == "ta")
2355 TailAgnostic = true;
2356 else if (Identifier == "tu")
2357 TailAgnostic = false;
2358 else
2359 return true;
2360
2361 State = VTypeState::SeenTailPolicy;
2362 return false;
2363 }
2364
2365 if (State < VTypeState::SeenMaskPolicy && Identifier.starts_with(Prefix: "m")) {
2366 if (Identifier == "ma")
2367 MaskAgnostic = true;
2368 else if (Identifier == "mu")
2369 MaskAgnostic = false;
2370 else
2371 return true;
2372
2373 State = VTypeState::SeenMaskPolicy;
2374 return false;
2375 }
2376
2377 return true;
2378}
2379
2380ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
2381 SMLoc S = getLoc();
2382
2383 // Default values
2384 unsigned Sew = 8;
2385 unsigned Lmul = 1;
2386 bool Fractional = false;
2387 bool TailAgnostic = false;
2388 bool MaskAgnostic = false;
2389 bool AltFmt = false;
2390
2391 VTypeState State = VTypeState::SeenNothingYet;
2392 do {
2393 if (parseVTypeToken(Tok: getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2394 MaskAgnostic, AltFmt)) {
2395 // The first time, errors return NoMatch rather than Failure
2396 if (State == VTypeState::SeenNothingYet)
2397 return ParseStatus::NoMatch;
2398 break;
2399 }
2400
2401 getLexer().Lex();
2402 } while (parseOptionalToken(T: AsmToken::Comma));
2403
2404 if (!getLexer().is(K: AsmToken::EndOfStatement) ||
2405 State == VTypeState::SeenNothingYet)
2406 return generateVTypeError(ErrorLoc: S);
2407
2408 RISCVVType::VLMUL VLMUL = RISCVVType::encodeLMUL(LMUL: Lmul, Fractional);
2409 if (Fractional) {
2410 unsigned ELEN = STI->hasFeature(Feature: RISCV::FeatureStdExtZve64x) ? 64 : 32;
2411 unsigned MaxSEW = ELEN / Lmul;
2412 // If MaxSEW < 8, we should have printed warning about reserved LMUL.
2413 if (MaxSEW >= 8 && Sew > MaxSEW)
2414 Warning(L: S, Msg: "use of vtype encodings with SEW > " + Twine(MaxSEW) +
2415 " and LMUL == mf" + Twine(Lmul) +
2416 " may not be compatible with all RVV implementations");
2417 }
2418
2419 unsigned VTypeI =
2420 RISCVVType::encodeVTYPE(VLMUL, SEW: Sew, TailAgnostic, MaskAgnostic, AltFmt);
2421 Operands.push_back(Elt: RISCVOperand::createVType(VTypeI, S));
2422 return ParseStatus::Success;
2423}
2424
2425bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
2426 if (STI->hasFeature(Feature: RISCV::FeatureStdExtZvfbfa) ||
2427 STI->hasFeature(Feature: RISCV::FeatureStdExtZvfofp8min) ||
2428 STI->hasFeature(Feature: RISCV::FeatureVendorXSfvfbfexp16e))
2429 return Error(
2430 L: ErrorLoc,
2431 Msg: "operand must be "
2432 "e[8|8alt|16|16alt|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2433 return Error(
2434 L: ErrorLoc,
2435 Msg: "operand must be "
2436 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2437}
2438
2439ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
2440 SMLoc S = getLoc();
2441
2442 unsigned Widen = 0;
2443 unsigned SEW = 0;
2444 bool AltFmt = false;
2445 StringRef Identifier;
2446
2447 if (getTok().isNot(K: AsmToken::Identifier))
2448 goto Fail;
2449
2450 Identifier = getTok().getIdentifier();
2451
2452 if (!Identifier.consume_front(Prefix: "e"))
2453 goto Fail;
2454
2455 if (Identifier.getAsInteger(Radix: 10, Result&: SEW)) {
2456 if (Identifier != "16alt")
2457 goto Fail;
2458
2459 AltFmt = true;
2460 SEW = 16;
2461 }
2462 if (!RISCVVType::isValidSEW(SEW))
2463 goto Fail;
2464
2465 Lex();
2466
2467 if (!parseOptionalToken(T: AsmToken::Comma))
2468 goto Fail;
2469
2470 if (getTok().isNot(K: AsmToken::Identifier))
2471 goto Fail;
2472
2473 Identifier = getTok().getIdentifier();
2474
2475 if (!Identifier.consume_front(Prefix: "w"))
2476 goto Fail;
2477 if (Identifier.getAsInteger(Radix: 10, Result&: Widen))
2478 goto Fail;
2479 if (Widen != 1 && Widen != 2 && Widen != 4)
2480 goto Fail;
2481
2482 Lex();
2483
2484 if (getLexer().is(K: AsmToken::EndOfStatement)) {
2485 Operands.push_back(Elt: RISCVOperand::createVType(
2486 VTypeI: RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));
2487 return ParseStatus::Success;
2488 }
2489
2490Fail:
2491 return generateXSfmmVTypeError(ErrorLoc: S);
2492}
2493
2494bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {
2495 return Error(L: ErrorLoc, Msg: "operand must be e[8|16|16alt|32|64],w[1|2|4]");
2496}
2497
2498ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2499 if (getLexer().isNot(K: AsmToken::Identifier))
2500 return ParseStatus::NoMatch;
2501
2502 StringRef Name = getLexer().getTok().getIdentifier();
2503 if (!Name.consume_back(Suffix: ".t"))
2504 return Error(L: getLoc(), Msg: "expected '.t' suffix");
2505 MCRegister Reg = matchRegisterNameHelper(Name);
2506
2507 if (!Reg)
2508 return ParseStatus::NoMatch;
2509 if (Reg != RISCV::V0)
2510 return ParseStatus::NoMatch;
2511 SMLoc S = getLoc();
2512 SMLoc E = getTok().getEndLoc();
2513 getLexer().Lex();
2514 Operands.push_back(Elt: RISCVOperand::createReg(Reg, S, E));
2515 return ParseStatus::Success;
2516}
2517
2518ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {
2519 if (!isRV64() || getSTI().hasFeature(Feature: RISCV::FeatureStdExtF))
2520 return ParseStatus::NoMatch;
2521
2522 return parseGPRAsFPR(Operands);
2523}
2524
2525ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2526 if (getLexer().isNot(K: AsmToken::Identifier))
2527 return ParseStatus::NoMatch;
2528
2529 StringRef Name = getLexer().getTok().getIdentifier();
2530 MCRegister Reg = matchRegisterNameHelper(Name);
2531
2532 if (!Reg)
2533 return ParseStatus::NoMatch;
2534 SMLoc S = getLoc();
2535 SMLoc E = getTok().getEndLoc();
2536 getLexer().Lex();
2537 Operands.push_back(Elt: RISCVOperand::createReg(
2538 Reg, S, E, IsGPRAsFPR: !getSTI().hasFeature(Feature: RISCV::FeatureStdExtF)));
2539 return ParseStatus::Success;
2540}
2541
2542ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {
2543 if (isRV64() || getSTI().hasFeature(Feature: RISCV::FeatureStdExtF))
2544 return ParseStatus::NoMatch;
2545
2546 if (getLexer().isNot(K: AsmToken::Identifier))
2547 return ParseStatus::NoMatch;
2548
2549 StringRef Name = getLexer().getTok().getIdentifier();
2550 MCRegister Reg = matchRegisterNameHelper(Name);
2551
2552 if (!Reg)
2553 return ParseStatus::NoMatch;
2554
2555 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))
2556 return ParseStatus::NoMatch;
2557
2558 if ((Reg - RISCV::X0) & 1) {
2559 // Only report the even register error if we have at least Zfinx so we know
2560 // some FP is enabled. We already checked F earlier.
2561 if (getSTI().hasFeature(Feature: RISCV::FeatureStdExtZfinx))
2562 return TokError(Msg: "double precision floating point operands must use even "
2563 "numbered X register");
2564 return ParseStatus::NoMatch;
2565 }
2566
2567 SMLoc S = getLoc();
2568 SMLoc E = getTok().getEndLoc();
2569 getLexer().Lex();
2570
2571 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2572 MCRegister Pair = RI->getMatchingSuperReg(
2573 Reg, SubIdx: RISCV::sub_gpr_even,
2574 RC: &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2575 Operands.push_back(Elt: RISCVOperand::createReg(Reg: Pair, S, E, /*isGPRAsFPR=*/IsGPRAsFPR: true));
2576 return ParseStatus::Success;
2577}
2578
2579template <bool IsRV64>
2580ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2581 return parseGPRPair(Operands, IsRV64Inst: IsRV64);
2582}
2583
2584ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2585 bool IsRV64Inst) {
2586 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2587 // RV64 as it will prevent matching the RV64 version of the same instruction
2588 // that doesn't use a GPRPair.
2589 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2590 // still parse as a pair.
2591 if (!IsRV64Inst && isRV64())
2592 return ParseStatus::NoMatch;
2593
2594 if (getLexer().isNot(K: AsmToken::Identifier))
2595 return ParseStatus::NoMatch;
2596
2597 StringRef Name = getLexer().getTok().getIdentifier();
2598 MCRegister Reg = matchRegisterNameHelper(Name);
2599
2600 if (!Reg)
2601 return ParseStatus::NoMatch;
2602
2603 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))
2604 return ParseStatus::NoMatch;
2605
2606 if ((Reg - RISCV::X0) & 1)
2607 return TokError(Msg: "register must be even");
2608
2609 SMLoc S = getLoc();
2610 SMLoc E = getTok().getEndLoc();
2611 getLexer().Lex();
2612
2613 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2614 MCRegister Pair = RI->getMatchingSuperReg(
2615 Reg, SubIdx: RISCV::sub_gpr_even,
2616 RC: &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2617 Operands.push_back(Elt: RISCVOperand::createReg(Reg: Pair, S, E));
2618 return ParseStatus::Success;
2619}
2620
2621ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2622 if (getLexer().isNot(K: AsmToken::Identifier))
2623 return TokError(
2624 Msg: "operand must be a valid floating point rounding mode mnemonic");
2625
2626 StringRef Str = getLexer().getTok().getIdentifier();
2627 RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str);
2628
2629 if (FRM == RISCVFPRndMode::Invalid)
2630 return TokError(
2631 Msg: "operand must be a valid floating point rounding mode mnemonic");
2632
2633 Operands.push_back(Elt: RISCVOperand::createFRMArg(FRM, S: getLoc()));
2634 Lex(); // Eat identifier token.
2635 return ParseStatus::Success;
2636}
2637
2638ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2639 const AsmToken &Tok = getLexer().getTok();
2640
2641 if (Tok.is(K: AsmToken::Integer)) {
2642 if (Tok.getIntVal() != 0)
2643 goto ParseFail;
2644
2645 Operands.push_back(Elt: RISCVOperand::createFenceArg(Val: 0, S: getLoc()));
2646 Lex();
2647 return ParseStatus::Success;
2648 }
2649
2650 if (Tok.is(K: AsmToken::Identifier)) {
2651 StringRef Str = Tok.getIdentifier();
2652
2653 // Letters must be unique, taken from 'iorw', and in ascending order. This
2654 // holds as long as each individual character is one of 'iorw' and is
2655 // greater than the previous character.
2656 unsigned Imm = 0;
2657 bool Valid = true;
2658 char Prev = '\0';
2659 for (char c : Str) {
2660 switch (c) {
2661 default:
2662 Valid = false;
2663 break;
2664 case 'i':
2665 Imm |= RISCVFenceField::I;
2666 break;
2667 case 'o':
2668 Imm |= RISCVFenceField::O;
2669 break;
2670 case 'r':
2671 Imm |= RISCVFenceField::R;
2672 break;
2673 case 'w':
2674 Imm |= RISCVFenceField::W;
2675 break;
2676 }
2677
2678 if (c <= Prev) {
2679 Valid = false;
2680 break;
2681 }
2682 Prev = c;
2683 }
2684
2685 if (!Valid)
2686 goto ParseFail;
2687
2688 Operands.push_back(Elt: RISCVOperand::createFenceArg(Val: Imm, S: getLoc()));
2689 Lex();
2690 return ParseStatus::Success;
2691 }
2692
2693ParseFail:
2694 return TokError(Msg: "operand must be formed of letters selected in-order from "
2695 "'iorw' or be 0");
2696}
2697
2698ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2699 if (parseToken(T: AsmToken::LParen, Msg: "expected '('"))
2700 return ParseStatus::Failure;
2701 Operands.push_back(Elt: RISCVOperand::createToken(Str: "(", S: getLoc()));
2702
2703 if (!parseRegister(Operands).isSuccess())
2704 return Error(L: getLoc(), Msg: "expected register");
2705
2706 if (parseToken(T: AsmToken::RParen, Msg: "expected ')'"))
2707 return ParseStatus::Failure;
2708 Operands.push_back(Elt: RISCVOperand::createToken(Str: ")", S: getLoc()));
2709
2710 return ParseStatus::Success;
2711}
2712
2713ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2714 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2715 // as one of their register operands, such as `(a0)`. This just denotes that
2716 // the register (in this case `a0`) contains a memory address.
2717 //
2718 // Normally, we would be able to parse these by putting the parens into the
2719 // instruction string. However, GNU as also accepts a zero-offset memory
2720 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2721 // with parseExpression followed by parseMemOpBaseReg, but these instructions
2722 // do not accept an immediate operand, and we do not want to add a "dummy"
2723 // operand that is silently dropped.
2724 //
2725 // Instead, we use this custom parser. This will: allow (and discard) an
2726 // offset if it is zero; require (and discard) parentheses; and add only the
2727 // parsed register operand to `Operands`.
2728 //
2729 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2730 // which will only print the register surrounded by parentheses (which GNU as
2731 // also uses as its canonical representation for these operands).
2732 std::unique_ptr<RISCVOperand> OptionalImmOp;
2733
2734 if (getLexer().isNot(K: AsmToken::LParen)) {
2735 // Parse an Integer token. We do not accept arbitrary constant expressions
2736 // in the offset field (because they may include parens, which complicates
2737 // parsing a lot).
2738 int64_t ImmVal;
2739 SMLoc ImmStart = getLoc();
2740 if (getParser().parseIntToken(V&: ImmVal,
2741 ErrMsg: "expected '(' or optional integer offset"))
2742 return ParseStatus::Failure;
2743
2744 // Create a RISCVOperand for checking later (so the error messages are
2745 // nicer), but we don't add it to Operands.
2746 SMLoc ImmEnd = getLoc();
2747 OptionalImmOp =
2748 RISCVOperand::createExpr(Val: MCConstantExpr::create(Value: ImmVal, Ctx&: getContext()),
2749 S: ImmStart, E: ImmEnd, IsRV64: isRV64());
2750 }
2751
2752 if (parseToken(T: AsmToken::LParen,
2753 Msg: OptionalImmOp ? "expected '(' after optional integer offset"
2754 : "expected '(' or optional integer offset"))
2755 return ParseStatus::Failure;
2756
2757 if (!parseRegister(Operands).isSuccess())
2758 return Error(L: getLoc(), Msg: "expected register");
2759
2760 if (parseToken(T: AsmToken::RParen, Msg: "expected ')'"))
2761 return ParseStatus::Failure;
2762
2763 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2764 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2765 return Error(
2766 L: OptionalImmOp->getStartLoc(), Msg: "optional integer offset must be 0",
2767 Range: SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2768
2769 return ParseStatus::Success;
2770}
2771
2772ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
2773 // RR : a2(a1)
2774 if (getLexer().getKind() != AsmToken::Identifier)
2775 return ParseStatus::NoMatch;
2776
2777 SMLoc S = getLoc();
2778 StringRef OffsetRegName = getLexer().getTok().getIdentifier();
2779 MCRegister OffsetReg = matchRegisterNameHelper(Name: OffsetRegName);
2780 if (!OffsetReg ||
2781 !RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg: OffsetReg))
2782 return Error(L: getLoc(), Msg: "expected GPR register");
2783 getLexer().Lex();
2784
2785 if (parseToken(T: AsmToken::LParen, Msg: "expected '(' or invalid operand"))
2786 return ParseStatus::Failure;
2787
2788 if (getLexer().getKind() != AsmToken::Identifier)
2789 return Error(L: getLoc(), Msg: "expected GPR register");
2790
2791 StringRef BaseRegName = getLexer().getTok().getIdentifier();
2792 MCRegister BaseReg = matchRegisterNameHelper(Name: BaseRegName);
2793 if (!BaseReg ||
2794 !RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg: BaseReg))
2795 return Error(L: getLoc(), Msg: "expected GPR register");
2796 getLexer().Lex();
2797
2798 if (parseToken(T: AsmToken::RParen, Msg: "expected ')'"))
2799 return ParseStatus::Failure;
2800
2801 Operands.push_back(Elt: RISCVOperand::createRegReg(BaseReg, OffsetReg, S));
2802
2803 return ParseStatus::Success;
2804}
2805
2806// RegList: {ra [, s0[-sN]]}
2807// XRegList: {x1 [, x8[-x9][, x18[-xN]]]}
2808
2809// When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
2810// must include `fp`/`s0` in the list:
2811// RegList: {ra, s0[-sN]}
2812// XRegList: {x1, x8[-x9][, x18[-xN]]}
2813ParseStatus RISCVAsmParser::parseRegList(OperandVector &Operands,
2814 bool MustIncludeS0) {
2815 if (getTok().isNot(K: AsmToken::LCurly))
2816 return ParseStatus::NoMatch;
2817
2818 SMLoc S = getLoc();
2819
2820 Lex();
2821
2822 bool UsesXRegs;
2823 MCRegister RegEnd;
2824 do {
2825 if (getTok().isNot(K: AsmToken::Identifier))
2826 return Error(L: getLoc(), Msg: "invalid register");
2827
2828 StringRef RegName = getTok().getIdentifier();
2829 MCRegister Reg = matchRegisterNameHelper(Name: RegName);
2830 if (!Reg)
2831 return Error(L: getLoc(), Msg: "invalid register");
2832
2833 if (!RegEnd) {
2834 UsesXRegs = RegName[0] == 'x';
2835 if (Reg != RISCV::X1)
2836 return Error(L: getLoc(), Msg: "register list must start from 'ra' or 'x1'");
2837 } else if (RegEnd == RISCV::X1) {
2838 if (Reg != RISCV::X8 || (UsesXRegs != (RegName[0] == 'x')))
2839 return Error(L: getLoc(), Msg: Twine("register must be '") +
2840 (UsesXRegs ? "x8" : "s0") + "'");
2841 } else if (RegEnd == RISCV::X9 && UsesXRegs) {
2842 if (Reg != RISCV::X18 || (RegName[0] != 'x'))
2843 return Error(L: getLoc(), Msg: "register must be 'x18'");
2844 } else {
2845 return Error(L: getLoc(), Msg: "too many register ranges");
2846 }
2847
2848 RegEnd = Reg;
2849
2850 Lex();
2851
2852 SMLoc MinusLoc = getLoc();
2853 if (parseOptionalToken(T: AsmToken::Minus)) {
2854 if (RegEnd == RISCV::X1)
2855 return Error(L: MinusLoc, Msg: Twine("register '") + (UsesXRegs ? "x1" : "ra") +
2856 "' cannot start a multiple register range");
2857
2858 if (getTok().isNot(K: AsmToken::Identifier))
2859 return Error(L: getLoc(), Msg: "invalid register");
2860
2861 StringRef RegName = getTok().getIdentifier();
2862 MCRegister Reg = matchRegisterNameHelper(Name: RegName);
2863 if (!Reg)
2864 return Error(L: getLoc(), Msg: "invalid register");
2865
2866 if (RegEnd == RISCV::X8) {
2867 if ((Reg != RISCV::X9 &&
2868 (UsesXRegs || Reg < RISCV::X18 || Reg > RISCV::X27)) ||
2869 (UsesXRegs != (RegName[0] == 'x'))) {
2870 if (UsesXRegs)
2871 return Error(L: getLoc(), Msg: "register must be 'x9'");
2872 return Error(L: getLoc(), Msg: "register must be in the range 's1' to 's11'");
2873 }
2874 } else if (RegEnd == RISCV::X18) {
2875 if (Reg < RISCV::X19 || Reg > RISCV::X27 || (RegName[0] != 'x'))
2876 return Error(L: getLoc(),
2877 Msg: "register must be in the range 'x19' to 'x27'");
2878 } else
2879 llvm_unreachable("unexpected register");
2880
2881 RegEnd = Reg;
2882
2883 Lex();
2884 }
2885 } while (parseOptionalToken(T: AsmToken::Comma));
2886
2887 if (parseToken(T: AsmToken::RCurly, Msg: "expected ',' or '}'"))
2888 return ParseStatus::Failure;
2889
2890 if (RegEnd == RISCV::X26)
2891 return Error(L: S, Msg: "invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, "
2892 "x18-x26}' is not supported");
2893
2894 auto Encode = RISCVZC::encodeRegList(EndReg: RegEnd, IsRVE: isRVE());
2895 assert(Encode != RISCVZC::INVALID_RLIST);
2896
2897 if (MustIncludeS0 && Encode == RISCVZC::RA)
2898 return Error(L: S, Msg: "register list must include 's0' or 'x8'");
2899
2900 Operands.push_back(Elt: RISCVOperand::createRegList(RlistEncode: Encode, S));
2901
2902 return ParseStatus::Success;
2903}
2904
2905ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
2906 bool ExpectNegative) {
2907 SMLoc S = getLoc();
2908 bool Negative = parseOptionalToken(T: AsmToken::Minus);
2909
2910 if (getTok().isNot(K: AsmToken::Integer))
2911 return ParseStatus::NoMatch;
2912
2913 int64_t StackAdjustment = getTok().getIntVal();
2914
2915 auto *RegListOp = static_cast<RISCVOperand *>(Operands.back().get());
2916 if (!RegListOp->isRegList())
2917 return ParseStatus::NoMatch;
2918
2919 unsigned RlistEncode = RegListOp->RegList.Encoding;
2920
2921 assert(RlistEncode != RISCVZC::INVALID_RLIST);
2922 unsigned StackAdjBase = RISCVZC::getStackAdjBase(RlistVal: RlistEncode, IsRV64: isRV64());
2923 if (Negative != ExpectNegative || StackAdjustment % 16 != 0 ||
2924 StackAdjustment < StackAdjBase || (StackAdjustment - StackAdjBase) > 48) {
2925 int64_t Lower = StackAdjBase;
2926 int64_t Upper = StackAdjBase + 48;
2927 if (ExpectNegative) {
2928 Lower = -Lower;
2929 Upper = -Upper;
2930 std::swap(a&: Lower, b&: Upper);
2931 }
2932 return generateImmOutOfRangeError(ErrorLoc: S, Lower, Upper,
2933 Msg: "stack adjustment for register list must "
2934 "be a multiple of 16 bytes in the range");
2935 }
2936
2937 unsigned StackAdj = (StackAdjustment - StackAdjBase);
2938 Operands.push_back(Elt: RISCVOperand::createStackAdj(StackAdj, S));
2939 Lex();
2940 return ParseStatus::Success;
2941}
2942
2943/// Looks at a token type and creates the relevant operand from this
2944/// information, adding to Operands. If operand was parsed, returns false, else
2945/// true.
2946bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2947 // Check if the current operand has a custom associated parser, if so, try to
2948 // custom parse the operand, or fallback to the general approach.
2949 ParseStatus Result =
2950 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
2951 if (Result.isSuccess())
2952 return false;
2953 if (Result.isFailure())
2954 return true;
2955
2956 // Attempt to parse token as a register.
2957 if (parseRegister(Operands, AllowParens: true).isSuccess())
2958 return false;
2959
2960 // Attempt to parse token as an expression
2961 if (parseExpression(Operands).isSuccess()) {
2962 // Parse memory base register if present
2963 if (getLexer().is(K: AsmToken::LParen))
2964 return !parseMemOpBaseReg(Operands).isSuccess();
2965 return false;
2966 }
2967
2968 // Finally we have exhausted all options and must declare defeat.
2969 Error(L: getLoc(), Msg: "unknown operand");
2970 return true;
2971}
2972
2973bool RISCVAsmParser::parseInstruction(ParseInstructionInfo &Info,
2974 StringRef Name, SMLoc NameLoc,
2975 OperandVector &Operands) {
2976 // Apply mnemonic aliases because the destination mnemonic may have require
2977 // custom operand parsing. The generic tblgen'erated code does this later, at
2978 // the start of MatchInstructionImpl(), but that's too late for custom
2979 // operand parsing.
2980 const FeatureBitset &AvailableFeatures = getAvailableFeatures();
2981 applyMnemonicAliases(Mnemonic&: Name, Features: AvailableFeatures, VariantID: 0);
2982
2983 // First operand is token for instruction
2984 Operands.push_back(Elt: RISCVOperand::createToken(Str: Name, S: NameLoc));
2985
2986 // If there are no more operands, then finish
2987 if (getLexer().is(K: AsmToken::EndOfStatement)) {
2988 getParser().Lex(); // Consume the EndOfStatement.
2989 return false;
2990 }
2991
2992 // Parse first operand
2993 if (parseOperand(Operands, Mnemonic: Name))
2994 return true;
2995
2996 // Parse until end of statement, consuming commas between operands
2997 while (parseOptionalToken(T: AsmToken::Comma)) {
2998 // Parse next operand
2999 if (parseOperand(Operands, Mnemonic: Name))
3000 return true;
3001 }
3002
3003 if (getParser().parseEOL(ErrMsg: "unexpected token")) {
3004 getParser().eatToEndOfStatement();
3005 return true;
3006 }
3007 return false;
3008}
3009
3010bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
3011 RISCV::Specifier &Kind) {
3012 Kind = RISCV::S_None;
3013 if (const auto *RE = dyn_cast<MCSpecifierExpr>(Val: Expr)) {
3014 Kind = RE->getSpecifier();
3015 Expr = RE->getSubExpr();
3016 }
3017
3018 MCValue Res;
3019 if (Expr->evaluateAsRelocatable(Res, Asm: nullptr))
3020 return Res.getSpecifier() == RISCV::S_None;
3021 return false;
3022}
3023
3024bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
3025 MCValue Res;
3026 if (Expr->evaluateAsRelocatable(Res, Asm: nullptr)) {
3027 return Res.getSpecifier() == RISCV::S_None && Res.getAddSym() &&
3028 Res.getSubSym();
3029 }
3030 return false;
3031}
3032
3033ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
3034 StringRef IDVal = DirectiveID.getString();
3035
3036 if (IDVal == ".option")
3037 return parseDirectiveOption();
3038 if (IDVal == ".attribute")
3039 return parseDirectiveAttribute();
3040 if (IDVal == ".insn")
3041 return parseDirectiveInsn(L: DirectiveID.getLoc());
3042 if (IDVal == ".variant_cc")
3043 return parseDirectiveVariantCC();
3044
3045 return ParseStatus::NoMatch;
3046}
3047
3048bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
3049 bool FromOptionDirective) {
3050 for (auto &Feature : RISCVFeatureKV)
3051 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Ext: Feature.Key))
3052 clearFeatureBits(Feature: Feature.Value, FeatureString: Feature.Key);
3053
3054 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
3055 Arch, /*EnableExperimentalExtension=*/true,
3056 /*ExperimentalExtensionVersionCheck=*/true);
3057 if (!ParseResult) {
3058 std::string Buffer;
3059 raw_string_ostream OutputErrMsg(Buffer);
3060 handleAllErrors(E: ParseResult.takeError(), Handlers: [&](llvm::StringError &ErrMsg) {
3061 OutputErrMsg << "invalid arch name '" << Arch << "', "
3062 << ErrMsg.getMessage();
3063 });
3064
3065 return Error(L: Loc, Msg: OutputErrMsg.str());
3066 }
3067 auto &ISAInfo = *ParseResult;
3068
3069 for (auto &Feature : RISCVFeatureKV)
3070 if (ISAInfo->hasExtension(Ext: Feature.Key))
3071 setFeatureBits(Feature: Feature.Value, FeatureString: Feature.Key);
3072
3073 if (FromOptionDirective) {
3074 if (ISAInfo->getXLen() == 32 && isRV64())
3075 return Error(L: Loc, Msg: "bad arch string switching from rv64 to rv32");
3076 else if (ISAInfo->getXLen() == 64 && !isRV64())
3077 return Error(L: Loc, Msg: "bad arch string switching from rv32 to rv64");
3078 }
3079
3080 if (ISAInfo->getXLen() == 32)
3081 clearFeatureBits(Feature: RISCV::Feature64Bit, FeatureString: "64bit");
3082 else if (ISAInfo->getXLen() == 64)
3083 setFeatureBits(Feature: RISCV::Feature64Bit, FeatureString: "64bit");
3084 else
3085 return Error(L: Loc, Msg: "bad arch string " + Arch);
3086
3087 Result = ISAInfo->toString();
3088 return false;
3089}
3090
3091bool RISCVAsmParser::parseDirectiveOption() {
3092 MCAsmParser &Parser = getParser();
3093 // Get the option token.
3094 AsmToken Tok = Parser.getTok();
3095
3096 // At the moment only identifiers are supported.
3097 if (parseToken(T: AsmToken::Identifier, Msg: "expected identifier"))
3098 return true;
3099
3100 StringRef Option = Tok.getIdentifier();
3101
3102 if (Option == "push") {
3103 if (Parser.parseEOL())
3104 return true;
3105
3106 getTargetStreamer().emitDirectiveOptionPush();
3107 pushFeatureBits();
3108 return false;
3109 }
3110
3111 if (Option == "pop") {
3112 SMLoc StartLoc = Parser.getTok().getLoc();
3113 if (Parser.parseEOL())
3114 return true;
3115
3116 getTargetStreamer().emitDirectiveOptionPop();
3117 if (popFeatureBits())
3118 return Error(L: StartLoc, Msg: ".option pop with no .option push");
3119
3120 return false;
3121 }
3122
3123 if (Option == "arch") {
3124 SmallVector<RISCVOptionArchArg> Args;
3125 do {
3126 if (Parser.parseComma())
3127 return true;
3128
3129 RISCVOptionArchArgType Type;
3130 if (parseOptionalToken(T: AsmToken::Plus))
3131 Type = RISCVOptionArchArgType::Plus;
3132 else if (parseOptionalToken(T: AsmToken::Minus))
3133 Type = RISCVOptionArchArgType::Minus;
3134 else if (!Args.empty())
3135 return Error(L: Parser.getTok().getLoc(),
3136 Msg: "unexpected token, expected + or -");
3137 else
3138 Type = RISCVOptionArchArgType::Full;
3139
3140 if (Parser.getTok().isNot(K: AsmToken::Identifier))
3141 return Error(L: Parser.getTok().getLoc(),
3142 Msg: "unexpected token, expected identifier");
3143
3144 StringRef Arch = Parser.getTok().getString();
3145 SMLoc Loc = Parser.getTok().getLoc();
3146 Parser.Lex();
3147
3148 if (Type == RISCVOptionArchArgType::Full) {
3149 std::string Result;
3150 if (resetToArch(Arch, Loc, Result, FromOptionDirective: true))
3151 return true;
3152
3153 Args.emplace_back(Args&: Type, Args&: Result);
3154 break;
3155 }
3156
3157 if (isDigit(C: Arch.back()))
3158 return Error(
3159 L: Loc, Msg: "extension version number parsing not currently implemented");
3160
3161 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Ext: Arch);
3162 if (!enableExperimentalExtension() &&
3163 StringRef(Feature).starts_with(Prefix: "experimental-"))
3164 return Error(L: Loc, Msg: "unexpected experimental extensions");
3165 auto Ext = llvm::lower_bound(Range: RISCVFeatureKV, Value&: Feature);
3166 if (Ext == std::end(arr: RISCVFeatureKV) || StringRef(Ext->Key) != Feature)
3167 return Error(L: Loc, Msg: "unknown extension feature");
3168
3169 Args.emplace_back(Args&: Type, Args: Arch.str());
3170
3171 if (Type == RISCVOptionArchArgType::Plus) {
3172 FeatureBitset OldFeatureBits = STI->getFeatureBits();
3173
3174 setFeatureBits(Feature: Ext->Value, FeatureString: Ext->Key);
3175 auto ParseResult = RISCVFeatures::parseFeatureBits(IsRV64: isRV64(), FeatureBits: STI->getFeatureBits());
3176 if (!ParseResult) {
3177 copySTI().setFeatureBits(OldFeatureBits);
3178 setAvailableFeatures(ComputeAvailableFeatures(FB: OldFeatureBits));
3179
3180 std::string Buffer;
3181 raw_string_ostream OutputErrMsg(Buffer);
3182 handleAllErrors(E: ParseResult.takeError(), Handlers: [&](llvm::StringError &ErrMsg) {
3183 OutputErrMsg << ErrMsg.getMessage();
3184 });
3185
3186 return Error(L: Loc, Msg: OutputErrMsg.str());
3187 }
3188 } else {
3189 assert(Type == RISCVOptionArchArgType::Minus);
3190 // It is invalid to disable an extension that there are other enabled
3191 // extensions depend on it.
3192 // TODO: Make use of RISCVISAInfo to handle this
3193 for (auto &Feature : RISCVFeatureKV) {
3194 if (getSTI().hasFeature(Feature: Feature.Value) &&
3195 Feature.Implies.test(I: Ext->Value))
3196 return Error(L: Loc, Msg: Twine("can't disable ") + Ext->Key +
3197 " extension; " + Feature.Key +
3198 " extension requires " + Ext->Key +
3199 " extension");
3200 }
3201
3202 clearFeatureBits(Feature: Ext->Value, FeatureString: Ext->Key);
3203 }
3204 } while (Parser.getTok().isNot(K: AsmToken::EndOfStatement));
3205
3206 if (Parser.parseEOL())
3207 return true;
3208
3209 getTargetStreamer().emitDirectiveOptionArch(Args);
3210 return false;
3211 }
3212
3213 if (Option == "exact") {
3214 if (Parser.parseEOL())
3215 return true;
3216
3217 getTargetStreamer().emitDirectiveOptionExact();
3218 setFeatureBits(Feature: RISCV::FeatureExactAssembly, FeatureString: "exact-asm");
3219 clearFeatureBits(Feature: RISCV::FeatureRelax, FeatureString: "relax");
3220 return false;
3221 }
3222
3223 if (Option == "noexact") {
3224 if (Parser.parseEOL())
3225 return true;
3226
3227 getTargetStreamer().emitDirectiveOptionNoExact();
3228 clearFeatureBits(Feature: RISCV::FeatureExactAssembly, FeatureString: "exact-asm");
3229 setFeatureBits(Feature: RISCV::FeatureRelax, FeatureString: "relax");
3230 return false;
3231 }
3232
3233 if (Option == "rvc") {
3234 if (Parser.parseEOL())
3235 return true;
3236
3237 getTargetStreamer().emitDirectiveOptionRVC();
3238 setFeatureBits(Feature: RISCV::FeatureStdExtC, FeatureString: "c");
3239 return false;
3240 }
3241
3242 if (Option == "norvc") {
3243 if (Parser.parseEOL())
3244 return true;
3245
3246 getTargetStreamer().emitDirectiveOptionNoRVC();
3247 clearFeatureBits(Feature: RISCV::FeatureStdExtC, FeatureString: "c");
3248 clearFeatureBits(Feature: RISCV::FeatureStdExtZca, FeatureString: "zca");
3249 return false;
3250 }
3251
3252 if (Option == "pic") {
3253 if (Parser.parseEOL())
3254 return true;
3255
3256 getTargetStreamer().emitDirectiveOptionPIC();
3257 ParserOptions.IsPicEnabled = true;
3258 return false;
3259 }
3260
3261 if (Option == "nopic") {
3262 if (Parser.parseEOL())
3263 return true;
3264
3265 getTargetStreamer().emitDirectiveOptionNoPIC();
3266 ParserOptions.IsPicEnabled = false;
3267 return false;
3268 }
3269
3270 if (Option == "relax") {
3271 if (Parser.parseEOL())
3272 return true;
3273
3274 getTargetStreamer().emitDirectiveOptionRelax();
3275 setFeatureBits(Feature: RISCV::FeatureRelax, FeatureString: "relax");
3276 return false;
3277 }
3278
3279 if (Option == "norelax") {
3280 if (Parser.parseEOL())
3281 return true;
3282
3283 getTargetStreamer().emitDirectiveOptionNoRelax();
3284 clearFeatureBits(Feature: RISCV::FeatureRelax, FeatureString: "relax");
3285 return false;
3286 }
3287
3288 // Unknown option.
3289 Warning(L: Parser.getTok().getLoc(),
3290 Msg: "unknown option, expected 'push', 'pop', "
3291 "'rvc', 'norvc', 'arch', 'relax', 'norelax', "
3292 "'exact', or 'noexact'");
3293 Parser.eatToEndOfStatement();
3294 return false;
3295}
3296
3297/// parseDirectiveAttribute
3298/// ::= .attribute expression ',' ( expression | "string" )
3299/// ::= .attribute identifier ',' ( expression | "string" )
3300bool RISCVAsmParser::parseDirectiveAttribute() {
3301 MCAsmParser &Parser = getParser();
3302 int64_t Tag;
3303 SMLoc TagLoc;
3304 TagLoc = Parser.getTok().getLoc();
3305 if (Parser.getTok().is(K: AsmToken::Identifier)) {
3306 StringRef Name = Parser.getTok().getIdentifier();
3307 std::optional<unsigned> Ret =
3308 ELFAttrs::attrTypeFromString(tag: Name, tagNameMap: RISCVAttrs::getRISCVAttributeTags());
3309 if (!Ret)
3310 return Error(L: TagLoc, Msg: "attribute name not recognised: " + Name);
3311 Tag = *Ret;
3312 Parser.Lex();
3313 } else {
3314 const MCExpr *AttrExpr;
3315
3316 TagLoc = Parser.getTok().getLoc();
3317 if (Parser.parseExpression(Res&: AttrExpr))
3318 return true;
3319
3320 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: AttrExpr);
3321 if (check(P: !CE, Loc: TagLoc, Msg: "expected numeric constant"))
3322 return true;
3323
3324 Tag = CE->getValue();
3325 }
3326
3327 if (Parser.parseComma())
3328 return true;
3329
3330 StringRef StringValue;
3331 int64_t IntegerValue = 0;
3332 bool IsIntegerValue = true;
3333
3334 // RISC-V attributes have a string value if the tag number is odd
3335 // and an integer value if the tag number is even.
3336 if (Tag % 2)
3337 IsIntegerValue = false;
3338
3339 SMLoc ValueExprLoc = Parser.getTok().getLoc();
3340 if (IsIntegerValue) {
3341 const MCExpr *ValueExpr;
3342 if (Parser.parseExpression(Res&: ValueExpr))
3343 return true;
3344
3345 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: ValueExpr);
3346 if (!CE)
3347 return Error(L: ValueExprLoc, Msg: "expected numeric constant");
3348 IntegerValue = CE->getValue();
3349 } else {
3350 if (Parser.getTok().isNot(K: AsmToken::String))
3351 return Error(L: Parser.getTok().getLoc(), Msg: "expected string constant");
3352
3353 StringValue = Parser.getTok().getStringContents();
3354 Parser.Lex();
3355 }
3356
3357 if (Parser.parseEOL())
3358 return true;
3359
3360 if (IsIntegerValue)
3361 getTargetStreamer().emitAttribute(Attribute: Tag, Value: IntegerValue);
3362 else if (Tag != RISCVAttrs::ARCH)
3363 getTargetStreamer().emitTextAttribute(Attribute: Tag, String: StringValue);
3364 else {
3365 std::string Result;
3366 if (resetToArch(Arch: StringValue, Loc: ValueExprLoc, Result, FromOptionDirective: false))
3367 return true;
3368
3369 // Then emit the arch string.
3370 getTargetStreamer().emitTextAttribute(Attribute: Tag, String: Result);
3371 }
3372
3373 return false;
3374}
3375
3376bool isValidInsnFormat(StringRef Format, const MCSubtargetInfo &STI) {
3377 return StringSwitch<bool>(Format)
3378 .Cases(CaseStrings: {"r", "r4", "i", "b", "sb", "u", "j", "uj", "s"}, Value: true)
3379 .Cases(CaseStrings: {"cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj"},
3380 Value: STI.hasFeature(Feature: RISCV::FeatureStdExtZca))
3381 .Cases(CaseStrings: {"qc.eai", "qc.ei", "qc.eb", "qc.ej", "qc.es"},
3382 Value: !STI.hasFeature(Feature: RISCV::Feature64Bit))
3383 .Default(Value: false);
3384}
3385
3386/// parseDirectiveInsn
3387/// ::= .insn [ format encoding, (operands (, operands)*) ]
3388/// ::= .insn [ length, value ]
3389/// ::= .insn [ value ]
3390bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3391 MCAsmParser &Parser = getParser();
3392
3393 // Expect instruction format as identifier.
3394 StringRef Format;
3395 SMLoc ErrorLoc = Parser.getTok().getLoc();
3396 if (Parser.parseIdentifier(Res&: Format)) {
3397 // Try parsing .insn [ length , ] value
3398 std::optional<int64_t> Length;
3399 int64_t Value = 0;
3400 if (Parser.parseAbsoluteExpression(Res&: Value))
3401 return true;
3402 if (Parser.parseOptionalToken(T: AsmToken::Comma)) {
3403 Length = Value;
3404 if (Parser.parseAbsoluteExpression(Res&: Value))
3405 return true;
3406
3407 if (*Length == 0 || (*Length % 2) != 0)
3408 return Error(L: ErrorLoc,
3409 Msg: "instruction lengths must be a non-zero multiple of two");
3410
3411 // TODO: Support Instructions > 64 bits.
3412 if (*Length > 8)
3413 return Error(L: ErrorLoc,
3414 Msg: "instruction lengths over 64 bits are not supported");
3415 }
3416
3417 // We only derive a length from the encoding for 16- and 32-bit
3418 // instructions, as the encodings for longer instructions are not frozen in
3419 // the spec.
3420 int64_t EncodingDerivedLength = ((Value & 0b11) == 0b11) ? 4 : 2;
3421
3422 if (Length) {
3423 // Only check the length against the encoding if the length is present and
3424 // could match
3425 if ((*Length <= 4) && (*Length != EncodingDerivedLength))
3426 return Error(L: ErrorLoc,
3427 Msg: "instruction length does not match the encoding");
3428
3429 if (!isUIntN(N: *Length * 8, x: Value))
3430 return Error(L: ErrorLoc, Msg: "encoding value does not fit into instruction");
3431 } else {
3432 if (!isUIntN(N: EncodingDerivedLength * 8, x: Value))
3433 return Error(L: ErrorLoc, Msg: "encoding value does not fit into instruction");
3434 }
3435
3436 if (!getSTI().hasFeature(Feature: RISCV::FeatureStdExtZca) &&
3437 (EncodingDerivedLength == 2))
3438 return Error(L: ErrorLoc, Msg: "compressed instructions are not allowed");
3439
3440 if (getParser().parseEOL(ErrMsg: "invalid operand for instruction")) {
3441 getParser().eatToEndOfStatement();
3442 return true;
3443 }
3444
3445 unsigned Opcode;
3446 if (Length) {
3447 switch (*Length) {
3448 case 2:
3449 Opcode = RISCV::Insn16;
3450 break;
3451 case 4:
3452 Opcode = RISCV::Insn32;
3453 break;
3454 case 6:
3455 Opcode = RISCV::Insn48;
3456 break;
3457 case 8:
3458 Opcode = RISCV::Insn64;
3459 break;
3460 default:
3461 llvm_unreachable("Error should have already been emitted");
3462 }
3463 } else
3464 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3465
3466 emitToStreamer(S&: getStreamer(), Inst: MCInstBuilder(Opcode).addImm(Val: Value));
3467 return false;
3468 }
3469
3470 if (!isValidInsnFormat(Format, STI: getSTI()))
3471 return Error(L: ErrorLoc, Msg: "invalid instruction format");
3472
3473 std::string FormatName = (".insn_" + Format).str();
3474
3475 ParseInstructionInfo Info;
3476 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
3477
3478 if (parseInstruction(Info, Name: FormatName, NameLoc: L, Operands))
3479 return true;
3480
3481 unsigned Opcode;
3482 uint64_t ErrorInfo;
3483 return matchAndEmitInstruction(IDLoc: L, Opcode, Operands, Out&: Parser.getStreamer(),
3484 ErrorInfo,
3485 /*MatchingInlineAsm=*/false);
3486}
3487
3488/// parseDirectiveVariantCC
3489/// ::= .variant_cc symbol
3490bool RISCVAsmParser::parseDirectiveVariantCC() {
3491 StringRef Name;
3492 if (getParser().parseIdentifier(Res&: Name))
3493 return TokError(Msg: "expected symbol name");
3494 if (parseEOL())
3495 return true;
3496 getTargetStreamer().emitDirectiveVariantCC(
3497 Symbol&: *getContext().getOrCreateSymbol(Name));
3498 return false;
3499}
3500
3501void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
3502 MCInst CInst;
3503 bool Res = false;
3504 const MCSubtargetInfo &STI = getSTI();
3505 if (!STI.hasFeature(Feature: RISCV::FeatureExactAssembly))
3506 Res = RISCVRVC::compress(OutInst&: CInst, MI: Inst, STI);
3507 if (Res)
3508 ++RISCVNumInstrsCompressed;
3509 S.emitInstruction(Inst: (Res ? CInst : Inst), STI);
3510}
3511
3512void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
3513 MCStreamer &Out) {
3514 SmallVector<MCInst, 8> Seq;
3515 RISCVMatInt::generateMCInstSeq(Val: Value, STI: getSTI(), DestReg, Insts&: Seq);
3516
3517 for (MCInst &Inst : Seq) {
3518 emitToStreamer(S&: Out, Inst);
3519 }
3520}
3521
3522void RISCVAsmParser::emitAuipcInstPair(MCRegister DestReg, MCRegister TmpReg,
3523 const MCExpr *Symbol,
3524 RISCV::Specifier VKHi,
3525 unsigned SecondOpcode, SMLoc IDLoc,
3526 MCStreamer &Out) {
3527 // A pair of instructions for PC-relative addressing; expands to
3528 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3529 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3530 MCContext &Ctx = getContext();
3531
3532 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol(Name: "pcrel_hi");
3533 Out.emitLabel(Symbol: TmpLabel);
3534
3535 const auto *SymbolHi = MCSpecifierExpr::create(Expr: Symbol, S: VKHi, Ctx);
3536 emitToStreamer(S&: Out,
3537 Inst: MCInstBuilder(RISCV::AUIPC).addReg(Reg: TmpReg).addExpr(Val: SymbolHi));
3538
3539 const MCExpr *RefToLinkTmpLabel = MCSpecifierExpr::create(
3540 Expr: MCSymbolRefExpr::create(Symbol: TmpLabel, Ctx), S: RISCV::S_PCREL_LO, Ctx);
3541
3542 emitToStreamer(S&: Out, Inst: MCInstBuilder(SecondOpcode)
3543 .addReg(Reg: DestReg)
3544 .addReg(Reg: TmpReg)
3545 .addExpr(Val: RefToLinkTmpLabel));
3546}
3547
3548void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
3549 MCStreamer &Out) {
3550 // The load local address pseudo-instruction "lla" is used in PC-relative
3551 // addressing of local symbols:
3552 // lla rdest, symbol
3553 // expands to
3554 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3555 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3556 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
3557 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
3558 emitAuipcInstPair(DestReg, TmpReg: DestReg, Symbol, VKHi: RISCV::S_PCREL_HI, SecondOpcode: RISCV::ADDI,
3559 IDLoc, Out);
3560}
3561
3562void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3563 MCStreamer &Out) {
3564 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3565 // addressing of global symbols:
3566 // lga rdest, symbol
3567 // expands to
3568 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3569 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3570 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
3571 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
3572 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3573 emitAuipcInstPair(DestReg, TmpReg: DestReg, Symbol, VKHi: RISCV::S_GOT_HI, SecondOpcode,
3574 IDLoc, Out);
3575}
3576
3577void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
3578 MCStreamer &Out) {
3579 // The load address pseudo-instruction "la" is used in PC-relative and
3580 // GOT-indirect addressing of global symbols:
3581 // la rdest, symbol
3582 // is an alias for either (for non-PIC)
3583 // lla rdest, symbol
3584 // or (for PIC)
3585 // lga rdest, symbol
3586 if (ParserOptions.IsPicEnabled)
3587 emitLoadGlobalAddress(Inst, IDLoc, Out);
3588 else
3589 emitLoadLocalAddress(Inst, IDLoc, Out);
3590}
3591
3592void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
3593 MCStreamer &Out) {
3594 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3595 // initial-exec TLS model addressing of global symbols:
3596 // la.tls.ie rdest, symbol
3597 // expands to
3598 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3599 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3600 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
3601 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
3602 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3603 emitAuipcInstPair(DestReg, TmpReg: DestReg, Symbol, VKHi: ELF::R_RISCV_TLS_GOT_HI20,
3604 SecondOpcode, IDLoc, Out);
3605}
3606
3607void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
3608 MCStreamer &Out) {
3609 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3610 // global-dynamic TLS model addressing of global symbols:
3611 // la.tls.gd rdest, symbol
3612 // expands to
3613 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3614 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3615 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
3616 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
3617 emitAuipcInstPair(DestReg, TmpReg: DestReg, Symbol, VKHi: ELF::R_RISCV_TLS_GD_HI20,
3618 SecondOpcode: RISCV::ADDI, IDLoc, Out);
3619}
3620
3621void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3622 SMLoc IDLoc, MCStreamer &Out,
3623 bool HasTmpReg) {
3624 // The load/store pseudo-instruction does a pc-relative load with
3625 // a symbol.
3626 //
3627 // The expansion looks like this
3628 //
3629 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3630 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3631 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3632 MCRegister DestReg = Inst.getOperand(i: DestRegOpIdx).getReg();
3633 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3634 MCRegister TmpReg = Inst.getOperand(i: 0).getReg();
3635
3636 // If TmpReg is a GPR pair, get the even register.
3637 if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(Reg: TmpReg)) {
3638 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3639 TmpReg = RI->getSubReg(Reg: TmpReg, Idx: RISCV::sub_gpr_even);
3640 }
3641
3642 const MCExpr *Symbol = Inst.getOperand(i: SymbolOpIdx).getExpr();
3643 emitAuipcInstPair(DestReg, TmpReg, Symbol, VKHi: RISCV::S_PCREL_HI, SecondOpcode: Opcode, IDLoc,
3644 Out);
3645}
3646
3647void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3648 int64_t Width, SMLoc IDLoc,
3649 MCStreamer &Out) {
3650 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3651 // amounts dependent on the XLEN.
3652 //
3653 // The expansion looks like this
3654 //
3655 // SLLI rd, rs, XLEN - Width
3656 // SR[A|R]I rd, rd, XLEN - Width
3657 const MCOperand &DestReg = Inst.getOperand(i: 0);
3658 const MCOperand &SourceReg = Inst.getOperand(i: 1);
3659
3660 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3661 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3662
3663 assert(ShAmt > 0 && "Shift amount must be non-zero.");
3664
3665 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::SLLI)
3666 .addOperand(Op: DestReg)
3667 .addOperand(Op: SourceReg)
3668 .addImm(Val: ShAmt));
3669
3670 emitToStreamer(S&: Out, Inst: MCInstBuilder(SecondOpcode)
3671 .addOperand(Op: DestReg)
3672 .addOperand(Op: DestReg)
3673 .addImm(Val: ShAmt));
3674}
3675
3676void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3677 MCStreamer &Out) {
3678 if (Inst.getNumOperands() == 3) {
3679 // unmasked va >= x
3680 //
3681 // pseudoinstruction: vmsge{u}.vx vd, va, x
3682 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3683 emitToStreamer(S&: Out, Inst: MCInstBuilder(Opcode)
3684 .addOperand(Op: Inst.getOperand(i: 0))
3685 .addOperand(Op: Inst.getOperand(i: 1))
3686 .addOperand(Op: Inst.getOperand(i: 2))
3687 .addReg(Reg: MCRegister())
3688 .setLoc(IDLoc));
3689 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMNAND_MM)
3690 .addOperand(Op: Inst.getOperand(i: 0))
3691 .addOperand(Op: Inst.getOperand(i: 0))
3692 .addOperand(Op: Inst.getOperand(i: 0))
3693 .setLoc(IDLoc));
3694 } else if (Inst.getNumOperands() == 4) {
3695 // masked va >= x, vd != v0
3696 //
3697 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3698 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3699 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
3700 "The destination register should not be V0.");
3701 emitToStreamer(S&: Out, Inst: MCInstBuilder(Opcode)
3702 .addOperand(Op: Inst.getOperand(i: 0))
3703 .addOperand(Op: Inst.getOperand(i: 1))
3704 .addOperand(Op: Inst.getOperand(i: 2))
3705 .addOperand(Op: Inst.getOperand(i: 3))
3706 .setLoc(IDLoc));
3707 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMXOR_MM)
3708 .addOperand(Op: Inst.getOperand(i: 0))
3709 .addOperand(Op: Inst.getOperand(i: 0))
3710 .addReg(Reg: RISCV::V0)
3711 .setLoc(IDLoc));
3712 } else if (Inst.getNumOperands() == 5 &&
3713 Inst.getOperand(i: 0).getReg() == RISCV::V0) {
3714 // masked va >= x, vd == v0
3715 //
3716 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3717 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3718 assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
3719 "The destination register should be V0.");
3720 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3721 "The temporary vector register should not be V0.");
3722 emitToStreamer(S&: Out, Inst: MCInstBuilder(Opcode)
3723 .addOperand(Op: Inst.getOperand(i: 1))
3724 .addOperand(Op: Inst.getOperand(i: 2))
3725 .addOperand(Op: Inst.getOperand(i: 3))
3726 .addReg(Reg: MCRegister())
3727 .setLoc(IDLoc));
3728 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMANDN_MM)
3729 .addOperand(Op: Inst.getOperand(i: 0))
3730 .addOperand(Op: Inst.getOperand(i: 0))
3731 .addOperand(Op: Inst.getOperand(i: 1))
3732 .setLoc(IDLoc));
3733 } else if (Inst.getNumOperands() == 5) {
3734 // masked va >= x, any vd
3735 //
3736 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3737 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3738 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3739 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3740 "The temporary vector register should not be V0.");
3741 emitToStreamer(S&: Out, Inst: MCInstBuilder(Opcode)
3742 .addOperand(Op: Inst.getOperand(i: 1))
3743 .addOperand(Op: Inst.getOperand(i: 2))
3744 .addOperand(Op: Inst.getOperand(i: 3))
3745 .addReg(Reg: MCRegister())
3746 .setLoc(IDLoc));
3747 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMANDN_MM)
3748 .addOperand(Op: Inst.getOperand(i: 1))
3749 .addReg(Reg: RISCV::V0)
3750 .addOperand(Op: Inst.getOperand(i: 1))
3751 .setLoc(IDLoc));
3752 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMANDN_MM)
3753 .addOperand(Op: Inst.getOperand(i: 0))
3754 .addOperand(Op: Inst.getOperand(i: 0))
3755 .addReg(Reg: RISCV::V0)
3756 .setLoc(IDLoc));
3757 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMOR_MM)
3758 .addOperand(Op: Inst.getOperand(i: 0))
3759 .addOperand(Op: Inst.getOperand(i: 1))
3760 .addOperand(Op: Inst.getOperand(i: 0))
3761 .setLoc(IDLoc));
3762 }
3763}
3764
3765bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
3766 OperandVector &Operands) {
3767 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
3768 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
3769 if (Inst.getOperand(i: 2).getReg() != RISCV::X4) {
3770 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3771 return Error(L: ErrorLoc, Msg: "the second input operand must be tp/x4 when using "
3772 "%tprel_add specifier");
3773 }
3774
3775 return false;
3776}
3777
3778bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
3779 OperandVector &Operands) {
3780 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
3781 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
3782 if (Inst.getOperand(i: 0).getReg() != RISCV::X5) {
3783 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3784 return Error(L: ErrorLoc, Msg: "the output operand must be t0/x5 when using "
3785 "%tlsdesc_call specifier");
3786 }
3787
3788 return false;
3789}
3790
3791std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
3792 return RISCVOperand::createReg(Reg: MCRegister(), S: llvm::SMLoc(), E: llvm::SMLoc());
3793}
3794
3795std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
3796 return RISCVOperand::createFRMArg(FRM: RISCVFPRndMode::RoundingMode::DYN,
3797 S: llvm::SMLoc());
3798}
3799
3800std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3801 return RISCVOperand::createFRMArg(FRM: RISCVFPRndMode::RoundingMode::RNE,
3802 S: llvm::SMLoc());
3803}
3804
3805static unsigned getNFforLXSEG(unsigned Opcode) {
3806 switch (Opcode) {
3807 default:
3808 return 1;
3809 case RISCV::VLOXSEG2EI8_V:
3810 case RISCV::VLOXSEG2EI16_V:
3811 case RISCV::VLOXSEG2EI32_V:
3812 case RISCV::VLOXSEG2EI64_V:
3813 case RISCV::VLUXSEG2EI8_V:
3814 case RISCV::VLUXSEG2EI16_V:
3815 case RISCV::VLUXSEG2EI32_V:
3816 case RISCV::VLUXSEG2EI64_V:
3817 return 2;
3818 case RISCV::VLOXSEG3EI8_V:
3819 case RISCV::VLOXSEG3EI16_V:
3820 case RISCV::VLOXSEG3EI32_V:
3821 case RISCV::VLOXSEG3EI64_V:
3822 case RISCV::VLUXSEG3EI8_V:
3823 case RISCV::VLUXSEG3EI16_V:
3824 case RISCV::VLUXSEG3EI32_V:
3825 case RISCV::VLUXSEG3EI64_V:
3826 return 3;
3827 case RISCV::VLOXSEG4EI8_V:
3828 case RISCV::VLOXSEG4EI16_V:
3829 case RISCV::VLOXSEG4EI32_V:
3830 case RISCV::VLOXSEG4EI64_V:
3831 case RISCV::VLUXSEG4EI8_V:
3832 case RISCV::VLUXSEG4EI16_V:
3833 case RISCV::VLUXSEG4EI32_V:
3834 case RISCV::VLUXSEG4EI64_V:
3835 return 4;
3836 case RISCV::VLOXSEG5EI8_V:
3837 case RISCV::VLOXSEG5EI16_V:
3838 case RISCV::VLOXSEG5EI32_V:
3839 case RISCV::VLOXSEG5EI64_V:
3840 case RISCV::VLUXSEG5EI8_V:
3841 case RISCV::VLUXSEG5EI16_V:
3842 case RISCV::VLUXSEG5EI32_V:
3843 case RISCV::VLUXSEG5EI64_V:
3844 return 5;
3845 case RISCV::VLOXSEG6EI8_V:
3846 case RISCV::VLOXSEG6EI16_V:
3847 case RISCV::VLOXSEG6EI32_V:
3848 case RISCV::VLOXSEG6EI64_V:
3849 case RISCV::VLUXSEG6EI8_V:
3850 case RISCV::VLUXSEG6EI16_V:
3851 case RISCV::VLUXSEG6EI32_V:
3852 case RISCV::VLUXSEG6EI64_V:
3853 return 6;
3854 case RISCV::VLOXSEG7EI8_V:
3855 case RISCV::VLOXSEG7EI16_V:
3856 case RISCV::VLOXSEG7EI32_V:
3857 case RISCV::VLOXSEG7EI64_V:
3858 case RISCV::VLUXSEG7EI8_V:
3859 case RISCV::VLUXSEG7EI16_V:
3860 case RISCV::VLUXSEG7EI32_V:
3861 case RISCV::VLUXSEG7EI64_V:
3862 return 7;
3863 case RISCV::VLOXSEG8EI8_V:
3864 case RISCV::VLOXSEG8EI16_V:
3865 case RISCV::VLOXSEG8EI32_V:
3866 case RISCV::VLOXSEG8EI64_V:
3867 case RISCV::VLUXSEG8EI8_V:
3868 case RISCV::VLUXSEG8EI16_V:
3869 case RISCV::VLUXSEG8EI32_V:
3870 case RISCV::VLUXSEG8EI64_V:
3871 return 8;
3872 }
3873}
3874
3875unsigned getLMULFromVectorRegister(MCRegister Reg) {
3876 if (RISCVMCRegisterClasses[RISCV::VRM2RegClassID].contains(Reg))
3877 return 2;
3878 if (RISCVMCRegisterClasses[RISCV::VRM4RegClassID].contains(Reg))
3879 return 4;
3880 if (RISCVMCRegisterClasses[RISCV::VRM8RegClassID].contains(Reg))
3881 return 8;
3882 return 1;
3883}
3884
3885bool RISCVAsmParser::validateInstruction(MCInst &Inst,
3886 OperandVector &Operands) {
3887 unsigned Opcode = Inst.getOpcode();
3888
3889 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3890 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3891 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
3892 MCRegister TempReg = Inst.getOperand(i: 1).getReg();
3893 if (DestReg == TempReg) {
3894 SMLoc Loc = Operands.back()->getStartLoc();
3895 return Error(L: Loc, Msg: "the temporary vector register cannot be the same as "
3896 "the destination register");
3897 }
3898 }
3899
3900 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3901 Opcode == RISCV::TH_LWD) {
3902 MCRegister Rd1 = Inst.getOperand(i: 0).getReg();
3903 MCRegister Rd2 = Inst.getOperand(i: 1).getReg();
3904 MCRegister Rs1 = Inst.getOperand(i: 2).getReg();
3905 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3906 if (Rs1 == Rd1 || Rs1 == Rd2 || Rd1 == Rd2) {
3907 SMLoc Loc = Operands[1]->getStartLoc();
3908 return Error(L: Loc, Msg: "rs1, rd1, and rd2 cannot overlap");
3909 }
3910 }
3911
3912 if (Opcode == RISCV::CM_MVSA01 || Opcode == RISCV::QC_CM_MVSA01) {
3913 MCRegister Rs1 = Inst.getOperand(i: 0).getReg();
3914 MCRegister Rs2 = Inst.getOperand(i: 1).getReg();
3915 if (Rs1 == Rs2) {
3916 SMLoc Loc = Operands[1]->getStartLoc();
3917 return Error(L: Loc, Msg: "rs1 and rs2 must be different");
3918 }
3919 }
3920
3921 const MCInstrDesc &MCID = MII.get(Opcode);
3922 if (!(MCID.TSFlags & RISCVII::RVVConstraintMask))
3923 return false;
3924
3925 int DestIdx = RISCV::getNamedOperandIdx(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vd);
3926 MCRegister DestReg = Inst.getOperand(i: DestIdx).getReg();
3927
3928 // Operands[1] or Operands[2] will be the first operand, DestReg.
3929 const MCParsedAsmOperand *ParsedOp = Operands[1].get();
3930 if (!ParsedOp->isReg()) {
3931 // XSfvcp instructions may have an immediate before vd.
3932 // FIXME: Is there a better way to do this?
3933 ParsedOp = Operands[2].get();
3934 }
3935 assert(ParsedOp->getReg() == DestReg && "Can't find parsed dest operand");
3936 SMLoc Loc = ParsedOp->getStartLoc();
3937
3938 unsigned Lmul = getLMULFromVectorRegister(Reg: DestReg);
3939 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3940 unsigned DestEncoding = RI->getEncodingValue(Reg: DestReg);
3941 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3942 int VS2Idx =
3943 RISCV::getNamedOperandIdx(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vs2);
3944 assert(VS2Idx >= 0 && "No vs2 operand?");
3945 unsigned CheckEncoding =
3946 RI->getEncodingValue(Reg: Inst.getOperand(i: VS2Idx).getReg());
3947 unsigned NF = getNFforLXSEG(Opcode);
3948 for (unsigned i = 0; i < std::max(a: NF, b: Lmul); i++) {
3949 if ((DestEncoding + i) == CheckEncoding)
3950 return Error(L: Loc, Msg: "the destination vector register group cannot overlap"
3951 " the source vector register group");
3952 }
3953 }
3954 if (MCID.TSFlags & RISCVII::VS1Constraint) {
3955 int VS1Idx =
3956 RISCV::getNamedOperandIdx(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vs1);
3957 // FIXME: The vs1 constraint is used on scalar and imm instructions so we
3958 // need to check that the operand exists.
3959 if (VS1Idx >= 0) {
3960 unsigned CheckEncoding =
3961 RI->getEncodingValue(Reg: Inst.getOperand(i: VS1Idx).getReg());
3962 for (unsigned i = 0; i < Lmul; i++) {
3963 if ((DestEncoding + i) == CheckEncoding)
3964 return Error(L: Loc,
3965 Msg: "the destination vector register group cannot overlap"
3966 " the source vector register group");
3967 }
3968 }
3969 }
3970
3971 if (MCID.TSFlags & RISCVII::VMConstraint) {
3972 int VMIdx = RISCV::getNamedOperandIdx(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vm);
3973 assert(VMIdx >= 0 && "No vm operand?");
3974
3975 if (DestReg == RISCV::V0) {
3976 if (MCID.operands()[Inst.getNumOperands() - 1].OperandType !=
3977 RISCVOp::OPERAND_VMASK)
3978 return Error(L: Loc, Msg: "the destination vector register group cannot be V0");
3979
3980 // Regardless masked or unmasked version, the number of operands is the
3981 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3982 // actually. We need to check the operand to see whether it is masked or
3983 // not.
3984 MCRegister CheckReg = Inst.getOperand(i: VMIdx).getReg();
3985 assert((!CheckReg.isValid() || CheckReg == RISCV::V0) &&
3986 "Unexpected mask operand register");
3987 if (CheckReg.isValid())
3988 return Error(L: Loc, Msg: "the destination vector register group cannot overlap"
3989 " the mask register");
3990 }
3991 }
3992
3993 return false;
3994}
3995
3996bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
3997 OperandVector &Operands,
3998 MCStreamer &Out) {
3999 Inst.setLoc(IDLoc);
4000
4001 switch (Inst.getOpcode()) {
4002 default:
4003 break;
4004 case RISCV::PseudoC_ADDI_NOP: {
4005 if (Inst.getOperand(i: 2).getImm() == 0)
4006 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::C_NOP));
4007 else
4008 emitToStreamer(
4009 S&: Out, Inst: MCInstBuilder(RISCV::C_NOP_HINT).addOperand(Op: Inst.getOperand(i: 2)));
4010 return false;
4011 }
4012 case RISCV::PACK: {
4013 // Convert PACK wth RS2==X0 to ZEXT_H_RV32 to match disassembler output.
4014 if (Inst.getOperand(i: 2).getReg() != RISCV::X0)
4015 break;
4016 if (getSTI().hasFeature(Feature: RISCV::Feature64Bit))
4017 break;
4018 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::ZEXT_H_RV32)
4019 .addOperand(Op: Inst.getOperand(i: 0))
4020 .addOperand(Op: Inst.getOperand(i: 1)));
4021 return false;
4022 }
4023 case RISCV::PACKW: {
4024 // Convert PACKW with RS2==X0 to ZEXT_H_RV64 to match disassembler output.
4025 if (Inst.getOperand(i: 2).getReg() != RISCV::X0)
4026 break;
4027 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::ZEXT_H_RV64)
4028 .addOperand(Op: Inst.getOperand(i: 0))
4029 .addOperand(Op: Inst.getOperand(i: 1)));
4030 return false;
4031 }
4032 case RISCV::PseudoLLAImm:
4033 case RISCV::PseudoLAImm:
4034 case RISCV::PseudoLI: {
4035 MCRegister Reg = Inst.getOperand(i: 0).getReg();
4036 const MCOperand &Op1 = Inst.getOperand(i: 1);
4037 if (Op1.isExpr()) {
4038 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
4039 // Just convert to an addi. This allows compatibility with gas.
4040 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::ADDI)
4041 .addReg(Reg)
4042 .addReg(Reg: RISCV::X0)
4043 .addExpr(Val: Op1.getExpr()));
4044 return false;
4045 }
4046 int64_t Imm = Inst.getOperand(i: 1).getImm();
4047 // On RV32 the immediate here can either be a signed or an unsigned
4048 // 32-bit number. Sign extension has to be performed to ensure that Imm
4049 // represents the expected signed 64-bit number.
4050 if (!isRV64())
4051 Imm = SignExtend64<32>(x: Imm);
4052 emitLoadImm(DestReg: Reg, Value: Imm, Out);
4053 return false;
4054 }
4055 case RISCV::PseudoLLA:
4056 emitLoadLocalAddress(Inst, IDLoc, Out);
4057 return false;
4058 case RISCV::PseudoLGA:
4059 emitLoadGlobalAddress(Inst, IDLoc, Out);
4060 return false;
4061 case RISCV::PseudoLA:
4062 emitLoadAddress(Inst, IDLoc, Out);
4063 return false;
4064 case RISCV::PseudoLA_TLS_IE:
4065 emitLoadTLSIEAddress(Inst, IDLoc, Out);
4066 return false;
4067 case RISCV::PseudoLA_TLS_GD:
4068 emitLoadTLSGDAddress(Inst, IDLoc, Out);
4069 return false;
4070 case RISCV::PseudoLB:
4071 case RISCV::PseudoQC_E_LB:
4072 emitLoadStoreSymbol(Inst, Opcode: RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
4073 return false;
4074 case RISCV::PseudoLBU:
4075 case RISCV::PseudoQC_E_LBU:
4076 emitLoadStoreSymbol(Inst, Opcode: RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
4077 return false;
4078 case RISCV::PseudoLH:
4079 case RISCV::PseudoQC_E_LH:
4080 emitLoadStoreSymbol(Inst, Opcode: RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
4081 return false;
4082 case RISCV::PseudoLHU:
4083 case RISCV::PseudoQC_E_LHU:
4084 emitLoadStoreSymbol(Inst, Opcode: RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
4085 return false;
4086 case RISCV::PseudoLW:
4087 case RISCV::PseudoQC_E_LW:
4088 emitLoadStoreSymbol(Inst, Opcode: RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
4089 return false;
4090 case RISCV::PseudoLWU:
4091 emitLoadStoreSymbol(Inst, Opcode: RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
4092 return false;
4093 case RISCV::PseudoLD:
4094 emitLoadStoreSymbol(Inst, Opcode: RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
4095 return false;
4096 case RISCV::PseudoLD_RV32:
4097 emitLoadStoreSymbol(Inst, Opcode: RISCV::LD_RV32, IDLoc, Out, /*HasTmpReg=*/false);
4098 return false;
4099 case RISCV::PseudoFLH:
4100 emitLoadStoreSymbol(Inst, Opcode: RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
4101 return false;
4102 case RISCV::PseudoFLW:
4103 emitLoadStoreSymbol(Inst, Opcode: RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
4104 return false;
4105 case RISCV::PseudoFLD:
4106 emitLoadStoreSymbol(Inst, Opcode: RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
4107 return false;
4108 case RISCV::PseudoFLQ:
4109 emitLoadStoreSymbol(Inst, Opcode: RISCV::FLQ, IDLoc, Out, /*HasTmpReg=*/true);
4110 return false;
4111 case RISCV::PseudoSB:
4112 case RISCV::PseudoQC_E_SB:
4113 emitLoadStoreSymbol(Inst, Opcode: RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
4114 return false;
4115 case RISCV::PseudoSH:
4116 case RISCV::PseudoQC_E_SH:
4117 emitLoadStoreSymbol(Inst, Opcode: RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
4118 return false;
4119 case RISCV::PseudoSW:
4120 case RISCV::PseudoQC_E_SW:
4121 emitLoadStoreSymbol(Inst, Opcode: RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
4122 return false;
4123 case RISCV::PseudoSD:
4124 emitLoadStoreSymbol(Inst, Opcode: RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
4125 return false;
4126 case RISCV::PseudoSD_RV32:
4127 emitLoadStoreSymbol(Inst, Opcode: RISCV::SD_RV32, IDLoc, Out, /*HasTmpReg=*/true);
4128 return false;
4129 case RISCV::PseudoFSH:
4130 emitLoadStoreSymbol(Inst, Opcode: RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
4131 return false;
4132 case RISCV::PseudoFSW:
4133 emitLoadStoreSymbol(Inst, Opcode: RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
4134 return false;
4135 case RISCV::PseudoFSD:
4136 emitLoadStoreSymbol(Inst, Opcode: RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
4137 return false;
4138 case RISCV::PseudoFSQ:
4139 emitLoadStoreSymbol(Inst, Opcode: RISCV::FSQ, IDLoc, Out, /*HasTmpReg=*/true);
4140 return false;
4141 case RISCV::PseudoAddTPRel:
4142 if (checkPseudoAddTPRel(Inst, Operands))
4143 return true;
4144 break;
4145 case RISCV::PseudoTLSDESCCall:
4146 if (checkPseudoTLSDESCCall(Inst, Operands))
4147 return true;
4148 break;
4149 case RISCV::PseudoSEXT_B:
4150 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
4151 return false;
4152 case RISCV::PseudoSEXT_H:
4153 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
4154 return false;
4155 case RISCV::PseudoZEXT_H:
4156 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
4157 return false;
4158 case RISCV::PseudoZEXT_W:
4159 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
4160 return false;
4161 case RISCV::PseudoVMSGEU_VX:
4162 case RISCV::PseudoVMSGEU_VX_M:
4163 case RISCV::PseudoVMSGEU_VX_M_T:
4164 emitVMSGE(Inst, Opcode: RISCV::VMSLTU_VX, IDLoc, Out);
4165 return false;
4166 case RISCV::PseudoVMSGE_VX:
4167 case RISCV::PseudoVMSGE_VX_M:
4168 case RISCV::PseudoVMSGE_VX_M_T:
4169 emitVMSGE(Inst, Opcode: RISCV::VMSLT_VX, IDLoc, Out);
4170 return false;
4171 case RISCV::PseudoVMSGE_VI:
4172 case RISCV::PseudoVMSLT_VI: {
4173 // These instructions are signed and so is immediate so we can subtract one
4174 // and change the opcode.
4175 int64_t Imm = Inst.getOperand(i: 2).getImm();
4176 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
4177 : RISCV::VMSLE_VI;
4178 emitToStreamer(S&: Out, Inst: MCInstBuilder(Opc)
4179 .addOperand(Op: Inst.getOperand(i: 0))
4180 .addOperand(Op: Inst.getOperand(i: 1))
4181 .addImm(Val: Imm - 1)
4182 .addOperand(Op: Inst.getOperand(i: 3))
4183 .setLoc(IDLoc));
4184 return false;
4185 }
4186 case RISCV::PseudoVMSGEU_VI:
4187 case RISCV::PseudoVMSLTU_VI: {
4188 int64_t Imm = Inst.getOperand(i: 2).getImm();
4189 // Unsigned comparisons are tricky because the immediate is signed. If the
4190 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
4191 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
4192 // vmsne v0, v1, v1 which is always false.
4193 if (Imm == 0) {
4194 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
4195 ? RISCV::VMSEQ_VV
4196 : RISCV::VMSNE_VV;
4197 emitToStreamer(S&: Out, Inst: MCInstBuilder(Opc)
4198 .addOperand(Op: Inst.getOperand(i: 0))
4199 .addOperand(Op: Inst.getOperand(i: 1))
4200 .addOperand(Op: Inst.getOperand(i: 1))
4201 .addOperand(Op: Inst.getOperand(i: 3))
4202 .setLoc(IDLoc));
4203 } else {
4204 // Other immediate values can subtract one like signed.
4205 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
4206 ? RISCV::VMSGTU_VI
4207 : RISCV::VMSLEU_VI;
4208 emitToStreamer(S&: Out, Inst: MCInstBuilder(Opc)
4209 .addOperand(Op: Inst.getOperand(i: 0))
4210 .addOperand(Op: Inst.getOperand(i: 1))
4211 .addImm(Val: Imm - 1)
4212 .addOperand(Op: Inst.getOperand(i: 3))
4213 .setLoc(IDLoc));
4214 }
4215
4216 return false;
4217 }
4218 case RISCV::PseudoCV_ELW:
4219 emitLoadStoreSymbol(Inst, Opcode: RISCV::CV_ELW, IDLoc, Out, /*HasTmpReg=*/false);
4220 return false;
4221 }
4222
4223 emitToStreamer(S&: Out, Inst);
4224 return false;
4225}
4226
4227extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
4228LLVMInitializeRISCVAsmParser() {
4229 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
4230 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
4231 RegisterMCAsmParser<RISCVAsmParser> A(getTheRISCV32beTarget());
4232 RegisterMCAsmParser<RISCVAsmParser> B(getTheRISCV64beTarget());
4233}
4234