Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
35294 views
//===-- RISCVAsmParser.cpp - Parse RISC-V assembly to MCInst instructions -===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MCTargetDesc/RISCVAsmBackend.h"9#include "MCTargetDesc/RISCVBaseInfo.h"10#include "MCTargetDesc/RISCVInstPrinter.h"11#include "MCTargetDesc/RISCVMCExpr.h"12#include "MCTargetDesc/RISCVMCTargetDesc.h"13#include "MCTargetDesc/RISCVMatInt.h"14#include "MCTargetDesc/RISCVTargetStreamer.h"15#include "TargetInfo/RISCVTargetInfo.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/ADT/SmallBitVector.h"18#include "llvm/ADT/SmallVector.h"19#include "llvm/ADT/Statistic.h"20#include "llvm/ADT/StringExtras.h"21#include "llvm/MC/MCAssembler.h"22#include "llvm/MC/MCContext.h"23#include "llvm/MC/MCExpr.h"24#include "llvm/MC/MCInst.h"25#include "llvm/MC/MCInstBuilder.h"26#include "llvm/MC/MCInstrInfo.h"27#include "llvm/MC/MCObjectFileInfo.h"28#include "llvm/MC/MCParser/MCAsmLexer.h"29#include "llvm/MC/MCParser/MCParsedAsmOperand.h"30#include "llvm/MC/MCParser/MCTargetAsmParser.h"31#include "llvm/MC/MCRegisterInfo.h"32#include "llvm/MC/MCStreamer.h"33#include "llvm/MC/MCSubtargetInfo.h"34#include "llvm/MC/MCValue.h"35#include "llvm/MC/TargetRegistry.h"36#include "llvm/Support/Casting.h"37#include "llvm/Support/CommandLine.h"38#include "llvm/Support/MathExtras.h"39#include "llvm/Support/RISCVAttributes.h"40#include "llvm/TargetParser/RISCVISAInfo.h"4142#include <limits>4344using namespace llvm;4546#define DEBUG_TYPE "riscv-asm-parser"4748STATISTIC(RISCVNumInstrsCompressed,49"Number of RISC-V Compressed instructions emitted");5051static cl::opt<bool> AddBuildAttributes("riscv-add-build-attributes",52cl::init(false));5354namespace llvm {55extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];56} // namespace llvm5758namespace {59struct RISCVOperand;6061struct ParserOptionsSet {62bool IsPicEnabled;63};6465class RISCVAsmParser : public MCTargetAsmParser {66// This tracks the parsing of the 4 operands that make up the vtype portion67// of vset(i)vli instructions which are separated by commas. The state names68// represent the next expected operand with Done meaning no other operands are69// expected.70enum VTypeState {71VTypeState_SEW,72VTypeState_LMUL,73VTypeState_TailPolicy,74VTypeState_MaskPolicy,75VTypeState_Done,76};7778SmallVector<FeatureBitset, 4> FeatureBitStack;7980SmallVector<ParserOptionsSet, 4> ParserOptionsStack;81ParserOptionsSet ParserOptions;8283SMLoc getLoc() const { return getParser().getTok().getLoc(); }84bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }85bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureStdExtE); }86bool enableExperimentalExtension() const {87return getSTI().hasFeature(RISCV::Experimental);88}8990RISCVTargetStreamer &getTargetStreamer() {91assert(getParser().getStreamer().getTargetStreamer() &&92"do not have a target streamer");93MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();94return static_cast<RISCVTargetStreamer &>(TS);95}9697unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,98unsigned Kind) override;99unsigned checkTargetMatchPredicate(MCInst &Inst) override;100101bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,102int64_t Lower, int64_t Upper,103const Twine &Msg);104bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,105const Twine &Msg);106107bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,108OperandVector &Operands, MCStreamer &Out,109uint64_t &ErrorInfo,110bool MatchingInlineAsm) override;111112MCRegister matchRegisterNameHelper(StringRef Name) const;113bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;114ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,115SMLoc &EndLoc) override;116117bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,118SMLoc NameLoc, OperandVector &Operands) override;119120ParseStatus parseDirective(AsmToken DirectiveID) override;121122bool parseVTypeToken(const AsmToken &Tok, VTypeState &State, unsigned &Sew,123unsigned &Lmul, bool &Fractional, bool &TailAgnostic,124bool &MaskAgnostic);125bool generateVTypeError(SMLoc ErrorLoc);126127// Helper to actually emit an instruction to the MCStreamer. Also, when128// possible, compression of the instruction is performed.129void emitToStreamer(MCStreamer &S, const MCInst &Inst);130131// Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that132// synthesize the desired immedate value into the destination register.133void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);134135// Helper to emit a combination of AUIPC and SecondOpcode. Used to implement136// helpers such as emitLoadLocalAddress and emitLoadAddress.137void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,138const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,139unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);140141// Helper to emit pseudo instruction "lla" used in PC-rel addressing.142void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);143144// Helper to emit pseudo instruction "lga" used in GOT-rel addressing.145void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);146147// Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.148void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);149150// Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS151// addressing.152void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);153154// Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS155// addressing.156void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);157158// Helper to emit pseudo load/store instruction with a symbol.159void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,160MCStreamer &Out, bool HasTmpReg);161162// Helper to emit pseudo sign/zero extend instruction.163void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,164SMLoc IDLoc, MCStreamer &Out);165166// Helper to emit pseudo vmsge{u}.vx instruction.167void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);168169// Checks that a PseudoAddTPRel is using x4/tp in its second input operand.170// Enforcing this using a restricted register class for the second input171// operand of PseudoAddTPRel results in a poor diagnostic due to the fact172// 'add' is an overloaded mnemonic.173bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);174175// Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.176// Enforcing this using a restricted register class for the output177// operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact178// 'jalr' is an overloaded mnemonic.179bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands);180181// Check instruction constraints.182bool validateInstruction(MCInst &Inst, OperandVector &Operands);183184/// Helper for processing MC instructions that have been successfully matched185/// by MatchAndEmitInstruction. Modifications to the emitted instructions,186/// like the expansion of pseudo instructions (e.g., "li"), can be performed187/// in this method.188bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,189MCStreamer &Out);190191// Auto-generated instruction matching functions192#define GET_ASSEMBLER_HEADER193#include "RISCVGenAsmMatcher.inc"194195ParseStatus parseCSRSystemRegister(OperandVector &Operands);196ParseStatus parseFPImm(OperandVector &Operands);197ParseStatus parseImmediate(OperandVector &Operands);198ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);199ParseStatus parseMemOpBaseReg(OperandVector &Operands);200ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);201ParseStatus parseOperandWithModifier(OperandVector &Operands);202ParseStatus parseBareSymbol(OperandVector &Operands);203ParseStatus parseCallSymbol(OperandVector &Operands);204ParseStatus parsePseudoJumpSymbol(OperandVector &Operands);205ParseStatus parseJALOffset(OperandVector &Operands);206ParseStatus parseVTypeI(OperandVector &Operands);207ParseStatus parseMaskReg(OperandVector &Operands);208ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);209ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);210ParseStatus parseGPRAsFPR(OperandVector &Operands);211template <bool IsRV64Inst> ParseStatus parseGPRPair(OperandVector &Operands);212ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);213ParseStatus parseFRMArg(OperandVector &Operands);214ParseStatus parseFenceArg(OperandVector &Operands);215ParseStatus parseReglist(OperandVector &Operands);216ParseStatus parseRegReg(OperandVector &Operands);217ParseStatus parseRetval(OperandVector &Operands);218ParseStatus parseZcmpStackAdj(OperandVector &Operands,219bool ExpectNegative = false);220ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) {221return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true);222}223224bool parseOperand(OperandVector &Operands, StringRef Mnemonic);225226bool parseDirectiveOption();227bool parseDirectiveAttribute();228bool parseDirectiveInsn(SMLoc L);229bool parseDirectiveVariantCC();230231/// Helper to reset target features for a new arch string. It232/// also records the new arch string that is expanded by RISCVISAInfo233/// and reports error for invalid arch string.234bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,235bool FromOptionDirective);236237void setFeatureBits(uint64_t Feature, StringRef FeatureString) {238if (!(getSTI().hasFeature(Feature))) {239MCSubtargetInfo &STI = copySTI();240setAvailableFeatures(241ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));242}243}244245void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {246if (getSTI().hasFeature(Feature)) {247MCSubtargetInfo &STI = copySTI();248setAvailableFeatures(249ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));250}251}252253void pushFeatureBits() {254assert(FeatureBitStack.size() == ParserOptionsStack.size() &&255"These two stacks must be kept synchronized");256FeatureBitStack.push_back(getSTI().getFeatureBits());257ParserOptionsStack.push_back(ParserOptions);258}259260bool popFeatureBits() {261assert(FeatureBitStack.size() == ParserOptionsStack.size() &&262"These two stacks must be kept synchronized");263if (FeatureBitStack.empty())264return true;265266FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();267copySTI().setFeatureBits(FeatureBits);268setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));269270ParserOptions = ParserOptionsStack.pop_back_val();271272return false;273}274275std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;276std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;277std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;278279public:280enum RISCVMatchResultTy {281Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,282Match_RequiresEvenGPRs,283#define GET_OPERAND_DIAGNOSTIC_TYPES284#include "RISCVGenAsmMatcher.inc"285#undef GET_OPERAND_DIAGNOSTIC_TYPES286};287288static bool classifySymbolRef(const MCExpr *Expr,289RISCVMCExpr::VariantKind &Kind);290static bool isSymbolDiff(const MCExpr *Expr);291292RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,293const MCInstrInfo &MII, const MCTargetOptions &Options)294: MCTargetAsmParser(Options, STI, MII) {295MCAsmParserExtension::Initialize(Parser);296297Parser.addAliasForDirective(".half", ".2byte");298Parser.addAliasForDirective(".hword", ".2byte");299Parser.addAliasForDirective(".word", ".4byte");300Parser.addAliasForDirective(".dword", ".8byte");301setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));302303auto ABIName = StringRef(Options.ABIName);304if (ABIName.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {305errs() << "Hard-float 'f' ABI can't be used for a target that "306"doesn't support the F instruction set extension (ignoring "307"target-abi)\n";308} else if (ABIName.ends_with("d") &&309!getSTI().hasFeature(RISCV::FeatureStdExtD)) {310errs() << "Hard-float 'd' ABI can't be used for a target that "311"doesn't support the D instruction set extension (ignoring "312"target-abi)\n";313}314315// Use computeTargetABI to check if ABIName is valid. If invalid, output316// error message.317RISCVABI::computeTargetABI(STI.getTargetTriple(), STI.getFeatureBits(),318ABIName);319320const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();321ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();322323if (AddBuildAttributes)324getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);325}326};327328/// RISCVOperand - Instances of this class represent a parsed machine329/// instruction330struct RISCVOperand final : public MCParsedAsmOperand {331332enum class KindTy {333Token,334Register,335Immediate,336FPImmediate,337SystemRegister,338VType,339FRM,340Fence,341Rlist,342Spimm,343RegReg,344} Kind;345346struct RegOp {347MCRegister RegNum;348bool IsGPRAsFPR;349};350351struct ImmOp {352const MCExpr *Val;353bool IsRV64;354};355356struct FPImmOp {357uint64_t Val;358};359360struct SysRegOp {361const char *Data;362unsigned Length;363unsigned Encoding;364// FIXME: Add the Encoding parsed fields as needed for checks,365// e.g.: read/write or user/supervisor/machine privileges.366};367368struct VTypeOp {369unsigned Val;370};371372struct FRMOp {373RISCVFPRndMode::RoundingMode FRM;374};375376struct FenceOp {377unsigned Val;378};379380struct RlistOp {381unsigned Val;382};383384struct SpimmOp {385unsigned Val;386};387388struct RegRegOp {389MCRegister Reg1;390MCRegister Reg2;391};392393SMLoc StartLoc, EndLoc;394union {395StringRef Tok;396RegOp Reg;397ImmOp Imm;398FPImmOp FPImm;399struct SysRegOp SysReg;400struct VTypeOp VType;401struct FRMOp FRM;402struct FenceOp Fence;403struct RlistOp Rlist;404struct SpimmOp Spimm;405struct RegRegOp RegReg;406};407408RISCVOperand(KindTy K) : Kind(K) {}409410public:411RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {412Kind = o.Kind;413StartLoc = o.StartLoc;414EndLoc = o.EndLoc;415switch (Kind) {416case KindTy::Register:417Reg = o.Reg;418break;419case KindTy::Immediate:420Imm = o.Imm;421break;422case KindTy::FPImmediate:423FPImm = o.FPImm;424break;425case KindTy::Token:426Tok = o.Tok;427break;428case KindTy::SystemRegister:429SysReg = o.SysReg;430break;431case KindTy::VType:432VType = o.VType;433break;434case KindTy::FRM:435FRM = o.FRM;436break;437case KindTy::Fence:438Fence = o.Fence;439break;440case KindTy::Rlist:441Rlist = o.Rlist;442break;443case KindTy::Spimm:444Spimm = o.Spimm;445break;446case KindTy::RegReg:447RegReg = o.RegReg;448break;449}450}451452bool isToken() const override { return Kind == KindTy::Token; }453bool isReg() const override { return Kind == KindTy::Register; }454bool isV0Reg() const {455return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;456}457bool isAnyReg() const {458return Kind == KindTy::Register &&459(RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum) ||460RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.RegNum) ||461RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.RegNum));462}463bool isAnyRegC() const {464return Kind == KindTy::Register &&465(RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(466Reg.RegNum) ||467RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(468Reg.RegNum));469}470bool isImm() const override { return Kind == KindTy::Immediate; }471bool isMem() const override { return false; }472bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }473bool isRegReg() const { return Kind == KindTy::RegReg; }474bool isRlist() const { return Kind == KindTy::Rlist; }475bool isSpimm() const { return Kind == KindTy::Spimm; }476477bool isGPR() const {478return Kind == KindTy::Register &&479RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);480}481482bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }483484bool isGPRPair() const {485return Kind == KindTy::Register &&486RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(487Reg.RegNum);488}489490static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,491RISCVMCExpr::VariantKind &VK) {492if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {493VK = RE->getKind();494return RE->evaluateAsConstant(Imm);495}496497if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {498VK = RISCVMCExpr::VK_RISCV_None;499Imm = CE->getValue();500return true;501}502503return false;504}505506// True if operand is a symbol with no modifiers, or a constant with no507// modifiers and isShiftedInt<N-1, 1>(Op).508template <int N> bool isBareSimmNLsb0() const {509int64_t Imm;510RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;511if (!isImm())512return false;513bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);514bool IsValid;515if (!IsConstantImm)516IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);517else518IsValid = isShiftedInt<N - 1, 1>(Imm);519return IsValid && VK == RISCVMCExpr::VK_RISCV_None;520}521522// Predicate methods for AsmOperands defined in RISCVInstrInfo.td523524bool isBareSymbol() const {525int64_t Imm;526RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;527// Must be of 'immediate' type but not a constant.528if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))529return false;530return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&531VK == RISCVMCExpr::VK_RISCV_None;532}533534bool isCallSymbol() const {535int64_t Imm;536RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;537// Must be of 'immediate' type but not a constant.538if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))539return false;540return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&541(VK == RISCVMCExpr::VK_RISCV_CALL ||542VK == RISCVMCExpr::VK_RISCV_CALL_PLT);543}544545bool isPseudoJumpSymbol() const {546int64_t Imm;547RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;548// Must be of 'immediate' type but not a constant.549if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))550return false;551return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&552VK == RISCVMCExpr::VK_RISCV_CALL;553}554555bool isTPRelAddSymbol() const {556int64_t Imm;557RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;558// Must be of 'immediate' type but not a constant.559if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))560return false;561return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&562VK == RISCVMCExpr::VK_RISCV_TPREL_ADD;563}564565bool isTLSDESCCallSymbol() const {566int64_t Imm;567RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;568// Must be of 'immediate' type but not a constant.569if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))570return false;571return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&572VK == RISCVMCExpr::VK_RISCV_TLSDESC_CALL;573}574575bool isCSRSystemRegister() const { return isSystemRegister(); }576577bool isVTypeImm(unsigned N) const {578int64_t Imm;579RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;580if (!isImm())581return false;582bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);583return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None;584}585586// If the last operand of the vsetvli/vsetvli instruction is a constant587// expression, KindTy is Immediate.588bool isVTypeI10() const {589if (Kind == KindTy::Immediate)590return isVTypeImm(10);591return Kind == KindTy::VType;592}593bool isVTypeI11() const {594if (Kind == KindTy::Immediate)595return isVTypeImm(11);596return Kind == KindTy::VType;597}598599/// Return true if the operand is a valid for the fence instruction e.g.600/// ('iorw').601bool isFenceArg() const { return Kind == KindTy::Fence; }602603/// Return true if the operand is a valid floating point rounding mode.604bool isFRMArg() const { return Kind == KindTy::FRM; }605bool isFRMArgLegacy() const { return Kind == KindTy::FRM; }606bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }607608/// Return true if the operand is a valid fli.s floating-point immediate.609bool isLoadFPImm() const {610if (isImm())611return isUImm5();612if (Kind != KindTy::FPImmediate)613return false;614int Idx = RISCVLoadFPImm::getLoadFPImm(615APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));616// Don't allow decimal version of the minimum value. It is a different value617// for each supported data type.618return Idx >= 0 && Idx != 1;619}620621bool isImmXLenLI() const {622int64_t Imm;623RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;624if (!isImm())625return false;626bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);627if (VK == RISCVMCExpr::VK_RISCV_LO ||628VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||629VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||630VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO)631return true;632// Given only Imm, ensuring that the actually specified constant is either633// a signed or unsigned 64-bit number is unfortunately impossible.634if (IsConstantImm) {635return VK == RISCVMCExpr::VK_RISCV_None &&636(isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));637}638639return RISCVAsmParser::isSymbolDiff(getImm());640}641642bool isImmXLenLI_Restricted() const {643int64_t Imm;644RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;645if (!isImm())646return false;647bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);648// 'la imm' supports constant immediates only.649return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) &&650(isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));651}652653bool isUImmLog2XLen() const {654int64_t Imm;655RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;656if (!isImm())657return false;658if (!evaluateConstantImm(getImm(), Imm, VK) ||659VK != RISCVMCExpr::VK_RISCV_None)660return false;661return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);662}663664bool isUImmLog2XLenNonZero() const {665int64_t Imm;666RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;667if (!isImm())668return false;669if (!evaluateConstantImm(getImm(), Imm, VK) ||670VK != RISCVMCExpr::VK_RISCV_None)671return false;672if (Imm == 0)673return false;674return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);675}676677bool isUImmLog2XLenHalf() const {678int64_t Imm;679RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;680if (!isImm())681return false;682if (!evaluateConstantImm(getImm(), Imm, VK) ||683VK != RISCVMCExpr::VK_RISCV_None)684return false;685return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);686}687688template <unsigned N> bool IsUImm() const {689int64_t Imm;690RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;691if (!isImm())692return false;693bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);694return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;695}696697bool isUImm1() const { return IsUImm<1>(); }698bool isUImm2() const { return IsUImm<2>(); }699bool isUImm3() const { return IsUImm<3>(); }700bool isUImm4() const { return IsUImm<4>(); }701bool isUImm5() const { return IsUImm<5>(); }702bool isUImm6() const { return IsUImm<6>(); }703bool isUImm7() const { return IsUImm<7>(); }704bool isUImm8() const { return IsUImm<8>(); }705bool isUImm16() const { return IsUImm<16>(); }706bool isUImm20() const { return IsUImm<20>(); }707bool isUImm32() const { return IsUImm<32>(); }708709bool isUImm8GE32() const {710int64_t Imm;711RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;712if (!isImm())713return false;714bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);715return IsConstantImm && isUInt<8>(Imm) && Imm >= 32 &&716VK == RISCVMCExpr::VK_RISCV_None;717}718719bool isRnumArg() const {720int64_t Imm;721RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;722if (!isImm())723return false;724bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);725return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) &&726VK == RISCVMCExpr::VK_RISCV_None;727}728729bool isRnumArg_0_7() const {730int64_t Imm;731RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;732if (!isImm())733return false;734bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);735return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(7) &&736VK == RISCVMCExpr::VK_RISCV_None;737}738739bool isRnumArg_1_10() const {740int64_t Imm;741RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;742if (!isImm())743return false;744bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);745return IsConstantImm && Imm >= INT64_C(1) && Imm <= INT64_C(10) &&746VK == RISCVMCExpr::VK_RISCV_None;747}748749bool isRnumArg_2_14() const {750int64_t Imm;751RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;752if (!isImm())753return false;754bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);755return IsConstantImm && Imm >= INT64_C(2) && Imm <= INT64_C(14) &&756VK == RISCVMCExpr::VK_RISCV_None;757}758759bool isSImm5() const {760if (!isImm())761return false;762RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;763int64_t Imm;764bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);765return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&766VK == RISCVMCExpr::VK_RISCV_None;767}768769bool isSImm6() const {770if (!isImm())771return false;772RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;773int64_t Imm;774bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);775return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&776VK == RISCVMCExpr::VK_RISCV_None;777}778779bool isSImm6NonZero() const {780if (!isImm())781return false;782RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;783int64_t Imm;784bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);785return IsConstantImm && Imm != 0 &&786isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&787VK == RISCVMCExpr::VK_RISCV_None;788}789790bool isCLUIImm() const {791if (!isImm())792return false;793int64_t Imm;794RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;795bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);796return IsConstantImm && (Imm != 0) &&797(isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&798VK == RISCVMCExpr::VK_RISCV_None;799}800801bool isUImm2Lsb0() const {802if (!isImm())803return false;804int64_t Imm;805RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;806bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);807return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&808VK == RISCVMCExpr::VK_RISCV_None;809}810811bool isUImm5Lsb0() const {812if (!isImm())813return false;814int64_t Imm;815RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;816bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);817return IsConstantImm && isShiftedUInt<4, 1>(Imm) &&818VK == RISCVMCExpr::VK_RISCV_None;819}820821bool isUImm6Lsb0() const {822if (!isImm())823return false;824int64_t Imm;825RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;826bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);827return IsConstantImm && isShiftedUInt<5, 1>(Imm) &&828VK == RISCVMCExpr::VK_RISCV_None;829}830831bool isUImm7Lsb00() const {832if (!isImm())833return false;834int64_t Imm;835RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;836bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);837return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&838VK == RISCVMCExpr::VK_RISCV_None;839}840841bool isUImm8Lsb00() const {842if (!isImm())843return false;844int64_t Imm;845RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;846bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);847return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&848VK == RISCVMCExpr::VK_RISCV_None;849}850851bool isUImm8Lsb000() const {852if (!isImm())853return false;854int64_t Imm;855RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;856bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);857return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&858VK == RISCVMCExpr::VK_RISCV_None;859}860861bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }862863bool isUImm9Lsb000() const {864if (!isImm())865return false;866int64_t Imm;867RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;868bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);869return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&870VK == RISCVMCExpr::VK_RISCV_None;871}872873bool isUImm10Lsb00NonZero() const {874if (!isImm())875return false;876int64_t Imm;877RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;878bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);879return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&880VK == RISCVMCExpr::VK_RISCV_None;881}882883// If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.884// This allows writing 'addi a0, a0, 0xffffffff'.885static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {886if (IsRV64Imm || !isUInt<32>(Imm))887return Imm;888return SignExtend64<32>(Imm);889}890891bool isSImm12() const {892RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;893int64_t Imm;894bool IsValid;895if (!isImm())896return false;897bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);898if (!IsConstantImm)899IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);900else901IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));902return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||903VK == RISCVMCExpr::VK_RISCV_LO ||904VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||905VK == RISCVMCExpr::VK_RISCV_TPREL_LO ||906VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||907VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO);908}909910bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }911912bool isSImm12Lsb00000() const {913if (!isImm())914return false;915RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;916int64_t Imm;917bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);918return IsConstantImm && isShiftedInt<7, 5>(Imm) &&919VK == RISCVMCExpr::VK_RISCV_None;920}921922bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }923924bool isSImm10Lsb0000NonZero() const {925if (!isImm())926return false;927int64_t Imm;928RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;929bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);930return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&931VK == RISCVMCExpr::VK_RISCV_None;932}933934bool isUImm20LUI() const {935RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;936int64_t Imm;937bool IsValid;938if (!isImm())939return false;940bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);941if (!IsConstantImm) {942IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);943return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||944VK == RISCVMCExpr::VK_RISCV_TPREL_HI);945} else {946return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||947VK == RISCVMCExpr::VK_RISCV_HI ||948VK == RISCVMCExpr::VK_RISCV_TPREL_HI);949}950}951952bool isUImm20AUIPC() const {953RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;954int64_t Imm;955bool IsValid;956if (!isImm())957return false;958bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);959if (!IsConstantImm) {960IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);961return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||962VK == RISCVMCExpr::VK_RISCV_GOT_HI ||963VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||964VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||965VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);966}967968return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||969VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||970VK == RISCVMCExpr::VK_RISCV_GOT_HI ||971VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||972VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||973VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);974}975976bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }977978bool isImmZero() const {979if (!isImm())980return false;981int64_t Imm;982RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;983bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);984return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;985}986987bool isSImm5Plus1() const {988if (!isImm())989return false;990RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;991int64_t Imm;992bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);993return IsConstantImm &&994isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&995VK == RISCVMCExpr::VK_RISCV_None;996}997998/// getStartLoc - Gets location of the first token of this operand999SMLoc getStartLoc() const override { return StartLoc; }1000/// getEndLoc - Gets location of the last token of this operand1001SMLoc getEndLoc() const override { return EndLoc; }1002/// True if this operand is for an RV64 instruction1003bool isRV64Imm() const {1004assert(Kind == KindTy::Immediate && "Invalid type access!");1005return Imm.IsRV64;1006}10071008MCRegister getReg() const override {1009assert(Kind == KindTy::Register && "Invalid type access!");1010return Reg.RegNum;1011}10121013StringRef getSysReg() const {1014assert(Kind == KindTy::SystemRegister && "Invalid type access!");1015return StringRef(SysReg.Data, SysReg.Length);1016}10171018const MCExpr *getImm() const {1019assert(Kind == KindTy::Immediate && "Invalid type access!");1020return Imm.Val;1021}10221023uint64_t getFPConst() const {1024assert(Kind == KindTy::FPImmediate && "Invalid type access!");1025return FPImm.Val;1026}10271028StringRef getToken() const {1029assert(Kind == KindTy::Token && "Invalid type access!");1030return Tok;1031}10321033unsigned getVType() const {1034assert(Kind == KindTy::VType && "Invalid type access!");1035return VType.Val;1036}10371038RISCVFPRndMode::RoundingMode getFRM() const {1039assert(Kind == KindTy::FRM && "Invalid type access!");1040return FRM.FRM;1041}10421043unsigned getFence() const {1044assert(Kind == KindTy::Fence && "Invalid type access!");1045return Fence.Val;1046}10471048void print(raw_ostream &OS) const override {1049auto RegName = [](MCRegister Reg) {1050if (Reg)1051return RISCVInstPrinter::getRegisterName(Reg);1052else1053return "noreg";1054};10551056switch (Kind) {1057case KindTy::Immediate:1058OS << *getImm();1059break;1060case KindTy::FPImmediate:1061break;1062case KindTy::Register:1063OS << "<register " << RegName(getReg()) << ">";1064break;1065case KindTy::Token:1066OS << "'" << getToken() << "'";1067break;1068case KindTy::SystemRegister:1069OS << "<sysreg: " << getSysReg() << '>';1070break;1071case KindTy::VType:1072OS << "<vtype: ";1073RISCVVType::printVType(getVType(), OS);1074OS << '>';1075break;1076case KindTy::FRM:1077OS << "<frm: ";1078roundingModeToString(getFRM());1079OS << '>';1080break;1081case KindTy::Fence:1082OS << "<fence: ";1083OS << getFence();1084OS << '>';1085break;1086case KindTy::Rlist:1087OS << "<rlist: ";1088RISCVZC::printRlist(Rlist.Val, OS);1089OS << '>';1090break;1091case KindTy::Spimm:1092OS << "<Spimm: ";1093OS << Spimm.Val;1094OS << '>';1095break;1096case KindTy::RegReg:1097OS << "<RegReg: Reg1 " << RegName(RegReg.Reg1);1098OS << " Reg2 " << RegName(RegReg.Reg2);1099break;1100}1101}11021103static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {1104auto Op = std::make_unique<RISCVOperand>(KindTy::Token);1105Op->Tok = Str;1106Op->StartLoc = S;1107Op->EndLoc = S;1108return Op;1109}11101111static std::unique_ptr<RISCVOperand>1112createReg(unsigned RegNo, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {1113auto Op = std::make_unique<RISCVOperand>(KindTy::Register);1114Op->Reg.RegNum = RegNo;1115Op->Reg.IsGPRAsFPR = IsGPRAsFPR;1116Op->StartLoc = S;1117Op->EndLoc = E;1118return Op;1119}11201121static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,1122SMLoc E, bool IsRV64) {1123auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);1124Op->Imm.Val = Val;1125Op->Imm.IsRV64 = IsRV64;1126Op->StartLoc = S;1127Op->EndLoc = E;1128return Op;1129}11301131static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {1132auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);1133Op->FPImm.Val = Val;1134Op->StartLoc = S;1135Op->EndLoc = S;1136return Op;1137}11381139static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,1140unsigned Encoding) {1141auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);1142Op->SysReg.Data = Str.data();1143Op->SysReg.Length = Str.size();1144Op->SysReg.Encoding = Encoding;1145Op->StartLoc = S;1146Op->EndLoc = S;1147return Op;1148}11491150static std::unique_ptr<RISCVOperand>1151createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {1152auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);1153Op->FRM.FRM = FRM;1154Op->StartLoc = S;1155Op->EndLoc = S;1156return Op;1157}11581159static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {1160auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);1161Op->Fence.Val = Val;1162Op->StartLoc = S;1163Op->EndLoc = S;1164return Op;1165}11661167static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {1168auto Op = std::make_unique<RISCVOperand>(KindTy::VType);1169Op->VType.Val = VTypeI;1170Op->StartLoc = S;1171Op->EndLoc = S;1172return Op;1173}11741175static std::unique_ptr<RISCVOperand> createRlist(unsigned RlistEncode,1176SMLoc S) {1177auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);1178Op->Rlist.Val = RlistEncode;1179Op->StartLoc = S;1180return Op;1181}11821183static std::unique_ptr<RISCVOperand> createRegReg(unsigned Reg1No,1184unsigned Reg2No, SMLoc S) {1185auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);1186Op->RegReg.Reg1 = Reg1No;1187Op->RegReg.Reg2 = Reg2No;1188Op->StartLoc = S;1189Op->EndLoc = S;1190return Op;1191}11921193static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S) {1194auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);1195Op->Spimm.Val = Spimm;1196Op->StartLoc = S;1197return Op;1198}11991200static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {1201assert(Expr && "Expr shouldn't be null!");1202int64_t Imm = 0;1203RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;1204bool IsConstant = evaluateConstantImm(Expr, Imm, VK);12051206if (IsConstant)1207Inst.addOperand(1208MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));1209else1210Inst.addOperand(MCOperand::createExpr(Expr));1211}12121213// Used by the TableGen Code1214void addRegOperands(MCInst &Inst, unsigned N) const {1215assert(N == 1 && "Invalid number of operands!");1216Inst.addOperand(MCOperand::createReg(getReg()));1217}12181219void addImmOperands(MCInst &Inst, unsigned N) const {1220assert(N == 1 && "Invalid number of operands!");1221addExpr(Inst, getImm(), isRV64Imm());1222}12231224void addFPImmOperands(MCInst &Inst, unsigned N) const {1225assert(N == 1 && "Invalid number of operands!");1226if (isImm()) {1227addExpr(Inst, getImm(), isRV64Imm());1228return;1229}12301231int Imm = RISCVLoadFPImm::getLoadFPImm(1232APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));1233Inst.addOperand(MCOperand::createImm(Imm));1234}12351236void addFenceArgOperands(MCInst &Inst, unsigned N) const {1237assert(N == 1 && "Invalid number of operands!");1238Inst.addOperand(MCOperand::createImm(Fence.Val));1239}12401241void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {1242assert(N == 1 && "Invalid number of operands!");1243Inst.addOperand(MCOperand::createImm(SysReg.Encoding));1244}12451246// Support non-canonical syntax:1247// "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"1248// "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"1249void addVTypeIOperands(MCInst &Inst, unsigned N) const {1250assert(N == 1 && "Invalid number of operands!");1251int64_t Imm = 0;1252if (Kind == KindTy::Immediate) {1253RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;1254[[maybe_unused]] bool IsConstantImm =1255evaluateConstantImm(getImm(), Imm, VK);1256assert(IsConstantImm && "Invalid VTypeI Operand!");1257} else {1258Imm = getVType();1259}1260Inst.addOperand(MCOperand::createImm(Imm));1261}12621263void addRlistOperands(MCInst &Inst, unsigned N) const {1264assert(N == 1 && "Invalid number of operands!");1265Inst.addOperand(MCOperand::createImm(Rlist.Val));1266}12671268void addRegRegOperands(MCInst &Inst, unsigned N) const {1269assert(N == 2 && "Invalid number of operands!");1270Inst.addOperand(MCOperand::createReg(RegReg.Reg1));1271Inst.addOperand(MCOperand::createReg(RegReg.Reg2));1272}12731274void addSpimmOperands(MCInst &Inst, unsigned N) const {1275assert(N == 1 && "Invalid number of operands!");1276Inst.addOperand(MCOperand::createImm(Spimm.Val));1277}12781279void addFRMArgOperands(MCInst &Inst, unsigned N) const {1280assert(N == 1 && "Invalid number of operands!");1281Inst.addOperand(MCOperand::createImm(getFRM()));1282}1283};1284} // end anonymous namespace.12851286#define GET_REGISTER_MATCHER1287#define GET_SUBTARGET_FEATURE_NAME1288#define GET_MATCHER_IMPLEMENTATION1289#define GET_MNEMONIC_SPELL_CHECKER1290#include "RISCVGenAsmMatcher.inc"12911292static MCRegister convertFPR64ToFPR16(MCRegister Reg) {1293assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");1294return Reg - RISCV::F0_D + RISCV::F0_H;1295}12961297static MCRegister convertFPR64ToFPR32(MCRegister Reg) {1298assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");1299return Reg - RISCV::F0_D + RISCV::F0_F;1300}13011302static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,1303unsigned Kind) {1304unsigned RegClassID;1305if (Kind == MCK_VRM2)1306RegClassID = RISCV::VRM2RegClassID;1307else if (Kind == MCK_VRM4)1308RegClassID = RISCV::VRM4RegClassID;1309else if (Kind == MCK_VRM8)1310RegClassID = RISCV::VRM8RegClassID;1311else1312return 0;1313return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,1314&RISCVMCRegisterClasses[RegClassID]);1315}13161317unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,1318unsigned Kind) {1319RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);1320if (!Op.isReg())1321return Match_InvalidOperand;13221323MCRegister Reg = Op.getReg();1324bool IsRegFPR64 =1325RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);1326bool IsRegFPR64C =1327RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);1328bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);13291330// As the parser couldn't differentiate an FPR32 from an FPR64, coerce the1331// register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.1332if ((IsRegFPR64 && Kind == MCK_FPR32) ||1333(IsRegFPR64C && Kind == MCK_FPR32C)) {1334Op.Reg.RegNum = convertFPR64ToFPR32(Reg);1335return Match_Success;1336}1337// As the parser couldn't differentiate an FPR16 from an FPR64, coerce the1338// register from FPR64 to FPR16 if necessary.1339if (IsRegFPR64 && Kind == MCK_FPR16) {1340Op.Reg.RegNum = convertFPR64ToFPR16(Reg);1341return Match_Success;1342}1343// As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce1344// the register from VR to VRM2/VRM4/VRM8 if necessary.1345if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {1346Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);1347if (Op.Reg.RegNum == 0)1348return Match_InvalidOperand;1349return Match_Success;1350}1351return Match_InvalidOperand;1352}13531354unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst &Inst) {1355const MCInstrDesc &MCID = MII.get(Inst.getOpcode());13561357for (unsigned I = 0; I < MCID.NumOperands; ++I) {1358if (MCID.operands()[I].RegClass == RISCV::GPRPairRegClassID) {1359const auto &Op = Inst.getOperand(I);1360assert(Op.isReg());13611362MCRegister Reg = Op.getReg();1363if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(Reg))1364continue;13651366// FIXME: We should form a paired register during parsing/matching.1367if (((Reg.id() - RISCV::X0) & 1) != 0)1368return Match_RequiresEvenGPRs;1369}1370}13711372return Match_Success;1373}13741375bool RISCVAsmParser::generateImmOutOfRangeError(1376SMLoc ErrorLoc, int64_t Lower, int64_t Upper,1377const Twine &Msg = "immediate must be an integer in the range") {1378return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");1379}13801381bool RISCVAsmParser::generateImmOutOfRangeError(1382OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,1383const Twine &Msg = "immediate must be an integer in the range") {1384SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1385return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg);1386}13871388bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,1389OperandVector &Operands,1390MCStreamer &Out,1391uint64_t &ErrorInfo,1392bool MatchingInlineAsm) {1393MCInst Inst;1394FeatureBitset MissingFeatures;13951396auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,1397MatchingInlineAsm);1398switch (Result) {1399default:1400break;1401case Match_Success:1402if (validateInstruction(Inst, Operands))1403return true;1404return processInstruction(Inst, IDLoc, Operands, Out);1405case Match_MissingFeature: {1406assert(MissingFeatures.any() && "Unknown missing features!");1407bool FirstFeature = true;1408std::string Msg = "instruction requires the following:";1409for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {1410if (MissingFeatures[i]) {1411Msg += FirstFeature ? " " : ", ";1412Msg += getSubtargetFeatureName(i);1413FirstFeature = false;1414}1415}1416return Error(IDLoc, Msg);1417}1418case Match_MnemonicFail: {1419FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());1420std::string Suggestion = RISCVMnemonicSpellCheck(1421((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);1422return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);1423}1424case Match_InvalidOperand: {1425SMLoc ErrorLoc = IDLoc;1426if (ErrorInfo != ~0ULL) {1427if (ErrorInfo >= Operands.size())1428return Error(ErrorLoc, "too few operands for instruction");14291430ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1431if (ErrorLoc == SMLoc())1432ErrorLoc = IDLoc;1433}1434return Error(ErrorLoc, "invalid operand for instruction");1435}1436}14371438// Handle the case when the error message is of specific type1439// other than the generic Match_InvalidOperand, and the1440// corresponding operand is missing.1441if (Result > FIRST_TARGET_MATCH_RESULT_TY) {1442SMLoc ErrorLoc = IDLoc;1443if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())1444return Error(ErrorLoc, "too few operands for instruction");1445}14461447switch (Result) {1448default:1449break;1450case Match_RequiresEvenGPRs:1451return Error(IDLoc,1452"double precision floating point operands must use even "1453"numbered X register");1454case Match_InvalidImmXLenLI:1455if (isRV64()) {1456SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1457return Error(ErrorLoc, "operand must be a constant 64-bit integer");1458}1459return generateImmOutOfRangeError(Operands, ErrorInfo,1460std::numeric_limits<int32_t>::min(),1461std::numeric_limits<uint32_t>::max());1462case Match_InvalidImmXLenLI_Restricted:1463if (isRV64()) {1464SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1465return Error(ErrorLoc, "operand either must be a constant 64-bit integer "1466"or a bare symbol name");1467}1468return generateImmOutOfRangeError(1469Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),1470std::numeric_limits<uint32_t>::max(),1471"operand either must be a bare symbol name or an immediate integer in "1472"the range");1473case Match_InvalidImmZero: {1474SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1475return Error(ErrorLoc, "immediate must be zero");1476}1477case Match_InvalidUImmLog2XLen:1478if (isRV64())1479return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);1480return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);1481case Match_InvalidUImmLog2XLenNonZero:1482if (isRV64())1483return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);1484return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);1485case Match_InvalidUImmLog2XLenHalf:1486if (isRV64())1487return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);1488return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);1489case Match_InvalidUImm1:1490return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);1491case Match_InvalidUImm2:1492return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);1493case Match_InvalidUImm2Lsb0:1494return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,1495"immediate must be one of");1496case Match_InvalidUImm3:1497return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);1498case Match_InvalidUImm4:1499return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);1500case Match_InvalidUImm5:1501return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);1502case Match_InvalidUImm6:1503return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);1504case Match_InvalidUImm7:1505return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);1506case Match_InvalidUImm8:1507return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);1508case Match_InvalidUImm8GE32:1509return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1);1510case Match_InvalidSImm5:1511return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),1512(1 << 4) - 1);1513case Match_InvalidSImm6:1514return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),1515(1 << 5) - 1);1516case Match_InvalidSImm6NonZero:1517return generateImmOutOfRangeError(1518Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,1519"immediate must be non-zero in the range");1520case Match_InvalidCLUIImm:1521return generateImmOutOfRangeError(1522Operands, ErrorInfo, 1, (1 << 5) - 1,1523"immediate must be in [0xfffe0, 0xfffff] or");1524case Match_InvalidUImm5Lsb0:1525return generateImmOutOfRangeError(1526Operands, ErrorInfo, 0, (1 << 5) - 2,1527"immediate must be a multiple of 2 bytes in the range");1528case Match_InvalidUImm6Lsb0:1529return generateImmOutOfRangeError(1530Operands, ErrorInfo, 0, (1 << 6) - 2,1531"immediate must be a multiple of 2 bytes in the range");1532case Match_InvalidUImm7Lsb00:1533return generateImmOutOfRangeError(1534Operands, ErrorInfo, 0, (1 << 7) - 4,1535"immediate must be a multiple of 4 bytes in the range");1536case Match_InvalidUImm8Lsb00:1537return generateImmOutOfRangeError(1538Operands, ErrorInfo, 0, (1 << 8) - 4,1539"immediate must be a multiple of 4 bytes in the range");1540case Match_InvalidUImm8Lsb000:1541return generateImmOutOfRangeError(1542Operands, ErrorInfo, 0, (1 << 8) - 8,1543"immediate must be a multiple of 8 bytes in the range");1544case Match_InvalidSImm9Lsb0:1545return generateImmOutOfRangeError(1546Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,1547"immediate must be a multiple of 2 bytes in the range");1548case Match_InvalidUImm9Lsb000:1549return generateImmOutOfRangeError(1550Operands, ErrorInfo, 0, (1 << 9) - 8,1551"immediate must be a multiple of 8 bytes in the range");1552case Match_InvalidUImm10Lsb00NonZero:1553return generateImmOutOfRangeError(1554Operands, ErrorInfo, 4, (1 << 10) - 4,1555"immediate must be a multiple of 4 bytes in the range");1556case Match_InvalidSImm10Lsb0000NonZero:1557return generateImmOutOfRangeError(1558Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,1559"immediate must be a multiple of 16 bytes and non-zero in the range");1560case Match_InvalidSImm12:1561return generateImmOutOfRangeError(1562Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,1563"operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "1564"integer in the range");1565case Match_InvalidSImm12Lsb0:1566return generateImmOutOfRangeError(1567Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,1568"immediate must be a multiple of 2 bytes in the range");1569case Match_InvalidSImm12Lsb00000:1570return generateImmOutOfRangeError(1571Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,1572"immediate must be a multiple of 32 bytes in the range");1573case Match_InvalidSImm13Lsb0:1574return generateImmOutOfRangeError(1575Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,1576"immediate must be a multiple of 2 bytes in the range");1577case Match_InvalidUImm20LUI:1578return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,1579"operand must be a symbol with "1580"%hi/%tprel_hi modifier or an integer in "1581"the range");1582case Match_InvalidUImm20:1583return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);1584case Match_InvalidUImm20AUIPC:1585return generateImmOutOfRangeError(1586Operands, ErrorInfo, 0, (1 << 20) - 1,1587"operand must be a symbol with a "1588"%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "1589"an integer in the range");1590case Match_InvalidSImm21Lsb0JAL:1591return generateImmOutOfRangeError(1592Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,1593"immediate must be a multiple of 2 bytes in the range");1594case Match_InvalidCSRSystemRegister: {1595return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,1596"operand must be a valid system register "1597"name or an integer in the range");1598}1599case Match_InvalidLoadFPImm: {1600SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1601return Error(ErrorLoc, "operand must be a valid floating-point constant");1602}1603case Match_InvalidBareSymbol: {1604SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1605return Error(ErrorLoc, "operand must be a bare symbol name");1606}1607case Match_InvalidPseudoJumpSymbol: {1608SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1609return Error(ErrorLoc, "operand must be a valid jump target");1610}1611case Match_InvalidCallSymbol: {1612SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1613return Error(ErrorLoc, "operand must be a bare symbol name");1614}1615case Match_InvalidTPRelAddSymbol: {1616SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1617return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");1618}1619case Match_InvalidTLSDESCCallSymbol: {1620SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1621return Error(ErrorLoc,1622"operand must be a symbol with %tlsdesc_call modifier");1623}1624case Match_InvalidRTZArg: {1625SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1626return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode");1627}1628case Match_InvalidVTypeI: {1629SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1630return generateVTypeError(ErrorLoc);1631}1632case Match_InvalidVMaskRegister: {1633SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1634return Error(ErrorLoc, "operand must be v0.t");1635}1636case Match_InvalidSImm5Plus1: {1637return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,1638(1 << 4),1639"immediate must be in the range");1640}1641case Match_InvalidRlist: {1642SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1643return Error(1644ErrorLoc,1645"operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");1646}1647case Match_InvalidStackAdj: {1648SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1649return Error(1650ErrorLoc,1651"stack adjustment is invalid for this instruction and register list; "1652"refer to Zc spec for a detailed range of stack adjustment");1653}1654case Match_InvalidRnumArg: {1655return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);1656}1657case Match_InvalidRegReg: {1658SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1659return Error(ErrorLoc, "operands must be register and register");1660}1661}16621663llvm_unreachable("Unknown match type detected!");1664}16651666// Attempts to match Name as a register (either using the default name or1667// alternative ABI names), setting RegNo to the matching register. Upon1668// failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x311669// will be rejected.1670MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {1671MCRegister Reg = MatchRegisterName(Name);1672// The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial1673// match always matches the 64-bit variant, and not the 16/32-bit one.1674assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));1675assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));1676// The default FPR register class is based on the tablegen enum ordering.1677static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");1678static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");1679if (!Reg)1680Reg = MatchRegisterAltName(Name);1681if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)1682Reg = RISCV::NoRegister;1683return Reg;1684}16851686bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,1687SMLoc &EndLoc) {1688if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())1689return Error(StartLoc, "invalid register name");1690return false;1691}16921693ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,1694SMLoc &EndLoc) {1695const AsmToken &Tok = getParser().getTok();1696StartLoc = Tok.getLoc();1697EndLoc = Tok.getEndLoc();1698StringRef Name = getLexer().getTok().getIdentifier();16991700Reg = matchRegisterNameHelper(Name);1701if (!Reg)1702return ParseStatus::NoMatch;17031704getParser().Lex(); // Eat identifier token.1705return ParseStatus::Success;1706}17071708ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,1709bool AllowParens) {1710SMLoc FirstS = getLoc();1711bool HadParens = false;1712AsmToken LParen;17131714// If this is an LParen and a parenthesised register name is allowed, parse it1715// atomically.1716if (AllowParens && getLexer().is(AsmToken::LParen)) {1717AsmToken Buf[2];1718size_t ReadCount = getLexer().peekTokens(Buf);1719if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {1720HadParens = true;1721LParen = getParser().getTok();1722getParser().Lex(); // Eat '('1723}1724}17251726switch (getLexer().getKind()) {1727default:1728if (HadParens)1729getLexer().UnLex(LParen);1730return ParseStatus::NoMatch;1731case AsmToken::Identifier:1732StringRef Name = getLexer().getTok().getIdentifier();1733MCRegister RegNo = matchRegisterNameHelper(Name);17341735if (!RegNo) {1736if (HadParens)1737getLexer().UnLex(LParen);1738return ParseStatus::NoMatch;1739}1740if (HadParens)1741Operands.push_back(RISCVOperand::createToken("(", FirstS));1742SMLoc S = getLoc();1743SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());1744getLexer().Lex();1745Operands.push_back(RISCVOperand::createReg(RegNo, S, E));1746}17471748if (HadParens) {1749getParser().Lex(); // Eat ')'1750Operands.push_back(RISCVOperand::createToken(")", getLoc()));1751}17521753return ParseStatus::Success;1754}17551756ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {1757SMLoc S = getLoc();1758SMLoc E;1759const MCExpr *Res;17601761switch (getLexer().getKind()) {1762default:1763return ParseStatus::NoMatch;1764case AsmToken::LParen:1765case AsmToken::Minus:1766case AsmToken::Plus:1767case AsmToken::Exclaim:1768case AsmToken::Tilde:1769case AsmToken::Integer:1770case AsmToken::String: {1771if (getParser().parseExpression(Res, E))1772return ParseStatus::Failure;17731774auto *CE = dyn_cast<MCConstantExpr>(Res);1775if (CE) {1776int64_t Imm = CE->getValue();1777if (isUInt<7>(Imm)) {1778Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));1779return ParseStatus::Success;1780}1781}17821783break;1784}1785case AsmToken::Identifier: {1786StringRef Identifier;1787if (getParser().parseIdentifier(Identifier))1788return ParseStatus::Failure;17891790auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);1791if (Opcode) {1792assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&1793"Unexpected opcode");1794Res = MCConstantExpr::create(Opcode->Value, getContext());1795E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());1796Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));1797return ParseStatus::Success;1798}17991800break;1801}1802case AsmToken::Percent:1803break;1804}18051806return generateImmOutOfRangeError(1807S, 0, 127,1808"opcode must be a valid opcode name or an immediate in the range");1809}18101811ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {1812SMLoc S = getLoc();1813SMLoc E;1814const MCExpr *Res;18151816switch (getLexer().getKind()) {1817default:1818return ParseStatus::NoMatch;1819case AsmToken::LParen:1820case AsmToken::Minus:1821case AsmToken::Plus:1822case AsmToken::Exclaim:1823case AsmToken::Tilde:1824case AsmToken::Integer:1825case AsmToken::String: {1826if (getParser().parseExpression(Res, E))1827return ParseStatus::Failure;18281829auto *CE = dyn_cast<MCConstantExpr>(Res);1830if (CE) {1831int64_t Imm = CE->getValue();1832if (Imm >= 0 && Imm <= 2) {1833Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));1834return ParseStatus::Success;1835}1836}18371838break;1839}1840case AsmToken::Identifier: {1841StringRef Identifier;1842if (getParser().parseIdentifier(Identifier))1843return ParseStatus::Failure;18441845unsigned Opcode;1846if (Identifier == "C0")1847Opcode = 0;1848else if (Identifier == "C1")1849Opcode = 1;1850else if (Identifier == "C2")1851Opcode = 2;1852else1853break;18541855Res = MCConstantExpr::create(Opcode, getContext());1856E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());1857Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));1858return ParseStatus::Success;1859}1860case AsmToken::Percent: {1861// Discard operand with modifier.1862break;1863}1864}18651866return generateImmOutOfRangeError(1867S, 0, 2,1868"opcode must be a valid opcode name or an immediate in the range");1869}18701871ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {1872SMLoc S = getLoc();1873const MCExpr *Res;18741875switch (getLexer().getKind()) {1876default:1877return ParseStatus::NoMatch;1878case AsmToken::LParen:1879case AsmToken::Minus:1880case AsmToken::Plus:1881case AsmToken::Exclaim:1882case AsmToken::Tilde:1883case AsmToken::Integer:1884case AsmToken::String: {1885if (getParser().parseExpression(Res))1886return ParseStatus::Failure;18871888auto *CE = dyn_cast<MCConstantExpr>(Res);1889if (CE) {1890int64_t Imm = CE->getValue();1891if (isUInt<12>(Imm)) {1892auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);1893// Accept an immediate representing a named Sys Reg if it satisfies the1894// the required features.1895for (auto &Reg : Range) {1896if (Reg.haveRequiredFeatures(STI->getFeatureBits())) {1897Operands.push_back(RISCVOperand::createSysReg(Reg.Name, S, Imm));1898return ParseStatus::Success;1899}1900}1901// Accept an immediate representing an un-named Sys Reg if the range is1902// valid, regardless of the required features.1903Operands.push_back(RISCVOperand::createSysReg("", S, Imm));1904return ParseStatus::Success;1905}1906}19071908return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);1909}1910case AsmToken::Identifier: {1911StringRef Identifier;1912if (getParser().parseIdentifier(Identifier))1913return ParseStatus::Failure;19141915auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);1916if (!SysReg)1917SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);1918if (!SysReg)1919if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))1920Warning(S, "'" + Identifier + "' is a deprecated alias for '" +1921SysReg->Name + "'");19221923// Accept a named Sys Reg if the required features are present.1924if (SysReg) {1925if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits()))1926return Error(S, "system register use requires an option to be enabled");1927Operands.push_back(1928RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));1929return ParseStatus::Success;1930}19311932return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,1933"operand must be a valid system register "1934"name or an integer in the range");1935}1936case AsmToken::Percent: {1937// Discard operand with modifier.1938return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);1939}1940}19411942return ParseStatus::NoMatch;1943}19441945ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {1946SMLoc S = getLoc();19471948// Parse special floats (inf/nan/min) representation.1949if (getTok().is(AsmToken::Identifier)) {1950StringRef Identifier = getTok().getIdentifier();1951if (Identifier.compare_insensitive("inf") == 0) {1952Operands.push_back(1953RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,1954getTok().getEndLoc(), isRV64()));1955} else if (Identifier.compare_insensitive("nan") == 0) {1956Operands.push_back(1957RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,1958getTok().getEndLoc(), isRV64()));1959} else if (Identifier.compare_insensitive("min") == 0) {1960Operands.push_back(1961RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S,1962getTok().getEndLoc(), isRV64()));1963} else {1964return TokError("invalid floating point literal");1965}19661967Lex(); // Eat the token.19681969return ParseStatus::Success;1970}19711972// Handle negation, as that still comes through as a separate token.1973bool IsNegative = parseOptionalToken(AsmToken::Minus);19741975const AsmToken &Tok = getTok();1976if (!Tok.is(AsmToken::Real))1977return TokError("invalid floating point immediate");19781979// Parse FP representation.1980APFloat RealVal(APFloat::IEEEdouble());1981auto StatusOrErr =1982RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);1983if (errorToBool(StatusOrErr.takeError()))1984return TokError("invalid floating point representation");19851986if (IsNegative)1987RealVal.changeSign();19881989Operands.push_back(RISCVOperand::createFPImm(1990RealVal.bitcastToAPInt().getZExtValue(), S));19911992Lex(); // Eat the token.19931994return ParseStatus::Success;1995}19961997ParseStatus RISCVAsmParser::parseImmediate(OperandVector &Operands) {1998SMLoc S = getLoc();1999SMLoc E;2000const MCExpr *Res;20012002switch (getLexer().getKind()) {2003default:2004return ParseStatus::NoMatch;2005case AsmToken::LParen:2006case AsmToken::Dot:2007case AsmToken::Minus:2008case AsmToken::Plus:2009case AsmToken::Exclaim:2010case AsmToken::Tilde:2011case AsmToken::Integer:2012case AsmToken::String:2013case AsmToken::Identifier:2014if (getParser().parseExpression(Res, E))2015return ParseStatus::Failure;2016break;2017case AsmToken::Percent:2018return parseOperandWithModifier(Operands);2019}20202021Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));2022return ParseStatus::Success;2023}20242025ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {2026SMLoc S = getLoc();2027SMLoc E;20282029if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))2030return ParseStatus::Failure;20312032if (getLexer().getKind() != AsmToken::Identifier)2033return Error(getLoc(), "expected valid identifier for operand modifier");2034StringRef Identifier = getParser().getTok().getIdentifier();2035RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);2036if (VK == RISCVMCExpr::VK_RISCV_Invalid)2037return Error(getLoc(), "unrecognized operand modifier");20382039getParser().Lex(); // Eat the identifier2040if (parseToken(AsmToken::LParen, "expected '('"))2041return ParseStatus::Failure;20422043const MCExpr *SubExpr;2044if (getParser().parseParenExpression(SubExpr, E))2045return ParseStatus::Failure;20462047const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());2048Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));2049return ParseStatus::Success;2050}20512052ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {2053SMLoc S = getLoc();2054const MCExpr *Res;20552056if (getLexer().getKind() != AsmToken::Identifier)2057return ParseStatus::NoMatch;20582059StringRef Identifier;2060AsmToken Tok = getLexer().getTok();20612062if (getParser().parseIdentifier(Identifier))2063return ParseStatus::Failure;20642065SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());20662067if (Identifier.consume_back("@plt"))2068return Error(getLoc(), "'@plt' operand not valid for instruction");20692070MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);20712072if (Sym->isVariable()) {2073const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);2074if (!isa<MCSymbolRefExpr>(V)) {2075getLexer().UnLex(Tok); // Put back if it's not a bare symbol.2076return ParseStatus::NoMatch;2077}2078Res = V;2079} else2080Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());20812082MCBinaryExpr::Opcode Opcode;2083switch (getLexer().getKind()) {2084default:2085Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));2086return ParseStatus::Success;2087case AsmToken::Plus:2088Opcode = MCBinaryExpr::Add;2089getLexer().Lex();2090break;2091case AsmToken::Minus:2092Opcode = MCBinaryExpr::Sub;2093getLexer().Lex();2094break;2095}20962097const MCExpr *Expr;2098if (getParser().parseExpression(Expr, E))2099return ParseStatus::Failure;2100Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());2101Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));2102return ParseStatus::Success;2103}21042105ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {2106SMLoc S = getLoc();2107const MCExpr *Res;21082109if (getLexer().getKind() != AsmToken::Identifier)2110return ParseStatus::NoMatch;21112112// Avoid parsing the register in `call rd, foo` as a call symbol.2113if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)2114return ParseStatus::NoMatch;21152116StringRef Identifier;2117if (getParser().parseIdentifier(Identifier))2118return ParseStatus::Failure;21192120SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());21212122RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;2123(void)Identifier.consume_back("@plt");21242125MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);2126Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());2127Res = RISCVMCExpr::create(Res, Kind, getContext());2128Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));2129return ParseStatus::Success;2130}21312132ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {2133SMLoc S = getLoc();2134SMLoc E;2135const MCExpr *Res;21362137if (getParser().parseExpression(Res, E))2138return ParseStatus::Failure;21392140if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||2141cast<MCSymbolRefExpr>(Res)->getKind() ==2142MCSymbolRefExpr::VariantKind::VK_PLT)2143return Error(S, "operand must be a valid jump target");21442145Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());2146Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));2147return ParseStatus::Success;2148}21492150ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {2151// Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`2152// both being acceptable forms. When parsing `jal ra, foo` this function2153// will be called for the `ra` register operand in an attempt to match the2154// single-operand alias. parseJALOffset must fail for this case. It would2155// seem logical to try parse the operand using parseImmediate and return2156// NoMatch if the next token is a comma (meaning we must be parsing a jal in2157// the second form rather than the first). We can't do this as there's no2158// way of rewinding the lexer state. Instead, return NoMatch if this operand2159// is an identifier and is followed by a comma.2160if (getLexer().is(AsmToken::Identifier) &&2161getLexer().peekTok().is(AsmToken::Comma))2162return ParseStatus::NoMatch;21632164return parseImmediate(Operands);2165}21662167bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,2168unsigned &Sew, unsigned &Lmul,2169bool &Fractional, bool &TailAgnostic,2170bool &MaskAgnostic) {2171if (Tok.isNot(AsmToken::Identifier))2172return true;21732174StringRef Identifier = Tok.getIdentifier();21752176switch (State) {2177case VTypeState_SEW:2178if (!Identifier.consume_front("e"))2179break;2180if (Identifier.getAsInteger(10, Sew))2181break;2182if (!RISCVVType::isValidSEW(Sew))2183break;2184State = VTypeState_LMUL;2185return false;2186case VTypeState_LMUL: {2187if (!Identifier.consume_front("m"))2188break;2189Fractional = Identifier.consume_front("f");2190if (Identifier.getAsInteger(10, Lmul))2191break;2192if (!RISCVVType::isValidLMUL(Lmul, Fractional))2193break;21942195if (Fractional) {2196unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;2197unsigned MinLMUL = ELEN / 8;2198if (Lmul > MinLMUL)2199Warning(Tok.getLoc(),2200"use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +2201Twine(MinLMUL) + " is reserved");2202}22032204State = VTypeState_TailPolicy;2205return false;2206}2207case VTypeState_TailPolicy:2208if (Identifier == "ta")2209TailAgnostic = true;2210else if (Identifier == "tu")2211TailAgnostic = false;2212else2213break;2214State = VTypeState_MaskPolicy;2215return false;2216case VTypeState_MaskPolicy:2217if (Identifier == "ma")2218MaskAgnostic = true;2219else if (Identifier == "mu")2220MaskAgnostic = false;2221else2222break;2223State = VTypeState_Done;2224return false;2225case VTypeState_Done:2226// Extra token?2227break;2228}22292230return true;2231}22322233ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {2234SMLoc S = getLoc();22352236unsigned Sew = 0;2237unsigned Lmul = 0;2238bool Fractional = false;2239bool TailAgnostic = false;2240bool MaskAgnostic = false;22412242VTypeState State = VTypeState_SEW;2243SMLoc SEWLoc = S;22442245if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,2246MaskAgnostic))2247return ParseStatus::NoMatch;22482249getLexer().Lex();22502251while (parseOptionalToken(AsmToken::Comma)) {2252if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,2253MaskAgnostic))2254break;22552256getLexer().Lex();2257}22582259if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) {2260RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);2261if (Fractional) {2262unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;2263unsigned MaxSEW = ELEN / Lmul;2264// If MaxSEW < 8, we should have printed warning about reserved LMUL.2265if (MaxSEW >= 8 && Sew > MaxSEW)2266Warning(SEWLoc,2267"use of vtype encodings with SEW > " + Twine(MaxSEW) +2268" and LMUL == mf" + Twine(Lmul) +2269" may not be compatible with all RVV implementations");2270}22712272unsigned VTypeI =2273RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);2274Operands.push_back(RISCVOperand::createVType(VTypeI, S));2275return ParseStatus::Success;2276}22772278return generateVTypeError(S);2279}22802281bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {2282return Error(2283ErrorLoc,2284"operand must be "2285"e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");2286}22872288ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {2289if (getLexer().isNot(AsmToken::Identifier))2290return ParseStatus::NoMatch;22912292StringRef Name = getLexer().getTok().getIdentifier();2293if (!Name.consume_back(".t"))2294return Error(getLoc(), "expected '.t' suffix");2295MCRegister RegNo = matchRegisterNameHelper(Name);22962297if (!RegNo)2298return ParseStatus::NoMatch;2299if (RegNo != RISCV::V0)2300return ParseStatus::NoMatch;2301SMLoc S = getLoc();2302SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());2303getLexer().Lex();2304Operands.push_back(RISCVOperand::createReg(RegNo, S, E));2305return ParseStatus::Success;2306}23072308ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {2309if (getLexer().isNot(AsmToken::Identifier))2310return ParseStatus::NoMatch;23112312StringRef Name = getLexer().getTok().getIdentifier();2313MCRegister RegNo = matchRegisterNameHelper(Name);23142315if (!RegNo)2316return ParseStatus::NoMatch;2317SMLoc S = getLoc();2318SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());2319getLexer().Lex();2320Operands.push_back(RISCVOperand::createReg(2321RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));2322return ParseStatus::Success;2323}23242325template <bool IsRV64>2326ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {2327return parseGPRPair(Operands, IsRV64);2328}23292330ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,2331bool IsRV64Inst) {2332// If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on2333// RV64 as it will prevent matching the RV64 version of the same instruction2334// that doesn't use a GPRPair.2335// If this is an RV64 GPRPair instruction, there is no RV32 version so we can2336// still parse as a pair.2337if (!IsRV64Inst && isRV64())2338return ParseStatus::NoMatch;23392340if (getLexer().isNot(AsmToken::Identifier))2341return ParseStatus::NoMatch;23422343StringRef Name = getLexer().getTok().getIdentifier();2344MCRegister RegNo = matchRegisterNameHelper(Name);23452346if (!RegNo)2347return ParseStatus::NoMatch;23482349if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(RegNo))2350return ParseStatus::NoMatch;23512352if ((RegNo - RISCV::X0) & 1)2353return TokError("register must be even");23542355SMLoc S = getLoc();2356SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());2357getLexer().Lex();23582359const MCRegisterInfo *RI = getContext().getRegisterInfo();2360unsigned Pair = RI->getMatchingSuperReg(2361RegNo, RISCV::sub_gpr_even,2362&RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);2363Operands.push_back(RISCVOperand::createReg(Pair, S, E));2364return ParseStatus::Success;2365}23662367ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {2368if (getLexer().isNot(AsmToken::Identifier))2369return TokError(2370"operand must be a valid floating point rounding mode mnemonic");23712372StringRef Str = getLexer().getTok().getIdentifier();2373RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str);23742375if (FRM == RISCVFPRndMode::Invalid)2376return TokError(2377"operand must be a valid floating point rounding mode mnemonic");23782379Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));2380Lex(); // Eat identifier token.2381return ParseStatus::Success;2382}23832384ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {2385const AsmToken &Tok = getLexer().getTok();23862387if (Tok.is(AsmToken::Integer)) {2388if (Tok.getIntVal() != 0)2389goto ParseFail;23902391Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));2392Lex();2393return ParseStatus::Success;2394}23952396if (Tok.is(AsmToken::Identifier)) {2397StringRef Str = Tok.getIdentifier();23982399// Letters must be unique, taken from 'iorw', and in ascending order. This2400// holds as long as each individual character is one of 'iorw' and is2401// greater than the previous character.2402unsigned Imm = 0;2403bool Valid = true;2404char Prev = '\0';2405for (char c : Str) {2406switch (c) {2407default:2408Valid = false;2409break;2410case 'i':2411Imm |= RISCVFenceField::I;2412break;2413case 'o':2414Imm |= RISCVFenceField::O;2415break;2416case 'r':2417Imm |= RISCVFenceField::R;2418break;2419case 'w':2420Imm |= RISCVFenceField::W;2421break;2422}24232424if (c <= Prev) {2425Valid = false;2426break;2427}2428Prev = c;2429}24302431if (!Valid)2432goto ParseFail;24332434Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));2435Lex();2436return ParseStatus::Success;2437}24382439ParseFail:2440return TokError("operand must be formed of letters selected in-order from "2441"'iorw' or be 0");2442}24432444ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {2445if (parseToken(AsmToken::LParen, "expected '('"))2446return ParseStatus::Failure;2447Operands.push_back(RISCVOperand::createToken("(", getLoc()));24482449if (!parseRegister(Operands).isSuccess())2450return Error(getLoc(), "expected register");24512452if (parseToken(AsmToken::RParen, "expected ')'"))2453return ParseStatus::Failure;2454Operands.push_back(RISCVOperand::createToken(")", getLoc()));24552456return ParseStatus::Success;2457}24582459ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {2460// Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"2461// as one of their register operands, such as `(a0)`. This just denotes that2462// the register (in this case `a0`) contains a memory address.2463//2464// Normally, we would be able to parse these by putting the parens into the2465// instruction string. However, GNU as also accepts a zero-offset memory2466// operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed2467// with parseImmediate followed by parseMemOpBaseReg, but these instructions2468// do not accept an immediate operand, and we do not want to add a "dummy"2469// operand that is silently dropped.2470//2471// Instead, we use this custom parser. This will: allow (and discard) an2472// offset if it is zero; require (and discard) parentheses; and add only the2473// parsed register operand to `Operands`.2474//2475// These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,2476// which will only print the register surrounded by parentheses (which GNU as2477// also uses as its canonical representation for these operands).2478std::unique_ptr<RISCVOperand> OptionalImmOp;24792480if (getLexer().isNot(AsmToken::LParen)) {2481// Parse an Integer token. We do not accept arbritrary constant expressions2482// in the offset field (because they may include parens, which complicates2483// parsing a lot).2484int64_t ImmVal;2485SMLoc ImmStart = getLoc();2486if (getParser().parseIntToken(ImmVal,2487"expected '(' or optional integer offset"))2488return ParseStatus::Failure;24892490// Create a RISCVOperand for checking later (so the error messages are2491// nicer), but we don't add it to Operands.2492SMLoc ImmEnd = getLoc();2493OptionalImmOp =2494RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),2495ImmStart, ImmEnd, isRV64());2496}24972498if (parseToken(AsmToken::LParen,2499OptionalImmOp ? "expected '(' after optional integer offset"2500: "expected '(' or optional integer offset"))2501return ParseStatus::Failure;25022503if (!parseRegister(Operands).isSuccess())2504return Error(getLoc(), "expected register");25052506if (parseToken(AsmToken::RParen, "expected ')'"))2507return ParseStatus::Failure;25082509// Deferred Handling of non-zero offsets. This makes the error messages nicer.2510if (OptionalImmOp && !OptionalImmOp->isImmZero())2511return Error(2512OptionalImmOp->getStartLoc(), "optional integer offset must be 0",2513SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));25142515return ParseStatus::Success;2516}25172518ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {2519// RR : a2(a1)2520if (getLexer().getKind() != AsmToken::Identifier)2521return ParseStatus::NoMatch;25222523StringRef RegName = getLexer().getTok().getIdentifier();2524MCRegister Reg = matchRegisterNameHelper(RegName);2525if (!Reg)2526return Error(getLoc(), "invalid register");2527getLexer().Lex();25282529if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))2530return ParseStatus::Failure;25312532if (getLexer().getKind() != AsmToken::Identifier)2533return Error(getLoc(), "expected register");25342535StringRef Reg2Name = getLexer().getTok().getIdentifier();2536MCRegister Reg2 = matchRegisterNameHelper(Reg2Name);2537if (!Reg2)2538return Error(getLoc(), "invalid register");2539getLexer().Lex();25402541if (parseToken(AsmToken::RParen, "expected ')'"))2542return ParseStatus::Failure;25432544Operands.push_back(RISCVOperand::createRegReg(Reg, Reg2, getLoc()));25452546return ParseStatus::Success;2547}25482549ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {2550// Rlist: {ra [, s0[-sN]]}2551// XRlist: {x1 [, x8[-x9][, x18[-xN]]]}2552SMLoc S = getLoc();25532554if (parseToken(AsmToken::LCurly, "register list must start with '{'"))2555return ParseStatus::Failure;25562557bool IsEABI = isRVE();25582559if (getLexer().isNot(AsmToken::Identifier))2560return Error(getLoc(), "register list must start from 'ra' or 'x1'");25612562StringRef RegName = getLexer().getTok().getIdentifier();2563MCRegister RegStart = matchRegisterNameHelper(RegName);2564MCRegister RegEnd;2565if (RegStart != RISCV::X1)2566return Error(getLoc(), "register list must start from 'ra' or 'x1'");2567getLexer().Lex();25682569// parse case like ,s02570if (parseOptionalToken(AsmToken::Comma)) {2571if (getLexer().isNot(AsmToken::Identifier))2572return Error(getLoc(), "invalid register");2573StringRef RegName = getLexer().getTok().getIdentifier();2574RegStart = matchRegisterNameHelper(RegName);2575if (!RegStart)2576return Error(getLoc(), "invalid register");2577if (RegStart != RISCV::X8)2578return Error(getLoc(),2579"continuous register list must start from 's0' or 'x8'");2580getLexer().Lex(); // eat reg2581}25822583// parse case like -s12584if (parseOptionalToken(AsmToken::Minus)) {2585StringRef EndName = getLexer().getTok().getIdentifier();2586// FIXME: the register mapping and checks of EABI is wrong2587RegEnd = matchRegisterNameHelper(EndName);2588if (!RegEnd)2589return Error(getLoc(), "invalid register");2590if (IsEABI && RegEnd != RISCV::X9)2591return Error(getLoc(), "contiguous register list of EABI can only be "2592"'s0-s1' or 'x8-x9' pair");2593getLexer().Lex();2594}25952596if (!IsEABI) {2597// parse extra part like ', x18[-x20]' for XRegList2598if (parseOptionalToken(AsmToken::Comma)) {2599if (RegEnd != RISCV::X9)2600return Error(2601getLoc(),2602"first contiguous registers pair of register list must be 'x8-x9'");26032604// parse ', x18' for extra part2605if (getLexer().isNot(AsmToken::Identifier))2606return Error(getLoc(), "invalid register");2607StringRef EndName = getLexer().getTok().getIdentifier();2608if (MatchRegisterName(EndName) != RISCV::X18)2609return Error(getLoc(),2610"second contiguous registers pair of register list "2611"must start from 'x18'");2612getLexer().Lex();26132614// parse '-x20' for extra part2615if (parseOptionalToken(AsmToken::Minus)) {2616if (getLexer().isNot(AsmToken::Identifier))2617return Error(getLoc(), "invalid register");2618EndName = getLexer().getTok().getIdentifier();2619if (MatchRegisterName(EndName) == RISCV::NoRegister)2620return Error(getLoc(), "invalid register");2621getLexer().Lex();2622}2623RegEnd = MatchRegisterName(EndName);2624}2625}26262627if (RegEnd == RISCV::X26)2628return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "2629"x18-x26} is not supported");26302631if (parseToken(AsmToken::RCurly, "register list must end with '}'"))2632return ParseStatus::Failure;26332634if (RegEnd == RISCV::NoRegister)2635RegEnd = RegStart;26362637auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);2638if (Encode == RISCVZC::INVALID_RLIST)2639return Error(S, "invalid register list");2640Operands.push_back(RISCVOperand::createRlist(Encode, S));26412642return ParseStatus::Success;2643}26442645ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,2646bool ExpectNegative) {2647bool Negative = parseOptionalToken(AsmToken::Minus);26482649SMLoc S = getLoc();2650int64_t StackAdjustment = getLexer().getTok().getIntVal();2651unsigned Spimm = 0;2652unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;26532654if (Negative != ExpectNegative ||2655!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64()))2656return ParseStatus::NoMatch;2657Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));2658getLexer().Lex();2659return ParseStatus::Success;2660}26612662/// Looks at a token type and creates the relevant operand from this2663/// information, adding to Operands. If operand was parsed, returns false, else2664/// true.2665bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {2666// Check if the current operand has a custom associated parser, if so, try to2667// custom parse the operand, or fallback to the general approach.2668ParseStatus Result =2669MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);2670if (Result.isSuccess())2671return false;2672if (Result.isFailure())2673return true;26742675// Attempt to parse token as a register.2676if (parseRegister(Operands, true).isSuccess())2677return false;26782679// Attempt to parse token as an immediate2680if (parseImmediate(Operands).isSuccess()) {2681// Parse memory base register if present2682if (getLexer().is(AsmToken::LParen))2683return !parseMemOpBaseReg(Operands).isSuccess();2684return false;2685}26862687// Finally we have exhausted all options and must declare defeat.2688Error(getLoc(), "unknown operand");2689return true;2690}26912692bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,2693StringRef Name, SMLoc NameLoc,2694OperandVector &Operands) {2695// Ensure that if the instruction occurs when relaxation is enabled,2696// relocations are forced for the file. Ideally this would be done when there2697// is enough information to reliably determine if the instruction itself may2698// cause relaxations. Unfortunately instruction processing stage occurs in the2699// same pass as relocation emission, so it's too late to set a 'sticky bit'2700// for the entire file.2701if (getSTI().hasFeature(RISCV::FeatureRelax)) {2702auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();2703if (Assembler != nullptr) {2704RISCVAsmBackend &MAB =2705static_cast<RISCVAsmBackend &>(Assembler->getBackend());2706MAB.setForceRelocs();2707}2708}27092710// First operand is token for instruction2711Operands.push_back(RISCVOperand::createToken(Name, NameLoc));27122713// If there are no more operands, then finish2714if (getLexer().is(AsmToken::EndOfStatement)) {2715getParser().Lex(); // Consume the EndOfStatement.2716return false;2717}27182719// Parse first operand2720if (parseOperand(Operands, Name))2721return true;27222723// Parse until end of statement, consuming commas between operands2724while (parseOptionalToken(AsmToken::Comma)) {2725// Parse next operand2726if (parseOperand(Operands, Name))2727return true;2728}27292730if (getParser().parseEOL("unexpected token")) {2731getParser().eatToEndOfStatement();2732return true;2733}2734return false;2735}27362737bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,2738RISCVMCExpr::VariantKind &Kind) {2739Kind = RISCVMCExpr::VK_RISCV_None;27402741if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {2742Kind = RE->getKind();2743Expr = RE->getSubExpr();2744}27452746MCValue Res;2747MCFixup Fixup;2748if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))2749return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;2750return false;2751}27522753bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {2754MCValue Res;2755MCFixup Fixup;2756if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) {2757return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() &&2758Res.getSymB();2759}2760return false;2761}27622763ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {2764StringRef IDVal = DirectiveID.getString();27652766if (IDVal == ".option")2767return parseDirectiveOption();2768if (IDVal == ".attribute")2769return parseDirectiveAttribute();2770if (IDVal == ".insn")2771return parseDirectiveInsn(DirectiveID.getLoc());2772if (IDVal == ".variant_cc")2773return parseDirectiveVariantCC();27742775return ParseStatus::NoMatch;2776}27772778bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,2779bool FromOptionDirective) {2780for (auto &Feature : RISCVFeatureKV)2781if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))2782clearFeatureBits(Feature.Value, Feature.Key);27832784auto ParseResult = llvm::RISCVISAInfo::parseArchString(2785Arch, /*EnableExperimentalExtension=*/true,2786/*ExperimentalExtensionVersionCheck=*/true);2787if (!ParseResult) {2788std::string Buffer;2789raw_string_ostream OutputErrMsg(Buffer);2790handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {2791OutputErrMsg << "invalid arch name '" << Arch << "', "2792<< ErrMsg.getMessage();2793});27942795return Error(Loc, OutputErrMsg.str());2796}2797auto &ISAInfo = *ParseResult;27982799for (auto &Feature : RISCVFeatureKV)2800if (ISAInfo->hasExtension(Feature.Key))2801setFeatureBits(Feature.Value, Feature.Key);28022803if (FromOptionDirective) {2804if (ISAInfo->getXLen() == 32 && isRV64())2805return Error(Loc, "bad arch string switching from rv64 to rv32");2806else if (ISAInfo->getXLen() == 64 && !isRV64())2807return Error(Loc, "bad arch string switching from rv32 to rv64");2808}28092810if (ISAInfo->getXLen() == 32)2811clearFeatureBits(RISCV::Feature64Bit, "64bit");2812else if (ISAInfo->getXLen() == 64)2813setFeatureBits(RISCV::Feature64Bit, "64bit");2814else2815return Error(Loc, "bad arch string " + Arch);28162817Result = ISAInfo->toString();2818return false;2819}28202821bool RISCVAsmParser::parseDirectiveOption() {2822MCAsmParser &Parser = getParser();2823// Get the option token.2824AsmToken Tok = Parser.getTok();28252826// At the moment only identifiers are supported.2827if (parseToken(AsmToken::Identifier, "expected identifier"))2828return true;28292830StringRef Option = Tok.getIdentifier();28312832if (Option == "push") {2833if (Parser.parseEOL())2834return true;28352836getTargetStreamer().emitDirectiveOptionPush();2837pushFeatureBits();2838return false;2839}28402841if (Option == "pop") {2842SMLoc StartLoc = Parser.getTok().getLoc();2843if (Parser.parseEOL())2844return true;28452846getTargetStreamer().emitDirectiveOptionPop();2847if (popFeatureBits())2848return Error(StartLoc, ".option pop with no .option push");28492850return false;2851}28522853if (Option == "arch") {2854SmallVector<RISCVOptionArchArg> Args;2855do {2856if (Parser.parseComma())2857return true;28582859RISCVOptionArchArgType Type;2860if (parseOptionalToken(AsmToken::Plus))2861Type = RISCVOptionArchArgType::Plus;2862else if (parseOptionalToken(AsmToken::Minus))2863Type = RISCVOptionArchArgType::Minus;2864else if (!Args.empty())2865return Error(Parser.getTok().getLoc(),2866"unexpected token, expected + or -");2867else2868Type = RISCVOptionArchArgType::Full;28692870if (Parser.getTok().isNot(AsmToken::Identifier))2871return Error(Parser.getTok().getLoc(),2872"unexpected token, expected identifier");28732874StringRef Arch = Parser.getTok().getString();2875SMLoc Loc = Parser.getTok().getLoc();2876Parser.Lex();28772878if (Type == RISCVOptionArchArgType::Full) {2879std::string Result;2880if (resetToArch(Arch, Loc, Result, true))2881return true;28822883Args.emplace_back(Type, Result);2884break;2885}28862887if (isDigit(Arch.back()))2888return Error(2889Loc, "extension version number parsing not currently implemented");28902891std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);2892if (!enableExperimentalExtension() &&2893StringRef(Feature).starts_with("experimental-"))2894return Error(Loc, "unexpected experimental extensions");2895auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature);2896if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature)2897return Error(Loc, "unknown extension feature");28982899Args.emplace_back(Type, Arch.str());29002901if (Type == RISCVOptionArchArgType::Plus) {2902FeatureBitset OldFeatureBits = STI->getFeatureBits();29032904setFeatureBits(Ext->Value, Ext->Key);2905auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits());2906if (!ParseResult) {2907copySTI().setFeatureBits(OldFeatureBits);2908setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));29092910std::string Buffer;2911raw_string_ostream OutputErrMsg(Buffer);2912handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {2913OutputErrMsg << ErrMsg.getMessage();2914});29152916return Error(Loc, OutputErrMsg.str());2917}2918} else {2919assert(Type == RISCVOptionArchArgType::Minus);2920// It is invalid to disable an extension that there are other enabled2921// extensions depend on it.2922// TODO: Make use of RISCVISAInfo to handle this2923for (auto &Feature : RISCVFeatureKV) {2924if (getSTI().hasFeature(Feature.Value) &&2925Feature.Implies.test(Ext->Value))2926return Error(Loc, Twine("can't disable ") + Ext->Key +2927" extension; " + Feature.Key +2928" extension requires " + Ext->Key +2929" extension");2930}29312932clearFeatureBits(Ext->Value, Ext->Key);2933}2934} while (Parser.getTok().isNot(AsmToken::EndOfStatement));29352936if (Parser.parseEOL())2937return true;29382939getTargetStreamer().emitDirectiveOptionArch(Args);2940return false;2941}29422943if (Option == "rvc") {2944if (Parser.parseEOL())2945return true;29462947getTargetStreamer().emitDirectiveOptionRVC();2948setFeatureBits(RISCV::FeatureStdExtC, "c");2949return false;2950}29512952if (Option == "norvc") {2953if (Parser.parseEOL())2954return true;29552956getTargetStreamer().emitDirectiveOptionNoRVC();2957clearFeatureBits(RISCV::FeatureStdExtC, "c");2958clearFeatureBits(RISCV::FeatureStdExtZca, "zca");2959return false;2960}29612962if (Option == "pic") {2963if (Parser.parseEOL())2964return true;29652966getTargetStreamer().emitDirectiveOptionPIC();2967ParserOptions.IsPicEnabled = true;2968return false;2969}29702971if (Option == "nopic") {2972if (Parser.parseEOL())2973return true;29742975getTargetStreamer().emitDirectiveOptionNoPIC();2976ParserOptions.IsPicEnabled = false;2977return false;2978}29792980if (Option == "relax") {2981if (Parser.parseEOL())2982return true;29832984getTargetStreamer().emitDirectiveOptionRelax();2985setFeatureBits(RISCV::FeatureRelax, "relax");2986return false;2987}29882989if (Option == "norelax") {2990if (Parser.parseEOL())2991return true;29922993getTargetStreamer().emitDirectiveOptionNoRelax();2994clearFeatureBits(RISCV::FeatureRelax, "relax");2995return false;2996}29972998// Unknown option.2999Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "3000"'rvc', 'norvc', 'arch', 'relax' or "3001"'norelax'");3002Parser.eatToEndOfStatement();3003return false;3004}30053006/// parseDirectiveAttribute3007/// ::= .attribute expression ',' ( expression | "string" )3008/// ::= .attribute identifier ',' ( expression | "string" )3009bool RISCVAsmParser::parseDirectiveAttribute() {3010MCAsmParser &Parser = getParser();3011int64_t Tag;3012SMLoc TagLoc;3013TagLoc = Parser.getTok().getLoc();3014if (Parser.getTok().is(AsmToken::Identifier)) {3015StringRef Name = Parser.getTok().getIdentifier();3016std::optional<unsigned> Ret =3017ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags());3018if (!Ret)3019return Error(TagLoc, "attribute name not recognised: " + Name);3020Tag = *Ret;3021Parser.Lex();3022} else {3023const MCExpr *AttrExpr;30243025TagLoc = Parser.getTok().getLoc();3026if (Parser.parseExpression(AttrExpr))3027return true;30283029const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);3030if (check(!CE, TagLoc, "expected numeric constant"))3031return true;30323033Tag = CE->getValue();3034}30353036if (Parser.parseComma())3037return true;30383039StringRef StringValue;3040int64_t IntegerValue = 0;3041bool IsIntegerValue = true;30423043// RISC-V attributes have a string value if the tag number is odd3044// and an integer value if the tag number is even.3045if (Tag % 2)3046IsIntegerValue = false;30473048SMLoc ValueExprLoc = Parser.getTok().getLoc();3049if (IsIntegerValue) {3050const MCExpr *ValueExpr;3051if (Parser.parseExpression(ValueExpr))3052return true;30533054const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);3055if (!CE)3056return Error(ValueExprLoc, "expected numeric constant");3057IntegerValue = CE->getValue();3058} else {3059if (Parser.getTok().isNot(AsmToken::String))3060return Error(Parser.getTok().getLoc(), "expected string constant");30613062StringValue = Parser.getTok().getStringContents();3063Parser.Lex();3064}30653066if (Parser.parseEOL())3067return true;30683069if (IsIntegerValue)3070getTargetStreamer().emitAttribute(Tag, IntegerValue);3071else if (Tag != RISCVAttrs::ARCH)3072getTargetStreamer().emitTextAttribute(Tag, StringValue);3073else {3074std::string Result;3075if (resetToArch(StringValue, ValueExprLoc, Result, false))3076return true;30773078// Then emit the arch string.3079getTargetStreamer().emitTextAttribute(Tag, Result);3080}30813082return false;3083}30843085bool isValidInsnFormat(StringRef Format, bool AllowC) {3086return StringSwitch<bool>(Format)3087.Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)3088.Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)3089.Default(false);3090}30913092/// parseDirectiveInsn3093/// ::= .insn [ format encoding, (operands (, operands)*) ]3094/// ::= .insn [ length, value ]3095/// ::= .insn [ value ]3096bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {3097MCAsmParser &Parser = getParser();30983099bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||3100getSTI().hasFeature(RISCV::FeatureStdExtZca);31013102// Expect instruction format as identifier.3103StringRef Format;3104SMLoc ErrorLoc = Parser.getTok().getLoc();3105if (Parser.parseIdentifier(Format)) {3106// Try parsing .insn [length], value3107int64_t Length = 0;3108int64_t Value = 0;3109if (Parser.parseIntToken(3110Value, "expected instruction format or an integer constant"))3111return true;3112if (Parser.parseOptionalToken(AsmToken::Comma)) {3113Length = Value;3114if (Parser.parseIntToken(Value, "expected an integer constant"))3115return true;3116}31173118// TODO: Add support for long instructions3119int64_t RealLength = (Value & 3) == 3 ? 4 : 2;3120if (!isUIntN(RealLength * 8, Value))3121return Error(ErrorLoc, "invalid operand for instruction");3122if (RealLength == 2 && !AllowC)3123return Error(ErrorLoc, "compressed instructions are not allowed");3124if (Length != 0 && Length != RealLength)3125return Error(ErrorLoc, "instruction length mismatch");31263127if (getParser().parseEOL("invalid operand for instruction")) {3128getParser().eatToEndOfStatement();3129return true;3130}31313132emitToStreamer(getStreamer(), MCInstBuilder(RealLength == 2 ? RISCV::Insn163133: RISCV::Insn32)3134.addImm(Value));3135return false;3136}31373138if (!isValidInsnFormat(Format, AllowC))3139return Error(ErrorLoc, "invalid instruction format");31403141std::string FormatName = (".insn_" + Format).str();31423143ParseInstructionInfo Info;3144SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;31453146if (ParseInstruction(Info, FormatName, L, Operands))3147return true;31483149unsigned Opcode;3150uint64_t ErrorInfo;3151return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),3152ErrorInfo,3153/*MatchingInlineAsm=*/false);3154}31553156/// parseDirectiveVariantCC3157/// ::= .variant_cc symbol3158bool RISCVAsmParser::parseDirectiveVariantCC() {3159StringRef Name;3160if (getParser().parseIdentifier(Name))3161return TokError("expected symbol name");3162if (parseEOL())3163return true;3164getTargetStreamer().emitDirectiveVariantCC(3165*getContext().getOrCreateSymbol(Name));3166return false;3167}31683169void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {3170MCInst CInst;3171bool Res = RISCVRVC::compress(CInst, Inst, getSTI());3172if (Res)3173++RISCVNumInstrsCompressed;3174S.emitInstruction((Res ? CInst : Inst), getSTI());3175}31763177void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,3178MCStreamer &Out) {3179SmallVector<MCInst, 8> Seq;3180RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);31813182for (MCInst &Inst : Seq) {3183emitToStreamer(Out, Inst);3184}3185}31863187void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,3188const MCExpr *Symbol,3189RISCVMCExpr::VariantKind VKHi,3190unsigned SecondOpcode, SMLoc IDLoc,3191MCStreamer &Out) {3192// A pair of instructions for PC-relative addressing; expands to3193// TmpLabel: AUIPC TmpReg, VKHi(symbol)3194// OP DestReg, TmpReg, %pcrel_lo(TmpLabel)3195MCContext &Ctx = getContext();31963197MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");3198Out.emitLabel(TmpLabel);31993200const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);3201emitToStreamer(3202Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));32033204const MCExpr *RefToLinkTmpLabel =3205RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),3206RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);32073208emitToStreamer(Out, MCInstBuilder(SecondOpcode)3209.addOperand(DestReg)3210.addOperand(TmpReg)3211.addExpr(RefToLinkTmpLabel));3212}32133214void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,3215MCStreamer &Out) {3216// The load local address pseudo-instruction "lla" is used in PC-relative3217// addressing of local symbols:3218// lla rdest, symbol3219// expands to3220// TmpLabel: AUIPC rdest, %pcrel_hi(symbol)3221// ADDI rdest, rdest, %pcrel_lo(TmpLabel)3222MCOperand DestReg = Inst.getOperand(0);3223const MCExpr *Symbol = Inst.getOperand(1).getExpr();3224emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,3225RISCV::ADDI, IDLoc, Out);3226}32273228void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,3229MCStreamer &Out) {3230// The load global address pseudo-instruction "lga" is used in GOT-indirect3231// addressing of global symbols:3232// lga rdest, symbol3233// expands to3234// TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)3235// Lx rdest, %pcrel_lo(TmpLabel)(rdest)3236MCOperand DestReg = Inst.getOperand(0);3237const MCExpr *Symbol = Inst.getOperand(1).getExpr();3238unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;3239emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,3240SecondOpcode, IDLoc, Out);3241}32423243void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,3244MCStreamer &Out) {3245// The load address pseudo-instruction "la" is used in PC-relative and3246// GOT-indirect addressing of global symbols:3247// la rdest, symbol3248// is an alias for either (for non-PIC)3249// lla rdest, symbol3250// or (for PIC)3251// lga rdest, symbol3252if (ParserOptions.IsPicEnabled)3253emitLoadGlobalAddress(Inst, IDLoc, Out);3254else3255emitLoadLocalAddress(Inst, IDLoc, Out);3256}32573258void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,3259MCStreamer &Out) {3260// The load TLS IE address pseudo-instruction "la.tls.ie" is used in3261// initial-exec TLS model addressing of global symbols:3262// la.tls.ie rdest, symbol3263// expands to3264// TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)3265// Lx rdest, %pcrel_lo(TmpLabel)(rdest)3266MCOperand DestReg = Inst.getOperand(0);3267const MCExpr *Symbol = Inst.getOperand(1).getExpr();3268unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;3269emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,3270SecondOpcode, IDLoc, Out);3271}32723273void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,3274MCStreamer &Out) {3275// The load TLS GD address pseudo-instruction "la.tls.gd" is used in3276// global-dynamic TLS model addressing of global symbols:3277// la.tls.gd rdest, symbol3278// expands to3279// TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)3280// ADDI rdest, rdest, %pcrel_lo(TmpLabel)3281MCOperand DestReg = Inst.getOperand(0);3282const MCExpr *Symbol = Inst.getOperand(1).getExpr();3283emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,3284RISCV::ADDI, IDLoc, Out);3285}32863287void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,3288SMLoc IDLoc, MCStreamer &Out,3289bool HasTmpReg) {3290// The load/store pseudo-instruction does a pc-relative load with3291// a symbol.3292//3293// The expansion looks like this3294//3295// TmpLabel: AUIPC tmp, %pcrel_hi(symbol)3296// [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)3297unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;3298MCOperand DestReg = Inst.getOperand(DestRegOpIdx);3299unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;3300MCOperand TmpReg = Inst.getOperand(0);3301const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();3302emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,3303Opcode, IDLoc, Out);3304}33053306void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,3307int64_t Width, SMLoc IDLoc,3308MCStreamer &Out) {3309// The sign/zero extend pseudo-instruction does two shifts, with the shift3310// amounts dependent on the XLEN.3311//3312// The expansion looks like this3313//3314// SLLI rd, rs, XLEN - Width3315// SR[A|R]I rd, rd, XLEN - Width3316MCOperand DestReg = Inst.getOperand(0);3317MCOperand SourceReg = Inst.getOperand(1);33183319unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;3320int64_t ShAmt = (isRV64() ? 64 : 32) - Width;33213322assert(ShAmt > 0 && "Shift amount must be non-zero.");33233324emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)3325.addOperand(DestReg)3326.addOperand(SourceReg)3327.addImm(ShAmt));33283329emitToStreamer(Out, MCInstBuilder(SecondOpcode)3330.addOperand(DestReg)3331.addOperand(DestReg)3332.addImm(ShAmt));3333}33343335void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,3336MCStreamer &Out) {3337if (Inst.getNumOperands() == 3) {3338// unmasked va >= x3339//3340// pseudoinstruction: vmsge{u}.vx vd, va, x3341// expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd3342emitToStreamer(Out, MCInstBuilder(Opcode)3343.addOperand(Inst.getOperand(0))3344.addOperand(Inst.getOperand(1))3345.addOperand(Inst.getOperand(2))3346.addReg(RISCV::NoRegister)3347.setLoc(IDLoc));3348emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)3349.addOperand(Inst.getOperand(0))3350.addOperand(Inst.getOperand(0))3351.addOperand(Inst.getOperand(0))3352.setLoc(IDLoc));3353} else if (Inst.getNumOperands() == 4) {3354// masked va >= x, vd != v03355//3356// pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t3357// expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v03358assert(Inst.getOperand(0).getReg() != RISCV::V0 &&3359"The destination register should not be V0.");3360emitToStreamer(Out, MCInstBuilder(Opcode)3361.addOperand(Inst.getOperand(0))3362.addOperand(Inst.getOperand(1))3363.addOperand(Inst.getOperand(2))3364.addOperand(Inst.getOperand(3))3365.setLoc(IDLoc));3366emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)3367.addOperand(Inst.getOperand(0))3368.addOperand(Inst.getOperand(0))3369.addReg(RISCV::V0)3370.setLoc(IDLoc));3371} else if (Inst.getNumOperands() == 5 &&3372Inst.getOperand(0).getReg() == RISCV::V0) {3373// masked va >= x, vd == v03374//3375// pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt3376// expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt3377assert(Inst.getOperand(0).getReg() == RISCV::V0 &&3378"The destination register should be V0.");3379assert(Inst.getOperand(1).getReg() != RISCV::V0 &&3380"The temporary vector register should not be V0.");3381emitToStreamer(Out, MCInstBuilder(Opcode)3382.addOperand(Inst.getOperand(1))3383.addOperand(Inst.getOperand(2))3384.addOperand(Inst.getOperand(3))3385.addReg(RISCV::NoRegister)3386.setLoc(IDLoc));3387emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)3388.addOperand(Inst.getOperand(0))3389.addOperand(Inst.getOperand(0))3390.addOperand(Inst.getOperand(1))3391.setLoc(IDLoc));3392} else if (Inst.getNumOperands() == 5) {3393// masked va >= x, any vd3394//3395// pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt3396// expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;3397// vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd3398assert(Inst.getOperand(1).getReg() != RISCV::V0 &&3399"The temporary vector register should not be V0.");3400emitToStreamer(Out, MCInstBuilder(Opcode)3401.addOperand(Inst.getOperand(1))3402.addOperand(Inst.getOperand(2))3403.addOperand(Inst.getOperand(3))3404.addReg(RISCV::NoRegister)3405.setLoc(IDLoc));3406emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)3407.addOperand(Inst.getOperand(1))3408.addReg(RISCV::V0)3409.addOperand(Inst.getOperand(1))3410.setLoc(IDLoc));3411emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)3412.addOperand(Inst.getOperand(0))3413.addOperand(Inst.getOperand(0))3414.addReg(RISCV::V0)3415.setLoc(IDLoc));3416emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)3417.addOperand(Inst.getOperand(0))3418.addOperand(Inst.getOperand(1))3419.addOperand(Inst.getOperand(0))3420.setLoc(IDLoc));3421}3422}34233424bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,3425OperandVector &Operands) {3426assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");3427assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");3428if (Inst.getOperand(2).getReg() != RISCV::X4) {3429SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();3430return Error(ErrorLoc, "the second input operand must be tp/x4 when using "3431"%tprel_add modifier");3432}34333434return false;3435}34363437bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,3438OperandVector &Operands) {3439assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");3440assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");3441if (Inst.getOperand(0).getReg() != RISCV::X5) {3442SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();3443return Error(ErrorLoc, "the output operand must be t0/x5 when using "3444"%tlsdesc_call modifier");3445}34463447return false;3448}34493450std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {3451return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),3452llvm::SMLoc());3453}34543455std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {3456return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,3457llvm::SMLoc());3458}34593460std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {3461return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,3462llvm::SMLoc());3463}34643465bool RISCVAsmParser::validateInstruction(MCInst &Inst,3466OperandVector &Operands) {3467unsigned Opcode = Inst.getOpcode();34683469if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||3470Opcode == RISCV::PseudoVMSGE_VX_M_T) {3471unsigned DestReg = Inst.getOperand(0).getReg();3472unsigned TempReg = Inst.getOperand(1).getReg();3473if (DestReg == TempReg) {3474SMLoc Loc = Operands.back()->getStartLoc();3475return Error(Loc, "the temporary vector register cannot be the same as "3476"the destination register");3477}3478}34793480if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||3481Opcode == RISCV::TH_LWD) {3482unsigned Rd1 = Inst.getOperand(0).getReg();3483unsigned Rd2 = Inst.getOperand(1).getReg();3484unsigned Rs1 = Inst.getOperand(2).getReg();3485// The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.3486if (Rs1 == Rd1 && Rs1 == Rd2) {3487SMLoc Loc = Operands[1]->getStartLoc();3488return Error(Loc, "rs1, rd1, and rd2 cannot all be the same");3489}3490}34913492if (Opcode == RISCV::CM_MVSA01) {3493unsigned Rd1 = Inst.getOperand(0).getReg();3494unsigned Rd2 = Inst.getOperand(1).getReg();3495if (Rd1 == Rd2) {3496SMLoc Loc = Operands[1]->getStartLoc();3497return Error(Loc, "rs1 and rs2 must be different");3498}3499}35003501bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||3502Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);3503bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);3504// The last operand of XTHeadMemPair instructions must be constant 3 or 43505// depending on the data width.3506if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) {3507SMLoc Loc = Operands.back()->getStartLoc();3508return Error(Loc, "operand must be constant 3");3509} else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) {3510SMLoc Loc = Operands.back()->getStartLoc();3511return Error(Loc, "operand must be constant 4");3512}35133514const MCInstrDesc &MCID = MII.get(Opcode);3515if (!(MCID.TSFlags & RISCVII::ConstraintMask))3516return false;35173518if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||3519Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {3520// Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.3521unsigned VCIXDst = Inst.getOperand(0).getReg();3522SMLoc VCIXDstLoc = Operands[2]->getStartLoc();3523if (MCID.TSFlags & RISCVII::VS1Constraint) {3524unsigned VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();3525if (VCIXDst == VCIXRs1)3526return Error(VCIXDstLoc, "the destination vector register group cannot"3527" overlap the source vector register group");3528}3529if (MCID.TSFlags & RISCVII::VS2Constraint) {3530unsigned VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();3531if (VCIXDst == VCIXRs2)3532return Error(VCIXDstLoc, "the destination vector register group cannot"3533" overlap the source vector register group");3534}3535return false;3536}35373538unsigned DestReg = Inst.getOperand(0).getReg();3539unsigned Offset = 0;3540int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);3541if (TiedOp == 0)3542Offset = 1;35433544// Operands[1] will be the first operand, DestReg.3545SMLoc Loc = Operands[1]->getStartLoc();3546if (MCID.TSFlags & RISCVII::VS2Constraint) {3547unsigned CheckReg = Inst.getOperand(Offset + 1).getReg();3548if (DestReg == CheckReg)3549return Error(Loc, "the destination vector register group cannot overlap"3550" the source vector register group");3551}3552if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {3553unsigned CheckReg = Inst.getOperand(Offset + 2).getReg();3554if (DestReg == CheckReg)3555return Error(Loc, "the destination vector register group cannot overlap"3556" the source vector register group");3557}3558if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {3559// vadc, vsbc are special cases. These instructions have no mask register.3560// The destination register could not be V0.3561if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||3562Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||3563Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||3564Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||3565Opcode == RISCV::VMERGE_VXM)3566return Error(Loc, "the destination vector register group cannot be V0");35673568// Regardless masked or unmasked version, the number of operands is the3569// same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"3570// actually. We need to check the last operand to ensure whether it is3571// masked or not.3572unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();3573assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&3574"Unexpected register for mask operand");35753576if (DestReg == CheckReg)3577return Error(Loc, "the destination vector register group cannot overlap"3578" the mask register");3579}3580return false;3581}35823583bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,3584OperandVector &Operands,3585MCStreamer &Out) {3586Inst.setLoc(IDLoc);35873588switch (Inst.getOpcode()) {3589default:3590break;3591case RISCV::PseudoLLAImm:3592case RISCV::PseudoLAImm:3593case RISCV::PseudoLI: {3594MCRegister Reg = Inst.getOperand(0).getReg();3595const MCOperand &Op1 = Inst.getOperand(1);3596if (Op1.isExpr()) {3597// We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.3598// Just convert to an addi. This allows compatibility with gas.3599emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)3600.addReg(Reg)3601.addReg(RISCV::X0)3602.addExpr(Op1.getExpr()));3603return false;3604}3605int64_t Imm = Inst.getOperand(1).getImm();3606// On RV32 the immediate here can either be a signed or an unsigned3607// 32-bit number. Sign extension has to be performed to ensure that Imm3608// represents the expected signed 64-bit number.3609if (!isRV64())3610Imm = SignExtend64<32>(Imm);3611emitLoadImm(Reg, Imm, Out);3612return false;3613}3614case RISCV::PseudoLLA:3615emitLoadLocalAddress(Inst, IDLoc, Out);3616return false;3617case RISCV::PseudoLGA:3618emitLoadGlobalAddress(Inst, IDLoc, Out);3619return false;3620case RISCV::PseudoLA:3621emitLoadAddress(Inst, IDLoc, Out);3622return false;3623case RISCV::PseudoLA_TLS_IE:3624emitLoadTLSIEAddress(Inst, IDLoc, Out);3625return false;3626case RISCV::PseudoLA_TLS_GD:3627emitLoadTLSGDAddress(Inst, IDLoc, Out);3628return false;3629case RISCV::PseudoLB:3630emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);3631return false;3632case RISCV::PseudoLBU:3633emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);3634return false;3635case RISCV::PseudoLH:3636emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);3637return false;3638case RISCV::PseudoLHU:3639emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);3640return false;3641case RISCV::PseudoLW:3642emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);3643return false;3644case RISCV::PseudoLWU:3645emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);3646return false;3647case RISCV::PseudoLD:3648emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);3649return false;3650case RISCV::PseudoFLH:3651emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);3652return false;3653case RISCV::PseudoFLW:3654emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);3655return false;3656case RISCV::PseudoFLD:3657emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);3658return false;3659case RISCV::PseudoSB:3660emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);3661return false;3662case RISCV::PseudoSH:3663emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);3664return false;3665case RISCV::PseudoSW:3666emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);3667return false;3668case RISCV::PseudoSD:3669emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);3670return false;3671case RISCV::PseudoFSH:3672emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);3673return false;3674case RISCV::PseudoFSW:3675emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);3676return false;3677case RISCV::PseudoFSD:3678emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);3679return false;3680case RISCV::PseudoAddTPRel:3681if (checkPseudoAddTPRel(Inst, Operands))3682return true;3683break;3684case RISCV::PseudoTLSDESCCall:3685if (checkPseudoTLSDESCCall(Inst, Operands))3686return true;3687break;3688case RISCV::PseudoSEXT_B:3689emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);3690return false;3691case RISCV::PseudoSEXT_H:3692emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);3693return false;3694case RISCV::PseudoZEXT_H:3695emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);3696return false;3697case RISCV::PseudoZEXT_W:3698emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);3699return false;3700case RISCV::PseudoVMSGEU_VX:3701case RISCV::PseudoVMSGEU_VX_M:3702case RISCV::PseudoVMSGEU_VX_M_T:3703emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);3704return false;3705case RISCV::PseudoVMSGE_VX:3706case RISCV::PseudoVMSGE_VX_M:3707case RISCV::PseudoVMSGE_VX_M_T:3708emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);3709return false;3710case RISCV::PseudoVMSGE_VI:3711case RISCV::PseudoVMSLT_VI: {3712// These instructions are signed and so is immediate so we can subtract one3713// and change the opcode.3714int64_t Imm = Inst.getOperand(2).getImm();3715unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI3716: RISCV::VMSLE_VI;3717emitToStreamer(Out, MCInstBuilder(Opc)3718.addOperand(Inst.getOperand(0))3719.addOperand(Inst.getOperand(1))3720.addImm(Imm - 1)3721.addOperand(Inst.getOperand(3))3722.setLoc(IDLoc));3723return false;3724}3725case RISCV::PseudoVMSGEU_VI:3726case RISCV::PseudoVMSLTU_VI: {3727int64_t Imm = Inst.getOperand(2).getImm();3728// Unsigned comparisons are tricky because the immediate is signed. If the3729// immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always3730// false, but vmsle.vi v0, v1, -1 is always true. Instead we use3731// vmsne v0, v1, v1 which is always false.3732if (Imm == 0) {3733unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI3734? RISCV::VMSEQ_VV3735: RISCV::VMSNE_VV;3736emitToStreamer(Out, MCInstBuilder(Opc)3737.addOperand(Inst.getOperand(0))3738.addOperand(Inst.getOperand(1))3739.addOperand(Inst.getOperand(1))3740.addOperand(Inst.getOperand(3))3741.setLoc(IDLoc));3742} else {3743// Other immediate values can subtract one like signed.3744unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI3745? RISCV::VMSGTU_VI3746: RISCV::VMSLEU_VI;3747emitToStreamer(Out, MCInstBuilder(Opc)3748.addOperand(Inst.getOperand(0))3749.addOperand(Inst.getOperand(1))3750.addImm(Imm - 1)3751.addOperand(Inst.getOperand(3))3752.setLoc(IDLoc));3753}37543755return false;3756}3757}37583759emitToStreamer(Out, Inst);3760return false;3761}37623763extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser() {3764RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());3765RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());3766}376737683769