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"
41349cc55cSDimitry Andric #include "llvm/Support/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 
getLoc() const840b57cec5SDimitry Andric   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
isRV64() const850b57cec5SDimitry Andric   bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
isRVE() const8606c3fb27SDimitry Andric   bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureRVE); }
870b57cec5SDimitry Andric 
getTargetStreamer()880b57cec5SDimitry Andric   RISCVTargetStreamer &getTargetStreamer() {
89bdd1243dSDimitry Andric     assert(getParser().getStreamer().getTargetStreamer() &&
90bdd1243dSDimitry Andric            "do not have a target streamer");
910b57cec5SDimitry Andric     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
920b57cec5SDimitry Andric     return static_cast<RISCVTargetStreamer &>(TS);
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
960b57cec5SDimitry Andric                                       unsigned Kind) override;
9706c3fb27SDimitry Andric   unsigned checkTargetMatchPredicate(MCInst &Inst) override;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
10006c3fb27SDimitry Andric                                   int64_t Lower, int64_t Upper,
10106c3fb27SDimitry Andric                                   const Twine &Msg);
10206c3fb27SDimitry Andric   bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
10306c3fb27SDimitry Andric                                   const Twine &Msg);
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1060b57cec5SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
1070b57cec5SDimitry Andric                                uint64_t &ErrorInfo,
1080b57cec5SDimitry Andric                                bool MatchingInlineAsm) override;
1090b57cec5SDimitry Andric 
1105f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1115f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1125ffd83dbSDimitry Andric                                SMLoc &EndLoc) override;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1150b57cec5SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
1160b57cec5SDimitry Andric 
11706c3fb27SDimitry Andric   ParseStatus parseDirective(AsmToken DirectiveID) override;
11806c3fb27SDimitry Andric 
11906c3fb27SDimitry Andric   bool parseVTypeToken(StringRef Identifier, VTypeState &State, unsigned &Sew,
12006c3fb27SDimitry Andric                        unsigned &Lmul, bool &Fractional, bool &TailAgnostic,
12106c3fb27SDimitry Andric                        bool &MaskAgnostic);
12206c3fb27SDimitry Andric   bool generateVTypeError(SMLoc ErrorLoc);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   // Helper to actually emit an instruction to the MCStreamer. Also, when
1250b57cec5SDimitry Andric   // possible, compression of the instruction is performed.
1260b57cec5SDimitry Andric   void emitToStreamer(MCStreamer &S, const MCInst &Inst);
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
1290b57cec5SDimitry Andric   // synthesize the desired immedate value into the destination register.
130e8d8bef9SDimitry Andric   void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
1330b57cec5SDimitry Andric   // helpers such as emitLoadLocalAddress and emitLoadAddress.
1340b57cec5SDimitry Andric   void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
1350b57cec5SDimitry Andric                          const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
1360b57cec5SDimitry Andric                          unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
1390b57cec5SDimitry Andric   void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1400b57cec5SDimitry Andric 
14106c3fb27SDimitry Andric   // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
14206c3fb27SDimitry Andric   void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
14306c3fb27SDimitry Andric 
1440b57cec5SDimitry Andric   // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
1450b57cec5SDimitry Andric   void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
1480b57cec5SDimitry Andric   // addressing.
1490b57cec5SDimitry Andric   void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
1520b57cec5SDimitry Andric   // addressing.
1530b57cec5SDimitry Andric   void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   // Helper to emit pseudo load/store instruction with a symbol.
1560b57cec5SDimitry Andric   void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
1570b57cec5SDimitry Andric                            MCStreamer &Out, bool HasTmpReg);
1580b57cec5SDimitry Andric 
159e8d8bef9SDimitry Andric   // Helper to emit pseudo sign/zero extend instruction.
160e8d8bef9SDimitry Andric   void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
161e8d8bef9SDimitry Andric                         SMLoc IDLoc, MCStreamer &Out);
162e8d8bef9SDimitry Andric 
163e8d8bef9SDimitry Andric   // Helper to emit pseudo vmsge{u}.vx instruction.
164e8d8bef9SDimitry Andric   void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
165e8d8bef9SDimitry Andric 
1660b57cec5SDimitry Andric   // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
1670b57cec5SDimitry Andric   // Enforcing this using a restricted register class for the second input
1680b57cec5SDimitry Andric   // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
1690b57cec5SDimitry Andric   // 'add' is an overloaded mnemonic.
1700b57cec5SDimitry Andric   bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
1710b57cec5SDimitry Andric 
1727a6dacacSDimitry Andric   // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.
1737a6dacacSDimitry Andric   // Enforcing this using a restricted register class for the output
1747a6dacacSDimitry Andric   // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact
1757a6dacacSDimitry Andric   // 'jalr' is an overloaded mnemonic.
1767a6dacacSDimitry Andric   bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands);
1777a6dacacSDimitry Andric 
1785ffd83dbSDimitry Andric   // Check instruction constraints.
1795ffd83dbSDimitry Andric   bool validateInstruction(MCInst &Inst, OperandVector &Operands);
1805ffd83dbSDimitry Andric 
1810b57cec5SDimitry Andric   /// Helper for processing MC instructions that have been successfully matched
1820b57cec5SDimitry Andric   /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
1830b57cec5SDimitry Andric   /// like the expansion of pseudo instructions (e.g., "li"), can be performed
1840b57cec5SDimitry Andric   /// in this method.
1850b57cec5SDimitry Andric   bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
1860b57cec5SDimitry Andric                           MCStreamer &Out);
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric // Auto-generated instruction matching functions
1890b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
1900b57cec5SDimitry Andric #include "RISCVGenAsmMatcher.inc"
1910b57cec5SDimitry Andric 
19206c3fb27SDimitry Andric   ParseStatus parseCSRSystemRegister(OperandVector &Operands);
19306c3fb27SDimitry Andric   ParseStatus parseFPImm(OperandVector &Operands);
19406c3fb27SDimitry Andric   ParseStatus parseImmediate(OperandVector &Operands);
19506c3fb27SDimitry Andric   ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);
19606c3fb27SDimitry Andric   ParseStatus parseMemOpBaseReg(OperandVector &Operands);
19706c3fb27SDimitry Andric   ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);
19806c3fb27SDimitry Andric   ParseStatus parseOperandWithModifier(OperandVector &Operands);
19906c3fb27SDimitry Andric   ParseStatus parseBareSymbol(OperandVector &Operands);
20006c3fb27SDimitry Andric   ParseStatus parseCallSymbol(OperandVector &Operands);
20106c3fb27SDimitry Andric   ParseStatus parsePseudoJumpSymbol(OperandVector &Operands);
20206c3fb27SDimitry Andric   ParseStatus parseJALOffset(OperandVector &Operands);
20306c3fb27SDimitry Andric   ParseStatus parseVTypeI(OperandVector &Operands);
20406c3fb27SDimitry Andric   ParseStatus parseMaskReg(OperandVector &Operands);
20506c3fb27SDimitry Andric   ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);
20606c3fb27SDimitry Andric   ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);
20706c3fb27SDimitry Andric   ParseStatus parseGPRAsFPR(OperandVector &Operands);
208297eecfbSDimitry Andric   template <bool IsRV64Inst> ParseStatus parseGPRPair(OperandVector &Operands);
209297eecfbSDimitry Andric   ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);
21006c3fb27SDimitry Andric   ParseStatus parseFRMArg(OperandVector &Operands);
21106c3fb27SDimitry Andric   ParseStatus parseFenceArg(OperandVector &Operands);
21206c3fb27SDimitry Andric   ParseStatus parseReglist(OperandVector &Operands);
2135f757f3fSDimitry Andric   ParseStatus parseRegReg(OperandVector &Operands);
21406c3fb27SDimitry Andric   ParseStatus parseRetval(OperandVector &Operands);
21506c3fb27SDimitry Andric   ParseStatus parseZcmpSpimm(OperandVector &Operands);
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   bool parseDirectiveOption();
2205ffd83dbSDimitry Andric   bool parseDirectiveAttribute();
221349cc55cSDimitry Andric   bool parseDirectiveInsn(SMLoc L);
222bdd1243dSDimitry Andric   bool parseDirectiveVariantCC();
2230b57cec5SDimitry Andric 
22406c3fb27SDimitry Andric   /// Helper to reset target features for a new arch string. It
22506c3fb27SDimitry Andric   /// also records the new arch string that is expanded by RISCVISAInfo
22606c3fb27SDimitry Andric   /// and reports error for invalid arch string.
22706c3fb27SDimitry Andric   bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
22806c3fb27SDimitry Andric                    bool FromOptionDirective);
22906c3fb27SDimitry Andric 
setFeatureBits(uint64_t Feature,StringRef FeatureString)2300b57cec5SDimitry Andric   void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
23106c3fb27SDimitry Andric     if (!(getSTI().hasFeature(Feature))) {
2320b57cec5SDimitry Andric       MCSubtargetInfo &STI = copySTI();
2330b57cec5SDimitry Andric       setAvailableFeatures(
2340b57cec5SDimitry Andric           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
2350b57cec5SDimitry Andric     }
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric 
clearFeatureBits(uint64_t Feature,StringRef FeatureString)2380b57cec5SDimitry Andric   void clearFeatureBits(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 
pushFeatureBits()2460b57cec5SDimitry Andric   void pushFeatureBits() {
2475ffd83dbSDimitry Andric     assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
2485ffd83dbSDimitry Andric            "These two stacks must be kept synchronized");
2490b57cec5SDimitry Andric     FeatureBitStack.push_back(getSTI().getFeatureBits());
2505ffd83dbSDimitry Andric     ParserOptionsStack.push_back(ParserOptions);
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric 
popFeatureBits()2530b57cec5SDimitry Andric   bool popFeatureBits() {
2545ffd83dbSDimitry Andric     assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
2555ffd83dbSDimitry Andric            "These two stacks must be kept synchronized");
2560b57cec5SDimitry Andric     if (FeatureBitStack.empty())
2570b57cec5SDimitry Andric       return true;
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric     FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
2600b57cec5SDimitry Andric     copySTI().setFeatureBits(FeatureBits);
2610b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
2620b57cec5SDimitry Andric 
2635ffd83dbSDimitry Andric     ParserOptions = ParserOptionsStack.pop_back_val();
2645ffd83dbSDimitry Andric 
2650b57cec5SDimitry Andric     return false;
2660b57cec5SDimitry Andric   }
2675ffd83dbSDimitry Andric 
2685ffd83dbSDimitry Andric   std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
26906c3fb27SDimitry Andric   std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
2705f757f3fSDimitry Andric   std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;
2715ffd83dbSDimitry Andric 
2720b57cec5SDimitry Andric public:
2730b57cec5SDimitry Andric   enum RISCVMatchResultTy {
2740b57cec5SDimitry Andric     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
27506c3fb27SDimitry Andric     Match_RequiresEvenGPRs,
2760b57cec5SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
2770b57cec5SDimitry Andric #include "RISCVGenAsmMatcher.inc"
2780b57cec5SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES
2790b57cec5SDimitry Andric   };
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   static bool classifySymbolRef(const MCExpr *Expr,
282e8d8bef9SDimitry Andric                                 RISCVMCExpr::VariantKind &Kind);
28306c3fb27SDimitry Andric   static bool isSymbolDiff(const MCExpr *Expr);
2840b57cec5SDimitry Andric 
RISCVAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)2850b57cec5SDimitry Andric   RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
2860b57cec5SDimitry Andric                  const MCInstrInfo &MII, const MCTargetOptions &Options)
2870b57cec5SDimitry Andric       : MCTargetAsmParser(Options, STI, MII) {
28806c3fb27SDimitry Andric     MCAsmParserExtension::Initialize(Parser);
28906c3fb27SDimitry Andric 
2900b57cec5SDimitry Andric     Parser.addAliasForDirective(".half", ".2byte");
2910b57cec5SDimitry Andric     Parser.addAliasForDirective(".hword", ".2byte");
2920b57cec5SDimitry Andric     Parser.addAliasForDirective(".word", ".4byte");
2930b57cec5SDimitry Andric     Parser.addAliasForDirective(".dword", ".8byte");
2940b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
295480093f4SDimitry Andric 
29613138422SDimitry Andric     auto ABIName = StringRef(Options.ABIName);
2975f757f3fSDimitry Andric     if (ABIName.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
298480093f4SDimitry Andric       errs() << "Hard-float 'f' ABI can't be used for a target that "
299480093f4SDimitry Andric                 "doesn't support the F instruction set extension (ignoring "
300480093f4SDimitry Andric                 "target-abi)\n";
3015f757f3fSDimitry Andric     } else if (ABIName.ends_with("d") &&
30206c3fb27SDimitry Andric                !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
303480093f4SDimitry Andric       errs() << "Hard-float 'd' ABI can't be used for a target that "
304480093f4SDimitry Andric                 "doesn't support the D instruction set extension (ignoring "
305480093f4SDimitry Andric                 "target-abi)\n";
306480093f4SDimitry Andric     }
3075ffd83dbSDimitry Andric 
30881ad6265SDimitry Andric     // Use computeTargetABI to check if ABIName is valid. If invalid, output
30981ad6265SDimitry Andric     // error message.
31081ad6265SDimitry Andric     RISCVABI::computeTargetABI(STI.getTargetTriple(), STI.getFeatureBits(),
31181ad6265SDimitry Andric                                ABIName);
31281ad6265SDimitry Andric 
3135ffd83dbSDimitry Andric     const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
3145ffd83dbSDimitry Andric     ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
31506c3fb27SDimitry Andric 
31606c3fb27SDimitry Andric     if (AddBuildAttributes)
31706c3fb27SDimitry Andric       getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);
3180b57cec5SDimitry Andric   }
3190b57cec5SDimitry Andric };
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric /// RISCVOperand - Instances of this class represent a parsed machine
3220b57cec5SDimitry Andric /// instruction
32306c3fb27SDimitry Andric struct RISCVOperand final : public MCParsedAsmOperand {
3240b57cec5SDimitry Andric 
3258bcb0991SDimitry Andric   enum class KindTy {
3260b57cec5SDimitry Andric     Token,
3270b57cec5SDimitry Andric     Register,
3280b57cec5SDimitry Andric     Immediate,
32906c3fb27SDimitry Andric     FPImmediate,
3305ffd83dbSDimitry Andric     SystemRegister,
3315ffd83dbSDimitry Andric     VType,
33206c3fb27SDimitry Andric     FRM,
33306c3fb27SDimitry Andric     Fence,
33406c3fb27SDimitry Andric     Rlist,
33506c3fb27SDimitry Andric     Spimm,
3365f757f3fSDimitry Andric     RegReg,
3370b57cec5SDimitry Andric   } Kind;
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   struct RegOp {
340e8d8bef9SDimitry Andric     MCRegister RegNum;
34106c3fb27SDimitry Andric     bool IsGPRAsFPR;
3420b57cec5SDimitry Andric   };
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   struct ImmOp {
3450b57cec5SDimitry Andric     const MCExpr *Val;
34606c3fb27SDimitry Andric     bool IsRV64;
34706c3fb27SDimitry Andric   };
34806c3fb27SDimitry Andric 
34906c3fb27SDimitry Andric   struct FPImmOp {
35006c3fb27SDimitry Andric     uint64_t Val;
3510b57cec5SDimitry Andric   };
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   struct SysRegOp {
3540b57cec5SDimitry Andric     const char *Data;
3550b57cec5SDimitry Andric     unsigned Length;
3560b57cec5SDimitry Andric     unsigned Encoding;
3570b57cec5SDimitry Andric     // FIXME: Add the Encoding parsed fields as needed for checks,
3580b57cec5SDimitry Andric     // e.g.: read/write or user/supervisor/machine privileges.
3590b57cec5SDimitry Andric   };
3600b57cec5SDimitry Andric 
3615ffd83dbSDimitry Andric   struct VTypeOp {
362e8d8bef9SDimitry Andric     unsigned Val;
3635ffd83dbSDimitry Andric   };
3645ffd83dbSDimitry Andric 
36506c3fb27SDimitry Andric   struct FRMOp {
36606c3fb27SDimitry Andric     RISCVFPRndMode::RoundingMode FRM;
36706c3fb27SDimitry Andric   };
36806c3fb27SDimitry Andric 
36906c3fb27SDimitry Andric   struct FenceOp {
37006c3fb27SDimitry Andric     unsigned Val;
37106c3fb27SDimitry Andric   };
37206c3fb27SDimitry Andric 
37306c3fb27SDimitry Andric   struct RlistOp {
37406c3fb27SDimitry Andric     unsigned Val;
37506c3fb27SDimitry Andric   };
37606c3fb27SDimitry Andric 
37706c3fb27SDimitry Andric   struct SpimmOp {
37806c3fb27SDimitry Andric     unsigned Val;
37906c3fb27SDimitry Andric   };
38006c3fb27SDimitry Andric 
3815f757f3fSDimitry Andric   struct RegRegOp {
3825f757f3fSDimitry Andric     MCRegister Reg1;
3835f757f3fSDimitry Andric     MCRegister Reg2;
3845f757f3fSDimitry Andric   };
3855f757f3fSDimitry Andric 
3860b57cec5SDimitry Andric   SMLoc StartLoc, EndLoc;
3870b57cec5SDimitry Andric   union {
3880b57cec5SDimitry Andric     StringRef Tok;
3890b57cec5SDimitry Andric     RegOp Reg;
3900b57cec5SDimitry Andric     ImmOp Imm;
39106c3fb27SDimitry Andric     FPImmOp FPImm;
3920b57cec5SDimitry Andric     struct SysRegOp SysReg;
3935ffd83dbSDimitry Andric     struct VTypeOp VType;
39406c3fb27SDimitry Andric     struct FRMOp FRM;
39506c3fb27SDimitry Andric     struct FenceOp Fence;
39606c3fb27SDimitry Andric     struct RlistOp Rlist;
39706c3fb27SDimitry Andric     struct SpimmOp Spimm;
3985f757f3fSDimitry Andric     struct RegRegOp RegReg;
3990b57cec5SDimitry Andric   };
4000b57cec5SDimitry Andric 
RISCVOperand__anon932ea4f60111::RISCVOperand40104eeddc0SDimitry Andric   RISCVOperand(KindTy K) : Kind(K) {}
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric public:
RISCVOperand__anon932ea4f60111::RISCVOperand4040b57cec5SDimitry Andric   RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
4050b57cec5SDimitry Andric     Kind = o.Kind;
4060b57cec5SDimitry Andric     StartLoc = o.StartLoc;
4070b57cec5SDimitry Andric     EndLoc = o.EndLoc;
4080b57cec5SDimitry Andric     switch (Kind) {
4098bcb0991SDimitry Andric     case KindTy::Register:
4100b57cec5SDimitry Andric       Reg = o.Reg;
4110b57cec5SDimitry Andric       break;
4128bcb0991SDimitry Andric     case KindTy::Immediate:
4130b57cec5SDimitry Andric       Imm = o.Imm;
4140b57cec5SDimitry Andric       break;
41506c3fb27SDimitry Andric     case KindTy::FPImmediate:
41606c3fb27SDimitry Andric       FPImm = o.FPImm;
41706c3fb27SDimitry Andric       break;
4188bcb0991SDimitry Andric     case KindTy::Token:
4190b57cec5SDimitry Andric       Tok = o.Tok;
4200b57cec5SDimitry Andric       break;
4218bcb0991SDimitry Andric     case KindTy::SystemRegister:
4220b57cec5SDimitry Andric       SysReg = o.SysReg;
4230b57cec5SDimitry Andric       break;
4245ffd83dbSDimitry Andric     case KindTy::VType:
4255ffd83dbSDimitry Andric       VType = o.VType;
4265ffd83dbSDimitry Andric       break;
42706c3fb27SDimitry Andric     case KindTy::FRM:
42806c3fb27SDimitry Andric       FRM = o.FRM;
42906c3fb27SDimitry Andric       break;
43006c3fb27SDimitry Andric     case KindTy::Fence:
43106c3fb27SDimitry Andric       Fence = o.Fence;
43206c3fb27SDimitry Andric       break;
43306c3fb27SDimitry Andric     case KindTy::Rlist:
43406c3fb27SDimitry Andric       Rlist = o.Rlist;
43506c3fb27SDimitry Andric       break;
43606c3fb27SDimitry Andric     case KindTy::Spimm:
43706c3fb27SDimitry Andric       Spimm = o.Spimm;
43806c3fb27SDimitry Andric       break;
4395f757f3fSDimitry Andric     case KindTy::RegReg:
4405f757f3fSDimitry Andric       RegReg = o.RegReg;
4415f757f3fSDimitry Andric       break;
4420b57cec5SDimitry Andric     }
4430b57cec5SDimitry Andric   }
4440b57cec5SDimitry Andric 
isToken__anon932ea4f60111::RISCVOperand4458bcb0991SDimitry Andric   bool isToken() const override { return Kind == KindTy::Token; }
isReg__anon932ea4f60111::RISCVOperand4468bcb0991SDimitry Andric   bool isReg() const override { return Kind == KindTy::Register; }
isV0Reg__anon932ea4f60111::RISCVOperand4475ffd83dbSDimitry Andric   bool isV0Reg() const {
4485ffd83dbSDimitry Andric     return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
4495ffd83dbSDimitry Andric   }
isAnyReg__anon932ea4f60111::RISCVOperand45006c3fb27SDimitry Andric   bool isAnyReg() const {
45106c3fb27SDimitry Andric     return Kind == KindTy::Register &&
45206c3fb27SDimitry Andric            (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum) ||
45306c3fb27SDimitry Andric             RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.RegNum) ||
45406c3fb27SDimitry Andric             RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.RegNum));
45506c3fb27SDimitry Andric   }
isAnyRegC__anon932ea4f60111::RISCVOperand45606c3fb27SDimitry Andric   bool isAnyRegC() const {
45706c3fb27SDimitry Andric     return Kind == KindTy::Register &&
45806c3fb27SDimitry Andric            (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
45906c3fb27SDimitry Andric                 Reg.RegNum) ||
46006c3fb27SDimitry Andric             RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
46106c3fb27SDimitry Andric                 Reg.RegNum));
46206c3fb27SDimitry Andric   }
isImm__anon932ea4f60111::RISCVOperand4638bcb0991SDimitry Andric   bool isImm() const override { return Kind == KindTy::Immediate; }
isMem__anon932ea4f60111::RISCVOperand4640b57cec5SDimitry Andric   bool isMem() const override { return false; }
isSystemRegister__anon932ea4f60111::RISCVOperand4658bcb0991SDimitry Andric   bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
isRegReg__anon932ea4f60111::RISCVOperand4665f757f3fSDimitry Andric   bool isRegReg() const { return Kind == KindTy::RegReg; }
isRlist__anon932ea4f60111::RISCVOperand46706c3fb27SDimitry Andric   bool isRlist() const { return Kind == KindTy::Rlist; }
isSpimm__anon932ea4f60111::RISCVOperand46806c3fb27SDimitry Andric   bool isSpimm() const { return Kind == KindTy::Spimm; }
4690b57cec5SDimitry Andric 
isGPR__anon932ea4f60111::RISCVOperand470480093f4SDimitry Andric   bool isGPR() const {
471480093f4SDimitry Andric     return Kind == KindTy::Register &&
472480093f4SDimitry Andric            RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
473480093f4SDimitry Andric   }
474480093f4SDimitry Andric 
isGPRAsFPR__anon932ea4f60111::RISCVOperand47506c3fb27SDimitry Andric   bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
476d56accc7SDimitry Andric 
isGPRPair__anon932ea4f60111::RISCVOperand477297eecfbSDimitry Andric   bool isGPRPair() const {
478297eecfbSDimitry Andric     return Kind == KindTy::Register &&
479297eecfbSDimitry Andric            RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
480297eecfbSDimitry Andric                Reg.RegNum);
481297eecfbSDimitry Andric   }
482297eecfbSDimitry Andric 
evaluateConstantImm__anon932ea4f60111::RISCVOperand4830b57cec5SDimitry Andric   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
4840b57cec5SDimitry Andric                                   RISCVMCExpr::VariantKind &VK) {
4850b57cec5SDimitry Andric     if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
4860b57cec5SDimitry Andric       VK = RE->getKind();
4870b57cec5SDimitry Andric       return RE->evaluateAsConstant(Imm);
4880b57cec5SDimitry Andric     }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
4910b57cec5SDimitry Andric       VK = RISCVMCExpr::VK_RISCV_None;
4920b57cec5SDimitry Andric       Imm = CE->getValue();
4930b57cec5SDimitry Andric       return true;
4940b57cec5SDimitry Andric     }
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric     return false;
4970b57cec5SDimitry Andric   }
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   // True if operand is a symbol with no modifiers, or a constant with no
5000b57cec5SDimitry Andric   // modifiers and isShiftedInt<N-1, 1>(Op).
isBareSimmNLsb0__anon932ea4f60111::RISCVOperand5010b57cec5SDimitry Andric   template <int N> bool isBareSimmNLsb0() const {
5020b57cec5SDimitry Andric     int64_t Imm;
5038bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5040b57cec5SDimitry Andric     if (!isImm())
5050b57cec5SDimitry Andric       return false;
5060b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
5070b57cec5SDimitry Andric     bool IsValid;
5080b57cec5SDimitry Andric     if (!IsConstantImm)
509e8d8bef9SDimitry Andric       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
5100b57cec5SDimitry Andric     else
5110b57cec5SDimitry Andric       IsValid = isShiftedInt<N - 1, 1>(Imm);
5120b57cec5SDimitry Andric     return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
5130b57cec5SDimitry Andric   }
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
5160b57cec5SDimitry Andric 
isBareSymbol__anon932ea4f60111::RISCVOperand5170b57cec5SDimitry Andric   bool isBareSymbol() const {
5180b57cec5SDimitry Andric     int64_t Imm;
5198bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5200b57cec5SDimitry Andric     // Must be of 'immediate' type but not a constant.
5210b57cec5SDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5220b57cec5SDimitry Andric       return false;
523e8d8bef9SDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5240b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
5250b57cec5SDimitry Andric   }
5260b57cec5SDimitry Andric 
isCallSymbol__anon932ea4f60111::RISCVOperand5270b57cec5SDimitry Andric   bool isCallSymbol() const {
5280b57cec5SDimitry Andric     int64_t Imm;
5298bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5300b57cec5SDimitry Andric     // Must be of 'immediate' type but not a constant.
5310b57cec5SDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5320b57cec5SDimitry Andric       return false;
533e8d8bef9SDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5340b57cec5SDimitry Andric            (VK == RISCVMCExpr::VK_RISCV_CALL ||
5350b57cec5SDimitry Andric             VK == RISCVMCExpr::VK_RISCV_CALL_PLT);
5360b57cec5SDimitry Andric   }
5370b57cec5SDimitry Andric 
isPseudoJumpSymbol__anon932ea4f60111::RISCVOperand5385ffd83dbSDimitry Andric   bool isPseudoJumpSymbol() const {
5395ffd83dbSDimitry Andric     int64_t Imm;
5405ffd83dbSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5415ffd83dbSDimitry Andric     // Must be of 'immediate' type but not a constant.
5425ffd83dbSDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5435ffd83dbSDimitry Andric       return false;
544e8d8bef9SDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5455ffd83dbSDimitry Andric            VK == RISCVMCExpr::VK_RISCV_CALL;
5465ffd83dbSDimitry Andric   }
5475ffd83dbSDimitry Andric 
isTPRelAddSymbol__anon932ea4f60111::RISCVOperand5480b57cec5SDimitry Andric   bool isTPRelAddSymbol() const {
5490b57cec5SDimitry Andric     int64_t Imm;
5508bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5510b57cec5SDimitry Andric     // Must be of 'immediate' type but not a constant.
5520b57cec5SDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5530b57cec5SDimitry Andric       return false;
554e8d8bef9SDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5550b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_TPREL_ADD;
5560b57cec5SDimitry Andric   }
5570b57cec5SDimitry Andric 
isTLSDESCCallSymbol__anon932ea4f60111::RISCVOperand5587a6dacacSDimitry Andric   bool isTLSDESCCallSymbol() const {
5597a6dacacSDimitry Andric     int64_t Imm;
5607a6dacacSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
5617a6dacacSDimitry Andric     // Must be of 'immediate' type but not a constant.
5627a6dacacSDimitry Andric     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
5637a6dacacSDimitry Andric       return false;
5647a6dacacSDimitry Andric     return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
5657a6dacacSDimitry Andric            VK == RISCVMCExpr::VK_RISCV_TLSDESC_CALL;
5667a6dacacSDimitry Andric   }
5677a6dacacSDimitry Andric 
isCSRSystemRegister__anon932ea4f60111::RISCVOperand5680b57cec5SDimitry Andric   bool isCSRSystemRegister() const { return isSystemRegister(); }
5690b57cec5SDimitry Andric 
isVTypeImm__anon932ea4f60111::RISCVOperand57004eeddc0SDimitry Andric   bool isVTypeImm(unsigned N) const {
57104eeddc0SDimitry Andric     int64_t Imm;
57204eeddc0SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
57304eeddc0SDimitry Andric     if (!isImm())
57404eeddc0SDimitry Andric       return false;
57504eeddc0SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
57604eeddc0SDimitry Andric     return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None;
57704eeddc0SDimitry Andric   }
57804eeddc0SDimitry Andric 
57904eeddc0SDimitry Andric   // If the last operand of the vsetvli/vsetvli instruction is a constant
58004eeddc0SDimitry Andric   // expression, KindTy is Immediate.
isVTypeI10__anon932ea4f60111::RISCVOperand58104eeddc0SDimitry Andric   bool isVTypeI10() const {
58204eeddc0SDimitry Andric     if (Kind == KindTy::Immediate)
58304eeddc0SDimitry Andric       return isVTypeImm(10);
58404eeddc0SDimitry Andric     return Kind == KindTy::VType;
58504eeddc0SDimitry Andric   }
isVTypeI11__anon932ea4f60111::RISCVOperand58604eeddc0SDimitry Andric   bool isVTypeI11() const {
58704eeddc0SDimitry Andric     if (Kind == KindTy::Immediate)
58804eeddc0SDimitry Andric       return isVTypeImm(11);
58904eeddc0SDimitry Andric     return Kind == KindTy::VType;
59004eeddc0SDimitry Andric   }
5915ffd83dbSDimitry Andric 
5920b57cec5SDimitry Andric   /// Return true if the operand is a valid for the fence instruction e.g.
5930b57cec5SDimitry Andric   /// ('iorw').
isFenceArg__anon932ea4f60111::RISCVOperand59406c3fb27SDimitry Andric   bool isFenceArg() const { return Kind == KindTy::Fence; }
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric   /// Return true if the operand is a valid floating point rounding mode.
isFRMArg__anon932ea4f60111::RISCVOperand59706c3fb27SDimitry Andric   bool isFRMArg() const { return Kind == KindTy::FRM; }
isFRMArgLegacy__anon932ea4f60111::RISCVOperand5985f757f3fSDimitry Andric   bool isFRMArgLegacy() const { return Kind == KindTy::FRM; }
isRTZArg__anon932ea4f60111::RISCVOperand59906c3fb27SDimitry Andric   bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }
6000b57cec5SDimitry Andric 
60106c3fb27SDimitry Andric   /// Return true if the operand is a valid fli.s floating-point immediate.
isLoadFPImm__anon932ea4f60111::RISCVOperand60206c3fb27SDimitry Andric   bool isLoadFPImm() const {
60306c3fb27SDimitry Andric     if (isImm())
60406c3fb27SDimitry Andric       return isUImm5();
60506c3fb27SDimitry Andric     if (Kind != KindTy::FPImmediate)
60606c3fb27SDimitry Andric       return false;
60706c3fb27SDimitry Andric     int Idx = RISCVLoadFPImm::getLoadFPImm(
60806c3fb27SDimitry Andric         APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
60906c3fb27SDimitry Andric     // Don't allow decimal version of the minimum value. It is a different value
61006c3fb27SDimitry Andric     // for each supported data type.
61106c3fb27SDimitry Andric     return Idx >= 0 && Idx != 1;
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric 
isImmXLenLI__anon932ea4f60111::RISCVOperand6140b57cec5SDimitry Andric   bool isImmXLenLI() const {
6150b57cec5SDimitry Andric     int64_t Imm;
6168bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
6170b57cec5SDimitry Andric     if (!isImm())
6180b57cec5SDimitry Andric       return false;
6190b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
6207a6dacacSDimitry Andric     if (VK == RISCVMCExpr::VK_RISCV_LO ||
6217a6dacacSDimitry Andric         VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
6227a6dacacSDimitry Andric         VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
6237a6dacacSDimitry Andric         VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO)
6240b57cec5SDimitry Andric       return true;
6250b57cec5SDimitry Andric     // Given only Imm, ensuring that the actually specified constant is either
6260b57cec5SDimitry Andric     // a signed or unsigned 64-bit number is unfortunately impossible.
62706c3fb27SDimitry Andric     if (IsConstantImm) {
62806c3fb27SDimitry Andric       return VK == RISCVMCExpr::VK_RISCV_None &&
62906c3fb27SDimitry Andric              (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
63006c3fb27SDimitry Andric     }
63106c3fb27SDimitry Andric 
63206c3fb27SDimitry Andric     return RISCVAsmParser::isSymbolDiff(getImm());
63306c3fb27SDimitry Andric   }
63406c3fb27SDimitry Andric 
isImmXLenLI_Restricted__anon932ea4f60111::RISCVOperand63506c3fb27SDimitry Andric   bool isImmXLenLI_Restricted() const {
63606c3fb27SDimitry Andric     int64_t Imm;
63706c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
63806c3fb27SDimitry Andric     if (!isImm())
63906c3fb27SDimitry Andric       return false;
64006c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
64106c3fb27SDimitry Andric     // 'la imm' supports constant immediates only.
64206c3fb27SDimitry Andric     return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) &&
64306c3fb27SDimitry Andric            (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
6440b57cec5SDimitry Andric   }
6450b57cec5SDimitry Andric 
isUImmLog2XLen__anon932ea4f60111::RISCVOperand6460b57cec5SDimitry Andric   bool isUImmLog2XLen() const {
6470b57cec5SDimitry Andric     int64_t Imm;
6488bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
6490b57cec5SDimitry Andric     if (!isImm())
6500b57cec5SDimitry Andric       return false;
6510b57cec5SDimitry Andric     if (!evaluateConstantImm(getImm(), Imm, VK) ||
6520b57cec5SDimitry Andric         VK != RISCVMCExpr::VK_RISCV_None)
6530b57cec5SDimitry Andric       return false;
65406c3fb27SDimitry Andric     return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
6550b57cec5SDimitry Andric   }
6560b57cec5SDimitry Andric 
isUImmLog2XLenNonZero__anon932ea4f60111::RISCVOperand6570b57cec5SDimitry Andric   bool isUImmLog2XLenNonZero() const {
6580b57cec5SDimitry Andric     int64_t Imm;
6598bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
6600b57cec5SDimitry Andric     if (!isImm())
6610b57cec5SDimitry Andric       return false;
6620b57cec5SDimitry Andric     if (!evaluateConstantImm(getImm(), Imm, VK) ||
6630b57cec5SDimitry Andric         VK != RISCVMCExpr::VK_RISCV_None)
6640b57cec5SDimitry Andric       return false;
6650b57cec5SDimitry Andric     if (Imm == 0)
6660b57cec5SDimitry Andric       return false;
66706c3fb27SDimitry Andric     return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
6680b57cec5SDimitry Andric   }
6690b57cec5SDimitry Andric 
isUImmLog2XLenHalf__anon932ea4f60111::RISCVOperand6705ffd83dbSDimitry Andric   bool isUImmLog2XLenHalf() const {
6715ffd83dbSDimitry Andric     int64_t Imm;
6725ffd83dbSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
6735ffd83dbSDimitry Andric     if (!isImm())
6745ffd83dbSDimitry Andric       return false;
6755ffd83dbSDimitry Andric     if (!evaluateConstantImm(getImm(), Imm, VK) ||
6765ffd83dbSDimitry Andric         VK != RISCVMCExpr::VK_RISCV_None)
6775ffd83dbSDimitry Andric       return false;
67806c3fb27SDimitry Andric     return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
6795ffd83dbSDimitry Andric   }
6805ffd83dbSDimitry Andric 
IsUImm__anon932ea4f60111::RISCVOperand68181ad6265SDimitry Andric   template <unsigned N> bool IsUImm() const {
682349cc55cSDimitry Andric     int64_t Imm;
683349cc55cSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
684349cc55cSDimitry Andric     if (!isImm())
685349cc55cSDimitry Andric       return false;
686349cc55cSDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
68781ad6265SDimitry Andric     return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
688349cc55cSDimitry Andric   }
689349cc55cSDimitry Andric 
isUImm1__anon932ea4f60111::RISCVOperand69006c3fb27SDimitry Andric   bool isUImm1() const { return IsUImm<1>(); }
isUImm2__anon932ea4f60111::RISCVOperand69106c3fb27SDimitry Andric   bool isUImm2() const { return IsUImm<2>(); }
isUImm3__anon932ea4f60111::RISCVOperand69206c3fb27SDimitry Andric   bool isUImm3() const { return IsUImm<3>(); }
isUImm4__anon932ea4f60111::RISCVOperand69306c3fb27SDimitry Andric   bool isUImm4() const { return IsUImm<4>(); }
isUImm5__anon932ea4f60111::RISCVOperand69406c3fb27SDimitry Andric   bool isUImm5() const { return IsUImm<5>(); }
isUImm6__anon932ea4f60111::RISCVOperand69506c3fb27SDimitry Andric   bool isUImm6() const { return IsUImm<6>(); }
isUImm7__anon932ea4f60111::RISCVOperand69606c3fb27SDimitry Andric   bool isUImm7() const { return IsUImm<7>(); }
isUImm8__anon932ea4f60111::RISCVOperand69706c3fb27SDimitry Andric   bool isUImm8() const { return IsUImm<8>(); }
isUImm20__anon932ea4f60111::RISCVOperand6985f757f3fSDimitry Andric   bool isUImm20() const { return IsUImm<20>(); }
69906c3fb27SDimitry Andric 
isUImm8GE32__anon932ea4f60111::RISCVOperand70006c3fb27SDimitry Andric   bool isUImm8GE32() const {
70106c3fb27SDimitry Andric     int64_t Imm;
70206c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
70306c3fb27SDimitry Andric     if (!isImm())
70406c3fb27SDimitry Andric       return false;
70506c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
70606c3fb27SDimitry Andric     return IsConstantImm && isUInt<8>(Imm) && Imm >= 32 &&
70706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
70806c3fb27SDimitry Andric   }
709349cc55cSDimitry Andric 
isRnumArg__anon932ea4f60111::RISCVOperand71004eeddc0SDimitry Andric   bool isRnumArg() const {
71104eeddc0SDimitry Andric     int64_t Imm;
71204eeddc0SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
71304eeddc0SDimitry Andric     if (!isImm())
71404eeddc0SDimitry Andric       return false;
71504eeddc0SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
71604eeddc0SDimitry Andric     return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) &&
71704eeddc0SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
71804eeddc0SDimitry Andric   }
71904eeddc0SDimitry Andric 
isRnumArg_0_7__anon932ea4f60111::RISCVOperand72006c3fb27SDimitry Andric   bool isRnumArg_0_7() const {
72106c3fb27SDimitry Andric     int64_t Imm;
72206c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
72306c3fb27SDimitry Andric     if (!isImm())
72406c3fb27SDimitry Andric       return false;
72506c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
72606c3fb27SDimitry Andric     return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(7) &&
72706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
72806c3fb27SDimitry Andric   }
72906c3fb27SDimitry Andric 
isRnumArg_1_10__anon932ea4f60111::RISCVOperand73006c3fb27SDimitry Andric   bool isRnumArg_1_10() 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(1) && Imm <= INT64_C(10) &&
73706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
73806c3fb27SDimitry Andric   }
73906c3fb27SDimitry Andric 
isRnumArg_2_14__anon932ea4f60111::RISCVOperand74006c3fb27SDimitry Andric   bool isRnumArg_2_14() 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(2) && Imm <= INT64_C(14) &&
74706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
74806c3fb27SDimitry Andric   }
74906c3fb27SDimitry Andric 
isSImm5__anon932ea4f60111::RISCVOperand7505ffd83dbSDimitry Andric   bool isSImm5() const {
7515ffd83dbSDimitry Andric     if (!isImm())
7525ffd83dbSDimitry Andric       return false;
7535ffd83dbSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
7545ffd83dbSDimitry Andric     int64_t Imm;
7555ffd83dbSDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
75606c3fb27SDimitry Andric     return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
75706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
7585ffd83dbSDimitry Andric   }
7595ffd83dbSDimitry Andric 
isSImm6__anon932ea4f60111::RISCVOperand7600b57cec5SDimitry Andric   bool isSImm6() const {
7610b57cec5SDimitry Andric     if (!isImm())
7620b57cec5SDimitry Andric       return false;
7638bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
7640b57cec5SDimitry Andric     int64_t Imm;
7650b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
76606c3fb27SDimitry Andric     return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
76706c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
7680b57cec5SDimitry Andric   }
7690b57cec5SDimitry Andric 
isSImm6NonZero__anon932ea4f60111::RISCVOperand7700b57cec5SDimitry Andric   bool isSImm6NonZero() 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 && Imm != 0 &&
77706c3fb27SDimitry Andric            isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
7780b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
7790b57cec5SDimitry Andric   }
7800b57cec5SDimitry Andric 
isCLUIImm__anon932ea4f60111::RISCVOperand7810b57cec5SDimitry Andric   bool isCLUIImm() const {
7820b57cec5SDimitry Andric     if (!isImm())
7830b57cec5SDimitry Andric       return false;
7840b57cec5SDimitry Andric     int64_t Imm;
7858bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
7860b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
7870b57cec5SDimitry Andric     return IsConstantImm && (Imm != 0) &&
7880b57cec5SDimitry Andric            (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
7890b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
7900b57cec5SDimitry Andric   }
7910b57cec5SDimitry Andric 
isUImm2Lsb0__anon932ea4f60111::RISCVOperand79206c3fb27SDimitry Andric   bool isUImm2Lsb0() const {
79306c3fb27SDimitry Andric     if (!isImm())
79406c3fb27SDimitry Andric       return false;
79506c3fb27SDimitry Andric     int64_t Imm;
79606c3fb27SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
79706c3fb27SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
79806c3fb27SDimitry Andric     return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
79906c3fb27SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
80006c3fb27SDimitry Andric   }
80106c3fb27SDimitry Andric 
isUImm7Lsb00__anon932ea4f60111::RISCVOperand8020b57cec5SDimitry Andric   bool isUImm7Lsb00() const {
8030b57cec5SDimitry Andric     if (!isImm())
8040b57cec5SDimitry Andric       return false;
8050b57cec5SDimitry Andric     int64_t Imm;
8068bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8070b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8080b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
8090b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8100b57cec5SDimitry Andric   }
8110b57cec5SDimitry Andric 
isUImm8Lsb00__anon932ea4f60111::RISCVOperand8120b57cec5SDimitry Andric   bool isUImm8Lsb00() const {
8130b57cec5SDimitry Andric     if (!isImm())
8140b57cec5SDimitry Andric       return false;
8150b57cec5SDimitry Andric     int64_t Imm;
8168bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8170b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8180b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
8190b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8200b57cec5SDimitry Andric   }
8210b57cec5SDimitry Andric 
isUImm8Lsb000__anon932ea4f60111::RISCVOperand8220b57cec5SDimitry Andric   bool isUImm8Lsb000() const {
8230b57cec5SDimitry Andric     if (!isImm())
8240b57cec5SDimitry Andric       return false;
8250b57cec5SDimitry Andric     int64_t Imm;
8268bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8270b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8280b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
8290b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8300b57cec5SDimitry Andric   }
8310b57cec5SDimitry Andric 
isSImm9Lsb0__anon932ea4f60111::RISCVOperand8320b57cec5SDimitry Andric   bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
8330b57cec5SDimitry Andric 
isUImm9Lsb000__anon932ea4f60111::RISCVOperand8340b57cec5SDimitry Andric   bool isUImm9Lsb000() const {
8350b57cec5SDimitry Andric     if (!isImm())
8360b57cec5SDimitry Andric       return false;
8370b57cec5SDimitry Andric     int64_t Imm;
8388bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8390b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8400b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
8410b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8420b57cec5SDimitry Andric   }
8430b57cec5SDimitry Andric 
isUImm10Lsb00NonZero__anon932ea4f60111::RISCVOperand8440b57cec5SDimitry Andric   bool isUImm10Lsb00NonZero() const {
8450b57cec5SDimitry Andric     if (!isImm())
8460b57cec5SDimitry Andric       return false;
8470b57cec5SDimitry Andric     int64_t Imm;
8488bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8490b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8500b57cec5SDimitry Andric     return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
8510b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
8520b57cec5SDimitry Andric   }
8530b57cec5SDimitry Andric 
85406c3fb27SDimitry Andric   // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
85506c3fb27SDimitry Andric   // This allows writing 'addi a0, a0, 0xffffffff'.
fixImmediateForRV32__anon932ea4f60111::RISCVOperand85606c3fb27SDimitry Andric   static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
85706c3fb27SDimitry Andric     if (IsRV64Imm || !isUInt<32>(Imm))
85806c3fb27SDimitry Andric       return Imm;
85906c3fb27SDimitry Andric     return SignExtend64<32>(Imm);
86006c3fb27SDimitry Andric   }
86106c3fb27SDimitry Andric 
isSImm12__anon932ea4f60111::RISCVOperand8620b57cec5SDimitry Andric   bool isSImm12() const {
8638bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
8640b57cec5SDimitry Andric     int64_t Imm;
8650b57cec5SDimitry Andric     bool IsValid;
8660b57cec5SDimitry Andric     if (!isImm())
8670b57cec5SDimitry Andric       return false;
8680b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
8690b57cec5SDimitry Andric     if (!IsConstantImm)
870e8d8bef9SDimitry Andric       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
8710b57cec5SDimitry Andric     else
87206c3fb27SDimitry Andric       IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
8730b57cec5SDimitry Andric     return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
8740b57cec5SDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_LO ||
8750b57cec5SDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
8767a6dacacSDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_TPREL_LO ||
8777a6dacacSDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
8787a6dacacSDimitry Andric                        VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO);
8790b57cec5SDimitry Andric   }
8800b57cec5SDimitry Andric 
isSImm12Lsb0__anon932ea4f60111::RISCVOperand8810b57cec5SDimitry Andric   bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
8820b57cec5SDimitry Andric 
isSImm12Lsb00000__anon932ea4f60111::RISCVOperand88381ad6265SDimitry Andric   bool isSImm12Lsb00000() const {
88481ad6265SDimitry Andric     if (!isImm())
88581ad6265SDimitry Andric       return false;
88681ad6265SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
88781ad6265SDimitry Andric     int64_t Imm;
88881ad6265SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
88981ad6265SDimitry Andric     return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
89081ad6265SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
89181ad6265SDimitry Andric   }
89281ad6265SDimitry Andric 
isSImm13Lsb0__anon932ea4f60111::RISCVOperand8930b57cec5SDimitry Andric   bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
8940b57cec5SDimitry Andric 
isSImm10Lsb0000NonZero__anon932ea4f60111::RISCVOperand8950b57cec5SDimitry Andric   bool isSImm10Lsb0000NonZero() const {
8960b57cec5SDimitry Andric     if (!isImm())
8970b57cec5SDimitry Andric       return false;
8980b57cec5SDimitry Andric     int64_t Imm;
8998bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9000b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
9010b57cec5SDimitry Andric     return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
9020b57cec5SDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
9030b57cec5SDimitry Andric   }
9040b57cec5SDimitry Andric 
isUImm20LUI__anon932ea4f60111::RISCVOperand9050b57cec5SDimitry Andric   bool isUImm20LUI() const {
9068bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9070b57cec5SDimitry Andric     int64_t Imm;
9080b57cec5SDimitry Andric     bool IsValid;
9090b57cec5SDimitry Andric     if (!isImm())
9100b57cec5SDimitry Andric       return false;
9110b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
9120b57cec5SDimitry Andric     if (!IsConstantImm) {
913e8d8bef9SDimitry Andric       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
9140b57cec5SDimitry Andric       return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
9150b57cec5SDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
9160b57cec5SDimitry Andric     } else {
9170b57cec5SDimitry Andric       return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
9180b57cec5SDimitry Andric                                  VK == RISCVMCExpr::VK_RISCV_HI ||
9190b57cec5SDimitry Andric                                  VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
9200b57cec5SDimitry Andric     }
9210b57cec5SDimitry Andric   }
9220b57cec5SDimitry Andric 
isUImm20AUIPC__anon932ea4f60111::RISCVOperand9230b57cec5SDimitry Andric   bool isUImm20AUIPC() const {
9248bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9250b57cec5SDimitry Andric     int64_t Imm;
9260b57cec5SDimitry Andric     bool IsValid;
9270b57cec5SDimitry Andric     if (!isImm())
9280b57cec5SDimitry Andric       return false;
9290b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
9300b57cec5SDimitry Andric     if (!IsConstantImm) {
931e8d8bef9SDimitry Andric       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
9320b57cec5SDimitry Andric       return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
9330b57cec5SDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
9340b57cec5SDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
9357a6dacacSDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
9367a6dacacSDimitry Andric                          VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
9377a6dacacSDimitry Andric     }
9387a6dacacSDimitry Andric 
9390b57cec5SDimitry Andric     return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
9400b57cec5SDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
9410b57cec5SDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
9420b57cec5SDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
9437a6dacacSDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
9447a6dacacSDimitry Andric                                VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
9450b57cec5SDimitry Andric   }
9460b57cec5SDimitry Andric 
isSImm21Lsb0JAL__anon932ea4f60111::RISCVOperand9470b57cec5SDimitry Andric   bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
9480b57cec5SDimitry Andric 
isImmZero__anon932ea4f60111::RISCVOperand9490b57cec5SDimitry Andric   bool isImmZero() const {
9500b57cec5SDimitry Andric     if (!isImm())
9510b57cec5SDimitry Andric       return false;
9520b57cec5SDimitry Andric     int64_t Imm;
9530b57cec5SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9540b57cec5SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
9550b57cec5SDimitry Andric     return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
9560b57cec5SDimitry Andric   }
9570b57cec5SDimitry Andric 
isSImm5Plus1__anon932ea4f60111::RISCVOperand9585ffd83dbSDimitry Andric   bool isSImm5Plus1() const {
9595ffd83dbSDimitry Andric     if (!isImm())
9605ffd83dbSDimitry Andric       return false;
9615ffd83dbSDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
9625ffd83dbSDimitry Andric     int64_t Imm;
9635ffd83dbSDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
96406c3fb27SDimitry Andric     return IsConstantImm &&
96506c3fb27SDimitry Andric            isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
9665ffd83dbSDimitry Andric            VK == RISCVMCExpr::VK_RISCV_None;
9675ffd83dbSDimitry Andric   }
9685ffd83dbSDimitry Andric 
9690b57cec5SDimitry Andric   /// getStartLoc - Gets location of the first token of this operand
getStartLoc__anon932ea4f60111::RISCVOperand9700b57cec5SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
9710b57cec5SDimitry Andric   /// getEndLoc - Gets location of the last token of this operand
getEndLoc__anon932ea4f60111::RISCVOperand9720b57cec5SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
9730b57cec5SDimitry Andric   /// True if this operand is for an RV64 instruction
isRV64Imm__anon932ea4f60111::RISCVOperand97406c3fb27SDimitry Andric   bool isRV64Imm() const {
97506c3fb27SDimitry Andric     assert(Kind == KindTy::Immediate && "Invalid type access!");
97606c3fb27SDimitry Andric     return Imm.IsRV64;
97706c3fb27SDimitry Andric   }
9780b57cec5SDimitry Andric 
getReg__anon932ea4f60111::RISCVOperand9790b57cec5SDimitry Andric   unsigned getReg() const override {
9808bcb0991SDimitry Andric     assert(Kind == KindTy::Register && "Invalid type access!");
9818bcb0991SDimitry Andric     return Reg.RegNum.id();
9820b57cec5SDimitry Andric   }
9830b57cec5SDimitry Andric 
getSysReg__anon932ea4f60111::RISCVOperand9840b57cec5SDimitry Andric   StringRef getSysReg() const {
985e8d8bef9SDimitry Andric     assert(Kind == KindTy::SystemRegister && "Invalid type access!");
9860b57cec5SDimitry Andric     return StringRef(SysReg.Data, SysReg.Length);
9870b57cec5SDimitry Andric   }
9880b57cec5SDimitry Andric 
getImm__anon932ea4f60111::RISCVOperand9890b57cec5SDimitry Andric   const MCExpr *getImm() const {
9908bcb0991SDimitry Andric     assert(Kind == KindTy::Immediate && "Invalid type access!");
9910b57cec5SDimitry Andric     return Imm.Val;
9920b57cec5SDimitry Andric   }
9930b57cec5SDimitry Andric 
getFPConst__anon932ea4f60111::RISCVOperand99406c3fb27SDimitry Andric   uint64_t getFPConst() const {
99506c3fb27SDimitry Andric     assert(Kind == KindTy::FPImmediate && "Invalid type access!");
99606c3fb27SDimitry Andric     return FPImm.Val;
99706c3fb27SDimitry Andric   }
99806c3fb27SDimitry Andric 
getToken__anon932ea4f60111::RISCVOperand9990b57cec5SDimitry Andric   StringRef getToken() const {
10008bcb0991SDimitry Andric     assert(Kind == KindTy::Token && "Invalid type access!");
10010b57cec5SDimitry Andric     return Tok;
10020b57cec5SDimitry Andric   }
10030b57cec5SDimitry Andric 
getVType__anon932ea4f60111::RISCVOperand1004e8d8bef9SDimitry Andric   unsigned getVType() const {
1005e8d8bef9SDimitry Andric     assert(Kind == KindTy::VType && "Invalid type access!");
1006e8d8bef9SDimitry Andric     return VType.Val;
10075ffd83dbSDimitry Andric   }
10085ffd83dbSDimitry Andric 
getFRM__anon932ea4f60111::RISCVOperand100906c3fb27SDimitry Andric   RISCVFPRndMode::RoundingMode getFRM() const {
101006c3fb27SDimitry Andric     assert(Kind == KindTy::FRM && "Invalid type access!");
101106c3fb27SDimitry Andric     return FRM.FRM;
101206c3fb27SDimitry Andric   }
101306c3fb27SDimitry Andric 
getFence__anon932ea4f60111::RISCVOperand101406c3fb27SDimitry Andric   unsigned getFence() const {
101506c3fb27SDimitry Andric     assert(Kind == KindTy::Fence && "Invalid type access!");
101606c3fb27SDimitry Andric     return Fence.Val;
101706c3fb27SDimitry Andric   }
101806c3fb27SDimitry Andric 
print__anon932ea4f60111::RISCVOperand10190b57cec5SDimitry Andric   void print(raw_ostream &OS) const override {
1020bdd1243dSDimitry Andric     auto RegName = [](MCRegister Reg) {
1021e8d8bef9SDimitry Andric       if (Reg)
1022e8d8bef9SDimitry Andric         return RISCVInstPrinter::getRegisterName(Reg);
1023e8d8bef9SDimitry Andric       else
1024e8d8bef9SDimitry Andric         return "noreg";
1025e8d8bef9SDimitry Andric     };
1026e8d8bef9SDimitry Andric 
10270b57cec5SDimitry Andric     switch (Kind) {
10288bcb0991SDimitry Andric     case KindTy::Immediate:
10290b57cec5SDimitry Andric       OS << *getImm();
10300b57cec5SDimitry Andric       break;
103106c3fb27SDimitry Andric     case KindTy::FPImmediate:
103206c3fb27SDimitry Andric       break;
10338bcb0991SDimitry Andric     case KindTy::Register:
1034e8d8bef9SDimitry Andric       OS << "<register " << RegName(getReg()) << ">";
10350b57cec5SDimitry Andric       break;
10368bcb0991SDimitry Andric     case KindTy::Token:
10370b57cec5SDimitry Andric       OS << "'" << getToken() << "'";
10380b57cec5SDimitry Andric       break;
10398bcb0991SDimitry Andric     case KindTy::SystemRegister:
10400b57cec5SDimitry Andric       OS << "<sysreg: " << getSysReg() << '>';
10410b57cec5SDimitry Andric       break;
10425ffd83dbSDimitry Andric     case KindTy::VType:
1043e8d8bef9SDimitry Andric       OS << "<vtype: ";
1044e8d8bef9SDimitry Andric       RISCVVType::printVType(getVType(), OS);
1045e8d8bef9SDimitry Andric       OS << '>';
10465ffd83dbSDimitry Andric       break;
104706c3fb27SDimitry Andric     case KindTy::FRM:
104806c3fb27SDimitry Andric       OS << "<frm: ";
104906c3fb27SDimitry Andric       roundingModeToString(getFRM());
105006c3fb27SDimitry Andric       OS << '>';
105106c3fb27SDimitry Andric       break;
105206c3fb27SDimitry Andric     case KindTy::Fence:
105306c3fb27SDimitry Andric       OS << "<fence: ";
105406c3fb27SDimitry Andric       OS << getFence();
105506c3fb27SDimitry Andric       OS << '>';
105606c3fb27SDimitry Andric       break;
105706c3fb27SDimitry Andric     case KindTy::Rlist:
105806c3fb27SDimitry Andric       OS << "<rlist: ";
105906c3fb27SDimitry Andric       RISCVZC::printRlist(Rlist.Val, OS);
106006c3fb27SDimitry Andric       OS << '>';
106106c3fb27SDimitry Andric       break;
106206c3fb27SDimitry Andric     case KindTy::Spimm:
106306c3fb27SDimitry Andric       OS << "<Spimm: ";
106406c3fb27SDimitry Andric       RISCVZC::printSpimm(Spimm.Val, OS);
106506c3fb27SDimitry Andric       OS << '>';
106606c3fb27SDimitry Andric       break;
10675f757f3fSDimitry Andric     case KindTy::RegReg:
10685f757f3fSDimitry Andric       OS << "<RegReg:  Reg1 " << RegName(RegReg.Reg1);
10695f757f3fSDimitry Andric       OS << " Reg2 " << RegName(RegReg.Reg2);
10705f757f3fSDimitry Andric       break;
10710b57cec5SDimitry Andric     }
10720b57cec5SDimitry Andric   }
10730b57cec5SDimitry Andric 
createToken__anon932ea4f60111::RISCVOperand107406c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
10758bcb0991SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
10760b57cec5SDimitry Andric     Op->Tok = Str;
10770b57cec5SDimitry Andric     Op->StartLoc = S;
10780b57cec5SDimitry Andric     Op->EndLoc = S;
10790b57cec5SDimitry Andric     return Op;
10800b57cec5SDimitry Andric   }
10810b57cec5SDimitry Andric 
108206c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand>
createReg__anon932ea4f60111::RISCVOperand108306c3fb27SDimitry Andric   createReg(unsigned RegNo, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
10848bcb0991SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
10850b57cec5SDimitry Andric     Op->Reg.RegNum = RegNo;
108606c3fb27SDimitry Andric     Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
10870b57cec5SDimitry Andric     Op->StartLoc = S;
10880b57cec5SDimitry Andric     Op->EndLoc = E;
10890b57cec5SDimitry Andric     return Op;
10900b57cec5SDimitry Andric   }
10910b57cec5SDimitry Andric 
createImm__anon932ea4f60111::RISCVOperand10920b57cec5SDimitry Andric   static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
10930b57cec5SDimitry Andric                                                  SMLoc E, bool IsRV64) {
10948bcb0991SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
10950b57cec5SDimitry Andric     Op->Imm.Val = Val;
109606c3fb27SDimitry Andric     Op->Imm.IsRV64 = IsRV64;
10970b57cec5SDimitry Andric     Op->StartLoc = S;
10980b57cec5SDimitry Andric     Op->EndLoc = E;
10990b57cec5SDimitry Andric     return Op;
11000b57cec5SDimitry Andric   }
11010b57cec5SDimitry Andric 
createFPImm__anon932ea4f60111::RISCVOperand110206c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {
110306c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
110406c3fb27SDimitry Andric     Op->FPImm.Val = Val;
110506c3fb27SDimitry Andric     Op->StartLoc = S;
110606c3fb27SDimitry Andric     Op->EndLoc = S;
110706c3fb27SDimitry Andric     return Op;
110806c3fb27SDimitry Andric   }
110906c3fb27SDimitry Andric 
createSysReg__anon932ea4f60111::RISCVOperand111006c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,
111106c3fb27SDimitry Andric                                                     unsigned Encoding) {
11128bcb0991SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
11130b57cec5SDimitry Andric     Op->SysReg.Data = Str.data();
11140b57cec5SDimitry Andric     Op->SysReg.Length = Str.size();
11150b57cec5SDimitry Andric     Op->SysReg.Encoding = Encoding;
11160b57cec5SDimitry Andric     Op->StartLoc = S;
11170eae32dcSDimitry Andric     Op->EndLoc = S;
11180b57cec5SDimitry Andric     return Op;
11190b57cec5SDimitry Andric   }
11200b57cec5SDimitry Andric 
112106c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand>
createFRMArg__anon932ea4f60111::RISCVOperand112206c3fb27SDimitry Andric   createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {
112306c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
112406c3fb27SDimitry Andric     Op->FRM.FRM = FRM;
112506c3fb27SDimitry Andric     Op->StartLoc = S;
112606c3fb27SDimitry Andric     Op->EndLoc = S;
112706c3fb27SDimitry Andric     return Op;
112806c3fb27SDimitry Andric   }
112906c3fb27SDimitry Andric 
createFenceArg__anon932ea4f60111::RISCVOperand113006c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {
113106c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
113206c3fb27SDimitry Andric     Op->Fence.Val = Val;
113306c3fb27SDimitry Andric     Op->StartLoc = S;
113406c3fb27SDimitry Andric     Op->EndLoc = S;
113506c3fb27SDimitry Andric     return Op;
113606c3fb27SDimitry Andric   }
113706c3fb27SDimitry Andric 
createVType__anon932ea4f60111::RISCVOperand113806c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {
11395ffd83dbSDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1140e8d8bef9SDimitry Andric     Op->VType.Val = VTypeI;
11415ffd83dbSDimitry Andric     Op->StartLoc = S;
11420eae32dcSDimitry Andric     Op->EndLoc = S;
11435ffd83dbSDimitry Andric     return Op;
11445ffd83dbSDimitry Andric   }
11455ffd83dbSDimitry Andric 
createRlist__anon932ea4f60111::RISCVOperand114606c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createRlist(unsigned RlistEncode,
114706c3fb27SDimitry Andric                                                    SMLoc S) {
114806c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
114906c3fb27SDimitry Andric     Op->Rlist.Val = RlistEncode;
115006c3fb27SDimitry Andric     Op->StartLoc = S;
115106c3fb27SDimitry Andric     return Op;
115206c3fb27SDimitry Andric   }
115306c3fb27SDimitry Andric 
createRegReg__anon932ea4f60111::RISCVOperand11545f757f3fSDimitry Andric   static std::unique_ptr<RISCVOperand> createRegReg(unsigned Reg1No,
11555f757f3fSDimitry Andric                                                     unsigned Reg2No, SMLoc S) {
11565f757f3fSDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
11575f757f3fSDimitry Andric     Op->RegReg.Reg1 = Reg1No;
11585f757f3fSDimitry Andric     Op->RegReg.Reg2 = Reg2No;
11595f757f3fSDimitry Andric     Op->StartLoc = S;
11605f757f3fSDimitry Andric     Op->EndLoc = S;
11615f757f3fSDimitry Andric     return Op;
11625f757f3fSDimitry Andric   }
11635f757f3fSDimitry Andric 
createSpimm__anon932ea4f60111::RISCVOperand116406c3fb27SDimitry Andric   static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S) {
116506c3fb27SDimitry Andric     auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
116606c3fb27SDimitry Andric     Op->Spimm.Val = Spimm;
116706c3fb27SDimitry Andric     Op->StartLoc = S;
116806c3fb27SDimitry Andric     return Op;
116906c3fb27SDimitry Andric   }
117006c3fb27SDimitry Andric 
addExpr__anon932ea4f60111::RISCVOperand117106c3fb27SDimitry Andric   static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
11720b57cec5SDimitry Andric     assert(Expr && "Expr shouldn't be null!");
11730b57cec5SDimitry Andric     int64_t Imm = 0;
11748bcb0991SDimitry Andric     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
11750b57cec5SDimitry Andric     bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric     if (IsConstant)
117806c3fb27SDimitry Andric       Inst.addOperand(
117906c3fb27SDimitry Andric           MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));
11800b57cec5SDimitry Andric     else
11810b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
11820b57cec5SDimitry Andric   }
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric   // Used by the TableGen Code
addRegOperands__anon932ea4f60111::RISCVOperand11850b57cec5SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
11860b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
11870b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(getReg()));
11880b57cec5SDimitry Andric   }
11890b57cec5SDimitry Andric 
addImmOperands__anon932ea4f60111::RISCVOperand11900b57cec5SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
11910b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
119206c3fb27SDimitry Andric     addExpr(Inst, getImm(), isRV64Imm());
119306c3fb27SDimitry Andric   }
119406c3fb27SDimitry Andric 
addFPImmOperands__anon932ea4f60111::RISCVOperand119506c3fb27SDimitry Andric   void addFPImmOperands(MCInst &Inst, unsigned N) const {
119606c3fb27SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
119706c3fb27SDimitry Andric     if (isImm()) {
119806c3fb27SDimitry Andric       addExpr(Inst, getImm(), isRV64Imm());
119906c3fb27SDimitry Andric       return;
120006c3fb27SDimitry Andric     }
120106c3fb27SDimitry Andric 
120206c3fb27SDimitry Andric     int Imm = RISCVLoadFPImm::getLoadFPImm(
120306c3fb27SDimitry Andric         APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
120406c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Imm));
12050b57cec5SDimitry Andric   }
12060b57cec5SDimitry Andric 
addFenceArgOperands__anon932ea4f60111::RISCVOperand12070b57cec5SDimitry Andric   void addFenceArgOperands(MCInst &Inst, unsigned N) const {
12080b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
120906c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Fence.Val));
12100b57cec5SDimitry Andric   }
12110b57cec5SDimitry Andric 
addCSRSystemRegisterOperands__anon932ea4f60111::RISCVOperand12120b57cec5SDimitry Andric   void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
12130b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12140b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
12150b57cec5SDimitry Andric   }
12160b57cec5SDimitry Andric 
121704eeddc0SDimitry Andric   // Support non-canonical syntax:
121804eeddc0SDimitry Andric   // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
121904eeddc0SDimitry Andric   // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
addVTypeIOperands__anon932ea4f60111::RISCVOperand12205ffd83dbSDimitry Andric   void addVTypeIOperands(MCInst &Inst, unsigned N) const {
12215ffd83dbSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
122204eeddc0SDimitry Andric     int64_t Imm = 0;
122304eeddc0SDimitry Andric     if (Kind == KindTy::Immediate) {
122404eeddc0SDimitry Andric       RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
122504eeddc0SDimitry Andric       bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
122604eeddc0SDimitry Andric       (void)IsConstantImm;
122704eeddc0SDimitry Andric       assert(IsConstantImm && "Invalid VTypeI Operand!");
122804eeddc0SDimitry Andric     } else {
122904eeddc0SDimitry Andric       Imm = getVType();
123004eeddc0SDimitry Andric     }
123104eeddc0SDimitry Andric     Inst.addOperand(MCOperand::createImm(Imm));
12325ffd83dbSDimitry Andric   }
12335ffd83dbSDimitry Andric 
addRlistOperands__anon932ea4f60111::RISCVOperand123406c3fb27SDimitry Andric   void addRlistOperands(MCInst &Inst, unsigned N) const {
123506c3fb27SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
123606c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Rlist.Val));
123706c3fb27SDimitry Andric   }
123806c3fb27SDimitry Andric 
addRegRegOperands__anon932ea4f60111::RISCVOperand12395f757f3fSDimitry Andric   void addRegRegOperands(MCInst &Inst, unsigned N) const {
12405f757f3fSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
12415f757f3fSDimitry Andric     Inst.addOperand(MCOperand::createReg(RegReg.Reg1));
12425f757f3fSDimitry Andric     Inst.addOperand(MCOperand::createReg(RegReg.Reg2));
12435f757f3fSDimitry Andric   }
12445f757f3fSDimitry Andric 
addSpimmOperands__anon932ea4f60111::RISCVOperand124506c3fb27SDimitry Andric   void addSpimmOperands(MCInst &Inst, unsigned N) const {
124606c3fb27SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
124706c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Spimm.Val));
12480b57cec5SDimitry Andric   }
12490b57cec5SDimitry Andric 
addFRMArgOperands__anon932ea4f60111::RISCVOperand12500b57cec5SDimitry Andric   void addFRMArgOperands(MCInst &Inst, unsigned N) const {
12510b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
125206c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(getFRM()));
12530b57cec5SDimitry Andric   }
12540b57cec5SDimitry Andric };
12550b57cec5SDimitry Andric } // end anonymous namespace.
12560b57cec5SDimitry Andric 
12570b57cec5SDimitry Andric #define GET_REGISTER_MATCHER
1258480093f4SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME
12590b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
1260480093f4SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
12610b57cec5SDimitry Andric #include "RISCVGenAsmMatcher.inc"
12620b57cec5SDimitry Andric 
convertFPR64ToFPR16(MCRegister Reg)1263e8d8bef9SDimitry Andric static MCRegister convertFPR64ToFPR16(MCRegister Reg) {
1264e8d8bef9SDimitry Andric   assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1265e8d8bef9SDimitry Andric   return Reg - RISCV::F0_D + RISCV::F0_H;
1266e8d8bef9SDimitry Andric }
1267e8d8bef9SDimitry Andric 
convertFPR64ToFPR32(MCRegister Reg)1268e8d8bef9SDimitry Andric static MCRegister convertFPR64ToFPR32(MCRegister Reg) {
12698bcb0991SDimitry Andric   assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
12708bcb0991SDimitry Andric   return Reg - RISCV::F0_D + RISCV::F0_F;
12710b57cec5SDimitry Andric }
12720b57cec5SDimitry Andric 
convertVRToVRMx(const MCRegisterInfo & RI,MCRegister Reg,unsigned Kind)1273fe6060f1SDimitry Andric static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
1274fe6060f1SDimitry Andric                                   unsigned Kind) {
1275fe6060f1SDimitry Andric   unsigned RegClassID;
1276fe6060f1SDimitry Andric   if (Kind == MCK_VRM2)
1277fe6060f1SDimitry Andric     RegClassID = RISCV::VRM2RegClassID;
1278fe6060f1SDimitry Andric   else if (Kind == MCK_VRM4)
1279fe6060f1SDimitry Andric     RegClassID = RISCV::VRM4RegClassID;
1280fe6060f1SDimitry Andric   else if (Kind == MCK_VRM8)
1281fe6060f1SDimitry Andric     RegClassID = RISCV::VRM8RegClassID;
1282fe6060f1SDimitry Andric   else
1283fe6060f1SDimitry Andric     return 0;
1284fe6060f1SDimitry Andric   return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
1285fe6060f1SDimitry Andric                                 &RISCVMCRegisterClasses[RegClassID]);
1286fe6060f1SDimitry Andric }
1287fe6060f1SDimitry Andric 
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)12880b57cec5SDimitry Andric unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
12890b57cec5SDimitry Andric                                                     unsigned Kind) {
12900b57cec5SDimitry Andric   RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
12910b57cec5SDimitry Andric   if (!Op.isReg())
12920b57cec5SDimitry Andric     return Match_InvalidOperand;
12930b57cec5SDimitry Andric 
1294e8d8bef9SDimitry Andric   MCRegister Reg = Op.getReg();
12958bcb0991SDimitry Andric   bool IsRegFPR64 =
12968bcb0991SDimitry Andric       RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
12978bcb0991SDimitry Andric   bool IsRegFPR64C =
12988bcb0991SDimitry Andric       RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1299fe6060f1SDimitry Andric   bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
13000b57cec5SDimitry Andric 
13010b57cec5SDimitry Andric   // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
13028bcb0991SDimitry Andric   // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
13038bcb0991SDimitry Andric   if ((IsRegFPR64 && Kind == MCK_FPR32) ||
13048bcb0991SDimitry Andric       (IsRegFPR64C && Kind == MCK_FPR32C)) {
13058bcb0991SDimitry Andric     Op.Reg.RegNum = convertFPR64ToFPR32(Reg);
13060b57cec5SDimitry Andric     return Match_Success;
13070b57cec5SDimitry Andric   }
1308e8d8bef9SDimitry Andric   // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1309e8d8bef9SDimitry Andric   // register from FPR64 to FPR16 if necessary.
1310e8d8bef9SDimitry Andric   if (IsRegFPR64 && Kind == MCK_FPR16) {
1311e8d8bef9SDimitry Andric     Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
1312e8d8bef9SDimitry Andric     return Match_Success;
1313e8d8bef9SDimitry Andric   }
1314fe6060f1SDimitry Andric   // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1315fe6060f1SDimitry Andric   // the register from VR to VRM2/VRM4/VRM8 if necessary.
1316fe6060f1SDimitry Andric   if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1317fe6060f1SDimitry Andric     Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1318fe6060f1SDimitry Andric     if (Op.Reg.RegNum == 0)
1319fe6060f1SDimitry Andric       return Match_InvalidOperand;
1320fe6060f1SDimitry Andric     return Match_Success;
1321fe6060f1SDimitry Andric   }
13220b57cec5SDimitry Andric   return Match_InvalidOperand;
13230b57cec5SDimitry Andric }
13240b57cec5SDimitry Andric 
checkTargetMatchPredicate(MCInst & Inst)132506c3fb27SDimitry Andric unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
132606c3fb27SDimitry Andric   const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
132706c3fb27SDimitry Andric 
132806c3fb27SDimitry Andric   for (unsigned I = 0; I < MCID.NumOperands; ++I) {
1329297eecfbSDimitry Andric     if (MCID.operands()[I].RegClass == RISCV::GPRPairRegClassID) {
133006c3fb27SDimitry Andric       const auto &Op = Inst.getOperand(I);
133106c3fb27SDimitry Andric       assert(Op.isReg());
133206c3fb27SDimitry Andric 
133306c3fb27SDimitry Andric       MCRegister Reg = Op.getReg();
1334297eecfbSDimitry Andric       if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(Reg))
1335297eecfbSDimitry Andric         continue;
1336297eecfbSDimitry Andric 
1337297eecfbSDimitry Andric       // FIXME: We should form a paired register during parsing/matching.
133806c3fb27SDimitry Andric       if (((Reg.id() - RISCV::X0) & 1) != 0)
133906c3fb27SDimitry Andric         return Match_RequiresEvenGPRs;
134006c3fb27SDimitry Andric     }
134106c3fb27SDimitry Andric   }
134206c3fb27SDimitry Andric 
134306c3fb27SDimitry Andric   return Match_Success;
134406c3fb27SDimitry Andric }
134506c3fb27SDimitry Andric 
generateImmOutOfRangeError(SMLoc ErrorLoc,int64_t Lower,int64_t Upper,const Twine & Msg="immediate must be an integer in the range")134606c3fb27SDimitry Andric bool RISCVAsmParser::generateImmOutOfRangeError(
134706c3fb27SDimitry Andric     SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
134806c3fb27SDimitry Andric     const Twine &Msg = "immediate must be an integer in the range") {
134906c3fb27SDimitry Andric   return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
135006c3fb27SDimitry Andric }
135106c3fb27SDimitry Andric 
generateImmOutOfRangeError(OperandVector & Operands,uint64_t ErrorInfo,int64_t Lower,int64_t Upper,const Twine & Msg="immediate must be an integer in the range")13520b57cec5SDimitry Andric bool RISCVAsmParser::generateImmOutOfRangeError(
13530b57cec5SDimitry Andric     OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
135406c3fb27SDimitry Andric     const Twine &Msg = "immediate must be an integer in the range") {
13550b57cec5SDimitry Andric   SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
135606c3fb27SDimitry Andric   return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg);
13570b57cec5SDimitry Andric }
13580b57cec5SDimitry Andric 
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)13590b57cec5SDimitry Andric bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
13600b57cec5SDimitry Andric                                              OperandVector &Operands,
13610b57cec5SDimitry Andric                                              MCStreamer &Out,
13620b57cec5SDimitry Andric                                              uint64_t &ErrorInfo,
13630b57cec5SDimitry Andric                                              bool MatchingInlineAsm) {
13640b57cec5SDimitry Andric   MCInst Inst;
1365480093f4SDimitry Andric   FeatureBitset MissingFeatures;
13660b57cec5SDimitry Andric 
1367fe6060f1SDimitry Andric   auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1368480093f4SDimitry Andric                                      MatchingInlineAsm);
13690b57cec5SDimitry Andric   switch (Result) {
13700b57cec5SDimitry Andric   default:
13710b57cec5SDimitry Andric     break;
13720b57cec5SDimitry Andric   case Match_Success:
13735ffd83dbSDimitry Andric     if (validateInstruction(Inst, Operands))
13745ffd83dbSDimitry Andric       return true;
13750b57cec5SDimitry Andric     return processInstruction(Inst, IDLoc, Operands, Out);
1376480093f4SDimitry Andric   case Match_MissingFeature: {
1377480093f4SDimitry Andric     assert(MissingFeatures.any() && "Unknown missing features!");
1378480093f4SDimitry Andric     bool FirstFeature = true;
1379480093f4SDimitry Andric     std::string Msg = "instruction requires the following:";
1380480093f4SDimitry Andric     for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1381480093f4SDimitry Andric       if (MissingFeatures[i]) {
1382480093f4SDimitry Andric         Msg += FirstFeature ? " " : ", ";
1383480093f4SDimitry Andric         Msg += getSubtargetFeatureName(i);
1384480093f4SDimitry Andric         FirstFeature = false;
1385480093f4SDimitry Andric       }
1386480093f4SDimitry Andric     }
1387480093f4SDimitry Andric     return Error(IDLoc, Msg);
1388480093f4SDimitry Andric   }
1389480093f4SDimitry Andric   case Match_MnemonicFail: {
1390480093f4SDimitry Andric     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1391349cc55cSDimitry Andric     std::string Suggestion = RISCVMnemonicSpellCheck(
1392349cc55cSDimitry Andric         ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1393480093f4SDimitry Andric     return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1394480093f4SDimitry Andric   }
13950b57cec5SDimitry Andric   case Match_InvalidOperand: {
13960b57cec5SDimitry Andric     SMLoc ErrorLoc = IDLoc;
1397349cc55cSDimitry Andric     if (ErrorInfo != ~0ULL) {
13980b57cec5SDimitry Andric       if (ErrorInfo >= Operands.size())
13990b57cec5SDimitry Andric         return Error(ErrorLoc, "too few operands for instruction");
14000b57cec5SDimitry Andric 
14010b57cec5SDimitry Andric       ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
14020b57cec5SDimitry Andric       if (ErrorLoc == SMLoc())
14030b57cec5SDimitry Andric         ErrorLoc = IDLoc;
14040b57cec5SDimitry Andric     }
14050b57cec5SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
14060b57cec5SDimitry Andric   }
14070b57cec5SDimitry Andric   }
14080b57cec5SDimitry Andric 
14090b57cec5SDimitry Andric   // Handle the case when the error message is of specific type
14100b57cec5SDimitry Andric   // other than the generic Match_InvalidOperand, and the
14110b57cec5SDimitry Andric   // corresponding operand is missing.
14120b57cec5SDimitry Andric   if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
14130b57cec5SDimitry Andric     SMLoc ErrorLoc = IDLoc;
1414349cc55cSDimitry Andric     if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
14150b57cec5SDimitry Andric       return Error(ErrorLoc, "too few operands for instruction");
14160b57cec5SDimitry Andric   }
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric   switch (Result) {
14190b57cec5SDimitry Andric   default:
14200b57cec5SDimitry Andric     break;
142106c3fb27SDimitry Andric   case Match_RequiresEvenGPRs:
142206c3fb27SDimitry Andric     return Error(IDLoc,
142306c3fb27SDimitry Andric                  "double precision floating point operands must use even "
142406c3fb27SDimitry Andric                  "numbered X register");
14250b57cec5SDimitry Andric   case Match_InvalidImmXLenLI:
14260b57cec5SDimitry Andric     if (isRV64()) {
14270b57cec5SDimitry Andric       SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
14280b57cec5SDimitry Andric       return Error(ErrorLoc, "operand must be a constant 64-bit integer");
14290b57cec5SDimitry Andric     }
14300b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo,
14310b57cec5SDimitry Andric                                       std::numeric_limits<int32_t>::min(),
14320b57cec5SDimitry Andric                                       std::numeric_limits<uint32_t>::max());
143306c3fb27SDimitry Andric   case Match_InvalidImmXLenLI_Restricted:
143406c3fb27SDimitry Andric     if (isRV64()) {
143506c3fb27SDimitry Andric       SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
143606c3fb27SDimitry Andric       return Error(ErrorLoc, "operand either must be a constant 64-bit integer "
143706c3fb27SDimitry Andric                              "or a bare symbol name");
143806c3fb27SDimitry Andric     }
143906c3fb27SDimitry Andric     return generateImmOutOfRangeError(
144006c3fb27SDimitry Andric         Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),
144106c3fb27SDimitry Andric         std::numeric_limits<uint32_t>::max(),
144206c3fb27SDimitry Andric         "operand either must be a bare symbol name or an immediate integer in "
144306c3fb27SDimitry Andric         "the range");
14448bcb0991SDimitry Andric   case Match_InvalidImmZero: {
14458bcb0991SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
14468bcb0991SDimitry Andric     return Error(ErrorLoc, "immediate must be zero");
14478bcb0991SDimitry Andric   }
14480b57cec5SDimitry Andric   case Match_InvalidUImmLog2XLen:
14490b57cec5SDimitry Andric     if (isRV64())
14500b57cec5SDimitry Andric       return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
14510b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
14520b57cec5SDimitry Andric   case Match_InvalidUImmLog2XLenNonZero:
14530b57cec5SDimitry Andric     if (isRV64())
14540b57cec5SDimitry Andric       return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
14550b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
14565ffd83dbSDimitry Andric   case Match_InvalidUImmLog2XLenHalf:
14575ffd83dbSDimitry Andric     if (isRV64())
14585ffd83dbSDimitry Andric       return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
14595ffd83dbSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
146006c3fb27SDimitry Andric   case Match_InvalidUImm1:
146106c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
1462349cc55cSDimitry Andric   case Match_InvalidUImm2:
1463349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
146406c3fb27SDimitry Andric   case Match_InvalidUImm2Lsb0:
146506c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
146606c3fb27SDimitry Andric                                       "immediate must be one of");
1467349cc55cSDimitry Andric   case Match_InvalidUImm3:
1468349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
146906c3fb27SDimitry Andric   case Match_InvalidUImm4:
147006c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
14710b57cec5SDimitry Andric   case Match_InvalidUImm5:
14720b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
147306c3fb27SDimitry Andric   case Match_InvalidUImm6:
147406c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1475349cc55cSDimitry Andric   case Match_InvalidUImm7:
1476349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
147706c3fb27SDimitry Andric   case Match_InvalidUImm8:
147806c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
147906c3fb27SDimitry Andric   case Match_InvalidUImm8GE32:
148006c3fb27SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1);
1481e8d8bef9SDimitry Andric   case Match_InvalidSImm5:
1482e8d8bef9SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1483e8d8bef9SDimitry Andric                                       (1 << 4) - 1);
14840b57cec5SDimitry Andric   case Match_InvalidSImm6:
14850b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
14860b57cec5SDimitry Andric                                       (1 << 5) - 1);
14870b57cec5SDimitry Andric   case Match_InvalidSImm6NonZero:
14880b57cec5SDimitry Andric     return generateImmOutOfRangeError(
14890b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
14900b57cec5SDimitry Andric         "immediate must be non-zero in the range");
14910b57cec5SDimitry Andric   case Match_InvalidCLUIImm:
14920b57cec5SDimitry Andric     return generateImmOutOfRangeError(
14930b57cec5SDimitry Andric         Operands, ErrorInfo, 1, (1 << 5) - 1,
14940b57cec5SDimitry Andric         "immediate must be in [0xfffe0, 0xfffff] or");
14950b57cec5SDimitry Andric   case Match_InvalidUImm7Lsb00:
14960b57cec5SDimitry Andric     return generateImmOutOfRangeError(
14970b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 7) - 4,
14980b57cec5SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
14990b57cec5SDimitry Andric   case Match_InvalidUImm8Lsb00:
15000b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15010b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 4,
15020b57cec5SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
15030b57cec5SDimitry Andric   case Match_InvalidUImm8Lsb000:
15040b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15050b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 8,
15060b57cec5SDimitry Andric         "immediate must be a multiple of 8 bytes in the range");
15070b57cec5SDimitry Andric   case Match_InvalidSImm9Lsb0:
15080b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15090b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
15100b57cec5SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
15110b57cec5SDimitry Andric   case Match_InvalidUImm9Lsb000:
15120b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15130b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 9) - 8,
15140b57cec5SDimitry Andric         "immediate must be a multiple of 8 bytes in the range");
15150b57cec5SDimitry Andric   case Match_InvalidUImm10Lsb00NonZero:
15160b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15170b57cec5SDimitry Andric         Operands, ErrorInfo, 4, (1 << 10) - 4,
15180b57cec5SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
15190b57cec5SDimitry Andric   case Match_InvalidSImm10Lsb0000NonZero:
15200b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15210b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
15220b57cec5SDimitry Andric         "immediate must be a multiple of 16 bytes and non-zero in the range");
15230b57cec5SDimitry Andric   case Match_InvalidSImm12:
15240b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15250b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
15260b57cec5SDimitry Andric         "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
15270b57cec5SDimitry Andric         "integer in the range");
15280b57cec5SDimitry Andric   case Match_InvalidSImm12Lsb0:
15290b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15300b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
15310b57cec5SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
153281ad6265SDimitry Andric   case Match_InvalidSImm12Lsb00000:
153381ad6265SDimitry Andric     return generateImmOutOfRangeError(
153481ad6265SDimitry Andric         Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,
153581ad6265SDimitry Andric         "immediate must be a multiple of 32 bytes in the range");
15360b57cec5SDimitry Andric   case Match_InvalidSImm13Lsb0:
15370b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15380b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
15390b57cec5SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
15400b57cec5SDimitry Andric   case Match_InvalidUImm20LUI:
15410b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
15420b57cec5SDimitry Andric                                       "operand must be a symbol with "
15430b57cec5SDimitry Andric                                       "%hi/%tprel_hi modifier or an integer in "
15440b57cec5SDimitry Andric                                       "the range");
15455f757f3fSDimitry Andric   case Match_InvalidUImm20:
15465f757f3fSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
15470b57cec5SDimitry Andric   case Match_InvalidUImm20AUIPC:
15480b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15490b57cec5SDimitry Andric         Operands, ErrorInfo, 0, (1 << 20) - 1,
15500b57cec5SDimitry Andric         "operand must be a symbol with a "
15510b57cec5SDimitry Andric         "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
15520b57cec5SDimitry Andric         "an integer in the range");
15530b57cec5SDimitry Andric   case Match_InvalidSImm21Lsb0JAL:
15540b57cec5SDimitry Andric     return generateImmOutOfRangeError(
15550b57cec5SDimitry Andric         Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
15560b57cec5SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
15570b57cec5SDimitry Andric   case Match_InvalidCSRSystemRegister: {
15580b57cec5SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
15590b57cec5SDimitry Andric                                       "operand must be a valid system register "
15600b57cec5SDimitry Andric                                       "name or an integer in the range");
15610b57cec5SDimitry Andric   }
156206c3fb27SDimitry Andric   case Match_InvalidLoadFPImm: {
15630b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
156406c3fb27SDimitry Andric     return Error(ErrorLoc, "operand must be a valid floating-point constant");
15650b57cec5SDimitry Andric   }
15660b57cec5SDimitry Andric   case Match_InvalidBareSymbol: {
15670b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
15680b57cec5SDimitry Andric     return Error(ErrorLoc, "operand must be a bare symbol name");
15690b57cec5SDimitry Andric   }
15705ffd83dbSDimitry Andric   case Match_InvalidPseudoJumpSymbol: {
15715ffd83dbSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
15725ffd83dbSDimitry Andric     return Error(ErrorLoc, "operand must be a valid jump target");
15735ffd83dbSDimitry Andric   }
15740b57cec5SDimitry Andric   case Match_InvalidCallSymbol: {
15750b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
15760b57cec5SDimitry Andric     return Error(ErrorLoc, "operand must be a bare symbol name");
15770b57cec5SDimitry Andric   }
15780b57cec5SDimitry Andric   case Match_InvalidTPRelAddSymbol: {
15790b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
15800b57cec5SDimitry Andric     return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
15810b57cec5SDimitry Andric   }
15827a6dacacSDimitry Andric   case Match_InvalidTLSDESCCallSymbol: {
15837a6dacacSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
15847a6dacacSDimitry Andric     return Error(ErrorLoc,
15857a6dacacSDimitry Andric                  "operand must be a symbol with %tlsdesc_call modifier");
15867a6dacacSDimitry Andric   }
158706c3fb27SDimitry Andric   case Match_InvalidRTZArg: {
158806c3fb27SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
158906c3fb27SDimitry Andric     return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode");
159006c3fb27SDimitry Andric   }
15915ffd83dbSDimitry Andric   case Match_InvalidVTypeI: {
15925ffd83dbSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
159306c3fb27SDimitry Andric     return generateVTypeError(ErrorLoc);
15945ffd83dbSDimitry Andric   }
15955ffd83dbSDimitry Andric   case Match_InvalidVMaskRegister: {
15965ffd83dbSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
15975ffd83dbSDimitry Andric     return Error(ErrorLoc, "operand must be v0.t");
15985ffd83dbSDimitry Andric   }
15995ffd83dbSDimitry Andric   case Match_InvalidSImm5Plus1: {
16005ffd83dbSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
16015ffd83dbSDimitry Andric                                       (1 << 4),
16025ffd83dbSDimitry Andric                                       "immediate must be in the range");
16035ffd83dbSDimitry Andric   }
160406c3fb27SDimitry Andric   case Match_InvalidRlist: {
160506c3fb27SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
160606c3fb27SDimitry Andric     return Error(
160706c3fb27SDimitry Andric         ErrorLoc,
160806c3fb27SDimitry Andric         "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
160906c3fb27SDimitry Andric   }
161006c3fb27SDimitry Andric   case Match_InvalidSpimm: {
161106c3fb27SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
161206c3fb27SDimitry Andric     return Error(
161306c3fb27SDimitry Andric         ErrorLoc,
161406c3fb27SDimitry Andric         "stack adjustment is invalid for this instruction and register list; "
161506c3fb27SDimitry Andric         "refer to Zc spec for a detailed range of stack adjustment");
161606c3fb27SDimitry Andric   }
161704eeddc0SDimitry Andric   case Match_InvalidRnumArg: {
161804eeddc0SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
161904eeddc0SDimitry Andric   }
16205f757f3fSDimitry Andric   case Match_InvalidRegReg: {
16215f757f3fSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16225f757f3fSDimitry Andric     return Error(ErrorLoc, "operands must be register and register");
16235f757f3fSDimitry Andric   }
16240b57cec5SDimitry Andric   }
16250b57cec5SDimitry Andric 
16260b57cec5SDimitry Andric   llvm_unreachable("Unknown match type detected!");
16270b57cec5SDimitry Andric }
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric // Attempts to match Name as a register (either using the default name or
16300b57cec5SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon
163106c3fb27SDimitry Andric // failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31
163206c3fb27SDimitry Andric // will be rejected.
matchRegisterNameHelper(bool IsRVE,StringRef Name)163306c3fb27SDimitry Andric static MCRegister matchRegisterNameHelper(bool IsRVE, StringRef Name) {
163406c3fb27SDimitry Andric   MCRegister Reg = MatchRegisterName(Name);
1635e8d8bef9SDimitry Andric   // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1636e8d8bef9SDimitry Andric   // match always matches the 64-bit variant, and not the 16/32-bit one.
163706c3fb27SDimitry Andric   assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
163806c3fb27SDimitry Andric   assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
16398bcb0991SDimitry Andric   // The default FPR register class is based on the tablegen enum ordering.
1640e8d8bef9SDimitry Andric   static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
16418bcb0991SDimitry Andric   static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
164206c3fb27SDimitry Andric   if (!Reg)
164306c3fb27SDimitry Andric     Reg = MatchRegisterAltName(Name);
164406c3fb27SDimitry Andric   if (IsRVE && Reg >= RISCV::X16 && Reg <= RISCV::X31)
164506c3fb27SDimitry Andric     Reg = RISCV::NoRegister;
164606c3fb27SDimitry Andric   return Reg;
16470b57cec5SDimitry Andric }
16480b57cec5SDimitry Andric 
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)16495f757f3fSDimitry Andric bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
16500b57cec5SDimitry Andric                                    SMLoc &EndLoc) {
16515f757f3fSDimitry Andric   if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
16525ffd83dbSDimitry Andric     return Error(StartLoc, "invalid register name");
16535ffd83dbSDimitry Andric   return false;
16545ffd83dbSDimitry Andric }
16555ffd83dbSDimitry Andric 
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)16565f757f3fSDimitry Andric ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
16575ffd83dbSDimitry Andric                                              SMLoc &EndLoc) {
16580b57cec5SDimitry Andric   const AsmToken &Tok = getParser().getTok();
16590b57cec5SDimitry Andric   StartLoc = Tok.getLoc();
16600b57cec5SDimitry Andric   EndLoc = Tok.getEndLoc();
16610b57cec5SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
16620b57cec5SDimitry Andric 
16635f757f3fSDimitry Andric   Reg = matchRegisterNameHelper(isRVE(), Name);
16645f757f3fSDimitry Andric   if (!Reg)
16655f757f3fSDimitry Andric     return ParseStatus::NoMatch;
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric   getParser().Lex(); // Eat identifier token.
16685f757f3fSDimitry Andric   return ParseStatus::Success;
16690b57cec5SDimitry Andric }
16700b57cec5SDimitry Andric 
parseRegister(OperandVector & Operands,bool AllowParens)167106c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
16720b57cec5SDimitry Andric                                           bool AllowParens) {
16730b57cec5SDimitry Andric   SMLoc FirstS = getLoc();
16740b57cec5SDimitry Andric   bool HadParens = false;
16750b57cec5SDimitry Andric   AsmToken LParen;
16760b57cec5SDimitry Andric 
16770b57cec5SDimitry Andric   // If this is an LParen and a parenthesised register name is allowed, parse it
16780b57cec5SDimitry Andric   // atomically.
16790b57cec5SDimitry Andric   if (AllowParens && getLexer().is(AsmToken::LParen)) {
16800b57cec5SDimitry Andric     AsmToken Buf[2];
16810b57cec5SDimitry Andric     size_t ReadCount = getLexer().peekTokens(Buf);
16820b57cec5SDimitry Andric     if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
16830b57cec5SDimitry Andric       HadParens = true;
16840b57cec5SDimitry Andric       LParen = getParser().getTok();
16850b57cec5SDimitry Andric       getParser().Lex(); // Eat '('
16860b57cec5SDimitry Andric     }
16870b57cec5SDimitry Andric   }
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric   switch (getLexer().getKind()) {
16900b57cec5SDimitry Andric   default:
16910b57cec5SDimitry Andric     if (HadParens)
16920b57cec5SDimitry Andric       getLexer().UnLex(LParen);
169306c3fb27SDimitry Andric     return ParseStatus::NoMatch;
16940b57cec5SDimitry Andric   case AsmToken::Identifier:
16950b57cec5SDimitry Andric     StringRef Name = getLexer().getTok().getIdentifier();
169606c3fb27SDimitry Andric     MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
16970b57cec5SDimitry Andric 
169806c3fb27SDimitry Andric     if (!RegNo) {
16990b57cec5SDimitry Andric       if (HadParens)
17000b57cec5SDimitry Andric         getLexer().UnLex(LParen);
170106c3fb27SDimitry Andric       return ParseStatus::NoMatch;
17020b57cec5SDimitry Andric     }
17030b57cec5SDimitry Andric     if (HadParens)
170406c3fb27SDimitry Andric       Operands.push_back(RISCVOperand::createToken("(", FirstS));
17050b57cec5SDimitry Andric     SMLoc S = getLoc();
17060eae32dcSDimitry Andric     SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
17070b57cec5SDimitry Andric     getLexer().Lex();
170806c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
17090b57cec5SDimitry Andric   }
17100b57cec5SDimitry Andric 
17110b57cec5SDimitry Andric   if (HadParens) {
17120b57cec5SDimitry Andric     getParser().Lex(); // Eat ')'
171306c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createToken(")", getLoc()));
17140b57cec5SDimitry Andric   }
17150b57cec5SDimitry Andric 
171606c3fb27SDimitry Andric   return ParseStatus::Success;
17170b57cec5SDimitry Andric }
17180b57cec5SDimitry Andric 
parseInsnDirectiveOpcode(OperandVector & Operands)171906c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
17200eae32dcSDimitry Andric   SMLoc S = getLoc();
17210eae32dcSDimitry Andric   SMLoc E;
17220eae32dcSDimitry Andric   const MCExpr *Res;
17230eae32dcSDimitry Andric 
17240eae32dcSDimitry Andric   switch (getLexer().getKind()) {
17250eae32dcSDimitry Andric   default:
172606c3fb27SDimitry Andric     return ParseStatus::NoMatch;
17270eae32dcSDimitry Andric   case AsmToken::LParen:
17280eae32dcSDimitry Andric   case AsmToken::Minus:
17290eae32dcSDimitry Andric   case AsmToken::Plus:
17300eae32dcSDimitry Andric   case AsmToken::Exclaim:
17310eae32dcSDimitry Andric   case AsmToken::Tilde:
17320eae32dcSDimitry Andric   case AsmToken::Integer:
17330eae32dcSDimitry Andric   case AsmToken::String: {
17340eae32dcSDimitry Andric     if (getParser().parseExpression(Res, E))
173506c3fb27SDimitry Andric       return ParseStatus::Failure;
17360eae32dcSDimitry Andric 
17370eae32dcSDimitry Andric     auto *CE = dyn_cast<MCConstantExpr>(Res);
17380eae32dcSDimitry Andric     if (CE) {
17390eae32dcSDimitry Andric       int64_t Imm = CE->getValue();
17400eae32dcSDimitry Andric       if (isUInt<7>(Imm)) {
17410eae32dcSDimitry Andric         Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
174206c3fb27SDimitry Andric         return ParseStatus::Success;
17430eae32dcSDimitry Andric       }
17440eae32dcSDimitry Andric     }
17450eae32dcSDimitry Andric 
174606c3fb27SDimitry Andric     break;
17470eae32dcSDimitry Andric   }
17480eae32dcSDimitry Andric   case AsmToken::Identifier: {
17490eae32dcSDimitry Andric     StringRef Identifier;
17500eae32dcSDimitry Andric     if (getParser().parseIdentifier(Identifier))
175106c3fb27SDimitry Andric       return ParseStatus::Failure;
17520eae32dcSDimitry Andric 
17530eae32dcSDimitry Andric     auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
17540eae32dcSDimitry Andric     if (Opcode) {
175506c3fb27SDimitry Andric       assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
175606c3fb27SDimitry Andric              "Unexpected opcode");
17570eae32dcSDimitry Andric       Res = MCConstantExpr::create(Opcode->Value, getContext());
17580eae32dcSDimitry Andric       E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
17590eae32dcSDimitry Andric       Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
176006c3fb27SDimitry Andric       return ParseStatus::Success;
17610eae32dcSDimitry Andric     }
17620eae32dcSDimitry Andric 
176306c3fb27SDimitry Andric     break;
176406c3fb27SDimitry Andric   }
176506c3fb27SDimitry Andric   case AsmToken::Percent:
176606c3fb27SDimitry Andric     break;
176706c3fb27SDimitry Andric   }
176806c3fb27SDimitry Andric 
176906c3fb27SDimitry Andric   return generateImmOutOfRangeError(
177006c3fb27SDimitry Andric       S, 0, 127,
177106c3fb27SDimitry Andric       "opcode must be a valid opcode name or an immediate in the range");
177206c3fb27SDimitry Andric }
177306c3fb27SDimitry Andric 
parseInsnCDirectiveOpcode(OperandVector & Operands)177406c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
177506c3fb27SDimitry Andric   SMLoc S = getLoc();
177606c3fb27SDimitry Andric   SMLoc E;
177706c3fb27SDimitry Andric   const MCExpr *Res;
177806c3fb27SDimitry Andric 
177906c3fb27SDimitry Andric   switch (getLexer().getKind()) {
178006c3fb27SDimitry Andric   default:
178106c3fb27SDimitry Andric     return ParseStatus::NoMatch;
178206c3fb27SDimitry Andric   case AsmToken::LParen:
178306c3fb27SDimitry Andric   case AsmToken::Minus:
178406c3fb27SDimitry Andric   case AsmToken::Plus:
178506c3fb27SDimitry Andric   case AsmToken::Exclaim:
178606c3fb27SDimitry Andric   case AsmToken::Tilde:
178706c3fb27SDimitry Andric   case AsmToken::Integer:
178806c3fb27SDimitry Andric   case AsmToken::String: {
178906c3fb27SDimitry Andric     if (getParser().parseExpression(Res, E))
179006c3fb27SDimitry Andric       return ParseStatus::Failure;
179106c3fb27SDimitry Andric 
179206c3fb27SDimitry Andric     auto *CE = dyn_cast<MCConstantExpr>(Res);
179306c3fb27SDimitry Andric     if (CE) {
179406c3fb27SDimitry Andric       int64_t Imm = CE->getValue();
179506c3fb27SDimitry Andric       if (Imm >= 0 && Imm <= 2) {
179606c3fb27SDimitry Andric         Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
179706c3fb27SDimitry Andric         return ParseStatus::Success;
179806c3fb27SDimitry Andric       }
179906c3fb27SDimitry Andric     }
180006c3fb27SDimitry Andric 
180106c3fb27SDimitry Andric     break;
180206c3fb27SDimitry Andric   }
180306c3fb27SDimitry Andric   case AsmToken::Identifier: {
180406c3fb27SDimitry Andric     StringRef Identifier;
180506c3fb27SDimitry Andric     if (getParser().parseIdentifier(Identifier))
180606c3fb27SDimitry Andric       return ParseStatus::Failure;
180706c3fb27SDimitry Andric 
180806c3fb27SDimitry Andric     unsigned Opcode;
180906c3fb27SDimitry Andric     if (Identifier == "C0")
181006c3fb27SDimitry Andric       Opcode = 0;
181106c3fb27SDimitry Andric     else if (Identifier == "C1")
181206c3fb27SDimitry Andric       Opcode = 1;
181306c3fb27SDimitry Andric     else if (Identifier == "C2")
181406c3fb27SDimitry Andric       Opcode = 2;
181506c3fb27SDimitry Andric     else
181606c3fb27SDimitry Andric       break;
181706c3fb27SDimitry Andric 
181806c3fb27SDimitry Andric     Res = MCConstantExpr::create(Opcode, getContext());
181906c3fb27SDimitry Andric     E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
182006c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
182106c3fb27SDimitry Andric     return ParseStatus::Success;
18220eae32dcSDimitry Andric   }
18230eae32dcSDimitry Andric   case AsmToken::Percent: {
18240eae32dcSDimitry Andric     // Discard operand with modifier.
182506c3fb27SDimitry Andric     break;
18260eae32dcSDimitry Andric   }
18270eae32dcSDimitry Andric   }
18280eae32dcSDimitry Andric 
182906c3fb27SDimitry Andric   return generateImmOutOfRangeError(
183006c3fb27SDimitry Andric       S, 0, 2,
183106c3fb27SDimitry Andric       "opcode must be a valid opcode name or an immediate in the range");
18320eae32dcSDimitry Andric }
18330eae32dcSDimitry Andric 
parseCSRSystemRegister(OperandVector & Operands)183406c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
18350b57cec5SDimitry Andric   SMLoc S = getLoc();
18360b57cec5SDimitry Andric   const MCExpr *Res;
18370b57cec5SDimitry Andric 
18380b57cec5SDimitry Andric   switch (getLexer().getKind()) {
18390b57cec5SDimitry Andric   default:
184006c3fb27SDimitry Andric     return ParseStatus::NoMatch;
18410b57cec5SDimitry Andric   case AsmToken::LParen:
18420b57cec5SDimitry Andric   case AsmToken::Minus:
18430b57cec5SDimitry Andric   case AsmToken::Plus:
18440b57cec5SDimitry Andric   case AsmToken::Exclaim:
18450b57cec5SDimitry Andric   case AsmToken::Tilde:
18460b57cec5SDimitry Andric   case AsmToken::Integer:
18470b57cec5SDimitry Andric   case AsmToken::String: {
18480b57cec5SDimitry Andric     if (getParser().parseExpression(Res))
184906c3fb27SDimitry Andric       return ParseStatus::Failure;
18500b57cec5SDimitry Andric 
18510b57cec5SDimitry Andric     auto *CE = dyn_cast<MCConstantExpr>(Res);
18520b57cec5SDimitry Andric     if (CE) {
18530b57cec5SDimitry Andric       int64_t Imm = CE->getValue();
18540b57cec5SDimitry Andric       if (isUInt<12>(Imm)) {
18550b57cec5SDimitry Andric         auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
18560b57cec5SDimitry Andric         // Accept an immediate representing a named or un-named Sys Reg
18570b57cec5SDimitry Andric         // if the range is valid, regardless of the required features.
185806c3fb27SDimitry Andric         Operands.push_back(
185906c3fb27SDimitry Andric             RISCVOperand::createSysReg(SysReg ? SysReg->Name : "", S, Imm));
186006c3fb27SDimitry Andric         return ParseStatus::Success;
18610b57cec5SDimitry Andric       }
18620b57cec5SDimitry Andric     }
18630b57cec5SDimitry Andric 
186406c3fb27SDimitry Andric     return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
18650b57cec5SDimitry Andric   }
18660b57cec5SDimitry Andric   case AsmToken::Identifier: {
18670b57cec5SDimitry Andric     StringRef Identifier;
18680b57cec5SDimitry Andric     if (getParser().parseIdentifier(Identifier))
186906c3fb27SDimitry Andric       return ParseStatus::Failure;
187006c3fb27SDimitry Andric 
18710b57cec5SDimitry Andric     auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
18725ffd83dbSDimitry Andric     if (!SysReg)
1873647cbc5dSDimitry Andric       SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1874647cbc5dSDimitry Andric     if (!SysReg)
1875fe6060f1SDimitry Andric       if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1876fe6060f1SDimitry Andric         Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1877fe6060f1SDimitry Andric                        SysReg->Name + "'");
1878fe6060f1SDimitry Andric 
18790b57cec5SDimitry Andric     // Accept a named Sys Reg if the required features are present.
18800b57cec5SDimitry Andric     if (SysReg) {
188106c3fb27SDimitry Andric       if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits()))
188206c3fb27SDimitry Andric         return Error(S, "system register use requires an option to be enabled");
188306c3fb27SDimitry Andric       Operands.push_back(
188406c3fb27SDimitry Andric           RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
188506c3fb27SDimitry Andric       return ParseStatus::Success;
18860b57cec5SDimitry Andric     }
18870b57cec5SDimitry Andric 
188806c3fb27SDimitry Andric     return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
188906c3fb27SDimitry Andric                                       "operand must be a valid system register "
189006c3fb27SDimitry Andric                                       "name or an integer in the range");
18910b57cec5SDimitry Andric   }
18920b57cec5SDimitry Andric   case AsmToken::Percent: {
18930b57cec5SDimitry Andric     // Discard operand with modifier.
189406c3fb27SDimitry Andric     return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
18950b57cec5SDimitry Andric   }
18960b57cec5SDimitry Andric   }
18970b57cec5SDimitry Andric 
189806c3fb27SDimitry Andric   return ParseStatus::NoMatch;
18990b57cec5SDimitry Andric }
19000b57cec5SDimitry Andric 
parseFPImm(OperandVector & Operands)190106c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
190206c3fb27SDimitry Andric   SMLoc S = getLoc();
190306c3fb27SDimitry Andric 
190406c3fb27SDimitry Andric   // Parse special floats (inf/nan/min) representation.
190506c3fb27SDimitry Andric   if (getTok().is(AsmToken::Identifier)) {
190606c3fb27SDimitry Andric     StringRef Identifier = getTok().getIdentifier();
190706c3fb27SDimitry Andric     if (Identifier.compare_insensitive("inf") == 0) {
190806c3fb27SDimitry Andric       Operands.push_back(
190906c3fb27SDimitry Andric           RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,
191006c3fb27SDimitry Andric                                   getTok().getEndLoc(), isRV64()));
191106c3fb27SDimitry Andric     } else if (Identifier.compare_insensitive("nan") == 0) {
191206c3fb27SDimitry Andric       Operands.push_back(
191306c3fb27SDimitry Andric           RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,
191406c3fb27SDimitry Andric                                   getTok().getEndLoc(), isRV64()));
191506c3fb27SDimitry Andric     } else if (Identifier.compare_insensitive("min") == 0) {
191606c3fb27SDimitry Andric       Operands.push_back(
191706c3fb27SDimitry Andric           RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S,
191806c3fb27SDimitry Andric                                   getTok().getEndLoc(), isRV64()));
191906c3fb27SDimitry Andric     } else {
192006c3fb27SDimitry Andric       return TokError("invalid floating point literal");
192106c3fb27SDimitry Andric     }
192206c3fb27SDimitry Andric 
192306c3fb27SDimitry Andric     Lex(); // Eat the token.
192406c3fb27SDimitry Andric 
192506c3fb27SDimitry Andric     return ParseStatus::Success;
192606c3fb27SDimitry Andric   }
192706c3fb27SDimitry Andric 
192806c3fb27SDimitry Andric   // Handle negation, as that still comes through as a separate token.
192906c3fb27SDimitry Andric   bool IsNegative = parseOptionalToken(AsmToken::Minus);
193006c3fb27SDimitry Andric 
193106c3fb27SDimitry Andric   const AsmToken &Tok = getTok();
193206c3fb27SDimitry Andric   if (!Tok.is(AsmToken::Real))
193306c3fb27SDimitry Andric     return TokError("invalid floating point immediate");
193406c3fb27SDimitry Andric 
193506c3fb27SDimitry Andric   // Parse FP representation.
193606c3fb27SDimitry Andric   APFloat RealVal(APFloat::IEEEdouble());
193706c3fb27SDimitry Andric   auto StatusOrErr =
193806c3fb27SDimitry Andric       RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
193906c3fb27SDimitry Andric   if (errorToBool(StatusOrErr.takeError()))
194006c3fb27SDimitry Andric     return TokError("invalid floating point representation");
194106c3fb27SDimitry Andric 
194206c3fb27SDimitry Andric   if (IsNegative)
194306c3fb27SDimitry Andric     RealVal.changeSign();
194406c3fb27SDimitry Andric 
194506c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createFPImm(
194606c3fb27SDimitry Andric       RealVal.bitcastToAPInt().getZExtValue(), S));
194706c3fb27SDimitry Andric 
194806c3fb27SDimitry Andric   Lex(); // Eat the token.
194906c3fb27SDimitry Andric 
195006c3fb27SDimitry Andric   return ParseStatus::Success;
195106c3fb27SDimitry Andric }
195206c3fb27SDimitry Andric 
parseImmediate(OperandVector & Operands)195306c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseImmediate(OperandVector &Operands) {
19540b57cec5SDimitry Andric   SMLoc S = getLoc();
19550eae32dcSDimitry Andric   SMLoc E;
19560b57cec5SDimitry Andric   const MCExpr *Res;
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric   switch (getLexer().getKind()) {
19590b57cec5SDimitry Andric   default:
196006c3fb27SDimitry Andric     return ParseStatus::NoMatch;
19610b57cec5SDimitry Andric   case AsmToken::LParen:
19620b57cec5SDimitry Andric   case AsmToken::Dot:
19630b57cec5SDimitry Andric   case AsmToken::Minus:
19640b57cec5SDimitry Andric   case AsmToken::Plus:
19650b57cec5SDimitry Andric   case AsmToken::Exclaim:
19660b57cec5SDimitry Andric   case AsmToken::Tilde:
19670b57cec5SDimitry Andric   case AsmToken::Integer:
19680b57cec5SDimitry Andric   case AsmToken::String:
19690b57cec5SDimitry Andric   case AsmToken::Identifier:
19700eae32dcSDimitry Andric     if (getParser().parseExpression(Res, E))
197106c3fb27SDimitry Andric       return ParseStatus::Failure;
19720b57cec5SDimitry Andric     break;
19730b57cec5SDimitry Andric   case AsmToken::Percent:
19740b57cec5SDimitry Andric     return parseOperandWithModifier(Operands);
19750b57cec5SDimitry Andric   }
19760b57cec5SDimitry Andric 
19770b57cec5SDimitry Andric   Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
197806c3fb27SDimitry Andric   return ParseStatus::Success;
19790b57cec5SDimitry Andric }
19800b57cec5SDimitry Andric 
parseOperandWithModifier(OperandVector & Operands)198106c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
19820b57cec5SDimitry Andric   SMLoc S = getLoc();
19830eae32dcSDimitry Andric   SMLoc E;
19840b57cec5SDimitry Andric 
198506c3fb27SDimitry Andric   if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))
198606c3fb27SDimitry Andric     return ParseStatus::Failure;
19870b57cec5SDimitry Andric 
198806c3fb27SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
198906c3fb27SDimitry Andric     return Error(getLoc(), "expected valid identifier for operand modifier");
19900b57cec5SDimitry Andric   StringRef Identifier = getParser().getTok().getIdentifier();
19910b57cec5SDimitry Andric   RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
199206c3fb27SDimitry Andric   if (VK == RISCVMCExpr::VK_RISCV_Invalid)
199306c3fb27SDimitry Andric     return Error(getLoc(), "unrecognized operand modifier");
19940b57cec5SDimitry Andric 
19950b57cec5SDimitry Andric   getParser().Lex(); // Eat the identifier
199606c3fb27SDimitry Andric   if (parseToken(AsmToken::LParen, "expected '('"))
199706c3fb27SDimitry Andric     return ParseStatus::Failure;
19980b57cec5SDimitry Andric 
19990b57cec5SDimitry Andric   const MCExpr *SubExpr;
200006c3fb27SDimitry Andric   if (getParser().parseParenExpression(SubExpr, E))
200106c3fb27SDimitry Andric     return ParseStatus::Failure;
20020b57cec5SDimitry Andric 
20030b57cec5SDimitry Andric   const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
20040b57cec5SDimitry Andric   Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
200506c3fb27SDimitry Andric   return ParseStatus::Success;
20060b57cec5SDimitry Andric }
20070b57cec5SDimitry Andric 
parseBareSymbol(OperandVector & Operands)200806c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
20090b57cec5SDimitry Andric   SMLoc S = getLoc();
20100b57cec5SDimitry Andric   const MCExpr *Res;
20110b57cec5SDimitry Andric 
20120b57cec5SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
201306c3fb27SDimitry Andric     return ParseStatus::NoMatch;
20140b57cec5SDimitry Andric 
20150b57cec5SDimitry Andric   StringRef Identifier;
20160b57cec5SDimitry Andric   AsmToken Tok = getLexer().getTok();
20170b57cec5SDimitry Andric 
20180b57cec5SDimitry Andric   if (getParser().parseIdentifier(Identifier))
201906c3fb27SDimitry Andric     return ParseStatus::Failure;
20200b57cec5SDimitry Andric 
20210eae32dcSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
20220eae32dcSDimitry Andric 
202306c3fb27SDimitry Andric   if (Identifier.consume_back("@plt"))
202406c3fb27SDimitry Andric     return Error(getLoc(), "'@plt' operand not valid for instruction");
20250b57cec5SDimitry Andric 
20260b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
20270b57cec5SDimitry Andric 
20280b57cec5SDimitry Andric   if (Sym->isVariable()) {
20290b57cec5SDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
20300b57cec5SDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
20310b57cec5SDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
203206c3fb27SDimitry Andric       return ParseStatus::NoMatch;
20330b57cec5SDimitry Andric     }
20340b57cec5SDimitry Andric     Res = V;
20350b57cec5SDimitry Andric   } else
20360b57cec5SDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric   MCBinaryExpr::Opcode Opcode;
20390b57cec5SDimitry Andric   switch (getLexer().getKind()) {
20400b57cec5SDimitry Andric   default:
20410b57cec5SDimitry Andric     Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
204206c3fb27SDimitry Andric     return ParseStatus::Success;
20430b57cec5SDimitry Andric   case AsmToken::Plus:
20440b57cec5SDimitry Andric     Opcode = MCBinaryExpr::Add;
2045d781ede6SDimitry Andric     getLexer().Lex();
20460b57cec5SDimitry Andric     break;
20470b57cec5SDimitry Andric   case AsmToken::Minus:
20480b57cec5SDimitry Andric     Opcode = MCBinaryExpr::Sub;
2049d781ede6SDimitry Andric     getLexer().Lex();
20500b57cec5SDimitry Andric     break;
20510b57cec5SDimitry Andric   }
20520b57cec5SDimitry Andric 
20530b57cec5SDimitry Andric   const MCExpr *Expr;
20540eae32dcSDimitry Andric   if (getParser().parseExpression(Expr, E))
205506c3fb27SDimitry Andric     return ParseStatus::Failure;
20560b57cec5SDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
20570b57cec5SDimitry Andric   Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
205806c3fb27SDimitry Andric   return ParseStatus::Success;
20590b57cec5SDimitry Andric }
20600b57cec5SDimitry Andric 
parseCallSymbol(OperandVector & Operands)206106c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
20620b57cec5SDimitry Andric   SMLoc S = getLoc();
20630b57cec5SDimitry Andric   const MCExpr *Res;
20640b57cec5SDimitry Andric 
20650b57cec5SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
206606c3fb27SDimitry Andric     return ParseStatus::NoMatch;
20670b57cec5SDimitry Andric 
20680b57cec5SDimitry Andric   // Avoid parsing the register in `call rd, foo` as a call symbol.
20690b57cec5SDimitry Andric   if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
207006c3fb27SDimitry Andric     return ParseStatus::NoMatch;
20710b57cec5SDimitry Andric 
20720b57cec5SDimitry Andric   StringRef Identifier;
20730b57cec5SDimitry Andric   if (getParser().parseIdentifier(Identifier))
207406c3fb27SDimitry Andric     return ParseStatus::Failure;
20750b57cec5SDimitry Andric 
20760eae32dcSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
20770eae32dcSDimitry Andric 
20781db9f3b2SDimitry Andric   RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
20791db9f3b2SDimitry Andric   (void)Identifier.consume_back("@plt");
20800b57cec5SDimitry Andric 
20810b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
20820b57cec5SDimitry Andric   Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
20830b57cec5SDimitry Andric   Res = RISCVMCExpr::create(Res, Kind, getContext());
20840b57cec5SDimitry Andric   Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
208506c3fb27SDimitry Andric   return ParseStatus::Success;
20860b57cec5SDimitry Andric }
20870b57cec5SDimitry Andric 
parsePseudoJumpSymbol(OperandVector & Operands)208806c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
20895ffd83dbSDimitry Andric   SMLoc S = getLoc();
20900eae32dcSDimitry Andric   SMLoc E;
20915ffd83dbSDimitry Andric   const MCExpr *Res;
20925ffd83dbSDimitry Andric 
20930eae32dcSDimitry Andric   if (getParser().parseExpression(Res, E))
209406c3fb27SDimitry Andric     return ParseStatus::Failure;
20955ffd83dbSDimitry Andric 
20965ffd83dbSDimitry Andric   if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
20975ffd83dbSDimitry Andric       cast<MCSymbolRefExpr>(Res)->getKind() ==
209806c3fb27SDimitry Andric           MCSymbolRefExpr::VariantKind::VK_PLT)
209906c3fb27SDimitry Andric     return Error(S, "operand must be a valid jump target");
21005ffd83dbSDimitry Andric 
21015ffd83dbSDimitry Andric   Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
21025ffd83dbSDimitry Andric   Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
210306c3fb27SDimitry Andric   return ParseStatus::Success;
21045ffd83dbSDimitry Andric }
21055ffd83dbSDimitry Andric 
parseJALOffset(OperandVector & Operands)210606c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
21070b57cec5SDimitry Andric   // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
21080b57cec5SDimitry Andric   // both being acceptable forms. When parsing `jal ra, foo` this function
21090b57cec5SDimitry Andric   // will be called for the `ra` register operand in an attempt to match the
21100b57cec5SDimitry Andric   // single-operand alias. parseJALOffset must fail for this case. It would
21110b57cec5SDimitry Andric   // seem logical to try parse the operand using parseImmediate and return
21120b57cec5SDimitry Andric   // NoMatch if the next token is a comma (meaning we must be parsing a jal in
21130b57cec5SDimitry Andric   // the second form rather than the first). We can't do this as there's no
21140b57cec5SDimitry Andric   // way of rewinding the lexer state. Instead, return NoMatch if this operand
21150b57cec5SDimitry Andric   // is an identifier and is followed by a comma.
21160b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Identifier) &&
21170b57cec5SDimitry Andric       getLexer().peekTok().is(AsmToken::Comma))
211806c3fb27SDimitry Andric     return ParseStatus::NoMatch;
21190b57cec5SDimitry Andric 
21200b57cec5SDimitry Andric   return parseImmediate(Operands);
21210b57cec5SDimitry Andric }
21220b57cec5SDimitry Andric 
parseVTypeToken(StringRef Identifier,VTypeState & State,unsigned & Sew,unsigned & Lmul,bool & Fractional,bool & TailAgnostic,bool & MaskAgnostic)212306c3fb27SDimitry Andric bool RISCVAsmParser::parseVTypeToken(StringRef Identifier, VTypeState &State,
212406c3fb27SDimitry Andric                                      unsigned &Sew, unsigned &Lmul,
212506c3fb27SDimitry Andric                                      bool &Fractional, bool &TailAgnostic,
212606c3fb27SDimitry Andric                                      bool &MaskAgnostic) {
212706c3fb27SDimitry Andric   switch (State) {
212806c3fb27SDimitry Andric   case VTypeState_SEW:
212906c3fb27SDimitry Andric     if (!Identifier.consume_front("e"))
2130fe6060f1SDimitry Andric       break;
213106c3fb27SDimitry Andric     if (Identifier.getAsInteger(10, Sew))
213206c3fb27SDimitry Andric       break;
213306c3fb27SDimitry Andric     if (!RISCVVType::isValidSEW(Sew))
213406c3fb27SDimitry Andric       break;
213506c3fb27SDimitry Andric     State = VTypeState_LMUL;
213606c3fb27SDimitry Andric     return false;
213706c3fb27SDimitry Andric   case VTypeState_LMUL: {
213806c3fb27SDimitry Andric     if (!Identifier.consume_front("m"))
213906c3fb27SDimitry Andric       break;
214006c3fb27SDimitry Andric     Fractional = Identifier.consume_front("f");
214106c3fb27SDimitry Andric     if (Identifier.getAsInteger(10, Lmul))
214206c3fb27SDimitry Andric       break;
214306c3fb27SDimitry Andric     if (!RISCVVType::isValidLMUL(Lmul, Fractional))
214406c3fb27SDimitry Andric       break;
214506c3fb27SDimitry Andric     State = VTypeState_TailPolicy;
214606c3fb27SDimitry Andric     return false;
214706c3fb27SDimitry Andric   }
214806c3fb27SDimitry Andric   case VTypeState_TailPolicy:
214906c3fb27SDimitry Andric     if (Identifier == "ta")
215006c3fb27SDimitry Andric       TailAgnostic = true;
215106c3fb27SDimitry Andric     else if (Identifier == "tu")
215206c3fb27SDimitry Andric       TailAgnostic = false;
215306c3fb27SDimitry Andric     else
215406c3fb27SDimitry Andric       break;
215506c3fb27SDimitry Andric     State = VTypeState_MaskPolicy;
215606c3fb27SDimitry Andric     return false;
215706c3fb27SDimitry Andric   case VTypeState_MaskPolicy:
215806c3fb27SDimitry Andric     if (Identifier == "ma")
215906c3fb27SDimitry Andric       MaskAgnostic = true;
216006c3fb27SDimitry Andric     else if (Identifier == "mu")
216106c3fb27SDimitry Andric       MaskAgnostic = false;
216206c3fb27SDimitry Andric     else
216306c3fb27SDimitry Andric       break;
216406c3fb27SDimitry Andric     State = VTypeState_Done;
216506c3fb27SDimitry Andric     return false;
216606c3fb27SDimitry Andric   case VTypeState_Done:
216706c3fb27SDimitry Andric     // Extra token?
216806c3fb27SDimitry Andric     break;
216906c3fb27SDimitry Andric   }
217006c3fb27SDimitry Andric 
217106c3fb27SDimitry Andric   return true;
217206c3fb27SDimitry Andric }
217306c3fb27SDimitry Andric 
parseVTypeI(OperandVector & Operands)217406c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
217506c3fb27SDimitry Andric   SMLoc S = getLoc();
217606c3fb27SDimitry Andric 
217706c3fb27SDimitry Andric   unsigned Sew = 0;
217806c3fb27SDimitry Andric   unsigned Lmul = 0;
217906c3fb27SDimitry Andric   bool Fractional = false;
218006c3fb27SDimitry Andric   bool TailAgnostic = false;
218106c3fb27SDimitry Andric   bool MaskAgnostic = false;
218206c3fb27SDimitry Andric 
218306c3fb27SDimitry Andric   VTypeState State = VTypeState_SEW;
218406c3fb27SDimitry Andric 
218506c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
218606c3fb27SDimitry Andric     return ParseStatus::NoMatch;
218706c3fb27SDimitry Andric 
218806c3fb27SDimitry Andric   StringRef Identifier = getTok().getIdentifier();
218906c3fb27SDimitry Andric 
219006c3fb27SDimitry Andric   if (parseVTypeToken(Identifier, State, Sew, Lmul, Fractional, TailAgnostic,
219106c3fb27SDimitry Andric                       MaskAgnostic))
219206c3fb27SDimitry Andric     return ParseStatus::NoMatch;
219306c3fb27SDimitry Andric 
219406c3fb27SDimitry Andric   getLexer().Lex();
219506c3fb27SDimitry Andric 
219606c3fb27SDimitry Andric   while (parseOptionalToken(AsmToken::Comma)) {
219706c3fb27SDimitry Andric     if (getLexer().isNot(AsmToken::Identifier))
219806c3fb27SDimitry Andric       break;
219906c3fb27SDimitry Andric 
220006c3fb27SDimitry Andric     Identifier = getTok().getIdentifier();
220106c3fb27SDimitry Andric 
220206c3fb27SDimitry Andric     if (parseVTypeToken(Identifier, State, Sew, Lmul, Fractional, TailAgnostic,
220306c3fb27SDimitry Andric                         MaskAgnostic))
220406c3fb27SDimitry Andric       break;
220506c3fb27SDimitry Andric 
2206fe6060f1SDimitry Andric     getLexer().Lex();
2207fe6060f1SDimitry Andric   }
2208fe6060f1SDimitry Andric 
220906c3fb27SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) {
221081ad6265SDimitry Andric     RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);
2211e8d8bef9SDimitry Andric 
2212e8d8bef9SDimitry Andric     unsigned VTypeI =
2213fe6060f1SDimitry Andric         RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);
221406c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createVType(VTypeI, S));
221506c3fb27SDimitry Andric     return ParseStatus::Success;
22165ffd83dbSDimitry Andric   }
22175ffd83dbSDimitry Andric 
221806c3fb27SDimitry Andric   return generateVTypeError(S);
2219fe6060f1SDimitry Andric }
2220fe6060f1SDimitry Andric 
generateVTypeError(SMLoc ErrorLoc)222106c3fb27SDimitry Andric bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
222206c3fb27SDimitry Andric   return Error(
222306c3fb27SDimitry Andric       ErrorLoc,
222406c3fb27SDimitry Andric       "operand must be "
222506c3fb27SDimitry Andric       "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
222606c3fb27SDimitry Andric }
222706c3fb27SDimitry Andric 
parseMaskReg(OperandVector & Operands)222806c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
222906c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
223006c3fb27SDimitry Andric     return ParseStatus::NoMatch;
223106c3fb27SDimitry Andric 
22325ffd83dbSDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
223306c3fb27SDimitry Andric   if (!Name.consume_back(".t"))
223406c3fb27SDimitry Andric     return Error(getLoc(), "expected '.t' suffix");
223506c3fb27SDimitry Andric   MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
22365ffd83dbSDimitry Andric 
223706c3fb27SDimitry Andric   if (!RegNo)
223806c3fb27SDimitry Andric     return ParseStatus::NoMatch;
22395ffd83dbSDimitry Andric   if (RegNo != RISCV::V0)
224006c3fb27SDimitry Andric     return ParseStatus::NoMatch;
22415ffd83dbSDimitry Andric   SMLoc S = getLoc();
22420eae32dcSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
22435ffd83dbSDimitry Andric   getLexer().Lex();
224406c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
224506c3fb27SDimitry Andric   return ParseStatus::Success;
22465ffd83dbSDimitry Andric }
22475ffd83dbSDimitry Andric 
parseGPRAsFPR(OperandVector & Operands)224806c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
224906c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
225006c3fb27SDimitry Andric     return ParseStatus::NoMatch;
22515ffd83dbSDimitry Andric 
2252d56accc7SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
225306c3fb27SDimitry Andric   MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
2254d56accc7SDimitry Andric 
225506c3fb27SDimitry Andric   if (!RegNo)
225606c3fb27SDimitry Andric     return ParseStatus::NoMatch;
2257d56accc7SDimitry Andric   SMLoc S = getLoc();
225806c3fb27SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2259d56accc7SDimitry Andric   getLexer().Lex();
2260d56accc7SDimitry Andric   Operands.push_back(RISCVOperand::createReg(
226106c3fb27SDimitry Andric       RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
226206c3fb27SDimitry Andric   return ParseStatus::Success;
2263d56accc7SDimitry Andric }
2264d56accc7SDimitry Andric 
2265297eecfbSDimitry Andric template <bool IsRV64>
parseGPRPair(OperandVector & Operands)2266297eecfbSDimitry Andric ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2267297eecfbSDimitry Andric   return parseGPRPair(Operands, IsRV64);
2268297eecfbSDimitry Andric }
2269297eecfbSDimitry Andric 
parseGPRPair(OperandVector & Operands,bool IsRV64Inst)2270297eecfbSDimitry Andric ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2271297eecfbSDimitry Andric                                          bool IsRV64Inst) {
2272297eecfbSDimitry Andric   // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2273297eecfbSDimitry Andric   // RV64 as it will prevent matching the RV64 version of the same instruction
2274297eecfbSDimitry Andric   // that doesn't use a GPRPair.
2275297eecfbSDimitry Andric   // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2276297eecfbSDimitry Andric   // still parse as a pair.
2277297eecfbSDimitry Andric   if (!IsRV64Inst && isRV64())
2278297eecfbSDimitry Andric     return ParseStatus::NoMatch;
2279297eecfbSDimitry Andric 
2280297eecfbSDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
2281297eecfbSDimitry Andric     return ParseStatus::NoMatch;
2282297eecfbSDimitry Andric 
2283297eecfbSDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
2284297eecfbSDimitry Andric   MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
2285297eecfbSDimitry Andric 
2286297eecfbSDimitry Andric   if (!RegNo)
2287297eecfbSDimitry Andric     return ParseStatus::NoMatch;
2288297eecfbSDimitry Andric 
2289297eecfbSDimitry Andric   if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(RegNo))
2290297eecfbSDimitry Andric     return ParseStatus::NoMatch;
2291297eecfbSDimitry Andric 
2292297eecfbSDimitry Andric   if ((RegNo - RISCV::X0) & 1)
2293297eecfbSDimitry Andric     return TokError("register must be even");
2294297eecfbSDimitry Andric 
2295297eecfbSDimitry Andric   SMLoc S = getLoc();
2296297eecfbSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2297297eecfbSDimitry Andric   getLexer().Lex();
2298297eecfbSDimitry Andric 
2299297eecfbSDimitry Andric   const MCRegisterInfo *RI = getContext().getRegisterInfo();
2300297eecfbSDimitry Andric   unsigned Pair = RI->getMatchingSuperReg(
2301297eecfbSDimitry Andric       RegNo, RISCV::sub_gpr_even,
2302297eecfbSDimitry Andric       &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2303297eecfbSDimitry Andric   Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2304297eecfbSDimitry Andric   return ParseStatus::Success;
2305297eecfbSDimitry Andric }
2306297eecfbSDimitry Andric 
parseFRMArg(OperandVector & Operands)230706c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
230806c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
230906c3fb27SDimitry Andric     return TokError(
231006c3fb27SDimitry Andric         "operand must be a valid floating point rounding mode mnemonic");
231106c3fb27SDimitry Andric 
231206c3fb27SDimitry Andric   StringRef Str = getLexer().getTok().getIdentifier();
231306c3fb27SDimitry Andric   RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str);
231406c3fb27SDimitry Andric 
231506c3fb27SDimitry Andric   if (FRM == RISCVFPRndMode::Invalid)
231606c3fb27SDimitry Andric     return TokError(
231706c3fb27SDimitry Andric         "operand must be a valid floating point rounding mode mnemonic");
231806c3fb27SDimitry Andric 
231906c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
232006c3fb27SDimitry Andric   Lex(); // Eat identifier token.
232106c3fb27SDimitry Andric   return ParseStatus::Success;
23220b57cec5SDimitry Andric }
23230b57cec5SDimitry Andric 
parseFenceArg(OperandVector & Operands)232406c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
232506c3fb27SDimitry Andric   const AsmToken &Tok = getLexer().getTok();
23260b57cec5SDimitry Andric 
232706c3fb27SDimitry Andric   if (Tok.is(AsmToken::Integer)) {
232806c3fb27SDimitry Andric     if (Tok.getIntVal() != 0)
232906c3fb27SDimitry Andric       goto ParseFail;
233006c3fb27SDimitry Andric 
233106c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
233206c3fb27SDimitry Andric     Lex();
233306c3fb27SDimitry Andric     return ParseStatus::Success;
23340b57cec5SDimitry Andric   }
23350b57cec5SDimitry Andric 
233606c3fb27SDimitry Andric   if (Tok.is(AsmToken::Identifier)) {
233706c3fb27SDimitry Andric     StringRef Str = Tok.getIdentifier();
233806c3fb27SDimitry Andric 
233906c3fb27SDimitry Andric     // Letters must be unique, taken from 'iorw', and in ascending order. This
234006c3fb27SDimitry Andric     // holds as long as each individual character is one of 'iorw' and is
234106c3fb27SDimitry Andric     // greater than the previous character.
234206c3fb27SDimitry Andric     unsigned Imm = 0;
234306c3fb27SDimitry Andric     bool Valid = true;
234406c3fb27SDimitry Andric     char Prev = '\0';
234506c3fb27SDimitry Andric     for (char c : Str) {
234606c3fb27SDimitry Andric       switch (c) {
234706c3fb27SDimitry Andric       default:
234806c3fb27SDimitry Andric         Valid = false;
234906c3fb27SDimitry Andric         break;
235006c3fb27SDimitry Andric       case 'i':
235106c3fb27SDimitry Andric         Imm |= RISCVFenceField::I;
235206c3fb27SDimitry Andric         break;
235306c3fb27SDimitry Andric       case 'o':
235406c3fb27SDimitry Andric         Imm |= RISCVFenceField::O;
235506c3fb27SDimitry Andric         break;
235606c3fb27SDimitry Andric       case 'r':
235706c3fb27SDimitry Andric         Imm |= RISCVFenceField::R;
235806c3fb27SDimitry Andric         break;
235906c3fb27SDimitry Andric       case 'w':
236006c3fb27SDimitry Andric         Imm |= RISCVFenceField::W;
236106c3fb27SDimitry Andric         break;
23620b57cec5SDimitry Andric       }
23630b57cec5SDimitry Andric 
236406c3fb27SDimitry Andric       if (c <= Prev) {
236506c3fb27SDimitry Andric         Valid = false;
236606c3fb27SDimitry Andric         break;
236706c3fb27SDimitry Andric       }
236806c3fb27SDimitry Andric       Prev = c;
23690b57cec5SDimitry Andric     }
23700b57cec5SDimitry Andric 
237106c3fb27SDimitry Andric     if (!Valid)
237206c3fb27SDimitry Andric       goto ParseFail;
237306c3fb27SDimitry Andric 
237406c3fb27SDimitry Andric     Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
237506c3fb27SDimitry Andric     Lex();
237606c3fb27SDimitry Andric     return ParseStatus::Success;
237706c3fb27SDimitry Andric   }
237806c3fb27SDimitry Andric 
237906c3fb27SDimitry Andric ParseFail:
238006c3fb27SDimitry Andric   return TokError("operand must be formed of letters selected in-order from "
238106c3fb27SDimitry Andric                   "'iorw' or be 0");
238206c3fb27SDimitry Andric }
238306c3fb27SDimitry Andric 
parseMemOpBaseReg(OperandVector & Operands)238406c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
238506c3fb27SDimitry Andric   if (parseToken(AsmToken::LParen, "expected '('"))
238606c3fb27SDimitry Andric     return ParseStatus::Failure;
238706c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createToken("(", getLoc()));
238806c3fb27SDimitry Andric 
238906c3fb27SDimitry Andric   if (!parseRegister(Operands).isSuccess())
239006c3fb27SDimitry Andric     return Error(getLoc(), "expected register");
239106c3fb27SDimitry Andric 
239206c3fb27SDimitry Andric   if (parseToken(AsmToken::RParen, "expected ')'"))
239306c3fb27SDimitry Andric     return ParseStatus::Failure;
239406c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createToken(")", getLoc()));
239506c3fb27SDimitry Andric 
239606c3fb27SDimitry Andric   return ParseStatus::Success;
239706c3fb27SDimitry Andric }
239806c3fb27SDimitry Andric 
parseZeroOffsetMemOp(OperandVector & Operands)239906c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
24000b57cec5SDimitry Andric   // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
24010b57cec5SDimitry Andric   // as one of their register operands, such as `(a0)`. This just denotes that
24020b57cec5SDimitry Andric   // the register (in this case `a0`) contains a memory address.
24030b57cec5SDimitry Andric   //
24040b57cec5SDimitry Andric   // Normally, we would be able to parse these by putting the parens into the
24050b57cec5SDimitry Andric   // instruction string. However, GNU as also accepts a zero-offset memory
24060b57cec5SDimitry Andric   // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
24070b57cec5SDimitry Andric   // with parseImmediate followed by parseMemOpBaseReg, but these instructions
24080b57cec5SDimitry Andric   // do not accept an immediate operand, and we do not want to add a "dummy"
24090b57cec5SDimitry Andric   // operand that is silently dropped.
24100b57cec5SDimitry Andric   //
24110b57cec5SDimitry Andric   // Instead, we use this custom parser. This will: allow (and discard) an
24120b57cec5SDimitry Andric   // offset if it is zero; require (and discard) parentheses; and add only the
24130b57cec5SDimitry Andric   // parsed register operand to `Operands`.
24140b57cec5SDimitry Andric   //
241581ad6265SDimitry Andric   // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
241681ad6265SDimitry Andric   // which will only print the register surrounded by parentheses (which GNU as
241781ad6265SDimitry Andric   // also uses as its canonical representation for these operands).
24180b57cec5SDimitry Andric   std::unique_ptr<RISCVOperand> OptionalImmOp;
24190b57cec5SDimitry Andric 
24200b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::LParen)) {
24210b57cec5SDimitry Andric     // Parse an Integer token. We do not accept arbritrary constant expressions
24220b57cec5SDimitry Andric     // in the offset field (because they may include parens, which complicates
24230b57cec5SDimitry Andric     // parsing a lot).
24240b57cec5SDimitry Andric     int64_t ImmVal;
24250b57cec5SDimitry Andric     SMLoc ImmStart = getLoc();
24260b57cec5SDimitry Andric     if (getParser().parseIntToken(ImmVal,
24270b57cec5SDimitry Andric                                   "expected '(' or optional integer offset"))
242806c3fb27SDimitry Andric       return ParseStatus::Failure;
24290b57cec5SDimitry Andric 
24300b57cec5SDimitry Andric     // Create a RISCVOperand for checking later (so the error messages are
24310b57cec5SDimitry Andric     // nicer), but we don't add it to Operands.
24320b57cec5SDimitry Andric     SMLoc ImmEnd = getLoc();
24330b57cec5SDimitry Andric     OptionalImmOp =
24340b57cec5SDimitry Andric         RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
24350b57cec5SDimitry Andric                                 ImmStart, ImmEnd, isRV64());
24360b57cec5SDimitry Andric   }
24370b57cec5SDimitry Andric 
243806c3fb27SDimitry Andric   if (parseToken(AsmToken::LParen,
243906c3fb27SDimitry Andric                  OptionalImmOp ? "expected '(' after optional integer offset"
244006c3fb27SDimitry Andric                                : "expected '(' or optional integer offset"))
244106c3fb27SDimitry Andric     return ParseStatus::Failure;
24420b57cec5SDimitry Andric 
244306c3fb27SDimitry Andric   if (!parseRegister(Operands).isSuccess())
244406c3fb27SDimitry Andric     return Error(getLoc(), "expected register");
24450b57cec5SDimitry Andric 
244606c3fb27SDimitry Andric   if (parseToken(AsmToken::RParen, "expected ')'"))
244706c3fb27SDimitry Andric     return ParseStatus::Failure;
24480b57cec5SDimitry Andric 
24490b57cec5SDimitry Andric   // Deferred Handling of non-zero offsets. This makes the error messages nicer.
245006c3fb27SDimitry Andric   if (OptionalImmOp && !OptionalImmOp->isImmZero())
245106c3fb27SDimitry Andric     return Error(
245206c3fb27SDimitry Andric         OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
24530b57cec5SDimitry Andric         SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
245406c3fb27SDimitry Andric 
245506c3fb27SDimitry Andric   return ParseStatus::Success;
24560b57cec5SDimitry Andric }
24570b57cec5SDimitry Andric 
parseRegReg(OperandVector & Operands)24585f757f3fSDimitry Andric ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
24595f757f3fSDimitry Andric   // RR : a2(a1)
24605f757f3fSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
24615f757f3fSDimitry Andric     return ParseStatus::NoMatch;
24625f757f3fSDimitry Andric 
24635f757f3fSDimitry Andric   StringRef RegName = getLexer().getTok().getIdentifier();
24645f757f3fSDimitry Andric   MCRegister Reg = matchRegisterNameHelper(isRVE(), RegName);
24655f757f3fSDimitry Andric   if (!Reg)
24665f757f3fSDimitry Andric     return Error(getLoc(), "invalid register");
24675f757f3fSDimitry Andric   getLexer().Lex();
24685f757f3fSDimitry Andric 
24695f757f3fSDimitry Andric   if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
24705f757f3fSDimitry Andric     return ParseStatus::Failure;
24715f757f3fSDimitry Andric 
24725f757f3fSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
24735f757f3fSDimitry Andric     return Error(getLoc(), "expected register");
24745f757f3fSDimitry Andric 
24755f757f3fSDimitry Andric   StringRef Reg2Name = getLexer().getTok().getIdentifier();
24765f757f3fSDimitry Andric   MCRegister Reg2 = matchRegisterNameHelper(isRVE(), Reg2Name);
24775f757f3fSDimitry Andric   if (!Reg2)
24785f757f3fSDimitry Andric     return Error(getLoc(), "invalid register");
24795f757f3fSDimitry Andric   getLexer().Lex();
24805f757f3fSDimitry Andric 
24815f757f3fSDimitry Andric   if (parseToken(AsmToken::RParen, "expected ')'"))
24825f757f3fSDimitry Andric     return ParseStatus::Failure;
24835f757f3fSDimitry Andric 
24845f757f3fSDimitry Andric   Operands.push_back(RISCVOperand::createRegReg(Reg, Reg2, getLoc()));
24855f757f3fSDimitry Andric 
24865f757f3fSDimitry Andric   return ParseStatus::Success;
24875f757f3fSDimitry Andric }
24885f757f3fSDimitry Andric 
parseReglist(OperandVector & Operands)248906c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
249006c3fb27SDimitry Andric   // Rlist: {ra [, s0[-sN]]}
249106c3fb27SDimitry Andric   // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
249206c3fb27SDimitry Andric   SMLoc S = getLoc();
249306c3fb27SDimitry Andric 
249406c3fb27SDimitry Andric   if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
249506c3fb27SDimitry Andric     return ParseStatus::Failure;
249606c3fb27SDimitry Andric 
249706c3fb27SDimitry Andric   bool IsEABI = isRVE();
249806c3fb27SDimitry Andric 
249906c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier))
250006c3fb27SDimitry Andric     return Error(getLoc(), "register list must start from 'ra' or 'x1'");
250106c3fb27SDimitry Andric 
250206c3fb27SDimitry Andric   StringRef RegName = getLexer().getTok().getIdentifier();
250306c3fb27SDimitry Andric   MCRegister RegStart = matchRegisterNameHelper(IsEABI, RegName);
250406c3fb27SDimitry Andric   MCRegister RegEnd;
250506c3fb27SDimitry Andric   if (RegStart != RISCV::X1)
250606c3fb27SDimitry Andric     return Error(getLoc(), "register list must start from 'ra' or 'x1'");
250706c3fb27SDimitry Andric   getLexer().Lex();
250806c3fb27SDimitry Andric 
250906c3fb27SDimitry Andric   // parse case like ,s0
251006c3fb27SDimitry Andric   if (parseOptionalToken(AsmToken::Comma)) {
251106c3fb27SDimitry Andric     if (getLexer().isNot(AsmToken::Identifier))
251206c3fb27SDimitry Andric       return Error(getLoc(), "invalid register");
251306c3fb27SDimitry Andric     StringRef RegName = getLexer().getTok().getIdentifier();
251406c3fb27SDimitry Andric     RegStart = matchRegisterNameHelper(IsEABI, RegName);
251506c3fb27SDimitry Andric     if (!RegStart)
251606c3fb27SDimitry Andric       return Error(getLoc(), "invalid register");
251706c3fb27SDimitry Andric     if (RegStart != RISCV::X8)
251806c3fb27SDimitry Andric       return Error(getLoc(),
251906c3fb27SDimitry Andric                    "continuous register list must start from 's0' or 'x8'");
252006c3fb27SDimitry Andric     getLexer().Lex(); // eat reg
252106c3fb27SDimitry Andric   }
252206c3fb27SDimitry Andric 
252306c3fb27SDimitry Andric   // parse case like -s1
252406c3fb27SDimitry Andric   if (parseOptionalToken(AsmToken::Minus)) {
252506c3fb27SDimitry Andric     StringRef EndName = getLexer().getTok().getIdentifier();
252606c3fb27SDimitry Andric     // FIXME: the register mapping and checks of EABI is wrong
252706c3fb27SDimitry Andric     RegEnd = matchRegisterNameHelper(IsEABI, EndName);
252806c3fb27SDimitry Andric     if (!RegEnd)
252906c3fb27SDimitry Andric       return Error(getLoc(), "invalid register");
253006c3fb27SDimitry Andric     if (IsEABI && RegEnd != RISCV::X9)
253106c3fb27SDimitry Andric       return Error(getLoc(), "contiguous register list of EABI can only be "
253206c3fb27SDimitry Andric                              "'s0-s1' or 'x8-x9' pair");
253306c3fb27SDimitry Andric     getLexer().Lex();
253406c3fb27SDimitry Andric   }
253506c3fb27SDimitry Andric 
253606c3fb27SDimitry Andric   if (!IsEABI) {
253706c3fb27SDimitry Andric     // parse extra part like ', x18[-x20]' for XRegList
253806c3fb27SDimitry Andric     if (parseOptionalToken(AsmToken::Comma)) {
253906c3fb27SDimitry Andric       if (RegEnd != RISCV::X9)
254006c3fb27SDimitry Andric         return Error(
254106c3fb27SDimitry Andric             getLoc(),
254206c3fb27SDimitry Andric             "first contiguous registers pair of register list must be 'x8-x9'");
254306c3fb27SDimitry Andric 
254406c3fb27SDimitry Andric       // parse ', x18' for extra part
254506c3fb27SDimitry Andric       if (getLexer().isNot(AsmToken::Identifier))
254606c3fb27SDimitry Andric         return Error(getLoc(), "invalid register");
254706c3fb27SDimitry Andric       StringRef EndName = getLexer().getTok().getIdentifier();
254806c3fb27SDimitry Andric       if (MatchRegisterName(EndName) != RISCV::X18)
254906c3fb27SDimitry Andric         return Error(getLoc(),
255006c3fb27SDimitry Andric                      "second contiguous registers pair of register list "
255106c3fb27SDimitry Andric                      "must start from 'x18'");
255206c3fb27SDimitry Andric       getLexer().Lex();
255306c3fb27SDimitry Andric 
255406c3fb27SDimitry Andric       // parse '-x20' for extra part
255506c3fb27SDimitry Andric       if (parseOptionalToken(AsmToken::Minus)) {
255606c3fb27SDimitry Andric         if (getLexer().isNot(AsmToken::Identifier))
255706c3fb27SDimitry Andric           return Error(getLoc(), "invalid register");
255806c3fb27SDimitry Andric         EndName = getLexer().getTok().getIdentifier();
255906c3fb27SDimitry Andric         if (MatchRegisterName(EndName) == RISCV::NoRegister)
256006c3fb27SDimitry Andric           return Error(getLoc(), "invalid register");
256106c3fb27SDimitry Andric         getLexer().Lex();
256206c3fb27SDimitry Andric       }
256306c3fb27SDimitry Andric       RegEnd = MatchRegisterName(EndName);
256406c3fb27SDimitry Andric     }
256506c3fb27SDimitry Andric   }
256606c3fb27SDimitry Andric 
256706c3fb27SDimitry Andric   if (RegEnd == RISCV::X26)
256806c3fb27SDimitry Andric     return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
256906c3fb27SDimitry Andric                            "x18-x26} is not supported");
257006c3fb27SDimitry Andric 
257106c3fb27SDimitry Andric   if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
257206c3fb27SDimitry Andric     return ParseStatus::Failure;
257306c3fb27SDimitry Andric 
257406c3fb27SDimitry Andric   if (RegEnd == RISCV::NoRegister)
257506c3fb27SDimitry Andric     RegEnd = RegStart;
257606c3fb27SDimitry Andric 
257706c3fb27SDimitry Andric   auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
257806c3fb27SDimitry Andric   if (Encode == 16)
257906c3fb27SDimitry Andric     return Error(S, "invalid register list");
258006c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createRlist(Encode, S));
258106c3fb27SDimitry Andric 
258206c3fb27SDimitry Andric   return ParseStatus::Success;
258306c3fb27SDimitry Andric }
258406c3fb27SDimitry Andric 
parseZcmpSpimm(OperandVector & Operands)258506c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseZcmpSpimm(OperandVector &Operands) {
258606c3fb27SDimitry Andric   (void)parseOptionalToken(AsmToken::Minus);
258706c3fb27SDimitry Andric 
258806c3fb27SDimitry Andric   SMLoc S = getLoc();
258906c3fb27SDimitry Andric   int64_t StackAdjustment = getLexer().getTok().getIntVal();
259006c3fb27SDimitry Andric   unsigned Spimm = 0;
259106c3fb27SDimitry Andric   unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
259206c3fb27SDimitry Andric 
259306c3fb27SDimitry Andric   bool IsEABI = isRVE();
259406c3fb27SDimitry Andric   if (!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64(), IsEABI))
259506c3fb27SDimitry Andric     return ParseStatus::NoMatch;
259606c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
259706c3fb27SDimitry Andric   getLexer().Lex();
259806c3fb27SDimitry Andric   return ParseStatus::Success;
25990b57cec5SDimitry Andric }
26000b57cec5SDimitry Andric 
26010b57cec5SDimitry Andric /// Looks at a token type and creates the relevant operand from this
26020b57cec5SDimitry Andric /// information, adding to Operands. If operand was parsed, returns false, else
26030b57cec5SDimitry Andric /// true.
parseOperand(OperandVector & Operands,StringRef Mnemonic)26040b57cec5SDimitry Andric bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
26050b57cec5SDimitry Andric   // Check if the current operand has a custom associated parser, if so, try to
26060b57cec5SDimitry Andric   // custom parse the operand, or fallback to the general approach.
260706c3fb27SDimitry Andric   ParseStatus Result =
26080b57cec5SDimitry Andric       MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
260906c3fb27SDimitry Andric   if (Result.isSuccess())
26100b57cec5SDimitry Andric     return false;
261106c3fb27SDimitry Andric   if (Result.isFailure())
26120b57cec5SDimitry Andric     return true;
26130b57cec5SDimitry Andric 
26140b57cec5SDimitry Andric   // Attempt to parse token as a register.
261506c3fb27SDimitry Andric   if (parseRegister(Operands, true).isSuccess())
26160b57cec5SDimitry Andric     return false;
26170b57cec5SDimitry Andric 
26180b57cec5SDimitry Andric   // Attempt to parse token as an immediate
261906c3fb27SDimitry Andric   if (parseImmediate(Operands).isSuccess()) {
26200b57cec5SDimitry Andric     // Parse memory base register if present
26210b57cec5SDimitry Andric     if (getLexer().is(AsmToken::LParen))
262206c3fb27SDimitry Andric       return !parseMemOpBaseReg(Operands).isSuccess();
26230b57cec5SDimitry Andric     return false;
26240b57cec5SDimitry Andric   }
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric   // Finally we have exhausted all options and must declare defeat.
26270b57cec5SDimitry Andric   Error(getLoc(), "unknown operand");
26280b57cec5SDimitry Andric   return true;
26290b57cec5SDimitry Andric }
26300b57cec5SDimitry Andric 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)26310b57cec5SDimitry Andric bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
26320b57cec5SDimitry Andric                                       StringRef Name, SMLoc NameLoc,
26330b57cec5SDimitry Andric                                       OperandVector &Operands) {
26340b57cec5SDimitry Andric   // Ensure that if the instruction occurs when relaxation is enabled,
26350b57cec5SDimitry Andric   // relocations are forced for the file. Ideally this would be done when there
26360b57cec5SDimitry Andric   // is enough information to reliably determine if the instruction itself may
26370b57cec5SDimitry Andric   // cause relaxations. Unfortunately instruction processing stage occurs in the
26380b57cec5SDimitry Andric   // same pass as relocation emission, so it's too late to set a 'sticky bit'
26390b57cec5SDimitry Andric   // for the entire file.
264006c3fb27SDimitry Andric   if (getSTI().hasFeature(RISCV::FeatureRelax)) {
26410b57cec5SDimitry Andric     auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
26420b57cec5SDimitry Andric     if (Assembler != nullptr) {
26430b57cec5SDimitry Andric       RISCVAsmBackend &MAB =
26440b57cec5SDimitry Andric           static_cast<RISCVAsmBackend &>(Assembler->getBackend());
26450b57cec5SDimitry Andric       MAB.setForceRelocs();
26460b57cec5SDimitry Andric     }
26470b57cec5SDimitry Andric   }
26480b57cec5SDimitry Andric 
26490b57cec5SDimitry Andric   // First operand is token for instruction
265006c3fb27SDimitry Andric   Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
26510b57cec5SDimitry Andric 
26520b57cec5SDimitry Andric   // If there are no more operands, then finish
265304eeddc0SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement)) {
265404eeddc0SDimitry Andric     getParser().Lex(); // Consume the EndOfStatement.
26550b57cec5SDimitry Andric     return false;
265604eeddc0SDimitry Andric   }
26570b57cec5SDimitry Andric 
26580b57cec5SDimitry Andric   // Parse first operand
26590b57cec5SDimitry Andric   if (parseOperand(Operands, Name))
26600b57cec5SDimitry Andric     return true;
26610b57cec5SDimitry Andric 
26620b57cec5SDimitry Andric   // Parse until end of statement, consuming commas between operands
266306c3fb27SDimitry Andric   while (parseOptionalToken(AsmToken::Comma)) {
26640b57cec5SDimitry Andric     // Parse next operand
26650b57cec5SDimitry Andric     if (parseOperand(Operands, Name))
26660b57cec5SDimitry Andric       return true;
26670b57cec5SDimitry Andric   }
26680b57cec5SDimitry Andric 
266906c3fb27SDimitry Andric   if (getParser().parseEOL("unexpected token")) {
26700b57cec5SDimitry Andric     getParser().eatToEndOfStatement();
267106c3fb27SDimitry Andric     return true;
26720b57cec5SDimitry Andric   }
26730b57cec5SDimitry Andric   return false;
26740b57cec5SDimitry Andric }
26750b57cec5SDimitry Andric 
classifySymbolRef(const MCExpr * Expr,RISCVMCExpr::VariantKind & Kind)26760b57cec5SDimitry Andric bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
2677e8d8bef9SDimitry Andric                                        RISCVMCExpr::VariantKind &Kind) {
26780b57cec5SDimitry Andric   Kind = RISCVMCExpr::VK_RISCV_None;
26790b57cec5SDimitry Andric 
26800b57cec5SDimitry Andric   if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
26810b57cec5SDimitry Andric     Kind = RE->getKind();
26820b57cec5SDimitry Andric     Expr = RE->getSubExpr();
26830b57cec5SDimitry Andric   }
26840b57cec5SDimitry Andric 
2685e8d8bef9SDimitry Andric   MCValue Res;
2686e8d8bef9SDimitry Andric   MCFixup Fixup;
2687e8d8bef9SDimitry Andric   if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
2688e8d8bef9SDimitry Andric     return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
26890b57cec5SDimitry Andric   return false;
26900b57cec5SDimitry Andric }
26910b57cec5SDimitry Andric 
isSymbolDiff(const MCExpr * Expr)269206c3fb27SDimitry Andric bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
269306c3fb27SDimitry Andric   MCValue Res;
269406c3fb27SDimitry Andric   MCFixup Fixup;
269506c3fb27SDimitry Andric   if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) {
269606c3fb27SDimitry Andric     return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() &&
269706c3fb27SDimitry Andric            Res.getSymB();
269806c3fb27SDimitry Andric   }
269906c3fb27SDimitry Andric   return false;
270006c3fb27SDimitry Andric }
270106c3fb27SDimitry Andric 
parseDirective(AsmToken DirectiveID)270206c3fb27SDimitry Andric ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
27030b57cec5SDimitry Andric   StringRef IDVal = DirectiveID.getString();
27040b57cec5SDimitry Andric 
27050b57cec5SDimitry Andric   if (IDVal == ".option")
27060b57cec5SDimitry Andric     return parseDirectiveOption();
2707349cc55cSDimitry Andric   if (IDVal == ".attribute")
27085ffd83dbSDimitry Andric     return parseDirectiveAttribute();
2709349cc55cSDimitry Andric   if (IDVal == ".insn")
2710349cc55cSDimitry Andric     return parseDirectiveInsn(DirectiveID.getLoc());
2711bdd1243dSDimitry Andric   if (IDVal == ".variant_cc")
2712bdd1243dSDimitry Andric     return parseDirectiveVariantCC();
27130b57cec5SDimitry Andric 
271406c3fb27SDimitry Andric   return ParseStatus::NoMatch;
271506c3fb27SDimitry Andric }
271606c3fb27SDimitry Andric 
resetToArch(StringRef Arch,SMLoc Loc,std::string & Result,bool FromOptionDirective)271706c3fb27SDimitry Andric bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
271806c3fb27SDimitry Andric                                  bool FromOptionDirective) {
271906c3fb27SDimitry Andric   for (auto Feature : RISCVFeatureKV)
272006c3fb27SDimitry Andric     if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
272106c3fb27SDimitry Andric       clearFeatureBits(Feature.Value, Feature.Key);
272206c3fb27SDimitry Andric 
272306c3fb27SDimitry Andric   auto ParseResult = llvm::RISCVISAInfo::parseArchString(
272406c3fb27SDimitry Andric       Arch, /*EnableExperimentalExtension=*/true,
272506c3fb27SDimitry Andric       /*ExperimentalExtensionVersionCheck=*/true);
272606c3fb27SDimitry Andric   if (!ParseResult) {
272706c3fb27SDimitry Andric     std::string Buffer;
272806c3fb27SDimitry Andric     raw_string_ostream OutputErrMsg(Buffer);
272906c3fb27SDimitry Andric     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
273006c3fb27SDimitry Andric       OutputErrMsg << "invalid arch name '" << Arch << "', "
273106c3fb27SDimitry Andric                    << ErrMsg.getMessage();
273206c3fb27SDimitry Andric     });
273306c3fb27SDimitry Andric 
273406c3fb27SDimitry Andric     return Error(Loc, OutputErrMsg.str());
273506c3fb27SDimitry Andric   }
273606c3fb27SDimitry Andric   auto &ISAInfo = *ParseResult;
273706c3fb27SDimitry Andric 
273806c3fb27SDimitry Andric   for (auto Feature : RISCVFeatureKV)
273906c3fb27SDimitry Andric     if (ISAInfo->hasExtension(Feature.Key))
274006c3fb27SDimitry Andric       setFeatureBits(Feature.Value, Feature.Key);
274106c3fb27SDimitry Andric 
274206c3fb27SDimitry Andric   if (FromOptionDirective) {
274306c3fb27SDimitry Andric     if (ISAInfo->getXLen() == 32 && isRV64())
274406c3fb27SDimitry Andric       return Error(Loc, "bad arch string switching from rv64 to rv32");
274506c3fb27SDimitry Andric     else if (ISAInfo->getXLen() == 64 && !isRV64())
274606c3fb27SDimitry Andric       return Error(Loc, "bad arch string switching from rv32 to rv64");
274706c3fb27SDimitry Andric   }
274806c3fb27SDimitry Andric 
274906c3fb27SDimitry Andric   if (ISAInfo->getXLen() == 32)
275006c3fb27SDimitry Andric     clearFeatureBits(RISCV::Feature64Bit, "64bit");
275106c3fb27SDimitry Andric   else if (ISAInfo->getXLen() == 64)
275206c3fb27SDimitry Andric     setFeatureBits(RISCV::Feature64Bit, "64bit");
275306c3fb27SDimitry Andric   else
275406c3fb27SDimitry Andric     return Error(Loc, "bad arch string " + Arch);
275506c3fb27SDimitry Andric 
275606c3fb27SDimitry Andric   Result = ISAInfo->toString();
275706c3fb27SDimitry Andric   return false;
27580b57cec5SDimitry Andric }
27590b57cec5SDimitry Andric 
parseDirectiveOption()27600b57cec5SDimitry Andric bool RISCVAsmParser::parseDirectiveOption() {
27610b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
27620b57cec5SDimitry Andric   // Get the option token.
27630b57cec5SDimitry Andric   AsmToken Tok = Parser.getTok();
276406c3fb27SDimitry Andric 
27650b57cec5SDimitry Andric   // At the moment only identifiers are supported.
276606c3fb27SDimitry Andric   if (parseToken(AsmToken::Identifier, "expected identifier"))
276706c3fb27SDimitry Andric     return true;
27680b57cec5SDimitry Andric 
27690b57cec5SDimitry Andric   StringRef Option = Tok.getIdentifier();
27700b57cec5SDimitry Andric 
27710b57cec5SDimitry Andric   if (Option == "push") {
277206c3fb27SDimitry Andric     if (Parser.parseEOL())
277306c3fb27SDimitry Andric       return true;
277406c3fb27SDimitry Andric 
27750b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionPush();
27760b57cec5SDimitry Andric     pushFeatureBits();
27770b57cec5SDimitry Andric     return false;
27780b57cec5SDimitry Andric   }
27790b57cec5SDimitry Andric 
27800b57cec5SDimitry Andric   if (Option == "pop") {
27810b57cec5SDimitry Andric     SMLoc StartLoc = Parser.getTok().getLoc();
278206c3fb27SDimitry Andric     if (Parser.parseEOL())
278306c3fb27SDimitry Andric       return true;
278406c3fb27SDimitry Andric 
27850b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionPop();
27860b57cec5SDimitry Andric     if (popFeatureBits())
27870b57cec5SDimitry Andric       return Error(StartLoc, ".option pop with no .option push");
27880b57cec5SDimitry Andric 
27890b57cec5SDimitry Andric     return false;
27900b57cec5SDimitry Andric   }
27910b57cec5SDimitry Andric 
279206c3fb27SDimitry Andric   if (Option == "arch") {
279306c3fb27SDimitry Andric     SmallVector<RISCVOptionArchArg> Args;
279406c3fb27SDimitry Andric     do {
279506c3fb27SDimitry Andric       if (Parser.parseComma())
279606c3fb27SDimitry Andric         return true;
27970b57cec5SDimitry Andric 
279806c3fb27SDimitry Andric       RISCVOptionArchArgType Type;
279906c3fb27SDimitry Andric       if (parseOptionalToken(AsmToken::Plus))
280006c3fb27SDimitry Andric         Type = RISCVOptionArchArgType::Plus;
280106c3fb27SDimitry Andric       else if (parseOptionalToken(AsmToken::Minus))
280206c3fb27SDimitry Andric         Type = RISCVOptionArchArgType::Minus;
280306c3fb27SDimitry Andric       else if (!Args.empty())
28040b57cec5SDimitry Andric         return Error(Parser.getTok().getLoc(),
280506c3fb27SDimitry Andric                      "unexpected token, expected + or -");
280606c3fb27SDimitry Andric       else
280706c3fb27SDimitry Andric         Type = RISCVOptionArchArgType::Full;
28080b57cec5SDimitry Andric 
280906c3fb27SDimitry Andric       if (Parser.getTok().isNot(AsmToken::Identifier))
281006c3fb27SDimitry Andric         return Error(Parser.getTok().getLoc(),
281106c3fb27SDimitry Andric                      "unexpected token, expected identifier");
281206c3fb27SDimitry Andric 
281306c3fb27SDimitry Andric       StringRef Arch = Parser.getTok().getString();
281406c3fb27SDimitry Andric       SMLoc Loc = Parser.getTok().getLoc();
281506c3fb27SDimitry Andric       Parser.Lex();
281606c3fb27SDimitry Andric 
281706c3fb27SDimitry Andric       if (Type == RISCVOptionArchArgType::Full) {
281806c3fb27SDimitry Andric         std::string Result;
281906c3fb27SDimitry Andric         if (resetToArch(Arch, Loc, Result, true))
282006c3fb27SDimitry Andric           return true;
282106c3fb27SDimitry Andric 
282206c3fb27SDimitry Andric         Args.emplace_back(Type, Result);
282306c3fb27SDimitry Andric         break;
282406c3fb27SDimitry Andric       }
282506c3fb27SDimitry Andric 
282606c3fb27SDimitry Andric       ArrayRef<SubtargetFeatureKV> KVArray(RISCVFeatureKV);
282706c3fb27SDimitry Andric       auto Ext = llvm::lower_bound(KVArray, Arch);
282806c3fb27SDimitry Andric       if (Ext == KVArray.end() || StringRef(Ext->Key) != Arch ||
282906c3fb27SDimitry Andric           !RISCVISAInfo::isSupportedExtension(Arch)) {
283006c3fb27SDimitry Andric         if (isDigit(Arch.back()))
283106c3fb27SDimitry Andric           return Error(
283206c3fb27SDimitry Andric               Loc,
283306c3fb27SDimitry Andric               "Extension version number parsing not currently implemented");
283406c3fb27SDimitry Andric         return Error(Loc, "unknown extension feature");
283506c3fb27SDimitry Andric       }
283606c3fb27SDimitry Andric 
283706c3fb27SDimitry Andric       Args.emplace_back(Type, Ext->Key);
283806c3fb27SDimitry Andric 
283906c3fb27SDimitry Andric       if (Type == RISCVOptionArchArgType::Plus) {
284006c3fb27SDimitry Andric         FeatureBitset OldFeatureBits = STI->getFeatureBits();
284106c3fb27SDimitry Andric 
284206c3fb27SDimitry Andric         setFeatureBits(Ext->Value, Ext->Key);
284306c3fb27SDimitry Andric         auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits());
284406c3fb27SDimitry Andric         if (!ParseResult) {
284506c3fb27SDimitry Andric           copySTI().setFeatureBits(OldFeatureBits);
284606c3fb27SDimitry Andric           setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
284706c3fb27SDimitry Andric 
284806c3fb27SDimitry Andric           std::string Buffer;
284906c3fb27SDimitry Andric           raw_string_ostream OutputErrMsg(Buffer);
285006c3fb27SDimitry Andric           handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
285106c3fb27SDimitry Andric             OutputErrMsg << ErrMsg.getMessage();
285206c3fb27SDimitry Andric           });
285306c3fb27SDimitry Andric 
285406c3fb27SDimitry Andric           return Error(Loc, OutputErrMsg.str());
285506c3fb27SDimitry Andric         }
285606c3fb27SDimitry Andric       } else {
285706c3fb27SDimitry Andric         assert(Type == RISCVOptionArchArgType::Minus);
285806c3fb27SDimitry Andric         // It is invalid to disable an extension that there are other enabled
285906c3fb27SDimitry Andric         // extensions depend on it.
286006c3fb27SDimitry Andric         // TODO: Make use of RISCVISAInfo to handle this
286106c3fb27SDimitry Andric         for (auto Feature : KVArray) {
286206c3fb27SDimitry Andric           if (getSTI().hasFeature(Feature.Value) &&
286306c3fb27SDimitry Andric               Feature.Implies.test(Ext->Value))
286406c3fb27SDimitry Andric             return Error(Loc,
286506c3fb27SDimitry Andric                          Twine("Can't disable ") + Ext->Key + " extension, " +
286606c3fb27SDimitry Andric                              Feature.Key + " extension requires " + Ext->Key +
286706c3fb27SDimitry Andric                              " extension be enabled");
286806c3fb27SDimitry Andric         }
286906c3fb27SDimitry Andric 
287006c3fb27SDimitry Andric         clearFeatureBits(Ext->Value, Ext->Key);
287106c3fb27SDimitry Andric       }
287206c3fb27SDimitry Andric     } while (Parser.getTok().isNot(AsmToken::EndOfStatement));
287306c3fb27SDimitry Andric 
287406c3fb27SDimitry Andric     if (Parser.parseEOL())
287506c3fb27SDimitry Andric       return true;
287606c3fb27SDimitry Andric 
287706c3fb27SDimitry Andric     getTargetStreamer().emitDirectiveOptionArch(Args);
287806c3fb27SDimitry Andric     return false;
287906c3fb27SDimitry Andric   }
288006c3fb27SDimitry Andric 
288106c3fb27SDimitry Andric   if (Option == "rvc") {
288206c3fb27SDimitry Andric     if (Parser.parseEOL())
288306c3fb27SDimitry Andric       return true;
288406c3fb27SDimitry Andric 
288506c3fb27SDimitry Andric     getTargetStreamer().emitDirectiveOptionRVC();
28860b57cec5SDimitry Andric     setFeatureBits(RISCV::FeatureStdExtC, "c");
28870b57cec5SDimitry Andric     return false;
28880b57cec5SDimitry Andric   }
28890b57cec5SDimitry Andric 
28900b57cec5SDimitry Andric   if (Option == "norvc") {
289106c3fb27SDimitry Andric     if (Parser.parseEOL())
289206c3fb27SDimitry Andric       return true;
289306c3fb27SDimitry Andric 
28940b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionNoRVC();
28950b57cec5SDimitry Andric     clearFeatureBits(RISCV::FeatureStdExtC, "c");
289606c3fb27SDimitry Andric     clearFeatureBits(RISCV::FeatureStdExtZca, "+zca");
28970b57cec5SDimitry Andric     return false;
28980b57cec5SDimitry Andric   }
28990b57cec5SDimitry Andric 
29005ffd83dbSDimitry Andric   if (Option == "pic") {
290106c3fb27SDimitry Andric     if (Parser.parseEOL())
290206c3fb27SDimitry Andric       return true;
290306c3fb27SDimitry Andric 
29045ffd83dbSDimitry Andric     getTargetStreamer().emitDirectiveOptionPIC();
29055ffd83dbSDimitry Andric     ParserOptions.IsPicEnabled = true;
29065ffd83dbSDimitry Andric     return false;
29075ffd83dbSDimitry Andric   }
29085ffd83dbSDimitry Andric 
29095ffd83dbSDimitry Andric   if (Option == "nopic") {
291006c3fb27SDimitry Andric     if (Parser.parseEOL())
291106c3fb27SDimitry Andric       return true;
291206c3fb27SDimitry Andric 
29135ffd83dbSDimitry Andric     getTargetStreamer().emitDirectiveOptionNoPIC();
29145ffd83dbSDimitry Andric     ParserOptions.IsPicEnabled = false;
29155ffd83dbSDimitry Andric     return false;
29165ffd83dbSDimitry Andric   }
29175ffd83dbSDimitry Andric 
29180b57cec5SDimitry Andric   if (Option == "relax") {
291906c3fb27SDimitry Andric     if (Parser.parseEOL())
292006c3fb27SDimitry Andric       return true;
292106c3fb27SDimitry Andric 
29220b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionRelax();
29230b57cec5SDimitry Andric     setFeatureBits(RISCV::FeatureRelax, "relax");
29240b57cec5SDimitry Andric     return false;
29250b57cec5SDimitry Andric   }
29260b57cec5SDimitry Andric 
29270b57cec5SDimitry Andric   if (Option == "norelax") {
292806c3fb27SDimitry Andric     if (Parser.parseEOL())
292906c3fb27SDimitry Andric       return true;
293006c3fb27SDimitry Andric 
29310b57cec5SDimitry Andric     getTargetStreamer().emitDirectiveOptionNoRelax();
29320b57cec5SDimitry Andric     clearFeatureBits(RISCV::FeatureRelax, "relax");
29330b57cec5SDimitry Andric     return false;
29340b57cec5SDimitry Andric   }
29350b57cec5SDimitry Andric 
29360b57cec5SDimitry Andric   // Unknown option.
293706c3fb27SDimitry Andric   Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
293806c3fb27SDimitry Andric                                     "'rvc', 'norvc', 'arch', 'relax' or "
29390b57cec5SDimitry Andric                                     "'norelax'");
29400b57cec5SDimitry Andric   Parser.eatToEndOfStatement();
29410b57cec5SDimitry Andric   return false;
29420b57cec5SDimitry Andric }
29430b57cec5SDimitry Andric 
29445ffd83dbSDimitry Andric /// parseDirectiveAttribute
29455ffd83dbSDimitry Andric ///  ::= .attribute expression ',' ( expression | "string" )
29465ffd83dbSDimitry Andric ///  ::= .attribute identifier ',' ( expression | "string" )
parseDirectiveAttribute()29475ffd83dbSDimitry Andric bool RISCVAsmParser::parseDirectiveAttribute() {
29485ffd83dbSDimitry Andric   MCAsmParser &Parser = getParser();
29495ffd83dbSDimitry Andric   int64_t Tag;
29505ffd83dbSDimitry Andric   SMLoc TagLoc;
29515ffd83dbSDimitry Andric   TagLoc = Parser.getTok().getLoc();
29525ffd83dbSDimitry Andric   if (Parser.getTok().is(AsmToken::Identifier)) {
29535ffd83dbSDimitry Andric     StringRef Name = Parser.getTok().getIdentifier();
2954bdd1243dSDimitry Andric     std::optional<unsigned> Ret =
2955fe6060f1SDimitry Andric         ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags());
295606c3fb27SDimitry Andric     if (!Ret)
295706c3fb27SDimitry Andric       return Error(TagLoc, "attribute name not recognised: " + Name);
295881ad6265SDimitry Andric     Tag = *Ret;
29595ffd83dbSDimitry Andric     Parser.Lex();
29605ffd83dbSDimitry Andric   } else {
29615ffd83dbSDimitry Andric     const MCExpr *AttrExpr;
29625ffd83dbSDimitry Andric 
29635ffd83dbSDimitry Andric     TagLoc = Parser.getTok().getLoc();
29645ffd83dbSDimitry Andric     if (Parser.parseExpression(AttrExpr))
29655ffd83dbSDimitry Andric       return true;
29665ffd83dbSDimitry Andric 
29675ffd83dbSDimitry Andric     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
29685ffd83dbSDimitry Andric     if (check(!CE, TagLoc, "expected numeric constant"))
29695ffd83dbSDimitry Andric       return true;
29705ffd83dbSDimitry Andric 
29715ffd83dbSDimitry Andric     Tag = CE->getValue();
29725ffd83dbSDimitry Andric   }
29735ffd83dbSDimitry Andric 
297406c3fb27SDimitry Andric   if (Parser.parseComma())
29755ffd83dbSDimitry Andric     return true;
29765ffd83dbSDimitry Andric 
29775ffd83dbSDimitry Andric   StringRef StringValue;
29785ffd83dbSDimitry Andric   int64_t IntegerValue = 0;
29795ffd83dbSDimitry Andric   bool IsIntegerValue = true;
29805ffd83dbSDimitry Andric 
29815ffd83dbSDimitry Andric   // RISC-V attributes have a string value if the tag number is odd
29825ffd83dbSDimitry Andric   // and an integer value if the tag number is even.
29835ffd83dbSDimitry Andric   if (Tag % 2)
29845ffd83dbSDimitry Andric     IsIntegerValue = false;
29855ffd83dbSDimitry Andric 
29865ffd83dbSDimitry Andric   SMLoc ValueExprLoc = Parser.getTok().getLoc();
29875ffd83dbSDimitry Andric   if (IsIntegerValue) {
29885ffd83dbSDimitry Andric     const MCExpr *ValueExpr;
29895ffd83dbSDimitry Andric     if (Parser.parseExpression(ValueExpr))
29905ffd83dbSDimitry Andric       return true;
29915ffd83dbSDimitry Andric 
29925ffd83dbSDimitry Andric     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
29935ffd83dbSDimitry Andric     if (!CE)
29945ffd83dbSDimitry Andric       return Error(ValueExprLoc, "expected numeric constant");
29955ffd83dbSDimitry Andric     IntegerValue = CE->getValue();
29965ffd83dbSDimitry Andric   } else {
29975ffd83dbSDimitry Andric     if (Parser.getTok().isNot(AsmToken::String))
29985ffd83dbSDimitry Andric       return Error(Parser.getTok().getLoc(), "expected string constant");
29995ffd83dbSDimitry Andric 
30005ffd83dbSDimitry Andric     StringValue = Parser.getTok().getStringContents();
30015ffd83dbSDimitry Andric     Parser.Lex();
30025ffd83dbSDimitry Andric   }
30035ffd83dbSDimitry Andric 
300481ad6265SDimitry Andric   if (Parser.parseEOL())
30055ffd83dbSDimitry Andric     return true;
30065ffd83dbSDimitry Andric 
30070eae32dcSDimitry Andric   if (IsIntegerValue)
30080eae32dcSDimitry Andric     getTargetStreamer().emitAttribute(Tag, IntegerValue);
30090eae32dcSDimitry Andric   else if (Tag != RISCVAttrs::ARCH)
30100eae32dcSDimitry Andric     getTargetStreamer().emitTextAttribute(Tag, StringValue);
30110eae32dcSDimitry Andric   else {
301206c3fb27SDimitry Andric     std::string Result;
301306c3fb27SDimitry Andric     if (resetToArch(StringValue, ValueExprLoc, Result, false))
301406c3fb27SDimitry Andric       return true;
3015349cc55cSDimitry Andric 
3016349cc55cSDimitry Andric     // Then emit the arch string.
301706c3fb27SDimitry Andric     getTargetStreamer().emitTextAttribute(Tag, Result);
30185ffd83dbSDimitry Andric   }
30195ffd83dbSDimitry Andric 
30205ffd83dbSDimitry Andric   return false;
30215ffd83dbSDimitry Andric }
30225ffd83dbSDimitry Andric 
isValidInsnFormat(StringRef Format,bool AllowC)302306c3fb27SDimitry Andric bool isValidInsnFormat(StringRef Format, bool AllowC) {
302406c3fb27SDimitry Andric   return StringSwitch<bool>(Format)
302506c3fb27SDimitry Andric       .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
302606c3fb27SDimitry Andric       .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)
302706c3fb27SDimitry Andric       .Default(false);
302806c3fb27SDimitry Andric }
302906c3fb27SDimitry Andric 
3030349cc55cSDimitry Andric /// parseDirectiveInsn
3031349cc55cSDimitry Andric /// ::= .insn [ format encoding, (operands (, operands)*) ]
parseDirectiveInsn(SMLoc L)3032349cc55cSDimitry Andric bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3033349cc55cSDimitry Andric   MCAsmParser &Parser = getParser();
3034349cc55cSDimitry Andric 
3035349cc55cSDimitry Andric   // Expect instruction format as identifier.
3036349cc55cSDimitry Andric   StringRef Format;
3037349cc55cSDimitry Andric   SMLoc ErrorLoc = Parser.getTok().getLoc();
3038349cc55cSDimitry Andric   if (Parser.parseIdentifier(Format))
3039349cc55cSDimitry Andric     return Error(ErrorLoc, "expected instruction format");
3040349cc55cSDimitry Andric 
304106c3fb27SDimitry Andric   bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
304206c3fb27SDimitry Andric                 getSTI().hasFeature(RISCV::FeatureStdExtZca);
304306c3fb27SDimitry Andric   if (!isValidInsnFormat(Format, AllowC))
3044349cc55cSDimitry Andric     return Error(ErrorLoc, "invalid instruction format");
3045349cc55cSDimitry Andric 
3046349cc55cSDimitry Andric   std::string FormatName = (".insn_" + Format).str();
3047349cc55cSDimitry Andric 
3048349cc55cSDimitry Andric   ParseInstructionInfo Info;
3049349cc55cSDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
3050349cc55cSDimitry Andric 
3051349cc55cSDimitry Andric   if (ParseInstruction(Info, FormatName, L, Operands))
3052349cc55cSDimitry Andric     return true;
3053349cc55cSDimitry Andric 
3054349cc55cSDimitry Andric   unsigned Opcode;
3055349cc55cSDimitry Andric   uint64_t ErrorInfo;
3056349cc55cSDimitry Andric   return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
3057349cc55cSDimitry Andric                                  ErrorInfo,
3058349cc55cSDimitry Andric                                  /*MatchingInlineAsm=*/false);
3059349cc55cSDimitry Andric }
3060349cc55cSDimitry Andric 
3061bdd1243dSDimitry Andric /// parseDirectiveVariantCC
3062bdd1243dSDimitry Andric ///  ::= .variant_cc symbol
parseDirectiveVariantCC()3063bdd1243dSDimitry Andric bool RISCVAsmParser::parseDirectiveVariantCC() {
3064bdd1243dSDimitry Andric   StringRef Name;
3065bdd1243dSDimitry Andric   if (getParser().parseIdentifier(Name))
3066bdd1243dSDimitry Andric     return TokError("expected symbol name");
3067bdd1243dSDimitry Andric   if (parseEOL())
306806c3fb27SDimitry Andric     return true;
3069bdd1243dSDimitry Andric   getTargetStreamer().emitDirectiveVariantCC(
3070bdd1243dSDimitry Andric       *getContext().getOrCreateSymbol(Name));
3071bdd1243dSDimitry Andric   return false;
3072bdd1243dSDimitry Andric }
3073bdd1243dSDimitry Andric 
emitToStreamer(MCStreamer & S,const MCInst & Inst)30740b57cec5SDimitry Andric void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
30750b57cec5SDimitry Andric   MCInst CInst;
3076bdd1243dSDimitry Andric   bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
3077480093f4SDimitry Andric   if (Res)
3078480093f4SDimitry Andric     ++RISCVNumInstrsCompressed;
30795ffd83dbSDimitry Andric   S.emitInstruction((Res ? CInst : Inst), getSTI());
30800b57cec5SDimitry Andric }
30810b57cec5SDimitry Andric 
emitLoadImm(MCRegister DestReg,int64_t Value,MCStreamer & Out)3082e8d8bef9SDimitry Andric void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
30830b57cec5SDimitry Andric                                  MCStreamer &Out) {
30845f757f3fSDimitry Andric   RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(Value, getSTI());
30850b57cec5SDimitry Andric 
3086e8d8bef9SDimitry Andric   MCRegister SrcReg = RISCV::X0;
308706c3fb27SDimitry Andric   for (const RISCVMatInt::Inst &Inst : Seq) {
308881ad6265SDimitry Andric     switch (Inst.getOpndKind()) {
308981ad6265SDimitry Andric     case RISCVMatInt::Imm:
309081ad6265SDimitry Andric       emitToStreamer(Out,
3091bdd1243dSDimitry Andric                      MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addImm(Inst.getImm()));
309281ad6265SDimitry Andric       break;
309381ad6265SDimitry Andric     case RISCVMatInt::RegX0:
30940b57cec5SDimitry Andric       emitToStreamer(
3095bdd1243dSDimitry Andric           Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg(
309681ad6265SDimitry Andric                    RISCV::X0));
309781ad6265SDimitry Andric       break;
309881ad6265SDimitry Andric     case RISCVMatInt::RegReg:
3099349cc55cSDimitry Andric       emitToStreamer(
3100bdd1243dSDimitry Andric           Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg(
3101349cc55cSDimitry Andric                    SrcReg));
310281ad6265SDimitry Andric       break;
310381ad6265SDimitry Andric     case RISCVMatInt::RegImm:
31040b57cec5SDimitry Andric       emitToStreamer(
3105bdd1243dSDimitry Andric           Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addImm(
3106bdd1243dSDimitry Andric                    Inst.getImm()));
310781ad6265SDimitry Andric       break;
31080b57cec5SDimitry Andric     }
31090b57cec5SDimitry Andric 
31100b57cec5SDimitry Andric     // Only the first instruction has X0 as its source.
31110b57cec5SDimitry Andric     SrcReg = DestReg;
31120b57cec5SDimitry Andric   }
31130b57cec5SDimitry Andric }
31140b57cec5SDimitry Andric 
emitAuipcInstPair(MCOperand DestReg,MCOperand TmpReg,const MCExpr * Symbol,RISCVMCExpr::VariantKind VKHi,unsigned SecondOpcode,SMLoc IDLoc,MCStreamer & Out)31150b57cec5SDimitry Andric void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
31160b57cec5SDimitry Andric                                        const MCExpr *Symbol,
31170b57cec5SDimitry Andric                                        RISCVMCExpr::VariantKind VKHi,
31180b57cec5SDimitry Andric                                        unsigned SecondOpcode, SMLoc IDLoc,
31190b57cec5SDimitry Andric                                        MCStreamer &Out) {
31200b57cec5SDimitry Andric   // A pair of instructions for PC-relative addressing; expands to
31210b57cec5SDimitry Andric   //   TmpLabel: AUIPC TmpReg, VKHi(symbol)
31220b57cec5SDimitry Andric   //             OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
31230b57cec5SDimitry Andric   MCContext &Ctx = getContext();
31240b57cec5SDimitry Andric 
3125e8d8bef9SDimitry Andric   MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
31265ffd83dbSDimitry Andric   Out.emitLabel(TmpLabel);
31270b57cec5SDimitry Andric 
31280b57cec5SDimitry Andric   const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
31290b57cec5SDimitry Andric   emitToStreamer(
31300b57cec5SDimitry Andric       Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
31310b57cec5SDimitry Andric 
31320b57cec5SDimitry Andric   const MCExpr *RefToLinkTmpLabel =
31330b57cec5SDimitry Andric       RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
31340b57cec5SDimitry Andric                           RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
31350b57cec5SDimitry Andric 
31360b57cec5SDimitry Andric   emitToStreamer(Out, MCInstBuilder(SecondOpcode)
31370b57cec5SDimitry Andric                           .addOperand(DestReg)
31380b57cec5SDimitry Andric                           .addOperand(TmpReg)
31390b57cec5SDimitry Andric                           .addExpr(RefToLinkTmpLabel));
31400b57cec5SDimitry Andric }
31410b57cec5SDimitry Andric 
emitLoadLocalAddress(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out)31420b57cec5SDimitry Andric void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
31430b57cec5SDimitry Andric                                           MCStreamer &Out) {
31440b57cec5SDimitry Andric   // The load local address pseudo-instruction "lla" is used in PC-relative
31450b57cec5SDimitry Andric   // addressing of local symbols:
31460b57cec5SDimitry Andric   //   lla rdest, symbol
31470b57cec5SDimitry Andric   // expands to
31480b57cec5SDimitry Andric   //   TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
31490b57cec5SDimitry Andric   //             ADDI rdest, rdest, %pcrel_lo(TmpLabel)
31500b57cec5SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
31510b57cec5SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
31520b57cec5SDimitry Andric   emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
31530b57cec5SDimitry Andric                     RISCV::ADDI, IDLoc, Out);
31540b57cec5SDimitry Andric }
31550b57cec5SDimitry Andric 
emitLoadGlobalAddress(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out)315606c3fb27SDimitry Andric void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
315706c3fb27SDimitry Andric                                            MCStreamer &Out) {
315806c3fb27SDimitry Andric   // The load global address pseudo-instruction "lga" is used in GOT-indirect
315906c3fb27SDimitry Andric   // addressing of global symbols:
316006c3fb27SDimitry Andric   //   lga rdest, symbol
316106c3fb27SDimitry Andric   // expands to
316206c3fb27SDimitry Andric   //   TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
316306c3fb27SDimitry Andric   //             Lx rdest, %pcrel_lo(TmpLabel)(rdest)
316406c3fb27SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
316506c3fb27SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
316606c3fb27SDimitry Andric   unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
316706c3fb27SDimitry Andric   emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,
316806c3fb27SDimitry Andric                     SecondOpcode, IDLoc, Out);
316906c3fb27SDimitry Andric }
317006c3fb27SDimitry Andric 
emitLoadAddress(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out)31710b57cec5SDimitry Andric void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
31720b57cec5SDimitry Andric                                      MCStreamer &Out) {
31730b57cec5SDimitry Andric   // The load address pseudo-instruction "la" is used in PC-relative and
31740b57cec5SDimitry Andric   // GOT-indirect addressing of global symbols:
31750b57cec5SDimitry Andric   //   la rdest, symbol
317606c3fb27SDimitry Andric   // is an alias for either (for non-PIC)
317706c3fb27SDimitry Andric   //   lla rdest, symbol
31780b57cec5SDimitry Andric   // or (for PIC)
317906c3fb27SDimitry Andric   //   lga rdest, symbol
318006c3fb27SDimitry Andric   if (ParserOptions.IsPicEnabled)
318106c3fb27SDimitry Andric     emitLoadGlobalAddress(Inst, IDLoc, Out);
318206c3fb27SDimitry Andric   else
318306c3fb27SDimitry Andric     emitLoadLocalAddress(Inst, IDLoc, Out);
31840b57cec5SDimitry Andric }
31850b57cec5SDimitry Andric 
emitLoadTLSIEAddress(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out)31860b57cec5SDimitry Andric void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
31870b57cec5SDimitry Andric                                           MCStreamer &Out) {
31880b57cec5SDimitry Andric   // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
31890b57cec5SDimitry Andric   // initial-exec TLS model addressing of global symbols:
31900b57cec5SDimitry Andric   //   la.tls.ie rdest, symbol
31910b57cec5SDimitry Andric   // expands to
31920b57cec5SDimitry Andric   //   TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
31930b57cec5SDimitry Andric   //             Lx rdest, %pcrel_lo(TmpLabel)(rdest)
31940b57cec5SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
31950b57cec5SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
31960b57cec5SDimitry Andric   unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
31970b57cec5SDimitry Andric   emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
31980b57cec5SDimitry Andric                     SecondOpcode, IDLoc, Out);
31990b57cec5SDimitry Andric }
32000b57cec5SDimitry Andric 
emitLoadTLSGDAddress(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out)32010b57cec5SDimitry Andric void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
32020b57cec5SDimitry Andric                                           MCStreamer &Out) {
32030b57cec5SDimitry Andric   // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
32040b57cec5SDimitry Andric   // global-dynamic TLS model addressing of global symbols:
32050b57cec5SDimitry Andric   //   la.tls.gd rdest, symbol
32060b57cec5SDimitry Andric   // expands to
32070b57cec5SDimitry Andric   //   TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
32080b57cec5SDimitry Andric   //             ADDI rdest, rdest, %pcrel_lo(TmpLabel)
32090b57cec5SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
32100b57cec5SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
32110b57cec5SDimitry Andric   emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
32120b57cec5SDimitry Andric                     RISCV::ADDI, IDLoc, Out);
32130b57cec5SDimitry Andric }
32140b57cec5SDimitry Andric 
emitLoadStoreSymbol(MCInst & Inst,unsigned Opcode,SMLoc IDLoc,MCStreamer & Out,bool HasTmpReg)32150b57cec5SDimitry Andric void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
32160b57cec5SDimitry Andric                                          SMLoc IDLoc, MCStreamer &Out,
32170b57cec5SDimitry Andric                                          bool HasTmpReg) {
32180b57cec5SDimitry Andric   // The load/store pseudo-instruction does a pc-relative load with
32190b57cec5SDimitry Andric   // a symbol.
32200b57cec5SDimitry Andric   //
32210b57cec5SDimitry Andric   // The expansion looks like this
32220b57cec5SDimitry Andric   //
32230b57cec5SDimitry Andric   //   TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
32240b57cec5SDimitry Andric   //             [S|L]X    rd, %pcrel_lo(TmpLabel)(tmp)
3225349cc55cSDimitry Andric   unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3226349cc55cSDimitry Andric   MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
32270b57cec5SDimitry Andric   unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3228349cc55cSDimitry Andric   MCOperand TmpReg = Inst.getOperand(0);
32290b57cec5SDimitry Andric   const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
32300b57cec5SDimitry Andric   emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
32310b57cec5SDimitry Andric                     Opcode, IDLoc, Out);
32320b57cec5SDimitry Andric }
32330b57cec5SDimitry Andric 
emitPseudoExtend(MCInst & Inst,bool SignExtend,int64_t Width,SMLoc IDLoc,MCStreamer & Out)3234e8d8bef9SDimitry Andric void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3235e8d8bef9SDimitry Andric                                       int64_t Width, SMLoc IDLoc,
3236e8d8bef9SDimitry Andric                                       MCStreamer &Out) {
3237e8d8bef9SDimitry Andric   // The sign/zero extend pseudo-instruction does two shifts, with the shift
3238e8d8bef9SDimitry Andric   // amounts dependent on the XLEN.
3239e8d8bef9SDimitry Andric   //
3240e8d8bef9SDimitry Andric   // The expansion looks like this
3241e8d8bef9SDimitry Andric   //
3242e8d8bef9SDimitry Andric   //    SLLI rd, rs, XLEN - Width
3243e8d8bef9SDimitry Andric   //    SR[A|R]I rd, rd, XLEN - Width
3244e8d8bef9SDimitry Andric   MCOperand DestReg = Inst.getOperand(0);
3245e8d8bef9SDimitry Andric   MCOperand SourceReg = Inst.getOperand(1);
3246e8d8bef9SDimitry Andric 
3247e8d8bef9SDimitry Andric   unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3248e8d8bef9SDimitry Andric   int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3249e8d8bef9SDimitry Andric 
3250e8d8bef9SDimitry Andric   assert(ShAmt > 0 && "Shift amount must be non-zero.");
3251e8d8bef9SDimitry Andric 
3252e8d8bef9SDimitry Andric   emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3253e8d8bef9SDimitry Andric                           .addOperand(DestReg)
3254e8d8bef9SDimitry Andric                           .addOperand(SourceReg)
3255e8d8bef9SDimitry Andric                           .addImm(ShAmt));
3256e8d8bef9SDimitry Andric 
3257e8d8bef9SDimitry Andric   emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3258e8d8bef9SDimitry Andric                           .addOperand(DestReg)
3259e8d8bef9SDimitry Andric                           .addOperand(DestReg)
3260e8d8bef9SDimitry Andric                           .addImm(ShAmt));
3261e8d8bef9SDimitry Andric }
3262e8d8bef9SDimitry Andric 
emitVMSGE(MCInst & Inst,unsigned Opcode,SMLoc IDLoc,MCStreamer & Out)3263e8d8bef9SDimitry Andric void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3264e8d8bef9SDimitry Andric                                MCStreamer &Out) {
3265e8d8bef9SDimitry Andric   if (Inst.getNumOperands() == 3) {
3266e8d8bef9SDimitry Andric     // unmasked va >= x
3267e8d8bef9SDimitry Andric     //
3268e8d8bef9SDimitry Andric     //  pseudoinstruction: vmsge{u}.vx vd, va, x
3269e8d8bef9SDimitry Andric     //  expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3270e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opcode)
3271e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3272e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(1))
3273e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(2))
3274e8d8bef9SDimitry Andric                             .addReg(RISCV::NoRegister));
3275e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
3276e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3277e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3278e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0)));
3279e8d8bef9SDimitry Andric   } else if (Inst.getNumOperands() == 4) {
3280e8d8bef9SDimitry Andric     // masked va >= x, vd != v0
3281e8d8bef9SDimitry Andric     //
3282e8d8bef9SDimitry Andric     //  pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3283e8d8bef9SDimitry Andric     //  expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3284e8d8bef9SDimitry Andric     assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
3285e8d8bef9SDimitry Andric            "The destination register should not be V0.");
3286e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opcode)
3287e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3288e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(1))
3289e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(2))
3290e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(3)));
3291e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
3292e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3293e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3294e8d8bef9SDimitry Andric                             .addReg(RISCV::V0));
3295fe6060f1SDimitry Andric   } else if (Inst.getNumOperands() == 5 &&
3296fe6060f1SDimitry Andric              Inst.getOperand(0).getReg() == RISCV::V0) {
3297e8d8bef9SDimitry Andric     // masked va >= x, vd == v0
3298e8d8bef9SDimitry Andric     //
3299e8d8bef9SDimitry Andric     //  pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3300349cc55cSDimitry Andric     //  expansion: vmslt{u}.vx vt, va, x;  vmandn.mm vd, vd, vt
3301e8d8bef9SDimitry Andric     assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
3302e8d8bef9SDimitry Andric            "The destination register should be V0.");
3303e8d8bef9SDimitry Andric     assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3304e8d8bef9SDimitry Andric            "The temporary vector register should not be V0.");
3305e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opcode)
3306e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(1))
3307e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(2))
3308e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(3))
33095f757f3fSDimitry Andric                             .addReg(RISCV::NoRegister));
3310349cc55cSDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3311e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3312e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3313e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(1)));
3314fe6060f1SDimitry Andric   } else if (Inst.getNumOperands() == 5) {
3315fe6060f1SDimitry Andric     // masked va >= x, any vd
3316fe6060f1SDimitry Andric     //
3317fe6060f1SDimitry Andric     // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
33185f757f3fSDimitry Andric     // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
33195f757f3fSDimitry Andric     //            vmandn.mm vd, vd, v0;  vmor.mm vd, vt, vd
3320fe6060f1SDimitry Andric     assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3321fe6060f1SDimitry Andric            "The temporary vector register should not be V0.");
3322fe6060f1SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opcode)
3323fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(1))
3324fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(2))
3325fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(3))
3326fe6060f1SDimitry Andric                             .addReg(RISCV::NoRegister));
3327349cc55cSDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3328fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(1))
3329fe6060f1SDimitry Andric                             .addReg(RISCV::V0)
3330fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(1)));
3331349cc55cSDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3332fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(0))
3333fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(0))
3334fe6060f1SDimitry Andric                             .addReg(RISCV::V0));
3335fe6060f1SDimitry Andric     emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
3336fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(0))
3337fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(1))
3338fe6060f1SDimitry Andric                             .addOperand(Inst.getOperand(0)));
3339e8d8bef9SDimitry Andric   }
3340e8d8bef9SDimitry Andric }
3341e8d8bef9SDimitry Andric 
checkPseudoAddTPRel(MCInst & Inst,OperandVector & Operands)33420b57cec5SDimitry Andric bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
33430b57cec5SDimitry Andric                                          OperandVector &Operands) {
33440b57cec5SDimitry Andric   assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
33450b57cec5SDimitry Andric   assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
33460b57cec5SDimitry Andric   if (Inst.getOperand(2).getReg() != RISCV::X4) {
33470b57cec5SDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
33480b57cec5SDimitry Andric     return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
33490b57cec5SDimitry Andric                            "%tprel_add modifier");
33500b57cec5SDimitry Andric   }
33510b57cec5SDimitry Andric 
33520b57cec5SDimitry Andric   return false;
33530b57cec5SDimitry Andric }
33540b57cec5SDimitry Andric 
checkPseudoTLSDESCCall(MCInst & Inst,OperandVector & Operands)33557a6dacacSDimitry Andric bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
33567a6dacacSDimitry Andric                                             OperandVector &Operands) {
33577a6dacacSDimitry Andric   assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
33587a6dacacSDimitry Andric   assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
33597a6dacacSDimitry Andric   if (Inst.getOperand(0).getReg() != RISCV::X5) {
33607a6dacacSDimitry Andric     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
33617a6dacacSDimitry Andric     return Error(ErrorLoc, "the output operand must be t0/x5 when using "
33627a6dacacSDimitry Andric                            "%tlsdesc_call modifier");
33637a6dacacSDimitry Andric   }
33647a6dacacSDimitry Andric 
33657a6dacacSDimitry Andric   return false;
33667a6dacacSDimitry Andric }
33677a6dacacSDimitry Andric 
defaultMaskRegOp() const33685ffd83dbSDimitry Andric std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
33695ffd83dbSDimitry Andric   return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
337006c3fb27SDimitry Andric                                  llvm::SMLoc());
337106c3fb27SDimitry Andric }
337206c3fb27SDimitry Andric 
defaultFRMArgOp() const337306c3fb27SDimitry Andric std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
337406c3fb27SDimitry Andric   return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
337506c3fb27SDimitry Andric                                     llvm::SMLoc());
33765ffd83dbSDimitry Andric }
33775ffd83dbSDimitry Andric 
defaultFRMArgLegacyOp() const33785f757f3fSDimitry Andric std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
33795f757f3fSDimitry Andric   return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
33805f757f3fSDimitry Andric                                     llvm::SMLoc());
33815f757f3fSDimitry Andric }
33825f757f3fSDimitry Andric 
validateInstruction(MCInst & Inst,OperandVector & Operands)33835ffd83dbSDimitry Andric bool RISCVAsmParser::validateInstruction(MCInst &Inst,
33845ffd83dbSDimitry Andric                                          OperandVector &Operands) {
338506c3fb27SDimitry Andric   unsigned Opcode = Inst.getOpcode();
338606c3fb27SDimitry Andric 
338706c3fb27SDimitry Andric   if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
338806c3fb27SDimitry Andric       Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3389fe6060f1SDimitry Andric     unsigned DestReg = Inst.getOperand(0).getReg();
3390fe6060f1SDimitry Andric     unsigned TempReg = Inst.getOperand(1).getReg();
3391fe6060f1SDimitry Andric     if (DestReg == TempReg) {
3392fe6060f1SDimitry Andric       SMLoc Loc = Operands.back()->getStartLoc();
3393fe6060f1SDimitry Andric       return Error(Loc, "The temporary vector register cannot be the same as "
3394fe6060f1SDimitry Andric                         "the destination register.");
3395fe6060f1SDimitry Andric     }
3396fe6060f1SDimitry Andric   }
3397fe6060f1SDimitry Andric 
339806c3fb27SDimitry Andric   if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
339906c3fb27SDimitry Andric       Opcode == RISCV::TH_LWD) {
340006c3fb27SDimitry Andric     unsigned Rd1 = Inst.getOperand(0).getReg();
340106c3fb27SDimitry Andric     unsigned Rd2 = Inst.getOperand(1).getReg();
340206c3fb27SDimitry Andric     unsigned Rs1 = Inst.getOperand(2).getReg();
340306c3fb27SDimitry Andric     // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
340406c3fb27SDimitry Andric     if (Rs1 == Rd1 && Rs1 == Rd2) {
340506c3fb27SDimitry Andric       SMLoc Loc = Operands[1]->getStartLoc();
340606c3fb27SDimitry Andric       return Error(Loc, "The source register and destination registers "
340706c3fb27SDimitry Andric                         "cannot be equal.");
340806c3fb27SDimitry Andric     }
340906c3fb27SDimitry Andric   }
341006c3fb27SDimitry Andric 
341106c3fb27SDimitry Andric   if (Opcode == RISCV::CM_MVSA01) {
341206c3fb27SDimitry Andric     unsigned Rd1 = Inst.getOperand(0).getReg();
341306c3fb27SDimitry Andric     unsigned Rd2 = Inst.getOperand(1).getReg();
341406c3fb27SDimitry Andric     if (Rd1 == Rd2) {
341506c3fb27SDimitry Andric       SMLoc Loc = Operands[1]->getStartLoc();
341606c3fb27SDimitry Andric       return Error(Loc, "'rs1' and 'rs2' must be different.");
341706c3fb27SDimitry Andric     }
341806c3fb27SDimitry Andric   }
341906c3fb27SDimitry Andric 
342006c3fb27SDimitry Andric   bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
342106c3fb27SDimitry Andric                            Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
342206c3fb27SDimitry Andric   bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
342306c3fb27SDimitry Andric   // The last operand of XTHeadMemPair instructions must be constant 3 or 4
342406c3fb27SDimitry Andric   // depending on the data width.
342506c3fb27SDimitry Andric   if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) {
342606c3fb27SDimitry Andric     SMLoc Loc = Operands.back()->getStartLoc();
342706c3fb27SDimitry Andric     return Error(Loc, "Operand must be constant 3.");
342806c3fb27SDimitry Andric   } else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) {
342906c3fb27SDimitry Andric     SMLoc Loc = Operands.back()->getStartLoc();
343006c3fb27SDimitry Andric     return Error(Loc, "Operand must be constant 4.");
343106c3fb27SDimitry Andric   }
343206c3fb27SDimitry Andric 
343306c3fb27SDimitry Andric   const MCInstrDesc &MCID = MII.get(Opcode);
343406c3fb27SDimitry Andric   if (!(MCID.TSFlags & RISCVII::ConstraintMask))
34355ffd83dbSDimitry Andric     return false;
34365ffd83dbSDimitry Andric 
343706c3fb27SDimitry Andric   if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
343806c3fb27SDimitry Andric       Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
343906c3fb27SDimitry Andric     // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
344006c3fb27SDimitry Andric     unsigned VCIXDst = Inst.getOperand(0).getReg();
344106c3fb27SDimitry Andric     SMLoc VCIXDstLoc = Operands[2]->getStartLoc();
344206c3fb27SDimitry Andric     if (MCID.TSFlags & RISCVII::VS1Constraint) {
344306c3fb27SDimitry Andric       unsigned VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
344406c3fb27SDimitry Andric       if (VCIXDst == VCIXRs1)
344506c3fb27SDimitry Andric         return Error(VCIXDstLoc, "The destination vector register group cannot"
344606c3fb27SDimitry Andric                                  " overlap the source vector register group.");
344706c3fb27SDimitry Andric     }
344806c3fb27SDimitry Andric     if (MCID.TSFlags & RISCVII::VS2Constraint) {
344906c3fb27SDimitry Andric       unsigned VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();
345006c3fb27SDimitry Andric       if (VCIXDst == VCIXRs2)
345106c3fb27SDimitry Andric         return Error(VCIXDstLoc, "The destination vector register group cannot"
345206c3fb27SDimitry Andric                                  " overlap the source vector register group.");
345306c3fb27SDimitry Andric     }
345406c3fb27SDimitry Andric     return false;
345506c3fb27SDimitry Andric   }
345606c3fb27SDimitry Andric 
34575ffd83dbSDimitry Andric   unsigned DestReg = Inst.getOperand(0).getReg();
34585f757f3fSDimitry Andric   unsigned Offset = 0;
34595f757f3fSDimitry Andric   int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);
34605f757f3fSDimitry Andric   if (TiedOp == 0)
34615f757f3fSDimitry Andric     Offset = 1;
34625f757f3fSDimitry Andric 
34635ffd83dbSDimitry Andric   // Operands[1] will be the first operand, DestReg.
34645ffd83dbSDimitry Andric   SMLoc Loc = Operands[1]->getStartLoc();
346506c3fb27SDimitry Andric   if (MCID.TSFlags & RISCVII::VS2Constraint) {
34665f757f3fSDimitry Andric     unsigned CheckReg = Inst.getOperand(Offset + 1).getReg();
3467e8d8bef9SDimitry Andric     if (DestReg == CheckReg)
34685ffd83dbSDimitry Andric       return Error(Loc, "The destination vector register group cannot overlap"
34695ffd83dbSDimitry Andric                         " the source vector register group.");
34705ffd83dbSDimitry Andric   }
34715f757f3fSDimitry Andric   if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {
34725f757f3fSDimitry Andric     unsigned CheckReg = Inst.getOperand(Offset + 2).getReg();
3473e8d8bef9SDimitry Andric     if (DestReg == CheckReg)
34745ffd83dbSDimitry Andric       return Error(Loc, "The destination vector register group cannot overlap"
34755ffd83dbSDimitry Andric                         " the source vector register group.");
34765ffd83dbSDimitry Andric   }
347706c3fb27SDimitry Andric   if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
3478e8d8bef9SDimitry Andric     // vadc, vsbc are special cases. These instructions have no mask register.
3479e8d8bef9SDimitry Andric     // The destination register could not be V0.
3480e8d8bef9SDimitry Andric     if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3481e8d8bef9SDimitry Andric         Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3482e8d8bef9SDimitry Andric         Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3483e8d8bef9SDimitry Andric         Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3484e8d8bef9SDimitry Andric         Opcode == RISCV::VMERGE_VXM)
3485e8d8bef9SDimitry Andric       return Error(Loc, "The destination vector register group cannot be V0.");
34865ffd83dbSDimitry Andric 
3487e8d8bef9SDimitry Andric     // Regardless masked or unmasked version, the number of operands is the
3488e8d8bef9SDimitry Andric     // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3489e8d8bef9SDimitry Andric     // actually. We need to check the last operand to ensure whether it is
3490e8d8bef9SDimitry Andric     // masked or not.
3491e8d8bef9SDimitry Andric     unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3492e8d8bef9SDimitry Andric     assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
3493e8d8bef9SDimitry Andric            "Unexpected register for mask operand");
3494e8d8bef9SDimitry Andric 
3495e8d8bef9SDimitry Andric     if (DestReg == CheckReg)
34965ffd83dbSDimitry Andric       return Error(Loc, "The destination vector register group cannot overlap"
34975ffd83dbSDimitry Andric                         " the mask register.");
34985ffd83dbSDimitry Andric   }
34995ffd83dbSDimitry Andric   return false;
35005ffd83dbSDimitry Andric }
35015ffd83dbSDimitry Andric 
processInstruction(MCInst & Inst,SMLoc IDLoc,OperandVector & Operands,MCStreamer & Out)35020b57cec5SDimitry Andric bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
35030b57cec5SDimitry Andric                                         OperandVector &Operands,
35040b57cec5SDimitry Andric                                         MCStreamer &Out) {
35050b57cec5SDimitry Andric   Inst.setLoc(IDLoc);
35060b57cec5SDimitry Andric 
35070b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
35080b57cec5SDimitry Andric   default:
35090b57cec5SDimitry Andric     break;
351006c3fb27SDimitry Andric   case RISCV::PseudoLLAImm:
351106c3fb27SDimitry Andric   case RISCV::PseudoLAImm:
35120b57cec5SDimitry Andric   case RISCV::PseudoLI: {
3513e8d8bef9SDimitry Andric     MCRegister Reg = Inst.getOperand(0).getReg();
35140b57cec5SDimitry Andric     const MCOperand &Op1 = Inst.getOperand(1);
35150b57cec5SDimitry Andric     if (Op1.isExpr()) {
35160b57cec5SDimitry Andric       // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
35170b57cec5SDimitry Andric       // Just convert to an addi. This allows compatibility with gas.
35180b57cec5SDimitry Andric       emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
35190b57cec5SDimitry Andric                               .addReg(Reg)
35200b57cec5SDimitry Andric                               .addReg(RISCV::X0)
35210b57cec5SDimitry Andric                               .addExpr(Op1.getExpr()));
35220b57cec5SDimitry Andric       return false;
35230b57cec5SDimitry Andric     }
35240b57cec5SDimitry Andric     int64_t Imm = Inst.getOperand(1).getImm();
35250b57cec5SDimitry Andric     // On RV32 the immediate here can either be a signed or an unsigned
35260b57cec5SDimitry Andric     // 32-bit number. Sign extension has to be performed to ensure that Imm
35270b57cec5SDimitry Andric     // represents the expected signed 64-bit number.
35280b57cec5SDimitry Andric     if (!isRV64())
35290b57cec5SDimitry Andric       Imm = SignExtend64<32>(Imm);
35300b57cec5SDimitry Andric     emitLoadImm(Reg, Imm, Out);
35310b57cec5SDimitry Andric     return false;
35320b57cec5SDimitry Andric   }
35330b57cec5SDimitry Andric   case RISCV::PseudoLLA:
35340b57cec5SDimitry Andric     emitLoadLocalAddress(Inst, IDLoc, Out);
35350b57cec5SDimitry Andric     return false;
353606c3fb27SDimitry Andric   case RISCV::PseudoLGA:
353706c3fb27SDimitry Andric     emitLoadGlobalAddress(Inst, IDLoc, Out);
353806c3fb27SDimitry Andric     return false;
35390b57cec5SDimitry Andric   case RISCV::PseudoLA:
35400b57cec5SDimitry Andric     emitLoadAddress(Inst, IDLoc, Out);
35410b57cec5SDimitry Andric     return false;
35420b57cec5SDimitry Andric   case RISCV::PseudoLA_TLS_IE:
35430b57cec5SDimitry Andric     emitLoadTLSIEAddress(Inst, IDLoc, Out);
35440b57cec5SDimitry Andric     return false;
35450b57cec5SDimitry Andric   case RISCV::PseudoLA_TLS_GD:
35460b57cec5SDimitry Andric     emitLoadTLSGDAddress(Inst, IDLoc, Out);
35470b57cec5SDimitry Andric     return false;
35480b57cec5SDimitry Andric   case RISCV::PseudoLB:
35490b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
35500b57cec5SDimitry Andric     return false;
35510b57cec5SDimitry Andric   case RISCV::PseudoLBU:
35520b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
35530b57cec5SDimitry Andric     return false;
35540b57cec5SDimitry Andric   case RISCV::PseudoLH:
35550b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
35560b57cec5SDimitry Andric     return false;
35570b57cec5SDimitry Andric   case RISCV::PseudoLHU:
35580b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
35590b57cec5SDimitry Andric     return false;
35600b57cec5SDimitry Andric   case RISCV::PseudoLW:
35610b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
35620b57cec5SDimitry Andric     return false;
35630b57cec5SDimitry Andric   case RISCV::PseudoLWU:
35640b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
35650b57cec5SDimitry Andric     return false;
35660b57cec5SDimitry Andric   case RISCV::PseudoLD:
35670b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
35680b57cec5SDimitry Andric     return false;
3569e8d8bef9SDimitry Andric   case RISCV::PseudoFLH:
3570e8d8bef9SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
3571e8d8bef9SDimitry Andric     return false;
35720b57cec5SDimitry Andric   case RISCV::PseudoFLW:
35730b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
35740b57cec5SDimitry Andric     return false;
35750b57cec5SDimitry Andric   case RISCV::PseudoFLD:
35760b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
35770b57cec5SDimitry Andric     return false;
35780b57cec5SDimitry Andric   case RISCV::PseudoSB:
35790b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
35800b57cec5SDimitry Andric     return false;
35810b57cec5SDimitry Andric   case RISCV::PseudoSH:
35820b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
35830b57cec5SDimitry Andric     return false;
35840b57cec5SDimitry Andric   case RISCV::PseudoSW:
35850b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
35860b57cec5SDimitry Andric     return false;
35870b57cec5SDimitry Andric   case RISCV::PseudoSD:
35880b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
35890b57cec5SDimitry Andric     return false;
3590e8d8bef9SDimitry Andric   case RISCV::PseudoFSH:
3591e8d8bef9SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
3592e8d8bef9SDimitry Andric     return false;
35930b57cec5SDimitry Andric   case RISCV::PseudoFSW:
35940b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
35950b57cec5SDimitry Andric     return false;
35960b57cec5SDimitry Andric   case RISCV::PseudoFSD:
35970b57cec5SDimitry Andric     emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
35980b57cec5SDimitry Andric     return false;
35990b57cec5SDimitry Andric   case RISCV::PseudoAddTPRel:
36000b57cec5SDimitry Andric     if (checkPseudoAddTPRel(Inst, Operands))
36010b57cec5SDimitry Andric       return true;
36020b57cec5SDimitry Andric     break;
36037a6dacacSDimitry Andric   case RISCV::PseudoTLSDESCCall:
36047a6dacacSDimitry Andric     if (checkPseudoTLSDESCCall(Inst, Operands))
36057a6dacacSDimitry Andric       return true;
36067a6dacacSDimitry Andric     break;
3607e8d8bef9SDimitry Andric   case RISCV::PseudoSEXT_B:
3608e8d8bef9SDimitry Andric     emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
3609e8d8bef9SDimitry Andric     return false;
3610e8d8bef9SDimitry Andric   case RISCV::PseudoSEXT_H:
3611e8d8bef9SDimitry Andric     emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
3612e8d8bef9SDimitry Andric     return false;
3613e8d8bef9SDimitry Andric   case RISCV::PseudoZEXT_H:
3614e8d8bef9SDimitry Andric     emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
3615e8d8bef9SDimitry Andric     return false;
3616e8d8bef9SDimitry Andric   case RISCV::PseudoZEXT_W:
3617e8d8bef9SDimitry Andric     emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
3618e8d8bef9SDimitry Andric     return false;
3619e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGEU_VX:
3620e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGEU_VX_M:
3621e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGEU_VX_M_T:
3622e8d8bef9SDimitry Andric     emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3623e8d8bef9SDimitry Andric     return false;
3624e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGE_VX:
3625e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGE_VX_M:
3626e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGE_VX_M_T:
3627e8d8bef9SDimitry Andric     emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3628e8d8bef9SDimitry Andric     return false;
3629e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGE_VI:
3630e8d8bef9SDimitry Andric   case RISCV::PseudoVMSLT_VI: {
3631e8d8bef9SDimitry Andric     // These instructions are signed and so is immediate so we can subtract one
3632e8d8bef9SDimitry Andric     // and change the opcode.
3633e8d8bef9SDimitry Andric     int64_t Imm = Inst.getOperand(2).getImm();
3634e8d8bef9SDimitry Andric     unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3635e8d8bef9SDimitry Andric                                                              : RISCV::VMSLE_VI;
3636e8d8bef9SDimitry Andric     emitToStreamer(Out, MCInstBuilder(Opc)
3637e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(0))
3638e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(1))
3639e8d8bef9SDimitry Andric                             .addImm(Imm - 1)
3640e8d8bef9SDimitry Andric                             .addOperand(Inst.getOperand(3)));
3641e8d8bef9SDimitry Andric     return false;
3642e8d8bef9SDimitry Andric   }
3643e8d8bef9SDimitry Andric   case RISCV::PseudoVMSGEU_VI:
3644e8d8bef9SDimitry Andric   case RISCV::PseudoVMSLTU_VI: {
3645e8d8bef9SDimitry Andric     int64_t Imm = Inst.getOperand(2).getImm();
3646e8d8bef9SDimitry Andric     // Unsigned comparisons are tricky because the immediate is signed. If the
3647e8d8bef9SDimitry Andric     // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3648e8d8bef9SDimitry Andric     // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3649e8d8bef9SDimitry Andric     // vmsne v0, v1, v1 which is always false.
3650e8d8bef9SDimitry Andric     if (Imm == 0) {
3651e8d8bef9SDimitry Andric       unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3652e8d8bef9SDimitry Andric                          ? RISCV::VMSEQ_VV
3653e8d8bef9SDimitry Andric                          : RISCV::VMSNE_VV;
3654e8d8bef9SDimitry Andric       emitToStreamer(Out, MCInstBuilder(Opc)
3655e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(0))
3656e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(1))
3657e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(1))
3658e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(3)));
3659e8d8bef9SDimitry Andric     } else {
3660e8d8bef9SDimitry Andric       // Other immediate values can subtract one like signed.
3661e8d8bef9SDimitry Andric       unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3662e8d8bef9SDimitry Andric                          ? RISCV::VMSGTU_VI
3663e8d8bef9SDimitry Andric                          : RISCV::VMSLEU_VI;
3664e8d8bef9SDimitry Andric       emitToStreamer(Out, MCInstBuilder(Opc)
3665e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(0))
3666e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(1))
3667e8d8bef9SDimitry Andric                               .addImm(Imm - 1)
3668e8d8bef9SDimitry Andric                               .addOperand(Inst.getOperand(3)));
3669e8d8bef9SDimitry Andric     }
3670e8d8bef9SDimitry Andric 
3671e8d8bef9SDimitry Andric     return false;
3672e8d8bef9SDimitry Andric   }
36730b57cec5SDimitry Andric   }
36740b57cec5SDimitry Andric 
36750b57cec5SDimitry Andric   emitToStreamer(Out, Inst);
36760b57cec5SDimitry Andric   return false;
36770b57cec5SDimitry Andric }
36780b57cec5SDimitry Andric 
LLVMInitializeRISCVAsmParser()3679480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser() {
36800b57cec5SDimitry Andric   RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
36810b57cec5SDimitry Andric   RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
36820b57cec5SDimitry Andric }
3683