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/SmallVector.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/MC/MCAssembler.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCExpr.h"
25 #include "llvm/MC/MCInst.h"
26 #include "llvm/MC/MCInstBuilder.h"
27 #include "llvm/MC/MCInstrInfo.h"
28 #include "llvm/MC/MCObjectFileInfo.h"
29 #include "llvm/MC/MCParser/MCAsmLexer.h"
30 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
31 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
32 #include "llvm/MC/MCRegisterInfo.h"
33 #include "llvm/MC/MCStreamer.h"
34 #include "llvm/MC/MCSubtargetInfo.h"
35 #include "llvm/MC/MCValue.h"
36 #include "llvm/MC/TargetRegistry.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/MathExtras.h"
40 #include "llvm/Support/RISCVAttributes.h"
41 #include "llvm/Support/RISCVISAInfo.h"
47 #define DEBUG_TYPE "riscv-asm-parser"
49 STATISTIC(RISCVNumInstrsCompressed
,
50 "Number of RISC-V Compressed instructions emitted");
52 static cl::opt
<bool> AddBuildAttributes("riscv-add-build-attributes",
56 extern const SubtargetFeatureKV RISCVFeatureKV
[RISCV::NumSubtargetFeatures
];
62 struct ParserOptionsSet
{
66 class RISCVAsmParser
: public MCTargetAsmParser
{
67 // This tracks the parsing of the 4 operands that make up the vtype portion
68 // of vset(i)vli instructions which are separated by commas. The state names
69 // represent the next expected operand with Done meaning no other operands are
74 VTypeState_TailPolicy
,
75 VTypeState_MaskPolicy
,
79 SmallVector
<FeatureBitset
, 4> FeatureBitStack
;
81 SmallVector
<ParserOptionsSet
, 4> ParserOptionsStack
;
82 ParserOptionsSet ParserOptions
;
84 SMLoc
getLoc() const { return getParser().getTok().getLoc(); }
85 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit
); }
86 bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureRVE
); }
88 RISCVTargetStreamer
&getTargetStreamer() {
89 assert(getParser().getStreamer().getTargetStreamer() &&
90 "do not have a target streamer");
91 MCTargetStreamer
&TS
= *getParser().getStreamer().getTargetStreamer();
92 return static_cast<RISCVTargetStreamer
&>(TS
);
95 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
96 unsigned Kind
) override
;
97 unsigned checkTargetMatchPredicate(MCInst
&Inst
) override
;
99 bool generateImmOutOfRangeError(OperandVector
&Operands
, uint64_t ErrorInfo
,
100 int64_t Lower
, int64_t Upper
,
102 bool generateImmOutOfRangeError(SMLoc ErrorLoc
, int64_t Lower
, int64_t Upper
,
105 bool MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
106 OperandVector
&Operands
, MCStreamer
&Out
,
108 bool MatchingInlineAsm
) override
;
110 bool parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
111 ParseStatus
tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
112 SMLoc
&EndLoc
) override
;
114 bool ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
115 SMLoc NameLoc
, OperandVector
&Operands
) override
;
117 ParseStatus
parseDirective(AsmToken DirectiveID
) override
;
119 bool parseVTypeToken(StringRef Identifier
, VTypeState
&State
, unsigned &Sew
,
120 unsigned &Lmul
, bool &Fractional
, bool &TailAgnostic
,
122 bool generateVTypeError(SMLoc ErrorLoc
);
124 // Helper to actually emit an instruction to the MCStreamer. Also, when
125 // possible, compression of the instruction is performed.
126 void emitToStreamer(MCStreamer
&S
, const MCInst
&Inst
);
128 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
129 // synthesize the desired immedate value into the destination register.
130 void emitLoadImm(MCRegister DestReg
, int64_t Value
, MCStreamer
&Out
);
132 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
133 // helpers such as emitLoadLocalAddress and emitLoadAddress.
134 void emitAuipcInstPair(MCOperand DestReg
, MCOperand TmpReg
,
135 const MCExpr
*Symbol
, RISCVMCExpr::VariantKind VKHi
,
136 unsigned SecondOpcode
, SMLoc IDLoc
, MCStreamer
&Out
);
138 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
139 void emitLoadLocalAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
141 // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
142 void emitLoadGlobalAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
144 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
145 void emitLoadAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
147 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
149 void emitLoadTLSIEAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
151 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
153 void emitLoadTLSGDAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
155 // Helper to emit pseudo load/store instruction with a symbol.
156 void emitLoadStoreSymbol(MCInst
&Inst
, unsigned Opcode
, SMLoc IDLoc
,
157 MCStreamer
&Out
, bool HasTmpReg
);
159 // Helper to emit pseudo sign/zero extend instruction.
160 void emitPseudoExtend(MCInst
&Inst
, bool SignExtend
, int64_t Width
,
161 SMLoc IDLoc
, MCStreamer
&Out
);
163 // Helper to emit pseudo vmsge{u}.vx instruction.
164 void emitVMSGE(MCInst
&Inst
, unsigned Opcode
, SMLoc IDLoc
, MCStreamer
&Out
);
166 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
167 // Enforcing this using a restricted register class for the second input
168 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
169 // 'add' is an overloaded mnemonic.
170 bool checkPseudoAddTPRel(MCInst
&Inst
, OperandVector
&Operands
);
172 // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.
173 // Enforcing this using a restricted register class for the output
174 // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact
175 // 'jalr' is an overloaded mnemonic.
176 bool checkPseudoTLSDESCCall(MCInst
&Inst
, OperandVector
&Operands
);
178 // Check instruction constraints.
179 bool validateInstruction(MCInst
&Inst
, OperandVector
&Operands
);
181 /// Helper for processing MC instructions that have been successfully matched
182 /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
183 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
185 bool processInstruction(MCInst
&Inst
, SMLoc IDLoc
, OperandVector
&Operands
,
188 // Auto-generated instruction matching functions
189 #define GET_ASSEMBLER_HEADER
190 #include "RISCVGenAsmMatcher.inc"
192 ParseStatus
parseCSRSystemRegister(OperandVector
&Operands
);
193 ParseStatus
parseFPImm(OperandVector
&Operands
);
194 ParseStatus
parseImmediate(OperandVector
&Operands
);
195 ParseStatus
parseRegister(OperandVector
&Operands
, bool AllowParens
= false);
196 ParseStatus
parseMemOpBaseReg(OperandVector
&Operands
);
197 ParseStatus
parseZeroOffsetMemOp(OperandVector
&Operands
);
198 ParseStatus
parseOperandWithModifier(OperandVector
&Operands
);
199 ParseStatus
parseBareSymbol(OperandVector
&Operands
);
200 ParseStatus
parseCallSymbol(OperandVector
&Operands
);
201 ParseStatus
parsePseudoJumpSymbol(OperandVector
&Operands
);
202 ParseStatus
parseJALOffset(OperandVector
&Operands
);
203 ParseStatus
parseVTypeI(OperandVector
&Operands
);
204 ParseStatus
parseMaskReg(OperandVector
&Operands
);
205 ParseStatus
parseInsnDirectiveOpcode(OperandVector
&Operands
);
206 ParseStatus
parseInsnCDirectiveOpcode(OperandVector
&Operands
);
207 ParseStatus
parseGPRAsFPR(OperandVector
&Operands
);
208 template <bool IsRV64Inst
> ParseStatus
parseGPRPair(OperandVector
&Operands
);
209 ParseStatus
parseGPRPair(OperandVector
&Operands
, bool IsRV64Inst
);
210 ParseStatus
parseFRMArg(OperandVector
&Operands
);
211 ParseStatus
parseFenceArg(OperandVector
&Operands
);
212 ParseStatus
parseReglist(OperandVector
&Operands
);
213 ParseStatus
parseRegReg(OperandVector
&Operands
);
214 ParseStatus
parseRetval(OperandVector
&Operands
);
215 ParseStatus
parseZcmpSpimm(OperandVector
&Operands
);
217 bool parseOperand(OperandVector
&Operands
, StringRef Mnemonic
);
219 bool parseDirectiveOption();
220 bool parseDirectiveAttribute();
221 bool parseDirectiveInsn(SMLoc L
);
222 bool parseDirectiveVariantCC();
224 /// Helper to reset target features for a new arch string. It
225 /// also records the new arch string that is expanded by RISCVISAInfo
226 /// and reports error for invalid arch string.
227 bool resetToArch(StringRef Arch
, SMLoc Loc
, std::string
&Result
,
228 bool FromOptionDirective
);
230 void setFeatureBits(uint64_t Feature
, StringRef FeatureString
) {
231 if (!(getSTI().hasFeature(Feature
))) {
232 MCSubtargetInfo
&STI
= copySTI();
233 setAvailableFeatures(
234 ComputeAvailableFeatures(STI
.ToggleFeature(FeatureString
)));
238 void clearFeatureBits(uint64_t Feature
, StringRef FeatureString
) {
239 if (getSTI().hasFeature(Feature
)) {
240 MCSubtargetInfo
&STI
= copySTI();
241 setAvailableFeatures(
242 ComputeAvailableFeatures(STI
.ToggleFeature(FeatureString
)));
246 void pushFeatureBits() {
247 assert(FeatureBitStack
.size() == ParserOptionsStack
.size() &&
248 "These two stacks must be kept synchronized");
249 FeatureBitStack
.push_back(getSTI().getFeatureBits());
250 ParserOptionsStack
.push_back(ParserOptions
);
253 bool popFeatureBits() {
254 assert(FeatureBitStack
.size() == ParserOptionsStack
.size() &&
255 "These two stacks must be kept synchronized");
256 if (FeatureBitStack
.empty())
259 FeatureBitset FeatureBits
= FeatureBitStack
.pop_back_val();
260 copySTI().setFeatureBits(FeatureBits
);
261 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits
));
263 ParserOptions
= ParserOptionsStack
.pop_back_val();
268 std::unique_ptr
<RISCVOperand
> defaultMaskRegOp() const;
269 std::unique_ptr
<RISCVOperand
> defaultFRMArgOp() const;
270 std::unique_ptr
<RISCVOperand
> defaultFRMArgLegacyOp() const;
273 enum RISCVMatchResultTy
{
274 Match_Dummy
= FIRST_TARGET_MATCH_RESULT_TY
,
275 Match_RequiresEvenGPRs
,
276 #define GET_OPERAND_DIAGNOSTIC_TYPES
277 #include "RISCVGenAsmMatcher.inc"
278 #undef GET_OPERAND_DIAGNOSTIC_TYPES
281 static bool classifySymbolRef(const MCExpr
*Expr
,
282 RISCVMCExpr::VariantKind
&Kind
);
283 static bool isSymbolDiff(const MCExpr
*Expr
);
285 RISCVAsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
286 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
287 : MCTargetAsmParser(Options
, STI
, MII
) {
288 MCAsmParserExtension::Initialize(Parser
);
290 Parser
.addAliasForDirective(".half", ".2byte");
291 Parser
.addAliasForDirective(".hword", ".2byte");
292 Parser
.addAliasForDirective(".word", ".4byte");
293 Parser
.addAliasForDirective(".dword", ".8byte");
294 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
296 auto ABIName
= StringRef(Options
.ABIName
);
297 if (ABIName
.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF
)) {
298 errs() << "Hard-float 'f' ABI can't be used for a target that "
299 "doesn't support the F instruction set extension (ignoring "
301 } else if (ABIName
.ends_with("d") &&
302 !getSTI().hasFeature(RISCV::FeatureStdExtD
)) {
303 errs() << "Hard-float 'd' ABI can't be used for a target that "
304 "doesn't support the D instruction set extension (ignoring "
308 // Use computeTargetABI to check if ABIName is valid. If invalid, output
310 RISCVABI::computeTargetABI(STI
.getTargetTriple(), STI
.getFeatureBits(),
313 const MCObjectFileInfo
*MOFI
= Parser
.getContext().getObjectFileInfo();
314 ParserOptions
.IsPicEnabled
= MOFI
->isPositionIndependent();
316 if (AddBuildAttributes
)
317 getTargetStreamer().emitTargetAttributes(STI
, /*EmitStackAlign*/ false);
321 /// RISCVOperand - Instances of this class represent a parsed machine
323 struct RISCVOperand final
: public MCParsedAsmOperand
{
357 // FIXME: Add the Encoding parsed fields as needed for checks,
358 // e.g.: read/write or user/supervisor/machine privileges.
366 RISCVFPRndMode::RoundingMode FRM
;
386 SMLoc StartLoc
, EndLoc
;
392 struct SysRegOp SysReg
;
393 struct VTypeOp VType
;
395 struct FenceOp Fence
;
396 struct RlistOp Rlist
;
397 struct SpimmOp Spimm
;
398 struct RegRegOp RegReg
;
401 RISCVOperand(KindTy K
) : Kind(K
) {}
404 RISCVOperand(const RISCVOperand
&o
) : MCParsedAsmOperand() {
406 StartLoc
= o
.StartLoc
;
409 case KindTy::Register
:
412 case KindTy::Immediate
:
415 case KindTy::FPImmediate
:
421 case KindTy::SystemRegister
:
445 bool isToken() const override
{ return Kind
== KindTy::Token
; }
446 bool isReg() const override
{ return Kind
== KindTy::Register
; }
447 bool isV0Reg() const {
448 return Kind
== KindTy::Register
&& Reg
.RegNum
== RISCV::V0
;
450 bool isAnyReg() const {
451 return Kind
== KindTy::Register
&&
452 (RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(Reg
.RegNum
) ||
453 RISCVMCRegisterClasses
[RISCV::FPR64RegClassID
].contains(Reg
.RegNum
) ||
454 RISCVMCRegisterClasses
[RISCV::VRRegClassID
].contains(Reg
.RegNum
));
456 bool isAnyRegC() const {
457 return Kind
== KindTy::Register
&&
458 (RISCVMCRegisterClasses
[RISCV::GPRCRegClassID
].contains(
460 RISCVMCRegisterClasses
[RISCV::FPR64CRegClassID
].contains(
463 bool isImm() const override
{ return Kind
== KindTy::Immediate
; }
464 bool isMem() const override
{ return false; }
465 bool isSystemRegister() const { return Kind
== KindTy::SystemRegister
; }
466 bool isRegReg() const { return Kind
== KindTy::RegReg
; }
467 bool isRlist() const { return Kind
== KindTy::Rlist
; }
468 bool isSpimm() const { return Kind
== KindTy::Spimm
; }
471 return Kind
== KindTy::Register
&&
472 RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(Reg
.RegNum
);
475 bool isGPRAsFPR() const { return isGPR() && Reg
.IsGPRAsFPR
; }
477 bool isGPRPair() const {
478 return Kind
== KindTy::Register
&&
479 RISCVMCRegisterClasses
[RISCV::GPRPairRegClassID
].contains(
483 static bool evaluateConstantImm(const MCExpr
*Expr
, int64_t &Imm
,
484 RISCVMCExpr::VariantKind
&VK
) {
485 if (auto *RE
= dyn_cast
<RISCVMCExpr
>(Expr
)) {
487 return RE
->evaluateAsConstant(Imm
);
490 if (auto CE
= dyn_cast
<MCConstantExpr
>(Expr
)) {
491 VK
= RISCVMCExpr::VK_RISCV_None
;
492 Imm
= CE
->getValue();
499 // True if operand is a symbol with no modifiers, or a constant with no
500 // modifiers and isShiftedInt<N-1, 1>(Op).
501 template <int N
> bool isBareSimmNLsb0() const {
503 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
506 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
509 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
511 IsValid
= isShiftedInt
<N
- 1, 1>(Imm
);
512 return IsValid
&& VK
== RISCVMCExpr::VK_RISCV_None
;
515 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
517 bool isBareSymbol() 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_None
;
527 bool isCallSymbol() 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_CALL
||
535 VK
== RISCVMCExpr::VK_RISCV_CALL_PLT
);
538 bool isPseudoJumpSymbol() const {
540 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
541 // Must be of 'immediate' type but not a constant.
542 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
544 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
545 VK
== RISCVMCExpr::VK_RISCV_CALL
;
548 bool isTPRelAddSymbol() const {
550 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
551 // Must be of 'immediate' type but not a constant.
552 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
554 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
555 VK
== RISCVMCExpr::VK_RISCV_TPREL_ADD
;
558 bool isTLSDESCCallSymbol() const {
560 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
561 // Must be of 'immediate' type but not a constant.
562 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
564 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
565 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_CALL
;
568 bool isCSRSystemRegister() const { return isSystemRegister(); }
570 bool isVTypeImm(unsigned N
) const {
572 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
575 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
576 return IsConstantImm
&& isUIntN(N
, Imm
) && VK
== RISCVMCExpr::VK_RISCV_None
;
579 // If the last operand of the vsetvli/vsetvli instruction is a constant
580 // expression, KindTy is Immediate.
581 bool isVTypeI10() const {
582 if (Kind
== KindTy::Immediate
)
583 return isVTypeImm(10);
584 return Kind
== KindTy::VType
;
586 bool isVTypeI11() const {
587 if (Kind
== KindTy::Immediate
)
588 return isVTypeImm(11);
589 return Kind
== KindTy::VType
;
592 /// Return true if the operand is a valid for the fence instruction e.g.
594 bool isFenceArg() const { return Kind
== KindTy::Fence
; }
596 /// Return true if the operand is a valid floating point rounding mode.
597 bool isFRMArg() const { return Kind
== KindTy::FRM
; }
598 bool isFRMArgLegacy() const { return Kind
== KindTy::FRM
; }
599 bool isRTZArg() const { return isFRMArg() && FRM
.FRM
== RISCVFPRndMode::RTZ
; }
601 /// Return true if the operand is a valid fli.s floating-point immediate.
602 bool isLoadFPImm() const {
605 if (Kind
!= KindTy::FPImmediate
)
607 int Idx
= RISCVLoadFPImm::getLoadFPImm(
608 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
609 // Don't allow decimal version of the minimum value. It is a different value
610 // for each supported data type.
611 return Idx
>= 0 && Idx
!= 1;
614 bool isImmXLenLI() const {
616 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
619 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
620 if (VK
== RISCVMCExpr::VK_RISCV_LO
||
621 VK
== RISCVMCExpr::VK_RISCV_PCREL_LO
||
622 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO
||
623 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO
)
625 // Given only Imm, ensuring that the actually specified constant is either
626 // a signed or unsigned 64-bit number is unfortunately impossible.
628 return VK
== RISCVMCExpr::VK_RISCV_None
&&
629 (isRV64Imm() || (isInt
<32>(Imm
) || isUInt
<32>(Imm
)));
632 return RISCVAsmParser::isSymbolDiff(getImm());
635 bool isImmXLenLI_Restricted() const {
637 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
640 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
641 // 'la imm' supports constant immediates only.
642 return IsConstantImm
&& (VK
== RISCVMCExpr::VK_RISCV_None
) &&
643 (isRV64Imm() || (isInt
<32>(Imm
) || isUInt
<32>(Imm
)));
646 bool isUImmLog2XLen() const {
648 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
651 if (!evaluateConstantImm(getImm(), Imm
, VK
) ||
652 VK
!= RISCVMCExpr::VK_RISCV_None
)
654 return (isRV64Imm() && isUInt
<6>(Imm
)) || isUInt
<5>(Imm
);
657 bool isUImmLog2XLenNonZero() const {
659 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
662 if (!evaluateConstantImm(getImm(), Imm
, VK
) ||
663 VK
!= RISCVMCExpr::VK_RISCV_None
)
667 return (isRV64Imm() && isUInt
<6>(Imm
)) || isUInt
<5>(Imm
);
670 bool isUImmLog2XLenHalf() const {
672 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
675 if (!evaluateConstantImm(getImm(), Imm
, VK
) ||
676 VK
!= RISCVMCExpr::VK_RISCV_None
)
678 return (isRV64Imm() && isUInt
<5>(Imm
)) || isUInt
<4>(Imm
);
681 template <unsigned N
> bool IsUImm() const {
683 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
686 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
687 return IsConstantImm
&& isUInt
<N
>(Imm
) && VK
== RISCVMCExpr::VK_RISCV_None
;
690 bool isUImm1() const { return IsUImm
<1>(); }
691 bool isUImm2() const { return IsUImm
<2>(); }
692 bool isUImm3() const { return IsUImm
<3>(); }
693 bool isUImm4() const { return IsUImm
<4>(); }
694 bool isUImm5() const { return IsUImm
<5>(); }
695 bool isUImm6() const { return IsUImm
<6>(); }
696 bool isUImm7() const { return IsUImm
<7>(); }
697 bool isUImm8() const { return IsUImm
<8>(); }
698 bool isUImm20() const { return IsUImm
<20>(); }
700 bool isUImm8GE32() const {
702 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
705 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
706 return IsConstantImm
&& isUInt
<8>(Imm
) && Imm
>= 32 &&
707 VK
== RISCVMCExpr::VK_RISCV_None
;
710 bool isRnumArg() const {
712 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
715 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
716 return IsConstantImm
&& Imm
>= INT64_C(0) && Imm
<= INT64_C(10) &&
717 VK
== RISCVMCExpr::VK_RISCV_None
;
720 bool isRnumArg_0_7() const {
722 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
725 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
726 return IsConstantImm
&& Imm
>= INT64_C(0) && Imm
<= INT64_C(7) &&
727 VK
== RISCVMCExpr::VK_RISCV_None
;
730 bool isRnumArg_1_10() const {
732 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
735 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
736 return IsConstantImm
&& Imm
>= INT64_C(1) && Imm
<= INT64_C(10) &&
737 VK
== RISCVMCExpr::VK_RISCV_None
;
740 bool isRnumArg_2_14() const {
742 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
745 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
746 return IsConstantImm
&& Imm
>= INT64_C(2) && Imm
<= INT64_C(14) &&
747 VK
== RISCVMCExpr::VK_RISCV_None
;
750 bool isSImm5() const {
753 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
755 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
756 return IsConstantImm
&& isInt
<5>(fixImmediateForRV32(Imm
, isRV64Imm())) &&
757 VK
== RISCVMCExpr::VK_RISCV_None
;
760 bool isSImm6() const {
763 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
765 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
766 return IsConstantImm
&& isInt
<6>(fixImmediateForRV32(Imm
, isRV64Imm())) &&
767 VK
== RISCVMCExpr::VK_RISCV_None
;
770 bool isSImm6NonZero() const {
773 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
775 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
776 return IsConstantImm
&& Imm
!= 0 &&
777 isInt
<6>(fixImmediateForRV32(Imm
, isRV64Imm())) &&
778 VK
== RISCVMCExpr::VK_RISCV_None
;
781 bool isCLUIImm() const {
785 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
786 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
787 return IsConstantImm
&& (Imm
!= 0) &&
788 (isUInt
<5>(Imm
) || (Imm
>= 0xfffe0 && Imm
<= 0xfffff)) &&
789 VK
== RISCVMCExpr::VK_RISCV_None
;
792 bool isUImm2Lsb0() const {
796 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
797 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
798 return IsConstantImm
&& isShiftedUInt
<1, 1>(Imm
) &&
799 VK
== RISCVMCExpr::VK_RISCV_None
;
802 bool isUImm7Lsb00() const {
806 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
807 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
808 return IsConstantImm
&& isShiftedUInt
<5, 2>(Imm
) &&
809 VK
== RISCVMCExpr::VK_RISCV_None
;
812 bool isUImm8Lsb00() const {
816 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
817 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
818 return IsConstantImm
&& isShiftedUInt
<6, 2>(Imm
) &&
819 VK
== RISCVMCExpr::VK_RISCV_None
;
822 bool isUImm8Lsb000() const {
826 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
827 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
828 return IsConstantImm
&& isShiftedUInt
<5, 3>(Imm
) &&
829 VK
== RISCVMCExpr::VK_RISCV_None
;
832 bool isSImm9Lsb0() const { return isBareSimmNLsb0
<9>(); }
834 bool isUImm9Lsb000() const {
838 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
839 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
840 return IsConstantImm
&& isShiftedUInt
<6, 3>(Imm
) &&
841 VK
== RISCVMCExpr::VK_RISCV_None
;
844 bool isUImm10Lsb00NonZero() const {
848 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
849 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
850 return IsConstantImm
&& isShiftedUInt
<8, 2>(Imm
) && (Imm
!= 0) &&
851 VK
== RISCVMCExpr::VK_RISCV_None
;
854 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
855 // This allows writing 'addi a0, a0, 0xffffffff'.
856 static int64_t fixImmediateForRV32(int64_t Imm
, bool IsRV64Imm
) {
857 if (IsRV64Imm
|| !isUInt
<32>(Imm
))
859 return SignExtend64
<32>(Imm
);
862 bool isSImm12() const {
863 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
868 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
870 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
872 IsValid
= isInt
<12>(fixImmediateForRV32(Imm
, isRV64Imm()));
873 return IsValid
&& ((IsConstantImm
&& VK
== RISCVMCExpr::VK_RISCV_None
) ||
874 VK
== RISCVMCExpr::VK_RISCV_LO
||
875 VK
== RISCVMCExpr::VK_RISCV_PCREL_LO
||
876 VK
== RISCVMCExpr::VK_RISCV_TPREL_LO
||
877 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO
||
878 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO
);
881 bool isSImm12Lsb0() const { return isBareSimmNLsb0
<12>(); }
883 bool isSImm12Lsb00000() const {
886 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
888 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
889 return IsConstantImm
&& isShiftedInt
<7, 5>(Imm
) &&
890 VK
== RISCVMCExpr::VK_RISCV_None
;
893 bool isSImm13Lsb0() const { return isBareSimmNLsb0
<13>(); }
895 bool isSImm10Lsb0000NonZero() const {
899 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
900 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
901 return IsConstantImm
&& (Imm
!= 0) && isShiftedInt
<6, 4>(Imm
) &&
902 VK
== RISCVMCExpr::VK_RISCV_None
;
905 bool isUImm20LUI() const {
906 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
911 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
912 if (!IsConstantImm
) {
913 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
914 return IsValid
&& (VK
== RISCVMCExpr::VK_RISCV_HI
||
915 VK
== RISCVMCExpr::VK_RISCV_TPREL_HI
);
917 return isUInt
<20>(Imm
) && (VK
== RISCVMCExpr::VK_RISCV_None
||
918 VK
== RISCVMCExpr::VK_RISCV_HI
||
919 VK
== RISCVMCExpr::VK_RISCV_TPREL_HI
);
923 bool isUImm20AUIPC() const {
924 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
929 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
930 if (!IsConstantImm
) {
931 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
932 return IsValid
&& (VK
== RISCVMCExpr::VK_RISCV_PCREL_HI
||
933 VK
== RISCVMCExpr::VK_RISCV_GOT_HI
||
934 VK
== RISCVMCExpr::VK_RISCV_TLS_GOT_HI
||
935 VK
== RISCVMCExpr::VK_RISCV_TLS_GD_HI
||
936 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_HI
);
939 return isUInt
<20>(Imm
) && (VK
== RISCVMCExpr::VK_RISCV_None
||
940 VK
== RISCVMCExpr::VK_RISCV_PCREL_HI
||
941 VK
== RISCVMCExpr::VK_RISCV_GOT_HI
||
942 VK
== RISCVMCExpr::VK_RISCV_TLS_GOT_HI
||
943 VK
== RISCVMCExpr::VK_RISCV_TLS_GD_HI
||
944 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_HI
);
947 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0
<21>(); }
949 bool isImmZero() const {
953 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
954 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
955 return IsConstantImm
&& (Imm
== 0) && VK
== RISCVMCExpr::VK_RISCV_None
;
958 bool isSImm5Plus1() const {
961 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
963 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
964 return IsConstantImm
&&
965 isInt
<5>(fixImmediateForRV32(Imm
, isRV64Imm()) - 1) &&
966 VK
== RISCVMCExpr::VK_RISCV_None
;
969 /// getStartLoc - Gets location of the first token of this operand
970 SMLoc
getStartLoc() const override
{ return StartLoc
; }
971 /// getEndLoc - Gets location of the last token of this operand
972 SMLoc
getEndLoc() const override
{ return EndLoc
; }
973 /// True if this operand is for an RV64 instruction
974 bool isRV64Imm() const {
975 assert(Kind
== KindTy::Immediate
&& "Invalid type access!");
979 unsigned getReg() const override
{
980 assert(Kind
== KindTy::Register
&& "Invalid type access!");
981 return Reg
.RegNum
.id();
984 StringRef
getSysReg() const {
985 assert(Kind
== KindTy::SystemRegister
&& "Invalid type access!");
986 return StringRef(SysReg
.Data
, SysReg
.Length
);
989 const MCExpr
*getImm() const {
990 assert(Kind
== KindTy::Immediate
&& "Invalid type access!");
994 uint64_t getFPConst() const {
995 assert(Kind
== KindTy::FPImmediate
&& "Invalid type access!");
999 StringRef
getToken() const {
1000 assert(Kind
== KindTy::Token
&& "Invalid type access!");
1004 unsigned getVType() const {
1005 assert(Kind
== KindTy::VType
&& "Invalid type access!");
1009 RISCVFPRndMode::RoundingMode
getFRM() const {
1010 assert(Kind
== KindTy::FRM
&& "Invalid type access!");
1014 unsigned getFence() const {
1015 assert(Kind
== KindTy::Fence
&& "Invalid type access!");
1019 void print(raw_ostream
&OS
) const override
{
1020 auto RegName
= [](MCRegister Reg
) {
1022 return RISCVInstPrinter::getRegisterName(Reg
);
1028 case KindTy::Immediate
:
1031 case KindTy::FPImmediate
:
1033 case KindTy::Register
:
1034 OS
<< "<register " << RegName(getReg()) << ">";
1037 OS
<< "'" << getToken() << "'";
1039 case KindTy::SystemRegister
:
1040 OS
<< "<sysreg: " << getSysReg() << '>';
1044 RISCVVType::printVType(getVType(), OS
);
1049 roundingModeToString(getFRM());
1059 RISCVZC::printRlist(Rlist
.Val
, OS
);
1064 RISCVZC::printSpimm(Spimm
.Val
, OS
);
1067 case KindTy::RegReg
:
1068 OS
<< "<RegReg: Reg1 " << RegName(RegReg
.Reg1
);
1069 OS
<< " Reg2 " << RegName(RegReg
.Reg2
);
1074 static std::unique_ptr
<RISCVOperand
> createToken(StringRef Str
, SMLoc S
) {
1075 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Token
);
1082 static std::unique_ptr
<RISCVOperand
>
1083 createReg(unsigned RegNo
, SMLoc S
, SMLoc E
, bool IsGPRAsFPR
= false) {
1084 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Register
);
1085 Op
->Reg
.RegNum
= RegNo
;
1086 Op
->Reg
.IsGPRAsFPR
= IsGPRAsFPR
;
1092 static std::unique_ptr
<RISCVOperand
> createImm(const MCExpr
*Val
, SMLoc S
,
1093 SMLoc E
, bool IsRV64
) {
1094 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Immediate
);
1096 Op
->Imm
.IsRV64
= IsRV64
;
1102 static std::unique_ptr
<RISCVOperand
> createFPImm(uint64_t Val
, SMLoc S
) {
1103 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::FPImmediate
);
1104 Op
->FPImm
.Val
= Val
;
1110 static std::unique_ptr
<RISCVOperand
> createSysReg(StringRef Str
, SMLoc S
,
1111 unsigned Encoding
) {
1112 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::SystemRegister
);
1113 Op
->SysReg
.Data
= Str
.data();
1114 Op
->SysReg
.Length
= Str
.size();
1115 Op
->SysReg
.Encoding
= Encoding
;
1121 static std::unique_ptr
<RISCVOperand
>
1122 createFRMArg(RISCVFPRndMode::RoundingMode FRM
, SMLoc S
) {
1123 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::FRM
);
1130 static std::unique_ptr
<RISCVOperand
> createFenceArg(unsigned Val
, SMLoc S
) {
1131 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Fence
);
1132 Op
->Fence
.Val
= Val
;
1138 static std::unique_ptr
<RISCVOperand
> createVType(unsigned VTypeI
, SMLoc S
) {
1139 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::VType
);
1140 Op
->VType
.Val
= VTypeI
;
1146 static std::unique_ptr
<RISCVOperand
> createRlist(unsigned RlistEncode
,
1148 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Rlist
);
1149 Op
->Rlist
.Val
= RlistEncode
;
1154 static std::unique_ptr
<RISCVOperand
> createRegReg(unsigned Reg1No
,
1155 unsigned Reg2No
, SMLoc S
) {
1156 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::RegReg
);
1157 Op
->RegReg
.Reg1
= Reg1No
;
1158 Op
->RegReg
.Reg2
= Reg2No
;
1164 static std::unique_ptr
<RISCVOperand
> createSpimm(unsigned Spimm
, SMLoc S
) {
1165 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Spimm
);
1166 Op
->Spimm
.Val
= Spimm
;
1171 static void addExpr(MCInst
&Inst
, const MCExpr
*Expr
, bool IsRV64Imm
) {
1172 assert(Expr
&& "Expr shouldn't be null!");
1174 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
1175 bool IsConstant
= evaluateConstantImm(Expr
, Imm
, VK
);
1179 MCOperand::createImm(fixImmediateForRV32(Imm
, IsRV64Imm
)));
1181 Inst
.addOperand(MCOperand::createExpr(Expr
));
1184 // Used by the TableGen Code
1185 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
1186 assert(N
== 1 && "Invalid number of operands!");
1187 Inst
.addOperand(MCOperand::createReg(getReg()));
1190 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
1191 assert(N
== 1 && "Invalid number of operands!");
1192 addExpr(Inst
, getImm(), isRV64Imm());
1195 void addFPImmOperands(MCInst
&Inst
, unsigned N
) const {
1196 assert(N
== 1 && "Invalid number of operands!");
1198 addExpr(Inst
, getImm(), isRV64Imm());
1202 int Imm
= RISCVLoadFPImm::getLoadFPImm(
1203 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1204 Inst
.addOperand(MCOperand::createImm(Imm
));
1207 void addFenceArgOperands(MCInst
&Inst
, unsigned N
) const {
1208 assert(N
== 1 && "Invalid number of operands!");
1209 Inst
.addOperand(MCOperand::createImm(Fence
.Val
));
1212 void addCSRSystemRegisterOperands(MCInst
&Inst
, unsigned N
) const {
1213 assert(N
== 1 && "Invalid number of operands!");
1214 Inst
.addOperand(MCOperand::createImm(SysReg
.Encoding
));
1217 // Support non-canonical syntax:
1218 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
1219 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
1220 void addVTypeIOperands(MCInst
&Inst
, unsigned N
) const {
1221 assert(N
== 1 && "Invalid number of operands!");
1223 if (Kind
== KindTy::Immediate
) {
1224 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
1225 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
1226 (void)IsConstantImm
;
1227 assert(IsConstantImm
&& "Invalid VTypeI Operand!");
1231 Inst
.addOperand(MCOperand::createImm(Imm
));
1234 void addRlistOperands(MCInst
&Inst
, unsigned N
) const {
1235 assert(N
== 1 && "Invalid number of operands!");
1236 Inst
.addOperand(MCOperand::createImm(Rlist
.Val
));
1239 void addRegRegOperands(MCInst
&Inst
, unsigned N
) const {
1240 assert(N
== 1 && "Invalid number of operands!");
1241 Inst
.addOperand(MCOperand::createReg(RegReg
.Reg1
));
1242 Inst
.addOperand(MCOperand::createReg(RegReg
.Reg2
));
1245 void addSpimmOperands(MCInst
&Inst
, unsigned N
) const {
1246 assert(N
== 1 && "Invalid number of operands!");
1247 Inst
.addOperand(MCOperand::createImm(Spimm
.Val
));
1250 void addFRMArgOperands(MCInst
&Inst
, unsigned N
) const {
1251 assert(N
== 1 && "Invalid number of operands!");
1252 Inst
.addOperand(MCOperand::createImm(getFRM()));
1255 } // end anonymous namespace.
1257 #define GET_REGISTER_MATCHER
1258 #define GET_SUBTARGET_FEATURE_NAME
1259 #define GET_MATCHER_IMPLEMENTATION
1260 #define GET_MNEMONIC_SPELL_CHECKER
1261 #include "RISCVGenAsmMatcher.inc"
1263 static MCRegister
convertFPR64ToFPR16(MCRegister Reg
) {
1264 assert(Reg
>= RISCV::F0_D
&& Reg
<= RISCV::F31_D
&& "Invalid register");
1265 return Reg
- RISCV::F0_D
+ RISCV::F0_H
;
1268 static MCRegister
convertFPR64ToFPR32(MCRegister Reg
) {
1269 assert(Reg
>= RISCV::F0_D
&& Reg
<= RISCV::F31_D
&& "Invalid register");
1270 return Reg
- RISCV::F0_D
+ RISCV::F0_F
;
1273 static MCRegister
convertVRToVRMx(const MCRegisterInfo
&RI
, MCRegister Reg
,
1275 unsigned RegClassID
;
1276 if (Kind
== MCK_VRM2
)
1277 RegClassID
= RISCV::VRM2RegClassID
;
1278 else if (Kind
== MCK_VRM4
)
1279 RegClassID
= RISCV::VRM4RegClassID
;
1280 else if (Kind
== MCK_VRM8
)
1281 RegClassID
= RISCV::VRM8RegClassID
;
1284 return RI
.getMatchingSuperReg(Reg
, RISCV::sub_vrm1_0
,
1285 &RISCVMCRegisterClasses
[RegClassID
]);
1288 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand
&AsmOp
,
1290 RISCVOperand
&Op
= static_cast<RISCVOperand
&>(AsmOp
);
1292 return Match_InvalidOperand
;
1294 MCRegister Reg
= Op
.getReg();
1296 RISCVMCRegisterClasses
[RISCV::FPR64RegClassID
].contains(Reg
);
1298 RISCVMCRegisterClasses
[RISCV::FPR64CRegClassID
].contains(Reg
);
1299 bool IsRegVR
= RISCVMCRegisterClasses
[RISCV::VRRegClassID
].contains(Reg
);
1301 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1302 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1303 if ((IsRegFPR64
&& Kind
== MCK_FPR32
) ||
1304 (IsRegFPR64C
&& Kind
== MCK_FPR32C
)) {
1305 Op
.Reg
.RegNum
= convertFPR64ToFPR32(Reg
);
1306 return Match_Success
;
1308 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1309 // register from FPR64 to FPR16 if necessary.
1310 if (IsRegFPR64
&& Kind
== MCK_FPR16
) {
1311 Op
.Reg
.RegNum
= convertFPR64ToFPR16(Reg
);
1312 return Match_Success
;
1314 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1315 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1316 if (IsRegVR
&& (Kind
== MCK_VRM2
|| Kind
== MCK_VRM4
|| Kind
== MCK_VRM8
)) {
1317 Op
.Reg
.RegNum
= convertVRToVRMx(*getContext().getRegisterInfo(), Reg
, Kind
);
1318 if (Op
.Reg
.RegNum
== 0)
1319 return Match_InvalidOperand
;
1320 return Match_Success
;
1322 return Match_InvalidOperand
;
1325 unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst
&Inst
) {
1326 const MCInstrDesc
&MCID
= MII
.get(Inst
.getOpcode());
1328 for (unsigned I
= 0; I
< MCID
.NumOperands
; ++I
) {
1329 if (MCID
.operands()[I
].RegClass
== RISCV::GPRPairRegClassID
) {
1330 const auto &Op
= Inst
.getOperand(I
);
1333 MCRegister Reg
= Op
.getReg();
1334 if (RISCVMCRegisterClasses
[RISCV::GPRPairRegClassID
].contains(Reg
))
1337 // FIXME: We should form a paired register during parsing/matching.
1338 if (((Reg
.id() - RISCV::X0
) & 1) != 0)
1339 return Match_RequiresEvenGPRs
;
1343 return Match_Success
;
1346 bool RISCVAsmParser::generateImmOutOfRangeError(
1347 SMLoc ErrorLoc
, int64_t Lower
, int64_t Upper
,
1348 const Twine
&Msg
= "immediate must be an integer in the range") {
1349 return Error(ErrorLoc
, Msg
+ " [" + Twine(Lower
) + ", " + Twine(Upper
) + "]");
1352 bool RISCVAsmParser::generateImmOutOfRangeError(
1353 OperandVector
&Operands
, uint64_t ErrorInfo
, int64_t Lower
, int64_t Upper
,
1354 const Twine
&Msg
= "immediate must be an integer in the range") {
1355 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1356 return generateImmOutOfRangeError(ErrorLoc
, Lower
, Upper
, Msg
);
1359 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
1360 OperandVector
&Operands
,
1362 uint64_t &ErrorInfo
,
1363 bool MatchingInlineAsm
) {
1365 FeatureBitset MissingFeatures
;
1367 auto Result
= MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MissingFeatures
,
1373 if (validateInstruction(Inst
, Operands
))
1375 return processInstruction(Inst
, IDLoc
, Operands
, Out
);
1376 case Match_MissingFeature
: {
1377 assert(MissingFeatures
.any() && "Unknown missing features!");
1378 bool FirstFeature
= true;
1379 std::string Msg
= "instruction requires the following:";
1380 for (unsigned i
= 0, e
= MissingFeatures
.size(); i
!= e
; ++i
) {
1381 if (MissingFeatures
[i
]) {
1382 Msg
+= FirstFeature
? " " : ", ";
1383 Msg
+= getSubtargetFeatureName(i
);
1384 FirstFeature
= false;
1387 return Error(IDLoc
, Msg
);
1389 case Match_MnemonicFail
: {
1390 FeatureBitset FBS
= ComputeAvailableFeatures(getSTI().getFeatureBits());
1391 std::string Suggestion
= RISCVMnemonicSpellCheck(
1392 ((RISCVOperand
&)*Operands
[0]).getToken(), FBS
, 0);
1393 return Error(IDLoc
, "unrecognized instruction mnemonic" + Suggestion
);
1395 case Match_InvalidOperand
: {
1396 SMLoc ErrorLoc
= IDLoc
;
1397 if (ErrorInfo
!= ~0ULL) {
1398 if (ErrorInfo
>= Operands
.size())
1399 return Error(ErrorLoc
, "too few operands for instruction");
1401 ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1402 if (ErrorLoc
== SMLoc())
1405 return Error(ErrorLoc
, "invalid operand for instruction");
1409 // Handle the case when the error message is of specific type
1410 // other than the generic Match_InvalidOperand, and the
1411 // corresponding operand is missing.
1412 if (Result
> FIRST_TARGET_MATCH_RESULT_TY
) {
1413 SMLoc ErrorLoc
= IDLoc
;
1414 if (ErrorInfo
!= ~0ULL && ErrorInfo
>= Operands
.size())
1415 return Error(ErrorLoc
, "too few operands for instruction");
1421 case Match_RequiresEvenGPRs
:
1423 "double precision floating point operands must use even "
1424 "numbered X register");
1425 case Match_InvalidImmXLenLI
:
1427 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1428 return Error(ErrorLoc
, "operand must be a constant 64-bit integer");
1430 return generateImmOutOfRangeError(Operands
, ErrorInfo
,
1431 std::numeric_limits
<int32_t>::min(),
1432 std::numeric_limits
<uint32_t>::max());
1433 case Match_InvalidImmXLenLI_Restricted
:
1435 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1436 return Error(ErrorLoc
, "operand either must be a constant 64-bit integer "
1437 "or a bare symbol name");
1439 return generateImmOutOfRangeError(
1440 Operands
, ErrorInfo
, std::numeric_limits
<int32_t>::min(),
1441 std::numeric_limits
<uint32_t>::max(),
1442 "operand either must be a bare symbol name or an immediate integer in "
1444 case Match_InvalidImmZero
: {
1445 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1446 return Error(ErrorLoc
, "immediate must be zero");
1448 case Match_InvalidUImmLog2XLen
:
1450 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 6) - 1);
1451 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 5) - 1);
1452 case Match_InvalidUImmLog2XLenNonZero
:
1454 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 1, (1 << 6) - 1);
1455 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 1, (1 << 5) - 1);
1456 case Match_InvalidUImmLog2XLenHalf
:
1458 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 5) - 1);
1459 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 4) - 1);
1460 case Match_InvalidUImm1
:
1461 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 1) - 1);
1462 case Match_InvalidUImm2
:
1463 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 2) - 1);
1464 case Match_InvalidUImm2Lsb0
:
1465 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, 2,
1466 "immediate must be one of");
1467 case Match_InvalidUImm3
:
1468 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 3) - 1);
1469 case Match_InvalidUImm4
:
1470 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 4) - 1);
1471 case Match_InvalidUImm5
:
1472 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 5) - 1);
1473 case Match_InvalidUImm6
:
1474 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 6) - 1);
1475 case Match_InvalidUImm7
:
1476 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 7) - 1);
1477 case Match_InvalidUImm8
:
1478 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 8) - 1);
1479 case Match_InvalidUImm8GE32
:
1480 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 32, (1 << 8) - 1);
1481 case Match_InvalidSImm5
:
1482 return generateImmOutOfRangeError(Operands
, ErrorInfo
, -(1 << 4),
1484 case Match_InvalidSImm6
:
1485 return generateImmOutOfRangeError(Operands
, ErrorInfo
, -(1 << 5),
1487 case Match_InvalidSImm6NonZero
:
1488 return generateImmOutOfRangeError(
1489 Operands
, ErrorInfo
, -(1 << 5), (1 << 5) - 1,
1490 "immediate must be non-zero in the range");
1491 case Match_InvalidCLUIImm
:
1492 return generateImmOutOfRangeError(
1493 Operands
, ErrorInfo
, 1, (1 << 5) - 1,
1494 "immediate must be in [0xfffe0, 0xfffff] or");
1495 case Match_InvalidUImm7Lsb00
:
1496 return generateImmOutOfRangeError(
1497 Operands
, ErrorInfo
, 0, (1 << 7) - 4,
1498 "immediate must be a multiple of 4 bytes in the range");
1499 case Match_InvalidUImm8Lsb00
:
1500 return generateImmOutOfRangeError(
1501 Operands
, ErrorInfo
, 0, (1 << 8) - 4,
1502 "immediate must be a multiple of 4 bytes in the range");
1503 case Match_InvalidUImm8Lsb000
:
1504 return generateImmOutOfRangeError(
1505 Operands
, ErrorInfo
, 0, (1 << 8) - 8,
1506 "immediate must be a multiple of 8 bytes in the range");
1507 case Match_InvalidSImm9Lsb0
:
1508 return generateImmOutOfRangeError(
1509 Operands
, ErrorInfo
, -(1 << 8), (1 << 8) - 2,
1510 "immediate must be a multiple of 2 bytes in the range");
1511 case Match_InvalidUImm9Lsb000
:
1512 return generateImmOutOfRangeError(
1513 Operands
, ErrorInfo
, 0, (1 << 9) - 8,
1514 "immediate must be a multiple of 8 bytes in the range");
1515 case Match_InvalidUImm10Lsb00NonZero
:
1516 return generateImmOutOfRangeError(
1517 Operands
, ErrorInfo
, 4, (1 << 10) - 4,
1518 "immediate must be a multiple of 4 bytes in the range");
1519 case Match_InvalidSImm10Lsb0000NonZero
:
1520 return generateImmOutOfRangeError(
1521 Operands
, ErrorInfo
, -(1 << 9), (1 << 9) - 16,
1522 "immediate must be a multiple of 16 bytes and non-zero in the range");
1523 case Match_InvalidSImm12
:
1524 return generateImmOutOfRangeError(
1525 Operands
, ErrorInfo
, -(1 << 11), (1 << 11) - 1,
1526 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1527 "integer in the range");
1528 case Match_InvalidSImm12Lsb0
:
1529 return generateImmOutOfRangeError(
1530 Operands
, ErrorInfo
, -(1 << 11), (1 << 11) - 2,
1531 "immediate must be a multiple of 2 bytes in the range");
1532 case Match_InvalidSImm12Lsb00000
:
1533 return generateImmOutOfRangeError(
1534 Operands
, ErrorInfo
, -(1 << 11), (1 << 11) - 32,
1535 "immediate must be a multiple of 32 bytes in the range");
1536 case Match_InvalidSImm13Lsb0
:
1537 return generateImmOutOfRangeError(
1538 Operands
, ErrorInfo
, -(1 << 12), (1 << 12) - 2,
1539 "immediate must be a multiple of 2 bytes in the range");
1540 case Match_InvalidUImm20LUI
:
1541 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 20) - 1,
1542 "operand must be a symbol with "
1543 "%hi/%tprel_hi modifier or an integer in "
1545 case Match_InvalidUImm20
:
1546 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 20) - 1);
1547 case Match_InvalidUImm20AUIPC
:
1548 return generateImmOutOfRangeError(
1549 Operands
, ErrorInfo
, 0, (1 << 20) - 1,
1550 "operand must be a symbol with a "
1551 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1552 "an integer in the range");
1553 case Match_InvalidSImm21Lsb0JAL
:
1554 return generateImmOutOfRangeError(
1555 Operands
, ErrorInfo
, -(1 << 20), (1 << 20) - 2,
1556 "immediate must be a multiple of 2 bytes in the range");
1557 case Match_InvalidCSRSystemRegister
: {
1558 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 12) - 1,
1559 "operand must be a valid system register "
1560 "name or an integer in the range");
1562 case Match_InvalidLoadFPImm
: {
1563 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1564 return Error(ErrorLoc
, "operand must be a valid floating-point constant");
1566 case Match_InvalidBareSymbol
: {
1567 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1568 return Error(ErrorLoc
, "operand must be a bare symbol name");
1570 case Match_InvalidPseudoJumpSymbol
: {
1571 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1572 return Error(ErrorLoc
, "operand must be a valid jump target");
1574 case Match_InvalidCallSymbol
: {
1575 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1576 return Error(ErrorLoc
, "operand must be a bare symbol name");
1578 case Match_InvalidTPRelAddSymbol
: {
1579 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1580 return Error(ErrorLoc
, "operand must be a symbol with %tprel_add modifier");
1582 case Match_InvalidTLSDESCCallSymbol
: {
1583 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1584 return Error(ErrorLoc
,
1585 "operand must be a symbol with %tlsdesc_call modifier");
1587 case Match_InvalidRTZArg
: {
1588 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1589 return Error(ErrorLoc
, "operand must be 'rtz' floating-point rounding mode");
1591 case Match_InvalidVTypeI
: {
1592 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1593 return generateVTypeError(ErrorLoc
);
1595 case Match_InvalidVMaskRegister
: {
1596 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1597 return Error(ErrorLoc
, "operand must be v0.t");
1599 case Match_InvalidSImm5Plus1
: {
1600 return generateImmOutOfRangeError(Operands
, ErrorInfo
, -(1 << 4) + 1,
1602 "immediate must be in the range");
1604 case Match_InvalidRlist
: {
1605 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1608 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1610 case Match_InvalidSpimm
: {
1611 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1614 "stack adjustment is invalid for this instruction and register list; "
1615 "refer to Zc spec for a detailed range of stack adjustment");
1617 case Match_InvalidRnumArg
: {
1618 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, 10);
1620 case Match_InvalidRegReg
: {
1621 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1622 return Error(ErrorLoc
, "operands must be register and register");
1626 llvm_unreachable("Unknown match type detected!");
1629 // Attempts to match Name as a register (either using the default name or
1630 // alternative ABI names), setting RegNo to the matching register. Upon
1631 // failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31
1632 // will be rejected.
1633 static MCRegister
matchRegisterNameHelper(bool IsRVE
, StringRef Name
) {
1634 MCRegister Reg
= MatchRegisterName(Name
);
1635 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1636 // match always matches the 64-bit variant, and not the 16/32-bit one.
1637 assert(!(Reg
>= RISCV::F0_H
&& Reg
<= RISCV::F31_H
));
1638 assert(!(Reg
>= RISCV::F0_F
&& Reg
<= RISCV::F31_F
));
1639 // The default FPR register class is based on the tablegen enum ordering.
1640 static_assert(RISCV::F0_D
< RISCV::F0_H
, "FPR matching must be updated");
1641 static_assert(RISCV::F0_D
< RISCV::F0_F
, "FPR matching must be updated");
1643 Reg
= MatchRegisterAltName(Name
);
1644 if (IsRVE
&& Reg
>= RISCV::X16
&& Reg
<= RISCV::X31
)
1645 Reg
= RISCV::NoRegister
;
1649 bool RISCVAsmParser::parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
1651 if (!tryParseRegister(Reg
, StartLoc
, EndLoc
).isSuccess())
1652 return Error(StartLoc
, "invalid register name");
1656 ParseStatus
RISCVAsmParser::tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
1658 const AsmToken
&Tok
= getParser().getTok();
1659 StartLoc
= Tok
.getLoc();
1660 EndLoc
= Tok
.getEndLoc();
1661 StringRef Name
= getLexer().getTok().getIdentifier();
1663 Reg
= matchRegisterNameHelper(isRVE(), Name
);
1665 return ParseStatus::NoMatch
;
1667 getParser().Lex(); // Eat identifier token.
1668 return ParseStatus::Success
;
1671 ParseStatus
RISCVAsmParser::parseRegister(OperandVector
&Operands
,
1673 SMLoc FirstS
= getLoc();
1674 bool HadParens
= false;
1677 // If this is an LParen and a parenthesised register name is allowed, parse it
1679 if (AllowParens
&& getLexer().is(AsmToken::LParen
)) {
1681 size_t ReadCount
= getLexer().peekTokens(Buf
);
1682 if (ReadCount
== 2 && Buf
[1].getKind() == AsmToken::RParen
) {
1684 LParen
= getParser().getTok();
1685 getParser().Lex(); // Eat '('
1689 switch (getLexer().getKind()) {
1692 getLexer().UnLex(LParen
);
1693 return ParseStatus::NoMatch
;
1694 case AsmToken::Identifier
:
1695 StringRef Name
= getLexer().getTok().getIdentifier();
1696 MCRegister RegNo
= matchRegisterNameHelper(isRVE(), Name
);
1700 getLexer().UnLex(LParen
);
1701 return ParseStatus::NoMatch
;
1704 Operands
.push_back(RISCVOperand::createToken("(", FirstS
));
1706 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
1708 Operands
.push_back(RISCVOperand::createReg(RegNo
, S
, E
));
1712 getParser().Lex(); // Eat ')'
1713 Operands
.push_back(RISCVOperand::createToken(")", getLoc()));
1716 return ParseStatus::Success
;
1719 ParseStatus
RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector
&Operands
) {
1724 switch (getLexer().getKind()) {
1726 return ParseStatus::NoMatch
;
1727 case AsmToken::LParen
:
1728 case AsmToken::Minus
:
1729 case AsmToken::Plus
:
1730 case AsmToken::Exclaim
:
1731 case AsmToken::Tilde
:
1732 case AsmToken::Integer
:
1733 case AsmToken::String
: {
1734 if (getParser().parseExpression(Res
, E
))
1735 return ParseStatus::Failure
;
1737 auto *CE
= dyn_cast
<MCConstantExpr
>(Res
);
1739 int64_t Imm
= CE
->getValue();
1740 if (isUInt
<7>(Imm
)) {
1741 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1742 return ParseStatus::Success
;
1748 case AsmToken::Identifier
: {
1749 StringRef Identifier
;
1750 if (getParser().parseIdentifier(Identifier
))
1751 return ParseStatus::Failure
;
1753 auto Opcode
= RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier
);
1755 assert(isUInt
<7>(Opcode
->Value
) && (Opcode
->Value
& 0x3) == 3 &&
1756 "Unexpected opcode");
1757 Res
= MCConstantExpr::create(Opcode
->Value
, getContext());
1758 E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
1759 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1760 return ParseStatus::Success
;
1765 case AsmToken::Percent
:
1769 return generateImmOutOfRangeError(
1771 "opcode must be a valid opcode name or an immediate in the range");
1774 ParseStatus
RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector
&Operands
) {
1779 switch (getLexer().getKind()) {
1781 return ParseStatus::NoMatch
;
1782 case AsmToken::LParen
:
1783 case AsmToken::Minus
:
1784 case AsmToken::Plus
:
1785 case AsmToken::Exclaim
:
1786 case AsmToken::Tilde
:
1787 case AsmToken::Integer
:
1788 case AsmToken::String
: {
1789 if (getParser().parseExpression(Res
, E
))
1790 return ParseStatus::Failure
;
1792 auto *CE
= dyn_cast
<MCConstantExpr
>(Res
);
1794 int64_t Imm
= CE
->getValue();
1795 if (Imm
>= 0 && Imm
<= 2) {
1796 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1797 return ParseStatus::Success
;
1803 case AsmToken::Identifier
: {
1804 StringRef Identifier
;
1805 if (getParser().parseIdentifier(Identifier
))
1806 return ParseStatus::Failure
;
1809 if (Identifier
== "C0")
1811 else if (Identifier
== "C1")
1813 else if (Identifier
== "C2")
1818 Res
= MCConstantExpr::create(Opcode
, getContext());
1819 E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
1820 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1821 return ParseStatus::Success
;
1823 case AsmToken::Percent
: {
1824 // Discard operand with modifier.
1829 return generateImmOutOfRangeError(
1831 "opcode must be a valid opcode name or an immediate in the range");
1834 ParseStatus
RISCVAsmParser::parseCSRSystemRegister(OperandVector
&Operands
) {
1838 switch (getLexer().getKind()) {
1840 return ParseStatus::NoMatch
;
1841 case AsmToken::LParen
:
1842 case AsmToken::Minus
:
1843 case AsmToken::Plus
:
1844 case AsmToken::Exclaim
:
1845 case AsmToken::Tilde
:
1846 case AsmToken::Integer
:
1847 case AsmToken::String
: {
1848 if (getParser().parseExpression(Res
))
1849 return ParseStatus::Failure
;
1851 auto *CE
= dyn_cast
<MCConstantExpr
>(Res
);
1853 int64_t Imm
= CE
->getValue();
1854 if (isUInt
<12>(Imm
)) {
1855 auto SysReg
= RISCVSysReg::lookupSysRegByEncoding(Imm
);
1856 // Accept an immediate representing a named or un-named Sys Reg
1857 // if the range is valid, regardless of the required features.
1859 RISCVOperand::createSysReg(SysReg
? SysReg
->Name
: "", S
, Imm
));
1860 return ParseStatus::Success
;
1864 return generateImmOutOfRangeError(S
, 0, (1 << 12) - 1);
1866 case AsmToken::Identifier
: {
1867 StringRef Identifier
;
1868 if (getParser().parseIdentifier(Identifier
))
1869 return ParseStatus::Failure
;
1871 auto SysReg
= RISCVSysReg::lookupSysRegByName(Identifier
);
1873 SysReg
= RISCVSysReg::lookupSysRegByAltName(Identifier
);
1875 if ((SysReg
= RISCVSysReg::lookupSysRegByDeprecatedName(Identifier
)))
1876 Warning(S
, "'" + Identifier
+ "' is a deprecated alias for '" +
1877 SysReg
->Name
+ "'");
1879 // Accept a named Sys Reg if the required features are present.
1881 if (!SysReg
->haveRequiredFeatures(getSTI().getFeatureBits()))
1882 return Error(S
, "system register use requires an option to be enabled");
1884 RISCVOperand::createSysReg(Identifier
, S
, SysReg
->Encoding
));
1885 return ParseStatus::Success
;
1888 return generateImmOutOfRangeError(S
, 0, (1 << 12) - 1,
1889 "operand must be a valid system register "
1890 "name or an integer in the range");
1892 case AsmToken::Percent
: {
1893 // Discard operand with modifier.
1894 return generateImmOutOfRangeError(S
, 0, (1 << 12) - 1);
1898 return ParseStatus::NoMatch
;
1901 ParseStatus
RISCVAsmParser::parseFPImm(OperandVector
&Operands
) {
1904 // Parse special floats (inf/nan/min) representation.
1905 if (getTok().is(AsmToken::Identifier
)) {
1906 StringRef Identifier
= getTok().getIdentifier();
1907 if (Identifier
.compare_insensitive("inf") == 0) {
1909 RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S
,
1910 getTok().getEndLoc(), isRV64()));
1911 } else if (Identifier
.compare_insensitive("nan") == 0) {
1913 RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S
,
1914 getTok().getEndLoc(), isRV64()));
1915 } else if (Identifier
.compare_insensitive("min") == 0) {
1917 RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S
,
1918 getTok().getEndLoc(), isRV64()));
1920 return TokError("invalid floating point literal");
1923 Lex(); // Eat the token.
1925 return ParseStatus::Success
;
1928 // Handle negation, as that still comes through as a separate token.
1929 bool IsNegative
= parseOptionalToken(AsmToken::Minus
);
1931 const AsmToken
&Tok
= getTok();
1932 if (!Tok
.is(AsmToken::Real
))
1933 return TokError("invalid floating point immediate");
1935 // Parse FP representation.
1936 APFloat
RealVal(APFloat::IEEEdouble());
1938 RealVal
.convertFromString(Tok
.getString(), APFloat::rmTowardZero
);
1939 if (errorToBool(StatusOrErr
.takeError()))
1940 return TokError("invalid floating point representation");
1943 RealVal
.changeSign();
1945 Operands
.push_back(RISCVOperand::createFPImm(
1946 RealVal
.bitcastToAPInt().getZExtValue(), S
));
1948 Lex(); // Eat the token.
1950 return ParseStatus::Success
;
1953 ParseStatus
RISCVAsmParser::parseImmediate(OperandVector
&Operands
) {
1958 switch (getLexer().getKind()) {
1960 return ParseStatus::NoMatch
;
1961 case AsmToken::LParen
:
1963 case AsmToken::Minus
:
1964 case AsmToken::Plus
:
1965 case AsmToken::Exclaim
:
1966 case AsmToken::Tilde
:
1967 case AsmToken::Integer
:
1968 case AsmToken::String
:
1969 case AsmToken::Identifier
:
1970 if (getParser().parseExpression(Res
, E
))
1971 return ParseStatus::Failure
;
1973 case AsmToken::Percent
:
1974 return parseOperandWithModifier(Operands
);
1977 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1978 return ParseStatus::Success
;
1981 ParseStatus
RISCVAsmParser::parseOperandWithModifier(OperandVector
&Operands
) {
1985 if (parseToken(AsmToken::Percent
, "expected '%' for operand modifier"))
1986 return ParseStatus::Failure
;
1988 if (getLexer().getKind() != AsmToken::Identifier
)
1989 return Error(getLoc(), "expected valid identifier for operand modifier");
1990 StringRef Identifier
= getParser().getTok().getIdentifier();
1991 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::getVariantKindForName(Identifier
);
1992 if (VK
== RISCVMCExpr::VK_RISCV_Invalid
)
1993 return Error(getLoc(), "unrecognized operand modifier");
1995 getParser().Lex(); // Eat the identifier
1996 if (parseToken(AsmToken::LParen
, "expected '('"))
1997 return ParseStatus::Failure
;
1999 const MCExpr
*SubExpr
;
2000 if (getParser().parseParenExpression(SubExpr
, E
))
2001 return ParseStatus::Failure
;
2003 const MCExpr
*ModExpr
= RISCVMCExpr::create(SubExpr
, VK
, getContext());
2004 Operands
.push_back(RISCVOperand::createImm(ModExpr
, S
, E
, isRV64()));
2005 return ParseStatus::Success
;
2008 ParseStatus
RISCVAsmParser::parseBareSymbol(OperandVector
&Operands
) {
2012 if (getLexer().getKind() != AsmToken::Identifier
)
2013 return ParseStatus::NoMatch
;
2015 StringRef Identifier
;
2016 AsmToken Tok
= getLexer().getTok();
2018 if (getParser().parseIdentifier(Identifier
))
2019 return ParseStatus::Failure
;
2021 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
2023 if (Identifier
.consume_back("@plt"))
2024 return Error(getLoc(), "'@plt' operand not valid for instruction");
2026 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Identifier
);
2028 if (Sym
->isVariable()) {
2029 const MCExpr
*V
= Sym
->getVariableValue(/*SetUsed=*/false);
2030 if (!isa
<MCSymbolRefExpr
>(V
)) {
2031 getLexer().UnLex(Tok
); // Put back if it's not a bare symbol.
2032 return ParseStatus::NoMatch
;
2036 Res
= MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, getContext());
2038 MCBinaryExpr::Opcode Opcode
;
2039 switch (getLexer().getKind()) {
2041 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2042 return ParseStatus::Success
;
2043 case AsmToken::Plus
:
2044 Opcode
= MCBinaryExpr::Add
;
2047 case AsmToken::Minus
:
2048 Opcode
= MCBinaryExpr::Sub
;
2054 if (getParser().parseExpression(Expr
, E
))
2055 return ParseStatus::Failure
;
2056 Res
= MCBinaryExpr::create(Opcode
, Res
, Expr
, getContext());
2057 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2058 return ParseStatus::Success
;
2061 ParseStatus
RISCVAsmParser::parseCallSymbol(OperandVector
&Operands
) {
2065 if (getLexer().getKind() != AsmToken::Identifier
)
2066 return ParseStatus::NoMatch
;
2068 // Avoid parsing the register in `call rd, foo` as a call symbol.
2069 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement
)
2070 return ParseStatus::NoMatch
;
2072 StringRef Identifier
;
2073 if (getParser().parseIdentifier(Identifier
))
2074 return ParseStatus::Failure
;
2076 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
2078 RISCVMCExpr::VariantKind Kind
= RISCVMCExpr::VK_RISCV_CALL_PLT
;
2079 (void)Identifier
.consume_back("@plt");
2081 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Identifier
);
2082 Res
= MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, getContext());
2083 Res
= RISCVMCExpr::create(Res
, Kind
, getContext());
2084 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2085 return ParseStatus::Success
;
2088 ParseStatus
RISCVAsmParser::parsePseudoJumpSymbol(OperandVector
&Operands
) {
2093 if (getParser().parseExpression(Res
, E
))
2094 return ParseStatus::Failure
;
2096 if (Res
->getKind() != MCExpr::ExprKind::SymbolRef
||
2097 cast
<MCSymbolRefExpr
>(Res
)->getKind() ==
2098 MCSymbolRefExpr::VariantKind::VK_PLT
)
2099 return Error(S
, "operand must be a valid jump target");
2101 Res
= RISCVMCExpr::create(Res
, RISCVMCExpr::VK_RISCV_CALL
, getContext());
2102 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2103 return ParseStatus::Success
;
2106 ParseStatus
RISCVAsmParser::parseJALOffset(OperandVector
&Operands
) {
2107 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2108 // both being acceptable forms. When parsing `jal ra, foo` this function
2109 // will be called for the `ra` register operand in an attempt to match the
2110 // single-operand alias. parseJALOffset must fail for this case. It would
2111 // seem logical to try parse the operand using parseImmediate and return
2112 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2113 // the second form rather than the first). We can't do this as there's no
2114 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2115 // is an identifier and is followed by a comma.
2116 if (getLexer().is(AsmToken::Identifier
) &&
2117 getLexer().peekTok().is(AsmToken::Comma
))
2118 return ParseStatus::NoMatch
;
2120 return parseImmediate(Operands
);
2123 bool RISCVAsmParser::parseVTypeToken(StringRef Identifier
, VTypeState
&State
,
2124 unsigned &Sew
, unsigned &Lmul
,
2125 bool &Fractional
, bool &TailAgnostic
,
2126 bool &MaskAgnostic
) {
2128 case VTypeState_SEW
:
2129 if (!Identifier
.consume_front("e"))
2131 if (Identifier
.getAsInteger(10, Sew
))
2133 if (!RISCVVType::isValidSEW(Sew
))
2135 State
= VTypeState_LMUL
;
2137 case VTypeState_LMUL
: {
2138 if (!Identifier
.consume_front("m"))
2140 Fractional
= Identifier
.consume_front("f");
2141 if (Identifier
.getAsInteger(10, Lmul
))
2143 if (!RISCVVType::isValidLMUL(Lmul
, Fractional
))
2145 State
= VTypeState_TailPolicy
;
2148 case VTypeState_TailPolicy
:
2149 if (Identifier
== "ta")
2150 TailAgnostic
= true;
2151 else if (Identifier
== "tu")
2152 TailAgnostic
= false;
2155 State
= VTypeState_MaskPolicy
;
2157 case VTypeState_MaskPolicy
:
2158 if (Identifier
== "ma")
2159 MaskAgnostic
= true;
2160 else if (Identifier
== "mu")
2161 MaskAgnostic
= false;
2164 State
= VTypeState_Done
;
2166 case VTypeState_Done
:
2174 ParseStatus
RISCVAsmParser::parseVTypeI(OperandVector
&Operands
) {
2179 bool Fractional
= false;
2180 bool TailAgnostic
= false;
2181 bool MaskAgnostic
= false;
2183 VTypeState State
= VTypeState_SEW
;
2185 if (getLexer().isNot(AsmToken::Identifier
))
2186 return ParseStatus::NoMatch
;
2188 StringRef Identifier
= getTok().getIdentifier();
2190 if (parseVTypeToken(Identifier
, State
, Sew
, Lmul
, Fractional
, TailAgnostic
,
2192 return ParseStatus::NoMatch
;
2196 while (parseOptionalToken(AsmToken::Comma
)) {
2197 if (getLexer().isNot(AsmToken::Identifier
))
2200 Identifier
= getTok().getIdentifier();
2202 if (parseVTypeToken(Identifier
, State
, Sew
, Lmul
, Fractional
, TailAgnostic
,
2209 if (getLexer().is(AsmToken::EndOfStatement
) && State
== VTypeState_Done
) {
2210 RISCVII::VLMUL VLMUL
= RISCVVType::encodeLMUL(Lmul
, Fractional
);
2213 RISCVVType::encodeVTYPE(VLMUL
, Sew
, TailAgnostic
, MaskAgnostic
);
2214 Operands
.push_back(RISCVOperand::createVType(VTypeI
, S
));
2215 return ParseStatus::Success
;
2218 return generateVTypeError(S
);
2221 bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc
) {
2225 "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2228 ParseStatus
RISCVAsmParser::parseMaskReg(OperandVector
&Operands
) {
2229 if (getLexer().isNot(AsmToken::Identifier
))
2230 return ParseStatus::NoMatch
;
2232 StringRef Name
= getLexer().getTok().getIdentifier();
2233 if (!Name
.consume_back(".t"))
2234 return Error(getLoc(), "expected '.t' suffix");
2235 MCRegister RegNo
= matchRegisterNameHelper(isRVE(), Name
);
2238 return ParseStatus::NoMatch
;
2239 if (RegNo
!= RISCV::V0
)
2240 return ParseStatus::NoMatch
;
2242 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
2244 Operands
.push_back(RISCVOperand::createReg(RegNo
, S
, E
));
2245 return ParseStatus::Success
;
2248 ParseStatus
RISCVAsmParser::parseGPRAsFPR(OperandVector
&Operands
) {
2249 if (getLexer().isNot(AsmToken::Identifier
))
2250 return ParseStatus::NoMatch
;
2252 StringRef Name
= getLexer().getTok().getIdentifier();
2253 MCRegister RegNo
= matchRegisterNameHelper(isRVE(), Name
);
2256 return ParseStatus::NoMatch
;
2258 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
2260 Operands
.push_back(RISCVOperand::createReg(
2261 RegNo
, S
, E
, !getSTI().hasFeature(RISCV::FeatureStdExtF
)));
2262 return ParseStatus::Success
;
2265 template <bool IsRV64
>
2266 ParseStatus
RISCVAsmParser::parseGPRPair(OperandVector
&Operands
) {
2267 return parseGPRPair(Operands
, IsRV64
);
2270 ParseStatus
RISCVAsmParser::parseGPRPair(OperandVector
&Operands
,
2272 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2273 // RV64 as it will prevent matching the RV64 version of the same instruction
2274 // that doesn't use a GPRPair.
2275 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2276 // still parse as a pair.
2277 if (!IsRV64Inst
&& isRV64())
2278 return ParseStatus::NoMatch
;
2280 if (getLexer().isNot(AsmToken::Identifier
))
2281 return ParseStatus::NoMatch
;
2283 StringRef Name
= getLexer().getTok().getIdentifier();
2284 MCRegister RegNo
= matchRegisterNameHelper(isRVE(), Name
);
2287 return ParseStatus::NoMatch
;
2289 if (!RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(RegNo
))
2290 return ParseStatus::NoMatch
;
2292 if ((RegNo
- RISCV::X0
) & 1)
2293 return TokError("register must be even");
2296 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
2299 const MCRegisterInfo
*RI
= getContext().getRegisterInfo();
2300 unsigned Pair
= RI
->getMatchingSuperReg(
2301 RegNo
, RISCV::sub_gpr_even
,
2302 &RISCVMCRegisterClasses
[RISCV::GPRPairRegClassID
]);
2303 Operands
.push_back(RISCVOperand::createReg(Pair
, S
, E
));
2304 return ParseStatus::Success
;
2307 ParseStatus
RISCVAsmParser::parseFRMArg(OperandVector
&Operands
) {
2308 if (getLexer().isNot(AsmToken::Identifier
))
2310 "operand must be a valid floating point rounding mode mnemonic");
2312 StringRef Str
= getLexer().getTok().getIdentifier();
2313 RISCVFPRndMode::RoundingMode FRM
= RISCVFPRndMode::stringToRoundingMode(Str
);
2315 if (FRM
== RISCVFPRndMode::Invalid
)
2317 "operand must be a valid floating point rounding mode mnemonic");
2319 Operands
.push_back(RISCVOperand::createFRMArg(FRM
, getLoc()));
2320 Lex(); // Eat identifier token.
2321 return ParseStatus::Success
;
2324 ParseStatus
RISCVAsmParser::parseFenceArg(OperandVector
&Operands
) {
2325 const AsmToken
&Tok
= getLexer().getTok();
2327 if (Tok
.is(AsmToken::Integer
)) {
2328 if (Tok
.getIntVal() != 0)
2331 Operands
.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2333 return ParseStatus::Success
;
2336 if (Tok
.is(AsmToken::Identifier
)) {
2337 StringRef Str
= Tok
.getIdentifier();
2339 // Letters must be unique, taken from 'iorw', and in ascending order. This
2340 // holds as long as each individual character is one of 'iorw' and is
2341 // greater than the previous character.
2345 for (char c
: Str
) {
2351 Imm
|= RISCVFenceField::I
;
2354 Imm
|= RISCVFenceField::O
;
2357 Imm
|= RISCVFenceField::R
;
2360 Imm
|= RISCVFenceField::W
;
2374 Operands
.push_back(RISCVOperand::createFenceArg(Imm
, getLoc()));
2376 return ParseStatus::Success
;
2380 return TokError("operand must be formed of letters selected in-order from "
2384 ParseStatus
RISCVAsmParser::parseMemOpBaseReg(OperandVector
&Operands
) {
2385 if (parseToken(AsmToken::LParen
, "expected '('"))
2386 return ParseStatus::Failure
;
2387 Operands
.push_back(RISCVOperand::createToken("(", getLoc()));
2389 if (!parseRegister(Operands
).isSuccess())
2390 return Error(getLoc(), "expected register");
2392 if (parseToken(AsmToken::RParen
, "expected ')'"))
2393 return ParseStatus::Failure
;
2394 Operands
.push_back(RISCVOperand::createToken(")", getLoc()));
2396 return ParseStatus::Success
;
2399 ParseStatus
RISCVAsmParser::parseZeroOffsetMemOp(OperandVector
&Operands
) {
2400 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2401 // as one of their register operands, such as `(a0)`. This just denotes that
2402 // the register (in this case `a0`) contains a memory address.
2404 // Normally, we would be able to parse these by putting the parens into the
2405 // instruction string. However, GNU as also accepts a zero-offset memory
2406 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2407 // with parseImmediate followed by parseMemOpBaseReg, but these instructions
2408 // do not accept an immediate operand, and we do not want to add a "dummy"
2409 // operand that is silently dropped.
2411 // Instead, we use this custom parser. This will: allow (and discard) an
2412 // offset if it is zero; require (and discard) parentheses; and add only the
2413 // parsed register operand to `Operands`.
2415 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2416 // which will only print the register surrounded by parentheses (which GNU as
2417 // also uses as its canonical representation for these operands).
2418 std::unique_ptr
<RISCVOperand
> OptionalImmOp
;
2420 if (getLexer().isNot(AsmToken::LParen
)) {
2421 // Parse an Integer token. We do not accept arbritrary constant expressions
2422 // in the offset field (because they may include parens, which complicates
2425 SMLoc ImmStart
= getLoc();
2426 if (getParser().parseIntToken(ImmVal
,
2427 "expected '(' or optional integer offset"))
2428 return ParseStatus::Failure
;
2430 // Create a RISCVOperand for checking later (so the error messages are
2431 // nicer), but we don't add it to Operands.
2432 SMLoc ImmEnd
= getLoc();
2434 RISCVOperand::createImm(MCConstantExpr::create(ImmVal
, getContext()),
2435 ImmStart
, ImmEnd
, isRV64());
2438 if (parseToken(AsmToken::LParen
,
2439 OptionalImmOp
? "expected '(' after optional integer offset"
2440 : "expected '(' or optional integer offset"))
2441 return ParseStatus::Failure
;
2443 if (!parseRegister(Operands
).isSuccess())
2444 return Error(getLoc(), "expected register");
2446 if (parseToken(AsmToken::RParen
, "expected ')'"))
2447 return ParseStatus::Failure
;
2449 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2450 if (OptionalImmOp
&& !OptionalImmOp
->isImmZero())
2452 OptionalImmOp
->getStartLoc(), "optional integer offset must be 0",
2453 SMRange(OptionalImmOp
->getStartLoc(), OptionalImmOp
->getEndLoc()));
2455 return ParseStatus::Success
;
2458 ParseStatus
RISCVAsmParser::parseRegReg(OperandVector
&Operands
) {
2460 if (getLexer().getKind() != AsmToken::Identifier
)
2461 return ParseStatus::NoMatch
;
2463 StringRef RegName
= getLexer().getTok().getIdentifier();
2464 MCRegister Reg
= matchRegisterNameHelper(isRVE(), RegName
);
2466 return Error(getLoc(), "invalid register");
2469 if (parseToken(AsmToken::LParen
, "expected '(' or invalid operand"))
2470 return ParseStatus::Failure
;
2472 if (getLexer().getKind() != AsmToken::Identifier
)
2473 return Error(getLoc(), "expected register");
2475 StringRef Reg2Name
= getLexer().getTok().getIdentifier();
2476 MCRegister Reg2
= matchRegisterNameHelper(isRVE(), Reg2Name
);
2478 return Error(getLoc(), "invalid register");
2481 if (parseToken(AsmToken::RParen
, "expected ')'"))
2482 return ParseStatus::Failure
;
2484 Operands
.push_back(RISCVOperand::createRegReg(Reg
, Reg2
, getLoc()));
2486 return ParseStatus::Success
;
2489 ParseStatus
RISCVAsmParser::parseReglist(OperandVector
&Operands
) {
2490 // Rlist: {ra [, s0[-sN]]}
2491 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2494 if (parseToken(AsmToken::LCurly
, "register list must start with '{'"))
2495 return ParseStatus::Failure
;
2497 bool IsEABI
= isRVE();
2499 if (getLexer().isNot(AsmToken::Identifier
))
2500 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2502 StringRef RegName
= getLexer().getTok().getIdentifier();
2503 MCRegister RegStart
= matchRegisterNameHelper(IsEABI
, RegName
);
2505 if (RegStart
!= RISCV::X1
)
2506 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2509 // parse case like ,s0
2510 if (parseOptionalToken(AsmToken::Comma
)) {
2511 if (getLexer().isNot(AsmToken::Identifier
))
2512 return Error(getLoc(), "invalid register");
2513 StringRef RegName
= getLexer().getTok().getIdentifier();
2514 RegStart
= matchRegisterNameHelper(IsEABI
, RegName
);
2516 return Error(getLoc(), "invalid register");
2517 if (RegStart
!= RISCV::X8
)
2518 return Error(getLoc(),
2519 "continuous register list must start from 's0' or 'x8'");
2520 getLexer().Lex(); // eat reg
2523 // parse case like -s1
2524 if (parseOptionalToken(AsmToken::Minus
)) {
2525 StringRef EndName
= getLexer().getTok().getIdentifier();
2526 // FIXME: the register mapping and checks of EABI is wrong
2527 RegEnd
= matchRegisterNameHelper(IsEABI
, EndName
);
2529 return Error(getLoc(), "invalid register");
2530 if (IsEABI
&& RegEnd
!= RISCV::X9
)
2531 return Error(getLoc(), "contiguous register list of EABI can only be "
2532 "'s0-s1' or 'x8-x9' pair");
2537 // parse extra part like ', x18[-x20]' for XRegList
2538 if (parseOptionalToken(AsmToken::Comma
)) {
2539 if (RegEnd
!= RISCV::X9
)
2542 "first contiguous registers pair of register list must be 'x8-x9'");
2544 // parse ', x18' for extra part
2545 if (getLexer().isNot(AsmToken::Identifier
))
2546 return Error(getLoc(), "invalid register");
2547 StringRef EndName
= getLexer().getTok().getIdentifier();
2548 if (MatchRegisterName(EndName
) != RISCV::X18
)
2549 return Error(getLoc(),
2550 "second contiguous registers pair of register list "
2551 "must start from 'x18'");
2554 // parse '-x20' for extra part
2555 if (parseOptionalToken(AsmToken::Minus
)) {
2556 if (getLexer().isNot(AsmToken::Identifier
))
2557 return Error(getLoc(), "invalid register");
2558 EndName
= getLexer().getTok().getIdentifier();
2559 if (MatchRegisterName(EndName
) == RISCV::NoRegister
)
2560 return Error(getLoc(), "invalid register");
2563 RegEnd
= MatchRegisterName(EndName
);
2567 if (RegEnd
== RISCV::X26
)
2568 return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2569 "x18-x26} is not supported");
2571 if (parseToken(AsmToken::RCurly
, "register list must end with '}'"))
2572 return ParseStatus::Failure
;
2574 if (RegEnd
== RISCV::NoRegister
)
2577 auto Encode
= RISCVZC::encodeRlist(RegEnd
, IsEABI
);
2579 return Error(S
, "invalid register list");
2580 Operands
.push_back(RISCVOperand::createRlist(Encode
, S
));
2582 return ParseStatus::Success
;
2585 ParseStatus
RISCVAsmParser::parseZcmpSpimm(OperandVector
&Operands
) {
2586 (void)parseOptionalToken(AsmToken::Minus
);
2589 int64_t StackAdjustment
= getLexer().getTok().getIntVal();
2591 unsigned RlistVal
= static_cast<RISCVOperand
*>(Operands
[1].get())->Rlist
.Val
;
2593 bool IsEABI
= isRVE();
2594 if (!RISCVZC::getSpimm(RlistVal
, Spimm
, StackAdjustment
, isRV64(), IsEABI
))
2595 return ParseStatus::NoMatch
;
2596 Operands
.push_back(RISCVOperand::createSpimm(Spimm
<< 4, S
));
2598 return ParseStatus::Success
;
2601 /// Looks at a token type and creates the relevant operand from this
2602 /// information, adding to Operands. If operand was parsed, returns false, else
2604 bool RISCVAsmParser::parseOperand(OperandVector
&Operands
, StringRef Mnemonic
) {
2605 // Check if the current operand has a custom associated parser, if so, try to
2606 // custom parse the operand, or fallback to the general approach.
2607 ParseStatus Result
=
2608 MatchOperandParserImpl(Operands
, Mnemonic
, /*ParseForAllFeatures=*/true);
2609 if (Result
.isSuccess())
2611 if (Result
.isFailure())
2614 // Attempt to parse token as a register.
2615 if (parseRegister(Operands
, true).isSuccess())
2618 // Attempt to parse token as an immediate
2619 if (parseImmediate(Operands
).isSuccess()) {
2620 // Parse memory base register if present
2621 if (getLexer().is(AsmToken::LParen
))
2622 return !parseMemOpBaseReg(Operands
).isSuccess();
2626 // Finally we have exhausted all options and must declare defeat.
2627 Error(getLoc(), "unknown operand");
2631 bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo
&Info
,
2632 StringRef Name
, SMLoc NameLoc
,
2633 OperandVector
&Operands
) {
2634 // Ensure that if the instruction occurs when relaxation is enabled,
2635 // relocations are forced for the file. Ideally this would be done when there
2636 // is enough information to reliably determine if the instruction itself may
2637 // cause relaxations. Unfortunately instruction processing stage occurs in the
2638 // same pass as relocation emission, so it's too late to set a 'sticky bit'
2639 // for the entire file.
2640 if (getSTI().hasFeature(RISCV::FeatureRelax
)) {
2641 auto *Assembler
= getTargetStreamer().getStreamer().getAssemblerPtr();
2642 if (Assembler
!= nullptr) {
2643 RISCVAsmBackend
&MAB
=
2644 static_cast<RISCVAsmBackend
&>(Assembler
->getBackend());
2645 MAB
.setForceRelocs();
2649 // First operand is token for instruction
2650 Operands
.push_back(RISCVOperand::createToken(Name
, NameLoc
));
2652 // If there are no more operands, then finish
2653 if (getLexer().is(AsmToken::EndOfStatement
)) {
2654 getParser().Lex(); // Consume the EndOfStatement.
2658 // Parse first operand
2659 if (parseOperand(Operands
, Name
))
2662 // Parse until end of statement, consuming commas between operands
2663 while (parseOptionalToken(AsmToken::Comma
)) {
2664 // Parse next operand
2665 if (parseOperand(Operands
, Name
))
2669 if (getParser().parseEOL("unexpected token")) {
2670 getParser().eatToEndOfStatement();
2676 bool RISCVAsmParser::classifySymbolRef(const MCExpr
*Expr
,
2677 RISCVMCExpr::VariantKind
&Kind
) {
2678 Kind
= RISCVMCExpr::VK_RISCV_None
;
2680 if (const RISCVMCExpr
*RE
= dyn_cast
<RISCVMCExpr
>(Expr
)) {
2681 Kind
= RE
->getKind();
2682 Expr
= RE
->getSubExpr();
2687 if (Expr
->evaluateAsRelocatable(Res
, nullptr, &Fixup
))
2688 return Res
.getRefKind() == RISCVMCExpr::VK_RISCV_None
;
2692 bool RISCVAsmParser::isSymbolDiff(const MCExpr
*Expr
) {
2695 if (Expr
->evaluateAsRelocatable(Res
, nullptr, &Fixup
)) {
2696 return Res
.getRefKind() == RISCVMCExpr::VK_RISCV_None
&& Res
.getSymA() &&
2702 ParseStatus
RISCVAsmParser::parseDirective(AsmToken DirectiveID
) {
2703 StringRef IDVal
= DirectiveID
.getString();
2705 if (IDVal
== ".option")
2706 return parseDirectiveOption();
2707 if (IDVal
== ".attribute")
2708 return parseDirectiveAttribute();
2709 if (IDVal
== ".insn")
2710 return parseDirectiveInsn(DirectiveID
.getLoc());
2711 if (IDVal
== ".variant_cc")
2712 return parseDirectiveVariantCC();
2714 return ParseStatus::NoMatch
;
2717 bool RISCVAsmParser::resetToArch(StringRef Arch
, SMLoc Loc
, std::string
&Result
,
2718 bool FromOptionDirective
) {
2719 for (auto Feature
: RISCVFeatureKV
)
2720 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature
.Key
))
2721 clearFeatureBits(Feature
.Value
, Feature
.Key
);
2723 auto ParseResult
= llvm::RISCVISAInfo::parseArchString(
2724 Arch
, /*EnableExperimentalExtension=*/true,
2725 /*ExperimentalExtensionVersionCheck=*/true);
2728 raw_string_ostream
OutputErrMsg(Buffer
);
2729 handleAllErrors(ParseResult
.takeError(), [&](llvm::StringError
&ErrMsg
) {
2730 OutputErrMsg
<< "invalid arch name '" << Arch
<< "', "
2731 << ErrMsg
.getMessage();
2734 return Error(Loc
, OutputErrMsg
.str());
2736 auto &ISAInfo
= *ParseResult
;
2738 for (auto Feature
: RISCVFeatureKV
)
2739 if (ISAInfo
->hasExtension(Feature
.Key
))
2740 setFeatureBits(Feature
.Value
, Feature
.Key
);
2742 if (FromOptionDirective
) {
2743 if (ISAInfo
->getXLen() == 32 && isRV64())
2744 return Error(Loc
, "bad arch string switching from rv64 to rv32");
2745 else if (ISAInfo
->getXLen() == 64 && !isRV64())
2746 return Error(Loc
, "bad arch string switching from rv32 to rv64");
2749 if (ISAInfo
->getXLen() == 32)
2750 clearFeatureBits(RISCV::Feature64Bit
, "64bit");
2751 else if (ISAInfo
->getXLen() == 64)
2752 setFeatureBits(RISCV::Feature64Bit
, "64bit");
2754 return Error(Loc
, "bad arch string " + Arch
);
2756 Result
= ISAInfo
->toString();
2760 bool RISCVAsmParser::parseDirectiveOption() {
2761 MCAsmParser
&Parser
= getParser();
2762 // Get the option token.
2763 AsmToken Tok
= Parser
.getTok();
2765 // At the moment only identifiers are supported.
2766 if (parseToken(AsmToken::Identifier
, "expected identifier"))
2769 StringRef Option
= Tok
.getIdentifier();
2771 if (Option
== "push") {
2772 if (Parser
.parseEOL())
2775 getTargetStreamer().emitDirectiveOptionPush();
2780 if (Option
== "pop") {
2781 SMLoc StartLoc
= Parser
.getTok().getLoc();
2782 if (Parser
.parseEOL())
2785 getTargetStreamer().emitDirectiveOptionPop();
2786 if (popFeatureBits())
2787 return Error(StartLoc
, ".option pop with no .option push");
2792 if (Option
== "arch") {
2793 SmallVector
<RISCVOptionArchArg
> Args
;
2795 if (Parser
.parseComma())
2798 RISCVOptionArchArgType Type
;
2799 if (parseOptionalToken(AsmToken::Plus
))
2800 Type
= RISCVOptionArchArgType::Plus
;
2801 else if (parseOptionalToken(AsmToken::Minus
))
2802 Type
= RISCVOptionArchArgType::Minus
;
2803 else if (!Args
.empty())
2804 return Error(Parser
.getTok().getLoc(),
2805 "unexpected token, expected + or -");
2807 Type
= RISCVOptionArchArgType::Full
;
2809 if (Parser
.getTok().isNot(AsmToken::Identifier
))
2810 return Error(Parser
.getTok().getLoc(),
2811 "unexpected token, expected identifier");
2813 StringRef Arch
= Parser
.getTok().getString();
2814 SMLoc Loc
= Parser
.getTok().getLoc();
2817 if (Type
== RISCVOptionArchArgType::Full
) {
2819 if (resetToArch(Arch
, Loc
, Result
, true))
2822 Args
.emplace_back(Type
, Result
);
2826 ArrayRef
<SubtargetFeatureKV
> KVArray(RISCVFeatureKV
);
2827 auto Ext
= llvm::lower_bound(KVArray
, Arch
);
2828 if (Ext
== KVArray
.end() || StringRef(Ext
->Key
) != Arch
||
2829 !RISCVISAInfo::isSupportedExtension(Arch
)) {
2830 if (isDigit(Arch
.back()))
2833 "Extension version number parsing not currently implemented");
2834 return Error(Loc
, "unknown extension feature");
2837 Args
.emplace_back(Type
, Ext
->Key
);
2839 if (Type
== RISCVOptionArchArgType::Plus
) {
2840 FeatureBitset OldFeatureBits
= STI
->getFeatureBits();
2842 setFeatureBits(Ext
->Value
, Ext
->Key
);
2843 auto ParseResult
= RISCVFeatures::parseFeatureBits(isRV64(), STI
->getFeatureBits());
2845 copySTI().setFeatureBits(OldFeatureBits
);
2846 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits
));
2849 raw_string_ostream
OutputErrMsg(Buffer
);
2850 handleAllErrors(ParseResult
.takeError(), [&](llvm::StringError
&ErrMsg
) {
2851 OutputErrMsg
<< ErrMsg
.getMessage();
2854 return Error(Loc
, OutputErrMsg
.str());
2857 assert(Type
== RISCVOptionArchArgType::Minus
);
2858 // It is invalid to disable an extension that there are other enabled
2859 // extensions depend on it.
2860 // TODO: Make use of RISCVISAInfo to handle this
2861 for (auto Feature
: KVArray
) {
2862 if (getSTI().hasFeature(Feature
.Value
) &&
2863 Feature
.Implies
.test(Ext
->Value
))
2865 Twine("Can't disable ") + Ext
->Key
+ " extension, " +
2866 Feature
.Key
+ " extension requires " + Ext
->Key
+
2867 " extension be enabled");
2870 clearFeatureBits(Ext
->Value
, Ext
->Key
);
2872 } while (Parser
.getTok().isNot(AsmToken::EndOfStatement
));
2874 if (Parser
.parseEOL())
2877 getTargetStreamer().emitDirectiveOptionArch(Args
);
2881 if (Option
== "rvc") {
2882 if (Parser
.parseEOL())
2885 getTargetStreamer().emitDirectiveOptionRVC();
2886 setFeatureBits(RISCV::FeatureStdExtC
, "c");
2890 if (Option
== "norvc") {
2891 if (Parser
.parseEOL())
2894 getTargetStreamer().emitDirectiveOptionNoRVC();
2895 clearFeatureBits(RISCV::FeatureStdExtC
, "c");
2896 clearFeatureBits(RISCV::FeatureStdExtZca
, "+zca");
2900 if (Option
== "pic") {
2901 if (Parser
.parseEOL())
2904 getTargetStreamer().emitDirectiveOptionPIC();
2905 ParserOptions
.IsPicEnabled
= true;
2909 if (Option
== "nopic") {
2910 if (Parser
.parseEOL())
2913 getTargetStreamer().emitDirectiveOptionNoPIC();
2914 ParserOptions
.IsPicEnabled
= false;
2918 if (Option
== "relax") {
2919 if (Parser
.parseEOL())
2922 getTargetStreamer().emitDirectiveOptionRelax();
2923 setFeatureBits(RISCV::FeatureRelax
, "relax");
2927 if (Option
== "norelax") {
2928 if (Parser
.parseEOL())
2931 getTargetStreamer().emitDirectiveOptionNoRelax();
2932 clearFeatureBits(RISCV::FeatureRelax
, "relax");
2937 Warning(Parser
.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
2938 "'rvc', 'norvc', 'arch', 'relax' or "
2940 Parser
.eatToEndOfStatement();
2944 /// parseDirectiveAttribute
2945 /// ::= .attribute expression ',' ( expression | "string" )
2946 /// ::= .attribute identifier ',' ( expression | "string" )
2947 bool RISCVAsmParser::parseDirectiveAttribute() {
2948 MCAsmParser
&Parser
= getParser();
2951 TagLoc
= Parser
.getTok().getLoc();
2952 if (Parser
.getTok().is(AsmToken::Identifier
)) {
2953 StringRef Name
= Parser
.getTok().getIdentifier();
2954 std::optional
<unsigned> Ret
=
2955 ELFAttrs::attrTypeFromString(Name
, RISCVAttrs::getRISCVAttributeTags());
2957 return Error(TagLoc
, "attribute name not recognised: " + Name
);
2961 const MCExpr
*AttrExpr
;
2963 TagLoc
= Parser
.getTok().getLoc();
2964 if (Parser
.parseExpression(AttrExpr
))
2967 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(AttrExpr
);
2968 if (check(!CE
, TagLoc
, "expected numeric constant"))
2971 Tag
= CE
->getValue();
2974 if (Parser
.parseComma())
2977 StringRef StringValue
;
2978 int64_t IntegerValue
= 0;
2979 bool IsIntegerValue
= true;
2981 // RISC-V attributes have a string value if the tag number is odd
2982 // and an integer value if the tag number is even.
2984 IsIntegerValue
= false;
2986 SMLoc ValueExprLoc
= Parser
.getTok().getLoc();
2987 if (IsIntegerValue
) {
2988 const MCExpr
*ValueExpr
;
2989 if (Parser
.parseExpression(ValueExpr
))
2992 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(ValueExpr
);
2994 return Error(ValueExprLoc
, "expected numeric constant");
2995 IntegerValue
= CE
->getValue();
2997 if (Parser
.getTok().isNot(AsmToken::String
))
2998 return Error(Parser
.getTok().getLoc(), "expected string constant");
3000 StringValue
= Parser
.getTok().getStringContents();
3004 if (Parser
.parseEOL())
3008 getTargetStreamer().emitAttribute(Tag
, IntegerValue
);
3009 else if (Tag
!= RISCVAttrs::ARCH
)
3010 getTargetStreamer().emitTextAttribute(Tag
, StringValue
);
3013 if (resetToArch(StringValue
, ValueExprLoc
, Result
, false))
3016 // Then emit the arch string.
3017 getTargetStreamer().emitTextAttribute(Tag
, Result
);
3023 bool isValidInsnFormat(StringRef Format
, bool AllowC
) {
3024 return StringSwitch
<bool>(Format
)
3025 .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
3026 .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC
)
3030 /// parseDirectiveInsn
3031 /// ::= .insn [ format encoding, (operands (, operands)*) ]
3032 bool RISCVAsmParser::parseDirectiveInsn(SMLoc L
) {
3033 MCAsmParser
&Parser
= getParser();
3035 // Expect instruction format as identifier.
3037 SMLoc ErrorLoc
= Parser
.getTok().getLoc();
3038 if (Parser
.parseIdentifier(Format
))
3039 return Error(ErrorLoc
, "expected instruction format");
3041 bool AllowC
= getSTI().hasFeature(RISCV::FeatureStdExtC
) ||
3042 getSTI().hasFeature(RISCV::FeatureStdExtZca
);
3043 if (!isValidInsnFormat(Format
, AllowC
))
3044 return Error(ErrorLoc
, "invalid instruction format");
3046 std::string FormatName
= (".insn_" + Format
).str();
3048 ParseInstructionInfo Info
;
3049 SmallVector
<std::unique_ptr
<MCParsedAsmOperand
>, 8> Operands
;
3051 if (ParseInstruction(Info
, FormatName
, L
, Operands
))
3056 return MatchAndEmitInstruction(L
, Opcode
, Operands
, Parser
.getStreamer(),
3058 /*MatchingInlineAsm=*/false);
3061 /// parseDirectiveVariantCC
3062 /// ::= .variant_cc symbol
3063 bool RISCVAsmParser::parseDirectiveVariantCC() {
3065 if (getParser().parseIdentifier(Name
))
3066 return TokError("expected symbol name");
3069 getTargetStreamer().emitDirectiveVariantCC(
3070 *getContext().getOrCreateSymbol(Name
));
3074 void RISCVAsmParser::emitToStreamer(MCStreamer
&S
, const MCInst
&Inst
) {
3076 bool Res
= RISCVRVC::compress(CInst
, Inst
, getSTI());
3078 ++RISCVNumInstrsCompressed
;
3079 S
.emitInstruction((Res
? CInst
: Inst
), getSTI());
3082 void RISCVAsmParser::emitLoadImm(MCRegister DestReg
, int64_t Value
,
3084 RISCVMatInt::InstSeq Seq
= RISCVMatInt::generateInstSeq(Value
, getSTI());
3086 MCRegister SrcReg
= RISCV::X0
;
3087 for (const RISCVMatInt::Inst
&Inst
: Seq
) {
3088 switch (Inst
.getOpndKind()) {
3089 case RISCVMatInt::Imm
:
3091 MCInstBuilder(Inst
.getOpcode()).addReg(DestReg
).addImm(Inst
.getImm()));
3093 case RISCVMatInt::RegX0
:
3095 Out
, MCInstBuilder(Inst
.getOpcode()).addReg(DestReg
).addReg(SrcReg
).addReg(
3098 case RISCVMatInt::RegReg
:
3100 Out
, MCInstBuilder(Inst
.getOpcode()).addReg(DestReg
).addReg(SrcReg
).addReg(
3103 case RISCVMatInt::RegImm
:
3105 Out
, MCInstBuilder(Inst
.getOpcode()).addReg(DestReg
).addReg(SrcReg
).addImm(
3110 // Only the first instruction has X0 as its source.
3115 void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg
, MCOperand TmpReg
,
3116 const MCExpr
*Symbol
,
3117 RISCVMCExpr::VariantKind VKHi
,
3118 unsigned SecondOpcode
, SMLoc IDLoc
,
3120 // A pair of instructions for PC-relative addressing; expands to
3121 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3122 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3123 MCContext
&Ctx
= getContext();
3125 MCSymbol
*TmpLabel
= Ctx
.createNamedTempSymbol("pcrel_hi");
3126 Out
.emitLabel(TmpLabel
);
3128 const RISCVMCExpr
*SymbolHi
= RISCVMCExpr::create(Symbol
, VKHi
, Ctx
);
3130 Out
, MCInstBuilder(RISCV::AUIPC
).addOperand(TmpReg
).addExpr(SymbolHi
));
3132 const MCExpr
*RefToLinkTmpLabel
=
3133 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel
, Ctx
),
3134 RISCVMCExpr::VK_RISCV_PCREL_LO
, Ctx
);
3136 emitToStreamer(Out
, MCInstBuilder(SecondOpcode
)
3137 .addOperand(DestReg
)
3139 .addExpr(RefToLinkTmpLabel
));
3142 void RISCVAsmParser::emitLoadLocalAddress(MCInst
&Inst
, SMLoc IDLoc
,
3144 // The load local address pseudo-instruction "lla" is used in PC-relative
3145 // addressing of local symbols:
3146 // lla rdest, symbol
3148 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3149 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3150 MCOperand DestReg
= Inst
.getOperand(0);
3151 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3152 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_PCREL_HI
,
3153 RISCV::ADDI
, IDLoc
, Out
);
3156 void RISCVAsmParser::emitLoadGlobalAddress(MCInst
&Inst
, SMLoc IDLoc
,
3158 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3159 // addressing of global symbols:
3160 // lga rdest, symbol
3162 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3163 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3164 MCOperand DestReg
= Inst
.getOperand(0);
3165 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3166 unsigned SecondOpcode
= isRV64() ? RISCV::LD
: RISCV::LW
;
3167 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_GOT_HI
,
3168 SecondOpcode
, IDLoc
, Out
);
3171 void RISCVAsmParser::emitLoadAddress(MCInst
&Inst
, SMLoc IDLoc
,
3173 // The load address pseudo-instruction "la" is used in PC-relative and
3174 // GOT-indirect addressing of global symbols:
3176 // is an alias for either (for non-PIC)
3177 // lla rdest, symbol
3179 // lga rdest, symbol
3180 if (ParserOptions
.IsPicEnabled
)
3181 emitLoadGlobalAddress(Inst
, IDLoc
, Out
);
3183 emitLoadLocalAddress(Inst
, IDLoc
, Out
);
3186 void RISCVAsmParser::emitLoadTLSIEAddress(MCInst
&Inst
, SMLoc IDLoc
,
3188 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3189 // initial-exec TLS model addressing of global symbols:
3190 // la.tls.ie rdest, symbol
3192 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3193 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3194 MCOperand DestReg
= Inst
.getOperand(0);
3195 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3196 unsigned SecondOpcode
= isRV64() ? RISCV::LD
: RISCV::LW
;
3197 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_TLS_GOT_HI
,
3198 SecondOpcode
, IDLoc
, Out
);
3201 void RISCVAsmParser::emitLoadTLSGDAddress(MCInst
&Inst
, SMLoc IDLoc
,
3203 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3204 // global-dynamic TLS model addressing of global symbols:
3205 // la.tls.gd rdest, symbol
3207 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3208 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3209 MCOperand DestReg
= Inst
.getOperand(0);
3210 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3211 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_TLS_GD_HI
,
3212 RISCV::ADDI
, IDLoc
, Out
);
3215 void RISCVAsmParser::emitLoadStoreSymbol(MCInst
&Inst
, unsigned Opcode
,
3216 SMLoc IDLoc
, MCStreamer
&Out
,
3218 // The load/store pseudo-instruction does a pc-relative load with
3221 // The expansion looks like this
3223 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3224 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3225 unsigned DestRegOpIdx
= HasTmpReg
? 1 : 0;
3226 MCOperand DestReg
= Inst
.getOperand(DestRegOpIdx
);
3227 unsigned SymbolOpIdx
= HasTmpReg
? 2 : 1;
3228 MCOperand TmpReg
= Inst
.getOperand(0);
3229 const MCExpr
*Symbol
= Inst
.getOperand(SymbolOpIdx
).getExpr();
3230 emitAuipcInstPair(DestReg
, TmpReg
, Symbol
, RISCVMCExpr::VK_RISCV_PCREL_HI
,
3231 Opcode
, IDLoc
, Out
);
3234 void RISCVAsmParser::emitPseudoExtend(MCInst
&Inst
, bool SignExtend
,
3235 int64_t Width
, SMLoc IDLoc
,
3237 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3238 // amounts dependent on the XLEN.
3240 // The expansion looks like this
3242 // SLLI rd, rs, XLEN - Width
3243 // SR[A|R]I rd, rd, XLEN - Width
3244 MCOperand DestReg
= Inst
.getOperand(0);
3245 MCOperand SourceReg
= Inst
.getOperand(1);
3247 unsigned SecondOpcode
= SignExtend
? RISCV::SRAI
: RISCV::SRLI
;
3248 int64_t ShAmt
= (isRV64() ? 64 : 32) - Width
;
3250 assert(ShAmt
> 0 && "Shift amount must be non-zero.");
3252 emitToStreamer(Out
, MCInstBuilder(RISCV::SLLI
)
3253 .addOperand(DestReg
)
3254 .addOperand(SourceReg
)
3257 emitToStreamer(Out
, MCInstBuilder(SecondOpcode
)
3258 .addOperand(DestReg
)
3259 .addOperand(DestReg
)
3263 void RISCVAsmParser::emitVMSGE(MCInst
&Inst
, unsigned Opcode
, SMLoc IDLoc
,
3265 if (Inst
.getNumOperands() == 3) {
3268 // pseudoinstruction: vmsge{u}.vx vd, va, x
3269 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3270 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3271 .addOperand(Inst
.getOperand(0))
3272 .addOperand(Inst
.getOperand(1))
3273 .addOperand(Inst
.getOperand(2))
3274 .addReg(RISCV::NoRegister
));
3275 emitToStreamer(Out
, MCInstBuilder(RISCV::VMNAND_MM
)
3276 .addOperand(Inst
.getOperand(0))
3277 .addOperand(Inst
.getOperand(0))
3278 .addOperand(Inst
.getOperand(0)));
3279 } else if (Inst
.getNumOperands() == 4) {
3280 // masked va >= x, vd != v0
3282 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3283 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3284 assert(Inst
.getOperand(0).getReg() != RISCV::V0
&&
3285 "The destination register should not be V0.");
3286 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3287 .addOperand(Inst
.getOperand(0))
3288 .addOperand(Inst
.getOperand(1))
3289 .addOperand(Inst
.getOperand(2))
3290 .addOperand(Inst
.getOperand(3)));
3291 emitToStreamer(Out
, MCInstBuilder(RISCV::VMXOR_MM
)
3292 .addOperand(Inst
.getOperand(0))
3293 .addOperand(Inst
.getOperand(0))
3294 .addReg(RISCV::V0
));
3295 } else if (Inst
.getNumOperands() == 5 &&
3296 Inst
.getOperand(0).getReg() == RISCV::V0
) {
3297 // masked va >= x, vd == v0
3299 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3300 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3301 assert(Inst
.getOperand(0).getReg() == RISCV::V0
&&
3302 "The destination register should be V0.");
3303 assert(Inst
.getOperand(1).getReg() != RISCV::V0
&&
3304 "The temporary vector register should not be V0.");
3305 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3306 .addOperand(Inst
.getOperand(1))
3307 .addOperand(Inst
.getOperand(2))
3308 .addOperand(Inst
.getOperand(3))
3309 .addReg(RISCV::NoRegister
));
3310 emitToStreamer(Out
, MCInstBuilder(RISCV::VMANDN_MM
)
3311 .addOperand(Inst
.getOperand(0))
3312 .addOperand(Inst
.getOperand(0))
3313 .addOperand(Inst
.getOperand(1)));
3314 } else if (Inst
.getNumOperands() == 5) {
3315 // masked va >= x, any vd
3317 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3318 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3319 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3320 assert(Inst
.getOperand(1).getReg() != RISCV::V0
&&
3321 "The temporary vector register should not be V0.");
3322 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3323 .addOperand(Inst
.getOperand(1))
3324 .addOperand(Inst
.getOperand(2))
3325 .addOperand(Inst
.getOperand(3))
3326 .addReg(RISCV::NoRegister
));
3327 emitToStreamer(Out
, MCInstBuilder(RISCV::VMANDN_MM
)
3328 .addOperand(Inst
.getOperand(1))
3330 .addOperand(Inst
.getOperand(1)));
3331 emitToStreamer(Out
, MCInstBuilder(RISCV::VMANDN_MM
)
3332 .addOperand(Inst
.getOperand(0))
3333 .addOperand(Inst
.getOperand(0))
3334 .addReg(RISCV::V0
));
3335 emitToStreamer(Out
, MCInstBuilder(RISCV::VMOR_MM
)
3336 .addOperand(Inst
.getOperand(0))
3337 .addOperand(Inst
.getOperand(1))
3338 .addOperand(Inst
.getOperand(0)));
3342 bool RISCVAsmParser::checkPseudoAddTPRel(MCInst
&Inst
,
3343 OperandVector
&Operands
) {
3344 assert(Inst
.getOpcode() == RISCV::PseudoAddTPRel
&& "Invalid instruction");
3345 assert(Inst
.getOperand(2).isReg() && "Unexpected second operand kind");
3346 if (Inst
.getOperand(2).getReg() != RISCV::X4
) {
3347 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[3]).getStartLoc();
3348 return Error(ErrorLoc
, "the second input operand must be tp/x4 when using "
3349 "%tprel_add modifier");
3355 bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst
&Inst
,
3356 OperandVector
&Operands
) {
3357 assert(Inst
.getOpcode() == RISCV::PseudoTLSDESCCall
&& "Invalid instruction");
3358 assert(Inst
.getOperand(0).isReg() && "Unexpected operand kind");
3359 if (Inst
.getOperand(0).getReg() != RISCV::X5
) {
3360 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[3]).getStartLoc();
3361 return Error(ErrorLoc
, "the output operand must be t0/x5 when using "
3362 "%tlsdesc_call modifier");
3368 std::unique_ptr
<RISCVOperand
> RISCVAsmParser::defaultMaskRegOp() const {
3369 return RISCVOperand::createReg(RISCV::NoRegister
, llvm::SMLoc(),
3373 std::unique_ptr
<RISCVOperand
> RISCVAsmParser::defaultFRMArgOp() const {
3374 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN
,
3378 std::unique_ptr
<RISCVOperand
> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3379 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE
,
3383 bool RISCVAsmParser::validateInstruction(MCInst
&Inst
,
3384 OperandVector
&Operands
) {
3385 unsigned Opcode
= Inst
.getOpcode();
3387 if (Opcode
== RISCV::PseudoVMSGEU_VX_M_T
||
3388 Opcode
== RISCV::PseudoVMSGE_VX_M_T
) {
3389 unsigned DestReg
= Inst
.getOperand(0).getReg();
3390 unsigned TempReg
= Inst
.getOperand(1).getReg();
3391 if (DestReg
== TempReg
) {
3392 SMLoc Loc
= Operands
.back()->getStartLoc();
3393 return Error(Loc
, "The temporary vector register cannot be the same as "
3394 "the destination register.");
3398 if (Opcode
== RISCV::TH_LDD
|| Opcode
== RISCV::TH_LWUD
||
3399 Opcode
== RISCV::TH_LWD
) {
3400 unsigned Rd1
= Inst
.getOperand(0).getReg();
3401 unsigned Rd2
= Inst
.getOperand(1).getReg();
3402 unsigned Rs1
= Inst
.getOperand(2).getReg();
3403 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3404 if (Rs1
== Rd1
&& Rs1
== Rd2
) {
3405 SMLoc Loc
= Operands
[1]->getStartLoc();
3406 return Error(Loc
, "The source register and destination registers "
3407 "cannot be equal.");
3411 if (Opcode
== RISCV::CM_MVSA01
) {
3412 unsigned Rd1
= Inst
.getOperand(0).getReg();
3413 unsigned Rd2
= Inst
.getOperand(1).getReg();
3415 SMLoc Loc
= Operands
[1]->getStartLoc();
3416 return Error(Loc
, "'rs1' and 'rs2' must be different.");
3420 bool IsTHeadMemPair32
= (Opcode
== RISCV::TH_LWD
||
3421 Opcode
== RISCV::TH_LWUD
|| Opcode
== RISCV::TH_SWD
);
3422 bool IsTHeadMemPair64
= (Opcode
== RISCV::TH_LDD
|| Opcode
== RISCV::TH_SDD
);
3423 // The last operand of XTHeadMemPair instructions must be constant 3 or 4
3424 // depending on the data width.
3425 if (IsTHeadMemPair32
&& Inst
.getOperand(4).getImm() != 3) {
3426 SMLoc Loc
= Operands
.back()->getStartLoc();
3427 return Error(Loc
, "Operand must be constant 3.");
3428 } else if (IsTHeadMemPair64
&& Inst
.getOperand(4).getImm() != 4) {
3429 SMLoc Loc
= Operands
.back()->getStartLoc();
3430 return Error(Loc
, "Operand must be constant 4.");
3433 const MCInstrDesc
&MCID
= MII
.get(Opcode
);
3434 if (!(MCID
.TSFlags
& RISCVII::ConstraintMask
))
3437 if (Opcode
== RISCV::VC_V_XVW
|| Opcode
== RISCV::VC_V_IVW
||
3438 Opcode
== RISCV::VC_V_FVW
|| Opcode
== RISCV::VC_V_VVW
) {
3439 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
3440 unsigned VCIXDst
= Inst
.getOperand(0).getReg();
3441 SMLoc VCIXDstLoc
= Operands
[2]->getStartLoc();
3442 if (MCID
.TSFlags
& RISCVII::VS1Constraint
) {
3443 unsigned VCIXRs1
= Inst
.getOperand(Inst
.getNumOperands() - 1).getReg();
3444 if (VCIXDst
== VCIXRs1
)
3445 return Error(VCIXDstLoc
, "The destination vector register group cannot"
3446 " overlap the source vector register group.");
3448 if (MCID
.TSFlags
& RISCVII::VS2Constraint
) {
3449 unsigned VCIXRs2
= Inst
.getOperand(Inst
.getNumOperands() - 2).getReg();
3450 if (VCIXDst
== VCIXRs2
)
3451 return Error(VCIXDstLoc
, "The destination vector register group cannot"
3452 " overlap the source vector register group.");
3457 unsigned DestReg
= Inst
.getOperand(0).getReg();
3458 unsigned Offset
= 0;
3459 int TiedOp
= MCID
.getOperandConstraint(1, MCOI::TIED_TO
);
3463 // Operands[1] will be the first operand, DestReg.
3464 SMLoc Loc
= Operands
[1]->getStartLoc();
3465 if (MCID
.TSFlags
& RISCVII::VS2Constraint
) {
3466 unsigned CheckReg
= Inst
.getOperand(Offset
+ 1).getReg();
3467 if (DestReg
== CheckReg
)
3468 return Error(Loc
, "The destination vector register group cannot overlap"
3469 " the source vector register group.");
3471 if ((MCID
.TSFlags
& RISCVII::VS1Constraint
) && Inst
.getOperand(Offset
+ 2).isReg()) {
3472 unsigned CheckReg
= Inst
.getOperand(Offset
+ 2).getReg();
3473 if (DestReg
== CheckReg
)
3474 return Error(Loc
, "The destination vector register group cannot overlap"
3475 " the source vector register group.");
3477 if ((MCID
.TSFlags
& RISCVII::VMConstraint
) && (DestReg
== RISCV::V0
)) {
3478 // vadc, vsbc are special cases. These instructions have no mask register.
3479 // The destination register could not be V0.
3480 if (Opcode
== RISCV::VADC_VVM
|| Opcode
== RISCV::VADC_VXM
||
3481 Opcode
== RISCV::VADC_VIM
|| Opcode
== RISCV::VSBC_VVM
||
3482 Opcode
== RISCV::VSBC_VXM
|| Opcode
== RISCV::VFMERGE_VFM
||
3483 Opcode
== RISCV::VMERGE_VIM
|| Opcode
== RISCV::VMERGE_VVM
||
3484 Opcode
== RISCV::VMERGE_VXM
)
3485 return Error(Loc
, "The destination vector register group cannot be V0.");
3487 // Regardless masked or unmasked version, the number of operands is the
3488 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3489 // actually. We need to check the last operand to ensure whether it is
3491 unsigned CheckReg
= Inst
.getOperand(Inst
.getNumOperands() - 1).getReg();
3492 assert((CheckReg
== RISCV::V0
|| CheckReg
== RISCV::NoRegister
) &&
3493 "Unexpected register for mask operand");
3495 if (DestReg
== CheckReg
)
3496 return Error(Loc
, "The destination vector register group cannot overlap"
3497 " the mask register.");
3502 bool RISCVAsmParser::processInstruction(MCInst
&Inst
, SMLoc IDLoc
,
3503 OperandVector
&Operands
,
3507 switch (Inst
.getOpcode()) {
3510 case RISCV::PseudoLLAImm
:
3511 case RISCV::PseudoLAImm
:
3512 case RISCV::PseudoLI
: {
3513 MCRegister Reg
= Inst
.getOperand(0).getReg();
3514 const MCOperand
&Op1
= Inst
.getOperand(1);
3516 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
3517 // Just convert to an addi. This allows compatibility with gas.
3518 emitToStreamer(Out
, MCInstBuilder(RISCV::ADDI
)
3521 .addExpr(Op1
.getExpr()));
3524 int64_t Imm
= Inst
.getOperand(1).getImm();
3525 // On RV32 the immediate here can either be a signed or an unsigned
3526 // 32-bit number. Sign extension has to be performed to ensure that Imm
3527 // represents the expected signed 64-bit number.
3529 Imm
= SignExtend64
<32>(Imm
);
3530 emitLoadImm(Reg
, Imm
, Out
);
3533 case RISCV::PseudoLLA
:
3534 emitLoadLocalAddress(Inst
, IDLoc
, Out
);
3536 case RISCV::PseudoLGA
:
3537 emitLoadGlobalAddress(Inst
, IDLoc
, Out
);
3539 case RISCV::PseudoLA
:
3540 emitLoadAddress(Inst
, IDLoc
, Out
);
3542 case RISCV::PseudoLA_TLS_IE
:
3543 emitLoadTLSIEAddress(Inst
, IDLoc
, Out
);
3545 case RISCV::PseudoLA_TLS_GD
:
3546 emitLoadTLSGDAddress(Inst
, IDLoc
, Out
);
3548 case RISCV::PseudoLB
:
3549 emitLoadStoreSymbol(Inst
, RISCV::LB
, IDLoc
, Out
, /*HasTmpReg=*/false);
3551 case RISCV::PseudoLBU
:
3552 emitLoadStoreSymbol(Inst
, RISCV::LBU
, IDLoc
, Out
, /*HasTmpReg=*/false);
3554 case RISCV::PseudoLH
:
3555 emitLoadStoreSymbol(Inst
, RISCV::LH
, IDLoc
, Out
, /*HasTmpReg=*/false);
3557 case RISCV::PseudoLHU
:
3558 emitLoadStoreSymbol(Inst
, RISCV::LHU
, IDLoc
, Out
, /*HasTmpReg=*/false);
3560 case RISCV::PseudoLW
:
3561 emitLoadStoreSymbol(Inst
, RISCV::LW
, IDLoc
, Out
, /*HasTmpReg=*/false);
3563 case RISCV::PseudoLWU
:
3564 emitLoadStoreSymbol(Inst
, RISCV::LWU
, IDLoc
, Out
, /*HasTmpReg=*/false);
3566 case RISCV::PseudoLD
:
3567 emitLoadStoreSymbol(Inst
, RISCV::LD
, IDLoc
, Out
, /*HasTmpReg=*/false);
3569 case RISCV::PseudoFLH
:
3570 emitLoadStoreSymbol(Inst
, RISCV::FLH
, IDLoc
, Out
, /*HasTmpReg=*/true);
3572 case RISCV::PseudoFLW
:
3573 emitLoadStoreSymbol(Inst
, RISCV::FLW
, IDLoc
, Out
, /*HasTmpReg=*/true);
3575 case RISCV::PseudoFLD
:
3576 emitLoadStoreSymbol(Inst
, RISCV::FLD
, IDLoc
, Out
, /*HasTmpReg=*/true);
3578 case RISCV::PseudoSB
:
3579 emitLoadStoreSymbol(Inst
, RISCV::SB
, IDLoc
, Out
, /*HasTmpReg=*/true);
3581 case RISCV::PseudoSH
:
3582 emitLoadStoreSymbol(Inst
, RISCV::SH
, IDLoc
, Out
, /*HasTmpReg=*/true);
3584 case RISCV::PseudoSW
:
3585 emitLoadStoreSymbol(Inst
, RISCV::SW
, IDLoc
, Out
, /*HasTmpReg=*/true);
3587 case RISCV::PseudoSD
:
3588 emitLoadStoreSymbol(Inst
, RISCV::SD
, IDLoc
, Out
, /*HasTmpReg=*/true);
3590 case RISCV::PseudoFSH
:
3591 emitLoadStoreSymbol(Inst
, RISCV::FSH
, IDLoc
, Out
, /*HasTmpReg=*/true);
3593 case RISCV::PseudoFSW
:
3594 emitLoadStoreSymbol(Inst
, RISCV::FSW
, IDLoc
, Out
, /*HasTmpReg=*/true);
3596 case RISCV::PseudoFSD
:
3597 emitLoadStoreSymbol(Inst
, RISCV::FSD
, IDLoc
, Out
, /*HasTmpReg=*/true);
3599 case RISCV::PseudoAddTPRel
:
3600 if (checkPseudoAddTPRel(Inst
, Operands
))
3603 case RISCV::PseudoTLSDESCCall
:
3604 if (checkPseudoTLSDESCCall(Inst
, Operands
))
3607 case RISCV::PseudoSEXT_B
:
3608 emitPseudoExtend(Inst
, /*SignExtend=*/true, /*Width=*/8, IDLoc
, Out
);
3610 case RISCV::PseudoSEXT_H
:
3611 emitPseudoExtend(Inst
, /*SignExtend=*/true, /*Width=*/16, IDLoc
, Out
);
3613 case RISCV::PseudoZEXT_H
:
3614 emitPseudoExtend(Inst
, /*SignExtend=*/false, /*Width=*/16, IDLoc
, Out
);
3616 case RISCV::PseudoZEXT_W
:
3617 emitPseudoExtend(Inst
, /*SignExtend=*/false, /*Width=*/32, IDLoc
, Out
);
3619 case RISCV::PseudoVMSGEU_VX
:
3620 case RISCV::PseudoVMSGEU_VX_M
:
3621 case RISCV::PseudoVMSGEU_VX_M_T
:
3622 emitVMSGE(Inst
, RISCV::VMSLTU_VX
, IDLoc
, Out
);
3624 case RISCV::PseudoVMSGE_VX
:
3625 case RISCV::PseudoVMSGE_VX_M
:
3626 case RISCV::PseudoVMSGE_VX_M_T
:
3627 emitVMSGE(Inst
, RISCV::VMSLT_VX
, IDLoc
, Out
);
3629 case RISCV::PseudoVMSGE_VI
:
3630 case RISCV::PseudoVMSLT_VI
: {
3631 // These instructions are signed and so is immediate so we can subtract one
3632 // and change the opcode.
3633 int64_t Imm
= Inst
.getOperand(2).getImm();
3634 unsigned Opc
= Inst
.getOpcode() == RISCV::PseudoVMSGE_VI
? RISCV::VMSGT_VI
3636 emitToStreamer(Out
, MCInstBuilder(Opc
)
3637 .addOperand(Inst
.getOperand(0))
3638 .addOperand(Inst
.getOperand(1))
3640 .addOperand(Inst
.getOperand(3)));
3643 case RISCV::PseudoVMSGEU_VI
:
3644 case RISCV::PseudoVMSLTU_VI
: {
3645 int64_t Imm
= Inst
.getOperand(2).getImm();
3646 // Unsigned comparisons are tricky because the immediate is signed. If the
3647 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3648 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3649 // vmsne v0, v1, v1 which is always false.
3651 unsigned Opc
= Inst
.getOpcode() == RISCV::PseudoVMSGEU_VI
3654 emitToStreamer(Out
, MCInstBuilder(Opc
)
3655 .addOperand(Inst
.getOperand(0))
3656 .addOperand(Inst
.getOperand(1))
3657 .addOperand(Inst
.getOperand(1))
3658 .addOperand(Inst
.getOperand(3)));
3660 // Other immediate values can subtract one like signed.
3661 unsigned Opc
= Inst
.getOpcode() == RISCV::PseudoVMSGEU_VI
3664 emitToStreamer(Out
, MCInstBuilder(Opc
)
3665 .addOperand(Inst
.getOperand(0))
3666 .addOperand(Inst
.getOperand(1))
3668 .addOperand(Inst
.getOperand(3)));
3675 emitToStreamer(Out
, Inst
);
3679 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeRISCVAsmParser() {
3680 RegisterMCAsmParser
<RISCVAsmParser
> X(getTheRISCV32Target());
3681 RegisterMCAsmParser
<RISCVAsmParser
> Y(getTheRISCV64Target());