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