1 //===-- RISCVAsmParser.cpp - Parse RISC-V assembly to MCInst instructions -===//
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
7 //===----------------------------------------------------------------------===//
9 #include "MCTargetDesc/RISCVAsmBackend.h"
10 #include "MCTargetDesc/RISCVBaseInfo.h"
11 #include "MCTargetDesc/RISCVInstPrinter.h"
12 #include "MCTargetDesc/RISCVMCExpr.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/SmallString.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/Statistic.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/MC/MCAssembler.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/MC/MCExpr.h"
26 #include "llvm/MC/MCInst.h"
27 #include "llvm/MC/MCInstBuilder.h"
28 #include "llvm/MC/MCInstrInfo.h"
29 #include "llvm/MC/MCObjectFileInfo.h"
30 #include "llvm/MC/MCParser/MCAsmLexer.h"
31 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
32 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
33 #include "llvm/MC/MCRegisterInfo.h"
34 #include "llvm/MC/MCStreamer.h"
35 #include "llvm/MC/MCSubtargetInfo.h"
36 #include "llvm/MC/MCValue.h"
37 #include "llvm/MC/TargetRegistry.h"
38 #include "llvm/Support/Casting.h"
39 #include "llvm/Support/CommandLine.h"
40 #include "llvm/Support/MathExtras.h"
41 #include "llvm/Support/RISCVAttributes.h"
42 #include "llvm/Support/RISCVISAInfo.h"
48 #define DEBUG_TYPE "riscv-asm-parser"
50 STATISTIC(RISCVNumInstrsCompressed
,
51 "Number of RISC-V Compressed instructions emitted");
53 static cl::opt
<bool> AddBuildAttributes("riscv-add-build-attributes",
57 extern const SubtargetFeatureKV RISCVFeatureKV
[RISCV::NumSubtargetFeatures
];
63 struct ParserOptionsSet
{
67 class RISCVAsmParser
: public MCTargetAsmParser
{
68 // This tracks the parsing of the 4 operands that make up the vtype portion
69 // of vset(i)vli instructions which are separated by commas. The state names
70 // represent the next expected operand with Done meaning no other operands are
75 VTypeState_TailPolicy
,
76 VTypeState_MaskPolicy
,
80 SmallVector
<FeatureBitset
, 4> FeatureBitStack
;
82 SmallVector
<ParserOptionsSet
, 4> ParserOptionsStack
;
83 ParserOptionsSet ParserOptions
;
85 SMLoc
getLoc() const { return getParser().getTok().getLoc(); }
86 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit
); }
87 bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureRVE
); }
89 RISCVTargetStreamer
&getTargetStreamer() {
90 assert(getParser().getStreamer().getTargetStreamer() &&
91 "do not have a target streamer");
92 MCTargetStreamer
&TS
= *getParser().getStreamer().getTargetStreamer();
93 return static_cast<RISCVTargetStreamer
&>(TS
);
96 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
97 unsigned Kind
) override
;
98 unsigned checkTargetMatchPredicate(MCInst
&Inst
) override
;
100 bool generateImmOutOfRangeError(OperandVector
&Operands
, uint64_t ErrorInfo
,
101 int64_t Lower
, int64_t Upper
,
103 bool generateImmOutOfRangeError(SMLoc ErrorLoc
, int64_t Lower
, int64_t Upper
,
106 bool MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
107 OperandVector
&Operands
, MCStreamer
&Out
,
109 bool MatchingInlineAsm
) override
;
111 bool parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
112 ParseStatus
tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
113 SMLoc
&EndLoc
) override
;
115 bool ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
116 SMLoc NameLoc
, OperandVector
&Operands
) override
;
118 ParseStatus
parseDirective(AsmToken DirectiveID
) override
;
120 bool parseVTypeToken(StringRef Identifier
, VTypeState
&State
, unsigned &Sew
,
121 unsigned &Lmul
, bool &Fractional
, bool &TailAgnostic
,
123 bool generateVTypeError(SMLoc ErrorLoc
);
125 // Helper to actually emit an instruction to the MCStreamer. Also, when
126 // possible, compression of the instruction is performed.
127 void emitToStreamer(MCStreamer
&S
, const MCInst
&Inst
);
129 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
130 // synthesize the desired immedate value into the destination register.
131 void emitLoadImm(MCRegister DestReg
, int64_t Value
, MCStreamer
&Out
);
133 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
134 // helpers such as emitLoadLocalAddress and emitLoadAddress.
135 void emitAuipcInstPair(MCOperand DestReg
, MCOperand TmpReg
,
136 const MCExpr
*Symbol
, RISCVMCExpr::VariantKind VKHi
,
137 unsigned SecondOpcode
, SMLoc IDLoc
, MCStreamer
&Out
);
139 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
140 void emitLoadLocalAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
142 // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
143 void emitLoadGlobalAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
145 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
146 void emitLoadAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
148 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
150 void emitLoadTLSIEAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
152 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
154 void emitLoadTLSGDAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
156 // Helper to emit pseudo load/store instruction with a symbol.
157 void emitLoadStoreSymbol(MCInst
&Inst
, unsigned Opcode
, SMLoc IDLoc
,
158 MCStreamer
&Out
, bool HasTmpReg
);
160 // Helper to emit pseudo sign/zero extend instruction.
161 void emitPseudoExtend(MCInst
&Inst
, bool SignExtend
, int64_t Width
,
162 SMLoc IDLoc
, MCStreamer
&Out
);
164 // Helper to emit pseudo vmsge{u}.vx instruction.
165 void emitVMSGE(MCInst
&Inst
, unsigned Opcode
, SMLoc IDLoc
, MCStreamer
&Out
);
167 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
168 // Enforcing this using a restricted register class for the second input
169 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
170 // 'add' is an overloaded mnemonic.
171 bool checkPseudoAddTPRel(MCInst
&Inst
, OperandVector
&Operands
);
173 // Check instruction constraints.
174 bool validateInstruction(MCInst
&Inst
, OperandVector
&Operands
);
176 /// Helper for processing MC instructions that have been successfully matched
177 /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
178 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
180 bool processInstruction(MCInst
&Inst
, SMLoc IDLoc
, OperandVector
&Operands
,
183 // Auto-generated instruction matching functions
184 #define GET_ASSEMBLER_HEADER
185 #include "RISCVGenAsmMatcher.inc"
187 ParseStatus
parseCSRSystemRegister(OperandVector
&Operands
);
188 ParseStatus
parseFPImm(OperandVector
&Operands
);
189 ParseStatus
parseImmediate(OperandVector
&Operands
);
190 ParseStatus
parseRegister(OperandVector
&Operands
, bool AllowParens
= false);
191 ParseStatus
parseMemOpBaseReg(OperandVector
&Operands
);
192 ParseStatus
parseZeroOffsetMemOp(OperandVector
&Operands
);
193 ParseStatus
parseOperandWithModifier(OperandVector
&Operands
);
194 ParseStatus
parseBareSymbol(OperandVector
&Operands
);
195 ParseStatus
parseCallSymbol(OperandVector
&Operands
);
196 ParseStatus
parsePseudoJumpSymbol(OperandVector
&Operands
);
197 ParseStatus
parseJALOffset(OperandVector
&Operands
);
198 ParseStatus
parseVTypeI(OperandVector
&Operands
);
199 ParseStatus
parseMaskReg(OperandVector
&Operands
);
200 ParseStatus
parseInsnDirectiveOpcode(OperandVector
&Operands
);
201 ParseStatus
parseInsnCDirectiveOpcode(OperandVector
&Operands
);
202 ParseStatus
parseGPRAsFPR(OperandVector
&Operands
);
203 ParseStatus
parseFRMArg(OperandVector
&Operands
);
204 ParseStatus
parseFenceArg(OperandVector
&Operands
);
205 ParseStatus
parseReglist(OperandVector
&Operands
);
206 ParseStatus
parseRetval(OperandVector
&Operands
);
207 ParseStatus
parseZcmpSpimm(OperandVector
&Operands
);
209 bool parseOperand(OperandVector
&Operands
, StringRef Mnemonic
);
211 bool parseDirectiveOption();
212 bool parseDirectiveAttribute();
213 bool parseDirectiveInsn(SMLoc L
);
214 bool parseDirectiveVariantCC();
216 /// Helper to reset target features for a new arch string. It
217 /// also records the new arch string that is expanded by RISCVISAInfo
218 /// and reports error for invalid arch string.
219 bool resetToArch(StringRef Arch
, SMLoc Loc
, std::string
&Result
,
220 bool FromOptionDirective
);
222 void setFeatureBits(uint64_t Feature
, StringRef FeatureString
) {
223 if (!(getSTI().hasFeature(Feature
))) {
224 MCSubtargetInfo
&STI
= copySTI();
225 setAvailableFeatures(
226 ComputeAvailableFeatures(STI
.ToggleFeature(FeatureString
)));
230 void clearFeatureBits(uint64_t Feature
, StringRef FeatureString
) {
231 if (getSTI().hasFeature(Feature
)) {
232 MCSubtargetInfo
&STI
= copySTI();
233 setAvailableFeatures(
234 ComputeAvailableFeatures(STI
.ToggleFeature(FeatureString
)));
238 void pushFeatureBits() {
239 assert(FeatureBitStack
.size() == ParserOptionsStack
.size() &&
240 "These two stacks must be kept synchronized");
241 FeatureBitStack
.push_back(getSTI().getFeatureBits());
242 ParserOptionsStack
.push_back(ParserOptions
);
245 bool popFeatureBits() {
246 assert(FeatureBitStack
.size() == ParserOptionsStack
.size() &&
247 "These two stacks must be kept synchronized");
248 if (FeatureBitStack
.empty())
251 FeatureBitset FeatureBits
= FeatureBitStack
.pop_back_val();
252 copySTI().setFeatureBits(FeatureBits
);
253 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits
));
255 ParserOptions
= ParserOptionsStack
.pop_back_val();
260 std::unique_ptr
<RISCVOperand
> defaultMaskRegOp() const;
261 std::unique_ptr
<RISCVOperand
> defaultFRMArgOp() const;
262 std::unique_ptr
<RISCVOperand
> defaultFRMArgLegacyOp() const;
265 enum RISCVMatchResultTy
{
266 Match_Dummy
= FIRST_TARGET_MATCH_RESULT_TY
,
267 Match_RequiresEvenGPRs
,
268 #define GET_OPERAND_DIAGNOSTIC_TYPES
269 #include "RISCVGenAsmMatcher.inc"
270 #undef GET_OPERAND_DIAGNOSTIC_TYPES
273 static bool classifySymbolRef(const MCExpr
*Expr
,
274 RISCVMCExpr::VariantKind
&Kind
);
275 static bool isSymbolDiff(const MCExpr
*Expr
);
277 RISCVAsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
278 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
279 : MCTargetAsmParser(Options
, STI
, MII
) {
280 MCAsmParserExtension::Initialize(Parser
);
282 Parser
.addAliasForDirective(".half", ".2byte");
283 Parser
.addAliasForDirective(".hword", ".2byte");
284 Parser
.addAliasForDirective(".word", ".4byte");
285 Parser
.addAliasForDirective(".dword", ".8byte");
286 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
288 auto ABIName
= StringRef(Options
.ABIName
);
289 if (ABIName
.endswith("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF
)) {
290 errs() << "Hard-float 'f' ABI can't be used for a target that "
291 "doesn't support the F instruction set extension (ignoring "
293 } else if (ABIName
.endswith("d") &&
294 !getSTI().hasFeature(RISCV::FeatureStdExtD
)) {
295 errs() << "Hard-float 'd' ABI can't be used for a target that "
296 "doesn't support the D instruction set extension (ignoring "
300 // Use computeTargetABI to check if ABIName is valid. If invalid, output
302 RISCVABI::computeTargetABI(STI
.getTargetTriple(), STI
.getFeatureBits(),
305 const MCObjectFileInfo
*MOFI
= Parser
.getContext().getObjectFileInfo();
306 ParserOptions
.IsPicEnabled
= MOFI
->isPositionIndependent();
308 if (AddBuildAttributes
)
309 getTargetStreamer().emitTargetAttributes(STI
, /*EmitStackAlign*/ false);
313 /// RISCVOperand - Instances of this class represent a parsed machine
315 struct RISCVOperand final
: public MCParsedAsmOperand
{
348 // FIXME: Add the Encoding parsed fields as needed for checks,
349 // e.g.: read/write or user/supervisor/machine privileges.
357 RISCVFPRndMode::RoundingMode FRM
;
372 SMLoc StartLoc
, EndLoc
;
378 struct SysRegOp SysReg
;
379 struct VTypeOp VType
;
381 struct FenceOp Fence
;
382 struct RlistOp Rlist
;
383 struct SpimmOp Spimm
;
386 RISCVOperand(KindTy K
) : Kind(K
) {}
389 RISCVOperand(const RISCVOperand
&o
) : MCParsedAsmOperand() {
391 StartLoc
= o
.StartLoc
;
394 case KindTy::Register
:
397 case KindTy::Immediate
:
400 case KindTy::FPImmediate
:
406 case KindTy::SystemRegister
:
427 bool isToken() const override
{ return Kind
== KindTy::Token
; }
428 bool isReg() const override
{ return Kind
== KindTy::Register
; }
429 bool isV0Reg() const {
430 return Kind
== KindTy::Register
&& Reg
.RegNum
== RISCV::V0
;
432 bool isAnyReg() const {
433 return Kind
== KindTy::Register
&&
434 (RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(Reg
.RegNum
) ||
435 RISCVMCRegisterClasses
[RISCV::FPR64RegClassID
].contains(Reg
.RegNum
) ||
436 RISCVMCRegisterClasses
[RISCV::VRRegClassID
].contains(Reg
.RegNum
));
438 bool isAnyRegC() const {
439 return Kind
== KindTy::Register
&&
440 (RISCVMCRegisterClasses
[RISCV::GPRCRegClassID
].contains(
442 RISCVMCRegisterClasses
[RISCV::FPR64CRegClassID
].contains(
445 bool isImm() const override
{ return Kind
== KindTy::Immediate
; }
446 bool isMem() const override
{ return false; }
447 bool isSystemRegister() const { return Kind
== KindTy::SystemRegister
; }
448 bool isRlist() const { return Kind
== KindTy::Rlist
; }
449 bool isSpimm() const { return Kind
== KindTy::Spimm
; }
452 return Kind
== KindTy::Register
&&
453 RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(Reg
.RegNum
);
456 bool isGPRAsFPR() const { return isGPR() && Reg
.IsGPRAsFPR
; }
458 bool isGPRF64AsFPR() const { return isGPR() && Reg
.IsGPRAsFPR
; }
460 bool isGPRPF64AsFPR() const { return isGPR() && Reg
.IsGPRAsFPR
; }
462 static bool evaluateConstantImm(const MCExpr
*Expr
, int64_t &Imm
,
463 RISCVMCExpr::VariantKind
&VK
) {
464 if (auto *RE
= dyn_cast
<RISCVMCExpr
>(Expr
)) {
466 return RE
->evaluateAsConstant(Imm
);
469 if (auto CE
= dyn_cast
<MCConstantExpr
>(Expr
)) {
470 VK
= RISCVMCExpr::VK_RISCV_None
;
471 Imm
= CE
->getValue();
478 // True if operand is a symbol with no modifiers, or a constant with no
479 // modifiers and isShiftedInt<N-1, 1>(Op).
480 template <int N
> bool isBareSimmNLsb0() const {
482 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
485 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
488 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
490 IsValid
= isShiftedInt
<N
- 1, 1>(Imm
);
491 return IsValid
&& VK
== RISCVMCExpr::VK_RISCV_None
;
494 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
496 bool isBareSymbol() const {
498 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
499 // Must be of 'immediate' type but not a constant.
500 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
502 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
503 VK
== RISCVMCExpr::VK_RISCV_None
;
506 bool isCallSymbol() const {
508 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
509 // Must be of 'immediate' type but not a constant.
510 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
512 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
513 (VK
== RISCVMCExpr::VK_RISCV_CALL
||
514 VK
== RISCVMCExpr::VK_RISCV_CALL_PLT
);
517 bool isPseudoJumpSymbol() const {
519 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
520 // Must be of 'immediate' type but not a constant.
521 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
523 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
524 VK
== RISCVMCExpr::VK_RISCV_CALL
;
527 bool isTPRelAddSymbol() const {
529 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
530 // Must be of 'immediate' type but not a constant.
531 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
533 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
534 VK
== RISCVMCExpr::VK_RISCV_TPREL_ADD
;
537 bool isCSRSystemRegister() const { return isSystemRegister(); }
539 bool isVTypeImm(unsigned N
) const {
541 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
544 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
545 return IsConstantImm
&& isUIntN(N
, Imm
) && VK
== RISCVMCExpr::VK_RISCV_None
;
548 // If the last operand of the vsetvli/vsetvli instruction is a constant
549 // expression, KindTy is Immediate.
550 bool isVTypeI10() const {
551 if (Kind
== KindTy::Immediate
)
552 return isVTypeImm(10);
553 return Kind
== KindTy::VType
;
555 bool isVTypeI11() const {
556 if (Kind
== KindTy::Immediate
)
557 return isVTypeImm(11);
558 return Kind
== KindTy::VType
;
561 /// Return true if the operand is a valid for the fence instruction e.g.
563 bool isFenceArg() const { return Kind
== KindTy::Fence
; }
565 /// Return true if the operand is a valid floating point rounding mode.
566 bool isFRMArg() const { return Kind
== KindTy::FRM
; }
567 bool isFRMArgLegacy() const { return Kind
== KindTy::FRM
; }
568 bool isRTZArg() const { return isFRMArg() && FRM
.FRM
== RISCVFPRndMode::RTZ
; }
570 /// Return true if the operand is a valid fli.s floating-point immediate.
571 bool isLoadFPImm() const {
574 if (Kind
!= KindTy::FPImmediate
)
576 int Idx
= RISCVLoadFPImm::getLoadFPImm(
577 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
578 // Don't allow decimal version of the minimum value. It is a different value
579 // for each supported data type.
580 return Idx
>= 0 && Idx
!= 1;
583 bool isImmXLenLI() const {
585 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
588 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
589 if (VK
== RISCVMCExpr::VK_RISCV_LO
|| VK
== RISCVMCExpr::VK_RISCV_PCREL_LO
)
591 // Given only Imm, ensuring that the actually specified constant is either
592 // a signed or unsigned 64-bit number is unfortunately impossible.
594 return VK
== RISCVMCExpr::VK_RISCV_None
&&
595 (isRV64Imm() || (isInt
<32>(Imm
) || isUInt
<32>(Imm
)));
598 return RISCVAsmParser::isSymbolDiff(getImm());
601 bool isImmXLenLI_Restricted() const {
603 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
606 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
607 // 'la imm' supports constant immediates only.
608 return IsConstantImm
&& (VK
== RISCVMCExpr::VK_RISCV_None
) &&
609 (isRV64Imm() || (isInt
<32>(Imm
) || isUInt
<32>(Imm
)));
612 bool isUImmLog2XLen() const {
614 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
617 if (!evaluateConstantImm(getImm(), Imm
, VK
) ||
618 VK
!= RISCVMCExpr::VK_RISCV_None
)
620 return (isRV64Imm() && isUInt
<6>(Imm
)) || isUInt
<5>(Imm
);
623 bool isUImmLog2XLenNonZero() const {
625 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
628 if (!evaluateConstantImm(getImm(), Imm
, VK
) ||
629 VK
!= RISCVMCExpr::VK_RISCV_None
)
633 return (isRV64Imm() && isUInt
<6>(Imm
)) || isUInt
<5>(Imm
);
636 bool isUImmLog2XLenHalf() const {
638 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
641 if (!evaluateConstantImm(getImm(), Imm
, VK
) ||
642 VK
!= RISCVMCExpr::VK_RISCV_None
)
644 return (isRV64Imm() && isUInt
<5>(Imm
)) || isUInt
<4>(Imm
);
647 template <unsigned N
> bool IsUImm() const {
649 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
652 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
653 return IsConstantImm
&& isUInt
<N
>(Imm
) && VK
== RISCVMCExpr::VK_RISCV_None
;
656 bool isUImm1() const { return IsUImm
<1>(); }
657 bool isUImm2() const { return IsUImm
<2>(); }
658 bool isUImm3() const { return IsUImm
<3>(); }
659 bool isUImm4() const { return IsUImm
<4>(); }
660 bool isUImm5() const { return IsUImm
<5>(); }
661 bool isUImm6() const { return IsUImm
<6>(); }
662 bool isUImm7() const { return IsUImm
<7>(); }
663 bool isUImm8() const { return IsUImm
<8>(); }
664 bool isUImm20() const { return IsUImm
<20>(); }
666 bool isUImm8GE32() const {
668 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
671 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
672 return IsConstantImm
&& isUInt
<8>(Imm
) && Imm
>= 32 &&
673 VK
== RISCVMCExpr::VK_RISCV_None
;
676 bool isRnumArg() const {
678 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
681 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
682 return IsConstantImm
&& Imm
>= INT64_C(0) && Imm
<= INT64_C(10) &&
683 VK
== RISCVMCExpr::VK_RISCV_None
;
686 bool isRnumArg_0_7() const {
688 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
691 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
692 return IsConstantImm
&& Imm
>= INT64_C(0) && Imm
<= INT64_C(7) &&
693 VK
== RISCVMCExpr::VK_RISCV_None
;
696 bool isRnumArg_1_10() const {
698 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
701 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
702 return IsConstantImm
&& Imm
>= INT64_C(1) && Imm
<= INT64_C(10) &&
703 VK
== RISCVMCExpr::VK_RISCV_None
;
706 bool isRnumArg_2_14() const {
708 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
711 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
712 return IsConstantImm
&& Imm
>= INT64_C(2) && Imm
<= INT64_C(14) &&
713 VK
== RISCVMCExpr::VK_RISCV_None
;
716 bool isSImm5() const {
719 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
721 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
722 return IsConstantImm
&& isInt
<5>(fixImmediateForRV32(Imm
, isRV64Imm())) &&
723 VK
== RISCVMCExpr::VK_RISCV_None
;
726 bool isSImm6() const {
729 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
731 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
732 return IsConstantImm
&& isInt
<6>(fixImmediateForRV32(Imm
, isRV64Imm())) &&
733 VK
== RISCVMCExpr::VK_RISCV_None
;
736 bool isSImm6NonZero() const {
739 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
741 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
742 return IsConstantImm
&& Imm
!= 0 &&
743 isInt
<6>(fixImmediateForRV32(Imm
, isRV64Imm())) &&
744 VK
== RISCVMCExpr::VK_RISCV_None
;
747 bool isCLUIImm() const {
751 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
752 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
753 return IsConstantImm
&& (Imm
!= 0) &&
754 (isUInt
<5>(Imm
) || (Imm
>= 0xfffe0 && Imm
<= 0xfffff)) &&
755 VK
== RISCVMCExpr::VK_RISCV_None
;
758 bool isUImm2Lsb0() const {
762 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
763 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
764 return IsConstantImm
&& isShiftedUInt
<1, 1>(Imm
) &&
765 VK
== RISCVMCExpr::VK_RISCV_None
;
768 bool isUImm7Lsb00() const {
772 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
773 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
774 return IsConstantImm
&& isShiftedUInt
<5, 2>(Imm
) &&
775 VK
== RISCVMCExpr::VK_RISCV_None
;
778 bool isUImm8Lsb00() const {
782 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
783 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
784 return IsConstantImm
&& isShiftedUInt
<6, 2>(Imm
) &&
785 VK
== RISCVMCExpr::VK_RISCV_None
;
788 bool isUImm8Lsb000() const {
792 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
793 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
794 return IsConstantImm
&& isShiftedUInt
<5, 3>(Imm
) &&
795 VK
== RISCVMCExpr::VK_RISCV_None
;
798 bool isSImm9Lsb0() const { return isBareSimmNLsb0
<9>(); }
800 bool isUImm9Lsb000() const {
804 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
805 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
806 return IsConstantImm
&& isShiftedUInt
<6, 3>(Imm
) &&
807 VK
== RISCVMCExpr::VK_RISCV_None
;
810 bool isUImm10Lsb00NonZero() const {
814 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
815 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
816 return IsConstantImm
&& isShiftedUInt
<8, 2>(Imm
) && (Imm
!= 0) &&
817 VK
== RISCVMCExpr::VK_RISCV_None
;
820 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
821 // This allows writing 'addi a0, a0, 0xffffffff'.
822 static int64_t fixImmediateForRV32(int64_t Imm
, bool IsRV64Imm
) {
823 if (IsRV64Imm
|| !isUInt
<32>(Imm
))
825 return SignExtend64
<32>(Imm
);
828 bool isSImm12() const {
829 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
834 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
836 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
838 IsValid
= isInt
<12>(fixImmediateForRV32(Imm
, isRV64Imm()));
839 return IsValid
&& ((IsConstantImm
&& VK
== RISCVMCExpr::VK_RISCV_None
) ||
840 VK
== RISCVMCExpr::VK_RISCV_LO
||
841 VK
== RISCVMCExpr::VK_RISCV_PCREL_LO
||
842 VK
== RISCVMCExpr::VK_RISCV_TPREL_LO
);
845 bool isSImm12Lsb0() const { return isBareSimmNLsb0
<12>(); }
847 bool isSImm12Lsb00000() const {
850 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
852 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
853 return IsConstantImm
&& isShiftedInt
<7, 5>(Imm
) &&
854 VK
== RISCVMCExpr::VK_RISCV_None
;
857 bool isSImm13Lsb0() const { return isBareSimmNLsb0
<13>(); }
859 bool isSImm10Lsb0000NonZero() const {
863 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
864 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
865 return IsConstantImm
&& (Imm
!= 0) && isShiftedInt
<6, 4>(Imm
) &&
866 VK
== RISCVMCExpr::VK_RISCV_None
;
869 bool isUImm20LUI() const {
870 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
875 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
876 if (!IsConstantImm
) {
877 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
878 return IsValid
&& (VK
== RISCVMCExpr::VK_RISCV_HI
||
879 VK
== RISCVMCExpr::VK_RISCV_TPREL_HI
);
881 return isUInt
<20>(Imm
) && (VK
== RISCVMCExpr::VK_RISCV_None
||
882 VK
== RISCVMCExpr::VK_RISCV_HI
||
883 VK
== RISCVMCExpr::VK_RISCV_TPREL_HI
);
887 bool isUImm20AUIPC() const {
888 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
893 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
894 if (!IsConstantImm
) {
895 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
896 return IsValid
&& (VK
== RISCVMCExpr::VK_RISCV_PCREL_HI
||
897 VK
== RISCVMCExpr::VK_RISCV_GOT_HI
||
898 VK
== RISCVMCExpr::VK_RISCV_TLS_GOT_HI
||
899 VK
== RISCVMCExpr::VK_RISCV_TLS_GD_HI
);
901 return isUInt
<20>(Imm
) && (VK
== RISCVMCExpr::VK_RISCV_None
||
902 VK
== RISCVMCExpr::VK_RISCV_PCREL_HI
||
903 VK
== RISCVMCExpr::VK_RISCV_GOT_HI
||
904 VK
== RISCVMCExpr::VK_RISCV_TLS_GOT_HI
||
905 VK
== RISCVMCExpr::VK_RISCV_TLS_GD_HI
);
909 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0
<21>(); }
911 bool isImmZero() const {
915 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
916 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
917 return IsConstantImm
&& (Imm
== 0) && VK
== RISCVMCExpr::VK_RISCV_None
;
920 bool isSImm5Plus1() const {
923 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
925 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
926 return IsConstantImm
&&
927 isInt
<5>(fixImmediateForRV32(Imm
, isRV64Imm()) - 1) &&
928 VK
== RISCVMCExpr::VK_RISCV_None
;
931 /// getStartLoc - Gets location of the first token of this operand
932 SMLoc
getStartLoc() const override
{ return StartLoc
; }
933 /// getEndLoc - Gets location of the last token of this operand
934 SMLoc
getEndLoc() const override
{ return EndLoc
; }
935 /// True if this operand is for an RV64 instruction
936 bool isRV64Imm() const {
937 assert(Kind
== KindTy::Immediate
&& "Invalid type access!");
941 unsigned getReg() const override
{
942 assert(Kind
== KindTy::Register
&& "Invalid type access!");
943 return Reg
.RegNum
.id();
946 StringRef
getSysReg() const {
947 assert(Kind
== KindTy::SystemRegister
&& "Invalid type access!");
948 return StringRef(SysReg
.Data
, SysReg
.Length
);
951 const MCExpr
*getImm() const {
952 assert(Kind
== KindTy::Immediate
&& "Invalid type access!");
956 uint64_t getFPConst() const {
957 assert(Kind
== KindTy::FPImmediate
&& "Invalid type access!");
961 StringRef
getToken() const {
962 assert(Kind
== KindTy::Token
&& "Invalid type access!");
966 unsigned getVType() const {
967 assert(Kind
== KindTy::VType
&& "Invalid type access!");
971 RISCVFPRndMode::RoundingMode
getFRM() const {
972 assert(Kind
== KindTy::FRM
&& "Invalid type access!");
976 unsigned getFence() const {
977 assert(Kind
== KindTy::Fence
&& "Invalid type access!");
981 void print(raw_ostream
&OS
) const override
{
982 auto RegName
= [](MCRegister Reg
) {
984 return RISCVInstPrinter::getRegisterName(Reg
);
990 case KindTy::Immediate
:
993 case KindTy::FPImmediate
:
995 case KindTy::Register
:
996 OS
<< "<register " << RegName(getReg()) << ">";
999 OS
<< "'" << getToken() << "'";
1001 case KindTy::SystemRegister
:
1002 OS
<< "<sysreg: " << getSysReg() << '>';
1006 RISCVVType::printVType(getVType(), OS
);
1011 roundingModeToString(getFRM());
1021 RISCVZC::printRlist(Rlist
.Val
, OS
);
1026 RISCVZC::printSpimm(Spimm
.Val
, OS
);
1032 static std::unique_ptr
<RISCVOperand
> createToken(StringRef Str
, SMLoc S
) {
1033 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Token
);
1040 static std::unique_ptr
<RISCVOperand
>
1041 createReg(unsigned RegNo
, SMLoc S
, SMLoc E
, bool IsGPRAsFPR
= false) {
1042 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Register
);
1043 Op
->Reg
.RegNum
= RegNo
;
1044 Op
->Reg
.IsGPRAsFPR
= IsGPRAsFPR
;
1050 static std::unique_ptr
<RISCVOperand
> createImm(const MCExpr
*Val
, SMLoc S
,
1051 SMLoc E
, bool IsRV64
) {
1052 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Immediate
);
1054 Op
->Imm
.IsRV64
= IsRV64
;
1060 static std::unique_ptr
<RISCVOperand
> createFPImm(uint64_t Val
, SMLoc S
) {
1061 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::FPImmediate
);
1062 Op
->FPImm
.Val
= Val
;
1068 static std::unique_ptr
<RISCVOperand
> createSysReg(StringRef Str
, SMLoc S
,
1069 unsigned Encoding
) {
1070 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::SystemRegister
);
1071 Op
->SysReg
.Data
= Str
.data();
1072 Op
->SysReg
.Length
= Str
.size();
1073 Op
->SysReg
.Encoding
= Encoding
;
1079 static std::unique_ptr
<RISCVOperand
>
1080 createFRMArg(RISCVFPRndMode::RoundingMode FRM
, SMLoc S
) {
1081 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::FRM
);
1088 static std::unique_ptr
<RISCVOperand
> createFenceArg(unsigned Val
, SMLoc S
) {
1089 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Fence
);
1090 Op
->Fence
.Val
= Val
;
1096 static std::unique_ptr
<RISCVOperand
> createVType(unsigned VTypeI
, SMLoc S
) {
1097 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::VType
);
1098 Op
->VType
.Val
= VTypeI
;
1104 static std::unique_ptr
<RISCVOperand
> createRlist(unsigned RlistEncode
,
1106 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Rlist
);
1107 Op
->Rlist
.Val
= RlistEncode
;
1112 static std::unique_ptr
<RISCVOperand
> createSpimm(unsigned Spimm
, SMLoc S
) {
1113 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Spimm
);
1114 Op
->Spimm
.Val
= Spimm
;
1119 static void addExpr(MCInst
&Inst
, const MCExpr
*Expr
, bool IsRV64Imm
) {
1120 assert(Expr
&& "Expr shouldn't be null!");
1122 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
1123 bool IsConstant
= evaluateConstantImm(Expr
, Imm
, VK
);
1127 MCOperand::createImm(fixImmediateForRV32(Imm
, IsRV64Imm
)));
1129 Inst
.addOperand(MCOperand::createExpr(Expr
));
1132 // Used by the TableGen Code
1133 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
1134 assert(N
== 1 && "Invalid number of operands!");
1135 Inst
.addOperand(MCOperand::createReg(getReg()));
1138 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
1139 assert(N
== 1 && "Invalid number of operands!");
1140 addExpr(Inst
, getImm(), isRV64Imm());
1143 void addFPImmOperands(MCInst
&Inst
, unsigned N
) const {
1144 assert(N
== 1 && "Invalid number of operands!");
1146 addExpr(Inst
, getImm(), isRV64Imm());
1150 int Imm
= RISCVLoadFPImm::getLoadFPImm(
1151 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1152 Inst
.addOperand(MCOperand::createImm(Imm
));
1155 void addFenceArgOperands(MCInst
&Inst
, unsigned N
) const {
1156 assert(N
== 1 && "Invalid number of operands!");
1157 Inst
.addOperand(MCOperand::createImm(Fence
.Val
));
1160 void addCSRSystemRegisterOperands(MCInst
&Inst
, unsigned N
) const {
1161 assert(N
== 1 && "Invalid number of operands!");
1162 Inst
.addOperand(MCOperand::createImm(SysReg
.Encoding
));
1165 // Support non-canonical syntax:
1166 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
1167 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
1168 void addVTypeIOperands(MCInst
&Inst
, unsigned N
) const {
1169 assert(N
== 1 && "Invalid number of operands!");
1171 if (Kind
== KindTy::Immediate
) {
1172 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
1173 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
1174 (void)IsConstantImm
;
1175 assert(IsConstantImm
&& "Invalid VTypeI Operand!");
1179 Inst
.addOperand(MCOperand::createImm(Imm
));
1182 void addRlistOperands(MCInst
&Inst
, unsigned N
) const {
1183 assert(N
== 1 && "Invalid number of operands!");
1184 Inst
.addOperand(MCOperand::createImm(Rlist
.Val
));
1187 void addSpimmOperands(MCInst
&Inst
, unsigned N
) const {
1188 assert(N
== 1 && "Invalid number of operands!");
1189 Inst
.addOperand(MCOperand::createImm(Spimm
.Val
));
1192 void addFRMArgOperands(MCInst
&Inst
, unsigned N
) const {
1193 assert(N
== 1 && "Invalid number of operands!");
1194 Inst
.addOperand(MCOperand::createImm(getFRM()));
1197 } // end anonymous namespace.
1199 #define GET_REGISTER_MATCHER
1200 #define GET_SUBTARGET_FEATURE_NAME
1201 #define GET_MATCHER_IMPLEMENTATION
1202 #define GET_MNEMONIC_SPELL_CHECKER
1203 #include "RISCVGenAsmMatcher.inc"
1205 static MCRegister
convertFPR64ToFPR16(MCRegister Reg
) {
1206 assert(Reg
>= RISCV::F0_D
&& Reg
<= RISCV::F31_D
&& "Invalid register");
1207 return Reg
- RISCV::F0_D
+ RISCV::F0_H
;
1210 static MCRegister
convertFPR64ToFPR32(MCRegister Reg
) {
1211 assert(Reg
>= RISCV::F0_D
&& Reg
<= RISCV::F31_D
&& "Invalid register");
1212 return Reg
- RISCV::F0_D
+ RISCV::F0_F
;
1215 static MCRegister
convertVRToVRMx(const MCRegisterInfo
&RI
, MCRegister Reg
,
1217 unsigned RegClassID
;
1218 if (Kind
== MCK_VRM2
)
1219 RegClassID
= RISCV::VRM2RegClassID
;
1220 else if (Kind
== MCK_VRM4
)
1221 RegClassID
= RISCV::VRM4RegClassID
;
1222 else if (Kind
== MCK_VRM8
)
1223 RegClassID
= RISCV::VRM8RegClassID
;
1226 return RI
.getMatchingSuperReg(Reg
, RISCV::sub_vrm1_0
,
1227 &RISCVMCRegisterClasses
[RegClassID
]);
1230 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand
&AsmOp
,
1232 RISCVOperand
&Op
= static_cast<RISCVOperand
&>(AsmOp
);
1234 return Match_InvalidOperand
;
1236 MCRegister Reg
= Op
.getReg();
1238 RISCVMCRegisterClasses
[RISCV::FPR64RegClassID
].contains(Reg
);
1240 RISCVMCRegisterClasses
[RISCV::FPR64CRegClassID
].contains(Reg
);
1241 bool IsRegVR
= RISCVMCRegisterClasses
[RISCV::VRRegClassID
].contains(Reg
);
1243 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1244 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1245 if ((IsRegFPR64
&& Kind
== MCK_FPR32
) ||
1246 (IsRegFPR64C
&& Kind
== MCK_FPR32C
)) {
1247 Op
.Reg
.RegNum
= convertFPR64ToFPR32(Reg
);
1248 return Match_Success
;
1250 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1251 // register from FPR64 to FPR16 if necessary.
1252 if (IsRegFPR64
&& Kind
== MCK_FPR16
) {
1253 Op
.Reg
.RegNum
= convertFPR64ToFPR16(Reg
);
1254 return Match_Success
;
1256 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1257 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1258 if (IsRegVR
&& (Kind
== MCK_VRM2
|| Kind
== MCK_VRM4
|| Kind
== MCK_VRM8
)) {
1259 Op
.Reg
.RegNum
= convertVRToVRMx(*getContext().getRegisterInfo(), Reg
, Kind
);
1260 if (Op
.Reg
.RegNum
== 0)
1261 return Match_InvalidOperand
;
1262 return Match_Success
;
1264 return Match_InvalidOperand
;
1267 unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst
&Inst
) {
1268 const MCInstrDesc
&MCID
= MII
.get(Inst
.getOpcode());
1270 for (unsigned I
= 0; I
< MCID
.NumOperands
; ++I
) {
1271 if (MCID
.operands()[I
].RegClass
== RISCV::GPRPF64RegClassID
) {
1272 const auto &Op
= Inst
.getOperand(I
);
1275 MCRegister Reg
= Op
.getReg();
1276 if (((Reg
.id() - RISCV::X0
) & 1) != 0)
1277 return Match_RequiresEvenGPRs
;
1281 return Match_Success
;
1284 bool RISCVAsmParser::generateImmOutOfRangeError(
1285 SMLoc ErrorLoc
, int64_t Lower
, int64_t Upper
,
1286 const Twine
&Msg
= "immediate must be an integer in the range") {
1287 return Error(ErrorLoc
, Msg
+ " [" + Twine(Lower
) + ", " + Twine(Upper
) + "]");
1290 bool RISCVAsmParser::generateImmOutOfRangeError(
1291 OperandVector
&Operands
, uint64_t ErrorInfo
, int64_t Lower
, int64_t Upper
,
1292 const Twine
&Msg
= "immediate must be an integer in the range") {
1293 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1294 return generateImmOutOfRangeError(ErrorLoc
, Lower
, Upper
, Msg
);
1297 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
1298 OperandVector
&Operands
,
1300 uint64_t &ErrorInfo
,
1301 bool MatchingInlineAsm
) {
1303 FeatureBitset MissingFeatures
;
1305 auto Result
= MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MissingFeatures
,
1311 if (validateInstruction(Inst
, Operands
))
1313 return processInstruction(Inst
, IDLoc
, Operands
, Out
);
1314 case Match_MissingFeature
: {
1315 assert(MissingFeatures
.any() && "Unknown missing features!");
1316 bool FirstFeature
= true;
1317 std::string Msg
= "instruction requires the following:";
1318 for (unsigned i
= 0, e
= MissingFeatures
.size(); i
!= e
; ++i
) {
1319 if (MissingFeatures
[i
]) {
1320 Msg
+= FirstFeature
? " " : ", ";
1321 Msg
+= getSubtargetFeatureName(i
);
1322 FirstFeature
= false;
1325 return Error(IDLoc
, Msg
);
1327 case Match_MnemonicFail
: {
1328 FeatureBitset FBS
= ComputeAvailableFeatures(getSTI().getFeatureBits());
1329 std::string Suggestion
= RISCVMnemonicSpellCheck(
1330 ((RISCVOperand
&)*Operands
[0]).getToken(), FBS
, 0);
1331 return Error(IDLoc
, "unrecognized instruction mnemonic" + Suggestion
);
1333 case Match_InvalidOperand
: {
1334 SMLoc ErrorLoc
= IDLoc
;
1335 if (ErrorInfo
!= ~0ULL) {
1336 if (ErrorInfo
>= Operands
.size())
1337 return Error(ErrorLoc
, "too few operands for instruction");
1339 ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1340 if (ErrorLoc
== SMLoc())
1343 return Error(ErrorLoc
, "invalid operand for instruction");
1347 // Handle the case when the error message is of specific type
1348 // other than the generic Match_InvalidOperand, and the
1349 // corresponding operand is missing.
1350 if (Result
> FIRST_TARGET_MATCH_RESULT_TY
) {
1351 SMLoc ErrorLoc
= IDLoc
;
1352 if (ErrorInfo
!= ~0ULL && ErrorInfo
>= Operands
.size())
1353 return Error(ErrorLoc
, "too few operands for instruction");
1359 case Match_RequiresEvenGPRs
:
1361 "double precision floating point operands must use even "
1362 "numbered X register");
1363 case Match_InvalidImmXLenLI
:
1365 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1366 return Error(ErrorLoc
, "operand must be a constant 64-bit integer");
1368 return generateImmOutOfRangeError(Operands
, ErrorInfo
,
1369 std::numeric_limits
<int32_t>::min(),
1370 std::numeric_limits
<uint32_t>::max());
1371 case Match_InvalidImmXLenLI_Restricted
:
1373 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1374 return Error(ErrorLoc
, "operand either must be a constant 64-bit integer "
1375 "or a bare symbol name");
1377 return generateImmOutOfRangeError(
1378 Operands
, ErrorInfo
, std::numeric_limits
<int32_t>::min(),
1379 std::numeric_limits
<uint32_t>::max(),
1380 "operand either must be a bare symbol name or an immediate integer in "
1382 case Match_InvalidImmZero
: {
1383 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1384 return Error(ErrorLoc
, "immediate must be zero");
1386 case Match_InvalidUImmLog2XLen
:
1388 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 6) - 1);
1389 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 5) - 1);
1390 case Match_InvalidUImmLog2XLenNonZero
:
1392 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 1, (1 << 6) - 1);
1393 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 1, (1 << 5) - 1);
1394 case Match_InvalidUImmLog2XLenHalf
:
1396 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 5) - 1);
1397 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 4) - 1);
1398 case Match_InvalidUImm1
:
1399 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 1) - 1);
1400 case Match_InvalidUImm2
:
1401 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 2) - 1);
1402 case Match_InvalidUImm2Lsb0
:
1403 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, 2,
1404 "immediate must be one of");
1405 case Match_InvalidUImm3
:
1406 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 3) - 1);
1407 case Match_InvalidUImm4
:
1408 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 4) - 1);
1409 case Match_InvalidUImm5
:
1410 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 5) - 1);
1411 case Match_InvalidUImm6
:
1412 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 6) - 1);
1413 case Match_InvalidUImm7
:
1414 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 7) - 1);
1415 case Match_InvalidUImm8
:
1416 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 8) - 1);
1417 case Match_InvalidUImm8GE32
:
1418 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 32, (1 << 8) - 1);
1419 case Match_InvalidSImm5
:
1420 return generateImmOutOfRangeError(Operands
, ErrorInfo
, -(1 << 4),
1422 case Match_InvalidSImm6
:
1423 return generateImmOutOfRangeError(Operands
, ErrorInfo
, -(1 << 5),
1425 case Match_InvalidSImm6NonZero
:
1426 return generateImmOutOfRangeError(
1427 Operands
, ErrorInfo
, -(1 << 5), (1 << 5) - 1,
1428 "immediate must be non-zero in the range");
1429 case Match_InvalidCLUIImm
:
1430 return generateImmOutOfRangeError(
1431 Operands
, ErrorInfo
, 1, (1 << 5) - 1,
1432 "immediate must be in [0xfffe0, 0xfffff] or");
1433 case Match_InvalidUImm7Lsb00
:
1434 return generateImmOutOfRangeError(
1435 Operands
, ErrorInfo
, 0, (1 << 7) - 4,
1436 "immediate must be a multiple of 4 bytes in the range");
1437 case Match_InvalidUImm8Lsb00
:
1438 return generateImmOutOfRangeError(
1439 Operands
, ErrorInfo
, 0, (1 << 8) - 4,
1440 "immediate must be a multiple of 4 bytes in the range");
1441 case Match_InvalidUImm8Lsb000
:
1442 return generateImmOutOfRangeError(
1443 Operands
, ErrorInfo
, 0, (1 << 8) - 8,
1444 "immediate must be a multiple of 8 bytes in the range");
1445 case Match_InvalidSImm9Lsb0
:
1446 return generateImmOutOfRangeError(
1447 Operands
, ErrorInfo
, -(1 << 8), (1 << 8) - 2,
1448 "immediate must be a multiple of 2 bytes in the range");
1449 case Match_InvalidUImm9Lsb000
:
1450 return generateImmOutOfRangeError(
1451 Operands
, ErrorInfo
, 0, (1 << 9) - 8,
1452 "immediate must be a multiple of 8 bytes in the range");
1453 case Match_InvalidUImm10Lsb00NonZero
:
1454 return generateImmOutOfRangeError(
1455 Operands
, ErrorInfo
, 4, (1 << 10) - 4,
1456 "immediate must be a multiple of 4 bytes in the range");
1457 case Match_InvalidSImm10Lsb0000NonZero
:
1458 return generateImmOutOfRangeError(
1459 Operands
, ErrorInfo
, -(1 << 9), (1 << 9) - 16,
1460 "immediate must be a multiple of 16 bytes and non-zero in the range");
1461 case Match_InvalidSImm12
:
1462 return generateImmOutOfRangeError(
1463 Operands
, ErrorInfo
, -(1 << 11), (1 << 11) - 1,
1464 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1465 "integer in the range");
1466 case Match_InvalidSImm12Lsb0
:
1467 return generateImmOutOfRangeError(
1468 Operands
, ErrorInfo
, -(1 << 11), (1 << 11) - 2,
1469 "immediate must be a multiple of 2 bytes in the range");
1470 case Match_InvalidSImm12Lsb00000
:
1471 return generateImmOutOfRangeError(
1472 Operands
, ErrorInfo
, -(1 << 11), (1 << 11) - 32,
1473 "immediate must be a multiple of 32 bytes in the range");
1474 case Match_InvalidSImm13Lsb0
:
1475 return generateImmOutOfRangeError(
1476 Operands
, ErrorInfo
, -(1 << 12), (1 << 12) - 2,
1477 "immediate must be a multiple of 2 bytes in the range");
1478 case Match_InvalidUImm20LUI
:
1479 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 20) - 1,
1480 "operand must be a symbol with "
1481 "%hi/%tprel_hi modifier or an integer in "
1483 case Match_InvalidUImm20
:
1484 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 20) - 1);
1485 case Match_InvalidUImm20AUIPC
:
1486 return generateImmOutOfRangeError(
1487 Operands
, ErrorInfo
, 0, (1 << 20) - 1,
1488 "operand must be a symbol with a "
1489 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1490 "an integer in the range");
1491 case Match_InvalidSImm21Lsb0JAL
:
1492 return generateImmOutOfRangeError(
1493 Operands
, ErrorInfo
, -(1 << 20), (1 << 20) - 2,
1494 "immediate must be a multiple of 2 bytes in the range");
1495 case Match_InvalidCSRSystemRegister
: {
1496 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 12) - 1,
1497 "operand must be a valid system register "
1498 "name or an integer in the range");
1500 case Match_InvalidLoadFPImm
: {
1501 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1502 return Error(ErrorLoc
, "operand must be a valid floating-point constant");
1504 case Match_InvalidBareSymbol
: {
1505 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1506 return Error(ErrorLoc
, "operand must be a bare symbol name");
1508 case Match_InvalidPseudoJumpSymbol
: {
1509 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1510 return Error(ErrorLoc
, "operand must be a valid jump target");
1512 case Match_InvalidCallSymbol
: {
1513 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1514 return Error(ErrorLoc
, "operand must be a bare symbol name");
1516 case Match_InvalidTPRelAddSymbol
: {
1517 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1518 return Error(ErrorLoc
, "operand must be a symbol with %tprel_add modifier");
1520 case Match_InvalidRTZArg
: {
1521 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1522 return Error(ErrorLoc
, "operand must be 'rtz' floating-point rounding mode");
1524 case Match_InvalidVTypeI
: {
1525 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1526 return generateVTypeError(ErrorLoc
);
1528 case Match_InvalidVMaskRegister
: {
1529 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1530 return Error(ErrorLoc
, "operand must be v0.t");
1532 case Match_InvalidSImm5Plus1
: {
1533 return generateImmOutOfRangeError(Operands
, ErrorInfo
, -(1 << 4) + 1,
1535 "immediate must be in the range");
1537 case Match_InvalidRlist
: {
1538 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1541 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1543 case Match_InvalidSpimm
: {
1544 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1547 "stack adjustment is invalid for this instruction and register list; "
1548 "refer to Zc spec for a detailed range of stack adjustment");
1550 case Match_InvalidRnumArg
: {
1551 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, 10);
1555 llvm_unreachable("Unknown match type detected!");
1558 // Attempts to match Name as a register (either using the default name or
1559 // alternative ABI names), setting RegNo to the matching register. Upon
1560 // failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31
1561 // will be rejected.
1562 static MCRegister
matchRegisterNameHelper(bool IsRVE
, StringRef Name
) {
1563 MCRegister Reg
= MatchRegisterName(Name
);
1564 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1565 // match always matches the 64-bit variant, and not the 16/32-bit one.
1566 assert(!(Reg
>= RISCV::F0_H
&& Reg
<= RISCV::F31_H
));
1567 assert(!(Reg
>= RISCV::F0_F
&& Reg
<= RISCV::F31_F
));
1568 // The default FPR register class is based on the tablegen enum ordering.
1569 static_assert(RISCV::F0_D
< RISCV::F0_H
, "FPR matching must be updated");
1570 static_assert(RISCV::F0_D
< RISCV::F0_F
, "FPR matching must be updated");
1572 Reg
= MatchRegisterAltName(Name
);
1573 if (IsRVE
&& Reg
>= RISCV::X16
&& Reg
<= RISCV::X31
)
1574 Reg
= RISCV::NoRegister
;
1578 bool RISCVAsmParser::parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
1580 if (!tryParseRegister(Reg
, StartLoc
, EndLoc
).isSuccess())
1581 return Error(StartLoc
, "invalid register name");
1585 ParseStatus
RISCVAsmParser::tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
1587 const AsmToken
&Tok
= getParser().getTok();
1588 StartLoc
= Tok
.getLoc();
1589 EndLoc
= Tok
.getEndLoc();
1590 StringRef Name
= getLexer().getTok().getIdentifier();
1592 Reg
= matchRegisterNameHelper(isRVE(), Name
);
1594 return ParseStatus::NoMatch
;
1596 getParser().Lex(); // Eat identifier token.
1597 return ParseStatus::Success
;
1600 ParseStatus
RISCVAsmParser::parseRegister(OperandVector
&Operands
,
1602 SMLoc FirstS
= getLoc();
1603 bool HadParens
= false;
1606 // If this is an LParen and a parenthesised register name is allowed, parse it
1608 if (AllowParens
&& getLexer().is(AsmToken::LParen
)) {
1610 size_t ReadCount
= getLexer().peekTokens(Buf
);
1611 if (ReadCount
== 2 && Buf
[1].getKind() == AsmToken::RParen
) {
1613 LParen
= getParser().getTok();
1614 getParser().Lex(); // Eat '('
1618 switch (getLexer().getKind()) {
1621 getLexer().UnLex(LParen
);
1622 return ParseStatus::NoMatch
;
1623 case AsmToken::Identifier
:
1624 StringRef Name
= getLexer().getTok().getIdentifier();
1625 MCRegister RegNo
= matchRegisterNameHelper(isRVE(), Name
);
1629 getLexer().UnLex(LParen
);
1630 return ParseStatus::NoMatch
;
1633 Operands
.push_back(RISCVOperand::createToken("(", FirstS
));
1635 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
1637 Operands
.push_back(RISCVOperand::createReg(RegNo
, S
, E
));
1641 getParser().Lex(); // Eat ')'
1642 Operands
.push_back(RISCVOperand::createToken(")", getLoc()));
1645 return ParseStatus::Success
;
1648 ParseStatus
RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector
&Operands
) {
1653 switch (getLexer().getKind()) {
1655 return ParseStatus::NoMatch
;
1656 case AsmToken::LParen
:
1657 case AsmToken::Minus
:
1658 case AsmToken::Plus
:
1659 case AsmToken::Exclaim
:
1660 case AsmToken::Tilde
:
1661 case AsmToken::Integer
:
1662 case AsmToken::String
: {
1663 if (getParser().parseExpression(Res
, E
))
1664 return ParseStatus::Failure
;
1666 auto *CE
= dyn_cast
<MCConstantExpr
>(Res
);
1668 int64_t Imm
= CE
->getValue();
1669 if (isUInt
<7>(Imm
)) {
1670 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1671 return ParseStatus::Success
;
1677 case AsmToken::Identifier
: {
1678 StringRef Identifier
;
1679 if (getParser().parseIdentifier(Identifier
))
1680 return ParseStatus::Failure
;
1682 auto Opcode
= RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier
);
1684 assert(isUInt
<7>(Opcode
->Value
) && (Opcode
->Value
& 0x3) == 3 &&
1685 "Unexpected opcode");
1686 Res
= MCConstantExpr::create(Opcode
->Value
, getContext());
1687 E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
1688 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1689 return ParseStatus::Success
;
1694 case AsmToken::Percent
:
1698 return generateImmOutOfRangeError(
1700 "opcode must be a valid opcode name or an immediate in the range");
1703 ParseStatus
RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector
&Operands
) {
1708 switch (getLexer().getKind()) {
1710 return ParseStatus::NoMatch
;
1711 case AsmToken::LParen
:
1712 case AsmToken::Minus
:
1713 case AsmToken::Plus
:
1714 case AsmToken::Exclaim
:
1715 case AsmToken::Tilde
:
1716 case AsmToken::Integer
:
1717 case AsmToken::String
: {
1718 if (getParser().parseExpression(Res
, E
))
1719 return ParseStatus::Failure
;
1721 auto *CE
= dyn_cast
<MCConstantExpr
>(Res
);
1723 int64_t Imm
= CE
->getValue();
1724 if (Imm
>= 0 && Imm
<= 2) {
1725 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1726 return ParseStatus::Success
;
1732 case AsmToken::Identifier
: {
1733 StringRef Identifier
;
1734 if (getParser().parseIdentifier(Identifier
))
1735 return ParseStatus::Failure
;
1738 if (Identifier
== "C0")
1740 else if (Identifier
== "C1")
1742 else if (Identifier
== "C2")
1747 Res
= MCConstantExpr::create(Opcode
, getContext());
1748 E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
1749 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1750 return ParseStatus::Success
;
1752 case AsmToken::Percent
: {
1753 // Discard operand with modifier.
1758 return generateImmOutOfRangeError(
1760 "opcode must be a valid opcode name or an immediate in the range");
1763 ParseStatus
RISCVAsmParser::parseCSRSystemRegister(OperandVector
&Operands
) {
1767 switch (getLexer().getKind()) {
1769 return ParseStatus::NoMatch
;
1770 case AsmToken::LParen
:
1771 case AsmToken::Minus
:
1772 case AsmToken::Plus
:
1773 case AsmToken::Exclaim
:
1774 case AsmToken::Tilde
:
1775 case AsmToken::Integer
:
1776 case AsmToken::String
: {
1777 if (getParser().parseExpression(Res
))
1778 return ParseStatus::Failure
;
1780 auto *CE
= dyn_cast
<MCConstantExpr
>(Res
);
1782 int64_t Imm
= CE
->getValue();
1783 if (isUInt
<12>(Imm
)) {
1784 auto SysReg
= RISCVSysReg::lookupSysRegByEncoding(Imm
);
1785 // Accept an immediate representing a named or un-named Sys Reg
1786 // if the range is valid, regardless of the required features.
1788 RISCVOperand::createSysReg(SysReg
? SysReg
->Name
: "", S
, Imm
));
1789 return ParseStatus::Success
;
1793 return generateImmOutOfRangeError(S
, 0, (1 << 12) - 1);
1795 case AsmToken::Identifier
: {
1796 StringRef Identifier
;
1797 if (getParser().parseIdentifier(Identifier
))
1798 return ParseStatus::Failure
;
1800 // Check for CSR names conflicts.
1801 // Custom CSR names might conflict with CSR names in privileged spec.
1802 // E.g. - SiFive mnscratch(0x350) and privileged spec mnscratch(0x740).
1803 auto CheckCSRNameConflict
= [&]() {
1804 if (!(RISCVSysReg::lookupSysRegByName(Identifier
))) {
1805 Error(S
, "system register use requires an option to be enabled");
1811 // First check for vendor specific CSRs.
1812 auto SiFiveReg
= RISCVSysReg::lookupSiFiveRegByName(Identifier
);
1814 if (SiFiveReg
->haveVendorRequiredFeatures(getSTI().getFeatureBits())) {
1816 RISCVOperand::createSysReg(Identifier
, S
, SiFiveReg
->Encoding
));
1817 return ParseStatus::Success
;
1819 if (CheckCSRNameConflict())
1820 return ParseStatus::Failure
;
1823 auto SysReg
= RISCVSysReg::lookupSysRegByName(Identifier
);
1825 if ((SysReg
= RISCVSysReg::lookupSysRegByDeprecatedName(Identifier
)))
1826 Warning(S
, "'" + Identifier
+ "' is a deprecated alias for '" +
1827 SysReg
->Name
+ "'");
1829 // Check for CSR encoding conflicts.
1830 // Custom CSR encoding might conflict with CSR encoding in privileged spec.
1831 // E.g. - SiFive mnscratch(0x350) and privileged spec miselect(0x350).
1832 auto CheckCSREncodingConflict
= [&]() {
1833 auto Reg
= RISCVSysReg::lookupSiFiveRegByEncoding(SysReg
->Encoding
);
1834 if (Reg
&& Reg
->haveVendorRequiredFeatures(getSTI().getFeatureBits())) {
1835 Warning(S
, "'" + Identifier
+ "' CSR is not available on the current " +
1836 "subtarget. Instead '" + Reg
->Name
+
1837 "' CSR will be used.");
1839 RISCVOperand::createSysReg(Reg
->Name
, S
, Reg
->Encoding
));
1845 // Accept a named SysReg if the required features are present.
1847 if (!SysReg
->haveRequiredFeatures(getSTI().getFeatureBits()))
1848 return Error(S
, "system register use requires an option to be enabled");
1849 if (CheckCSREncodingConflict())
1850 return ParseStatus::Success
;
1852 RISCVOperand::createSysReg(Identifier
, S
, SysReg
->Encoding
));
1853 return ParseStatus::Success
;
1856 return generateImmOutOfRangeError(S
, 0, (1 << 12) - 1,
1857 "operand must be a valid system register "
1858 "name or an integer in the range");
1860 case AsmToken::Percent
: {
1861 // Discard operand with modifier.
1862 return generateImmOutOfRangeError(S
, 0, (1 << 12) - 1);
1866 return ParseStatus::NoMatch
;
1869 ParseStatus
RISCVAsmParser::parseFPImm(OperandVector
&Operands
) {
1872 // Parse special floats (inf/nan/min) representation.
1873 if (getTok().is(AsmToken::Identifier
)) {
1874 StringRef Identifier
= getTok().getIdentifier();
1875 if (Identifier
.compare_insensitive("inf") == 0) {
1877 RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S
,
1878 getTok().getEndLoc(), isRV64()));
1879 } else if (Identifier
.compare_insensitive("nan") == 0) {
1881 RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S
,
1882 getTok().getEndLoc(), isRV64()));
1883 } else if (Identifier
.compare_insensitive("min") == 0) {
1885 RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S
,
1886 getTok().getEndLoc(), isRV64()));
1888 return TokError("invalid floating point literal");
1891 Lex(); // Eat the token.
1893 return ParseStatus::Success
;
1896 // Handle negation, as that still comes through as a separate token.
1897 bool IsNegative
= parseOptionalToken(AsmToken::Minus
);
1899 const AsmToken
&Tok
= getTok();
1900 if (!Tok
.is(AsmToken::Real
))
1901 return TokError("invalid floating point immediate");
1903 // Parse FP representation.
1904 APFloat
RealVal(APFloat::IEEEdouble());
1906 RealVal
.convertFromString(Tok
.getString(), APFloat::rmTowardZero
);
1907 if (errorToBool(StatusOrErr
.takeError()))
1908 return TokError("invalid floating point representation");
1911 RealVal
.changeSign();
1913 Operands
.push_back(RISCVOperand::createFPImm(
1914 RealVal
.bitcastToAPInt().getZExtValue(), S
));
1916 Lex(); // Eat the token.
1918 return ParseStatus::Success
;
1921 ParseStatus
RISCVAsmParser::parseImmediate(OperandVector
&Operands
) {
1926 switch (getLexer().getKind()) {
1928 return ParseStatus::NoMatch
;
1929 case AsmToken::LParen
:
1931 case AsmToken::Minus
:
1932 case AsmToken::Plus
:
1933 case AsmToken::Exclaim
:
1934 case AsmToken::Tilde
:
1935 case AsmToken::Integer
:
1936 case AsmToken::String
:
1937 case AsmToken::Identifier
:
1938 if (getParser().parseExpression(Res
, E
))
1939 return ParseStatus::Failure
;
1941 case AsmToken::Percent
:
1942 return parseOperandWithModifier(Operands
);
1945 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1946 return ParseStatus::Success
;
1949 ParseStatus
RISCVAsmParser::parseOperandWithModifier(OperandVector
&Operands
) {
1953 if (parseToken(AsmToken::Percent
, "expected '%' for operand modifier"))
1954 return ParseStatus::Failure
;
1956 if (getLexer().getKind() != AsmToken::Identifier
)
1957 return Error(getLoc(), "expected valid identifier for operand modifier");
1958 StringRef Identifier
= getParser().getTok().getIdentifier();
1959 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::getVariantKindForName(Identifier
);
1960 if (VK
== RISCVMCExpr::VK_RISCV_Invalid
)
1961 return Error(getLoc(), "unrecognized operand modifier");
1963 getParser().Lex(); // Eat the identifier
1964 if (parseToken(AsmToken::LParen
, "expected '('"))
1965 return ParseStatus::Failure
;
1967 const MCExpr
*SubExpr
;
1968 if (getParser().parseParenExpression(SubExpr
, E
))
1969 return ParseStatus::Failure
;
1971 const MCExpr
*ModExpr
= RISCVMCExpr::create(SubExpr
, VK
, getContext());
1972 Operands
.push_back(RISCVOperand::createImm(ModExpr
, S
, E
, isRV64()));
1973 return ParseStatus::Success
;
1976 ParseStatus
RISCVAsmParser::parseBareSymbol(OperandVector
&Operands
) {
1980 if (getLexer().getKind() != AsmToken::Identifier
)
1981 return ParseStatus::NoMatch
;
1983 StringRef Identifier
;
1984 AsmToken Tok
= getLexer().getTok();
1986 if (getParser().parseIdentifier(Identifier
))
1987 return ParseStatus::Failure
;
1989 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
1991 if (Identifier
.consume_back("@plt"))
1992 return Error(getLoc(), "'@plt' operand not valid for instruction");
1994 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Identifier
);
1996 if (Sym
->isVariable()) {
1997 const MCExpr
*V
= Sym
->getVariableValue(/*SetUsed=*/false);
1998 if (!isa
<MCSymbolRefExpr
>(V
)) {
1999 getLexer().UnLex(Tok
); // Put back if it's not a bare symbol.
2000 return ParseStatus::NoMatch
;
2004 Res
= MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, getContext());
2006 MCBinaryExpr::Opcode Opcode
;
2007 switch (getLexer().getKind()) {
2009 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2010 return ParseStatus::Success
;
2011 case AsmToken::Plus
:
2012 Opcode
= MCBinaryExpr::Add
;
2015 case AsmToken::Minus
:
2016 Opcode
= MCBinaryExpr::Sub
;
2022 if (getParser().parseExpression(Expr
, E
))
2023 return ParseStatus::Failure
;
2024 Res
= MCBinaryExpr::create(Opcode
, Res
, Expr
, getContext());
2025 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2026 return ParseStatus::Success
;
2029 ParseStatus
RISCVAsmParser::parseCallSymbol(OperandVector
&Operands
) {
2033 if (getLexer().getKind() != AsmToken::Identifier
)
2034 return ParseStatus::NoMatch
;
2036 // Avoid parsing the register in `call rd, foo` as a call symbol.
2037 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement
)
2038 return ParseStatus::NoMatch
;
2040 StringRef Identifier
;
2041 if (getParser().parseIdentifier(Identifier
))
2042 return ParseStatus::Failure
;
2044 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
2046 RISCVMCExpr::VariantKind Kind
= RISCVMCExpr::VK_RISCV_CALL
;
2047 if (Identifier
.consume_back("@plt"))
2048 Kind
= RISCVMCExpr::VK_RISCV_CALL_PLT
;
2050 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Identifier
);
2051 Res
= MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, getContext());
2052 Res
= RISCVMCExpr::create(Res
, Kind
, getContext());
2053 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2054 return ParseStatus::Success
;
2057 ParseStatus
RISCVAsmParser::parsePseudoJumpSymbol(OperandVector
&Operands
) {
2062 if (getParser().parseExpression(Res
, E
))
2063 return ParseStatus::Failure
;
2065 if (Res
->getKind() != MCExpr::ExprKind::SymbolRef
||
2066 cast
<MCSymbolRefExpr
>(Res
)->getKind() ==
2067 MCSymbolRefExpr::VariantKind::VK_PLT
)
2068 return Error(S
, "operand must be a valid jump target");
2070 Res
= RISCVMCExpr::create(Res
, RISCVMCExpr::VK_RISCV_CALL
, getContext());
2071 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2072 return ParseStatus::Success
;
2075 ParseStatus
RISCVAsmParser::parseJALOffset(OperandVector
&Operands
) {
2076 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2077 // both being acceptable forms. When parsing `jal ra, foo` this function
2078 // will be called for the `ra` register operand in an attempt to match the
2079 // single-operand alias. parseJALOffset must fail for this case. It would
2080 // seem logical to try parse the operand using parseImmediate and return
2081 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2082 // the second form rather than the first). We can't do this as there's no
2083 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2084 // is an identifier and is followed by a comma.
2085 if (getLexer().is(AsmToken::Identifier
) &&
2086 getLexer().peekTok().is(AsmToken::Comma
))
2087 return ParseStatus::NoMatch
;
2089 return parseImmediate(Operands
);
2092 bool RISCVAsmParser::parseVTypeToken(StringRef Identifier
, VTypeState
&State
,
2093 unsigned &Sew
, unsigned &Lmul
,
2094 bool &Fractional
, bool &TailAgnostic
,
2095 bool &MaskAgnostic
) {
2097 case VTypeState_SEW
:
2098 if (!Identifier
.consume_front("e"))
2100 if (Identifier
.getAsInteger(10, Sew
))
2102 if (!RISCVVType::isValidSEW(Sew
))
2104 State
= VTypeState_LMUL
;
2106 case VTypeState_LMUL
: {
2107 if (!Identifier
.consume_front("m"))
2109 Fractional
= Identifier
.consume_front("f");
2110 if (Identifier
.getAsInteger(10, Lmul
))
2112 if (!RISCVVType::isValidLMUL(Lmul
, Fractional
))
2114 State
= VTypeState_TailPolicy
;
2117 case VTypeState_TailPolicy
:
2118 if (Identifier
== "ta")
2119 TailAgnostic
= true;
2120 else if (Identifier
== "tu")
2121 TailAgnostic
= false;
2124 State
= VTypeState_MaskPolicy
;
2126 case VTypeState_MaskPolicy
:
2127 if (Identifier
== "ma")
2128 MaskAgnostic
= true;
2129 else if (Identifier
== "mu")
2130 MaskAgnostic
= false;
2133 State
= VTypeState_Done
;
2135 case VTypeState_Done
:
2143 ParseStatus
RISCVAsmParser::parseVTypeI(OperandVector
&Operands
) {
2148 bool Fractional
= false;
2149 bool TailAgnostic
= false;
2150 bool MaskAgnostic
= false;
2152 VTypeState State
= VTypeState_SEW
;
2154 if (getLexer().isNot(AsmToken::Identifier
))
2155 return ParseStatus::NoMatch
;
2157 StringRef Identifier
= getTok().getIdentifier();
2159 if (parseVTypeToken(Identifier
, State
, Sew
, Lmul
, Fractional
, TailAgnostic
,
2161 return ParseStatus::NoMatch
;
2165 while (parseOptionalToken(AsmToken::Comma
)) {
2166 if (getLexer().isNot(AsmToken::Identifier
))
2169 Identifier
= getTok().getIdentifier();
2171 if (parseVTypeToken(Identifier
, State
, Sew
, Lmul
, Fractional
, TailAgnostic
,
2178 if (getLexer().is(AsmToken::EndOfStatement
) && State
== VTypeState_Done
) {
2179 RISCVII::VLMUL VLMUL
= RISCVVType::encodeLMUL(Lmul
, Fractional
);
2182 RISCVVType::encodeVTYPE(VLMUL
, Sew
, TailAgnostic
, MaskAgnostic
);
2183 Operands
.push_back(RISCVOperand::createVType(VTypeI
, S
));
2184 return ParseStatus::Success
;
2187 return generateVTypeError(S
);
2190 bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc
) {
2194 "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2197 ParseStatus
RISCVAsmParser::parseMaskReg(OperandVector
&Operands
) {
2198 if (getLexer().isNot(AsmToken::Identifier
))
2199 return ParseStatus::NoMatch
;
2201 StringRef Name
= getLexer().getTok().getIdentifier();
2202 if (!Name
.consume_back(".t"))
2203 return Error(getLoc(), "expected '.t' suffix");
2204 MCRegister RegNo
= matchRegisterNameHelper(isRVE(), Name
);
2207 return ParseStatus::NoMatch
;
2208 if (RegNo
!= RISCV::V0
)
2209 return ParseStatus::NoMatch
;
2211 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
2213 Operands
.push_back(RISCVOperand::createReg(RegNo
, S
, E
));
2214 return ParseStatus::Success
;
2217 ParseStatus
RISCVAsmParser::parseGPRAsFPR(OperandVector
&Operands
) {
2218 if (getLexer().isNot(AsmToken::Identifier
))
2219 return ParseStatus::NoMatch
;
2221 StringRef Name
= getLexer().getTok().getIdentifier();
2222 MCRegister RegNo
= matchRegisterNameHelper(isRVE(), Name
);
2225 return ParseStatus::NoMatch
;
2227 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
2229 Operands
.push_back(RISCVOperand::createReg(
2230 RegNo
, S
, E
, !getSTI().hasFeature(RISCV::FeatureStdExtF
)));
2231 return ParseStatus::Success
;
2234 ParseStatus
RISCVAsmParser::parseFRMArg(OperandVector
&Operands
) {
2235 if (getLexer().isNot(AsmToken::Identifier
))
2237 "operand must be a valid floating point rounding mode mnemonic");
2239 StringRef Str
= getLexer().getTok().getIdentifier();
2240 RISCVFPRndMode::RoundingMode FRM
= RISCVFPRndMode::stringToRoundingMode(Str
);
2242 if (FRM
== RISCVFPRndMode::Invalid
)
2244 "operand must be a valid floating point rounding mode mnemonic");
2246 Operands
.push_back(RISCVOperand::createFRMArg(FRM
, getLoc()));
2247 Lex(); // Eat identifier token.
2248 return ParseStatus::Success
;
2251 ParseStatus
RISCVAsmParser::parseFenceArg(OperandVector
&Operands
) {
2252 const AsmToken
&Tok
= getLexer().getTok();
2254 if (Tok
.is(AsmToken::Integer
)) {
2255 if (Tok
.getIntVal() != 0)
2258 Operands
.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2260 return ParseStatus::Success
;
2263 if (Tok
.is(AsmToken::Identifier
)) {
2264 StringRef Str
= Tok
.getIdentifier();
2266 // Letters must be unique, taken from 'iorw', and in ascending order. This
2267 // holds as long as each individual character is one of 'iorw' and is
2268 // greater than the previous character.
2272 for (char c
: Str
) {
2278 Imm
|= RISCVFenceField::I
;
2281 Imm
|= RISCVFenceField::O
;
2284 Imm
|= RISCVFenceField::R
;
2287 Imm
|= RISCVFenceField::W
;
2301 Operands
.push_back(RISCVOperand::createFenceArg(Imm
, getLoc()));
2303 return ParseStatus::Success
;
2307 return TokError("operand must be formed of letters selected in-order from "
2311 ParseStatus
RISCVAsmParser::parseMemOpBaseReg(OperandVector
&Operands
) {
2312 if (parseToken(AsmToken::LParen
, "expected '('"))
2313 return ParseStatus::Failure
;
2314 Operands
.push_back(RISCVOperand::createToken("(", getLoc()));
2316 if (!parseRegister(Operands
).isSuccess())
2317 return Error(getLoc(), "expected register");
2319 if (parseToken(AsmToken::RParen
, "expected ')'"))
2320 return ParseStatus::Failure
;
2321 Operands
.push_back(RISCVOperand::createToken(")", getLoc()));
2323 return ParseStatus::Success
;
2326 ParseStatus
RISCVAsmParser::parseZeroOffsetMemOp(OperandVector
&Operands
) {
2327 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2328 // as one of their register operands, such as `(a0)`. This just denotes that
2329 // the register (in this case `a0`) contains a memory address.
2331 // Normally, we would be able to parse these by putting the parens into the
2332 // instruction string. However, GNU as also accepts a zero-offset memory
2333 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2334 // with parseImmediate followed by parseMemOpBaseReg, but these instructions
2335 // do not accept an immediate operand, and we do not want to add a "dummy"
2336 // operand that is silently dropped.
2338 // Instead, we use this custom parser. This will: allow (and discard) an
2339 // offset if it is zero; require (and discard) parentheses; and add only the
2340 // parsed register operand to `Operands`.
2342 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2343 // which will only print the register surrounded by parentheses (which GNU as
2344 // also uses as its canonical representation for these operands).
2345 std::unique_ptr
<RISCVOperand
> OptionalImmOp
;
2347 if (getLexer().isNot(AsmToken::LParen
)) {
2348 // Parse an Integer token. We do not accept arbritrary constant expressions
2349 // in the offset field (because they may include parens, which complicates
2352 SMLoc ImmStart
= getLoc();
2353 if (getParser().parseIntToken(ImmVal
,
2354 "expected '(' or optional integer offset"))
2355 return ParseStatus::Failure
;
2357 // Create a RISCVOperand for checking later (so the error messages are
2358 // nicer), but we don't add it to Operands.
2359 SMLoc ImmEnd
= getLoc();
2361 RISCVOperand::createImm(MCConstantExpr::create(ImmVal
, getContext()),
2362 ImmStart
, ImmEnd
, isRV64());
2365 if (parseToken(AsmToken::LParen
,
2366 OptionalImmOp
? "expected '(' after optional integer offset"
2367 : "expected '(' or optional integer offset"))
2368 return ParseStatus::Failure
;
2370 if (!parseRegister(Operands
).isSuccess())
2371 return Error(getLoc(), "expected register");
2373 if (parseToken(AsmToken::RParen
, "expected ')'"))
2374 return ParseStatus::Failure
;
2376 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2377 if (OptionalImmOp
&& !OptionalImmOp
->isImmZero())
2379 OptionalImmOp
->getStartLoc(), "optional integer offset must be 0",
2380 SMRange(OptionalImmOp
->getStartLoc(), OptionalImmOp
->getEndLoc()));
2382 return ParseStatus::Success
;
2385 ParseStatus
RISCVAsmParser::parseReglist(OperandVector
&Operands
) {
2386 // Rlist: {ra [, s0[-sN]]}
2387 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2390 if (parseToken(AsmToken::LCurly
, "register list must start with '{'"))
2391 return ParseStatus::Failure
;
2393 bool IsEABI
= isRVE();
2395 if (getLexer().isNot(AsmToken::Identifier
))
2396 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2398 StringRef RegName
= getLexer().getTok().getIdentifier();
2399 MCRegister RegStart
= matchRegisterNameHelper(IsEABI
, RegName
);
2401 if (RegStart
!= RISCV::X1
)
2402 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2405 // parse case like ,s0
2406 if (parseOptionalToken(AsmToken::Comma
)) {
2407 if (getLexer().isNot(AsmToken::Identifier
))
2408 return Error(getLoc(), "invalid register");
2409 StringRef RegName
= getLexer().getTok().getIdentifier();
2410 RegStart
= matchRegisterNameHelper(IsEABI
, RegName
);
2412 return Error(getLoc(), "invalid register");
2413 if (RegStart
!= RISCV::X8
)
2414 return Error(getLoc(),
2415 "continuous register list must start from 's0' or 'x8'");
2416 getLexer().Lex(); // eat reg
2419 // parse case like -s1
2420 if (parseOptionalToken(AsmToken::Minus
)) {
2421 StringRef EndName
= getLexer().getTok().getIdentifier();
2422 // FIXME: the register mapping and checks of EABI is wrong
2423 RegEnd
= matchRegisterNameHelper(IsEABI
, EndName
);
2425 return Error(getLoc(), "invalid register");
2426 if (IsEABI
&& RegEnd
!= RISCV::X9
)
2427 return Error(getLoc(), "contiguous register list of EABI can only be "
2428 "'s0-s1' or 'x8-x9' pair");
2433 // parse extra part like ', x18[-x20]' for XRegList
2434 if (parseOptionalToken(AsmToken::Comma
)) {
2435 if (RegEnd
!= RISCV::X9
)
2438 "first contiguous registers pair of register list must be 'x8-x9'");
2440 // parse ', x18' for extra part
2441 if (getLexer().isNot(AsmToken::Identifier
))
2442 return Error(getLoc(), "invalid register");
2443 StringRef EndName
= getLexer().getTok().getIdentifier();
2444 if (MatchRegisterName(EndName
) != RISCV::X18
)
2445 return Error(getLoc(),
2446 "second contiguous registers pair of register list "
2447 "must start from 'x18'");
2450 // parse '-x20' for extra part
2451 if (parseOptionalToken(AsmToken::Minus
)) {
2452 if (getLexer().isNot(AsmToken::Identifier
))
2453 return Error(getLoc(), "invalid register");
2454 EndName
= getLexer().getTok().getIdentifier();
2455 if (MatchRegisterName(EndName
) == RISCV::NoRegister
)
2456 return Error(getLoc(), "invalid register");
2459 RegEnd
= MatchRegisterName(EndName
);
2463 if (RegEnd
== RISCV::X26
)
2464 return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2465 "x18-x26} is not supported");
2467 if (parseToken(AsmToken::RCurly
, "register list must end with '}'"))
2468 return ParseStatus::Failure
;
2470 if (RegEnd
== RISCV::NoRegister
)
2473 auto Encode
= RISCVZC::encodeRlist(RegEnd
, IsEABI
);
2475 return Error(S
, "invalid register list");
2476 Operands
.push_back(RISCVOperand::createRlist(Encode
, S
));
2478 return ParseStatus::Success
;
2481 ParseStatus
RISCVAsmParser::parseZcmpSpimm(OperandVector
&Operands
) {
2482 (void)parseOptionalToken(AsmToken::Minus
);
2485 int64_t StackAdjustment
= getLexer().getTok().getIntVal();
2487 unsigned RlistVal
= static_cast<RISCVOperand
*>(Operands
[1].get())->Rlist
.Val
;
2489 bool IsEABI
= isRVE();
2490 if (!RISCVZC::getSpimm(RlistVal
, Spimm
, StackAdjustment
, isRV64(), IsEABI
))
2491 return ParseStatus::NoMatch
;
2492 Operands
.push_back(RISCVOperand::createSpimm(Spimm
<< 4, S
));
2494 return ParseStatus::Success
;
2497 /// Looks at a token type and creates the relevant operand from this
2498 /// information, adding to Operands. If operand was parsed, returns false, else
2500 bool RISCVAsmParser::parseOperand(OperandVector
&Operands
, StringRef Mnemonic
) {
2501 // Check if the current operand has a custom associated parser, if so, try to
2502 // custom parse the operand, or fallback to the general approach.
2503 ParseStatus Result
=
2504 MatchOperandParserImpl(Operands
, Mnemonic
, /*ParseForAllFeatures=*/true);
2505 if (Result
.isSuccess())
2507 if (Result
.isFailure())
2510 // Attempt to parse token as a register.
2511 if (parseRegister(Operands
, true).isSuccess())
2514 // Attempt to parse token as an immediate
2515 if (parseImmediate(Operands
).isSuccess()) {
2516 // Parse memory base register if present
2517 if (getLexer().is(AsmToken::LParen
))
2518 return !parseMemOpBaseReg(Operands
).isSuccess();
2522 // Finally we have exhausted all options and must declare defeat.
2523 Error(getLoc(), "unknown operand");
2527 bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo
&Info
,
2528 StringRef Name
, SMLoc NameLoc
,
2529 OperandVector
&Operands
) {
2530 // Ensure that if the instruction occurs when relaxation is enabled,
2531 // relocations are forced for the file. Ideally this would be done when there
2532 // is enough information to reliably determine if the instruction itself may
2533 // cause relaxations. Unfortunately instruction processing stage occurs in the
2534 // same pass as relocation emission, so it's too late to set a 'sticky bit'
2535 // for the entire file.
2536 if (getSTI().hasFeature(RISCV::FeatureRelax
)) {
2537 auto *Assembler
= getTargetStreamer().getStreamer().getAssemblerPtr();
2538 if (Assembler
!= nullptr) {
2539 RISCVAsmBackend
&MAB
=
2540 static_cast<RISCVAsmBackend
&>(Assembler
->getBackend());
2541 MAB
.setForceRelocs();
2545 // First operand is token for instruction
2546 Operands
.push_back(RISCVOperand::createToken(Name
, NameLoc
));
2548 // If there are no more operands, then finish
2549 if (getLexer().is(AsmToken::EndOfStatement
)) {
2550 getParser().Lex(); // Consume the EndOfStatement.
2554 // Parse first operand
2555 if (parseOperand(Operands
, Name
))
2558 // Parse until end of statement, consuming commas between operands
2559 while (parseOptionalToken(AsmToken::Comma
)) {
2560 // Parse next operand
2561 if (parseOperand(Operands
, Name
))
2565 if (getParser().parseEOL("unexpected token")) {
2566 getParser().eatToEndOfStatement();
2572 bool RISCVAsmParser::classifySymbolRef(const MCExpr
*Expr
,
2573 RISCVMCExpr::VariantKind
&Kind
) {
2574 Kind
= RISCVMCExpr::VK_RISCV_None
;
2576 if (const RISCVMCExpr
*RE
= dyn_cast
<RISCVMCExpr
>(Expr
)) {
2577 Kind
= RE
->getKind();
2578 Expr
= RE
->getSubExpr();
2583 if (Expr
->evaluateAsRelocatable(Res
, nullptr, &Fixup
))
2584 return Res
.getRefKind() == RISCVMCExpr::VK_RISCV_None
;
2588 bool RISCVAsmParser::isSymbolDiff(const MCExpr
*Expr
) {
2591 if (Expr
->evaluateAsRelocatable(Res
, nullptr, &Fixup
)) {
2592 return Res
.getRefKind() == RISCVMCExpr::VK_RISCV_None
&& Res
.getSymA() &&
2598 ParseStatus
RISCVAsmParser::parseDirective(AsmToken DirectiveID
) {
2599 StringRef IDVal
= DirectiveID
.getString();
2601 if (IDVal
== ".option")
2602 return parseDirectiveOption();
2603 if (IDVal
== ".attribute")
2604 return parseDirectiveAttribute();
2605 if (IDVal
== ".insn")
2606 return parseDirectiveInsn(DirectiveID
.getLoc());
2607 if (IDVal
== ".variant_cc")
2608 return parseDirectiveVariantCC();
2610 return ParseStatus::NoMatch
;
2613 bool RISCVAsmParser::resetToArch(StringRef Arch
, SMLoc Loc
, std::string
&Result
,
2614 bool FromOptionDirective
) {
2615 for (auto Feature
: RISCVFeatureKV
)
2616 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature
.Key
))
2617 clearFeatureBits(Feature
.Value
, Feature
.Key
);
2619 auto ParseResult
= llvm::RISCVISAInfo::parseArchString(
2620 Arch
, /*EnableExperimentalExtension=*/true,
2621 /*ExperimentalExtensionVersionCheck=*/true);
2624 raw_string_ostream
OutputErrMsg(Buffer
);
2625 handleAllErrors(ParseResult
.takeError(), [&](llvm::StringError
&ErrMsg
) {
2626 OutputErrMsg
<< "invalid arch name '" << Arch
<< "', "
2627 << ErrMsg
.getMessage();
2630 return Error(Loc
, OutputErrMsg
.str());
2632 auto &ISAInfo
= *ParseResult
;
2634 for (auto Feature
: RISCVFeatureKV
)
2635 if (ISAInfo
->hasExtension(Feature
.Key
))
2636 setFeatureBits(Feature
.Value
, Feature
.Key
);
2638 if (FromOptionDirective
) {
2639 if (ISAInfo
->getXLen() == 32 && isRV64())
2640 return Error(Loc
, "bad arch string switching from rv64 to rv32");
2641 else if (ISAInfo
->getXLen() == 64 && !isRV64())
2642 return Error(Loc
, "bad arch string switching from rv32 to rv64");
2645 if (ISAInfo
->getXLen() == 32)
2646 clearFeatureBits(RISCV::Feature64Bit
, "64bit");
2647 else if (ISAInfo
->getXLen() == 64)
2648 setFeatureBits(RISCV::Feature64Bit
, "64bit");
2650 return Error(Loc
, "bad arch string " + Arch
);
2652 Result
= ISAInfo
->toString();
2656 bool RISCVAsmParser::parseDirectiveOption() {
2657 MCAsmParser
&Parser
= getParser();
2658 // Get the option token.
2659 AsmToken Tok
= Parser
.getTok();
2661 // At the moment only identifiers are supported.
2662 if (parseToken(AsmToken::Identifier
, "expected identifier"))
2665 StringRef Option
= Tok
.getIdentifier();
2667 if (Option
== "push") {
2668 if (Parser
.parseEOL())
2671 getTargetStreamer().emitDirectiveOptionPush();
2676 if (Option
== "pop") {
2677 SMLoc StartLoc
= Parser
.getTok().getLoc();
2678 if (Parser
.parseEOL())
2681 getTargetStreamer().emitDirectiveOptionPop();
2682 if (popFeatureBits())
2683 return Error(StartLoc
, ".option pop with no .option push");
2688 if (Option
== "arch") {
2689 SmallVector
<RISCVOptionArchArg
> Args
;
2691 if (Parser
.parseComma())
2694 RISCVOptionArchArgType Type
;
2695 if (parseOptionalToken(AsmToken::Plus
))
2696 Type
= RISCVOptionArchArgType::Plus
;
2697 else if (parseOptionalToken(AsmToken::Minus
))
2698 Type
= RISCVOptionArchArgType::Minus
;
2699 else if (!Args
.empty())
2700 return Error(Parser
.getTok().getLoc(),
2701 "unexpected token, expected + or -");
2703 Type
= RISCVOptionArchArgType::Full
;
2705 if (Parser
.getTok().isNot(AsmToken::Identifier
))
2706 return Error(Parser
.getTok().getLoc(),
2707 "unexpected token, expected identifier");
2709 StringRef Arch
= Parser
.getTok().getString();
2710 SMLoc Loc
= Parser
.getTok().getLoc();
2713 if (Type
== RISCVOptionArchArgType::Full
) {
2715 if (resetToArch(Arch
, Loc
, Result
, true))
2718 Args
.emplace_back(Type
, Result
);
2722 ArrayRef
<SubtargetFeatureKV
> KVArray(RISCVFeatureKV
);
2723 auto Ext
= llvm::lower_bound(KVArray
, Arch
);
2724 if (Ext
== KVArray
.end() || StringRef(Ext
->Key
) != Arch
||
2725 !RISCVISAInfo::isSupportedExtension(Arch
)) {
2726 if (isDigit(Arch
.back()))
2729 "Extension version number parsing not currently implemented");
2730 return Error(Loc
, "unknown extension feature");
2733 Args
.emplace_back(Type
, Ext
->Key
);
2735 if (Type
== RISCVOptionArchArgType::Plus
) {
2736 FeatureBitset OldFeatureBits
= STI
->getFeatureBits();
2738 setFeatureBits(Ext
->Value
, Ext
->Key
);
2739 auto ParseResult
= RISCVFeatures::parseFeatureBits(isRV64(), STI
->getFeatureBits());
2741 copySTI().setFeatureBits(OldFeatureBits
);
2742 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits
));
2745 raw_string_ostream
OutputErrMsg(Buffer
);
2746 handleAllErrors(ParseResult
.takeError(), [&](llvm::StringError
&ErrMsg
) {
2747 OutputErrMsg
<< ErrMsg
.getMessage();
2750 return Error(Loc
, OutputErrMsg
.str());
2753 assert(Type
== RISCVOptionArchArgType::Minus
);
2754 // It is invalid to disable an extension that there are other enabled
2755 // extensions depend on it.
2756 // TODO: Make use of RISCVISAInfo to handle this
2757 for (auto Feature
: KVArray
) {
2758 if (getSTI().hasFeature(Feature
.Value
) &&
2759 Feature
.Implies
.test(Ext
->Value
))
2761 Twine("Can't disable ") + Ext
->Key
+ " extension, " +
2762 Feature
.Key
+ " extension requires " + Ext
->Key
+
2763 " extension be enabled");
2766 clearFeatureBits(Ext
->Value
, Ext
->Key
);
2768 } while (Parser
.getTok().isNot(AsmToken::EndOfStatement
));
2770 if (Parser
.parseEOL())
2773 getTargetStreamer().emitDirectiveOptionArch(Args
);
2777 if (Option
== "rvc") {
2778 if (Parser
.parseEOL())
2781 getTargetStreamer().emitDirectiveOptionRVC();
2782 setFeatureBits(RISCV::FeatureStdExtC
, "c");
2786 if (Option
== "norvc") {
2787 if (Parser
.parseEOL())
2790 getTargetStreamer().emitDirectiveOptionNoRVC();
2791 clearFeatureBits(RISCV::FeatureStdExtC
, "c");
2792 clearFeatureBits(RISCV::FeatureStdExtZca
, "+zca");
2796 if (Option
== "pic") {
2797 if (Parser
.parseEOL())
2800 getTargetStreamer().emitDirectiveOptionPIC();
2801 ParserOptions
.IsPicEnabled
= true;
2805 if (Option
== "nopic") {
2806 if (Parser
.parseEOL())
2809 getTargetStreamer().emitDirectiveOptionNoPIC();
2810 ParserOptions
.IsPicEnabled
= false;
2814 if (Option
== "relax") {
2815 if (Parser
.parseEOL())
2818 getTargetStreamer().emitDirectiveOptionRelax();
2819 setFeatureBits(RISCV::FeatureRelax
, "relax");
2823 if (Option
== "norelax") {
2824 if (Parser
.parseEOL())
2827 getTargetStreamer().emitDirectiveOptionNoRelax();
2828 clearFeatureBits(RISCV::FeatureRelax
, "relax");
2833 Warning(Parser
.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
2834 "'rvc', 'norvc', 'arch', 'relax' or "
2836 Parser
.eatToEndOfStatement();
2840 /// parseDirectiveAttribute
2841 /// ::= .attribute expression ',' ( expression | "string" )
2842 /// ::= .attribute identifier ',' ( expression | "string" )
2843 bool RISCVAsmParser::parseDirectiveAttribute() {
2844 MCAsmParser
&Parser
= getParser();
2847 TagLoc
= Parser
.getTok().getLoc();
2848 if (Parser
.getTok().is(AsmToken::Identifier
)) {
2849 StringRef Name
= Parser
.getTok().getIdentifier();
2850 std::optional
<unsigned> Ret
=
2851 ELFAttrs::attrTypeFromString(Name
, RISCVAttrs::getRISCVAttributeTags());
2853 return Error(TagLoc
, "attribute name not recognised: " + Name
);
2857 const MCExpr
*AttrExpr
;
2859 TagLoc
= Parser
.getTok().getLoc();
2860 if (Parser
.parseExpression(AttrExpr
))
2863 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(AttrExpr
);
2864 if (check(!CE
, TagLoc
, "expected numeric constant"))
2867 Tag
= CE
->getValue();
2870 if (Parser
.parseComma())
2873 StringRef StringValue
;
2874 int64_t IntegerValue
= 0;
2875 bool IsIntegerValue
= true;
2877 // RISC-V attributes have a string value if the tag number is odd
2878 // and an integer value if the tag number is even.
2880 IsIntegerValue
= false;
2882 SMLoc ValueExprLoc
= Parser
.getTok().getLoc();
2883 if (IsIntegerValue
) {
2884 const MCExpr
*ValueExpr
;
2885 if (Parser
.parseExpression(ValueExpr
))
2888 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(ValueExpr
);
2890 return Error(ValueExprLoc
, "expected numeric constant");
2891 IntegerValue
= CE
->getValue();
2893 if (Parser
.getTok().isNot(AsmToken::String
))
2894 return Error(Parser
.getTok().getLoc(), "expected string constant");
2896 StringValue
= Parser
.getTok().getStringContents();
2900 if (Parser
.parseEOL())
2904 getTargetStreamer().emitAttribute(Tag
, IntegerValue
);
2905 else if (Tag
!= RISCVAttrs::ARCH
)
2906 getTargetStreamer().emitTextAttribute(Tag
, StringValue
);
2909 if (resetToArch(StringValue
, ValueExprLoc
, Result
, false))
2912 // Then emit the arch string.
2913 getTargetStreamer().emitTextAttribute(Tag
, Result
);
2919 bool isValidInsnFormat(StringRef Format
, bool AllowC
) {
2920 return StringSwitch
<bool>(Format
)
2921 .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
2922 .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC
)
2926 /// parseDirectiveInsn
2927 /// ::= .insn [ format encoding, (operands (, operands)*) ]
2928 bool RISCVAsmParser::parseDirectiveInsn(SMLoc L
) {
2929 MCAsmParser
&Parser
= getParser();
2931 // Expect instruction format as identifier.
2933 SMLoc ErrorLoc
= Parser
.getTok().getLoc();
2934 if (Parser
.parseIdentifier(Format
))
2935 return Error(ErrorLoc
, "expected instruction format");
2937 bool AllowC
= getSTI().hasFeature(RISCV::FeatureStdExtC
) ||
2938 getSTI().hasFeature(RISCV::FeatureStdExtZca
);
2939 if (!isValidInsnFormat(Format
, AllowC
))
2940 return Error(ErrorLoc
, "invalid instruction format");
2942 std::string FormatName
= (".insn_" + Format
).str();
2944 ParseInstructionInfo Info
;
2945 SmallVector
<std::unique_ptr
<MCParsedAsmOperand
>, 8> Operands
;
2947 if (ParseInstruction(Info
, FormatName
, L
, Operands
))
2952 return MatchAndEmitInstruction(L
, Opcode
, Operands
, Parser
.getStreamer(),
2954 /*MatchingInlineAsm=*/false);
2957 /// parseDirectiveVariantCC
2958 /// ::= .variant_cc symbol
2959 bool RISCVAsmParser::parseDirectiveVariantCC() {
2961 if (getParser().parseIdentifier(Name
))
2962 return TokError("expected symbol name");
2965 getTargetStreamer().emitDirectiveVariantCC(
2966 *getContext().getOrCreateSymbol(Name
));
2970 void RISCVAsmParser::emitToStreamer(MCStreamer
&S
, const MCInst
&Inst
) {
2972 bool Res
= RISCVRVC::compress(CInst
, Inst
, getSTI());
2974 ++RISCVNumInstrsCompressed
;
2975 S
.emitInstruction((Res
? CInst
: Inst
), getSTI());
2978 void RISCVAsmParser::emitLoadImm(MCRegister DestReg
, int64_t Value
,
2980 RISCVMatInt::InstSeq Seq
=
2981 RISCVMatInt::generateInstSeq(Value
, getSTI().getFeatureBits());
2983 MCRegister SrcReg
= RISCV::X0
;
2984 for (const RISCVMatInt::Inst
&Inst
: Seq
) {
2985 switch (Inst
.getOpndKind()) {
2986 case RISCVMatInt::Imm
:
2988 MCInstBuilder(Inst
.getOpcode()).addReg(DestReg
).addImm(Inst
.getImm()));
2990 case RISCVMatInt::RegX0
:
2992 Out
, MCInstBuilder(Inst
.getOpcode()).addReg(DestReg
).addReg(SrcReg
).addReg(
2995 case RISCVMatInt::RegReg
:
2997 Out
, MCInstBuilder(Inst
.getOpcode()).addReg(DestReg
).addReg(SrcReg
).addReg(
3000 case RISCVMatInt::RegImm
:
3002 Out
, MCInstBuilder(Inst
.getOpcode()).addReg(DestReg
).addReg(SrcReg
).addImm(
3007 // Only the first instruction has X0 as its source.
3012 void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg
, MCOperand TmpReg
,
3013 const MCExpr
*Symbol
,
3014 RISCVMCExpr::VariantKind VKHi
,
3015 unsigned SecondOpcode
, SMLoc IDLoc
,
3017 // A pair of instructions for PC-relative addressing; expands to
3018 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3019 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3020 MCContext
&Ctx
= getContext();
3022 MCSymbol
*TmpLabel
= Ctx
.createNamedTempSymbol("pcrel_hi");
3023 Out
.emitLabel(TmpLabel
);
3025 const RISCVMCExpr
*SymbolHi
= RISCVMCExpr::create(Symbol
, VKHi
, Ctx
);
3027 Out
, MCInstBuilder(RISCV::AUIPC
).addOperand(TmpReg
).addExpr(SymbolHi
));
3029 const MCExpr
*RefToLinkTmpLabel
=
3030 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel
, Ctx
),
3031 RISCVMCExpr::VK_RISCV_PCREL_LO
, Ctx
);
3033 emitToStreamer(Out
, MCInstBuilder(SecondOpcode
)
3034 .addOperand(DestReg
)
3036 .addExpr(RefToLinkTmpLabel
));
3039 void RISCVAsmParser::emitLoadLocalAddress(MCInst
&Inst
, SMLoc IDLoc
,
3041 // The load local address pseudo-instruction "lla" is used in PC-relative
3042 // addressing of local symbols:
3043 // lla rdest, symbol
3045 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3046 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3047 MCOperand DestReg
= Inst
.getOperand(0);
3048 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3049 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_PCREL_HI
,
3050 RISCV::ADDI
, IDLoc
, Out
);
3053 void RISCVAsmParser::emitLoadGlobalAddress(MCInst
&Inst
, SMLoc IDLoc
,
3055 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3056 // addressing of global symbols:
3057 // lga rdest, symbol
3059 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3060 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3061 MCOperand DestReg
= Inst
.getOperand(0);
3062 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3063 unsigned SecondOpcode
= isRV64() ? RISCV::LD
: RISCV::LW
;
3064 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_GOT_HI
,
3065 SecondOpcode
, IDLoc
, Out
);
3068 void RISCVAsmParser::emitLoadAddress(MCInst
&Inst
, SMLoc IDLoc
,
3070 // The load address pseudo-instruction "la" is used in PC-relative and
3071 // GOT-indirect addressing of global symbols:
3073 // is an alias for either (for non-PIC)
3074 // lla rdest, symbol
3076 // lga rdest, symbol
3077 if (ParserOptions
.IsPicEnabled
)
3078 emitLoadGlobalAddress(Inst
, IDLoc
, Out
);
3080 emitLoadLocalAddress(Inst
, IDLoc
, Out
);
3083 void RISCVAsmParser::emitLoadTLSIEAddress(MCInst
&Inst
, SMLoc IDLoc
,
3085 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3086 // initial-exec TLS model addressing of global symbols:
3087 // la.tls.ie rdest, symbol
3089 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3090 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3091 MCOperand DestReg
= Inst
.getOperand(0);
3092 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3093 unsigned SecondOpcode
= isRV64() ? RISCV::LD
: RISCV::LW
;
3094 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_TLS_GOT_HI
,
3095 SecondOpcode
, IDLoc
, Out
);
3098 void RISCVAsmParser::emitLoadTLSGDAddress(MCInst
&Inst
, SMLoc IDLoc
,
3100 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3101 // global-dynamic TLS model addressing of global symbols:
3102 // la.tls.gd rdest, symbol
3104 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3105 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3106 MCOperand DestReg
= Inst
.getOperand(0);
3107 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3108 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_TLS_GD_HI
,
3109 RISCV::ADDI
, IDLoc
, Out
);
3112 void RISCVAsmParser::emitLoadStoreSymbol(MCInst
&Inst
, unsigned Opcode
,
3113 SMLoc IDLoc
, MCStreamer
&Out
,
3115 // The load/store pseudo-instruction does a pc-relative load with
3118 // The expansion looks like this
3120 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3121 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3122 unsigned DestRegOpIdx
= HasTmpReg
? 1 : 0;
3123 MCOperand DestReg
= Inst
.getOperand(DestRegOpIdx
);
3124 unsigned SymbolOpIdx
= HasTmpReg
? 2 : 1;
3125 MCOperand TmpReg
= Inst
.getOperand(0);
3126 const MCExpr
*Symbol
= Inst
.getOperand(SymbolOpIdx
).getExpr();
3127 emitAuipcInstPair(DestReg
, TmpReg
, Symbol
, RISCVMCExpr::VK_RISCV_PCREL_HI
,
3128 Opcode
, IDLoc
, Out
);
3131 void RISCVAsmParser::emitPseudoExtend(MCInst
&Inst
, bool SignExtend
,
3132 int64_t Width
, SMLoc IDLoc
,
3134 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3135 // amounts dependent on the XLEN.
3137 // The expansion looks like this
3139 // SLLI rd, rs, XLEN - Width
3140 // SR[A|R]I rd, rd, XLEN - Width
3141 MCOperand DestReg
= Inst
.getOperand(0);
3142 MCOperand SourceReg
= Inst
.getOperand(1);
3144 unsigned SecondOpcode
= SignExtend
? RISCV::SRAI
: RISCV::SRLI
;
3145 int64_t ShAmt
= (isRV64() ? 64 : 32) - Width
;
3147 assert(ShAmt
> 0 && "Shift amount must be non-zero.");
3149 emitToStreamer(Out
, MCInstBuilder(RISCV::SLLI
)
3150 .addOperand(DestReg
)
3151 .addOperand(SourceReg
)
3154 emitToStreamer(Out
, MCInstBuilder(SecondOpcode
)
3155 .addOperand(DestReg
)
3156 .addOperand(DestReg
)
3160 void RISCVAsmParser::emitVMSGE(MCInst
&Inst
, unsigned Opcode
, SMLoc IDLoc
,
3162 if (Inst
.getNumOperands() == 3) {
3165 // pseudoinstruction: vmsge{u}.vx vd, va, x
3166 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3167 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3168 .addOperand(Inst
.getOperand(0))
3169 .addOperand(Inst
.getOperand(1))
3170 .addOperand(Inst
.getOperand(2))
3171 .addReg(RISCV::NoRegister
));
3172 emitToStreamer(Out
, MCInstBuilder(RISCV::VMNAND_MM
)
3173 .addOperand(Inst
.getOperand(0))
3174 .addOperand(Inst
.getOperand(0))
3175 .addOperand(Inst
.getOperand(0)));
3176 } else if (Inst
.getNumOperands() == 4) {
3177 // masked va >= x, vd != v0
3179 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3180 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3181 assert(Inst
.getOperand(0).getReg() != RISCV::V0
&&
3182 "The destination register should not be V0.");
3183 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3184 .addOperand(Inst
.getOperand(0))
3185 .addOperand(Inst
.getOperand(1))
3186 .addOperand(Inst
.getOperand(2))
3187 .addOperand(Inst
.getOperand(3)));
3188 emitToStreamer(Out
, MCInstBuilder(RISCV::VMXOR_MM
)
3189 .addOperand(Inst
.getOperand(0))
3190 .addOperand(Inst
.getOperand(0))
3191 .addReg(RISCV::V0
));
3192 } else if (Inst
.getNumOperands() == 5 &&
3193 Inst
.getOperand(0).getReg() == RISCV::V0
) {
3194 // masked va >= x, vd == v0
3196 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3197 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3198 assert(Inst
.getOperand(0).getReg() == RISCV::V0
&&
3199 "The destination register should be V0.");
3200 assert(Inst
.getOperand(1).getReg() != RISCV::V0
&&
3201 "The temporary vector register should not be V0.");
3202 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3203 .addOperand(Inst
.getOperand(1))
3204 .addOperand(Inst
.getOperand(2))
3205 .addOperand(Inst
.getOperand(3))
3206 .addReg(RISCV::NoRegister
));
3207 emitToStreamer(Out
, MCInstBuilder(RISCV::VMANDN_MM
)
3208 .addOperand(Inst
.getOperand(0))
3209 .addOperand(Inst
.getOperand(0))
3210 .addOperand(Inst
.getOperand(1)));
3211 } else if (Inst
.getNumOperands() == 5) {
3212 // masked va >= x, any vd
3214 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3215 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3216 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3217 assert(Inst
.getOperand(1).getReg() != RISCV::V0
&&
3218 "The temporary vector register should not be V0.");
3219 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3220 .addOperand(Inst
.getOperand(1))
3221 .addOperand(Inst
.getOperand(2))
3222 .addOperand(Inst
.getOperand(3))
3223 .addReg(RISCV::NoRegister
));
3224 emitToStreamer(Out
, MCInstBuilder(RISCV::VMANDN_MM
)
3225 .addOperand(Inst
.getOperand(1))
3227 .addOperand(Inst
.getOperand(1)));
3228 emitToStreamer(Out
, MCInstBuilder(RISCV::VMANDN_MM
)
3229 .addOperand(Inst
.getOperand(0))
3230 .addOperand(Inst
.getOperand(0))
3231 .addReg(RISCV::V0
));
3232 emitToStreamer(Out
, MCInstBuilder(RISCV::VMOR_MM
)
3233 .addOperand(Inst
.getOperand(0))
3234 .addOperand(Inst
.getOperand(1))
3235 .addOperand(Inst
.getOperand(0)));
3239 bool RISCVAsmParser::checkPseudoAddTPRel(MCInst
&Inst
,
3240 OperandVector
&Operands
) {
3241 assert(Inst
.getOpcode() == RISCV::PseudoAddTPRel
&& "Invalid instruction");
3242 assert(Inst
.getOperand(2).isReg() && "Unexpected second operand kind");
3243 if (Inst
.getOperand(2).getReg() != RISCV::X4
) {
3244 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[3]).getStartLoc();
3245 return Error(ErrorLoc
, "the second input operand must be tp/x4 when using "
3246 "%tprel_add modifier");
3252 std::unique_ptr
<RISCVOperand
> RISCVAsmParser::defaultMaskRegOp() const {
3253 return RISCVOperand::createReg(RISCV::NoRegister
, llvm::SMLoc(),
3257 std::unique_ptr
<RISCVOperand
> RISCVAsmParser::defaultFRMArgOp() const {
3258 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN
,
3262 std::unique_ptr
<RISCVOperand
> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3263 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE
,
3267 bool RISCVAsmParser::validateInstruction(MCInst
&Inst
,
3268 OperandVector
&Operands
) {
3269 unsigned Opcode
= Inst
.getOpcode();
3271 if (Opcode
== RISCV::PseudoVMSGEU_VX_M_T
||
3272 Opcode
== RISCV::PseudoVMSGE_VX_M_T
) {
3273 unsigned DestReg
= Inst
.getOperand(0).getReg();
3274 unsigned TempReg
= Inst
.getOperand(1).getReg();
3275 if (DestReg
== TempReg
) {
3276 SMLoc Loc
= Operands
.back()->getStartLoc();
3277 return Error(Loc
, "The temporary vector register cannot be the same as "
3278 "the destination register.");
3282 if (Opcode
== RISCV::TH_LDD
|| Opcode
== RISCV::TH_LWUD
||
3283 Opcode
== RISCV::TH_LWD
) {
3284 unsigned Rd1
= Inst
.getOperand(0).getReg();
3285 unsigned Rd2
= Inst
.getOperand(1).getReg();
3286 unsigned Rs1
= Inst
.getOperand(2).getReg();
3287 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3288 if (Rs1
== Rd1
&& Rs1
== Rd2
) {
3289 SMLoc Loc
= Operands
[1]->getStartLoc();
3290 return Error(Loc
, "The source register and destination registers "
3291 "cannot be equal.");
3295 if (Opcode
== RISCV::CM_MVSA01
) {
3296 unsigned Rd1
= Inst
.getOperand(0).getReg();
3297 unsigned Rd2
= Inst
.getOperand(1).getReg();
3299 SMLoc Loc
= Operands
[1]->getStartLoc();
3300 return Error(Loc
, "'rs1' and 'rs2' must be different.");
3304 bool IsTHeadMemPair32
= (Opcode
== RISCV::TH_LWD
||
3305 Opcode
== RISCV::TH_LWUD
|| Opcode
== RISCV::TH_SWD
);
3306 bool IsTHeadMemPair64
= (Opcode
== RISCV::TH_LDD
|| Opcode
== RISCV::TH_SDD
);
3307 // The last operand of XTHeadMemPair instructions must be constant 3 or 4
3308 // depending on the data width.
3309 if (IsTHeadMemPair32
&& Inst
.getOperand(4).getImm() != 3) {
3310 SMLoc Loc
= Operands
.back()->getStartLoc();
3311 return Error(Loc
, "Operand must be constant 3.");
3312 } else if (IsTHeadMemPair64
&& Inst
.getOperand(4).getImm() != 4) {
3313 SMLoc Loc
= Operands
.back()->getStartLoc();
3314 return Error(Loc
, "Operand must be constant 4.");
3317 bool IsAMOCAS_D
= Opcode
== RISCV::AMOCAS_D
|| Opcode
== RISCV::AMOCAS_D_AQ
||
3318 Opcode
== RISCV::AMOCAS_D_RL
||
3319 Opcode
== RISCV::AMOCAS_D_AQ_RL
;
3320 bool IsAMOCAS_Q
= Opcode
== RISCV::AMOCAS_Q
|| Opcode
== RISCV::AMOCAS_Q_AQ
||
3321 Opcode
== RISCV::AMOCAS_Q_RL
||
3322 Opcode
== RISCV::AMOCAS_Q_AQ_RL
;
3323 if ((!isRV64() && IsAMOCAS_D
) || IsAMOCAS_Q
) {
3324 unsigned Rd
= Inst
.getOperand(0).getReg();
3325 unsigned Rs2
= Inst
.getOperand(2).getReg();
3326 assert(Rd
>= RISCV::X0
&& Rd
<= RISCV::X31
);
3327 if ((Rd
- RISCV::X0
) % 2 != 0) {
3328 SMLoc Loc
= Operands
[1]->getStartLoc();
3329 return Error(Loc
, "The destination register must be even.");
3331 assert(Rs2
>= RISCV::X0
&& Rs2
<= RISCV::X31
);
3332 if ((Rs2
- RISCV::X0
) % 2 != 0) {
3333 SMLoc Loc
= Operands
[2]->getStartLoc();
3334 return Error(Loc
, "The source register must be even.");
3338 const MCInstrDesc
&MCID
= MII
.get(Opcode
);
3339 if (!(MCID
.TSFlags
& RISCVII::ConstraintMask
))
3342 if (Opcode
== RISCV::VC_V_XVW
|| Opcode
== RISCV::VC_V_IVW
||
3343 Opcode
== RISCV::VC_V_FVW
|| Opcode
== RISCV::VC_V_VVW
) {
3344 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
3345 unsigned VCIXDst
= Inst
.getOperand(0).getReg();
3346 SMLoc VCIXDstLoc
= Operands
[2]->getStartLoc();
3347 if (MCID
.TSFlags
& RISCVII::VS1Constraint
) {
3348 unsigned VCIXRs1
= Inst
.getOperand(Inst
.getNumOperands() - 1).getReg();
3349 if (VCIXDst
== VCIXRs1
)
3350 return Error(VCIXDstLoc
, "The destination vector register group cannot"
3351 " overlap the source vector register group.");
3353 if (MCID
.TSFlags
& RISCVII::VS2Constraint
) {
3354 unsigned VCIXRs2
= Inst
.getOperand(Inst
.getNumOperands() - 2).getReg();
3355 if (VCIXDst
== VCIXRs2
)
3356 return Error(VCIXDstLoc
, "The destination vector register group cannot"
3357 " overlap the source vector register group.");
3362 unsigned DestReg
= Inst
.getOperand(0).getReg();
3363 unsigned Offset
= 0;
3364 int TiedOp
= MCID
.getOperandConstraint(1, MCOI::TIED_TO
);
3368 // Operands[1] will be the first operand, DestReg.
3369 SMLoc Loc
= Operands
[1]->getStartLoc();
3370 if (MCID
.TSFlags
& RISCVII::VS2Constraint
) {
3371 unsigned CheckReg
= Inst
.getOperand(Offset
+ 1).getReg();
3372 if (DestReg
== CheckReg
)
3373 return Error(Loc
, "The destination vector register group cannot overlap"
3374 " the source vector register group.");
3376 if ((MCID
.TSFlags
& RISCVII::VS1Constraint
) && Inst
.getOperand(Offset
+ 2).isReg()) {
3377 unsigned CheckReg
= Inst
.getOperand(Offset
+ 2).getReg();
3378 if (DestReg
== CheckReg
)
3379 return Error(Loc
, "The destination vector register group cannot overlap"
3380 " the source vector register group.");
3382 if ((MCID
.TSFlags
& RISCVII::VMConstraint
) && (DestReg
== RISCV::V0
)) {
3383 // vadc, vsbc are special cases. These instructions have no mask register.
3384 // The destination register could not be V0.
3385 if (Opcode
== RISCV::VADC_VVM
|| Opcode
== RISCV::VADC_VXM
||
3386 Opcode
== RISCV::VADC_VIM
|| Opcode
== RISCV::VSBC_VVM
||
3387 Opcode
== RISCV::VSBC_VXM
|| Opcode
== RISCV::VFMERGE_VFM
||
3388 Opcode
== RISCV::VMERGE_VIM
|| Opcode
== RISCV::VMERGE_VVM
||
3389 Opcode
== RISCV::VMERGE_VXM
)
3390 return Error(Loc
, "The destination vector register group cannot be V0.");
3392 // Regardless masked or unmasked version, the number of operands is the
3393 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3394 // actually. We need to check the last operand to ensure whether it is
3396 unsigned CheckReg
= Inst
.getOperand(Inst
.getNumOperands() - 1).getReg();
3397 assert((CheckReg
== RISCV::V0
|| CheckReg
== RISCV::NoRegister
) &&
3398 "Unexpected register for mask operand");
3400 if (DestReg
== CheckReg
)
3401 return Error(Loc
, "The destination vector register group cannot overlap"
3402 " the mask register.");
3407 bool RISCVAsmParser::processInstruction(MCInst
&Inst
, SMLoc IDLoc
,
3408 OperandVector
&Operands
,
3412 switch (Inst
.getOpcode()) {
3415 case RISCV::PseudoLLAImm
:
3416 case RISCV::PseudoLAImm
:
3417 case RISCV::PseudoLI
: {
3418 MCRegister Reg
= Inst
.getOperand(0).getReg();
3419 const MCOperand
&Op1
= Inst
.getOperand(1);
3421 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
3422 // Just convert to an addi. This allows compatibility with gas.
3423 emitToStreamer(Out
, MCInstBuilder(RISCV::ADDI
)
3426 .addExpr(Op1
.getExpr()));
3429 int64_t Imm
= Inst
.getOperand(1).getImm();
3430 // On RV32 the immediate here can either be a signed or an unsigned
3431 // 32-bit number. Sign extension has to be performed to ensure that Imm
3432 // represents the expected signed 64-bit number.
3434 Imm
= SignExtend64
<32>(Imm
);
3435 emitLoadImm(Reg
, Imm
, Out
);
3438 case RISCV::PseudoLLA
:
3439 emitLoadLocalAddress(Inst
, IDLoc
, Out
);
3441 case RISCV::PseudoLGA
:
3442 emitLoadGlobalAddress(Inst
, IDLoc
, Out
);
3444 case RISCV::PseudoLA
:
3445 emitLoadAddress(Inst
, IDLoc
, Out
);
3447 case RISCV::PseudoLA_TLS_IE
:
3448 emitLoadTLSIEAddress(Inst
, IDLoc
, Out
);
3450 case RISCV::PseudoLA_TLS_GD
:
3451 emitLoadTLSGDAddress(Inst
, IDLoc
, Out
);
3453 case RISCV::PseudoLB
:
3454 emitLoadStoreSymbol(Inst
, RISCV::LB
, IDLoc
, Out
, /*HasTmpReg=*/false);
3456 case RISCV::PseudoLBU
:
3457 emitLoadStoreSymbol(Inst
, RISCV::LBU
, IDLoc
, Out
, /*HasTmpReg=*/false);
3459 case RISCV::PseudoLH
:
3460 emitLoadStoreSymbol(Inst
, RISCV::LH
, IDLoc
, Out
, /*HasTmpReg=*/false);
3462 case RISCV::PseudoLHU
:
3463 emitLoadStoreSymbol(Inst
, RISCV::LHU
, IDLoc
, Out
, /*HasTmpReg=*/false);
3465 case RISCV::PseudoLW
:
3466 emitLoadStoreSymbol(Inst
, RISCV::LW
, IDLoc
, Out
, /*HasTmpReg=*/false);
3468 case RISCV::PseudoLWU
:
3469 emitLoadStoreSymbol(Inst
, RISCV::LWU
, IDLoc
, Out
, /*HasTmpReg=*/false);
3471 case RISCV::PseudoLD
:
3472 emitLoadStoreSymbol(Inst
, RISCV::LD
, IDLoc
, Out
, /*HasTmpReg=*/false);
3474 case RISCV::PseudoFLH
:
3475 emitLoadStoreSymbol(Inst
, RISCV::FLH
, IDLoc
, Out
, /*HasTmpReg=*/true);
3477 case RISCV::PseudoFLW
:
3478 emitLoadStoreSymbol(Inst
, RISCV::FLW
, IDLoc
, Out
, /*HasTmpReg=*/true);
3480 case RISCV::PseudoFLD
:
3481 emitLoadStoreSymbol(Inst
, RISCV::FLD
, IDLoc
, Out
, /*HasTmpReg=*/true);
3483 case RISCV::PseudoSB
:
3484 emitLoadStoreSymbol(Inst
, RISCV::SB
, IDLoc
, Out
, /*HasTmpReg=*/true);
3486 case RISCV::PseudoSH
:
3487 emitLoadStoreSymbol(Inst
, RISCV::SH
, IDLoc
, Out
, /*HasTmpReg=*/true);
3489 case RISCV::PseudoSW
:
3490 emitLoadStoreSymbol(Inst
, RISCV::SW
, IDLoc
, Out
, /*HasTmpReg=*/true);
3492 case RISCV::PseudoSD
:
3493 emitLoadStoreSymbol(Inst
, RISCV::SD
, IDLoc
, Out
, /*HasTmpReg=*/true);
3495 case RISCV::PseudoFSH
:
3496 emitLoadStoreSymbol(Inst
, RISCV::FSH
, IDLoc
, Out
, /*HasTmpReg=*/true);
3498 case RISCV::PseudoFSW
:
3499 emitLoadStoreSymbol(Inst
, RISCV::FSW
, IDLoc
, Out
, /*HasTmpReg=*/true);
3501 case RISCV::PseudoFSD
:
3502 emitLoadStoreSymbol(Inst
, RISCV::FSD
, IDLoc
, Out
, /*HasTmpReg=*/true);
3504 case RISCV::PseudoAddTPRel
:
3505 if (checkPseudoAddTPRel(Inst
, Operands
))
3508 case RISCV::PseudoSEXT_B
:
3509 emitPseudoExtend(Inst
, /*SignExtend=*/true, /*Width=*/8, IDLoc
, Out
);
3511 case RISCV::PseudoSEXT_H
:
3512 emitPseudoExtend(Inst
, /*SignExtend=*/true, /*Width=*/16, IDLoc
, Out
);
3514 case RISCV::PseudoZEXT_H
:
3515 emitPseudoExtend(Inst
, /*SignExtend=*/false, /*Width=*/16, IDLoc
, Out
);
3517 case RISCV::PseudoZEXT_W
:
3518 emitPseudoExtend(Inst
, /*SignExtend=*/false, /*Width=*/32, IDLoc
, Out
);
3520 case RISCV::PseudoVMSGEU_VX
:
3521 case RISCV::PseudoVMSGEU_VX_M
:
3522 case RISCV::PseudoVMSGEU_VX_M_T
:
3523 emitVMSGE(Inst
, RISCV::VMSLTU_VX
, IDLoc
, Out
);
3525 case RISCV::PseudoVMSGE_VX
:
3526 case RISCV::PseudoVMSGE_VX_M
:
3527 case RISCV::PseudoVMSGE_VX_M_T
:
3528 emitVMSGE(Inst
, RISCV::VMSLT_VX
, IDLoc
, Out
);
3530 case RISCV::PseudoVMSGE_VI
:
3531 case RISCV::PseudoVMSLT_VI
: {
3532 // These instructions are signed and so is immediate so we can subtract one
3533 // and change the opcode.
3534 int64_t Imm
= Inst
.getOperand(2).getImm();
3535 unsigned Opc
= Inst
.getOpcode() == RISCV::PseudoVMSGE_VI
? RISCV::VMSGT_VI
3537 emitToStreamer(Out
, MCInstBuilder(Opc
)
3538 .addOperand(Inst
.getOperand(0))
3539 .addOperand(Inst
.getOperand(1))
3541 .addOperand(Inst
.getOperand(3)));
3544 case RISCV::PseudoVMSGEU_VI
:
3545 case RISCV::PseudoVMSLTU_VI
: {
3546 int64_t Imm
= Inst
.getOperand(2).getImm();
3547 // Unsigned comparisons are tricky because the immediate is signed. If the
3548 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3549 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3550 // vmsne v0, v1, v1 which is always false.
3552 unsigned Opc
= Inst
.getOpcode() == RISCV::PseudoVMSGEU_VI
3555 emitToStreamer(Out
, MCInstBuilder(Opc
)
3556 .addOperand(Inst
.getOperand(0))
3557 .addOperand(Inst
.getOperand(1))
3558 .addOperand(Inst
.getOperand(1))
3559 .addOperand(Inst
.getOperand(3)));
3561 // Other immediate values can subtract one like signed.
3562 unsigned Opc
= Inst
.getOpcode() == RISCV::PseudoVMSGEU_VI
3565 emitToStreamer(Out
, MCInstBuilder(Opc
)
3566 .addOperand(Inst
.getOperand(0))
3567 .addOperand(Inst
.getOperand(1))
3569 .addOperand(Inst
.getOperand(3)));
3576 emitToStreamer(Out
, Inst
);
3580 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeRISCVAsmParser() {
3581 RegisterMCAsmParser
<RISCVAsmParser
> X(getTheRISCV32Target());
3582 RegisterMCAsmParser
<RISCVAsmParser
> Y(getTheRISCV64Target());