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