xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===-- RISCVAsmParser.cpp - Parse RISC-V assembly to MCInst instructions -===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MCTargetDesc/RISCVAsmBackend.h"
10e8d8bef9SDimitry Andric #include "MCTargetDesc/RISCVBaseInfo.h"
11e8d8bef9SDimitry Andric #include "MCTargetDesc/RISCVInstPrinter.h"
120b57cec5SDimitry Andric #include "MCTargetDesc/RISCVMCExpr.h"
130b57cec5SDimitry Andric #include "MCTargetDesc/RISCVMCTargetDesc.h"
14e8d8bef9SDimitry Andric #include "MCTargetDesc/RISCVMatInt.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/RISCVTargetStreamer.h"
160b57cec5SDimitry Andric #include "TargetInfo/RISCVTargetInfo.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
185ffd83dbSDimitry Andric #include "llvm/ADT/SmallBitVector.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
20480093f4SDimitry Andric #include "llvm/ADT/Statistic.h"
2106c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
2781ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
340b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
35e8d8bef9SDimitry Andric #include "llvm/MC/MCValue.h"
36349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
370b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
3806c3fb27SDimitry Andric #include "llvm/Support/CommandLine.h"
390b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
405ffd83dbSDimitry Andric #include "llvm/Support/RISCVAttributes.h"
41*0fca6ea1SDimitry Andric #include "llvm/TargetParser/RISCVISAInfo.h"
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric #include <limits>
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric using namespace llvm;
460b57cec5SDimitry Andric 
47480093f4SDimitry Andric #define DEBUG_TYPE "riscv-asm-parser"
48480093f4SDimitry Andric 
49480093f4SDimitry Andric STATISTIC(RISCVNumInstrsCompressed,
50480093f4SDimitry Andric           "Number of RISC-V Compressed instructions emitted");
51480093f4SDimitry Andric 
5206c3fb27SDimitry Andric static cl::opt<bool> AddBuildAttributes("riscv-add-build-attributes",
5306c3fb27SDimitry Andric                                         cl::init(false));
5406c3fb27SDimitry Andric 
55349cc55cSDimitry Andric namespace llvm {
56349cc55cSDimitry Andric extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
57349cc55cSDimitry Andric } // namespace llvm
58349cc55cSDimitry Andric 
590b57cec5SDimitry Andric namespace {
600b57cec5SDimitry Andric struct RISCVOperand;
610b57cec5SDimitry Andric 
625ffd83dbSDimitry Andric struct ParserOptionsSet {
635ffd83dbSDimitry Andric   bool IsPicEnabled;
645ffd83dbSDimitry Andric };
655ffd83dbSDimitry Andric 
660b57cec5SDimitry Andric class RISCVAsmParser : public MCTargetAsmParser {
6706c3fb27SDimitry Andric   // This tracks the parsing of the 4 operands that make up the vtype portion
6806c3fb27SDimitry Andric   // of vset(i)vli instructions which are separated by commas. The state names
6906c3fb27SDimitry Andric   // represent the next expected operand with Done meaning no other operands are
7006c3fb27SDimitry Andric   // expected.
7106c3fb27SDimitry Andric   enum VTypeState {
7206c3fb27SDimitry Andric     VTypeState_SEW,
7306c3fb27SDimitry Andric     VTypeState_LMUL,
7406c3fb27SDimitry Andric     VTypeState_TailPolicy,
7506c3fb27SDimitry Andric     VTypeState_MaskPolicy,
7606c3fb27SDimitry Andric     VTypeState_Done,
7706c3fb27SDimitry Andric   };
7806c3fb27SDimitry Andric 
790b57cec5SDimitry Andric   SmallVector<FeatureBitset, 4> FeatureBitStack;
800b57cec5SDimitry Andric 
815ffd83dbSDimitry Andric   SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
825ffd83dbSDimitry Andric   ParserOptionsSet ParserOptions;
835ffd83dbSDimitry Andric 
840b57cec5SDimitry Andric   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
850b57cec5SDimitry Andric   bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
86*0fca6ea1SDimitry Andric   bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureStdExtE); }
87*0fca6ea1SDimitry Andric   bool enableExperimentalExtension() const {
88*0fca6ea1SDimitry Andric     return getSTI().hasFeature(RISCV::Experimental);
89*0fca6ea1SDimitry Andric   }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   RISCVTargetStreamer &getTargetStreamer() {
92bdd1243dSDimitry Andric     assert(getParser().getStreamer().getTargetStreamer() &&
93bdd1243dSDimitry Andric            "do not have a target streamer");
940b57cec5SDimitry Andric     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
950b57cec5SDimitry Andric     return static_cast<RISCVTargetStreamer &>(TS);
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
990b57cec5SDimitry Andric                                       unsigned Kind) override;
10006c3fb27SDimitry Andric   unsigned checkTargetMatchPredicate(MCInst &Inst) override;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
10306c3fb27SDimitry Andric                                   int64_t Lower, int64_t Upper,
10406c3fb27SDimitry Andric                                   const Twine &Msg);
10506c3fb27SDimitry Andric   bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
10606c3fb27SDimitry Andric                                   const Twine &Msg);
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1090b57cec5SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
1100b57cec5SDimitry Andric                                uint64_t &ErrorInfo,
1110b57cec5SDimitry Andric                                bool MatchingInlineAsm) override;
1120b57cec5SDimitry Andric 
113*0fca6ea1SDimitry Andric   MCRegister matchRegisterNameHelper(StringRef Name) const;
1145f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1155f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1165ffd83dbSDimitry Andric                                SMLoc &EndLoc) override;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1190b57cec5SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
1200b57cec5SDimitry Andric 
12106c3fb27SDimitry Andric   ParseStatus parseDirective(AsmToken DirectiveID) override;
12206c3fb27SDimitry Andric 
123*0fca6ea1SDimitry Andric   bool parseVTypeToken(const AsmToken &Tok, VTypeState &State, unsigned &Sew,
12406c3fb27SDimitry Andric                        unsigned &Lmul, bool &Fractional, bool &TailAgnostic,
12506c3fb27SDimitry Andric                        bool &MaskAgnostic);
12606c3fb27SDimitry Andric   bool generateVTypeError(SMLoc ErrorLoc);
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   // Helper to actually emit an instruction to the MCStreamer. Also, when
1290b57cec5SDimitry Andric   // possible, compression of the instruction is performed.
1300b57cec5SDimitry Andric   void emitToStreamer(MCStreamer &S, const MCInst &Inst);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
1330b57cec5SDimitry Andric   // synthesize the desired immedate value into the destination register.
134e8d8bef9SDimitry Andric   void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
1370b57cec5SDimitry Andric   // helpers such as emitLoadLocalAddress and emitLoadAddress.
1380b57cec5SDimitry Andric   void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
1390b57cec5SDimitry Andric                          const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
1400b57cec5SDimitry Andric                          unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
1430b57cec5SDimitry Andric   void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1440b57cec5SDimitry Andric 
14506c3fb27SDimitry Andric   // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
14606c3fb27SDimitry Andric   void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
14706c3fb27SDimitry Andric 
1480b57cec5SDimitry Andric   // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
1490b57cec5SDimitry Andric   void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
1520b57cec5SDimitry Andric   // addressing.
1530b57cec5SDimitry Andric   void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
1560b57cec5SDimitry Andric   // addressing.
1570b57cec5SDimitry Andric   void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   // Helper to emit pseudo load/store instruction with a symbol.
1600b57cec5SDimitry Andric   void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
1610b57cec5SDimitry Andric                            MCStreamer &Out, bool HasTmpReg);
1620b57cec5SDimitry Andric 
163e8d8bef9SDimitry Andric   // Helper to emit pseudo sign/zero extend instruction.
164e8d8bef9SDimitry Andric   void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
165e8d8bef9SDimitry Andric                         SMLoc IDLoc, MCStreamer &Out);
166e8d8bef9SDimitry Andric 
167e8d8bef9SDimitry Andric   // Helper to emit pseudo vmsge{u}.vx instruction.
168e8d8bef9SDimitry Andric   void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
169e8d8bef9SDimitry Andric 
1700b57cec5SDimitry Andric   // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
1710b57cec5SDimitry Andric   // Enforcing this using a restricted register class for the second input
1720b57cec5SDimitry Andric   // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
1730b57cec5SDimitry Andric   // 'add' is an overloaded mnemonic.
1740b57cec5SDimitry Andric   bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
1750b57cec5SDimitry Andric 
1767a6dacacSDimitry Andric   // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.
1777a6dacacSDimitry Andric   // Enforcing this using a restricted register class for the output
1787a6dacacSDimitry Andric   // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact
1797a6dacacSDimitry Andric   // 'jalr' is an overloaded mnemonic.
1807a6dacacSDimitry Andric   bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands);
1817a6dacacSDimitry Andric 
1825ffd83dbSDimitry Andric   // Check instruction constraints.
1835ffd83dbSDimitry Andric   bool validateInstruction(MCInst &Inst, OperandVector &Operands);
1845ffd83dbSDimitry Andric 
1850b57cec5SDimitry Andric   /// Helper for processing MC instructions that have been successfully matched
1860b57cec5SDimitry Andric   /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
1870b57cec5SDimitry Andric   /// like the expansion of pseudo instructions (e.g., "li"), can be performed
1880b57cec5SDimitry Andric   /// in this method.
1890b57cec5SDimitry Andric   bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
1900b57cec5SDimitry Andric                           MCStreamer &Out);
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric // Auto-generated instruction matching functions
1930b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
1940b57cec5SDimitry Andric #include "RISCVGenAsmMatcher.inc"
1950b57cec5SDimitry Andric 
19606c3fb27SDimitry Andric   ParseStatus parseCSRSystemRegister(OperandVector &Operands);
19706c3fb27SDimitry Andric   ParseStatus parseFPImm(OperandVector &Operands);
19806c3fb27SDimitry Andric   ParseStatus parseImmediate(OperandVector &Operands);
19906c3fb27SDimitry Andric   ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);
20006c3fb27SDimitry Andric   ParseStatus parseMemOpBaseReg(OperandVector &Operands);
20106c3fb27SDimitry Andric   ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);
20206c3fb27SDimitry Andric   ParseStatus parseOperandWithModifier(OperandVector &Operands);
20306c3fb27SDimitry Andric   ParseStatus parseBareSymbol(OperandVector &Operands);
20406c3fb27SDimitry Andric   ParseStatus parseCallSymbol(OperandVector &Operands);
20506c3fb27SDimitry Andric   ParseStatus parsePseudoJumpSymbol(OperandVector &Operands);
20606c3fb27SDimitry Andric   ParseStatus parseJALOffset(OperandVector &Operands);
20706c3fb27SDimitry Andric   ParseStatus parseVTypeI(OperandVector &Operands);
20806c3fb27SDimitry Andric   ParseStatus parseMaskReg(OperandVector &Operands);
20906c3fb27SDimitry Andric   ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);
21006c3fb27SDimitry Andric   ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);
21106c3fb27SDimitry Andric   ParseStatus parseGPRAsFPR(OperandVector &Operands);
212297eecfbSDimitry Andric   template <bool IsRV64Inst> ParseStatus parseGPRPair(OperandVector &Operands);
213297eecfbSDimitry Andric   ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);
21406c3fb27SDimitry Andric   ParseStatus parseFRMArg(OperandVector &Operands);
21506c3fb27SDimitry Andric   ParseStatus parseFenceArg(OperandVector &Operands);
21606c3fb27SDimitry Andric   ParseStatus parseReglist(OperandVector &Operands);
2175f757f3fSDimitry Andric   ParseStatus parseRegReg(OperandVector &Operands);
21806c3fb27SDimitry Andric   ParseStatus parseRetval(OperandVector &Operands);
219*0fca6ea1SDimitry Andric   ParseStatus parseZcmpStackAdj(OperandVector &Operands,
220*0fca6ea1SDimitry Andric                                 bool ExpectNegative = false);
221*0fca6ea1SDimitry Andric   ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) {
222*0fca6ea1SDimitry Andric     return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true);
223*0fca6ea1SDimitry Andric   }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   bool parseDirectiveOption();
2285ffd83dbSDimitry Andric   bool parseDirectiveAttribute();
229349cc55cSDimitry Andric   bool parseDirectiveInsn(SMLoc L);
230bdd1243dSDimitry Andric   bool parseDirectiveVariantCC();
2310b57cec5SDimitry Andric 
23206c3fb27SDimitry Andric   /// Helper to reset target features for a new arch string. It
23306c3fb27SDimitry Andric   /// also records the new arch string that is expanded by RISCVISAInfo
23406c3fb27SDimitry Andric   /// and reports error for invalid arch string.
23506c3fb27SDimitry Andric   bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
23606c3fb27SDimitry Andric                    bool FromOptionDirective);
23706c3fb27SDimitry Andric 
2380b57cec5SDimitry Andric   void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
23906c3fb27SDimitry Andric     if (!(getSTI().hasFeature(Feature))) {
2400b57cec5SDimitry Andric       MCSubtargetInfo &STI = copySTI();
2410b57cec5SDimitry Andric       setAvailableFeatures(
2420b57cec5SDimitry Andric           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
2430b57cec5SDimitry Andric     }
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
24706c3fb27SDimitry Andric     if (getSTI().hasFeature(Feature)) {
2480b57cec5SDimitry Andric       MCSubtargetInfo &STI = copySTI();
2490b57cec5SDimitry Andric       setAvailableFeatures(
2500b57cec5SDimitry Andric           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
2510b57cec5SDimitry Andric     }
2520b57cec5SDimitry Andric   }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   void pushFeatureBits() {
2555ffd83dbSDimitry Andric     assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
2565ffd83dbSDimitry Andric            "These two stacks must be kept synchronized");
2570b57cec5SDimitry Andric     FeatureBitStack.push_back(getSTI().getFeatureBits());
2585ffd83dbSDimitry Andric     ParserOptionsStack.push_back(ParserOptions);
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   bool popFeatureBits() {
2625ffd83dbSDimitry Andric     assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
2635ffd83dbSDimitry Andric            "These two stacks must be kept synchronized");
2640b57cec5SDimitry Andric     if (FeatureBitStack.empty())
2650b57cec5SDimitry Andric       return true;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric     FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
2680b57cec5SDimitry Andric     copySTI().setFeatureBits(FeatureBits);
2690b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
2700b57cec5SDimitry Andric 
2715ffd83dbSDimitry Andric     ParserOptions = ParserOptionsStack.pop_back_val();
2725ffd83dbSDimitry Andric 
2730b57cec5SDimitry Andric     return false;
2740b57cec5SDimitry Andric   }
2755ffd83dbSDimitry Andric 
2765ffd83dbSDimitry Andric   std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
27706c3fb27SDimitry Andric   std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
2785f757f3fSDimitry Andric   std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;
2795ffd83dbSDimitry Andric 
2800b57cec5SDimitry Andric public:
2810b57cec5SDimitry Andric   enum RISCVMatchResultTy {
2820b57cec5SDimitry Andric     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
28306c3fb27SDimitry Andric     Match_RequiresEvenGPRs,
2840b57cec5SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
2850b57cec5SDimitry Andric #include "RISCVGenAsmMatcher.inc"
2860b57cec5SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES
2870b57cec5SDimitry Andric   };
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   static bool classifySymbolRef(const MCExpr *Expr,
290e8d8bef9SDimitry Andric                                 RISCVMCExpr::VariantKind &Kind);
29106c3fb27SDimitry Andric   static bool isSymbolDiff(const MCExpr *Expr);
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
2940b57cec5SDimitry Andric                  const MCInstrInfo &MII, const MCTargetOptions &Options)
2950b57cec5SDimitry Andric       : MCTargetAsmParser(Options, STI, MII) {
29606c3fb27SDimitry Andric     MCAsmParserExtension::Initialize(Parser);
29706c3fb27SDimitry Andric 
2980b57cec5SDimitry Andric     Parser.addAliasForDirective(".half", ".2byte");
2990b57cec5SDimitry Andric     Parser.addAliasForDirective(".hword", ".2byte");
3000b57cec5SDimitry Andric     Parser.addAliasForDirective(".word", ".4byte");
3010b57cec5SDimitry Andric     Parser.addAliasForDirective(".dword", ".8byte");
3020b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
303480093f4SDimitry Andric 
30413138422SDimitry Andric     auto ABIName = StringRef(Options.ABIName);
3055f757f3fSDimitry Andric     if (ABIName.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
306480093f4SDimitry Andric       errs() << "Hard-float 'f' ABI can't be used for a target that "
307480093f4SDimitry Andric                 "doesn't support the F instruction set extension (ignoring "
308480093f4SDimitry Andric                 "target-abi)\n";
3095f757f3fSDimitry Andric     } else if (ABIName.ends_with("d") &&
31006c3fb27SDimitry Andric                !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
311480093f4SDimitry Andric       errs() << "Hard-float 'd' ABI can't be used for a target that "
312480093f4SDimitry Andric                 "doesn't support the D instruction set extension (ignoring "
313480093f4SDimitry Andric                 "target-abi)\n";
314480093f4SDimitry Andric     }
3155ffd83dbSDimitry Andric 
31681ad6265SDimitry Andric     // Use computeTargetABI to check if ABIName is valid. If invalid, output
31781ad6265SDimitry Andric     // error message.
31881ad6265SDimitry Andric     RISCVABI::computeTargetABI(STI.getTargetTriple(), STI.getFeatureBits(),
31981ad6265SDimitry Andric                                ABIName);
32081ad6265SDimitry Andric 
3215ffd83dbSDimitry Andric     const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
3225ffd83dbSDimitry Andric     ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
32306c3fb27SDimitry Andric 
32406c3fb27SDimitry Andric     if (AddBuildAttributes)
32506c3fb27SDimitry Andric       getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric };
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric /// RISCVOperand - Instances of this class represent a parsed machine
3300b57cec5SDimitry Andric /// instruction
33106c3fb27SDimitry Andric struct RISCVOperand final : public MCParsedAsmOperand {
3320b57cec5SDimitry Andric 
3338bcb0991SDimitry Andric   enum class KindTy {
3340b57cec5SDimitry Andric     Token,
3350b57cec5SDimitry Andric     Register,
3360b57cec5SDimitry Andric     Immediate,
33706c3fb27SDimitry Andric     FPImmediate,
3385ffd83dbSDimitry Andric     SystemRegister,
3395ffd83dbSDimitry Andric     VType,
34006c3fb27SDimitry Andric     FRM,
34106c3fb27SDimitry Andric     Fence,
34206c3fb27SDimitry Andric     Rlist,
34306c3fb27SDimitry Andric     Spimm,
3445f757f3fSDimitry Andric     RegReg,
3450b57cec5SDimitry Andric   } Kind;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   struct RegOp {
348e8d8bef9SDimitry Andric     MCRegister RegNum;
34906c3fb27SDimitry Andric     bool IsGPRAsFPR;
3500b57cec5SDimitry Andric   };
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   struct ImmOp {
3530b57cec5SDimitry Andric     const MCExpr *Val;
35406c3fb27SDimitry Andric     bool IsRV64;
35506c3fb27SDimitry Andric   };
35606c3fb27SDimitry Andric 
35706c3fb27SDimitry Andric   struct FPImmOp {
35806c3fb27SDimitry Andric     uint64_t Val;
3590b57cec5SDimitry Andric   };
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   struct SysRegOp {
3620b57cec5SDimitry Andric     const char *Data;
3630b57cec5SDimitry Andric     unsigned Length;
3640b57cec5SDimitry Andric     unsigned Encoding;
3650b57cec5SDimitry Andric     // FIXME: Add the Encoding parsed fields as needed for checks,
3660b57cec5SDimitry Andric     // e.g.: read/write or user/supervisor/machine privileges.
3670b57cec5SDimitry Andric   };
3680b57cec5SDimitry Andric 
3695ffd83dbSDimitry Andric   struct VTypeOp {
370e8d8bef9SDimitry Andric     unsigned Val;
3715ffd83dbSDimitry Andric   };
3725ffd83dbSDimitry Andric 
37306c3fb27SDimitry Andric   struct FRMOp {
37406c3fb27SDimitry Andric     RISCVFPRndMode::RoundingMode FRM;
37506c3fb27SDimitry Andric   };
37606c3fb27SDimitry Andric 
37706c3fb27SDimitry Andric   struct FenceOp {
37806c3fb27SDimitry Andric     unsigned Val;
37906c3fb27SDimitry Andric   };
38006c3fb27SDimitry Andric 
38106c3fb27SDimitry Andric   struct RlistOp {
38206c3fb27SDimitry Andric     unsigned Val;
38306c3fb27SDimitry Andric   };
38406c3fb27SDimitry Andric 
38506c3fb27SDimitry Andric   struct SpimmOp {
38606c3fb27SDimitry Andric     unsigned Val;
38706c3fb27SDimitry Andric   };
38806c3fb27SDimitry Andric 
3895f757f3fSDimitry Andric   struct RegRegOp {
3905f757f3fSDimitry Andric     MCRegister Reg1;
3915f757f3fSDimitry Andric     MCRegister Reg2;
3925f757f3fSDimitry Andric   };
3935f757f3fSDimitry Andric 
3940b57cec5SDimitry Andric   SMLoc StartLoc, EndLoc;
3950b57cec5SDimitry Andric   union {
3960b57cec5SDimitry Andric     StringRef Tok;
3970b57cec5SDimitry Andric     RegOp Reg;
3980b57cec5SDimitry Andric     ImmOp Imm;
39906c3fb27SDimitry Andric     FPImmOp FPImm;
4000b57cec5SDimitry Andric     struct SysRegOp SysReg;
4015ffd83dbSDimitry Andric     struct VTypeOp VType;
40206c3fb27SDimitry Andric     struct FRMOp FRM;
40306c3fb27SDimitry Andric     struct FenceOp Fence;
40406c3fb27SDimitry Andric     struct RlistOp Rlist;
40506c3fb27SDimitry Andric     struct SpimmOp Spimm;
4065f757f3fSDimitry Andric     struct RegRegOp RegReg;
4070b57cec5SDimitry Andric   };
4080b57cec5SDimitry Andric 
40904eeddc0SDimitry Andric   RISCVOperand(KindTy K) : Kind(K) {}
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric public:
4120b57cec5SDimitry Andric   RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
4130b57cec5SDimitry Andric     Kind = o.Kind;
4140b57cec5SDimitry Andric     StartLoc = o.StartLoc;
4150b57cec5SDimitry Andric     EndLoc = o.EndLoc;
4160b57cec5SDimitry Andric     switch (Kind) {
4178bcb0991SDimitry Andric     case KindTy::Register:
4180b57cec5SDimitry Andric       Reg = o.Reg;
4190b57cec5SDimitry Andric       break;
4208bcb0991SDimitry Andric     case KindTy::Immediate:
4210b57cec5SDimitry Andric       Imm = o.Imm;
4220b57cec5SDimitry Andric       break;
42306c3fb27SDimitry Andric     case KindTy::FPImmediate:
42406c3fb27SDimitry Andric       FPImm = o.FPImm;
42506c3fb27SDimitry Andric       break;
4268bcb0991SDimitry Andric     case KindTy::Token:
4270b57cec5SDimitry Andric       Tok = o.Tok;
4280b57cec5SDimitry Andric       break;
4298bcb0991SDimitry Andric     case KindTy::SystemRegister:
4300b57cec5SDimitry Andric       SysReg = o.SysReg;
4310b57cec5SDimitry Andric       break;
4325ffd83dbSDimitry Andric     case KindTy::VType:
4335ffd83dbSDimitry Andric       VType = o.VType;
4345ffd83dbSDimitry Andric       break;
43506c3fb27SDimitry Andric     case KindTy::FRM:
43606c3fb27SDimitry Andric       FRM = o.FRM;
43706c3fb27SDimitry Andric       break;
43806c3fb27SDimitry Andric     case KindTy::Fence:
43906c3fb27SDimitry Andric       Fence = o.Fence;
44006c3fb27SDimitry Andric       break;
44106c3fb27SDimitry Andric     case KindTy::Rlist:
44206c3fb27SDimitry Andric       Rlist = o.Rlist;
44306c3fb27SDimitry Andric       break;
44406c3fb27SDimitry Andric     case KindTy::Spimm:
44506c3fb27SDimitry Andric       Spimm = o.Spimm;
44606c3fb27SDimitry Andric       break;
4475f757f3fSDimitry Andric     case KindTy::RegReg:
4485f757f3fSDimitry Andric       RegReg = o.RegReg;
4495f757f3fSDimitry Andric       break;
4500b57cec5SDimitry Andric     }
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric 
4538bcb0991SDimitry Andric   bool isToken() const override { return Kind == KindTy::Token; }
4548bcb0991SDimitry Andric   bool isReg() const override { return Kind == KindTy::Register; }
4555ffd83dbSDimitry Andric   bool isV0Reg() const {
4565ffd83dbSDimitry Andric     return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
4575ffd83dbSDimitry Andric   }
45806c3fb27SDimitry Andric   bool isAnyReg() const {
45906c3fb27SDimitry Andric     return Kind == KindTy::Register &&
46006c3fb27SDimitry Andric            (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum) ||
46106c3fb27SDimitry Andric             RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.RegNum) ||
46206c3fb27SDimitry Andric             RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.RegNum));
46306c3fb27SDimitry Andric   }
46406c3fb27SDimitry Andric   bool isAnyRegC() const {
46506c3fb27SDimitry Andric     return Kind == KindTy::Register &&
46606c3fb27SDimitry Andric            (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
46706c3fb27SDimitry Andric                 Reg.RegNum) ||
46806c3fb27SDimitry Andric             RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
46906c3fb27SDimitry Andric                 Reg.RegNum));
47006c3fb27SDimitry Andric   }
4718bcb0991SDimitry Andric   bool isImm() const override { return Kind == KindTy::Immediate; }
4720b57cec5SDimitry Andric   bool isMem() const override { return false; }
4738bcb0991SDimitry Andric   bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
4745f757f3fSDimitry Andric   bool isRegReg() const { return Kind == KindTy::RegReg; }
47506c3fb27SDimitry Andric   bool isRlist() const { return Kind == KindTy::Rlist; }
47606c3fb27SDimitry Andric   bool isSpimm() const { return Kind == KindTy::Spimm; }
4770b57cec5SDimitry Andric 
478480093f4SDimitry Andric   bool isGPR() const {
479480093f4SDimitry Andric     return Kind == KindTy::Register &&
480480093f4SDimitry Andric            RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
481480093f4SDimitry Andric   }
482480093f4SDimitry Andric 
48306c3fb27SDimitry Andric   bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
484d56accc7SDimitry Andric 
485297eecfbSDimitry Andric   bool isGPRPair() const {
486297eecfbSDimitry Andric     return Kind == KindTy::Register &&
487297eecfbSDimitry Andric            RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
488297eecfbSDimitry Andric                Reg.RegNum);
489297eecfbSDimitry Andric   }
490297eecfbSDimitry Andric 
4910b57cec5SDimitry Andric   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
4920b57cec5SDimitry Andric                                   RISCVMCExpr::VariantKind &VK) {
4930b57cec5SDimitry Andric     if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
4940b57cec5SDimitry Andric       VK = RE->getKind();
4950b57cec5SDimitry Andric       return RE->evaluateAsConstant(Imm);
4960b57cec5SDimitry Andric     }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
4990b57cec5SDimitry Andric       VK = RISCVMCExpr::VK_RISCV_None;
5000b57cec5SDimitry Andric       Imm = CE->getValue();
5010b57cec5SDimitry Andric       return true;
5020b57cec5SDimitry Andric     }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric     return false;
5050b57cec5SDimitry Andric   }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   // True if operand is a symbol with no modifiers, or a constant with no
5080b57cec5SDimitry Andric   // modifiers and isShiftedInt<N-1, 1>(Op).
5090b57cec5SDimitry Andric   template <int N> bool isBareSimmNLsb0() const {
5100b57cec5SDimitry Andric     int64_t Imm;
5118bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5120b57cec5SDimitry Andric     if (!isImm())
5130b57cec5SDimitry Andric       return false;
5140b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
5150b57cec5SDimitry Andric     bool IsValid;
5160b57cec5SDimitry Andric     if (!IsConstantImm)
517e8d8bef9SDimitry Andric       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
5180b57cec5SDimitry Andric     else
5190b57cec5SDimitry Andric       IsValid = isShiftedInt<N - 1, 1>(Imm);
5200b57cec5SDimitry Andric     return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
5210b57cec5SDimitry Andric   }
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   bool isBareSymbol() const {
5260b57cec5SDimitry Andric     int64_t Imm;
5278bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5280b57cec5SDimitry Andric     // Must be of 'immediate' type but not a constant.
5290b57cec5SDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5300b57cec5SDimitry Andric       return false;
531e8d8bef9SDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5320b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
5330b57cec5SDimitry Andric   }
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   bool isCallSymbol() const {
5360b57cec5SDimitry Andric     int64_t Imm;
5378bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5380b57cec5SDimitry Andric     // Must be of 'immediate' type but not a constant.
5390b57cec5SDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5400b57cec5SDimitry Andric       return false;
541e8d8bef9SDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5420b57cec5SDimitry Andric            (VK == RISCVMCExpr::VK_RISCV_CALL ||
5430b57cec5SDimitry Andric             VK == RISCVMCExpr::VK_RISCV_CALL_PLT);
5440b57cec5SDimitry Andric   }
5450b57cec5SDimitry Andric 
5465ffd83dbSDimitry Andric   bool isPseudoJumpSymbol() const {
5475ffd83dbSDimitry Andric     int64_t Imm;
5485ffd83dbSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5495ffd83dbSDimitry Andric     // Must be of 'immediate' type but not a constant.
5505ffd83dbSDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5515ffd83dbSDimitry Andric       return false;
552e8d8bef9SDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5535ffd83dbSDimitry Andric            VK == RISCVMCExpr::VK_RISCV_CALL;
5545ffd83dbSDimitry Andric   }
5555ffd83dbSDimitry Andric 
5560b57cec5SDimitry Andric   bool isTPRelAddSymbol() const {
5570b57cec5SDimitry Andric     int64_t Imm;
5588bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5590b57cec5SDimitry Andric     // Must be of 'immediate' type but not a constant.
5600b57cec5SDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5610b57cec5SDimitry Andric       return false;
562e8d8bef9SDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5630b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_TPREL_ADD;
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric 
5667a6dacacSDimitry Andric   bool isTLSDESCCallSymbol() const {
5677a6dacacSDimitry Andric     int64_t Imm;
5687a6dacacSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5697a6dacacSDimitry Andric     // Must be of 'immediate' type but not a constant.
5707a6dacacSDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5717a6dacacSDimitry Andric       return false;
5727a6dacacSDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5737a6dacacSDimitry Andric            VK == RISCVMCExpr::VK_RISCV_TLSDESC_CALL;
5747a6dacacSDimitry Andric   }
5757a6dacacSDimitry Andric 
5760b57cec5SDimitry Andric   bool isCSRSystemRegister() const { return isSystemRegister(); }
5770b57cec5SDimitry Andric 
57804eeddc0SDimitry Andric   bool isVTypeImm(unsigned N) const {
57904eeddc0SDimitry Andric     int64_t Imm;
58004eeddc0SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
58104eeddc0SDimitry Andric     if (!isImm())
58204eeddc0SDimitry Andric       return false;
58304eeddc0SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
58404eeddc0SDimitry Andric     return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None;
58504eeddc0SDimitry Andric   }
58604eeddc0SDimitry Andric 
58704eeddc0SDimitry Andric   // If the last operand of the vsetvli/vsetvli instruction is a constant
58804eeddc0SDimitry Andric   // expression, KindTy is Immediate.
58904eeddc0SDimitry Andric   bool isVTypeI10() const {
59004eeddc0SDimitry Andric     if (Kind == KindTy::Immediate)
59104eeddc0SDimitry Andric       return isVTypeImm(10);
59204eeddc0SDimitry Andric     return Kind == KindTy::VType;
59304eeddc0SDimitry Andric   }
59404eeddc0SDimitry Andric   bool isVTypeI11() const {
59504eeddc0SDimitry Andric     if (Kind == KindTy::Immediate)
59604eeddc0SDimitry Andric       return isVTypeImm(11);
59704eeddc0SDimitry Andric     return Kind == KindTy::VType;
59804eeddc0SDimitry Andric   }
5995ffd83dbSDimitry Andric 
6000b57cec5SDimitry Andric   /// Return true if the operand is a valid for the fence instruction e.g.
6010b57cec5SDimitry Andric   /// ('iorw').
60206c3fb27SDimitry Andric   bool isFenceArg() const { return Kind == KindTy::Fence; }
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   /// Return true if the operand is a valid floating point rounding mode.
60506c3fb27SDimitry Andric   bool isFRMArg() const { return Kind == KindTy::FRM; }
6065f757f3fSDimitry Andric   bool isFRMArgLegacy() const { return Kind == KindTy::FRM; }
60706c3fb27SDimitry Andric   bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }
6080b57cec5SDimitry Andric 
60906c3fb27SDimitry Andric   /// Return true if the operand is a valid fli.s floating-point immediate.
61006c3fb27SDimitry Andric   bool isLoadFPImm() const {
61106c3fb27SDimitry Andric     if (isImm())
61206c3fb27SDimitry Andric       return isUImm5();
61306c3fb27SDimitry Andric     if (Kind != KindTy::FPImmediate)
61406c3fb27SDimitry Andric       return false;
61506c3fb27SDimitry Andric     int Idx = RISCVLoadFPImm::getLoadFPImm(
61606c3fb27SDimitry Andric         APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
61706c3fb27SDimitry Andric     // Don't allow decimal version of the minimum value. It is a different value
61806c3fb27SDimitry Andric     // for each supported data type.
61906c3fb27SDimitry Andric     return Idx >= 0 && Idx != 1;
6200b57cec5SDimitry Andric   }
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric   bool isImmXLenLI() const {
6230b57cec5SDimitry Andric     int64_t Imm;
6248bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
6250b57cec5SDimitry Andric     if (!isImm())
6260b57cec5SDimitry Andric       return false;
6270b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
6287a6dacacSDimitry Andric     if (VK == RISCVMCExpr::VK_RISCV_LO ||
6297a6dacacSDimitry Andric         VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
6307a6dacacSDimitry Andric         VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
6317a6dacacSDimitry Andric         VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO)
6320b57cec5SDimitry Andric       return true;
6330b57cec5SDimitry Andric     // Given only Imm, ensuring that the actually specified constant is either
6340b57cec5SDimitry Andric     // a signed or unsigned 64-bit number is unfortunately impossible.
63506c3fb27SDimitry Andric     if (IsConstantImm) {
63606c3fb27SDimitry Andric       return VK == RISCVMCExpr::VK_RISCV_None &&
63706c3fb27SDimitry Andric              (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
63806c3fb27SDimitry Andric     }
63906c3fb27SDimitry Andric 
64006c3fb27SDimitry Andric     return RISCVAsmParser::isSymbolDiff(getImm());
64106c3fb27SDimitry Andric   }
64206c3fb27SDimitry Andric 
64306c3fb27SDimitry Andric   bool isImmXLenLI_Restricted() const {
64406c3fb27SDimitry Andric     int64_t Imm;
64506c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
64606c3fb27SDimitry Andric     if (!isImm())
64706c3fb27SDimitry Andric       return false;
64806c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
64906c3fb27SDimitry Andric     // 'la imm' supports constant immediates only.
65006c3fb27SDimitry Andric     return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) &&
65106c3fb27SDimitry Andric            (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
6520b57cec5SDimitry Andric   }
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   bool isUImmLog2XLen() const {
6550b57cec5SDimitry Andric     int64_t Imm;
6568bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
6570b57cec5SDimitry Andric     if (!isImm())
6580b57cec5SDimitry Andric       return false;
6590b57cec5SDimitry Andric     if (!evaluateConstantImm(getImm(), Imm, VK) ||
6600b57cec5SDimitry Andric         VK != RISCVMCExpr::VK_RISCV_None)
6610b57cec5SDimitry Andric       return false;
66206c3fb27SDimitry Andric     return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
6630b57cec5SDimitry Andric   }
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   bool isUImmLog2XLenNonZero() const {
6660b57cec5SDimitry Andric     int64_t Imm;
6678bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
6680b57cec5SDimitry Andric     if (!isImm())
6690b57cec5SDimitry Andric       return false;
6700b57cec5SDimitry Andric     if (!evaluateConstantImm(getImm(), Imm, VK) ||
6710b57cec5SDimitry Andric         VK != RISCVMCExpr::VK_RISCV_None)
6720b57cec5SDimitry Andric       return false;
6730b57cec5SDimitry Andric     if (Imm == 0)
6740b57cec5SDimitry Andric       return false;
67506c3fb27SDimitry Andric     return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
6760b57cec5SDimitry Andric   }
6770b57cec5SDimitry Andric 
6785ffd83dbSDimitry Andric   bool isUImmLog2XLenHalf() const {
6795ffd83dbSDimitry Andric     int64_t Imm;
6805ffd83dbSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
6815ffd83dbSDimitry Andric     if (!isImm())
6825ffd83dbSDimitry Andric       return false;
6835ffd83dbSDimitry Andric     if (!evaluateConstantImm(getImm(), Imm, VK) ||
6845ffd83dbSDimitry Andric         VK != RISCVMCExpr::VK_RISCV_None)
6855ffd83dbSDimitry Andric       return false;
68606c3fb27SDimitry Andric     return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
6875ffd83dbSDimitry Andric   }
6885ffd83dbSDimitry Andric 
68981ad6265SDimitry Andric   template <unsigned N> bool IsUImm() const {
690349cc55cSDimitry Andric     int64_t Imm;
691349cc55cSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
692349cc55cSDimitry Andric     if (!isImm())
693349cc55cSDimitry Andric       return false;
694349cc55cSDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
69581ad6265SDimitry Andric     return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
696349cc55cSDimitry Andric   }
697349cc55cSDimitry Andric 
69806c3fb27SDimitry Andric   bool isUImm1() const { return IsUImm<1>(); }
69906c3fb27SDimitry Andric   bool isUImm2() const { return IsUImm<2>(); }
70006c3fb27SDimitry Andric   bool isUImm3() const { return IsUImm<3>(); }
70106c3fb27SDimitry Andric   bool isUImm4() const { return IsUImm<4>(); }
70206c3fb27SDimitry Andric   bool isUImm5() const { return IsUImm<5>(); }
70306c3fb27SDimitry Andric   bool isUImm6() const { return IsUImm<6>(); }
70406c3fb27SDimitry Andric   bool isUImm7() const { return IsUImm<7>(); }
70506c3fb27SDimitry Andric   bool isUImm8() const { return IsUImm<8>(); }
706*0fca6ea1SDimitry Andric   bool isUImm16() const { return IsUImm<16>(); }
7075f757f3fSDimitry Andric   bool isUImm20() const { return IsUImm<20>(); }
708*0fca6ea1SDimitry Andric   bool isUImm32() const { return IsUImm<32>(); }
70906c3fb27SDimitry Andric 
71006c3fb27SDimitry Andric   bool isUImm8GE32() const {
71106c3fb27SDimitry Andric     int64_t Imm;
71206c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
71306c3fb27SDimitry Andric     if (!isImm())
71406c3fb27SDimitry Andric       return false;
71506c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
71606c3fb27SDimitry Andric     return IsConstantImm && isUInt<8>(Imm) && Imm >= 32 &&
71706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
71806c3fb27SDimitry Andric   }
719349cc55cSDimitry Andric 
72004eeddc0SDimitry Andric   bool isRnumArg() const {
72104eeddc0SDimitry Andric     int64_t Imm;
72204eeddc0SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
72304eeddc0SDimitry Andric     if (!isImm())
72404eeddc0SDimitry Andric       return false;
72504eeddc0SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
72604eeddc0SDimitry Andric     return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) &&
72704eeddc0SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
72804eeddc0SDimitry Andric   }
72904eeddc0SDimitry Andric 
73006c3fb27SDimitry Andric   bool isRnumArg_0_7() const {
73106c3fb27SDimitry Andric     int64_t Imm;
73206c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
73306c3fb27SDimitry Andric     if (!isImm())
73406c3fb27SDimitry Andric       return false;
73506c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
73606c3fb27SDimitry Andric     return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(7) &&
73706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
73806c3fb27SDimitry Andric   }
73906c3fb27SDimitry Andric 
74006c3fb27SDimitry Andric   bool isRnumArg_1_10() const {
74106c3fb27SDimitry Andric     int64_t Imm;
74206c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
74306c3fb27SDimitry Andric     if (!isImm())
74406c3fb27SDimitry Andric       return false;
74506c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
74606c3fb27SDimitry Andric     return IsConstantImm && Imm >= INT64_C(1) && Imm <= INT64_C(10) &&
74706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
74806c3fb27SDimitry Andric   }
74906c3fb27SDimitry Andric 
75006c3fb27SDimitry Andric   bool isRnumArg_2_14() const {
75106c3fb27SDimitry Andric     int64_t Imm;
75206c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
75306c3fb27SDimitry Andric     if (!isImm())
75406c3fb27SDimitry Andric       return false;
75506c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
75606c3fb27SDimitry Andric     return IsConstantImm && Imm >= INT64_C(2) && Imm <= INT64_C(14) &&
75706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
75806c3fb27SDimitry Andric   }
75906c3fb27SDimitry Andric 
7605ffd83dbSDimitry Andric   bool isSImm5() const {
7615ffd83dbSDimitry Andric     if (!isImm())
7625ffd83dbSDimitry Andric       return false;
7635ffd83dbSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
7645ffd83dbSDimitry Andric     int64_t Imm;
7655ffd83dbSDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
76606c3fb27SDimitry Andric     return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
76706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
7685ffd83dbSDimitry Andric   }
7695ffd83dbSDimitry Andric 
7700b57cec5SDimitry Andric   bool isSImm6() const {
7710b57cec5SDimitry Andric     if (!isImm())
7720b57cec5SDimitry Andric       return false;
7738bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
7740b57cec5SDimitry Andric     int64_t Imm;
7750b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
77606c3fb27SDimitry Andric     return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
77706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
7780b57cec5SDimitry Andric   }
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   bool isSImm6NonZero() const {
7810b57cec5SDimitry Andric     if (!isImm())
7820b57cec5SDimitry Andric       return false;
7838bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
7840b57cec5SDimitry Andric     int64_t Imm;
7850b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
78606c3fb27SDimitry Andric     return IsConstantImm && Imm != 0 &&
78706c3fb27SDimitry Andric            isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
7880b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
7890b57cec5SDimitry Andric   }
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   bool isCLUIImm() const {
7920b57cec5SDimitry Andric     if (!isImm())
7930b57cec5SDimitry Andric       return false;
7940b57cec5SDimitry Andric     int64_t Imm;
7958bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
7960b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
7970b57cec5SDimitry Andric     return IsConstantImm && (Imm != 0) &&
7980b57cec5SDimitry Andric            (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
7990b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8000b57cec5SDimitry Andric   }
8010b57cec5SDimitry Andric 
80206c3fb27SDimitry Andric   bool isUImm2Lsb0() const {
80306c3fb27SDimitry Andric     if (!isImm())
80406c3fb27SDimitry Andric       return false;
80506c3fb27SDimitry Andric     int64_t Imm;
80606c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
80706c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
80806c3fb27SDimitry Andric     return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
80906c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
81006c3fb27SDimitry Andric   }
81106c3fb27SDimitry Andric 
812*0fca6ea1SDimitry Andric   bool isUImm5Lsb0() const {
813*0fca6ea1SDimitry Andric     if (!isImm())
814*0fca6ea1SDimitry Andric       return false;
815*0fca6ea1SDimitry Andric     int64_t Imm;
816*0fca6ea1SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
817*0fca6ea1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
818*0fca6ea1SDimitry Andric     return IsConstantImm && isShiftedUInt<4, 1>(Imm) &&
819*0fca6ea1SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
820*0fca6ea1SDimitry Andric   }
821*0fca6ea1SDimitry Andric 
822*0fca6ea1SDimitry Andric   bool isUImm6Lsb0() const {
823*0fca6ea1SDimitry Andric     if (!isImm())
824*0fca6ea1SDimitry Andric       return false;
825*0fca6ea1SDimitry Andric     int64_t Imm;
826*0fca6ea1SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
827*0fca6ea1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
828*0fca6ea1SDimitry Andric     return IsConstantImm && isShiftedUInt<5, 1>(Imm) &&
829*0fca6ea1SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
830*0fca6ea1SDimitry Andric   }
831*0fca6ea1SDimitry Andric 
8320b57cec5SDimitry Andric   bool isUImm7Lsb00() const {
8330b57cec5SDimitry Andric     if (!isImm())
8340b57cec5SDimitry Andric       return false;
8350b57cec5SDimitry Andric     int64_t Imm;
8368bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8370b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8380b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
8390b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8400b57cec5SDimitry Andric   }
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric   bool isUImm8Lsb00() const {
8430b57cec5SDimitry Andric     if (!isImm())
8440b57cec5SDimitry Andric       return false;
8450b57cec5SDimitry Andric     int64_t Imm;
8468bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8470b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8480b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
8490b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8500b57cec5SDimitry Andric   }
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric   bool isUImm8Lsb000() const {
8530b57cec5SDimitry Andric     if (!isImm())
8540b57cec5SDimitry Andric       return false;
8550b57cec5SDimitry Andric     int64_t Imm;
8568bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8570b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8580b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
8590b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8600b57cec5SDimitry Andric   }
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric   bool isUImm9Lsb000() const {
8650b57cec5SDimitry Andric     if (!isImm())
8660b57cec5SDimitry Andric       return false;
8670b57cec5SDimitry Andric     int64_t Imm;
8688bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8690b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8700b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
8710b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8720b57cec5SDimitry Andric   }
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric   bool isUImm10Lsb00NonZero() const {
8750b57cec5SDimitry Andric     if (!isImm())
8760b57cec5SDimitry Andric       return false;
8770b57cec5SDimitry Andric     int64_t Imm;
8788bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8790b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8800b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
8810b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8820b57cec5SDimitry Andric   }
8830b57cec5SDimitry Andric 
88406c3fb27SDimitry Andric   // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
88506c3fb27SDimitry Andric   // This allows writing 'addi a0, a0, 0xffffffff'.
88606c3fb27SDimitry Andric   static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
88706c3fb27SDimitry Andric     if (IsRV64Imm || !isUInt<32>(Imm))
88806c3fb27SDimitry Andric       return Imm;
88906c3fb27SDimitry Andric     return SignExtend64<32>(Imm);
89006c3fb27SDimitry Andric   }
89106c3fb27SDimitry Andric 
8920b57cec5SDimitry Andric   bool isSImm12() const {
8938bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8940b57cec5SDimitry Andric     int64_t Imm;
8950b57cec5SDimitry Andric     bool IsValid;
8960b57cec5SDimitry Andric     if (!isImm())
8970b57cec5SDimitry Andric       return false;
8980b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8990b57cec5SDimitry Andric     if (!IsConstantImm)
900e8d8bef9SDimitry Andric       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
9010b57cec5SDimitry Andric     else
90206c3fb27SDimitry Andric       IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
9030b57cec5SDimitry Andric     return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
9040b57cec5SDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_LO ||
9050b57cec5SDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
9067a6dacacSDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_TPREL_LO ||
9077a6dacacSDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
9087a6dacacSDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO);
9090b57cec5SDimitry Andric   }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric   bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
9120b57cec5SDimitry Andric 
91381ad6265SDimitry Andric   bool isSImm12Lsb00000() const {
91481ad6265SDimitry Andric     if (!isImm())
91581ad6265SDimitry Andric       return false;
91681ad6265SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
91781ad6265SDimitry Andric     int64_t Imm;
91881ad6265SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
91981ad6265SDimitry Andric     return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
92081ad6265SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
92181ad6265SDimitry Andric   }
92281ad6265SDimitry Andric 
9230b57cec5SDimitry Andric   bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric   bool isSImm10Lsb0000NonZero() const {
9260b57cec5SDimitry Andric     if (!isImm())
9270b57cec5SDimitry Andric       return false;
9280b57cec5SDimitry Andric     int64_t Imm;
9298bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9300b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
9310b57cec5SDimitry Andric     return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
9320b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
9330b57cec5SDimitry Andric   }
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric   bool isUImm20LUI() const {
9368bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9370b57cec5SDimitry Andric     int64_t Imm;
9380b57cec5SDimitry Andric     bool IsValid;
9390b57cec5SDimitry Andric     if (!isImm())
9400b57cec5SDimitry Andric       return false;
9410b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
9420b57cec5SDimitry Andric     if (!IsConstantImm) {
943e8d8bef9SDimitry Andric       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
9440b57cec5SDimitry Andric       return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
9450b57cec5SDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
9460b57cec5SDimitry Andric     } else {
9470b57cec5SDimitry Andric       return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
9480b57cec5SDimitry Andric                                  VK == RISCVMCExpr::VK_RISCV_HI ||
9490b57cec5SDimitry Andric                                  VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
9500b57cec5SDimitry Andric     }
9510b57cec5SDimitry Andric   }
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric   bool isUImm20AUIPC() const {
9548bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9550b57cec5SDimitry Andric     int64_t Imm;
9560b57cec5SDimitry Andric     bool IsValid;
9570b57cec5SDimitry Andric     if (!isImm())
9580b57cec5SDimitry Andric       return false;
9590b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
9600b57cec5SDimitry Andric     if (!IsConstantImm) {
961e8d8bef9SDimitry Andric       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
9620b57cec5SDimitry Andric       return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
9630b57cec5SDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
9640b57cec5SDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
9657a6dacacSDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
9667a6dacacSDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
9677a6dacacSDimitry Andric     }
9687a6dacacSDimitry Andric 
9690b57cec5SDimitry Andric     return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
9700b57cec5SDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
9710b57cec5SDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
9720b57cec5SDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
9737a6dacacSDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
9747a6dacacSDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
9750b57cec5SDimitry Andric   }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric   bool isImmZero() const {
9800b57cec5SDimitry Andric     if (!isImm())
9810b57cec5SDimitry Andric       return false;
9820b57cec5SDimitry Andric     int64_t Imm;
9830b57cec5SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9840b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
9850b57cec5SDimitry Andric     return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
9860b57cec5SDimitry Andric   }
9870b57cec5SDimitry Andric 
9885ffd83dbSDimitry Andric   bool isSImm5Plus1() const {
9895ffd83dbSDimitry Andric     if (!isImm())
9905ffd83dbSDimitry Andric       return false;
9915ffd83dbSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9925ffd83dbSDimitry Andric     int64_t Imm;
9935ffd83dbSDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
99406c3fb27SDimitry Andric     return IsConstantImm &&
99506c3fb27SDimitry Andric            isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
9965ffd83dbSDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
9975ffd83dbSDimitry Andric   }
9985ffd83dbSDimitry Andric 
9990b57cec5SDimitry Andric   /// getStartLoc - Gets location of the first token of this operand
10000b57cec5SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
10010b57cec5SDimitry Andric   /// getEndLoc - Gets location of the last token of this operand
10020b57cec5SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
10030b57cec5SDimitry Andric   /// True if this operand is for an RV64 instruction
100406c3fb27SDimitry Andric   bool isRV64Imm() const {
100506c3fb27SDimitry Andric     assert(Kind == KindTy::Immediate && "Invalid type access!");
100606c3fb27SDimitry Andric     return Imm.IsRV64;
100706c3fb27SDimitry Andric   }
10080b57cec5SDimitry Andric 
1009*0fca6ea1SDimitry Andric   MCRegister getReg() const override {
10108bcb0991SDimitry Andric     assert(Kind == KindTy::Register && "Invalid type access!");
1011*0fca6ea1SDimitry Andric     return Reg.RegNum;
10120b57cec5SDimitry Andric   }
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   StringRef getSysReg() const {
1015e8d8bef9SDimitry Andric     assert(Kind == KindTy::SystemRegister && "Invalid type access!");
10160b57cec5SDimitry Andric     return StringRef(SysReg.Data, SysReg.Length);
10170b57cec5SDimitry Andric   }
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   const MCExpr *getImm() const {
10208bcb0991SDimitry Andric     assert(Kind == KindTy::Immediate && "Invalid type access!");
10210b57cec5SDimitry Andric     return Imm.Val;
10220b57cec5SDimitry Andric   }
10230b57cec5SDimitry Andric 
102406c3fb27SDimitry Andric   uint64_t getFPConst() const {
102506c3fb27SDimitry Andric     assert(Kind == KindTy::FPImmediate && "Invalid type access!");
102606c3fb27SDimitry Andric     return FPImm.Val;
102706c3fb27SDimitry Andric   }
102806c3fb27SDimitry Andric 
10290b57cec5SDimitry Andric   StringRef getToken() const {
10308bcb0991SDimitry Andric     assert(Kind == KindTy::Token && "Invalid type access!");
10310b57cec5SDimitry Andric     return Tok;
10320b57cec5SDimitry Andric   }
10330b57cec5SDimitry Andric 
1034e8d8bef9SDimitry Andric   unsigned getVType() const {
1035e8d8bef9SDimitry Andric     assert(Kind == KindTy::VType && "Invalid type access!");
1036e8d8bef9SDimitry Andric     return VType.Val;
10375ffd83dbSDimitry Andric   }
10385ffd83dbSDimitry Andric 
103906c3fb27SDimitry Andric   RISCVFPRndMode::RoundingMode getFRM() const {
104006c3fb27SDimitry Andric     assert(Kind == KindTy::FRM && "Invalid type access!");
104106c3fb27SDimitry Andric     return FRM.FRM;
104206c3fb27SDimitry Andric   }
104306c3fb27SDimitry Andric 
104406c3fb27SDimitry Andric   unsigned getFence() const {
104506c3fb27SDimitry Andric     assert(Kind == KindTy::Fence && "Invalid type access!");
104606c3fb27SDimitry Andric     return Fence.Val;
104706c3fb27SDimitry Andric   }
104806c3fb27SDimitry Andric 
10490b57cec5SDimitry Andric   void print(raw_ostream &OS) const override {
1050bdd1243dSDimitry Andric     auto RegName = [](MCRegister Reg) {
1051e8d8bef9SDimitry Andric       if (Reg)
1052e8d8bef9SDimitry Andric         return RISCVInstPrinter::getRegisterName(Reg);
1053e8d8bef9SDimitry Andric       else
1054e8d8bef9SDimitry Andric         return "noreg";
1055e8d8bef9SDimitry Andric     };
1056e8d8bef9SDimitry Andric 
10570b57cec5SDimitry Andric     switch (Kind) {
10588bcb0991SDimitry Andric     case KindTy::Immediate:
10590b57cec5SDimitry Andric       OS << *getImm();
10600b57cec5SDimitry Andric       break;
106106c3fb27SDimitry Andric     case KindTy::FPImmediate:
106206c3fb27SDimitry Andric       break;
10638bcb0991SDimitry Andric     case KindTy::Register:
1064e8d8bef9SDimitry Andric       OS << "<register " << RegName(getReg()) << ">";
10650b57cec5SDimitry Andric       break;
10668bcb0991SDimitry Andric     case KindTy::Token:
10670b57cec5SDimitry Andric       OS << "'" << getToken() << "'";
10680b57cec5SDimitry Andric       break;
10698bcb0991SDimitry Andric     case KindTy::SystemRegister:
10700b57cec5SDimitry Andric       OS << "<sysreg: " << getSysReg() << '>';
10710b57cec5SDimitry Andric       break;
10725ffd83dbSDimitry Andric     case KindTy::VType:
1073e8d8bef9SDimitry Andric       OS << "<vtype: ";
1074e8d8bef9SDimitry Andric       RISCVVType::printVType(getVType(), OS);
1075e8d8bef9SDimitry Andric       OS << '>';
10765ffd83dbSDimitry Andric       break;
107706c3fb27SDimitry Andric     case KindTy::FRM:
107806c3fb27SDimitry Andric       OS << "<frm: ";
107906c3fb27SDimitry Andric       roundingModeToString(getFRM());
108006c3fb27SDimitry Andric       OS << '>';
108106c3fb27SDimitry Andric       break;
108206c3fb27SDimitry Andric     case KindTy::Fence:
108306c3fb27SDimitry Andric       OS << "<fence: ";
108406c3fb27SDimitry Andric       OS << getFence();
108506c3fb27SDimitry Andric       OS << '>';
108606c3fb27SDimitry Andric       break;
108706c3fb27SDimitry Andric     case KindTy::Rlist:
108806c3fb27SDimitry Andric       OS << "<rlist: ";
108906c3fb27SDimitry Andric       RISCVZC::printRlist(Rlist.Val, OS);
109006c3fb27SDimitry Andric       OS << '>';
109106c3fb27SDimitry Andric       break;
109206c3fb27SDimitry Andric     case KindTy::Spimm:
109306c3fb27SDimitry Andric       OS << "<Spimm: ";
1094*0fca6ea1SDimitry Andric       OS << Spimm.Val;
109506c3fb27SDimitry Andric       OS << '>';
109606c3fb27SDimitry Andric       break;
10975f757f3fSDimitry Andric     case KindTy::RegReg:
10985f757f3fSDimitry Andric       OS << "<RegReg:  Reg1 " << RegName(RegReg.Reg1);
10995f757f3fSDimitry Andric       OS << " Reg2 " << RegName(RegReg.Reg2);
11005f757f3fSDimitry Andric       break;
11010b57cec5SDimitry Andric     }
11020b57cec5SDimitry Andric   }
11030b57cec5SDimitry Andric 
110406c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
11058bcb0991SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
11060b57cec5SDimitry Andric     Op->Tok = Str;
11070b57cec5SDimitry Andric     Op->StartLoc = S;
11080b57cec5SDimitry Andric     Op->EndLoc = S;
11090b57cec5SDimitry Andric     return Op;
11100b57cec5SDimitry Andric   }
11110b57cec5SDimitry Andric 
111206c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand>
111306c3fb27SDimitry Andric   createReg(unsigned RegNo, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
11148bcb0991SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
11150b57cec5SDimitry Andric     Op->Reg.RegNum = RegNo;
111606c3fb27SDimitry Andric     Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
11170b57cec5SDimitry Andric     Op->StartLoc = S;
11180b57cec5SDimitry Andric     Op->EndLoc = E;
11190b57cec5SDimitry Andric     return Op;
11200b57cec5SDimitry Andric   }
11210b57cec5SDimitry Andric 
11220b57cec5SDimitry Andric   static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
11230b57cec5SDimitry Andric                                                  SMLoc E, bool IsRV64) {
11248bcb0991SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
11250b57cec5SDimitry Andric     Op->Imm.Val = Val;
112606c3fb27SDimitry Andric     Op->Imm.IsRV64 = IsRV64;
11270b57cec5SDimitry Andric     Op->StartLoc = S;
11280b57cec5SDimitry Andric     Op->EndLoc = E;
11290b57cec5SDimitry Andric     return Op;
11300b57cec5SDimitry Andric   }
11310b57cec5SDimitry Andric 
113206c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {
113306c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
113406c3fb27SDimitry Andric     Op->FPImm.Val = Val;
113506c3fb27SDimitry Andric     Op->StartLoc = S;
113606c3fb27SDimitry Andric     Op->EndLoc = S;
113706c3fb27SDimitry Andric     return Op;
113806c3fb27SDimitry Andric   }
113906c3fb27SDimitry Andric 
114006c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,
114106c3fb27SDimitry Andric                                                     unsigned Encoding) {
11428bcb0991SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
11430b57cec5SDimitry Andric     Op->SysReg.Data = Str.data();
11440b57cec5SDimitry Andric     Op->SysReg.Length = Str.size();
11450b57cec5SDimitry Andric     Op->SysReg.Encoding = Encoding;
11460b57cec5SDimitry Andric     Op->StartLoc = S;
11470eae32dcSDimitry Andric     Op->EndLoc = S;
11480b57cec5SDimitry Andric     return Op;
11490b57cec5SDimitry Andric   }
11500b57cec5SDimitry Andric 
115106c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand>
115206c3fb27SDimitry Andric   createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {
115306c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
115406c3fb27SDimitry Andric     Op->FRM.FRM = FRM;
115506c3fb27SDimitry Andric     Op->StartLoc = S;
115606c3fb27SDimitry Andric     Op->EndLoc = S;
115706c3fb27SDimitry Andric     return Op;
115806c3fb27SDimitry Andric   }
115906c3fb27SDimitry Andric 
116006c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {
116106c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
116206c3fb27SDimitry Andric     Op->Fence.Val = Val;
116306c3fb27SDimitry Andric     Op->StartLoc = S;
116406c3fb27SDimitry Andric     Op->EndLoc = S;
116506c3fb27SDimitry Andric     return Op;
116606c3fb27SDimitry Andric   }
116706c3fb27SDimitry Andric 
116806c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {
11695ffd83dbSDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1170e8d8bef9SDimitry Andric     Op->VType.Val = VTypeI;
11715ffd83dbSDimitry Andric     Op->StartLoc = S;
11720eae32dcSDimitry Andric     Op->EndLoc = S;
11735ffd83dbSDimitry Andric     return Op;
11745ffd83dbSDimitry Andric   }
11755ffd83dbSDimitry Andric 
117606c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createRlist(unsigned RlistEncode,
117706c3fb27SDimitry Andric                                                    SMLoc S) {
117806c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
117906c3fb27SDimitry Andric     Op->Rlist.Val = RlistEncode;
118006c3fb27SDimitry Andric     Op->StartLoc = S;
118106c3fb27SDimitry Andric     return Op;
118206c3fb27SDimitry Andric   }
118306c3fb27SDimitry Andric 
11845f757f3fSDimitry Andric   static std::unique_ptr<RISCVOperand> createRegReg(unsigned Reg1No,
11855f757f3fSDimitry Andric                                                     unsigned Reg2No, SMLoc S) {
11865f757f3fSDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
11875f757f3fSDimitry Andric     Op->RegReg.Reg1 = Reg1No;
11885f757f3fSDimitry Andric     Op->RegReg.Reg2 = Reg2No;
11895f757f3fSDimitry Andric     Op->StartLoc = S;
11905f757f3fSDimitry Andric     Op->EndLoc = S;
11915f757f3fSDimitry Andric     return Op;
11925f757f3fSDimitry Andric   }
11935f757f3fSDimitry Andric 
119406c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S) {
119506c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
119606c3fb27SDimitry Andric     Op->Spimm.Val = Spimm;
119706c3fb27SDimitry Andric     Op->StartLoc = S;
119806c3fb27SDimitry Andric     return Op;
119906c3fb27SDimitry Andric   }
120006c3fb27SDimitry Andric 
120106c3fb27SDimitry Andric   static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
12020b57cec5SDimitry Andric     assert(Expr && "Expr shouldn't be null!");
12030b57cec5SDimitry Andric     int64_t Imm = 0;
12048bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
12050b57cec5SDimitry Andric     bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
12060b57cec5SDimitry Andric 
12070b57cec5SDimitry Andric     if (IsConstant)
120806c3fb27SDimitry Andric       Inst.addOperand(
120906c3fb27SDimitry Andric           MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));
12100b57cec5SDimitry Andric     else
12110b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
12120b57cec5SDimitry Andric   }
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric   // Used by the TableGen Code
12150b57cec5SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
12160b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12170b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getReg()));
12180b57cec5SDimitry Andric   }
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
12210b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
122206c3fb27SDimitry Andric     addExpr(Inst, getImm(), isRV64Imm());
122306c3fb27SDimitry Andric   }
122406c3fb27SDimitry Andric 
122506c3fb27SDimitry Andric   void addFPImmOperands(MCInst &Inst, unsigned N) const {
122606c3fb27SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
122706c3fb27SDimitry Andric     if (isImm()) {
122806c3fb27SDimitry Andric       addExpr(Inst, getImm(), isRV64Imm());
122906c3fb27SDimitry Andric       return;
123006c3fb27SDimitry Andric     }
123106c3fb27SDimitry Andric 
123206c3fb27SDimitry Andric     int Imm = RISCVLoadFPImm::getLoadFPImm(
123306c3fb27SDimitry Andric         APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
123406c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Imm));
12350b57cec5SDimitry Andric   }
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric   void addFenceArgOperands(MCInst &Inst, unsigned N) const {
12380b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
123906c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Fence.Val));
12400b57cec5SDimitry Andric   }
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric   void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
12430b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12440b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
12450b57cec5SDimitry Andric   }
12460b57cec5SDimitry Andric 
124704eeddc0SDimitry Andric   // Support non-canonical syntax:
124804eeddc0SDimitry Andric   // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
124904eeddc0SDimitry Andric   // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
12505ffd83dbSDimitry Andric   void addVTypeIOperands(MCInst &Inst, unsigned N) const {
12515ffd83dbSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
125204eeddc0SDimitry Andric     int64_t Imm = 0;
125304eeddc0SDimitry Andric     if (Kind == KindTy::Immediate) {
125404eeddc0SDimitry Andric       RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1255*0fca6ea1SDimitry Andric       [[maybe_unused]] bool IsConstantImm =
1256*0fca6ea1SDimitry Andric           evaluateConstantImm(getImm(), Imm, VK);
125704eeddc0SDimitry Andric       assert(IsConstantImm && "Invalid VTypeI Operand!");
125804eeddc0SDimitry Andric     } else {
125904eeddc0SDimitry Andric       Imm = getVType();
126004eeddc0SDimitry Andric     }
126104eeddc0SDimitry Andric     Inst.addOperand(MCOperand::createImm(Imm));
12625ffd83dbSDimitry Andric   }
12635ffd83dbSDimitry Andric 
126406c3fb27SDimitry Andric   void addRlistOperands(MCInst &Inst, unsigned N) const {
126506c3fb27SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
126606c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Rlist.Val));
126706c3fb27SDimitry Andric   }
126806c3fb27SDimitry Andric 
12695f757f3fSDimitry Andric   void addRegRegOperands(MCInst &Inst, unsigned N) const {
1270*0fca6ea1SDimitry Andric     assert(N == 2 && "Invalid number of operands!");
12715f757f3fSDimitry Andric     Inst.addOperand(MCOperand::createReg(RegReg.Reg1));
12725f757f3fSDimitry Andric     Inst.addOperand(MCOperand::createReg(RegReg.Reg2));
12735f757f3fSDimitry Andric   }
12745f757f3fSDimitry Andric 
127506c3fb27SDimitry Andric   void addSpimmOperands(MCInst &Inst, unsigned N) const {
127606c3fb27SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
127706c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Spimm.Val));
12780b57cec5SDimitry Andric   }
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric   void addFRMArgOperands(MCInst &Inst, unsigned N) const {
12810b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
128206c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(getFRM()));
12830b57cec5SDimitry Andric   }
12840b57cec5SDimitry Andric };
12850b57cec5SDimitry Andric } // end anonymous namespace.
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric #define GET_REGISTER_MATCHER
1288480093f4SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME
12890b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
1290480093f4SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
12910b57cec5SDimitry Andric #include "RISCVGenAsmMatcher.inc"
12920b57cec5SDimitry Andric 
1293e8d8bef9SDimitry Andric static MCRegister convertFPR64ToFPR16(MCRegister Reg) {
1294e8d8bef9SDimitry Andric   assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1295e8d8bef9SDimitry Andric   return Reg - RISCV::F0_D + RISCV::F0_H;
1296e8d8bef9SDimitry Andric }
1297e8d8bef9SDimitry Andric 
1298e8d8bef9SDimitry Andric static MCRegister convertFPR64ToFPR32(MCRegister Reg) {
12998bcb0991SDimitry Andric   assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
13008bcb0991SDimitry Andric   return Reg - RISCV::F0_D + RISCV::F0_F;
13010b57cec5SDimitry Andric }
13020b57cec5SDimitry Andric 
1303fe6060f1SDimitry Andric static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
1304fe6060f1SDimitry Andric                                   unsigned Kind) {
1305fe6060f1SDimitry Andric   unsigned RegClassID;
1306fe6060f1SDimitry Andric   if (Kind == MCK_VRM2)
1307fe6060f1SDimitry Andric     RegClassID = RISCV::VRM2RegClassID;
1308fe6060f1SDimitry Andric   else if (Kind == MCK_VRM4)
1309fe6060f1SDimitry Andric     RegClassID = RISCV::VRM4RegClassID;
1310fe6060f1SDimitry Andric   else if (Kind == MCK_VRM8)
1311fe6060f1SDimitry Andric     RegClassID = RISCV::VRM8RegClassID;
1312fe6060f1SDimitry Andric   else
1313fe6060f1SDimitry Andric     return 0;
1314fe6060f1SDimitry Andric   return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
1315fe6060f1SDimitry Andric                                 &RISCVMCRegisterClasses[RegClassID]);
1316fe6060f1SDimitry Andric }
1317fe6060f1SDimitry Andric 
13180b57cec5SDimitry Andric unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
13190b57cec5SDimitry Andric                                                     unsigned Kind) {
13200b57cec5SDimitry Andric   RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
13210b57cec5SDimitry Andric   if (!Op.isReg())
13220b57cec5SDimitry Andric     return Match_InvalidOperand;
13230b57cec5SDimitry Andric 
1324e8d8bef9SDimitry Andric   MCRegister Reg = Op.getReg();
13258bcb0991SDimitry Andric   bool IsRegFPR64 =
13268bcb0991SDimitry Andric       RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
13278bcb0991SDimitry Andric   bool IsRegFPR64C =
13288bcb0991SDimitry Andric       RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1329fe6060f1SDimitry Andric   bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
13300b57cec5SDimitry Andric 
13310b57cec5SDimitry Andric   // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
13328bcb0991SDimitry Andric   // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
13338bcb0991SDimitry Andric   if ((IsRegFPR64 && Kind == MCK_FPR32) ||
13348bcb0991SDimitry Andric       (IsRegFPR64C && Kind == MCK_FPR32C)) {
13358bcb0991SDimitry Andric     Op.Reg.RegNum = convertFPR64ToFPR32(Reg);
13360b57cec5SDimitry Andric     return Match_Success;
13370b57cec5SDimitry Andric   }
1338e8d8bef9SDimitry Andric   // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1339e8d8bef9SDimitry Andric   // register from FPR64 to FPR16 if necessary.
1340e8d8bef9SDimitry Andric   if (IsRegFPR64 && Kind == MCK_FPR16) {
1341e8d8bef9SDimitry Andric     Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
1342e8d8bef9SDimitry Andric     return Match_Success;
1343e8d8bef9SDimitry Andric   }
1344fe6060f1SDimitry Andric   // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1345fe6060f1SDimitry Andric   // the register from VR to VRM2/VRM4/VRM8 if necessary.
1346fe6060f1SDimitry Andric   if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1347fe6060f1SDimitry Andric     Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1348fe6060f1SDimitry Andric     if (Op.Reg.RegNum == 0)
1349fe6060f1SDimitry Andric       return Match_InvalidOperand;
1350fe6060f1SDimitry Andric     return Match_Success;
1351fe6060f1SDimitry Andric   }
13520b57cec5SDimitry Andric   return Match_InvalidOperand;
13530b57cec5SDimitry Andric }
13540b57cec5SDimitry Andric 
135506c3fb27SDimitry Andric unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
135606c3fb27SDimitry Andric   const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
135706c3fb27SDimitry Andric 
135806c3fb27SDimitry Andric   for (unsigned I = 0; I < MCID.NumOperands; ++I) {
1359297eecfbSDimitry Andric     if (MCID.operands()[I].RegClass == RISCV::GPRPairRegClassID) {
136006c3fb27SDimitry Andric       const auto &Op = Inst.getOperand(I);
136106c3fb27SDimitry Andric       assert(Op.isReg());
136206c3fb27SDimitry Andric 
136306c3fb27SDimitry Andric       MCRegister Reg = Op.getReg();
1364297eecfbSDimitry Andric       if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(Reg))
1365297eecfbSDimitry Andric         continue;
1366297eecfbSDimitry Andric 
1367297eecfbSDimitry Andric       // FIXME: We should form a paired register during parsing/matching.
136806c3fb27SDimitry Andric       if (((Reg.id() - RISCV::X0) & 1) != 0)
136906c3fb27SDimitry Andric         return Match_RequiresEvenGPRs;
137006c3fb27SDimitry Andric     }
137106c3fb27SDimitry Andric   }
137206c3fb27SDimitry Andric 
137306c3fb27SDimitry Andric   return Match_Success;
137406c3fb27SDimitry Andric }
137506c3fb27SDimitry Andric 
137606c3fb27SDimitry Andric bool RISCVAsmParser::generateImmOutOfRangeError(
137706c3fb27SDimitry Andric     SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
137806c3fb27SDimitry Andric     const Twine &Msg = "immediate must be an integer in the range") {
137906c3fb27SDimitry Andric   return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
138006c3fb27SDimitry Andric }
138106c3fb27SDimitry Andric 
13820b57cec5SDimitry Andric bool RISCVAsmParser::generateImmOutOfRangeError(
13830b57cec5SDimitry Andric     OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
138406c3fb27SDimitry Andric     const Twine &Msg = "immediate must be an integer in the range") {
13850b57cec5SDimitry Andric   SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
138606c3fb27SDimitry Andric   return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg);
13870b57cec5SDimitry Andric }
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
13900b57cec5SDimitry Andric                                              OperandVector &Operands,
13910b57cec5SDimitry Andric                                              MCStreamer &Out,
13920b57cec5SDimitry Andric                                              uint64_t &ErrorInfo,
13930b57cec5SDimitry Andric                                              bool MatchingInlineAsm) {
13940b57cec5SDimitry Andric   MCInst Inst;
1395480093f4SDimitry Andric   FeatureBitset MissingFeatures;
13960b57cec5SDimitry Andric 
1397fe6060f1SDimitry Andric   auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1398480093f4SDimitry Andric                                      MatchingInlineAsm);
13990b57cec5SDimitry Andric   switch (Result) {
14000b57cec5SDimitry Andric   default:
14010b57cec5SDimitry Andric     break;
14020b57cec5SDimitry Andric   case Match_Success:
14035ffd83dbSDimitry Andric     if (validateInstruction(Inst, Operands))
14045ffd83dbSDimitry Andric       return true;
14050b57cec5SDimitry Andric     return processInstruction(Inst, IDLoc, Operands, Out);
1406480093f4SDimitry Andric   case Match_MissingFeature: {
1407480093f4SDimitry Andric     assert(MissingFeatures.any() && "Unknown missing features!");
1408480093f4SDimitry Andric     bool FirstFeature = true;
1409480093f4SDimitry Andric     std::string Msg = "instruction requires the following:";
1410480093f4SDimitry Andric     for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1411480093f4SDimitry Andric       if (MissingFeatures[i]) {
1412480093f4SDimitry Andric         Msg += FirstFeature ? " " : ", ";
1413480093f4SDimitry Andric         Msg += getSubtargetFeatureName(i);
1414480093f4SDimitry Andric         FirstFeature = false;
1415480093f4SDimitry Andric       }
1416480093f4SDimitry Andric     }
1417480093f4SDimitry Andric     return Error(IDLoc, Msg);
1418480093f4SDimitry Andric   }
1419480093f4SDimitry Andric   case Match_MnemonicFail: {
1420480093f4SDimitry Andric     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1421349cc55cSDimitry Andric     std::string Suggestion = RISCVMnemonicSpellCheck(
1422349cc55cSDimitry Andric         ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1423480093f4SDimitry Andric     return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1424480093f4SDimitry Andric   }
14250b57cec5SDimitry Andric   case Match_InvalidOperand: {
14260b57cec5SDimitry Andric     SMLoc ErrorLoc = IDLoc;
1427349cc55cSDimitry Andric     if (ErrorInfo != ~0ULL) {
14280b57cec5SDimitry Andric       if (ErrorInfo >= Operands.size())
14290b57cec5SDimitry Andric         return Error(ErrorLoc, "too few operands for instruction");
14300b57cec5SDimitry Andric 
14310b57cec5SDimitry Andric       ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
14320b57cec5SDimitry Andric       if (ErrorLoc == SMLoc())
14330b57cec5SDimitry Andric         ErrorLoc = IDLoc;
14340b57cec5SDimitry Andric     }
14350b57cec5SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
14360b57cec5SDimitry Andric   }
14370b57cec5SDimitry Andric   }
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric   // Handle the case when the error message is of specific type
14400b57cec5SDimitry Andric   // other than the generic Match_InvalidOperand, and the
14410b57cec5SDimitry Andric   // corresponding operand is missing.
14420b57cec5SDimitry Andric   if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
14430b57cec5SDimitry Andric     SMLoc ErrorLoc = IDLoc;
1444349cc55cSDimitry Andric     if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
14450b57cec5SDimitry Andric       return Error(ErrorLoc, "too few operands for instruction");
14460b57cec5SDimitry Andric   }
14470b57cec5SDimitry Andric 
14480b57cec5SDimitry Andric   switch (Result) {
14490b57cec5SDimitry Andric   default:
14500b57cec5SDimitry Andric     break;
145106c3fb27SDimitry Andric   case Match_RequiresEvenGPRs:
145206c3fb27SDimitry Andric     return Error(IDLoc,
145306c3fb27SDimitry Andric                  "double precision floating point operands must use even "
145406c3fb27SDimitry Andric                  "numbered X register");
14550b57cec5SDimitry Andric   case Match_InvalidImmXLenLI:
14560b57cec5SDimitry Andric     if (isRV64()) {
14570b57cec5SDimitry Andric       SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
14580b57cec5SDimitry Andric       return Error(ErrorLoc, "operand must be a constant 64-bit integer");
14590b57cec5SDimitry Andric     }
14600b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo,
14610b57cec5SDimitry Andric                                       std::numeric_limits<int32_t>::min(),
14620b57cec5SDimitry Andric                                       std::numeric_limits<uint32_t>::max());
146306c3fb27SDimitry Andric   case Match_InvalidImmXLenLI_Restricted:
146406c3fb27SDimitry Andric     if (isRV64()) {
146506c3fb27SDimitry Andric       SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
146606c3fb27SDimitry Andric       return Error(ErrorLoc, "operand either must be a constant 64-bit integer "
146706c3fb27SDimitry Andric                              "or a bare symbol name");
146806c3fb27SDimitry Andric     }
146906c3fb27SDimitry Andric     return generateImmOutOfRangeError(
147006c3fb27SDimitry Andric         Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),
147106c3fb27SDimitry Andric         std::numeric_limits<uint32_t>::max(),
147206c3fb27SDimitry Andric         "operand either must be a bare symbol name or an immediate integer in "
147306c3fb27SDimitry Andric         "the range");
14748bcb0991SDimitry Andric   case Match_InvalidImmZero: {
14758bcb0991SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
14768bcb0991SDimitry Andric     return Error(ErrorLoc, "immediate must be zero");
14778bcb0991SDimitry Andric   }
14780b57cec5SDimitry Andric   case Match_InvalidUImmLog2XLen:
14790b57cec5SDimitry Andric     if (isRV64())
14800b57cec5SDimitry Andric       return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
14810b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
14820b57cec5SDimitry Andric   case Match_InvalidUImmLog2XLenNonZero:
14830b57cec5SDimitry Andric     if (isRV64())
14840b57cec5SDimitry Andric       return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
14850b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
14865ffd83dbSDimitry Andric   case Match_InvalidUImmLog2XLenHalf:
14875ffd83dbSDimitry Andric     if (isRV64())
14885ffd83dbSDimitry Andric       return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
14895ffd83dbSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
149006c3fb27SDimitry Andric   case Match_InvalidUImm1:
149106c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
1492349cc55cSDimitry Andric   case Match_InvalidUImm2:
1493349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
149406c3fb27SDimitry Andric   case Match_InvalidUImm2Lsb0:
149506c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
149606c3fb27SDimitry Andric                                       "immediate must be one of");
1497349cc55cSDimitry Andric   case Match_InvalidUImm3:
1498349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
149906c3fb27SDimitry Andric   case Match_InvalidUImm4:
150006c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
15010b57cec5SDimitry Andric   case Match_InvalidUImm5:
15020b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
150306c3fb27SDimitry Andric   case Match_InvalidUImm6:
150406c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1505349cc55cSDimitry Andric   case Match_InvalidUImm7:
1506349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
150706c3fb27SDimitry Andric   case Match_InvalidUImm8:
150806c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
150906c3fb27SDimitry Andric   case Match_InvalidUImm8GE32:
151006c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1);
1511e8d8bef9SDimitry Andric   case Match_InvalidSImm5:
1512e8d8bef9SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1513e8d8bef9SDimitry Andric                                       (1 << 4) - 1);
15140b57cec5SDimitry Andric   case Match_InvalidSImm6:
15150b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
15160b57cec5SDimitry Andric                                       (1 << 5) - 1);
15170b57cec5SDimitry Andric   case Match_InvalidSImm6NonZero:
15180b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15190b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
15200b57cec5SDimitry Andric         "immediate must be non-zero in the range");
15210b57cec5SDimitry Andric   case Match_InvalidCLUIImm:
15220b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15230b57cec5SDimitry Andric         Operands, ErrorInfo, 1, (1 << 5) - 1,
15240b57cec5SDimitry Andric         "immediate must be in [0xfffe0, 0xfffff] or");
1525*0fca6ea1SDimitry Andric   case Match_InvalidUImm5Lsb0:
1526*0fca6ea1SDimitry Andric     return generateImmOutOfRangeError(
1527*0fca6ea1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 5) - 2,
1528*0fca6ea1SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
1529*0fca6ea1SDimitry Andric   case Match_InvalidUImm6Lsb0:
1530*0fca6ea1SDimitry Andric     return generateImmOutOfRangeError(
1531*0fca6ea1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 6) - 2,
1532*0fca6ea1SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
15330b57cec5SDimitry Andric   case Match_InvalidUImm7Lsb00:
15340b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15350b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 7) - 4,
15360b57cec5SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
15370b57cec5SDimitry Andric   case Match_InvalidUImm8Lsb00:
15380b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15390b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 4,
15400b57cec5SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
15410b57cec5SDimitry Andric   case Match_InvalidUImm8Lsb000:
15420b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15430b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 8,
15440b57cec5SDimitry Andric         "immediate must be a multiple of 8 bytes in the range");
15450b57cec5SDimitry Andric   case Match_InvalidSImm9Lsb0:
15460b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15470b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
15480b57cec5SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
15490b57cec5SDimitry Andric   case Match_InvalidUImm9Lsb000:
15500b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15510b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 9) - 8,
15520b57cec5SDimitry Andric         "immediate must be a multiple of 8 bytes in the range");
15530b57cec5SDimitry Andric   case Match_InvalidUImm10Lsb00NonZero:
15540b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15550b57cec5SDimitry Andric         Operands, ErrorInfo, 4, (1 << 10) - 4,
15560b57cec5SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
15570b57cec5SDimitry Andric   case Match_InvalidSImm10Lsb0000NonZero:
15580b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15590b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
15600b57cec5SDimitry Andric         "immediate must be a multiple of 16 bytes and non-zero in the range");
15610b57cec5SDimitry Andric   case Match_InvalidSImm12:
15620b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15630b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
15640b57cec5SDimitry Andric         "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
15650b57cec5SDimitry Andric         "integer in the range");
15660b57cec5SDimitry Andric   case Match_InvalidSImm12Lsb0:
15670b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15680b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
15690b57cec5SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
157081ad6265SDimitry Andric   case Match_InvalidSImm12Lsb00000:
157181ad6265SDimitry Andric     return generateImmOutOfRangeError(
157281ad6265SDimitry Andric         Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,
157381ad6265SDimitry Andric         "immediate must be a multiple of 32 bytes in the range");
15740b57cec5SDimitry Andric   case Match_InvalidSImm13Lsb0:
15750b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15760b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
15770b57cec5SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
15780b57cec5SDimitry Andric   case Match_InvalidUImm20LUI:
15790b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
15800b57cec5SDimitry Andric                                       "operand must be a symbol with "
15810b57cec5SDimitry Andric                                       "%hi/%tprel_hi modifier or an integer in "
15820b57cec5SDimitry Andric                                       "the range");
15835f757f3fSDimitry Andric   case Match_InvalidUImm20:
15845f757f3fSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
15850b57cec5SDimitry Andric   case Match_InvalidUImm20AUIPC:
15860b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15870b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 20) - 1,
15880b57cec5SDimitry Andric         "operand must be a symbol with a "
15890b57cec5SDimitry Andric         "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
15900b57cec5SDimitry Andric         "an integer in the range");
15910b57cec5SDimitry Andric   case Match_InvalidSImm21Lsb0JAL:
15920b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15930b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
15940b57cec5SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
15950b57cec5SDimitry Andric   case Match_InvalidCSRSystemRegister: {
15960b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
15970b57cec5SDimitry Andric                                       "operand must be a valid system register "
15980b57cec5SDimitry Andric                                       "name or an integer in the range");
15990b57cec5SDimitry Andric   }
160006c3fb27SDimitry Andric   case Match_InvalidLoadFPImm: {
16010b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
160206c3fb27SDimitry Andric     return Error(ErrorLoc, "operand must be a valid floating-point constant");
16030b57cec5SDimitry Andric   }
16040b57cec5SDimitry Andric   case Match_InvalidBareSymbol: {
16050b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16060b57cec5SDimitry Andric     return Error(ErrorLoc, "operand must be a bare symbol name");
16070b57cec5SDimitry Andric   }
16085ffd83dbSDimitry Andric   case Match_InvalidPseudoJumpSymbol: {
16095ffd83dbSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16105ffd83dbSDimitry Andric     return Error(ErrorLoc, "operand must be a valid jump target");
16115ffd83dbSDimitry Andric   }
16120b57cec5SDimitry Andric   case Match_InvalidCallSymbol: {
16130b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16140b57cec5SDimitry Andric     return Error(ErrorLoc, "operand must be a bare symbol name");
16150b57cec5SDimitry Andric   }
16160b57cec5SDimitry Andric   case Match_InvalidTPRelAddSymbol: {
16170b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16180b57cec5SDimitry Andric     return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
16190b57cec5SDimitry Andric   }
16207a6dacacSDimitry Andric   case Match_InvalidTLSDESCCallSymbol: {
16217a6dacacSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16227a6dacacSDimitry Andric     return Error(ErrorLoc,
16237a6dacacSDimitry Andric                  "operand must be a symbol with %tlsdesc_call modifier");
16247a6dacacSDimitry Andric   }
162506c3fb27SDimitry Andric   case Match_InvalidRTZArg: {
162606c3fb27SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
162706c3fb27SDimitry Andric     return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode");
162806c3fb27SDimitry Andric   }
16295ffd83dbSDimitry Andric   case Match_InvalidVTypeI: {
16305ffd83dbSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
163106c3fb27SDimitry Andric     return generateVTypeError(ErrorLoc);
16325ffd83dbSDimitry Andric   }
16335ffd83dbSDimitry Andric   case Match_InvalidVMaskRegister: {
16345ffd83dbSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16355ffd83dbSDimitry Andric     return Error(ErrorLoc, "operand must be v0.t");
16365ffd83dbSDimitry Andric   }
16375ffd83dbSDimitry Andric   case Match_InvalidSImm5Plus1: {
16385ffd83dbSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
16395ffd83dbSDimitry Andric                                       (1 << 4),
16405ffd83dbSDimitry Andric                                       "immediate must be in the range");
16415ffd83dbSDimitry Andric   }
164206c3fb27SDimitry Andric   case Match_InvalidRlist: {
164306c3fb27SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
164406c3fb27SDimitry Andric     return Error(
164506c3fb27SDimitry Andric         ErrorLoc,
164606c3fb27SDimitry Andric         "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
164706c3fb27SDimitry Andric   }
1648*0fca6ea1SDimitry Andric   case Match_InvalidStackAdj: {
164906c3fb27SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
165006c3fb27SDimitry Andric     return Error(
165106c3fb27SDimitry Andric         ErrorLoc,
165206c3fb27SDimitry Andric         "stack adjustment is invalid for this instruction and register list; "
165306c3fb27SDimitry Andric         "refer to Zc spec for a detailed range of stack adjustment");
165406c3fb27SDimitry Andric   }
165504eeddc0SDimitry Andric   case Match_InvalidRnumArg: {
165604eeddc0SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
165704eeddc0SDimitry Andric   }
16585f757f3fSDimitry Andric   case Match_InvalidRegReg: {
16595f757f3fSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16605f757f3fSDimitry Andric     return Error(ErrorLoc, "operands must be register and register");
16615f757f3fSDimitry Andric   }
16620b57cec5SDimitry Andric   }
16630b57cec5SDimitry Andric 
16640b57cec5SDimitry Andric   llvm_unreachable("Unknown match type detected!");
16650b57cec5SDimitry Andric }
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric // Attempts to match Name as a register (either using the default name or
16680b57cec5SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon
166906c3fb27SDimitry Andric // failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31
167006c3fb27SDimitry Andric // will be rejected.
1671*0fca6ea1SDimitry Andric MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {
167206c3fb27SDimitry Andric   MCRegister Reg = MatchRegisterName(Name);
1673e8d8bef9SDimitry Andric   // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1674e8d8bef9SDimitry Andric   // match always matches the 64-bit variant, and not the 16/32-bit one.
167506c3fb27SDimitry Andric   assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
167606c3fb27SDimitry Andric   assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
16778bcb0991SDimitry Andric   // The default FPR register class is based on the tablegen enum ordering.
1678e8d8bef9SDimitry Andric   static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
16798bcb0991SDimitry Andric   static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
168006c3fb27SDimitry Andric   if (!Reg)
168106c3fb27SDimitry Andric     Reg = MatchRegisterAltName(Name);
1682*0fca6ea1SDimitry Andric   if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)
168306c3fb27SDimitry Andric     Reg = RISCV::NoRegister;
168406c3fb27SDimitry Andric   return Reg;
16850b57cec5SDimitry Andric }
16860b57cec5SDimitry Andric 
16875f757f3fSDimitry Andric bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
16880b57cec5SDimitry Andric                                    SMLoc &EndLoc) {
16895f757f3fSDimitry Andric   if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
16905ffd83dbSDimitry Andric     return Error(StartLoc, "invalid register name");
16915ffd83dbSDimitry Andric   return false;
16925ffd83dbSDimitry Andric }
16935ffd83dbSDimitry Andric 
16945f757f3fSDimitry Andric ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
16955ffd83dbSDimitry Andric                                              SMLoc &EndLoc) {
16960b57cec5SDimitry Andric   const AsmToken &Tok = getParser().getTok();
16970b57cec5SDimitry Andric   StartLoc = Tok.getLoc();
16980b57cec5SDimitry Andric   EndLoc = Tok.getEndLoc();
16990b57cec5SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
17000b57cec5SDimitry Andric 
1701*0fca6ea1SDimitry Andric   Reg = matchRegisterNameHelper(Name);
17025f757f3fSDimitry Andric   if (!Reg)
17035f757f3fSDimitry Andric     return ParseStatus::NoMatch;
17040b57cec5SDimitry Andric 
17050b57cec5SDimitry Andric   getParser().Lex(); // Eat identifier token.
17065f757f3fSDimitry Andric   return ParseStatus::Success;
17070b57cec5SDimitry Andric }
17080b57cec5SDimitry Andric 
170906c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
17100b57cec5SDimitry Andric                                           bool AllowParens) {
17110b57cec5SDimitry Andric   SMLoc FirstS = getLoc();
17120b57cec5SDimitry Andric   bool HadParens = false;
17130b57cec5SDimitry Andric   AsmToken LParen;
17140b57cec5SDimitry Andric 
17150b57cec5SDimitry Andric   // If this is an LParen and a parenthesised register name is allowed, parse it
17160b57cec5SDimitry Andric   // atomically.
17170b57cec5SDimitry Andric   if (AllowParens && getLexer().is(AsmToken::LParen)) {
17180b57cec5SDimitry Andric     AsmToken Buf[2];
17190b57cec5SDimitry Andric     size_t ReadCount = getLexer().peekTokens(Buf);
17200b57cec5SDimitry Andric     if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
17210b57cec5SDimitry Andric       HadParens = true;
17220b57cec5SDimitry Andric       LParen = getParser().getTok();
17230b57cec5SDimitry Andric       getParser().Lex(); // Eat '('
17240b57cec5SDimitry Andric     }
17250b57cec5SDimitry Andric   }
17260b57cec5SDimitry Andric 
17270b57cec5SDimitry Andric   switch (getLexer().getKind()) {
17280b57cec5SDimitry Andric   default:
17290b57cec5SDimitry Andric     if (HadParens)
17300b57cec5SDimitry Andric       getLexer().UnLex(LParen);
173106c3fb27SDimitry Andric     return ParseStatus::NoMatch;
17320b57cec5SDimitry Andric   case AsmToken::Identifier:
17330b57cec5SDimitry Andric     StringRef Name = getLexer().getTok().getIdentifier();
1734*0fca6ea1SDimitry Andric     MCRegister RegNo = matchRegisterNameHelper(Name);
17350b57cec5SDimitry Andric 
173606c3fb27SDimitry Andric     if (!RegNo) {
17370b57cec5SDimitry Andric       if (HadParens)
17380b57cec5SDimitry Andric         getLexer().UnLex(LParen);
173906c3fb27SDimitry Andric       return ParseStatus::NoMatch;
17400b57cec5SDimitry Andric     }
17410b57cec5SDimitry Andric     if (HadParens)
174206c3fb27SDimitry Andric       Operands.push_back(RISCVOperand::createToken("(", FirstS));
17430b57cec5SDimitry Andric     SMLoc S = getLoc();
17440eae32dcSDimitry Andric     SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
17450b57cec5SDimitry Andric     getLexer().Lex();
174606c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
17470b57cec5SDimitry Andric   }
17480b57cec5SDimitry Andric 
17490b57cec5SDimitry Andric   if (HadParens) {
17500b57cec5SDimitry Andric     getParser().Lex(); // Eat ')'
175106c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createToken(")", getLoc()));
17520b57cec5SDimitry Andric   }
17530b57cec5SDimitry Andric 
175406c3fb27SDimitry Andric   return ParseStatus::Success;
17550b57cec5SDimitry Andric }
17560b57cec5SDimitry Andric 
175706c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
17580eae32dcSDimitry Andric   SMLoc S = getLoc();
17590eae32dcSDimitry Andric   SMLoc E;
17600eae32dcSDimitry Andric   const MCExpr *Res;
17610eae32dcSDimitry Andric 
17620eae32dcSDimitry Andric   switch (getLexer().getKind()) {
17630eae32dcSDimitry Andric   default:
176406c3fb27SDimitry Andric     return ParseStatus::NoMatch;
17650eae32dcSDimitry Andric   case AsmToken::LParen:
17660eae32dcSDimitry Andric   case AsmToken::Minus:
17670eae32dcSDimitry Andric   case AsmToken::Plus:
17680eae32dcSDimitry Andric   case AsmToken::Exclaim:
17690eae32dcSDimitry Andric   case AsmToken::Tilde:
17700eae32dcSDimitry Andric   case AsmToken::Integer:
17710eae32dcSDimitry Andric   case AsmToken::String: {
17720eae32dcSDimitry Andric     if (getParser().parseExpression(Res, E))
177306c3fb27SDimitry Andric       return ParseStatus::Failure;
17740eae32dcSDimitry Andric 
17750eae32dcSDimitry Andric     auto *CE = dyn_cast<MCConstantExpr>(Res);
17760eae32dcSDimitry Andric     if (CE) {
17770eae32dcSDimitry Andric       int64_t Imm = CE->getValue();
17780eae32dcSDimitry Andric       if (isUInt<7>(Imm)) {
17790eae32dcSDimitry Andric         Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
178006c3fb27SDimitry Andric         return ParseStatus::Success;
17810eae32dcSDimitry Andric       }
17820eae32dcSDimitry Andric     }
17830eae32dcSDimitry Andric 
178406c3fb27SDimitry Andric     break;
17850eae32dcSDimitry Andric   }
17860eae32dcSDimitry Andric   case AsmToken::Identifier: {
17870eae32dcSDimitry Andric     StringRef Identifier;
17880eae32dcSDimitry Andric     if (getParser().parseIdentifier(Identifier))
178906c3fb27SDimitry Andric       return ParseStatus::Failure;
17900eae32dcSDimitry Andric 
17910eae32dcSDimitry Andric     auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
17920eae32dcSDimitry Andric     if (Opcode) {
179306c3fb27SDimitry Andric       assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
179406c3fb27SDimitry Andric              "Unexpected opcode");
17950eae32dcSDimitry Andric       Res = MCConstantExpr::create(Opcode->Value, getContext());
17960eae32dcSDimitry Andric       E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
17970eae32dcSDimitry Andric       Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
179806c3fb27SDimitry Andric       return ParseStatus::Success;
17990eae32dcSDimitry Andric     }
18000eae32dcSDimitry Andric 
180106c3fb27SDimitry Andric     break;
180206c3fb27SDimitry Andric   }
180306c3fb27SDimitry Andric   case AsmToken::Percent:
180406c3fb27SDimitry Andric     break;
180506c3fb27SDimitry Andric   }
180606c3fb27SDimitry Andric 
180706c3fb27SDimitry Andric   return generateImmOutOfRangeError(
180806c3fb27SDimitry Andric       S, 0, 127,
180906c3fb27SDimitry Andric       "opcode must be a valid opcode name or an immediate in the range");
181006c3fb27SDimitry Andric }
181106c3fb27SDimitry Andric 
181206c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
181306c3fb27SDimitry Andric   SMLoc S = getLoc();
181406c3fb27SDimitry Andric   SMLoc E;
181506c3fb27SDimitry Andric   const MCExpr *Res;
181606c3fb27SDimitry Andric 
181706c3fb27SDimitry Andric   switch (getLexer().getKind()) {
181806c3fb27SDimitry Andric   default:
181906c3fb27SDimitry Andric     return ParseStatus::NoMatch;
182006c3fb27SDimitry Andric   case AsmToken::LParen:
182106c3fb27SDimitry Andric   case AsmToken::Minus:
182206c3fb27SDimitry Andric   case AsmToken::Plus:
182306c3fb27SDimitry Andric   case AsmToken::Exclaim:
182406c3fb27SDimitry Andric   case AsmToken::Tilde:
182506c3fb27SDimitry Andric   case AsmToken::Integer:
182606c3fb27SDimitry Andric   case AsmToken::String: {
182706c3fb27SDimitry Andric     if (getParser().parseExpression(Res, E))
182806c3fb27SDimitry Andric       return ParseStatus::Failure;
182906c3fb27SDimitry Andric 
183006c3fb27SDimitry Andric     auto *CE = dyn_cast<MCConstantExpr>(Res);
183106c3fb27SDimitry Andric     if (CE) {
183206c3fb27SDimitry Andric       int64_t Imm = CE->getValue();
183306c3fb27SDimitry Andric       if (Imm >= 0 && Imm <= 2) {
183406c3fb27SDimitry Andric         Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
183506c3fb27SDimitry Andric         return ParseStatus::Success;
183606c3fb27SDimitry Andric       }
183706c3fb27SDimitry Andric     }
183806c3fb27SDimitry Andric 
183906c3fb27SDimitry Andric     break;
184006c3fb27SDimitry Andric   }
184106c3fb27SDimitry Andric   case AsmToken::Identifier: {
184206c3fb27SDimitry Andric     StringRef Identifier;
184306c3fb27SDimitry Andric     if (getParser().parseIdentifier(Identifier))
184406c3fb27SDimitry Andric       return ParseStatus::Failure;
184506c3fb27SDimitry Andric 
184606c3fb27SDimitry Andric     unsigned Opcode;
184706c3fb27SDimitry Andric     if (Identifier == "C0")
184806c3fb27SDimitry Andric       Opcode = 0;
184906c3fb27SDimitry Andric     else if (Identifier == "C1")
185006c3fb27SDimitry Andric       Opcode = 1;
185106c3fb27SDimitry Andric     else if (Identifier == "C2")
185206c3fb27SDimitry Andric       Opcode = 2;
185306c3fb27SDimitry Andric     else
185406c3fb27SDimitry Andric       break;
185506c3fb27SDimitry Andric 
185606c3fb27SDimitry Andric     Res = MCConstantExpr::create(Opcode, getContext());
185706c3fb27SDimitry Andric     E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
185806c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
185906c3fb27SDimitry Andric     return ParseStatus::Success;
18600eae32dcSDimitry Andric   }
18610eae32dcSDimitry Andric   case AsmToken::Percent: {
18620eae32dcSDimitry Andric     // Discard operand with modifier.
186306c3fb27SDimitry Andric     break;
18640eae32dcSDimitry Andric   }
18650eae32dcSDimitry Andric   }
18660eae32dcSDimitry Andric 
186706c3fb27SDimitry Andric   return generateImmOutOfRangeError(
186806c3fb27SDimitry Andric       S, 0, 2,
186906c3fb27SDimitry Andric       "opcode must be a valid opcode name or an immediate in the range");
18700eae32dcSDimitry Andric }
18710eae32dcSDimitry Andric 
187206c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
18730b57cec5SDimitry Andric   SMLoc S = getLoc();
18740b57cec5SDimitry Andric   const MCExpr *Res;
18750b57cec5SDimitry Andric 
18760b57cec5SDimitry Andric   switch (getLexer().getKind()) {
18770b57cec5SDimitry Andric   default:
187806c3fb27SDimitry Andric     return ParseStatus::NoMatch;
18790b57cec5SDimitry Andric   case AsmToken::LParen:
18800b57cec5SDimitry Andric   case AsmToken::Minus:
18810b57cec5SDimitry Andric   case AsmToken::Plus:
18820b57cec5SDimitry Andric   case AsmToken::Exclaim:
18830b57cec5SDimitry Andric   case AsmToken::Tilde:
18840b57cec5SDimitry Andric   case AsmToken::Integer:
18850b57cec5SDimitry Andric   case AsmToken::String: {
18860b57cec5SDimitry Andric     if (getParser().parseExpression(Res))
188706c3fb27SDimitry Andric       return ParseStatus::Failure;
18880b57cec5SDimitry Andric 
18890b57cec5SDimitry Andric     auto *CE = dyn_cast<MCConstantExpr>(Res);
18900b57cec5SDimitry Andric     if (CE) {
18910b57cec5SDimitry Andric       int64_t Imm = CE->getValue();
18920b57cec5SDimitry Andric       if (isUInt<12>(Imm)) {
1893*0fca6ea1SDimitry Andric         auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1894*0fca6ea1SDimitry Andric         // Accept an immediate representing a named Sys Reg if it satisfies the
1895*0fca6ea1SDimitry Andric         // the required features.
1896*0fca6ea1SDimitry Andric         for (auto &Reg : Range) {
1897*0fca6ea1SDimitry Andric           if (Reg.haveRequiredFeatures(STI->getFeatureBits())) {
1898*0fca6ea1SDimitry Andric             Operands.push_back(RISCVOperand::createSysReg(Reg.Name, S, Imm));
1899*0fca6ea1SDimitry Andric             return ParseStatus::Success;
1900*0fca6ea1SDimitry Andric           }
1901*0fca6ea1SDimitry Andric         }
1902*0fca6ea1SDimitry Andric         // Accept an immediate representing an un-named Sys Reg if the range is
1903*0fca6ea1SDimitry Andric         // valid, regardless of the required features.
1904*0fca6ea1SDimitry Andric         Operands.push_back(RISCVOperand::createSysReg("", S, Imm));
190506c3fb27SDimitry Andric         return ParseStatus::Success;
19060b57cec5SDimitry Andric       }
19070b57cec5SDimitry Andric     }
19080b57cec5SDimitry Andric 
190906c3fb27SDimitry Andric     return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
19100b57cec5SDimitry Andric   }
19110b57cec5SDimitry Andric   case AsmToken::Identifier: {
19120b57cec5SDimitry Andric     StringRef Identifier;
19130b57cec5SDimitry Andric     if (getParser().parseIdentifier(Identifier))
191406c3fb27SDimitry Andric       return ParseStatus::Failure;
191506c3fb27SDimitry Andric 
19160b57cec5SDimitry Andric     auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
19175ffd83dbSDimitry Andric     if (!SysReg)
1918647cbc5dSDimitry Andric       SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1919647cbc5dSDimitry Andric     if (!SysReg)
1920fe6060f1SDimitry Andric       if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1921fe6060f1SDimitry Andric         Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1922fe6060f1SDimitry Andric                        SysReg->Name + "'");
1923fe6060f1SDimitry Andric 
19240b57cec5SDimitry Andric     // Accept a named Sys Reg if the required features are present.
19250b57cec5SDimitry Andric     if (SysReg) {
192606c3fb27SDimitry Andric       if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits()))
192706c3fb27SDimitry Andric         return Error(S, "system register use requires an option to be enabled");
192806c3fb27SDimitry Andric       Operands.push_back(
192906c3fb27SDimitry Andric           RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
193006c3fb27SDimitry Andric       return ParseStatus::Success;
19310b57cec5SDimitry Andric     }
19320b57cec5SDimitry Andric 
193306c3fb27SDimitry Andric     return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
193406c3fb27SDimitry Andric                                       "operand must be a valid system register "
193506c3fb27SDimitry Andric                                       "name or an integer in the range");
19360b57cec5SDimitry Andric   }
19370b57cec5SDimitry Andric   case AsmToken::Percent: {
19380b57cec5SDimitry Andric     // Discard operand with modifier.
193906c3fb27SDimitry Andric     return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
19400b57cec5SDimitry Andric   }
19410b57cec5SDimitry Andric   }
19420b57cec5SDimitry Andric 
194306c3fb27SDimitry Andric   return ParseStatus::NoMatch;
19440b57cec5SDimitry Andric }
19450b57cec5SDimitry Andric 
194606c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
194706c3fb27SDimitry Andric   SMLoc S = getLoc();
194806c3fb27SDimitry Andric 
194906c3fb27SDimitry Andric   // Parse special floats (inf/nan/min) representation.
195006c3fb27SDimitry Andric   if (getTok().is(AsmToken::Identifier)) {
195106c3fb27SDimitry Andric     StringRef Identifier = getTok().getIdentifier();
195206c3fb27SDimitry Andric     if (Identifier.compare_insensitive("inf") == 0) {
195306c3fb27SDimitry Andric       Operands.push_back(
195406c3fb27SDimitry Andric           RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,
195506c3fb27SDimitry Andric                                   getTok().getEndLoc(), isRV64()));
195606c3fb27SDimitry Andric     } else if (Identifier.compare_insensitive("nan") == 0) {
195706c3fb27SDimitry Andric       Operands.push_back(
195806c3fb27SDimitry Andric           RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,
195906c3fb27SDimitry Andric                                   getTok().getEndLoc(), isRV64()));
196006c3fb27SDimitry Andric     } else if (Identifier.compare_insensitive("min") == 0) {
196106c3fb27SDimitry Andric       Operands.push_back(
196206c3fb27SDimitry Andric           RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S,
196306c3fb27SDimitry Andric                                   getTok().getEndLoc(), isRV64()));
196406c3fb27SDimitry Andric     } else {
196506c3fb27SDimitry Andric       return TokError("invalid floating point literal");
196606c3fb27SDimitry Andric     }
196706c3fb27SDimitry Andric 
196806c3fb27SDimitry Andric     Lex(); // Eat the token.
196906c3fb27SDimitry Andric 
197006c3fb27SDimitry Andric     return ParseStatus::Success;
197106c3fb27SDimitry Andric   }
197206c3fb27SDimitry Andric 
197306c3fb27SDimitry Andric   // Handle negation, as that still comes through as a separate token.
197406c3fb27SDimitry Andric   bool IsNegative = parseOptionalToken(AsmToken::Minus);
197506c3fb27SDimitry Andric 
197606c3fb27SDimitry Andric   const AsmToken &Tok = getTok();
197706c3fb27SDimitry Andric   if (!Tok.is(AsmToken::Real))
197806c3fb27SDimitry Andric     return TokError("invalid floating point immediate");
197906c3fb27SDimitry Andric 
198006c3fb27SDimitry Andric   // Parse FP representation.
198106c3fb27SDimitry Andric   APFloat RealVal(APFloat::IEEEdouble());
198206c3fb27SDimitry Andric   auto StatusOrErr =
198306c3fb27SDimitry Andric       RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
198406c3fb27SDimitry Andric   if (errorToBool(StatusOrErr.takeError()))
198506c3fb27SDimitry Andric     return TokError("invalid floating point representation");
198606c3fb27SDimitry Andric 
198706c3fb27SDimitry Andric   if (IsNegative)
198806c3fb27SDimitry Andric     RealVal.changeSign();
198906c3fb27SDimitry Andric 
199006c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createFPImm(
199106c3fb27SDimitry Andric       RealVal.bitcastToAPInt().getZExtValue(), S));
199206c3fb27SDimitry Andric 
199306c3fb27SDimitry Andric   Lex(); // Eat the token.
199406c3fb27SDimitry Andric 
199506c3fb27SDimitry Andric   return ParseStatus::Success;
199606c3fb27SDimitry Andric }
199706c3fb27SDimitry Andric 
199806c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseImmediate(OperandVector &Operands) {
19990b57cec5SDimitry Andric   SMLoc S = getLoc();
20000eae32dcSDimitry Andric   SMLoc E;
20010b57cec5SDimitry Andric   const MCExpr *Res;
20020b57cec5SDimitry Andric 
20030b57cec5SDimitry Andric   switch (getLexer().getKind()) {
20040b57cec5SDimitry Andric   default:
200506c3fb27SDimitry Andric     return ParseStatus::NoMatch;
20060b57cec5SDimitry Andric   case AsmToken::LParen:
20070b57cec5SDimitry Andric   case AsmToken::Dot:
20080b57cec5SDimitry Andric   case AsmToken::Minus:
20090b57cec5SDimitry Andric   case AsmToken::Plus:
20100b57cec5SDimitry Andric   case AsmToken::Exclaim:
20110b57cec5SDimitry Andric   case AsmToken::Tilde:
20120b57cec5SDimitry Andric   case AsmToken::Integer:
20130b57cec5SDimitry Andric   case AsmToken::String:
20140b57cec5SDimitry Andric   case AsmToken::Identifier:
20150eae32dcSDimitry Andric     if (getParser().parseExpression(Res, E))
201606c3fb27SDimitry Andric       return ParseStatus::Failure;
20170b57cec5SDimitry Andric     break;
20180b57cec5SDimitry Andric   case AsmToken::Percent:
20190b57cec5SDimitry Andric     return parseOperandWithModifier(Operands);
20200b57cec5SDimitry Andric   }
20210b57cec5SDimitry Andric 
20220b57cec5SDimitry Andric   Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
202306c3fb27SDimitry Andric   return ParseStatus::Success;
20240b57cec5SDimitry Andric }
20250b57cec5SDimitry Andric 
202606c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
20270b57cec5SDimitry Andric   SMLoc S = getLoc();
20280eae32dcSDimitry Andric   SMLoc E;
20290b57cec5SDimitry Andric 
203006c3fb27SDimitry Andric   if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))
203106c3fb27SDimitry Andric     return ParseStatus::Failure;
20320b57cec5SDimitry Andric 
203306c3fb27SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
203406c3fb27SDimitry Andric     return Error(getLoc(), "expected valid identifier for operand modifier");
20350b57cec5SDimitry Andric   StringRef Identifier = getParser().getTok().getIdentifier();
20360b57cec5SDimitry Andric   RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
203706c3fb27SDimitry Andric   if (VK == RISCVMCExpr::VK_RISCV_Invalid)
203806c3fb27SDimitry Andric     return Error(getLoc(), "unrecognized operand modifier");
20390b57cec5SDimitry Andric 
20400b57cec5SDimitry Andric   getParser().Lex(); // Eat the identifier
204106c3fb27SDimitry Andric   if (parseToken(AsmToken::LParen, "expected '('"))
204206c3fb27SDimitry Andric     return ParseStatus::Failure;
20430b57cec5SDimitry Andric 
20440b57cec5SDimitry Andric   const MCExpr *SubExpr;
204506c3fb27SDimitry Andric   if (getParser().parseParenExpression(SubExpr, E))
204606c3fb27SDimitry Andric     return ParseStatus::Failure;
20470b57cec5SDimitry Andric 
20480b57cec5SDimitry Andric   const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
20490b57cec5SDimitry Andric   Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
205006c3fb27SDimitry Andric   return ParseStatus::Success;
20510b57cec5SDimitry Andric }
20520b57cec5SDimitry Andric 
205306c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
20540b57cec5SDimitry Andric   SMLoc S = getLoc();
20550b57cec5SDimitry Andric   const MCExpr *Res;
20560b57cec5SDimitry Andric 
20570b57cec5SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
205806c3fb27SDimitry Andric     return ParseStatus::NoMatch;
20590b57cec5SDimitry Andric 
20600b57cec5SDimitry Andric   StringRef Identifier;
20610b57cec5SDimitry Andric   AsmToken Tok = getLexer().getTok();
20620b57cec5SDimitry Andric 
20630b57cec5SDimitry Andric   if (getParser().parseIdentifier(Identifier))
206406c3fb27SDimitry Andric     return ParseStatus::Failure;
20650b57cec5SDimitry Andric 
20660eae32dcSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
20670eae32dcSDimitry Andric 
206806c3fb27SDimitry Andric   if (Identifier.consume_back("@plt"))
206906c3fb27SDimitry Andric     return Error(getLoc(), "'@plt' operand not valid for instruction");
20700b57cec5SDimitry Andric 
20710b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
20720b57cec5SDimitry Andric 
20730b57cec5SDimitry Andric   if (Sym->isVariable()) {
20740b57cec5SDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
20750b57cec5SDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
20760b57cec5SDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
207706c3fb27SDimitry Andric       return ParseStatus::NoMatch;
20780b57cec5SDimitry Andric     }
20790b57cec5SDimitry Andric     Res = V;
20800b57cec5SDimitry Andric   } else
20810b57cec5SDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
20820b57cec5SDimitry Andric 
20830b57cec5SDimitry Andric   MCBinaryExpr::Opcode Opcode;
20840b57cec5SDimitry Andric   switch (getLexer().getKind()) {
20850b57cec5SDimitry Andric   default:
20860b57cec5SDimitry Andric     Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
208706c3fb27SDimitry Andric     return ParseStatus::Success;
20880b57cec5SDimitry Andric   case AsmToken::Plus:
20890b57cec5SDimitry Andric     Opcode = MCBinaryExpr::Add;
2090d781ede6SDimitry Andric     getLexer().Lex();
20910b57cec5SDimitry Andric     break;
20920b57cec5SDimitry Andric   case AsmToken::Minus:
20930b57cec5SDimitry Andric     Opcode = MCBinaryExpr::Sub;
2094d781ede6SDimitry Andric     getLexer().Lex();
20950b57cec5SDimitry Andric     break;
20960b57cec5SDimitry Andric   }
20970b57cec5SDimitry Andric 
20980b57cec5SDimitry Andric   const MCExpr *Expr;
20990eae32dcSDimitry Andric   if (getParser().parseExpression(Expr, E))
210006c3fb27SDimitry Andric     return ParseStatus::Failure;
21010b57cec5SDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
21020b57cec5SDimitry Andric   Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
210306c3fb27SDimitry Andric   return ParseStatus::Success;
21040b57cec5SDimitry Andric }
21050b57cec5SDimitry Andric 
210606c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
21070b57cec5SDimitry Andric   SMLoc S = getLoc();
21080b57cec5SDimitry Andric   const MCExpr *Res;
21090b57cec5SDimitry Andric 
21100b57cec5SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
211106c3fb27SDimitry Andric     return ParseStatus::NoMatch;
21120b57cec5SDimitry Andric 
21130b57cec5SDimitry Andric   // Avoid parsing the register in `call rd, foo` as a call symbol.
21140b57cec5SDimitry Andric   if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
211506c3fb27SDimitry Andric     return ParseStatus::NoMatch;
21160b57cec5SDimitry Andric 
21170b57cec5SDimitry Andric   StringRef Identifier;
21180b57cec5SDimitry Andric   if (getParser().parseIdentifier(Identifier))
211906c3fb27SDimitry Andric     return ParseStatus::Failure;
21200b57cec5SDimitry Andric 
21210eae32dcSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
21220eae32dcSDimitry Andric 
21231db9f3b2SDimitry Andric   RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
21241db9f3b2SDimitry Andric   (void)Identifier.consume_back("@plt");
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
21270b57cec5SDimitry Andric   Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
21280b57cec5SDimitry Andric   Res = RISCVMCExpr::create(Res, Kind, getContext());
21290b57cec5SDimitry Andric   Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
213006c3fb27SDimitry Andric   return ParseStatus::Success;
21310b57cec5SDimitry Andric }
21320b57cec5SDimitry Andric 
213306c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
21345ffd83dbSDimitry Andric   SMLoc S = getLoc();
21350eae32dcSDimitry Andric   SMLoc E;
21365ffd83dbSDimitry Andric   const MCExpr *Res;
21375ffd83dbSDimitry Andric 
21380eae32dcSDimitry Andric   if (getParser().parseExpression(Res, E))
213906c3fb27SDimitry Andric     return ParseStatus::Failure;
21405ffd83dbSDimitry Andric 
21415ffd83dbSDimitry Andric   if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
21425ffd83dbSDimitry Andric       cast<MCSymbolRefExpr>(Res)->getKind() ==
214306c3fb27SDimitry Andric           MCSymbolRefExpr::VariantKind::VK_PLT)
214406c3fb27SDimitry Andric     return Error(S, "operand must be a valid jump target");
21455ffd83dbSDimitry Andric 
21465ffd83dbSDimitry Andric   Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
21475ffd83dbSDimitry Andric   Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
214806c3fb27SDimitry Andric   return ParseStatus::Success;
21495ffd83dbSDimitry Andric }
21505ffd83dbSDimitry Andric 
215106c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
21520b57cec5SDimitry Andric   // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
21530b57cec5SDimitry Andric   // both being acceptable forms. When parsing `jal ra, foo` this function
21540b57cec5SDimitry Andric   // will be called for the `ra` register operand in an attempt to match the
21550b57cec5SDimitry Andric   // single-operand alias. parseJALOffset must fail for this case. It would
21560b57cec5SDimitry Andric   // seem logical to try parse the operand using parseImmediate and return
21570b57cec5SDimitry Andric   // NoMatch if the next token is a comma (meaning we must be parsing a jal in
21580b57cec5SDimitry Andric   // the second form rather than the first). We can't do this as there's no
21590b57cec5SDimitry Andric   // way of rewinding the lexer state. Instead, return NoMatch if this operand
21600b57cec5SDimitry Andric   // is an identifier and is followed by a comma.
21610b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Identifier) &&
21620b57cec5SDimitry Andric       getLexer().peekTok().is(AsmToken::Comma))
216306c3fb27SDimitry Andric     return ParseStatus::NoMatch;
21640b57cec5SDimitry Andric 
21650b57cec5SDimitry Andric   return parseImmediate(Operands);
21660b57cec5SDimitry Andric }
21670b57cec5SDimitry Andric 
2168*0fca6ea1SDimitry Andric bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,
216906c3fb27SDimitry Andric                                      unsigned &Sew, unsigned &Lmul,
217006c3fb27SDimitry Andric                                      bool &Fractional, bool &TailAgnostic,
217106c3fb27SDimitry Andric                                      bool &MaskAgnostic) {
2172*0fca6ea1SDimitry Andric   if (Tok.isNot(AsmToken::Identifier))
2173*0fca6ea1SDimitry Andric     return true;
2174*0fca6ea1SDimitry Andric 
2175*0fca6ea1SDimitry Andric   StringRef Identifier = Tok.getIdentifier();
2176*0fca6ea1SDimitry Andric 
217706c3fb27SDimitry Andric   switch (State) {
217806c3fb27SDimitry Andric   case VTypeState_SEW:
217906c3fb27SDimitry Andric     if (!Identifier.consume_front("e"))
2180fe6060f1SDimitry Andric       break;
218106c3fb27SDimitry Andric     if (Identifier.getAsInteger(10, Sew))
218206c3fb27SDimitry Andric       break;
218306c3fb27SDimitry Andric     if (!RISCVVType::isValidSEW(Sew))
218406c3fb27SDimitry Andric       break;
218506c3fb27SDimitry Andric     State = VTypeState_LMUL;
218606c3fb27SDimitry Andric     return false;
218706c3fb27SDimitry Andric   case VTypeState_LMUL: {
218806c3fb27SDimitry Andric     if (!Identifier.consume_front("m"))
218906c3fb27SDimitry Andric       break;
219006c3fb27SDimitry Andric     Fractional = Identifier.consume_front("f");
219106c3fb27SDimitry Andric     if (Identifier.getAsInteger(10, Lmul))
219206c3fb27SDimitry Andric       break;
219306c3fb27SDimitry Andric     if (!RISCVVType::isValidLMUL(Lmul, Fractional))
219406c3fb27SDimitry Andric       break;
2195*0fca6ea1SDimitry Andric 
2196*0fca6ea1SDimitry Andric     if (Fractional) {
2197*0fca6ea1SDimitry Andric       unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2198*0fca6ea1SDimitry Andric       unsigned MinLMUL = ELEN / 8;
2199*0fca6ea1SDimitry Andric       if (Lmul > MinLMUL)
2200*0fca6ea1SDimitry Andric         Warning(Tok.getLoc(),
2201*0fca6ea1SDimitry Andric                 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2202*0fca6ea1SDimitry Andric                     Twine(MinLMUL) + " is reserved");
2203*0fca6ea1SDimitry Andric     }
2204*0fca6ea1SDimitry Andric 
220506c3fb27SDimitry Andric     State = VTypeState_TailPolicy;
220606c3fb27SDimitry Andric     return false;
220706c3fb27SDimitry Andric   }
220806c3fb27SDimitry Andric   case VTypeState_TailPolicy:
220906c3fb27SDimitry Andric     if (Identifier == "ta")
221006c3fb27SDimitry Andric       TailAgnostic = true;
221106c3fb27SDimitry Andric     else if (Identifier == "tu")
221206c3fb27SDimitry Andric       TailAgnostic = false;
221306c3fb27SDimitry Andric     else
221406c3fb27SDimitry Andric       break;
221506c3fb27SDimitry Andric     State = VTypeState_MaskPolicy;
221606c3fb27SDimitry Andric     return false;
221706c3fb27SDimitry Andric   case VTypeState_MaskPolicy:
221806c3fb27SDimitry Andric     if (Identifier == "ma")
221906c3fb27SDimitry Andric       MaskAgnostic = true;
222006c3fb27SDimitry Andric     else if (Identifier == "mu")
222106c3fb27SDimitry Andric       MaskAgnostic = false;
222206c3fb27SDimitry Andric     else
222306c3fb27SDimitry Andric       break;
222406c3fb27SDimitry Andric     State = VTypeState_Done;
222506c3fb27SDimitry Andric     return false;
222606c3fb27SDimitry Andric   case VTypeState_Done:
222706c3fb27SDimitry Andric     // Extra token?
222806c3fb27SDimitry Andric     break;
222906c3fb27SDimitry Andric   }
223006c3fb27SDimitry Andric 
223106c3fb27SDimitry Andric   return true;
223206c3fb27SDimitry Andric }
223306c3fb27SDimitry Andric 
223406c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
223506c3fb27SDimitry Andric   SMLoc S = getLoc();
223606c3fb27SDimitry Andric 
223706c3fb27SDimitry Andric   unsigned Sew = 0;
223806c3fb27SDimitry Andric   unsigned Lmul = 0;
223906c3fb27SDimitry Andric   bool Fractional = false;
224006c3fb27SDimitry Andric   bool TailAgnostic = false;
224106c3fb27SDimitry Andric   bool MaskAgnostic = false;
224206c3fb27SDimitry Andric 
224306c3fb27SDimitry Andric   VTypeState State = VTypeState_SEW;
2244*0fca6ea1SDimitry Andric   SMLoc SEWLoc = S;
224506c3fb27SDimitry Andric 
2246*0fca6ea1SDimitry Andric   if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
224706c3fb27SDimitry Andric                       MaskAgnostic))
224806c3fb27SDimitry Andric     return ParseStatus::NoMatch;
224906c3fb27SDimitry Andric 
225006c3fb27SDimitry Andric   getLexer().Lex();
225106c3fb27SDimitry Andric 
225206c3fb27SDimitry Andric   while (parseOptionalToken(AsmToken::Comma)) {
2253*0fca6ea1SDimitry Andric     if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
225406c3fb27SDimitry Andric                         MaskAgnostic))
225506c3fb27SDimitry Andric       break;
225606c3fb27SDimitry Andric 
2257fe6060f1SDimitry Andric     getLexer().Lex();
2258fe6060f1SDimitry Andric   }
2259fe6060f1SDimitry Andric 
226006c3fb27SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) {
226181ad6265SDimitry Andric     RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);
2262*0fca6ea1SDimitry Andric     if (Fractional) {
2263*0fca6ea1SDimitry Andric       unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2264*0fca6ea1SDimitry Andric       unsigned MaxSEW = ELEN / Lmul;
2265*0fca6ea1SDimitry Andric       // If MaxSEW < 8, we should have printed warning about reserved LMUL.
2266*0fca6ea1SDimitry Andric       if (MaxSEW >= 8 && Sew > MaxSEW)
2267*0fca6ea1SDimitry Andric         Warning(SEWLoc,
2268*0fca6ea1SDimitry Andric                 "use of vtype encodings with SEW > " + Twine(MaxSEW) +
2269*0fca6ea1SDimitry Andric                     " and LMUL == mf" + Twine(Lmul) +
2270*0fca6ea1SDimitry Andric                     " may not be compatible with all RVV implementations");
2271*0fca6ea1SDimitry Andric     }
2272e8d8bef9SDimitry Andric 
2273e8d8bef9SDimitry Andric     unsigned VTypeI =
2274fe6060f1SDimitry Andric         RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);
227506c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createVType(VTypeI, S));
227606c3fb27SDimitry Andric     return ParseStatus::Success;
22775ffd83dbSDimitry Andric   }
22785ffd83dbSDimitry Andric 
227906c3fb27SDimitry Andric   return generateVTypeError(S);
2280fe6060f1SDimitry Andric }
2281fe6060f1SDimitry Andric 
228206c3fb27SDimitry Andric bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
228306c3fb27SDimitry Andric   return Error(
228406c3fb27SDimitry Andric       ErrorLoc,
228506c3fb27SDimitry Andric       "operand must be "
2286*0fca6ea1SDimitry Andric       "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
228706c3fb27SDimitry Andric }
228806c3fb27SDimitry Andric 
228906c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
229006c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
229106c3fb27SDimitry Andric     return ParseStatus::NoMatch;
229206c3fb27SDimitry Andric 
22935ffd83dbSDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
229406c3fb27SDimitry Andric   if (!Name.consume_back(".t"))
229506c3fb27SDimitry Andric     return Error(getLoc(), "expected '.t' suffix");
2296*0fca6ea1SDimitry Andric   MCRegister RegNo = matchRegisterNameHelper(Name);
22975ffd83dbSDimitry Andric 
229806c3fb27SDimitry Andric   if (!RegNo)
229906c3fb27SDimitry Andric     return ParseStatus::NoMatch;
23005ffd83dbSDimitry Andric   if (RegNo != RISCV::V0)
230106c3fb27SDimitry Andric     return ParseStatus::NoMatch;
23025ffd83dbSDimitry Andric   SMLoc S = getLoc();
23030eae32dcSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
23045ffd83dbSDimitry Andric   getLexer().Lex();
230506c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
230606c3fb27SDimitry Andric   return ParseStatus::Success;
23075ffd83dbSDimitry Andric }
23085ffd83dbSDimitry Andric 
230906c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
231006c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
231106c3fb27SDimitry Andric     return ParseStatus::NoMatch;
23125ffd83dbSDimitry Andric 
2313d56accc7SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
2314*0fca6ea1SDimitry Andric   MCRegister RegNo = matchRegisterNameHelper(Name);
2315d56accc7SDimitry Andric 
231606c3fb27SDimitry Andric   if (!RegNo)
231706c3fb27SDimitry Andric     return ParseStatus::NoMatch;
2318d56accc7SDimitry Andric   SMLoc S = getLoc();
231906c3fb27SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2320d56accc7SDimitry Andric   getLexer().Lex();
2321d56accc7SDimitry Andric   Operands.push_back(RISCVOperand::createReg(
232206c3fb27SDimitry Andric       RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
232306c3fb27SDimitry Andric   return ParseStatus::Success;
2324d56accc7SDimitry Andric }
2325d56accc7SDimitry Andric 
2326297eecfbSDimitry Andric template <bool IsRV64>
2327297eecfbSDimitry Andric ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2328297eecfbSDimitry Andric   return parseGPRPair(Operands, IsRV64);
2329297eecfbSDimitry Andric }
2330297eecfbSDimitry Andric 
2331297eecfbSDimitry Andric ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2332297eecfbSDimitry Andric                                          bool IsRV64Inst) {
2333297eecfbSDimitry Andric   // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2334297eecfbSDimitry Andric   // RV64 as it will prevent matching the RV64 version of the same instruction
2335297eecfbSDimitry Andric   // that doesn't use a GPRPair.
2336297eecfbSDimitry Andric   // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2337297eecfbSDimitry Andric   // still parse as a pair.
2338297eecfbSDimitry Andric   if (!IsRV64Inst && isRV64())
2339297eecfbSDimitry Andric     return ParseStatus::NoMatch;
2340297eecfbSDimitry Andric 
2341297eecfbSDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
2342297eecfbSDimitry Andric     return ParseStatus::NoMatch;
2343297eecfbSDimitry Andric 
2344297eecfbSDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
2345*0fca6ea1SDimitry Andric   MCRegister RegNo = matchRegisterNameHelper(Name);
2346297eecfbSDimitry Andric 
2347297eecfbSDimitry Andric   if (!RegNo)
2348297eecfbSDimitry Andric     return ParseStatus::NoMatch;
2349297eecfbSDimitry Andric 
2350297eecfbSDimitry Andric   if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(RegNo))
2351297eecfbSDimitry Andric     return ParseStatus::NoMatch;
2352297eecfbSDimitry Andric 
2353297eecfbSDimitry Andric   if ((RegNo - RISCV::X0) & 1)
2354297eecfbSDimitry Andric     return TokError("register must be even");
2355297eecfbSDimitry Andric 
2356297eecfbSDimitry Andric   SMLoc S = getLoc();
2357297eecfbSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2358297eecfbSDimitry Andric   getLexer().Lex();
2359297eecfbSDimitry Andric 
2360297eecfbSDimitry Andric   const MCRegisterInfo *RI = getContext().getRegisterInfo();
2361297eecfbSDimitry Andric   unsigned Pair = RI->getMatchingSuperReg(
2362297eecfbSDimitry Andric       RegNo, RISCV::sub_gpr_even,
2363297eecfbSDimitry Andric       &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2364297eecfbSDimitry Andric   Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2365297eecfbSDimitry Andric   return ParseStatus::Success;
2366297eecfbSDimitry Andric }
2367297eecfbSDimitry Andric 
236806c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
236906c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
237006c3fb27SDimitry Andric     return TokError(
237106c3fb27SDimitry Andric         "operand must be a valid floating point rounding mode mnemonic");
237206c3fb27SDimitry Andric 
237306c3fb27SDimitry Andric   StringRef Str = getLexer().getTok().getIdentifier();
237406c3fb27SDimitry Andric   RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str);
237506c3fb27SDimitry Andric 
237606c3fb27SDimitry Andric   if (FRM == RISCVFPRndMode::Invalid)
237706c3fb27SDimitry Andric     return TokError(
237806c3fb27SDimitry Andric         "operand must be a valid floating point rounding mode mnemonic");
237906c3fb27SDimitry Andric 
238006c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
238106c3fb27SDimitry Andric   Lex(); // Eat identifier token.
238206c3fb27SDimitry Andric   return ParseStatus::Success;
23830b57cec5SDimitry Andric }
23840b57cec5SDimitry Andric 
238506c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
238606c3fb27SDimitry Andric   const AsmToken &Tok = getLexer().getTok();
23870b57cec5SDimitry Andric 
238806c3fb27SDimitry Andric   if (Tok.is(AsmToken::Integer)) {
238906c3fb27SDimitry Andric     if (Tok.getIntVal() != 0)
239006c3fb27SDimitry Andric       goto ParseFail;
239106c3fb27SDimitry Andric 
239206c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
239306c3fb27SDimitry Andric     Lex();
239406c3fb27SDimitry Andric     return ParseStatus::Success;
23950b57cec5SDimitry Andric   }
23960b57cec5SDimitry Andric 
239706c3fb27SDimitry Andric   if (Tok.is(AsmToken::Identifier)) {
239806c3fb27SDimitry Andric     StringRef Str = Tok.getIdentifier();
239906c3fb27SDimitry Andric 
240006c3fb27SDimitry Andric     // Letters must be unique, taken from 'iorw', and in ascending order. This
240106c3fb27SDimitry Andric     // holds as long as each individual character is one of 'iorw' and is
240206c3fb27SDimitry Andric     // greater than the previous character.
240306c3fb27SDimitry Andric     unsigned Imm = 0;
240406c3fb27SDimitry Andric     bool Valid = true;
240506c3fb27SDimitry Andric     char Prev = '\0';
240606c3fb27SDimitry Andric     for (char c : Str) {
240706c3fb27SDimitry Andric       switch (c) {
240806c3fb27SDimitry Andric       default:
240906c3fb27SDimitry Andric         Valid = false;
241006c3fb27SDimitry Andric         break;
241106c3fb27SDimitry Andric       case 'i':
241206c3fb27SDimitry Andric         Imm |= RISCVFenceField::I;
241306c3fb27SDimitry Andric         break;
241406c3fb27SDimitry Andric       case 'o':
241506c3fb27SDimitry Andric         Imm |= RISCVFenceField::O;
241606c3fb27SDimitry Andric         break;
241706c3fb27SDimitry Andric       case 'r':
241806c3fb27SDimitry Andric         Imm |= RISCVFenceField::R;
241906c3fb27SDimitry Andric         break;
242006c3fb27SDimitry Andric       case 'w':
242106c3fb27SDimitry Andric         Imm |= RISCVFenceField::W;
242206c3fb27SDimitry Andric         break;
24230b57cec5SDimitry Andric       }
24240b57cec5SDimitry Andric 
242506c3fb27SDimitry Andric       if (c <= Prev) {
242606c3fb27SDimitry Andric         Valid = false;
242706c3fb27SDimitry Andric         break;
242806c3fb27SDimitry Andric       }
242906c3fb27SDimitry Andric       Prev = c;
24300b57cec5SDimitry Andric     }
24310b57cec5SDimitry Andric 
243206c3fb27SDimitry Andric     if (!Valid)
243306c3fb27SDimitry Andric       goto ParseFail;
243406c3fb27SDimitry Andric 
243506c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
243606c3fb27SDimitry Andric     Lex();
243706c3fb27SDimitry Andric     return ParseStatus::Success;
243806c3fb27SDimitry Andric   }
243906c3fb27SDimitry Andric 
244006c3fb27SDimitry Andric ParseFail:
244106c3fb27SDimitry Andric   return TokError("operand must be formed of letters selected in-order from "
244206c3fb27SDimitry Andric                   "'iorw' or be 0");
244306c3fb27SDimitry Andric }
244406c3fb27SDimitry Andric 
244506c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
244606c3fb27SDimitry Andric   if (parseToken(AsmToken::LParen, "expected '('"))
244706c3fb27SDimitry Andric     return ParseStatus::Failure;
244806c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createToken("(", getLoc()));
244906c3fb27SDimitry Andric 
245006c3fb27SDimitry Andric   if (!parseRegister(Operands).isSuccess())
245106c3fb27SDimitry Andric     return Error(getLoc(), "expected register");
245206c3fb27SDimitry Andric 
245306c3fb27SDimitry Andric   if (parseToken(AsmToken::RParen, "expected ')'"))
245406c3fb27SDimitry Andric     return ParseStatus::Failure;
245506c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createToken(")", getLoc()));
245606c3fb27SDimitry Andric 
245706c3fb27SDimitry Andric   return ParseStatus::Success;
245806c3fb27SDimitry Andric }
245906c3fb27SDimitry Andric 
246006c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
24610b57cec5SDimitry Andric   // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
24620b57cec5SDimitry Andric   // as one of their register operands, such as `(a0)`. This just denotes that
24630b57cec5SDimitry Andric   // the register (in this case `a0`) contains a memory address.
24640b57cec5SDimitry Andric   //
24650b57cec5SDimitry Andric   // Normally, we would be able to parse these by putting the parens into the
24660b57cec5SDimitry Andric   // instruction string. However, GNU as also accepts a zero-offset memory
24670b57cec5SDimitry Andric   // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
24680b57cec5SDimitry Andric   // with parseImmediate followed by parseMemOpBaseReg, but these instructions
24690b57cec5SDimitry Andric   // do not accept an immediate operand, and we do not want to add a "dummy"
24700b57cec5SDimitry Andric   // operand that is silently dropped.
24710b57cec5SDimitry Andric   //
24720b57cec5SDimitry Andric   // Instead, we use this custom parser. This will: allow (and discard) an
24730b57cec5SDimitry Andric   // offset if it is zero; require (and discard) parentheses; and add only the
24740b57cec5SDimitry Andric   // parsed register operand to `Operands`.
24750b57cec5SDimitry Andric   //
247681ad6265SDimitry Andric   // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
247781ad6265SDimitry Andric   // which will only print the register surrounded by parentheses (which GNU as
247881ad6265SDimitry Andric   // also uses as its canonical representation for these operands).
24790b57cec5SDimitry Andric   std::unique_ptr<RISCVOperand> OptionalImmOp;
24800b57cec5SDimitry Andric 
24810b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::LParen)) {
24820b57cec5SDimitry Andric     // Parse an Integer token. We do not accept arbritrary constant expressions
24830b57cec5SDimitry Andric     // in the offset field (because they may include parens, which complicates
24840b57cec5SDimitry Andric     // parsing a lot).
24850b57cec5SDimitry Andric     int64_t ImmVal;
24860b57cec5SDimitry Andric     SMLoc ImmStart = getLoc();
24870b57cec5SDimitry Andric     if (getParser().parseIntToken(ImmVal,
24880b57cec5SDimitry Andric                                   "expected '(' or optional integer offset"))
248906c3fb27SDimitry Andric       return ParseStatus::Failure;
24900b57cec5SDimitry Andric 
24910b57cec5SDimitry Andric     // Create a RISCVOperand for checking later (so the error messages are
24920b57cec5SDimitry Andric     // nicer), but we don't add it to Operands.
24930b57cec5SDimitry Andric     SMLoc ImmEnd = getLoc();
24940b57cec5SDimitry Andric     OptionalImmOp =
24950b57cec5SDimitry Andric         RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
24960b57cec5SDimitry Andric                                 ImmStart, ImmEnd, isRV64());
24970b57cec5SDimitry Andric   }
24980b57cec5SDimitry Andric 
249906c3fb27SDimitry Andric   if (parseToken(AsmToken::LParen,
250006c3fb27SDimitry Andric                  OptionalImmOp ? "expected '(' after optional integer offset"
250106c3fb27SDimitry Andric                                : "expected '(' or optional integer offset"))
250206c3fb27SDimitry Andric     return ParseStatus::Failure;
25030b57cec5SDimitry Andric 
250406c3fb27SDimitry Andric   if (!parseRegister(Operands).isSuccess())
250506c3fb27SDimitry Andric     return Error(getLoc(), "expected register");
25060b57cec5SDimitry Andric 
250706c3fb27SDimitry Andric   if (parseToken(AsmToken::RParen, "expected ')'"))
250806c3fb27SDimitry Andric     return ParseStatus::Failure;
25090b57cec5SDimitry Andric 
25100b57cec5SDimitry Andric   // Deferred Handling of non-zero offsets. This makes the error messages nicer.
251106c3fb27SDimitry Andric   if (OptionalImmOp && !OptionalImmOp->isImmZero())
251206c3fb27SDimitry Andric     return Error(
251306c3fb27SDimitry Andric         OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
25140b57cec5SDimitry Andric         SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
251506c3fb27SDimitry Andric 
251606c3fb27SDimitry Andric   return ParseStatus::Success;
25170b57cec5SDimitry Andric }
25180b57cec5SDimitry Andric 
25195f757f3fSDimitry Andric ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
25205f757f3fSDimitry Andric   // RR : a2(a1)
25215f757f3fSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
25225f757f3fSDimitry Andric     return ParseStatus::NoMatch;
25235f757f3fSDimitry Andric 
25245f757f3fSDimitry Andric   StringRef RegName = getLexer().getTok().getIdentifier();
2525*0fca6ea1SDimitry Andric   MCRegister Reg = matchRegisterNameHelper(RegName);
25265f757f3fSDimitry Andric   if (!Reg)
25275f757f3fSDimitry Andric     return Error(getLoc(), "invalid register");
25285f757f3fSDimitry Andric   getLexer().Lex();
25295f757f3fSDimitry Andric 
25305f757f3fSDimitry Andric   if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
25315f757f3fSDimitry Andric     return ParseStatus::Failure;
25325f757f3fSDimitry Andric 
25335f757f3fSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
25345f757f3fSDimitry Andric     return Error(getLoc(), "expected register");
25355f757f3fSDimitry Andric 
25365f757f3fSDimitry Andric   StringRef Reg2Name = getLexer().getTok().getIdentifier();
2537*0fca6ea1SDimitry Andric   MCRegister Reg2 = matchRegisterNameHelper(Reg2Name);
25385f757f3fSDimitry Andric   if (!Reg2)
25395f757f3fSDimitry Andric     return Error(getLoc(), "invalid register");
25405f757f3fSDimitry Andric   getLexer().Lex();
25415f757f3fSDimitry Andric 
25425f757f3fSDimitry Andric   if (parseToken(AsmToken::RParen, "expected ')'"))
25435f757f3fSDimitry Andric     return ParseStatus::Failure;
25445f757f3fSDimitry Andric 
25455f757f3fSDimitry Andric   Operands.push_back(RISCVOperand::createRegReg(Reg, Reg2, getLoc()));
25465f757f3fSDimitry Andric 
25475f757f3fSDimitry Andric   return ParseStatus::Success;
25485f757f3fSDimitry Andric }
25495f757f3fSDimitry Andric 
255006c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
255106c3fb27SDimitry Andric   // Rlist: {ra [, s0[-sN]]}
255206c3fb27SDimitry Andric   // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
255306c3fb27SDimitry Andric   SMLoc S = getLoc();
255406c3fb27SDimitry Andric 
255506c3fb27SDimitry Andric   if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
255606c3fb27SDimitry Andric     return ParseStatus::Failure;
255706c3fb27SDimitry Andric 
255806c3fb27SDimitry Andric   bool IsEABI = isRVE();
255906c3fb27SDimitry Andric 
256006c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
256106c3fb27SDimitry Andric     return Error(getLoc(), "register list must start from 'ra' or 'x1'");
256206c3fb27SDimitry Andric 
256306c3fb27SDimitry Andric   StringRef RegName = getLexer().getTok().getIdentifier();
2564*0fca6ea1SDimitry Andric   MCRegister RegStart = matchRegisterNameHelper(RegName);
256506c3fb27SDimitry Andric   MCRegister RegEnd;
256606c3fb27SDimitry Andric   if (RegStart != RISCV::X1)
256706c3fb27SDimitry Andric     return Error(getLoc(), "register list must start from 'ra' or 'x1'");
256806c3fb27SDimitry Andric   getLexer().Lex();
256906c3fb27SDimitry Andric 
257006c3fb27SDimitry Andric   // parse case like ,s0
257106c3fb27SDimitry Andric   if (parseOptionalToken(AsmToken::Comma)) {
257206c3fb27SDimitry Andric     if (getLexer().isNot(AsmToken::Identifier))
257306c3fb27SDimitry Andric       return Error(getLoc(), "invalid register");
257406c3fb27SDimitry Andric     StringRef RegName = getLexer().getTok().getIdentifier();
2575*0fca6ea1SDimitry Andric     RegStart = matchRegisterNameHelper(RegName);
257606c3fb27SDimitry Andric     if (!RegStart)
257706c3fb27SDimitry Andric       return Error(getLoc(), "invalid register");
257806c3fb27SDimitry Andric     if (RegStart != RISCV::X8)
257906c3fb27SDimitry Andric       return Error(getLoc(),
258006c3fb27SDimitry Andric                    "continuous register list must start from 's0' or 'x8'");
258106c3fb27SDimitry Andric     getLexer().Lex(); // eat reg
258206c3fb27SDimitry Andric   }
258306c3fb27SDimitry Andric 
258406c3fb27SDimitry Andric   // parse case like -s1
258506c3fb27SDimitry Andric   if (parseOptionalToken(AsmToken::Minus)) {
258606c3fb27SDimitry Andric     StringRef EndName = getLexer().getTok().getIdentifier();
258706c3fb27SDimitry Andric     // FIXME: the register mapping and checks of EABI is wrong
2588*0fca6ea1SDimitry Andric     RegEnd = matchRegisterNameHelper(EndName);
258906c3fb27SDimitry Andric     if (!RegEnd)
259006c3fb27SDimitry Andric       return Error(getLoc(), "invalid register");
259106c3fb27SDimitry Andric     if (IsEABI && RegEnd != RISCV::X9)
259206c3fb27SDimitry Andric       return Error(getLoc(), "contiguous register list of EABI can only be "
259306c3fb27SDimitry Andric                              "'s0-s1' or 'x8-x9' pair");
259406c3fb27SDimitry Andric     getLexer().Lex();
259506c3fb27SDimitry Andric   }
259606c3fb27SDimitry Andric 
259706c3fb27SDimitry Andric   if (!IsEABI) {
259806c3fb27SDimitry Andric     // parse extra part like ', x18[-x20]' for XRegList
259906c3fb27SDimitry Andric     if (parseOptionalToken(AsmToken::Comma)) {
260006c3fb27SDimitry Andric       if (RegEnd != RISCV::X9)
260106c3fb27SDimitry Andric         return Error(
260206c3fb27SDimitry Andric             getLoc(),
260306c3fb27SDimitry Andric             "first contiguous registers pair of register list must be 'x8-x9'");
260406c3fb27SDimitry Andric 
260506c3fb27SDimitry Andric       // parse ', x18' for extra part
260606c3fb27SDimitry Andric       if (getLexer().isNot(AsmToken::Identifier))
260706c3fb27SDimitry Andric         return Error(getLoc(), "invalid register");
260806c3fb27SDimitry Andric       StringRef EndName = getLexer().getTok().getIdentifier();
260906c3fb27SDimitry Andric       if (MatchRegisterName(EndName) != RISCV::X18)
261006c3fb27SDimitry Andric         return Error(getLoc(),
261106c3fb27SDimitry Andric                      "second contiguous registers pair of register list "
261206c3fb27SDimitry Andric                      "must start from 'x18'");
261306c3fb27SDimitry Andric       getLexer().Lex();
261406c3fb27SDimitry Andric 
261506c3fb27SDimitry Andric       // parse '-x20' for extra part
261606c3fb27SDimitry Andric       if (parseOptionalToken(AsmToken::Minus)) {
261706c3fb27SDimitry Andric         if (getLexer().isNot(AsmToken::Identifier))
261806c3fb27SDimitry Andric           return Error(getLoc(), "invalid register");
261906c3fb27SDimitry Andric         EndName = getLexer().getTok().getIdentifier();
262006c3fb27SDimitry Andric         if (MatchRegisterName(EndName) == RISCV::NoRegister)
262106c3fb27SDimitry Andric           return Error(getLoc(), "invalid register");
262206c3fb27SDimitry Andric         getLexer().Lex();
262306c3fb27SDimitry Andric       }
262406c3fb27SDimitry Andric       RegEnd = MatchRegisterName(EndName);
262506c3fb27SDimitry Andric     }
262606c3fb27SDimitry Andric   }
262706c3fb27SDimitry Andric 
262806c3fb27SDimitry Andric   if (RegEnd == RISCV::X26)
262906c3fb27SDimitry Andric     return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
263006c3fb27SDimitry Andric                            "x18-x26} is not supported");
263106c3fb27SDimitry Andric 
263206c3fb27SDimitry Andric   if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
263306c3fb27SDimitry Andric     return ParseStatus::Failure;
263406c3fb27SDimitry Andric 
263506c3fb27SDimitry Andric   if (RegEnd == RISCV::NoRegister)
263606c3fb27SDimitry Andric     RegEnd = RegStart;
263706c3fb27SDimitry Andric 
263806c3fb27SDimitry Andric   auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
2639*0fca6ea1SDimitry Andric   if (Encode == RISCVZC::INVALID_RLIST)
264006c3fb27SDimitry Andric     return Error(S, "invalid register list");
264106c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createRlist(Encode, S));
264206c3fb27SDimitry Andric 
264306c3fb27SDimitry Andric   return ParseStatus::Success;
264406c3fb27SDimitry Andric }
264506c3fb27SDimitry Andric 
2646*0fca6ea1SDimitry Andric ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
2647*0fca6ea1SDimitry Andric                                               bool ExpectNegative) {
2648*0fca6ea1SDimitry Andric   bool Negative = parseOptionalToken(AsmToken::Minus);
264906c3fb27SDimitry Andric 
265006c3fb27SDimitry Andric   SMLoc S = getLoc();
265106c3fb27SDimitry Andric   int64_t StackAdjustment = getLexer().getTok().getIntVal();
265206c3fb27SDimitry Andric   unsigned Spimm = 0;
265306c3fb27SDimitry Andric   unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
265406c3fb27SDimitry Andric 
2655*0fca6ea1SDimitry Andric   if (Negative != ExpectNegative ||
2656*0fca6ea1SDimitry Andric       !RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64()))
265706c3fb27SDimitry Andric     return ParseStatus::NoMatch;
265806c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
265906c3fb27SDimitry Andric   getLexer().Lex();
266006c3fb27SDimitry Andric   return ParseStatus::Success;
26610b57cec5SDimitry Andric }
26620b57cec5SDimitry Andric 
26630b57cec5SDimitry Andric /// Looks at a token type and creates the relevant operand from this
26640b57cec5SDimitry Andric /// information, adding to Operands. If operand was parsed, returns false, else
26650b57cec5SDimitry Andric /// true.
26660b57cec5SDimitry Andric bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
26670b57cec5SDimitry Andric   // Check if the current operand has a custom associated parser, if so, try to
26680b57cec5SDimitry Andric   // custom parse the operand, or fallback to the general approach.
266906c3fb27SDimitry Andric   ParseStatus Result =
26700b57cec5SDimitry Andric       MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
267106c3fb27SDimitry Andric   if (Result.isSuccess())
26720b57cec5SDimitry Andric     return false;
267306c3fb27SDimitry Andric   if (Result.isFailure())
26740b57cec5SDimitry Andric     return true;
26750b57cec5SDimitry Andric 
26760b57cec5SDimitry Andric   // Attempt to parse token as a register.
267706c3fb27SDimitry Andric   if (parseRegister(Operands, true).isSuccess())
26780b57cec5SDimitry Andric     return false;
26790b57cec5SDimitry Andric 
26800b57cec5SDimitry Andric   // Attempt to parse token as an immediate
268106c3fb27SDimitry Andric   if (parseImmediate(Operands).isSuccess()) {
26820b57cec5SDimitry Andric     // Parse memory base register if present
26830b57cec5SDimitry Andric     if (getLexer().is(AsmToken::LParen))
268406c3fb27SDimitry Andric       return !parseMemOpBaseReg(Operands).isSuccess();
26850b57cec5SDimitry Andric     return false;
26860b57cec5SDimitry Andric   }
26870b57cec5SDimitry Andric 
26880b57cec5SDimitry Andric   // Finally we have exhausted all options and must declare defeat.
26890b57cec5SDimitry Andric   Error(getLoc(), "unknown operand");
26900b57cec5SDimitry Andric   return true;
26910b57cec5SDimitry Andric }
26920b57cec5SDimitry Andric 
26930b57cec5SDimitry Andric bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
26940b57cec5SDimitry Andric                                       StringRef Name, SMLoc NameLoc,
26950b57cec5SDimitry Andric                                       OperandVector &Operands) {
26960b57cec5SDimitry Andric   // Ensure that if the instruction occurs when relaxation is enabled,
26970b57cec5SDimitry Andric   // relocations are forced for the file. Ideally this would be done when there
26980b57cec5SDimitry Andric   // is enough information to reliably determine if the instruction itself may
26990b57cec5SDimitry Andric   // cause relaxations. Unfortunately instruction processing stage occurs in the
27000b57cec5SDimitry Andric   // same pass as relocation emission, so it's too late to set a 'sticky bit'
27010b57cec5SDimitry Andric   // for the entire file.
270206c3fb27SDimitry Andric   if (getSTI().hasFeature(RISCV::FeatureRelax)) {
27030b57cec5SDimitry Andric     auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
27040b57cec5SDimitry Andric     if (Assembler != nullptr) {
27050b57cec5SDimitry Andric       RISCVAsmBackend &MAB =
27060b57cec5SDimitry Andric           static_cast<RISCVAsmBackend &>(Assembler->getBackend());
27070b57cec5SDimitry Andric       MAB.setForceRelocs();
27080b57cec5SDimitry Andric     }
27090b57cec5SDimitry Andric   }
27100b57cec5SDimitry Andric 
27110b57cec5SDimitry Andric   // First operand is token for instruction
271206c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
27130b57cec5SDimitry Andric 
27140b57cec5SDimitry Andric   // If there are no more operands, then finish
271504eeddc0SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement)) {
271604eeddc0SDimitry Andric     getParser().Lex(); // Consume the EndOfStatement.
27170b57cec5SDimitry Andric     return false;
271804eeddc0SDimitry Andric   }
27190b57cec5SDimitry Andric 
27200b57cec5SDimitry Andric   // Parse first operand
27210b57cec5SDimitry Andric   if (parseOperand(Operands, Name))
27220b57cec5SDimitry Andric     return true;
27230b57cec5SDimitry Andric 
27240b57cec5SDimitry Andric   // Parse until end of statement, consuming commas between operands
272506c3fb27SDimitry Andric   while (parseOptionalToken(AsmToken::Comma)) {
27260b57cec5SDimitry Andric     // Parse next operand
27270b57cec5SDimitry Andric     if (parseOperand(Operands, Name))
27280b57cec5SDimitry Andric       return true;
27290b57cec5SDimitry Andric   }
27300b57cec5SDimitry Andric 
273106c3fb27SDimitry Andric   if (getParser().parseEOL("unexpected token")) {
27320b57cec5SDimitry Andric     getParser().eatToEndOfStatement();
273306c3fb27SDimitry Andric     return true;
27340b57cec5SDimitry Andric   }
27350b57cec5SDimitry Andric   return false;
27360b57cec5SDimitry Andric }
27370b57cec5SDimitry Andric 
27380b57cec5SDimitry Andric bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
2739e8d8bef9SDimitry Andric                                        RISCVMCExpr::VariantKind &Kind) {
27400b57cec5SDimitry Andric   Kind = RISCVMCExpr::VK_RISCV_None;
27410b57cec5SDimitry Andric 
27420b57cec5SDimitry Andric   if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
27430b57cec5SDimitry Andric     Kind = RE->getKind();
27440b57cec5SDimitry Andric     Expr = RE->getSubExpr();
27450b57cec5SDimitry Andric   }
27460b57cec5SDimitry Andric 
2747e8d8bef9SDimitry Andric   MCValue Res;
2748e8d8bef9SDimitry Andric   MCFixup Fixup;
2749e8d8bef9SDimitry Andric   if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
2750e8d8bef9SDimitry Andric     return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
27510b57cec5SDimitry Andric   return false;
27520b57cec5SDimitry Andric }
27530b57cec5SDimitry Andric 
275406c3fb27SDimitry Andric bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
275506c3fb27SDimitry Andric   MCValue Res;
275606c3fb27SDimitry Andric   MCFixup Fixup;
275706c3fb27SDimitry Andric   if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) {
275806c3fb27SDimitry Andric     return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() &&
275906c3fb27SDimitry Andric            Res.getSymB();
276006c3fb27SDimitry Andric   }
276106c3fb27SDimitry Andric   return false;
276206c3fb27SDimitry Andric }
276306c3fb27SDimitry Andric 
276406c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
27650b57cec5SDimitry Andric   StringRef IDVal = DirectiveID.getString();
27660b57cec5SDimitry Andric 
27670b57cec5SDimitry Andric   if (IDVal == ".option")
27680b57cec5SDimitry Andric     return parseDirectiveOption();
2769349cc55cSDimitry Andric   if (IDVal == ".attribute")
27705ffd83dbSDimitry Andric     return parseDirectiveAttribute();
2771349cc55cSDimitry Andric   if (IDVal == ".insn")
2772349cc55cSDimitry Andric     return parseDirectiveInsn(DirectiveID.getLoc());
2773bdd1243dSDimitry Andric   if (IDVal == ".variant_cc")
2774bdd1243dSDimitry Andric     return parseDirectiveVariantCC();
27750b57cec5SDimitry Andric 
277606c3fb27SDimitry Andric   return ParseStatus::NoMatch;
277706c3fb27SDimitry Andric }
277806c3fb27SDimitry Andric 
277906c3fb27SDimitry Andric bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
278006c3fb27SDimitry Andric                                  bool FromOptionDirective) {
2781*0fca6ea1SDimitry Andric   for (auto &Feature : RISCVFeatureKV)
278206c3fb27SDimitry Andric     if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
278306c3fb27SDimitry Andric       clearFeatureBits(Feature.Value, Feature.Key);
278406c3fb27SDimitry Andric 
278506c3fb27SDimitry Andric   auto ParseResult = llvm::RISCVISAInfo::parseArchString(
278606c3fb27SDimitry Andric       Arch, /*EnableExperimentalExtension=*/true,
278706c3fb27SDimitry Andric       /*ExperimentalExtensionVersionCheck=*/true);
278806c3fb27SDimitry Andric   if (!ParseResult) {
278906c3fb27SDimitry Andric     std::string Buffer;
279006c3fb27SDimitry Andric     raw_string_ostream OutputErrMsg(Buffer);
279106c3fb27SDimitry Andric     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
279206c3fb27SDimitry Andric       OutputErrMsg << "invalid arch name '" << Arch << "', "
279306c3fb27SDimitry Andric                    << ErrMsg.getMessage();
279406c3fb27SDimitry Andric     });
279506c3fb27SDimitry Andric 
279606c3fb27SDimitry Andric     return Error(Loc, OutputErrMsg.str());
279706c3fb27SDimitry Andric   }
279806c3fb27SDimitry Andric   auto &ISAInfo = *ParseResult;
279906c3fb27SDimitry Andric 
2800*0fca6ea1SDimitry Andric   for (auto &Feature : RISCVFeatureKV)
280106c3fb27SDimitry Andric     if (ISAInfo->hasExtension(Feature.Key))
280206c3fb27SDimitry Andric       setFeatureBits(Feature.Value, Feature.Key);
280306c3fb27SDimitry Andric 
280406c3fb27SDimitry Andric   if (FromOptionDirective) {
280506c3fb27SDimitry Andric     if (ISAInfo->getXLen() == 32 && isRV64())
280606c3fb27SDimitry Andric       return Error(Loc, "bad arch string switching from rv64 to rv32");
280706c3fb27SDimitry Andric     else if (ISAInfo->getXLen() == 64 && !isRV64())
280806c3fb27SDimitry Andric       return Error(Loc, "bad arch string switching from rv32 to rv64");
280906c3fb27SDimitry Andric   }
281006c3fb27SDimitry Andric 
281106c3fb27SDimitry Andric   if (ISAInfo->getXLen() == 32)
281206c3fb27SDimitry Andric     clearFeatureBits(RISCV::Feature64Bit, "64bit");
281306c3fb27SDimitry Andric   else if (ISAInfo->getXLen() == 64)
281406c3fb27SDimitry Andric     setFeatureBits(RISCV::Feature64Bit, "64bit");
281506c3fb27SDimitry Andric   else
281606c3fb27SDimitry Andric     return Error(Loc, "bad arch string " + Arch);
281706c3fb27SDimitry Andric 
281806c3fb27SDimitry Andric   Result = ISAInfo->toString();
281906c3fb27SDimitry Andric   return false;
28200b57cec5SDimitry Andric }
28210b57cec5SDimitry Andric 
28220b57cec5SDimitry Andric bool RISCVAsmParser::parseDirectiveOption() {
28230b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
28240b57cec5SDimitry Andric   // Get the option token.
28250b57cec5SDimitry Andric   AsmToken Tok = Parser.getTok();
282606c3fb27SDimitry Andric 
28270b57cec5SDimitry Andric   // At the moment only identifiers are supported.
282806c3fb27SDimitry Andric   if (parseToken(AsmToken::Identifier, "expected identifier"))
282906c3fb27SDimitry Andric     return true;
28300b57cec5SDimitry Andric 
28310b57cec5SDimitry Andric   StringRef Option = Tok.getIdentifier();
28320b57cec5SDimitry Andric 
28330b57cec5SDimitry Andric   if (Option == "push") {
283406c3fb27SDimitry Andric     if (Parser.parseEOL())
283506c3fb27SDimitry Andric       return true;
283606c3fb27SDimitry Andric 
28370b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionPush();
28380b57cec5SDimitry Andric     pushFeatureBits();
28390b57cec5SDimitry Andric     return false;
28400b57cec5SDimitry Andric   }
28410b57cec5SDimitry Andric 
28420b57cec5SDimitry Andric   if (Option == "pop") {
28430b57cec5SDimitry Andric     SMLoc StartLoc = Parser.getTok().getLoc();
284406c3fb27SDimitry Andric     if (Parser.parseEOL())
284506c3fb27SDimitry Andric       return true;
284606c3fb27SDimitry Andric 
28470b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionPop();
28480b57cec5SDimitry Andric     if (popFeatureBits())
28490b57cec5SDimitry Andric       return Error(StartLoc, ".option pop with no .option push");
28500b57cec5SDimitry Andric 
28510b57cec5SDimitry Andric     return false;
28520b57cec5SDimitry Andric   }
28530b57cec5SDimitry Andric 
285406c3fb27SDimitry Andric   if (Option == "arch") {
285506c3fb27SDimitry Andric     SmallVector<RISCVOptionArchArg> Args;
285606c3fb27SDimitry Andric     do {
285706c3fb27SDimitry Andric       if (Parser.parseComma())
285806c3fb27SDimitry Andric         return true;
28590b57cec5SDimitry Andric 
286006c3fb27SDimitry Andric       RISCVOptionArchArgType Type;
286106c3fb27SDimitry Andric       if (parseOptionalToken(AsmToken::Plus))
286206c3fb27SDimitry Andric         Type = RISCVOptionArchArgType::Plus;
286306c3fb27SDimitry Andric       else if (parseOptionalToken(AsmToken::Minus))
286406c3fb27SDimitry Andric         Type = RISCVOptionArchArgType::Minus;
286506c3fb27SDimitry Andric       else if (!Args.empty())
28660b57cec5SDimitry Andric         return Error(Parser.getTok().getLoc(),
286706c3fb27SDimitry Andric                      "unexpected token, expected + or -");
286806c3fb27SDimitry Andric       else
286906c3fb27SDimitry Andric         Type = RISCVOptionArchArgType::Full;
28700b57cec5SDimitry Andric 
287106c3fb27SDimitry Andric       if (Parser.getTok().isNot(AsmToken::Identifier))
287206c3fb27SDimitry Andric         return Error(Parser.getTok().getLoc(),
287306c3fb27SDimitry Andric                      "unexpected token, expected identifier");
287406c3fb27SDimitry Andric 
287506c3fb27SDimitry Andric       StringRef Arch = Parser.getTok().getString();
287606c3fb27SDimitry Andric       SMLoc Loc = Parser.getTok().getLoc();
287706c3fb27SDimitry Andric       Parser.Lex();
287806c3fb27SDimitry Andric 
287906c3fb27SDimitry Andric       if (Type == RISCVOptionArchArgType::Full) {
288006c3fb27SDimitry Andric         std::string Result;
288106c3fb27SDimitry Andric         if (resetToArch(Arch, Loc, Result, true))
288206c3fb27SDimitry Andric           return true;
288306c3fb27SDimitry Andric 
288406c3fb27SDimitry Andric         Args.emplace_back(Type, Result);
288506c3fb27SDimitry Andric         break;
288606c3fb27SDimitry Andric       }
288706c3fb27SDimitry Andric 
288806c3fb27SDimitry Andric       if (isDigit(Arch.back()))
288906c3fb27SDimitry Andric         return Error(
2890*0fca6ea1SDimitry Andric             Loc, "extension version number parsing not currently implemented");
289106c3fb27SDimitry Andric 
2892*0fca6ea1SDimitry Andric       std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);
2893*0fca6ea1SDimitry Andric       if (!enableExperimentalExtension() &&
2894*0fca6ea1SDimitry Andric           StringRef(Feature).starts_with("experimental-"))
2895*0fca6ea1SDimitry Andric         return Error(Loc, "unexpected experimental extensions");
2896*0fca6ea1SDimitry Andric       auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature);
2897*0fca6ea1SDimitry Andric       if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature)
2898*0fca6ea1SDimitry Andric         return Error(Loc, "unknown extension feature");
2899*0fca6ea1SDimitry Andric 
2900*0fca6ea1SDimitry Andric       Args.emplace_back(Type, Arch.str());
290106c3fb27SDimitry Andric 
290206c3fb27SDimitry Andric       if (Type == RISCVOptionArchArgType::Plus) {
290306c3fb27SDimitry Andric         FeatureBitset OldFeatureBits = STI->getFeatureBits();
290406c3fb27SDimitry Andric 
290506c3fb27SDimitry Andric         setFeatureBits(Ext->Value, Ext->Key);
290606c3fb27SDimitry Andric         auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits());
290706c3fb27SDimitry Andric         if (!ParseResult) {
290806c3fb27SDimitry Andric           copySTI().setFeatureBits(OldFeatureBits);
290906c3fb27SDimitry Andric           setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
291006c3fb27SDimitry Andric 
291106c3fb27SDimitry Andric           std::string Buffer;
291206c3fb27SDimitry Andric           raw_string_ostream OutputErrMsg(Buffer);
291306c3fb27SDimitry Andric           handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
291406c3fb27SDimitry Andric             OutputErrMsg << ErrMsg.getMessage();
291506c3fb27SDimitry Andric           });
291606c3fb27SDimitry Andric 
291706c3fb27SDimitry Andric           return Error(Loc, OutputErrMsg.str());
291806c3fb27SDimitry Andric         }
291906c3fb27SDimitry Andric       } else {
292006c3fb27SDimitry Andric         assert(Type == RISCVOptionArchArgType::Minus);
292106c3fb27SDimitry Andric         // It is invalid to disable an extension that there are other enabled
292206c3fb27SDimitry Andric         // extensions depend on it.
292306c3fb27SDimitry Andric         // TODO: Make use of RISCVISAInfo to handle this
2924*0fca6ea1SDimitry Andric         for (auto &Feature : RISCVFeatureKV) {
292506c3fb27SDimitry Andric           if (getSTI().hasFeature(Feature.Value) &&
292606c3fb27SDimitry Andric               Feature.Implies.test(Ext->Value))
2927*0fca6ea1SDimitry Andric             return Error(Loc, Twine("can't disable ") + Ext->Key +
2928*0fca6ea1SDimitry Andric                                   " extension; " + Feature.Key +
2929*0fca6ea1SDimitry Andric                                   " extension requires " + Ext->Key +
2930*0fca6ea1SDimitry Andric                                   " extension");
293106c3fb27SDimitry Andric         }
293206c3fb27SDimitry Andric 
293306c3fb27SDimitry Andric         clearFeatureBits(Ext->Value, Ext->Key);
293406c3fb27SDimitry Andric       }
293506c3fb27SDimitry Andric     } while (Parser.getTok().isNot(AsmToken::EndOfStatement));
293606c3fb27SDimitry Andric 
293706c3fb27SDimitry Andric     if (Parser.parseEOL())
293806c3fb27SDimitry Andric       return true;
293906c3fb27SDimitry Andric 
294006c3fb27SDimitry Andric     getTargetStreamer().emitDirectiveOptionArch(Args);
294106c3fb27SDimitry Andric     return false;
294206c3fb27SDimitry Andric   }
294306c3fb27SDimitry Andric 
294406c3fb27SDimitry Andric   if (Option == "rvc") {
294506c3fb27SDimitry Andric     if (Parser.parseEOL())
294606c3fb27SDimitry Andric       return true;
294706c3fb27SDimitry Andric 
294806c3fb27SDimitry Andric     getTargetStreamer().emitDirectiveOptionRVC();
29490b57cec5SDimitry Andric     setFeatureBits(RISCV::FeatureStdExtC, "c");
29500b57cec5SDimitry Andric     return false;
29510b57cec5SDimitry Andric   }
29520b57cec5SDimitry Andric 
29530b57cec5SDimitry Andric   if (Option == "norvc") {
295406c3fb27SDimitry Andric     if (Parser.parseEOL())
295506c3fb27SDimitry Andric       return true;
295606c3fb27SDimitry Andric 
29570b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionNoRVC();
29580b57cec5SDimitry Andric     clearFeatureBits(RISCV::FeatureStdExtC, "c");
2959*0fca6ea1SDimitry Andric     clearFeatureBits(RISCV::FeatureStdExtZca, "zca");
29600b57cec5SDimitry Andric     return false;
29610b57cec5SDimitry Andric   }
29620b57cec5SDimitry Andric 
29635ffd83dbSDimitry Andric   if (Option == "pic") {
296406c3fb27SDimitry Andric     if (Parser.parseEOL())
296506c3fb27SDimitry Andric       return true;
296606c3fb27SDimitry Andric 
29675ffd83dbSDimitry Andric     getTargetStreamer().emitDirectiveOptionPIC();
29685ffd83dbSDimitry Andric     ParserOptions.IsPicEnabled = true;
29695ffd83dbSDimitry Andric     return false;
29705ffd83dbSDimitry Andric   }
29715ffd83dbSDimitry Andric 
29725ffd83dbSDimitry Andric   if (Option == "nopic") {
297306c3fb27SDimitry Andric     if (Parser.parseEOL())
297406c3fb27SDimitry Andric       return true;
297506c3fb27SDimitry Andric 
29765ffd83dbSDimitry Andric     getTargetStreamer().emitDirectiveOptionNoPIC();
29775ffd83dbSDimitry Andric     ParserOptions.IsPicEnabled = false;
29785ffd83dbSDimitry Andric     return false;
29795ffd83dbSDimitry Andric   }
29805ffd83dbSDimitry Andric 
29810b57cec5SDimitry Andric   if (Option == "relax") {
298206c3fb27SDimitry Andric     if (Parser.parseEOL())
298306c3fb27SDimitry Andric       return true;
298406c3fb27SDimitry Andric 
29850b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionRelax();
29860b57cec5SDimitry Andric     setFeatureBits(RISCV::FeatureRelax, "relax");
29870b57cec5SDimitry Andric     return false;
29880b57cec5SDimitry Andric   }
29890b57cec5SDimitry Andric 
29900b57cec5SDimitry Andric   if (Option == "norelax") {
299106c3fb27SDimitry Andric     if (Parser.parseEOL())
299206c3fb27SDimitry Andric       return true;
299306c3fb27SDimitry Andric 
29940b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionNoRelax();
29950b57cec5SDimitry Andric     clearFeatureBits(RISCV::FeatureRelax, "relax");
29960b57cec5SDimitry Andric     return false;
29970b57cec5SDimitry Andric   }
29980b57cec5SDimitry Andric 
29990b57cec5SDimitry Andric   // Unknown option.
300006c3fb27SDimitry Andric   Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
300106c3fb27SDimitry Andric                                     "'rvc', 'norvc', 'arch', 'relax' or "
30020b57cec5SDimitry Andric                                     "'norelax'");
30030b57cec5SDimitry Andric   Parser.eatToEndOfStatement();
30040b57cec5SDimitry Andric   return false;
30050b57cec5SDimitry Andric }
30060b57cec5SDimitry Andric 
30075ffd83dbSDimitry Andric /// parseDirectiveAttribute
30085ffd83dbSDimitry Andric ///  ::= .attribute expression ',' ( expression | "string" )
30095ffd83dbSDimitry Andric ///  ::= .attribute identifier ',' ( expression | "string" )
30105ffd83dbSDimitry Andric bool RISCVAsmParser::parseDirectiveAttribute() {
30115ffd83dbSDimitry Andric   MCAsmParser &Parser = getParser();
30125ffd83dbSDimitry Andric   int64_t Tag;
30135ffd83dbSDimitry Andric   SMLoc TagLoc;
30145ffd83dbSDimitry Andric   TagLoc = Parser.getTok().getLoc();
30155ffd83dbSDimitry Andric   if (Parser.getTok().is(AsmToken::Identifier)) {
30165ffd83dbSDimitry Andric     StringRef Name = Parser.getTok().getIdentifier();
3017bdd1243dSDimitry Andric     std::optional<unsigned> Ret =
3018fe6060f1SDimitry Andric         ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags());
301906c3fb27SDimitry Andric     if (!Ret)
302006c3fb27SDimitry Andric       return Error(TagLoc, "attribute name not recognised: " + Name);
302181ad6265SDimitry Andric     Tag = *Ret;
30225ffd83dbSDimitry Andric     Parser.Lex();
30235ffd83dbSDimitry Andric   } else {
30245ffd83dbSDimitry Andric     const MCExpr *AttrExpr;
30255ffd83dbSDimitry Andric 
30265ffd83dbSDimitry Andric     TagLoc = Parser.getTok().getLoc();
30275ffd83dbSDimitry Andric     if (Parser.parseExpression(AttrExpr))
30285ffd83dbSDimitry Andric       return true;
30295ffd83dbSDimitry Andric 
30305ffd83dbSDimitry Andric     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
30315ffd83dbSDimitry Andric     if (check(!CE, TagLoc, "expected numeric constant"))
30325ffd83dbSDimitry Andric       return true;
30335ffd83dbSDimitry Andric 
30345ffd83dbSDimitry Andric     Tag = CE->getValue();
30355ffd83dbSDimitry Andric   }
30365ffd83dbSDimitry Andric 
303706c3fb27SDimitry Andric   if (Parser.parseComma())
30385ffd83dbSDimitry Andric     return true;
30395ffd83dbSDimitry Andric 
30405ffd83dbSDimitry Andric   StringRef StringValue;
30415ffd83dbSDimitry Andric   int64_t IntegerValue = 0;
30425ffd83dbSDimitry Andric   bool IsIntegerValue = true;
30435ffd83dbSDimitry Andric 
30445ffd83dbSDimitry Andric   // RISC-V attributes have a string value if the tag number is odd
30455ffd83dbSDimitry Andric   // and an integer value if the tag number is even.
30465ffd83dbSDimitry Andric   if (Tag % 2)
30475ffd83dbSDimitry Andric     IsIntegerValue = false;
30485ffd83dbSDimitry Andric 
30495ffd83dbSDimitry Andric   SMLoc ValueExprLoc = Parser.getTok().getLoc();
30505ffd83dbSDimitry Andric   if (IsIntegerValue) {
30515ffd83dbSDimitry Andric     const MCExpr *ValueExpr;
30525ffd83dbSDimitry Andric     if (Parser.parseExpression(ValueExpr))
30535ffd83dbSDimitry Andric       return true;
30545ffd83dbSDimitry Andric 
30555ffd83dbSDimitry Andric     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
30565ffd83dbSDimitry Andric     if (!CE)
30575ffd83dbSDimitry Andric       return Error(ValueExprLoc, "expected numeric constant");
30585ffd83dbSDimitry Andric     IntegerValue = CE->getValue();
30595ffd83dbSDimitry Andric   } else {
30605ffd83dbSDimitry Andric     if (Parser.getTok().isNot(AsmToken::String))
30615ffd83dbSDimitry Andric       return Error(Parser.getTok().getLoc(), "expected string constant");
30625ffd83dbSDimitry Andric 
30635ffd83dbSDimitry Andric     StringValue = Parser.getTok().getStringContents();
30645ffd83dbSDimitry Andric     Parser.Lex();
30655ffd83dbSDimitry Andric   }
30665ffd83dbSDimitry Andric 
306781ad6265SDimitry Andric   if (Parser.parseEOL())
30685ffd83dbSDimitry Andric     return true;
30695ffd83dbSDimitry Andric 
30700eae32dcSDimitry Andric   if (IsIntegerValue)
30710eae32dcSDimitry Andric     getTargetStreamer().emitAttribute(Tag, IntegerValue);
30720eae32dcSDimitry Andric   else if (Tag != RISCVAttrs::ARCH)
30730eae32dcSDimitry Andric     getTargetStreamer().emitTextAttribute(Tag, StringValue);
30740eae32dcSDimitry Andric   else {
307506c3fb27SDimitry Andric     std::string Result;
307606c3fb27SDimitry Andric     if (resetToArch(StringValue, ValueExprLoc, Result, false))
307706c3fb27SDimitry Andric       return true;
3078349cc55cSDimitry Andric 
3079349cc55cSDimitry Andric     // Then emit the arch string.
308006c3fb27SDimitry Andric     getTargetStreamer().emitTextAttribute(Tag, Result);
30815ffd83dbSDimitry Andric   }
30825ffd83dbSDimitry Andric 
30835ffd83dbSDimitry Andric   return false;
30845ffd83dbSDimitry Andric }
30855ffd83dbSDimitry Andric 
308606c3fb27SDimitry Andric bool isValidInsnFormat(StringRef Format, bool AllowC) {
308706c3fb27SDimitry Andric   return StringSwitch<bool>(Format)
308806c3fb27SDimitry Andric       .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
308906c3fb27SDimitry Andric       .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)
309006c3fb27SDimitry Andric       .Default(false);
309106c3fb27SDimitry Andric }
309206c3fb27SDimitry Andric 
3093349cc55cSDimitry Andric /// parseDirectiveInsn
3094349cc55cSDimitry Andric /// ::= .insn [ format encoding, (operands (, operands)*) ]
3095*0fca6ea1SDimitry Andric /// ::= .insn [ length, value ]
3096*0fca6ea1SDimitry Andric /// ::= .insn [ value ]
3097349cc55cSDimitry Andric bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3098349cc55cSDimitry Andric   MCAsmParser &Parser = getParser();
3099349cc55cSDimitry Andric 
3100*0fca6ea1SDimitry Andric   bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3101*0fca6ea1SDimitry Andric                 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3102*0fca6ea1SDimitry Andric 
3103349cc55cSDimitry Andric   // Expect instruction format as identifier.
3104349cc55cSDimitry Andric   StringRef Format;
3105349cc55cSDimitry Andric   SMLoc ErrorLoc = Parser.getTok().getLoc();
3106*0fca6ea1SDimitry Andric   if (Parser.parseIdentifier(Format)) {
3107*0fca6ea1SDimitry Andric     // Try parsing .insn [length], value
3108*0fca6ea1SDimitry Andric     int64_t Length = 0;
3109*0fca6ea1SDimitry Andric     int64_t Value = 0;
3110*0fca6ea1SDimitry Andric     if (Parser.parseIntToken(
3111*0fca6ea1SDimitry Andric             Value, "expected instruction format or an integer constant"))
3112*0fca6ea1SDimitry Andric       return true;
3113*0fca6ea1SDimitry Andric     if (Parser.parseOptionalToken(AsmToken::Comma)) {
3114*0fca6ea1SDimitry Andric       Length = Value;
3115*0fca6ea1SDimitry Andric       if (Parser.parseIntToken(Value, "expected an integer constant"))
3116*0fca6ea1SDimitry Andric         return true;
3117*0fca6ea1SDimitry Andric     }
3118349cc55cSDimitry Andric 
3119*0fca6ea1SDimitry Andric     // TODO: Add support for long instructions
3120*0fca6ea1SDimitry Andric     int64_t RealLength = (Value & 3) == 3 ? 4 : 2;
3121*0fca6ea1SDimitry Andric     if (!isUIntN(RealLength * 8, Value))
3122*0fca6ea1SDimitry Andric       return Error(ErrorLoc, "invalid operand for instruction");
3123*0fca6ea1SDimitry Andric     if (RealLength == 2 && !AllowC)
3124*0fca6ea1SDimitry Andric       return Error(ErrorLoc, "compressed instructions are not allowed");
3125*0fca6ea1SDimitry Andric     if (Length != 0 && Length != RealLength)
3126*0fca6ea1SDimitry Andric       return Error(ErrorLoc, "instruction length mismatch");
3127*0fca6ea1SDimitry Andric 
3128*0fca6ea1SDimitry Andric     if (getParser().parseEOL("invalid operand for instruction")) {
3129*0fca6ea1SDimitry Andric       getParser().eatToEndOfStatement();
3130*0fca6ea1SDimitry Andric       return true;
3131*0fca6ea1SDimitry Andric     }
3132*0fca6ea1SDimitry Andric 
3133*0fca6ea1SDimitry Andric     emitToStreamer(getStreamer(), MCInstBuilder(RealLength == 2 ? RISCV::Insn16
3134*0fca6ea1SDimitry Andric                                                                 : RISCV::Insn32)
3135*0fca6ea1SDimitry Andric                                       .addImm(Value));
3136*0fca6ea1SDimitry Andric     return false;
3137*0fca6ea1SDimitry Andric   }
3138*0fca6ea1SDimitry Andric 
313906c3fb27SDimitry Andric   if (!isValidInsnFormat(Format, AllowC))
3140349cc55cSDimitry Andric     return Error(ErrorLoc, "invalid instruction format");
3141349cc55cSDimitry Andric 
3142349cc55cSDimitry Andric   std::string FormatName = (".insn_" + Format).str();
3143349cc55cSDimitry Andric 
3144349cc55cSDimitry Andric   ParseInstructionInfo Info;
3145349cc55cSDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
3146349cc55cSDimitry Andric 
3147349cc55cSDimitry Andric   if (ParseInstruction(Info, FormatName, L, Operands))
3148349cc55cSDimitry Andric     return true;
3149349cc55cSDimitry Andric 
3150349cc55cSDimitry Andric   unsigned Opcode;
3151349cc55cSDimitry Andric   uint64_t ErrorInfo;
3152349cc55cSDimitry Andric   return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
3153349cc55cSDimitry Andric                                  ErrorInfo,
3154349cc55cSDimitry Andric                                  /*MatchingInlineAsm=*/false);
3155349cc55cSDimitry Andric }
3156349cc55cSDimitry Andric 
3157bdd1243dSDimitry Andric /// parseDirectiveVariantCC
3158bdd1243dSDimitry Andric ///  ::= .variant_cc symbol
3159bdd1243dSDimitry Andric bool RISCVAsmParser::parseDirectiveVariantCC() {
3160bdd1243dSDimitry Andric   StringRef Name;
3161bdd1243dSDimitry Andric   if (getParser().parseIdentifier(Name))
3162bdd1243dSDimitry Andric     return TokError("expected symbol name");
3163bdd1243dSDimitry Andric   if (parseEOL())
316406c3fb27SDimitry Andric     return true;
3165bdd1243dSDimitry Andric   getTargetStreamer().emitDirectiveVariantCC(
3166bdd1243dSDimitry Andric       *getContext().getOrCreateSymbol(Name));
3167bdd1243dSDimitry Andric   return false;
3168bdd1243dSDimitry Andric }
3169bdd1243dSDimitry Andric 
31700b57cec5SDimitry Andric void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
31710b57cec5SDimitry Andric   MCInst CInst;
3172bdd1243dSDimitry Andric   bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
3173480093f4SDimitry Andric   if (Res)
3174480093f4SDimitry Andric     ++RISCVNumInstrsCompressed;
31755ffd83dbSDimitry Andric   S.emitInstruction((Res ? CInst : Inst), getSTI());
31760b57cec5SDimitry Andric }
31770b57cec5SDimitry Andric 
3178e8d8bef9SDimitry Andric void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
31790b57cec5SDimitry Andric                                  MCStreamer &Out) {
3180*0fca6ea1SDimitry Andric   SmallVector<MCInst, 8> Seq;
3181*0fca6ea1SDimitry Andric   RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);
31820b57cec5SDimitry Andric 
3183*0fca6ea1SDimitry Andric   for (MCInst &Inst : Seq) {
3184*0fca6ea1SDimitry Andric     emitToStreamer(Out, Inst);
31850b57cec5SDimitry Andric   }
31860b57cec5SDimitry Andric }
31870b57cec5SDimitry Andric 
31880b57cec5SDimitry Andric void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
31890b57cec5SDimitry Andric                                        const MCExpr *Symbol,
31900b57cec5SDimitry Andric                                        RISCVMCExpr::VariantKind VKHi,
31910b57cec5SDimitry Andric                                        unsigned SecondOpcode, SMLoc IDLoc,
31920b57cec5SDimitry Andric                                        MCStreamer &Out) {
31930b57cec5SDimitry Andric   // A pair of instructions for PC-relative addressing; expands to
31940b57cec5SDimitry Andric   //   TmpLabel: AUIPC TmpReg, VKHi(symbol)
31950b57cec5SDimitry Andric   //             OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
31960b57cec5SDimitry Andric   MCContext &Ctx = getContext();
31970b57cec5SDimitry Andric 
3198e8d8bef9SDimitry Andric   MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
31995ffd83dbSDimitry Andric   Out.emitLabel(TmpLabel);
32000b57cec5SDimitry Andric 
32010b57cec5SDimitry Andric   const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
32020b57cec5SDimitry Andric   emitToStreamer(
32030b57cec5SDimitry Andric       Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
32040b57cec5SDimitry Andric 
32050b57cec5SDimitry Andric   const MCExpr *RefToLinkTmpLabel =
32060b57cec5SDimitry Andric       RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
32070b57cec5SDimitry Andric                           RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
32080b57cec5SDimitry Andric 
32090b57cec5SDimitry Andric   emitToStreamer(Out, MCInstBuilder(SecondOpcode)
32100b57cec5SDimitry Andric                           .addOperand(DestReg)
32110b57cec5SDimitry Andric                           .addOperand(TmpReg)
32120b57cec5SDimitry Andric                           .addExpr(RefToLinkTmpLabel));
32130b57cec5SDimitry Andric }
32140b57cec5SDimitry Andric 
32150b57cec5SDimitry Andric void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
32160b57cec5SDimitry Andric                                           MCStreamer &Out) {
32170b57cec5SDimitry Andric   // The load local address pseudo-instruction "lla" is used in PC-relative
32180b57cec5SDimitry Andric   // addressing of local symbols:
32190b57cec5SDimitry Andric   //   lla rdest, symbol
32200b57cec5SDimitry Andric   // expands to
32210b57cec5SDimitry Andric   //   TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
32220b57cec5SDimitry Andric   //             ADDI rdest, rdest, %pcrel_lo(TmpLabel)
32230b57cec5SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
32240b57cec5SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
32250b57cec5SDimitry Andric   emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
32260b57cec5SDimitry Andric                     RISCV::ADDI, IDLoc, Out);
32270b57cec5SDimitry Andric }
32280b57cec5SDimitry Andric 
322906c3fb27SDimitry Andric void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
323006c3fb27SDimitry Andric                                            MCStreamer &Out) {
323106c3fb27SDimitry Andric   // The load global address pseudo-instruction "lga" is used in GOT-indirect
323206c3fb27SDimitry Andric   // addressing of global symbols:
323306c3fb27SDimitry Andric   //   lga rdest, symbol
323406c3fb27SDimitry Andric   // expands to
323506c3fb27SDimitry Andric   //   TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
323606c3fb27SDimitry Andric   //             Lx rdest, %pcrel_lo(TmpLabel)(rdest)
323706c3fb27SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
323806c3fb27SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
323906c3fb27SDimitry Andric   unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
324006c3fb27SDimitry Andric   emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,
324106c3fb27SDimitry Andric                     SecondOpcode, IDLoc, Out);
324206c3fb27SDimitry Andric }
324306c3fb27SDimitry Andric 
32440b57cec5SDimitry Andric void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
32450b57cec5SDimitry Andric                                      MCStreamer &Out) {
32460b57cec5SDimitry Andric   // The load address pseudo-instruction "la" is used in PC-relative and
32470b57cec5SDimitry Andric   // GOT-indirect addressing of global symbols:
32480b57cec5SDimitry Andric   //   la rdest, symbol
324906c3fb27SDimitry Andric   // is an alias for either (for non-PIC)
325006c3fb27SDimitry Andric   //   lla rdest, symbol
32510b57cec5SDimitry Andric   // or (for PIC)
325206c3fb27SDimitry Andric   //   lga rdest, symbol
325306c3fb27SDimitry Andric   if (ParserOptions.IsPicEnabled)
325406c3fb27SDimitry Andric     emitLoadGlobalAddress(Inst, IDLoc, Out);
325506c3fb27SDimitry Andric   else
325606c3fb27SDimitry Andric     emitLoadLocalAddress(Inst, IDLoc, Out);
32570b57cec5SDimitry Andric }
32580b57cec5SDimitry Andric 
32590b57cec5SDimitry Andric void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
32600b57cec5SDimitry Andric                                           MCStreamer &Out) {
32610b57cec5SDimitry Andric   // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
32620b57cec5SDimitry Andric   // initial-exec TLS model addressing of global symbols:
32630b57cec5SDimitry Andric   //   la.tls.ie rdest, symbol
32640b57cec5SDimitry Andric   // expands to
32650b57cec5SDimitry Andric   //   TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
32660b57cec5SDimitry Andric   //             Lx rdest, %pcrel_lo(TmpLabel)(rdest)
32670b57cec5SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
32680b57cec5SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
32690b57cec5SDimitry Andric   unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
32700b57cec5SDimitry Andric   emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
32710b57cec5SDimitry Andric                     SecondOpcode, IDLoc, Out);
32720b57cec5SDimitry Andric }
32730b57cec5SDimitry Andric 
32740b57cec5SDimitry Andric void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
32750b57cec5SDimitry Andric                                           MCStreamer &Out) {
32760b57cec5SDimitry Andric   // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
32770b57cec5SDimitry Andric   // global-dynamic TLS model addressing of global symbols:
32780b57cec5SDimitry Andric   //   la.tls.gd rdest, symbol
32790b57cec5SDimitry Andric   // expands to
32800b57cec5SDimitry Andric   //   TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
32810b57cec5SDimitry Andric   //             ADDI rdest, rdest, %pcrel_lo(TmpLabel)
32820b57cec5SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
32830b57cec5SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
32840b57cec5SDimitry Andric   emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
32850b57cec5SDimitry Andric                     RISCV::ADDI, IDLoc, Out);
32860b57cec5SDimitry Andric }
32870b57cec5SDimitry Andric 
32880b57cec5SDimitry Andric void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
32890b57cec5SDimitry Andric                                          SMLoc IDLoc, MCStreamer &Out,
32900b57cec5SDimitry Andric                                          bool HasTmpReg) {
32910b57cec5SDimitry Andric   // The load/store pseudo-instruction does a pc-relative load with
32920b57cec5SDimitry Andric   // a symbol.
32930b57cec5SDimitry Andric   //
32940b57cec5SDimitry Andric   // The expansion looks like this
32950b57cec5SDimitry Andric   //
32960b57cec5SDimitry Andric   //   TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
32970b57cec5SDimitry Andric   //             [S|L]X    rd, %pcrel_lo(TmpLabel)(tmp)
3298349cc55cSDimitry Andric   unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3299349cc55cSDimitry Andric   MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
33000b57cec5SDimitry Andric   unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3301349cc55cSDimitry Andric   MCOperand TmpReg = Inst.getOperand(0);
33020b57cec5SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
33030b57cec5SDimitry Andric   emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
33040b57cec5SDimitry Andric                     Opcode, IDLoc, Out);
33050b57cec5SDimitry Andric }
33060b57cec5SDimitry Andric 
3307e8d8bef9SDimitry Andric void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3308e8d8bef9SDimitry Andric                                       int64_t Width, SMLoc IDLoc,
3309e8d8bef9SDimitry Andric                                       MCStreamer &Out) {
3310e8d8bef9SDimitry Andric   // The sign/zero extend pseudo-instruction does two shifts, with the shift
3311e8d8bef9SDimitry Andric   // amounts dependent on the XLEN.
3312e8d8bef9SDimitry Andric   //
3313e8d8bef9SDimitry Andric   // The expansion looks like this
3314e8d8bef9SDimitry Andric   //
3315e8d8bef9SDimitry Andric   //    SLLI rd, rs, XLEN - Width
3316e8d8bef9SDimitry Andric   //    SR[A|R]I rd, rd, XLEN - Width
3317e8d8bef9SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
3318e8d8bef9SDimitry Andric   MCOperand SourceReg = Inst.getOperand(1);
3319e8d8bef9SDimitry Andric 
3320e8d8bef9SDimitry Andric   unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3321e8d8bef9SDimitry Andric   int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3322e8d8bef9SDimitry Andric 
3323e8d8bef9SDimitry Andric   assert(ShAmt > 0 && "Shift amount must be non-zero.");
3324e8d8bef9SDimitry Andric 
3325e8d8bef9SDimitry Andric   emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3326e8d8bef9SDimitry Andric                           .addOperand(DestReg)
3327e8d8bef9SDimitry Andric                           .addOperand(SourceReg)
3328e8d8bef9SDimitry Andric                           .addImm(ShAmt));
3329e8d8bef9SDimitry Andric 
3330e8d8bef9SDimitry Andric   emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3331e8d8bef9SDimitry Andric                           .addOperand(DestReg)
3332e8d8bef9SDimitry Andric                           .addOperand(DestReg)
3333e8d8bef9SDimitry Andric                           .addImm(ShAmt));
3334e8d8bef9SDimitry Andric }
3335e8d8bef9SDimitry Andric 
3336e8d8bef9SDimitry Andric void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3337e8d8bef9SDimitry Andric                                MCStreamer &Out) {
3338e8d8bef9SDimitry Andric   if (Inst.getNumOperands() == 3) {
3339e8d8bef9SDimitry Andric     // unmasked va >= x
3340e8d8bef9SDimitry Andric     //
3341e8d8bef9SDimitry Andric     //  pseudoinstruction: vmsge{u}.vx vd, va, x
3342e8d8bef9SDimitry Andric     //  expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3343e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opcode)
3344e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3345e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(1))
3346e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(2))
3347*0fca6ea1SDimitry Andric                             .addReg(RISCV::NoRegister)
3348*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3349e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
3350e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3351e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3352*0fca6ea1SDimitry Andric                             .addOperand(Inst.getOperand(0))
3353*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3354e8d8bef9SDimitry Andric   } else if (Inst.getNumOperands() == 4) {
3355e8d8bef9SDimitry Andric     // masked va >= x, vd != v0
3356e8d8bef9SDimitry Andric     //
3357e8d8bef9SDimitry Andric     //  pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3358e8d8bef9SDimitry Andric     //  expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3359e8d8bef9SDimitry Andric     assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
3360e8d8bef9SDimitry Andric            "The destination register should not be V0.");
3361e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opcode)
3362e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3363e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(1))
3364e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(2))
3365*0fca6ea1SDimitry Andric                             .addOperand(Inst.getOperand(3))
3366*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3367e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
3368e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3369e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3370*0fca6ea1SDimitry Andric                             .addReg(RISCV::V0)
3371*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3372fe6060f1SDimitry Andric   } else if (Inst.getNumOperands() == 5 &&
3373fe6060f1SDimitry Andric              Inst.getOperand(0).getReg() == RISCV::V0) {
3374e8d8bef9SDimitry Andric     // masked va >= x, vd == v0
3375e8d8bef9SDimitry Andric     //
3376e8d8bef9SDimitry Andric     //  pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3377349cc55cSDimitry Andric     //  expansion: vmslt{u}.vx vt, va, x;  vmandn.mm vd, vd, vt
3378e8d8bef9SDimitry Andric     assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
3379e8d8bef9SDimitry Andric            "The destination register should be V0.");
3380e8d8bef9SDimitry Andric     assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3381e8d8bef9SDimitry Andric            "The temporary vector register should not be V0.");
3382e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opcode)
3383e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(1))
3384e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(2))
3385e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(3))
3386*0fca6ea1SDimitry Andric                             .addReg(RISCV::NoRegister)
3387*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3388349cc55cSDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3389e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3390e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3391*0fca6ea1SDimitry Andric                             .addOperand(Inst.getOperand(1))
3392*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3393fe6060f1SDimitry Andric   } else if (Inst.getNumOperands() == 5) {
3394fe6060f1SDimitry Andric     // masked va >= x, any vd
3395fe6060f1SDimitry Andric     //
3396fe6060f1SDimitry Andric     // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
33975f757f3fSDimitry Andric     // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
33985f757f3fSDimitry Andric     //            vmandn.mm vd, vd, v0;  vmor.mm vd, vt, vd
3399fe6060f1SDimitry Andric     assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3400fe6060f1SDimitry Andric            "The temporary vector register should not be V0.");
3401fe6060f1SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opcode)
3402fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(1))
3403fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(2))
3404fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(3))
3405*0fca6ea1SDimitry Andric                             .addReg(RISCV::NoRegister)
3406*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3407349cc55cSDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3408fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(1))
3409fe6060f1SDimitry Andric                             .addReg(RISCV::V0)
3410*0fca6ea1SDimitry Andric                             .addOperand(Inst.getOperand(1))
3411*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3412349cc55cSDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3413fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(0))
3414fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(0))
3415*0fca6ea1SDimitry Andric                             .addReg(RISCV::V0)
3416*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3417fe6060f1SDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
3418fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(0))
3419fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(1))
3420*0fca6ea1SDimitry Andric                             .addOperand(Inst.getOperand(0))
3421*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3422e8d8bef9SDimitry Andric   }
3423e8d8bef9SDimitry Andric }
3424e8d8bef9SDimitry Andric 
34250b57cec5SDimitry Andric bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
34260b57cec5SDimitry Andric                                          OperandVector &Operands) {
34270b57cec5SDimitry Andric   assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
34280b57cec5SDimitry Andric   assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
34290b57cec5SDimitry Andric   if (Inst.getOperand(2).getReg() != RISCV::X4) {
34300b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
34310b57cec5SDimitry Andric     return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
34320b57cec5SDimitry Andric                            "%tprel_add modifier");
34330b57cec5SDimitry Andric   }
34340b57cec5SDimitry Andric 
34350b57cec5SDimitry Andric   return false;
34360b57cec5SDimitry Andric }
34370b57cec5SDimitry Andric 
34387a6dacacSDimitry Andric bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
34397a6dacacSDimitry Andric                                             OperandVector &Operands) {
34407a6dacacSDimitry Andric   assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
34417a6dacacSDimitry Andric   assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
34427a6dacacSDimitry Andric   if (Inst.getOperand(0).getReg() != RISCV::X5) {
34437a6dacacSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
34447a6dacacSDimitry Andric     return Error(ErrorLoc, "the output operand must be t0/x5 when using "
34457a6dacacSDimitry Andric                            "%tlsdesc_call modifier");
34467a6dacacSDimitry Andric   }
34477a6dacacSDimitry Andric 
34487a6dacacSDimitry Andric   return false;
34497a6dacacSDimitry Andric }
34507a6dacacSDimitry Andric 
34515ffd83dbSDimitry Andric std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
34525ffd83dbSDimitry Andric   return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
345306c3fb27SDimitry Andric                                  llvm::SMLoc());
345406c3fb27SDimitry Andric }
345506c3fb27SDimitry Andric 
345606c3fb27SDimitry Andric std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
345706c3fb27SDimitry Andric   return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
345806c3fb27SDimitry Andric                                     llvm::SMLoc());
34595ffd83dbSDimitry Andric }
34605ffd83dbSDimitry Andric 
34615f757f3fSDimitry Andric std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
34625f757f3fSDimitry Andric   return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
34635f757f3fSDimitry Andric                                     llvm::SMLoc());
34645f757f3fSDimitry Andric }
34655f757f3fSDimitry Andric 
34665ffd83dbSDimitry Andric bool RISCVAsmParser::validateInstruction(MCInst &Inst,
34675ffd83dbSDimitry Andric                                          OperandVector &Operands) {
346806c3fb27SDimitry Andric   unsigned Opcode = Inst.getOpcode();
346906c3fb27SDimitry Andric 
347006c3fb27SDimitry Andric   if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
347106c3fb27SDimitry Andric       Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3472fe6060f1SDimitry Andric     unsigned DestReg = Inst.getOperand(0).getReg();
3473fe6060f1SDimitry Andric     unsigned TempReg = Inst.getOperand(1).getReg();
3474fe6060f1SDimitry Andric     if (DestReg == TempReg) {
3475fe6060f1SDimitry Andric       SMLoc Loc = Operands.back()->getStartLoc();
3476*0fca6ea1SDimitry Andric       return Error(Loc, "the temporary vector register cannot be the same as "
3477*0fca6ea1SDimitry Andric                         "the destination register");
3478fe6060f1SDimitry Andric     }
3479fe6060f1SDimitry Andric   }
3480fe6060f1SDimitry Andric 
348106c3fb27SDimitry Andric   if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
348206c3fb27SDimitry Andric       Opcode == RISCV::TH_LWD) {
348306c3fb27SDimitry Andric     unsigned Rd1 = Inst.getOperand(0).getReg();
348406c3fb27SDimitry Andric     unsigned Rd2 = Inst.getOperand(1).getReg();
348506c3fb27SDimitry Andric     unsigned Rs1 = Inst.getOperand(2).getReg();
348606c3fb27SDimitry Andric     // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
348706c3fb27SDimitry Andric     if (Rs1 == Rd1 && Rs1 == Rd2) {
348806c3fb27SDimitry Andric       SMLoc Loc = Operands[1]->getStartLoc();
3489*0fca6ea1SDimitry Andric       return Error(Loc, "rs1, rd1, and rd2 cannot all be the same");
349006c3fb27SDimitry Andric     }
349106c3fb27SDimitry Andric   }
349206c3fb27SDimitry Andric 
349306c3fb27SDimitry Andric   if (Opcode == RISCV::CM_MVSA01) {
349406c3fb27SDimitry Andric     unsigned Rd1 = Inst.getOperand(0).getReg();
349506c3fb27SDimitry Andric     unsigned Rd2 = Inst.getOperand(1).getReg();
349606c3fb27SDimitry Andric     if (Rd1 == Rd2) {
349706c3fb27SDimitry Andric       SMLoc Loc = Operands[1]->getStartLoc();
3498*0fca6ea1SDimitry Andric       return Error(Loc, "rs1 and rs2 must be different");
349906c3fb27SDimitry Andric     }
350006c3fb27SDimitry Andric   }
350106c3fb27SDimitry Andric 
350206c3fb27SDimitry Andric   bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
350306c3fb27SDimitry Andric                            Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
350406c3fb27SDimitry Andric   bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
350506c3fb27SDimitry Andric   // The last operand of XTHeadMemPair instructions must be constant 3 or 4
350606c3fb27SDimitry Andric   // depending on the data width.
350706c3fb27SDimitry Andric   if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) {
350806c3fb27SDimitry Andric     SMLoc Loc = Operands.back()->getStartLoc();
3509*0fca6ea1SDimitry Andric     return Error(Loc, "operand must be constant 3");
351006c3fb27SDimitry Andric   } else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) {
351106c3fb27SDimitry Andric     SMLoc Loc = Operands.back()->getStartLoc();
3512*0fca6ea1SDimitry Andric     return Error(Loc, "operand must be constant 4");
351306c3fb27SDimitry Andric   }
351406c3fb27SDimitry Andric 
351506c3fb27SDimitry Andric   const MCInstrDesc &MCID = MII.get(Opcode);
351606c3fb27SDimitry Andric   if (!(MCID.TSFlags & RISCVII::ConstraintMask))
35175ffd83dbSDimitry Andric     return false;
35185ffd83dbSDimitry Andric 
351906c3fb27SDimitry Andric   if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
352006c3fb27SDimitry Andric       Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
352106c3fb27SDimitry Andric     // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
352206c3fb27SDimitry Andric     unsigned VCIXDst = Inst.getOperand(0).getReg();
352306c3fb27SDimitry Andric     SMLoc VCIXDstLoc = Operands[2]->getStartLoc();
352406c3fb27SDimitry Andric     if (MCID.TSFlags & RISCVII::VS1Constraint) {
352506c3fb27SDimitry Andric       unsigned VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
352606c3fb27SDimitry Andric       if (VCIXDst == VCIXRs1)
3527*0fca6ea1SDimitry Andric         return Error(VCIXDstLoc, "the destination vector register group cannot"
3528*0fca6ea1SDimitry Andric                                  " overlap the source vector register group");
352906c3fb27SDimitry Andric     }
353006c3fb27SDimitry Andric     if (MCID.TSFlags & RISCVII::VS2Constraint) {
353106c3fb27SDimitry Andric       unsigned VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();
353206c3fb27SDimitry Andric       if (VCIXDst == VCIXRs2)
3533*0fca6ea1SDimitry Andric         return Error(VCIXDstLoc, "the destination vector register group cannot"
3534*0fca6ea1SDimitry Andric                                  " overlap the source vector register group");
353506c3fb27SDimitry Andric     }
353606c3fb27SDimitry Andric     return false;
353706c3fb27SDimitry Andric   }
353806c3fb27SDimitry Andric 
35395ffd83dbSDimitry Andric   unsigned DestReg = Inst.getOperand(0).getReg();
35405f757f3fSDimitry Andric   unsigned Offset = 0;
35415f757f3fSDimitry Andric   int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);
35425f757f3fSDimitry Andric   if (TiedOp == 0)
35435f757f3fSDimitry Andric     Offset = 1;
35445f757f3fSDimitry Andric 
35455ffd83dbSDimitry Andric   // Operands[1] will be the first operand, DestReg.
35465ffd83dbSDimitry Andric   SMLoc Loc = Operands[1]->getStartLoc();
354706c3fb27SDimitry Andric   if (MCID.TSFlags & RISCVII::VS2Constraint) {
35485f757f3fSDimitry Andric     unsigned CheckReg = Inst.getOperand(Offset + 1).getReg();
3549e8d8bef9SDimitry Andric     if (DestReg == CheckReg)
3550*0fca6ea1SDimitry Andric       return Error(Loc, "the destination vector register group cannot overlap"
3551*0fca6ea1SDimitry Andric                         " the source vector register group");
35525ffd83dbSDimitry Andric   }
35535f757f3fSDimitry Andric   if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {
35545f757f3fSDimitry Andric     unsigned CheckReg = Inst.getOperand(Offset + 2).getReg();
3555e8d8bef9SDimitry Andric     if (DestReg == CheckReg)
3556*0fca6ea1SDimitry Andric       return Error(Loc, "the destination vector register group cannot overlap"
3557*0fca6ea1SDimitry Andric                         " the source vector register group");
35585ffd83dbSDimitry Andric   }
355906c3fb27SDimitry Andric   if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
3560e8d8bef9SDimitry Andric     // vadc, vsbc are special cases. These instructions have no mask register.
3561e8d8bef9SDimitry Andric     // The destination register could not be V0.
3562e8d8bef9SDimitry Andric     if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3563e8d8bef9SDimitry Andric         Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3564e8d8bef9SDimitry Andric         Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3565e8d8bef9SDimitry Andric         Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3566e8d8bef9SDimitry Andric         Opcode == RISCV::VMERGE_VXM)
3567*0fca6ea1SDimitry Andric       return Error(Loc, "the destination vector register group cannot be V0");
35685ffd83dbSDimitry Andric 
3569e8d8bef9SDimitry Andric     // Regardless masked or unmasked version, the number of operands is the
3570e8d8bef9SDimitry Andric     // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3571e8d8bef9SDimitry Andric     // actually. We need to check the last operand to ensure whether it is
3572e8d8bef9SDimitry Andric     // masked or not.
3573e8d8bef9SDimitry Andric     unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3574e8d8bef9SDimitry Andric     assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
3575e8d8bef9SDimitry Andric            "Unexpected register for mask operand");
3576e8d8bef9SDimitry Andric 
3577e8d8bef9SDimitry Andric     if (DestReg == CheckReg)
3578*0fca6ea1SDimitry Andric       return Error(Loc, "the destination vector register group cannot overlap"
3579*0fca6ea1SDimitry Andric                         " the mask register");
35805ffd83dbSDimitry Andric   }
35815ffd83dbSDimitry Andric   return false;
35825ffd83dbSDimitry Andric }
35835ffd83dbSDimitry Andric 
35840b57cec5SDimitry Andric bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
35850b57cec5SDimitry Andric                                         OperandVector &Operands,
35860b57cec5SDimitry Andric                                         MCStreamer &Out) {
35870b57cec5SDimitry Andric   Inst.setLoc(IDLoc);
35880b57cec5SDimitry Andric 
35890b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
35900b57cec5SDimitry Andric   default:
35910b57cec5SDimitry Andric     break;
359206c3fb27SDimitry Andric   case RISCV::PseudoLLAImm:
359306c3fb27SDimitry Andric   case RISCV::PseudoLAImm:
35940b57cec5SDimitry Andric   case RISCV::PseudoLI: {
3595e8d8bef9SDimitry Andric     MCRegister Reg = Inst.getOperand(0).getReg();
35960b57cec5SDimitry Andric     const MCOperand &Op1 = Inst.getOperand(1);
35970b57cec5SDimitry Andric     if (Op1.isExpr()) {
35980b57cec5SDimitry Andric       // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
35990b57cec5SDimitry Andric       // Just convert to an addi. This allows compatibility with gas.
36000b57cec5SDimitry Andric       emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
36010b57cec5SDimitry Andric                               .addReg(Reg)
36020b57cec5SDimitry Andric                               .addReg(RISCV::X0)
36030b57cec5SDimitry Andric                               .addExpr(Op1.getExpr()));
36040b57cec5SDimitry Andric       return false;
36050b57cec5SDimitry Andric     }
36060b57cec5SDimitry Andric     int64_t Imm = Inst.getOperand(1).getImm();
36070b57cec5SDimitry Andric     // On RV32 the immediate here can either be a signed or an unsigned
36080b57cec5SDimitry Andric     // 32-bit number. Sign extension has to be performed to ensure that Imm
36090b57cec5SDimitry Andric     // represents the expected signed 64-bit number.
36100b57cec5SDimitry Andric     if (!isRV64())
36110b57cec5SDimitry Andric       Imm = SignExtend64<32>(Imm);
36120b57cec5SDimitry Andric     emitLoadImm(Reg, Imm, Out);
36130b57cec5SDimitry Andric     return false;
36140b57cec5SDimitry Andric   }
36150b57cec5SDimitry Andric   case RISCV::PseudoLLA:
36160b57cec5SDimitry Andric     emitLoadLocalAddress(Inst, IDLoc, Out);
36170b57cec5SDimitry Andric     return false;
361806c3fb27SDimitry Andric   case RISCV::PseudoLGA:
361906c3fb27SDimitry Andric     emitLoadGlobalAddress(Inst, IDLoc, Out);
362006c3fb27SDimitry Andric     return false;
36210b57cec5SDimitry Andric   case RISCV::PseudoLA:
36220b57cec5SDimitry Andric     emitLoadAddress(Inst, IDLoc, Out);
36230b57cec5SDimitry Andric     return false;
36240b57cec5SDimitry Andric   case RISCV::PseudoLA_TLS_IE:
36250b57cec5SDimitry Andric     emitLoadTLSIEAddress(Inst, IDLoc, Out);
36260b57cec5SDimitry Andric     return false;
36270b57cec5SDimitry Andric   case RISCV::PseudoLA_TLS_GD:
36280b57cec5SDimitry Andric     emitLoadTLSGDAddress(Inst, IDLoc, Out);
36290b57cec5SDimitry Andric     return false;
36300b57cec5SDimitry Andric   case RISCV::PseudoLB:
36310b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
36320b57cec5SDimitry Andric     return false;
36330b57cec5SDimitry Andric   case RISCV::PseudoLBU:
36340b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
36350b57cec5SDimitry Andric     return false;
36360b57cec5SDimitry Andric   case RISCV::PseudoLH:
36370b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
36380b57cec5SDimitry Andric     return false;
36390b57cec5SDimitry Andric   case RISCV::PseudoLHU:
36400b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
36410b57cec5SDimitry Andric     return false;
36420b57cec5SDimitry Andric   case RISCV::PseudoLW:
36430b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
36440b57cec5SDimitry Andric     return false;
36450b57cec5SDimitry Andric   case RISCV::PseudoLWU:
36460b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
36470b57cec5SDimitry Andric     return false;
36480b57cec5SDimitry Andric   case RISCV::PseudoLD:
36490b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
36500b57cec5SDimitry Andric     return false;
3651e8d8bef9SDimitry Andric   case RISCV::PseudoFLH:
3652e8d8bef9SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
3653e8d8bef9SDimitry Andric     return false;
36540b57cec5SDimitry Andric   case RISCV::PseudoFLW:
36550b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
36560b57cec5SDimitry Andric     return false;
36570b57cec5SDimitry Andric   case RISCV::PseudoFLD:
36580b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
36590b57cec5SDimitry Andric     return false;
36600b57cec5SDimitry Andric   case RISCV::PseudoSB:
36610b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
36620b57cec5SDimitry Andric     return false;
36630b57cec5SDimitry Andric   case RISCV::PseudoSH:
36640b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
36650b57cec5SDimitry Andric     return false;
36660b57cec5SDimitry Andric   case RISCV::PseudoSW:
36670b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
36680b57cec5SDimitry Andric     return false;
36690b57cec5SDimitry Andric   case RISCV::PseudoSD:
36700b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
36710b57cec5SDimitry Andric     return false;
3672e8d8bef9SDimitry Andric   case RISCV::PseudoFSH:
3673e8d8bef9SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
3674e8d8bef9SDimitry Andric     return false;
36750b57cec5SDimitry Andric   case RISCV::PseudoFSW:
36760b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
36770b57cec5SDimitry Andric     return false;
36780b57cec5SDimitry Andric   case RISCV::PseudoFSD:
36790b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
36800b57cec5SDimitry Andric     return false;
36810b57cec5SDimitry Andric   case RISCV::PseudoAddTPRel:
36820b57cec5SDimitry Andric     if (checkPseudoAddTPRel(Inst, Operands))
36830b57cec5SDimitry Andric       return true;
36840b57cec5SDimitry Andric     break;
36857a6dacacSDimitry Andric   case RISCV::PseudoTLSDESCCall:
36867a6dacacSDimitry Andric     if (checkPseudoTLSDESCCall(Inst, Operands))
36877a6dacacSDimitry Andric       return true;
36887a6dacacSDimitry Andric     break;
3689e8d8bef9SDimitry Andric   case RISCV::PseudoSEXT_B:
3690e8d8bef9SDimitry Andric     emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
3691e8d8bef9SDimitry Andric     return false;
3692e8d8bef9SDimitry Andric   case RISCV::PseudoSEXT_H:
3693e8d8bef9SDimitry Andric     emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
3694e8d8bef9SDimitry Andric     return false;
3695e8d8bef9SDimitry Andric   case RISCV::PseudoZEXT_H:
3696e8d8bef9SDimitry Andric     emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
3697e8d8bef9SDimitry Andric     return false;
3698e8d8bef9SDimitry Andric   case RISCV::PseudoZEXT_W:
3699e8d8bef9SDimitry Andric     emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
3700e8d8bef9SDimitry Andric     return false;
3701e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGEU_VX:
3702e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGEU_VX_M:
3703e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGEU_VX_M_T:
3704e8d8bef9SDimitry Andric     emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3705e8d8bef9SDimitry Andric     return false;
3706e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGE_VX:
3707e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGE_VX_M:
3708e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGE_VX_M_T:
3709e8d8bef9SDimitry Andric     emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3710e8d8bef9SDimitry Andric     return false;
3711e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGE_VI:
3712e8d8bef9SDimitry Andric   case RISCV::PseudoVMSLT_VI: {
3713e8d8bef9SDimitry Andric     // These instructions are signed and so is immediate so we can subtract one
3714e8d8bef9SDimitry Andric     // and change the opcode.
3715e8d8bef9SDimitry Andric     int64_t Imm = Inst.getOperand(2).getImm();
3716e8d8bef9SDimitry Andric     unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3717e8d8bef9SDimitry Andric                                                              : RISCV::VMSLE_VI;
3718e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opc)
3719e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3720e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(1))
3721e8d8bef9SDimitry Andric                             .addImm(Imm - 1)
3722*0fca6ea1SDimitry Andric                             .addOperand(Inst.getOperand(3))
3723*0fca6ea1SDimitry Andric                             .setLoc(IDLoc));
3724e8d8bef9SDimitry Andric     return false;
3725e8d8bef9SDimitry Andric   }
3726e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGEU_VI:
3727e8d8bef9SDimitry Andric   case RISCV::PseudoVMSLTU_VI: {
3728e8d8bef9SDimitry Andric     int64_t Imm = Inst.getOperand(2).getImm();
3729e8d8bef9SDimitry Andric     // Unsigned comparisons are tricky because the immediate is signed. If the
3730e8d8bef9SDimitry Andric     // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3731e8d8bef9SDimitry Andric     // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3732e8d8bef9SDimitry Andric     // vmsne v0, v1, v1 which is always false.
3733e8d8bef9SDimitry Andric     if (Imm == 0) {
3734e8d8bef9SDimitry Andric       unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3735e8d8bef9SDimitry Andric                          ? RISCV::VMSEQ_VV
3736e8d8bef9SDimitry Andric                          : RISCV::VMSNE_VV;
3737e8d8bef9SDimitry Andric       emitToStreamer(Out, MCInstBuilder(Opc)
3738e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(0))
3739e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(1))
3740e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(1))
3741*0fca6ea1SDimitry Andric                               .addOperand(Inst.getOperand(3))
3742*0fca6ea1SDimitry Andric                               .setLoc(IDLoc));
3743e8d8bef9SDimitry Andric     } else {
3744e8d8bef9SDimitry Andric       // Other immediate values can subtract one like signed.
3745e8d8bef9SDimitry Andric       unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3746e8d8bef9SDimitry Andric                          ? RISCV::VMSGTU_VI
3747e8d8bef9SDimitry Andric                          : RISCV::VMSLEU_VI;
3748e8d8bef9SDimitry Andric       emitToStreamer(Out, MCInstBuilder(Opc)
3749e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(0))
3750e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(1))
3751e8d8bef9SDimitry Andric                               .addImm(Imm - 1)
3752*0fca6ea1SDimitry Andric                               .addOperand(Inst.getOperand(3))
3753*0fca6ea1SDimitry Andric                               .setLoc(IDLoc));
3754e8d8bef9SDimitry Andric     }
3755e8d8bef9SDimitry Andric 
3756e8d8bef9SDimitry Andric     return false;
3757e8d8bef9SDimitry Andric   }
37580b57cec5SDimitry Andric   }
37590b57cec5SDimitry Andric 
37600b57cec5SDimitry Andric   emitToStreamer(Out, Inst);
37610b57cec5SDimitry Andric   return false;
37620b57cec5SDimitry Andric }
37630b57cec5SDimitry Andric 
3764480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser() {
37650b57cec5SDimitry Andric   RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
37660b57cec5SDimitry Andric   RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
37670b57cec5SDimitry Andric }
3768