Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
35294 views
// LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MCTargetDesc/LoongArchInstPrinter.h"9#include "MCTargetDesc/LoongArchMCExpr.h"10#include "MCTargetDesc/LoongArchMCTargetDesc.h"11#include "MCTargetDesc/LoongArchMatInt.h"12#include "TargetInfo/LoongArchTargetInfo.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCInstBuilder.h"15#include "llvm/MC/MCInstrInfo.h"16#include "llvm/MC/MCParser/MCAsmLexer.h"17#include "llvm/MC/MCParser/MCParsedAsmOperand.h"18#include "llvm/MC/MCParser/MCTargetAsmParser.h"19#include "llvm/MC/MCRegisterInfo.h"20#include "llvm/MC/MCStreamer.h"21#include "llvm/MC/MCSubtargetInfo.h"22#include "llvm/MC/MCValue.h"23#include "llvm/MC/TargetRegistry.h"24#include "llvm/Support/Casting.h"2526using namespace llvm;2728#define DEBUG_TYPE "loongarch-asm-parser"2930namespace {31class LoongArchAsmParser : public MCTargetAsmParser {32SMLoc getLoc() const { return getParser().getTok().getLoc(); }33bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); }3435struct Inst {36unsigned Opc;37LoongArchMCExpr::VariantKind VK;38Inst(unsigned Opc,39LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None)40: Opc(Opc), VK(VK) {}41};42using InstSeq = SmallVector<Inst>;4344/// Parse a register as used in CFI directives.45bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;46ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,47SMLoc &EndLoc) override;4849bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,50SMLoc NameLoc, OperandVector &Operands) override;5152bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,53OperandVector &Operands, MCStreamer &Out,54uint64_t &ErrorInfo,55bool MatchingInlineAsm) override;5657unsigned checkTargetMatchPredicate(MCInst &Inst) override;5859unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,60unsigned Kind) override;6162bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,63int64_t Lower, int64_t Upper,64const Twine &Msg);6566/// Helper for processing MC instructions that have been successfully matched67/// by MatchAndEmitInstruction.68bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,69MCStreamer &Out);7071// Auto-generated instruction matching functions.72#define GET_ASSEMBLER_HEADER73#include "LoongArchGenAsmMatcher.inc"7475ParseStatus parseRegister(OperandVector &Operands);76ParseStatus parseImmediate(OperandVector &Operands);77ParseStatus parseOperandWithModifier(OperandVector &Operands);78ParseStatus parseSImm26Operand(OperandVector &Operands);79ParseStatus parseAtomicMemOp(OperandVector &Operands);8081bool parseOperand(OperandVector &Operands, StringRef Mnemonic);8283// Helper to emit the sequence of instructions generated by the84// "emitLoadAddress*" functions.85void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,86const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,87SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);8889// Helper to emit pseudo instruction "la.abs $rd, sym".90void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);9192// Helper to emit pseudo instruction "la.pcrel $rd, sym".93void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);94// Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".95void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);9697// Helper to emit pseudo instruction "la.got $rd, sym".98void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);99// Helper to emit pseudo instruction "la.got $rd, $rj, sym".100void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);101102// Helper to emit pseudo instruction "la.tls.le $rd, sym".103void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);104105// Helper to emit pseudo instruction "la.tls.ie $rd, sym".106void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);107// Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".108void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);109110// Helper to emit pseudo instruction "la.tls.ld $rd, sym".111void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);112// Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".113void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);114115// Helper to emit pseudo instruction "la.tls.gd $rd, sym".116void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);117// Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".118void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);119120// Helper to emit pseudo instruction "la.tls.desc $rd, sym".121void emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);122void emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);123// Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".124void emitLoadAddressTLSDescPcrelLarge(MCInst &Inst, SMLoc IDLoc,125MCStreamer &Out);126127// Helper to emit pseudo instruction "li.w/d $rd, $imm".128void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);129130// Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".131void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,132bool IsTailCall);133134public:135enum LoongArchMatchResultTy {136Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,137Match_RequiresMsbNotLessThanLsb,138Match_RequiresOpnd2NotR0R1,139Match_RequiresAMORdDifferRkRj,140Match_RequiresLAORdDifferRj,141Match_RequiresLAORdR4,142#define GET_OPERAND_DIAGNOSTIC_TYPES143#include "LoongArchGenAsmMatcher.inc"144#undef GET_OPERAND_DIAGNOSTIC_TYPES145};146147static bool classifySymbolRef(const MCExpr *Expr,148LoongArchMCExpr::VariantKind &Kind);149150LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,151const MCInstrInfo &MII, const MCTargetOptions &Options)152: MCTargetAsmParser(Options, STI, MII) {153Parser.addAliasForDirective(".half", ".2byte");154Parser.addAliasForDirective(".hword", ".2byte");155Parser.addAliasForDirective(".word", ".4byte");156Parser.addAliasForDirective(".dword", ".8byte");157158// Initialize the set of available features.159setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));160}161};162163// Instances of this class represent a parsed LoongArch machine instruction.164class LoongArchOperand : public MCParsedAsmOperand {165enum class KindTy {166Token,167Register,168Immediate,169} Kind;170171struct RegOp {172MCRegister RegNum;173};174175struct ImmOp {176const MCExpr *Val;177};178179SMLoc StartLoc, EndLoc;180union {181StringRef Tok;182struct RegOp Reg;183struct ImmOp Imm;184};185186public:187LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}188189bool isToken() const override { return Kind == KindTy::Token; }190bool isReg() const override { return Kind == KindTy::Register; }191bool isImm() const override { return Kind == KindTy::Immediate; }192bool isMem() const override { return false; }193void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }194bool isGPR() const {195return Kind == KindTy::Register &&196LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(197Reg.RegNum);198}199200static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,201LoongArchMCExpr::VariantKind &VK) {202if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) {203VK = LE->getKind();204return false;205}206207if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {208Imm = CE->getValue();209return true;210}211212return false;213}214215template <unsigned N, int P = 0> bool isUImm() const {216if (!isImm())217return false;218219int64_t Imm;220LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;221bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);222return IsConstantImm && isUInt<N>(Imm - P) &&223VK == LoongArchMCExpr::VK_LoongArch_None;224}225226template <unsigned N, unsigned S = 0> bool isSImm() const {227if (!isImm())228return false;229230int64_t Imm;231LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;232bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);233return IsConstantImm && isShiftedInt<N, S>(Imm) &&234VK == LoongArchMCExpr::VK_LoongArch_None;235}236237bool isBareSymbol() const {238int64_t Imm;239LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;240// Must be of 'immediate' type but not a constant.241if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))242return false;243return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&244VK == LoongArchMCExpr::VK_LoongArch_None;245}246247bool isTPRelAddSymbol() const {248int64_t Imm;249LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;250// Must be of 'immediate' type but not a constant.251if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))252return false;253return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&254VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R;255}256257bool isUImm1() const { return isUImm<1>(); }258bool isUImm2() const { return isUImm<2>(); }259bool isUImm2plus1() const { return isUImm<2, 1>(); }260bool isUImm3() const { return isUImm<3>(); }261bool isUImm4() const { return isUImm<4>(); }262bool isSImm5() const { return isSImm<5>(); }263bool isUImm5() const { return isUImm<5>(); }264bool isUImm6() const { return isUImm<6>(); }265bool isUImm7() const { return isUImm<7>(); }266bool isSImm8() const { return isSImm<8>(); }267bool isSImm8lsl1() const { return isSImm<8, 1>(); }268bool isSImm8lsl2() const { return isSImm<8, 2>(); }269bool isSImm8lsl3() const { return isSImm<8, 3>(); }270bool isUImm8() const { return isUImm<8>(); }271bool isSImm9lsl3() const { return isSImm<9, 3>(); }272bool isSImm10() const { return isSImm<10>(); }273bool isSImm10lsl2() const { return isSImm<10, 2>(); }274bool isSImm11lsl1() const { return isSImm<11, 1>(); }275bool isSImm12() const { return isSImm<12>(); }276277bool isSImm12addlike() const {278if (!isImm())279return false;280281int64_t Imm;282LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;283bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);284bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||285VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||286VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||287VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||288VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R ||289VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12 ||290VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;291return IsConstantImm292? isInt<12>(Imm) && IsValidKind293: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&294IsValidKind;295}296297bool isSImm12lu52id() const {298if (!isImm())299return false;300301int64_t Imm;302LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;303bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);304bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||305VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 ||306VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 ||307VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 ||308VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 ||309VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 ||310VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 ||311VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12 ||312VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12 ||313VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12;314return IsConstantImm315? isInt<12>(Imm) && IsValidKind316: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&317IsValidKind;318}319320bool isUImm12() const { return isUImm<12>(); }321322bool isUImm12ori() const {323if (!isImm())324return false;325326int64_t Imm;327LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;328bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);329bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||330VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 ||331VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||332VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 ||333VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||334VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 ||335VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 ||336VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||337VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12;338return IsConstantImm339? isUInt<12>(Imm) && IsValidKind340: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&341IsValidKind;342}343344bool isSImm13() const { return isSImm<13>(); }345bool isUImm14() const { return isUImm<14>(); }346bool isUImm15() const { return isUImm<15>(); }347348bool isSImm14lsl2() const { return isSImm<14, 2>(); }349bool isSImm16() const { return isSImm<16>(); }350351bool isSImm16lsl2() const {352if (!isImm())353return false;354355int64_t Imm;356LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;357bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);358bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||359VK == LoongArchMCExpr::VK_LoongArch_B16 ||360VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||361VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL;362return IsConstantImm363? isShiftedInt<16, 2>(Imm) && IsValidKind364: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&365IsValidKind;366}367368bool isSImm20() const { return isSImm<20>(); }369370bool isSImm20pcalau12i() const {371if (!isImm())372return false;373374int64_t Imm;375LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;376bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);377bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||378VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 ||379VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 ||380VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 ||381VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 ||382VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20 ||383VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20;384return IsConstantImm385? isInt<20>(Imm) && IsValidKind386: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&387IsValidKind;388}389390bool isSImm20lu12iw() const {391if (!isImm())392return false;393394int64_t Imm;395LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;396bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);397bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||398VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 ||399VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 ||400VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 ||401VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 ||402VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 ||403VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20 ||404VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R ||405VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20;406return IsConstantImm407? isInt<20>(Imm) && IsValidKind408: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&409IsValidKind;410}411412bool isSImm20lu32id() const {413if (!isImm())414return false;415416int64_t Imm;417LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;418bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);419bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||420VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 ||421VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 ||422VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 ||423VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 ||424VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 ||425VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 ||426VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20 ||427VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20 ||428VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20;429430return IsConstantImm431? isInt<20>(Imm) && IsValidKind432: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&433IsValidKind;434}435436bool isSImm20pcaddu18i() const {437if (!isImm())438return false;439440int64_t Imm;441LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;442bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);443bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||444VK == LoongArchMCExpr::VK_LoongArch_CALL36;445446return IsConstantImm447? isInt<20>(Imm) && IsValidKind448: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&449IsValidKind;450}451452bool isSImm20pcaddi() const {453if (!isImm())454return false;455456int64_t Imm;457LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;458bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);459bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||460VK == LoongArchMCExpr::VK_LoongArch_PCREL20_S2 ||461VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2 ||462VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2 ||463VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2;464return IsConstantImm465? isInt<20>(Imm) && IsValidKind466: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&467IsValidKind;468}469470bool isSImm21lsl2() const {471if (!isImm())472return false;473474int64_t Imm;475LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;476bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);477bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||478VK == LoongArchMCExpr::VK_LoongArch_B21;479return IsConstantImm480? isShiftedInt<21, 2>(Imm) && IsValidKind481: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&482IsValidKind;483}484485bool isSImm26Operand() const {486if (!isImm())487return false;488489int64_t Imm;490LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;491bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);492bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||493VK == LoongArchMCExpr::VK_LoongArch_CALL ||494VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT ||495VK == LoongArchMCExpr::VK_LoongArch_B26;496return IsConstantImm497? isShiftedInt<26, 2>(Imm) && IsValidKind498: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&499IsValidKind;500}501502bool isImm32() const { return isSImm<32>() || isUImm<32>(); }503bool isImm64() const {504if (!isImm())505return false;506int64_t Imm;507LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;508bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);509return IsConstantImm && VK == LoongArchMCExpr::VK_LoongArch_None;510}511512/// Gets location of the first token of this operand.513SMLoc getStartLoc() const override { return StartLoc; }514/// Gets location of the last token of this operand.515SMLoc getEndLoc() const override { return EndLoc; }516517MCRegister getReg() const override {518assert(Kind == KindTy::Register && "Invalid type access!");519return Reg.RegNum;520}521522const MCExpr *getImm() const {523assert(Kind == KindTy::Immediate && "Invalid type access!");524return Imm.Val;525}526527StringRef getToken() const {528assert(Kind == KindTy::Token && "Invalid type access!");529return Tok;530}531532void print(raw_ostream &OS) const override {533auto RegName = [](MCRegister Reg) {534if (Reg)535return LoongArchInstPrinter::getRegisterName(Reg);536else537return "noreg";538};539540switch (Kind) {541case KindTy::Immediate:542OS << *getImm();543break;544case KindTy::Register:545OS << "<register " << RegName(getReg()) << ">";546break;547case KindTy::Token:548OS << "'" << getToken() << "'";549break;550}551}552553static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) {554auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);555Op->Tok = Str;556Op->StartLoc = S;557Op->EndLoc = S;558return Op;559}560561static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S,562SMLoc E) {563auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);564Op->Reg.RegNum = RegNo;565Op->StartLoc = S;566Op->EndLoc = E;567return Op;568}569570static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S,571SMLoc E) {572auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);573Op->Imm.Val = Val;574Op->StartLoc = S;575Op->EndLoc = E;576return Op;577}578579void addExpr(MCInst &Inst, const MCExpr *Expr) const {580if (auto CE = dyn_cast<MCConstantExpr>(Expr))581Inst.addOperand(MCOperand::createImm(CE->getValue()));582else583Inst.addOperand(MCOperand::createExpr(Expr));584}585586// Used by the TableGen Code.587void addRegOperands(MCInst &Inst, unsigned N) const {588assert(N == 1 && "Invalid number of operands!");589Inst.addOperand(MCOperand::createReg(getReg()));590}591void addImmOperands(MCInst &Inst, unsigned N) const {592assert(N == 1 && "Invalid number of operands!");593addExpr(Inst, getImm());594}595};596} // end namespace597598#define GET_REGISTER_MATCHER599#define GET_SUBTARGET_FEATURE_NAME600#define GET_MATCHER_IMPLEMENTATION601#define GET_MNEMONIC_SPELL_CHECKER602#include "LoongArchGenAsmMatcher.inc"603604static MCRegister convertFPR32ToFPR64(MCRegister Reg) {605assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");606return Reg - LoongArch::F0 + LoongArch::F0_64;607}608609// Attempts to match Name as a register (either using the default name or610// alternative ABI names), setting RegNo to the matching register. Upon611// failure, returns true and sets RegNo to 0.612static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {613RegNo = MatchRegisterName(Name);614// The 32-bit and 64-bit FPRs have the same asm name. Check that the initial615// match always matches the 32-bit variant, and not the 64-bit one.616assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));617// The default FPR register class is based on the tablegen enum ordering.618static_assert(LoongArch::F0 < LoongArch::F0_64,619"FPR matching must be updated");620if (RegNo == LoongArch::NoRegister)621RegNo = MatchRegisterAltName(Name);622623return RegNo == LoongArch::NoRegister;624}625626bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,627SMLoc &EndLoc) {628return Error(getLoc(), "invalid register number");629}630631ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg,632SMLoc &StartLoc,633SMLoc &EndLoc) {634llvm_unreachable("Unimplemented function.");635}636637bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,638LoongArchMCExpr::VariantKind &Kind) {639Kind = LoongArchMCExpr::VK_LoongArch_None;640641if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {642Kind = RE->getKind();643Expr = RE->getSubExpr();644}645646MCValue Res;647if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr))648return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None;649return false;650}651652ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {653if (!parseOptionalToken(AsmToken::Dollar))654return ParseStatus::NoMatch;655if (getLexer().getKind() != AsmToken::Identifier)656return ParseStatus::NoMatch;657658StringRef Name = getLexer().getTok().getIdentifier();659MCRegister RegNo;660matchRegisterNameHelper(RegNo, Name);661if (RegNo == LoongArch::NoRegister)662return ParseStatus::NoMatch;663664SMLoc S = getLoc();665SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());666getLexer().Lex();667Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));668669return ParseStatus::Success;670}671672ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {673SMLoc S = getLoc();674SMLoc E;675const MCExpr *Res;676677switch (getLexer().getKind()) {678default:679return ParseStatus::NoMatch;680case AsmToken::LParen:681case AsmToken::Dot:682case AsmToken::Minus:683case AsmToken::Plus:684case AsmToken::Exclaim:685case AsmToken::Tilde:686case AsmToken::Integer:687case AsmToken::String:688case AsmToken::Identifier:689if (getParser().parseExpression(Res, E))690return ParseStatus::Failure;691break;692case AsmToken::Percent:693return parseOperandWithModifier(Operands);694}695696Operands.push_back(LoongArchOperand::createImm(Res, S, E));697return ParseStatus::Success;698}699700ParseStatus701LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {702SMLoc S = getLoc();703SMLoc E;704705if (getLexer().getKind() != AsmToken::Percent)706return Error(getLoc(), "expected '%' for operand modifier");707708getParser().Lex(); // Eat '%'709710if (getLexer().getKind() != AsmToken::Identifier)711return Error(getLoc(), "expected valid identifier for operand modifier");712StringRef Identifier = getParser().getTok().getIdentifier();713LoongArchMCExpr::VariantKind VK =714LoongArchMCExpr::getVariantKindForName(Identifier);715if (VK == LoongArchMCExpr::VK_LoongArch_Invalid)716return Error(getLoc(), "unrecognized operand modifier");717718getParser().Lex(); // Eat the identifier719if (getLexer().getKind() != AsmToken::LParen)720return Error(getLoc(), "expected '('");721getParser().Lex(); // Eat '('722723const MCExpr *SubExpr;724if (getParser().parseParenExpression(SubExpr, E))725return ParseStatus::Failure;726727const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());728Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));729return ParseStatus::Success;730}731732ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {733SMLoc S = getLoc();734const MCExpr *Res;735736if (getLexer().getKind() == AsmToken::Percent)737return parseOperandWithModifier(Operands);738739if (getLexer().getKind() != AsmToken::Identifier)740return ParseStatus::NoMatch;741742StringRef Identifier;743if (getParser().parseIdentifier(Identifier))744return ParseStatus::Failure;745746SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());747748MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);749Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());750Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL,751getContext());752Operands.push_back(LoongArchOperand::createImm(Res, S, E));753return ParseStatus::Success;754}755756ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {757// Parse "$r*".758if (!parseRegister(Operands).isSuccess())759return ParseStatus::NoMatch;760761// If there is a next operand and it is 0, ignore it. Otherwise print a762// diagnostic message.763if (parseOptionalToken(AsmToken::Comma)) {764int64_t ImmVal;765SMLoc ImmStart = getLoc();766if (getParser().parseIntToken(ImmVal, "expected optional integer offset"))767return ParseStatus::Failure;768if (ImmVal)769return Error(ImmStart, "optional integer offset must be 0");770}771772return ParseStatus::Success;773}774/// Looks at a token type and creates the relevant operand from this775/// information, adding to Operands. Return true upon an error.776bool LoongArchAsmParser::parseOperand(OperandVector &Operands,777StringRef Mnemonic) {778// Check if the current operand has a custom associated parser, if so, try to779// custom parse the operand, or fallback to the general approach.780ParseStatus Result =781MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);782if (Result.isSuccess())783return false;784if (Result.isFailure())785return true;786787if (parseRegister(Operands).isSuccess() ||788parseImmediate(Operands).isSuccess())789return false;790791// Finally we have exhausted all options and must declare defeat.792return Error(getLoc(), "unknown operand");793}794795bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info,796StringRef Name, SMLoc NameLoc,797OperandVector &Operands) {798// First operand in MCInst is instruction mnemonic.799Operands.push_back(LoongArchOperand::createToken(Name, NameLoc));800801// If there are no more operands, then finish.802if (parseOptionalToken(AsmToken::EndOfStatement))803return false;804805// Parse first operand.806if (parseOperand(Operands, Name))807return true;808809// Parse until end of statement, consuming commas between operands.810while (parseOptionalToken(AsmToken::Comma))811if (parseOperand(Operands, Name))812return true;813814// Parse end of statement and return successfully.815if (parseOptionalToken(AsmToken::EndOfStatement))816return false;817818SMLoc Loc = getLexer().getLoc();819getParser().eatToEndOfStatement();820return Error(Loc, "unexpected token");821}822823void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,824const MCExpr *Symbol,825SmallVectorImpl<Inst> &Insts,826SMLoc IDLoc, MCStreamer &Out,827bool RelaxHint) {828MCContext &Ctx = getContext();829for (LoongArchAsmParser::Inst &Inst : Insts) {830unsigned Opc = Inst.Opc;831LoongArchMCExpr::VariantKind VK = Inst.VK;832const LoongArchMCExpr *LE =833LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);834switch (Opc) {835default:836llvm_unreachable("unexpected opcode");837case LoongArch::PCALAU12I:838case LoongArch::LU12I_W:839Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),840getSTI());841break;842case LoongArch::ORI:843case LoongArch::ADDI_W:844case LoongArch::LD_W:845case LoongArch::LD_D: {846if (VK == LoongArchMCExpr::VK_LoongArch_None) {847Out.emitInstruction(848MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),849getSTI());850continue;851} else if (VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD) {852Out.emitInstruction(MCInstBuilder(Opc)853.addReg(LoongArch::R1)854.addReg(DestReg)855.addExpr(LE),856getSTI());857continue;858}859Out.emitInstruction(860MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),861getSTI());862break;863}864case LoongArch::LU32I_D:865Out.emitInstruction(MCInstBuilder(Opc)866.addReg(DestReg == TmpReg ? DestReg : TmpReg)867.addReg(DestReg == TmpReg ? DestReg : TmpReg)868.addExpr(LE),869getSTI());870break;871case LoongArch::LU52I_D:872Out.emitInstruction(873MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE),874getSTI());875break;876case LoongArch::ADDI_D:877Out.emitInstruction(878MCInstBuilder(Opc)879.addReg(TmpReg)880.addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)881.addExpr(LE),882getSTI());883break;884case LoongArch::ADD_D:885case LoongArch::LDX_D:886Out.emitInstruction(887MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),888getSTI());889break;890case LoongArch::JIRL:891Out.emitInstruction(MCInstBuilder(Opc)892.addReg(LoongArch::R1)893.addReg(LoongArch::R1)894.addExpr(LE),895getSTI());896break;897}898}899}900901void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,902MCStreamer &Out) {903// la.abs $rd, sym904// expands to:905// lu12i.w $rd, %abs_hi20(sym)906// ori $rd, $rd, %abs_lo12(sym)907//908// for 64bit appends:909// lu32i.d $rd, %abs64_lo20(sym)910// lu52i.d $rd, $rd, %abs64_hi12(sym)911MCRegister DestReg = Inst.getOperand(0).getReg();912const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS913? Inst.getOperand(1).getExpr()914: Inst.getOperand(2).getExpr();915InstSeq Insts;916917Insts.push_back(LoongArchAsmParser::Inst(918LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20));919Insts.push_back(LoongArchAsmParser::Inst(920LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12));921922if (is64Bit()) {923Insts.push_back(LoongArchAsmParser::Inst(924LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20));925Insts.push_back(LoongArchAsmParser::Inst(926LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12));927}928929emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);930}931932void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,933MCStreamer &Out) {934// la.pcrel $rd, sym935// expands to:936// pcalau12i $rd, %pc_hi20(sym)937// addi.w/d $rd, rd, %pc_lo12(sym)938MCRegister DestReg = Inst.getOperand(0).getReg();939const MCExpr *Symbol = Inst.getOperand(1).getExpr();940InstSeq Insts;941unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;942943Insts.push_back(LoongArchAsmParser::Inst(944LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));945Insts.push_back(946LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));947948emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);949}950951void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,952MCStreamer &Out) {953// la.pcrel $rd, $rj, sym954// expands to:955// pcalau12i $rd, %pc_hi20(sym)956// addi.d $rj, $r0, %pc_lo12(sym)957// lu32i.d $rj, %pc64_lo20(sym)958// lu52i.d $rj, $rj, %pc64_hi12(sym)959// add.d $rd, $rd, $rj960MCRegister DestReg = Inst.getOperand(0).getReg();961MCRegister TmpReg = Inst.getOperand(1).getReg();962const MCExpr *Symbol = Inst.getOperand(2).getExpr();963InstSeq Insts;964965Insts.push_back(LoongArchAsmParser::Inst(966LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));967Insts.push_back(LoongArchAsmParser::Inst(968LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));969Insts.push_back(LoongArchAsmParser::Inst(970LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20));971Insts.push_back(LoongArchAsmParser::Inst(972LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12));973Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));974975emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);976}977978void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,979MCStreamer &Out) {980// la.got $rd, sym981// expands to:982// pcalau12i $rd, %got_pc_hi20(sym)983// ld.w/d $rd, $rd, %got_pc_lo12(sym)984MCRegister DestReg = Inst.getOperand(0).getReg();985const MCExpr *Symbol = Inst.getOperand(1).getExpr();986InstSeq Insts;987unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;988989Insts.push_back(LoongArchAsmParser::Inst(990LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));991Insts.push_back(992LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));993994emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);995}996997void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,998MCStreamer &Out) {999// la.got $rd, $rj, sym1000// expands to:1001// pcalau12i $rd, %got_pc_hi20(sym)1002// addi.d $rj, $r0, %got_pc_lo12(sym)1003// lu32i.d $rj, %got64_pc_lo20(sym)1004// lu52i.d $rj, $rj, %got64_pc_hi12(sym)1005// ldx.d $rd, $rd, $rj1006MCRegister DestReg = Inst.getOperand(0).getReg();1007MCRegister TmpReg = Inst.getOperand(1).getReg();1008const MCExpr *Symbol = Inst.getOperand(2).getExpr();1009InstSeq Insts;10101011Insts.push_back(LoongArchAsmParser::Inst(1012LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));1013Insts.push_back(LoongArchAsmParser::Inst(1014LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));1015Insts.push_back(LoongArchAsmParser::Inst(1016LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));1017Insts.push_back(LoongArchAsmParser::Inst(1018LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));1019Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));10201021emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1022}10231024void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,1025MCStreamer &Out) {1026// la.tls.le $rd, sym1027// expands to:1028// lu12i.w $rd, %le_hi20(sym)1029// ori $rd, $rd, %le_lo12(sym)1030MCRegister DestReg = Inst.getOperand(0).getReg();1031const MCExpr *Symbol = Inst.getOperand(1).getExpr();1032InstSeq Insts;10331034Insts.push_back(LoongArchAsmParser::Inst(1035LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20));1036Insts.push_back(LoongArchAsmParser::Inst(1037LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12));10381039emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1040}10411042void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,1043MCStreamer &Out) {1044// la.tls.ie $rd, sym1045// expands to:1046// pcalau12i $rd, %ie_pc_hi20(sym)1047// ld.w/d $rd, $rd, %ie_pc_lo12(sym)1048MCRegister DestReg = Inst.getOperand(0).getReg();1049const MCExpr *Symbol = Inst.getOperand(1).getExpr();1050InstSeq Insts;1051unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;10521053Insts.push_back(LoongArchAsmParser::Inst(1054LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));1055Insts.push_back(LoongArchAsmParser::Inst(1056LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));10571058emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1059}10601061void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,1062MCStreamer &Out) {1063// la.tls.ie $rd, $rj, sym1064// expands to:1065// pcalau12i $rd, %ie_pc_hi20(sym)1066// addi.d $rj, $r0, %ie_pc_lo12(sym)1067// lu32i.d $rj, %ie64_pc_lo20(sym)1068// lu52i.d $rj, $rj, %ie64_pc_hi12(sym)1069// ldx.d $rd, $rd, $rj1070MCRegister DestReg = Inst.getOperand(0).getReg();1071MCRegister TmpReg = Inst.getOperand(1).getReg();1072const MCExpr *Symbol = Inst.getOperand(2).getExpr();1073InstSeq Insts;10741075Insts.push_back(LoongArchAsmParser::Inst(1076LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));1077Insts.push_back(LoongArchAsmParser::Inst(1078LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));1079Insts.push_back(LoongArchAsmParser::Inst(1080LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20));1081Insts.push_back(LoongArchAsmParser::Inst(1082LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12));1083Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));10841085emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1086}10871088void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,1089MCStreamer &Out) {1090// la.tls.ld $rd, sym1091// expands to:1092// pcalau12i $rd, %ld_pc_hi20(sym)1093// addi.w/d $rd, $rd, %got_pc_lo12(sym)1094MCRegister DestReg = Inst.getOperand(0).getReg();1095const MCExpr *Symbol = Inst.getOperand(1).getExpr();1096InstSeq Insts;1097unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;10981099Insts.push_back(LoongArchAsmParser::Inst(1100LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));1101Insts.push_back(LoongArchAsmParser::Inst(1102ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));11031104emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1105}11061107void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,1108MCStreamer &Out) {1109// la.tls.ld $rd, $rj, sym1110// expands to:1111// pcalau12i $rd, %ld_pc_hi20(sym)1112// addi.d $rj, $r0, %got_pc_lo12(sym)1113// lu32i.d $rj, %got64_pc_lo20(sym)1114// lu52i.d $rj, $rj, %got64_pc_hi12(sym)1115// add.d $rd, $rd, $rj1116MCRegister DestReg = Inst.getOperand(0).getReg();1117MCRegister TmpReg = Inst.getOperand(1).getReg();1118const MCExpr *Symbol = Inst.getOperand(2).getExpr();1119InstSeq Insts;11201121Insts.push_back(LoongArchAsmParser::Inst(1122LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));1123Insts.push_back(LoongArchAsmParser::Inst(1124LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));1125Insts.push_back(LoongArchAsmParser::Inst(1126LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));1127Insts.push_back(LoongArchAsmParser::Inst(1128LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));1129Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));11301131emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1132}11331134void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,1135MCStreamer &Out) {1136// la.tls.gd $rd, sym1137// expands to:1138// pcalau12i $rd, %gd_pc_hi20(sym)1139// addi.w/d $rd, $rd, %got_pc_lo12(sym)1140MCRegister DestReg = Inst.getOperand(0).getReg();1141const MCExpr *Symbol = Inst.getOperand(1).getExpr();1142InstSeq Insts;1143unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;11441145Insts.push_back(LoongArchAsmParser::Inst(1146LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));1147Insts.push_back(LoongArchAsmParser::Inst(1148ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));11491150emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1151}11521153void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,1154MCStreamer &Out) {1155// la.tls.gd $rd, $rj, sym1156// expands to:1157// pcalau12i $rd, %gd_pc_hi20(sym)1158// addi.d $rj, $r0, %got_pc_lo12(sym)1159// lu32i.d $rj, %got64_pc_lo20(sym)1160// lu52i.d $rj, $rj, %got64_pc_hi12(sym)1161// add.d $rd, $rd, $rj1162MCRegister DestReg = Inst.getOperand(0).getReg();1163MCRegister TmpReg = Inst.getOperand(1).getReg();1164const MCExpr *Symbol = Inst.getOperand(2).getExpr();1165InstSeq Insts;11661167Insts.push_back(LoongArchAsmParser::Inst(1168LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));1169Insts.push_back(LoongArchAsmParser::Inst(1170LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));1171Insts.push_back(LoongArchAsmParser::Inst(1172LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));1173Insts.push_back(LoongArchAsmParser::Inst(1174LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));1175Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));11761177emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1178}11791180void LoongArchAsmParser::emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc,1181MCStreamer &Out) {1182// `la.tls.desc $rd, sym` with `la-global-with-abs` feature1183// for la32 expands to:1184// lu12i.w $rd, %desc_hi20(sym)1185// ori $rd, $rd, %desc_lo12(sym)1186// ld.w $ra, $rd, %desc_ld(sym)1187// jirl $ra, $ra, %desc_call(sym)1188//1189// for la64 expands to:1190// lu12i.w $rd, %desc_hi20(sym)1191// ori $rd, $rd, %desc_lo12(sym)1192// lu32i.d $rd, %desc64_lo20(sym)1193// lu52i.d $rd, $rd, %desc64_hi12(sym)1194// ld.d $ra, $rd, %desc_ld(sym)1195// jirl $ra, $ra, %desc_call(sym)1196MCRegister DestReg = Inst.getOperand(0).getReg();1197const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_TLS_DESC_ABS1198? Inst.getOperand(1).getExpr()1199: Inst.getOperand(2).getExpr();1200unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;1201InstSeq Insts;12021203Insts.push_back(LoongArchAsmParser::Inst(1204LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20));1205Insts.push_back(LoongArchAsmParser::Inst(1206LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12));12071208if (is64Bit()) {1209Insts.push_back(LoongArchAsmParser::Inst(1210LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20));1211Insts.push_back(LoongArchAsmParser::Inst(1212LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12));1213}12141215Insts.push_back(1216LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));1217Insts.push_back(LoongArchAsmParser::Inst(1218LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));12191220emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1221}12221223void LoongArchAsmParser::emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc,1224MCStreamer &Out) {1225// la.tls.desc $rd, sym1226// expands to:1227// pcalau12i $rd, %desc_pc_hi20(sym)1228// addi.w/d $rd, $rd, %desc_pc_lo12(sym)1229// ld.w/d $ra, $rd, %desc_ld(sym)1230// jirl $ra, $ra, %desc_call(sym)1231MCRegister DestReg = Inst.getOperand(0).getReg();1232const MCExpr *Symbol = Inst.getOperand(1).getExpr();1233unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;1234unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;1235InstSeq Insts;12361237Insts.push_back(LoongArchAsmParser::Inst(1238LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));1239Insts.push_back(LoongArchAsmParser::Inst(1240ADDI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));1241Insts.push_back(1242LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));1243Insts.push_back(LoongArchAsmParser::Inst(1244LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));12451246emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);1247}12481249void LoongArchAsmParser::emitLoadAddressTLSDescPcrelLarge(MCInst &Inst,1250SMLoc IDLoc,1251MCStreamer &Out) {1252// la.tls.desc $rd, $rj, sym1253// expands to:1254// pcalau12i $rd, %desc_pc_hi20(sym)1255// addi.d $rj, $r0, %desc_pc_lo12(sym)1256// lu32i.d $rj, %desc64_pc_lo20(sym)1257// lu52i.d $rj, $rj, %desc64_pc_hi12(sym)1258// add.d $rd, $rd, $rj1259// ld.w/d $ra, $rd, %desc_ld(sym)1260// jirl $ra, $ra, %desc_call(sym)1261MCRegister DestReg = Inst.getOperand(0).getReg();1262MCRegister TmpReg = Inst.getOperand(1).getReg();1263const MCExpr *Symbol = Inst.getOperand(2).getExpr();1264InstSeq Insts;12651266Insts.push_back(LoongArchAsmParser::Inst(1267LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));1268Insts.push_back(LoongArchAsmParser::Inst(1269LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));1270Insts.push_back(LoongArchAsmParser::Inst(1271LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20));1272Insts.push_back(LoongArchAsmParser::Inst(1273LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12));1274Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));1275Insts.push_back(LoongArchAsmParser::Inst(1276LoongArch::LD_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));1277Insts.push_back(LoongArchAsmParser::Inst(1278LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));12791280emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);1281}12821283void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,1284MCStreamer &Out) {1285MCRegister DestReg = Inst.getOperand(0).getReg();1286int64_t Imm = Inst.getOperand(1).getImm();1287MCRegister SrcReg = LoongArch::R0;12881289if (Inst.getOpcode() == LoongArch::PseudoLI_W)1290Imm = SignExtend64<32>(Imm);12911292for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) {1293unsigned Opc = Inst.Opc;1294if (Opc == LoongArch::LU12I_W)1295Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm),1296getSTI());1297else1298Out.emitInstruction(1299MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm),1300getSTI());1301SrcReg = DestReg;1302}1303}13041305void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,1306MCStreamer &Out, bool IsTailCall) {1307// call36 sym1308// expands to:1309// pcaddu18i $ra, %call36(sym)1310// jirl $ra, $ra, 01311//1312// tail36 $rj, sym1313// expands to:1314// pcaddu18i $rj, %call36(sym)1315// jirl $r0, $rj, 01316unsigned ScratchReg =1317IsTailCall ? Inst.getOperand(0).getReg() : (unsigned)LoongArch::R1;1318const MCExpr *Sym =1319IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();1320const LoongArchMCExpr *LE = LoongArchMCExpr::create(1321Sym, llvm::LoongArchMCExpr::VK_LoongArch_CALL36, getContext());13221323Out.emitInstruction(1324MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),1325getSTI());1326Out.emitInstruction(1327MCInstBuilder(LoongArch::JIRL)1328.addReg(IsTailCall ? (unsigned)LoongArch::R0 : ScratchReg)1329.addReg(ScratchReg)1330.addImm(0),1331getSTI());1332}13331334bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,1335OperandVector &Operands,1336MCStreamer &Out) {1337Inst.setLoc(IDLoc);1338switch (Inst.getOpcode()) {1339default:1340break;1341case LoongArch::PseudoLA_ABS:1342case LoongArch::PseudoLA_ABS_LARGE:1343emitLoadAddressAbs(Inst, IDLoc, Out);1344return false;1345case LoongArch::PseudoLA_PCREL:1346emitLoadAddressPcrel(Inst, IDLoc, Out);1347return false;1348case LoongArch::PseudoLA_PCREL_LARGE:1349emitLoadAddressPcrelLarge(Inst, IDLoc, Out);1350return false;1351case LoongArch::PseudoLA_GOT:1352emitLoadAddressGot(Inst, IDLoc, Out);1353return false;1354case LoongArch::PseudoLA_GOT_LARGE:1355emitLoadAddressGotLarge(Inst, IDLoc, Out);1356return false;1357case LoongArch::PseudoLA_TLS_LE:1358emitLoadAddressTLSLE(Inst, IDLoc, Out);1359return false;1360case LoongArch::PseudoLA_TLS_IE:1361emitLoadAddressTLSIE(Inst, IDLoc, Out);1362return false;1363case LoongArch::PseudoLA_TLS_IE_LARGE:1364emitLoadAddressTLSIELarge(Inst, IDLoc, Out);1365return false;1366case LoongArch::PseudoLA_TLS_LD:1367emitLoadAddressTLSLD(Inst, IDLoc, Out);1368return false;1369case LoongArch::PseudoLA_TLS_LD_LARGE:1370emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);1371return false;1372case LoongArch::PseudoLA_TLS_GD:1373emitLoadAddressTLSGD(Inst, IDLoc, Out);1374return false;1375case LoongArch::PseudoLA_TLS_GD_LARGE:1376emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);1377return false;1378case LoongArch::PseudoLA_TLS_DESC_ABS:1379case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:1380emitLoadAddressTLSDescAbs(Inst, IDLoc, Out);1381return false;1382case LoongArch::PseudoLA_TLS_DESC_PC:1383emitLoadAddressTLSDescPcrel(Inst, IDLoc, Out);1384return false;1385case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:1386emitLoadAddressTLSDescPcrelLarge(Inst, IDLoc, Out);1387return false;1388case LoongArch::PseudoLI_W:1389case LoongArch::PseudoLI_D:1390emitLoadImm(Inst, IDLoc, Out);1391return false;1392case LoongArch::PseudoCALL36:1393emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);1394return false;1395case LoongArch::PseudoTAIL36:1396emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);1397return false;1398}1399Out.emitInstruction(Inst, getSTI());1400return false;1401}14021403unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {1404unsigned Opc = Inst.getOpcode();1405switch (Opc) {1406default:1407if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) {1408unsigned Rd = Inst.getOperand(0).getReg();1409unsigned Rk = Inst.getOperand(1).getReg();1410unsigned Rj = Inst.getOperand(2).getReg();1411if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)1412return Match_RequiresAMORdDifferRkRj;1413}1414break;1415case LoongArch::PseudoLA_TLS_DESC_ABS:1416case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:1417case LoongArch::PseudoLA_TLS_DESC_PC:1418case LoongArch::PseudoLA_TLS_DESC_PC_LARGE: {1419unsigned Rd = Inst.getOperand(0).getReg();1420if (Rd != LoongArch::R4)1421return Match_RequiresLAORdR4;1422break;1423}1424case LoongArch::PseudoLA_PCREL_LARGE:1425case LoongArch::PseudoLA_GOT_LARGE:1426case LoongArch::PseudoLA_TLS_IE_LARGE:1427case LoongArch::PseudoLA_TLS_LD_LARGE:1428case LoongArch::PseudoLA_TLS_GD_LARGE: {1429unsigned Rd = Inst.getOperand(0).getReg();1430unsigned Rj = Inst.getOperand(1).getReg();1431if (Rd == Rj)1432return Match_RequiresLAORdDifferRj;1433break;1434}1435case LoongArch::CSRXCHG:1436case LoongArch::GCSRXCHG: {1437unsigned Rj = Inst.getOperand(2).getReg();1438if (Rj == LoongArch::R0 || Rj == LoongArch::R1)1439return Match_RequiresOpnd2NotR0R1;1440return Match_Success;1441}1442case LoongArch::BSTRINS_W:1443case LoongArch::BSTRINS_D:1444case LoongArch::BSTRPICK_W:1445case LoongArch::BSTRPICK_D: {1446unsigned Opc = Inst.getOpcode();1447const signed Msb =1448(Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)1449? Inst.getOperand(3).getImm()1450: Inst.getOperand(2).getImm();1451const signed Lsb =1452(Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)1453? Inst.getOperand(4).getImm()1454: Inst.getOperand(3).getImm();1455if (Msb < Lsb)1456return Match_RequiresMsbNotLessThanLsb;1457return Match_Success;1458}1459}14601461return Match_Success;1462}14631464unsigned1465LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,1466unsigned Kind) {1467LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);1468if (!Op.isReg())1469return Match_InvalidOperand;14701471MCRegister Reg = Op.getReg();1472// As the parser couldn't differentiate an FPR32 from an FPR64, coerce the1473// register from FPR32 to FPR64 if necessary.1474if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&1475Kind == MCK_FPR64) {1476Op.setReg(convertFPR32ToFPR64(Reg));1477return Match_Success;1478}14791480return Match_InvalidOperand;1481}14821483bool LoongArchAsmParser::generateImmOutOfRangeError(1484OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,1485const Twine &Msg = "immediate must be an integer in the range") {1486SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1487return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");1488}14891490bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,1491OperandVector &Operands,1492MCStreamer &Out,1493uint64_t &ErrorInfo,1494bool MatchingInlineAsm) {1495MCInst Inst;1496FeatureBitset MissingFeatures;14971498auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,1499MatchingInlineAsm);1500switch (Result) {1501default:1502break;1503case Match_Success:1504return processInstruction(Inst, IDLoc, Operands, Out);1505case Match_MissingFeature: {1506assert(MissingFeatures.any() && "Unknown missing features!");1507bool FirstFeature = true;1508std::string Msg = "instruction requires the following:";1509for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {1510if (MissingFeatures[i]) {1511Msg += FirstFeature ? " " : ", ";1512Msg += getSubtargetFeatureName(i);1513FirstFeature = false;1514}1515}1516return Error(IDLoc, Msg);1517}1518case Match_MnemonicFail: {1519FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());1520std::string Suggestion = LoongArchMnemonicSpellCheck(1521((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0);1522return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);1523}1524case Match_InvalidOperand: {1525SMLoc ErrorLoc = IDLoc;1526if (ErrorInfo != ~0ULL) {1527if (ErrorInfo >= Operands.size())1528return Error(ErrorLoc, "too few operands for instruction");15291530ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1531if (ErrorLoc == SMLoc())1532ErrorLoc = IDLoc;1533}1534return Error(ErrorLoc, "invalid operand for instruction");1535}1536}15371538// Handle the case when the error message is of specific type1539// other than the generic Match_InvalidOperand, and the1540// corresponding operand is missing.1541if (Result > FIRST_TARGET_MATCH_RESULT_TY) {1542SMLoc ErrorLoc = IDLoc;1543if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())1544return Error(ErrorLoc, "too few operands for instruction");1545}15461547switch (Result) {1548default:1549break;1550case Match_RequiresMsbNotLessThanLsb: {1551SMLoc ErrorStart = Operands[3]->getStartLoc();1552return Error(ErrorStart, "msb is less than lsb",1553SMRange(ErrorStart, Operands[4]->getEndLoc()));1554}1555case Match_RequiresOpnd2NotR0R1:1556return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");1557case Match_RequiresAMORdDifferRkRj:1558return Error(Operands[1]->getStartLoc(),1559"$rd must be different from both $rk and $rj");1560case Match_RequiresLAORdDifferRj:1561return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");1562case Match_RequiresLAORdR4:1563return Error(Operands[1]->getStartLoc(), "$rd must be $r4");1564case Match_InvalidUImm1:1565return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1566/*Upper=*/(1 << 1) - 1);1567case Match_InvalidUImm2:1568return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1569/*Upper=*/(1 << 2) - 1);1570case Match_InvalidUImm2plus1:1571return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,1572/*Upper=*/(1 << 2));1573case Match_InvalidUImm3:1574return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1575/*Upper=*/(1 << 3) - 1);1576case Match_InvalidUImm4:1577return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1578/*Upper=*/(1 << 4) - 1);1579case Match_InvalidUImm5:1580return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1581/*Upper=*/(1 << 5) - 1);1582case Match_InvalidUImm6:1583return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1584/*Upper=*/(1 << 6) - 1);1585case Match_InvalidUImm7:1586return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1587/*Upper=*/(1 << 7) - 1);1588case Match_InvalidUImm8:1589return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1590/*Upper=*/(1 << 8) - 1);1591case Match_InvalidUImm12:1592return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1593/*Upper=*/(1 << 12) - 1);1594case Match_InvalidUImm12ori:1595return generateImmOutOfRangeError(1596Operands, ErrorInfo, /*Lower=*/0,1597/*Upper=*/(1 << 12) - 1,1598"operand must be a symbol with modifier (e.g. %abs_lo12) or an "1599"integer in the range");1600case Match_InvalidUImm14:1601return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1602/*Upper=*/(1 << 14) - 1);1603case Match_InvalidUImm15:1604return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,1605/*Upper=*/(1 << 15) - 1);1606case Match_InvalidSImm5:1607return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),1608/*Upper=*/(1 << 4) - 1);1609case Match_InvalidSImm8:1610return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),1611/*Upper=*/(1 << 7) - 1);1612case Match_InvalidSImm8lsl1:1613return generateImmOutOfRangeError(1614Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,1615"immediate must be a multiple of 2 in the range");1616case Match_InvalidSImm8lsl2:1617return generateImmOutOfRangeError(1618Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,1619"immediate must be a multiple of 4 in the range");1620case Match_InvalidSImm10:1621return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),1622/*Upper=*/(1 << 9) - 1);1623case Match_InvalidSImm8lsl3:1624return generateImmOutOfRangeError(1625Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,1626"immediate must be a multiple of 8 in the range");1627case Match_InvalidSImm9lsl3:1628return generateImmOutOfRangeError(1629Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,1630"immediate must be a multiple of 8 in the range");1631case Match_InvalidSImm10lsl2:1632return generateImmOutOfRangeError(1633Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,1634"immediate must be a multiple of 4 in the range");1635case Match_InvalidSImm11lsl1:1636return generateImmOutOfRangeError(1637Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,1638"immediate must be a multiple of 2 in the range");1639case Match_InvalidSImm12:1640return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),1641/*Upper=*/(1 << 11) - 1);1642case Match_InvalidSImm12addlike:1643return generateImmOutOfRangeError(1644Operands, ErrorInfo, /*Lower=*/-(1 << 11),1645/*Upper=*/(1 << 11) - 1,1646"operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "1647"in the range");1648case Match_InvalidSImm12lu52id:1649return generateImmOutOfRangeError(1650Operands, ErrorInfo, /*Lower=*/-(1 << 11),1651/*Upper=*/(1 << 11) - 1,1652"operand must be a symbol with modifier (e.g. %pc64_hi12) or an "1653"integer in the range");1654case Match_InvalidSImm13:1655return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),1656/*Upper=*/(1 << 12) - 1);1657case Match_InvalidSImm14lsl2:1658return generateImmOutOfRangeError(1659Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,1660"immediate must be a multiple of 4 in the range");1661case Match_InvalidSImm16:1662return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15),1663/*Upper=*/(1 << 15) - 1);1664case Match_InvalidSImm16lsl2:1665return generateImmOutOfRangeError(1666Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,1667"operand must be a symbol with modifier (e.g. %b16) or an integer "1668"in the range");1669case Match_InvalidSImm20:1670return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),1671/*Upper=*/(1 << 19) - 1);1672case Match_InvalidSImm20lu12iw:1673return generateImmOutOfRangeError(1674Operands, ErrorInfo, /*Lower=*/-(1 << 19),1675/*Upper=*/(1 << 19) - 1,1676"operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "1677"in the range");1678case Match_InvalidSImm20lu32id:1679return generateImmOutOfRangeError(1680Operands, ErrorInfo, /*Lower=*/-(1 << 19),1681/*Upper=*/(1 << 19) - 1,1682"operand must be a symbol with modifier (e.g. %abs64_lo20) or an "1683"integer in the range");1684case Match_InvalidSImm20pcalau12i:1685return generateImmOutOfRangeError(1686Operands, ErrorInfo, /*Lower=*/-(1 << 19),1687/*Upper=*/(1 << 19) - 1,1688"operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "1689"in the range");1690case Match_InvalidSImm20pcaddu18i:1691return generateImmOutOfRangeError(1692Operands, ErrorInfo, /*Lower=*/-(1 << 19),1693/*Upper=*/(1 << 19) - 1,1694"operand must be a symbol with modifier (e.g. %call36) or an integer "1695"in the range");1696case Match_InvalidSImm20pcaddi:1697return generateImmOutOfRangeError(1698Operands, ErrorInfo, /*Lower=*/-(1 << 19),1699/*Upper=*/(1 << 19) - 1,1700"operand must be a symbol with modifier (e.g. %pcrel_20) or an integer "1701"in the range");1702case Match_InvalidSImm21lsl2:1703return generateImmOutOfRangeError(1704Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,1705"operand must be a symbol with modifier (e.g. %b21) or an integer "1706"in the range");1707case Match_InvalidSImm26Operand:1708return generateImmOutOfRangeError(1709Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,1710"operand must be a bare symbol name or an immediate must be a multiple "1711"of 4 in the range");1712case Match_InvalidImm32: {1713SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1714return Error(ErrorLoc, "operand must be a 32 bit immediate");1715}1716case Match_InvalidImm64: {1717SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1718return Error(ErrorLoc, "operand must be a 64 bit immediate");1719}1720case Match_InvalidBareSymbol: {1721SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1722return Error(ErrorLoc, "operand must be a bare symbol name");1723}1724case Match_InvalidTPRelAddSymbol: {1725SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();1726return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");1727}1728}1729llvm_unreachable("Unknown match type detected!");1730}17311732extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() {1733RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target());1734RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target());1735}173617371738