181ad6265SDimitry Andric // LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "MCTargetDesc/LoongArchInstPrinter.h" 10bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchMCExpr.h" 1181ad6265SDimitry Andric #include "MCTargetDesc/LoongArchMCTargetDesc.h" 12bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchMatInt.h" 1381ad6265SDimitry Andric #include "TargetInfo/LoongArchTargetInfo.h" 1481ad6265SDimitry Andric #include "llvm/MC/MCContext.h" 15bdd1243dSDimitry Andric #include "llvm/MC/MCInstBuilder.h" 1681ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 1781ad6265SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 1881ad6265SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 1981ad6265SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h" 2081ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 2181ad6265SDimitry Andric #include "llvm/MC/MCStreamer.h" 2281ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 23bdd1243dSDimitry Andric #include "llvm/MC/MCValue.h" 2481ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 2581ad6265SDimitry Andric #include "llvm/Support/Casting.h" 2681ad6265SDimitry Andric 2781ad6265SDimitry Andric using namespace llvm; 2881ad6265SDimitry Andric 2981ad6265SDimitry Andric #define DEBUG_TYPE "loongarch-asm-parser" 3081ad6265SDimitry Andric 3181ad6265SDimitry Andric namespace { 3281ad6265SDimitry Andric class LoongArchAsmParser : public MCTargetAsmParser { 3381ad6265SDimitry Andric SMLoc getLoc() const { return getParser().getTok().getLoc(); } 34bdd1243dSDimitry Andric bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); } 35bdd1243dSDimitry Andric 36bdd1243dSDimitry Andric struct Inst { 37bdd1243dSDimitry Andric unsigned Opc; 38bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK; 39bdd1243dSDimitry Andric Inst(unsigned Opc, 40bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None) 41bdd1243dSDimitry Andric : Opc(Opc), VK(VK) {} 42bdd1243dSDimitry Andric }; 43bdd1243dSDimitry Andric using InstSeq = SmallVector<Inst>; 4481ad6265SDimitry Andric 4581ad6265SDimitry Andric /// Parse a register as used in CFI directives. 465f757f3fSDimitry Andric bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; 475f757f3fSDimitry Andric ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 4881ad6265SDimitry Andric SMLoc &EndLoc) override; 4981ad6265SDimitry Andric 5081ad6265SDimitry Andric bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 5181ad6265SDimitry Andric SMLoc NameLoc, OperandVector &Operands) override; 5281ad6265SDimitry Andric 5381ad6265SDimitry Andric bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 5481ad6265SDimitry Andric OperandVector &Operands, MCStreamer &Out, 5581ad6265SDimitry Andric uint64_t &ErrorInfo, 5681ad6265SDimitry Andric bool MatchingInlineAsm) override; 5781ad6265SDimitry Andric 5881ad6265SDimitry Andric unsigned checkTargetMatchPredicate(MCInst &Inst) override; 5981ad6265SDimitry Andric 6081ad6265SDimitry Andric unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 6181ad6265SDimitry Andric unsigned Kind) override; 6281ad6265SDimitry Andric 6381ad6265SDimitry Andric bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, 6406c3fb27SDimitry Andric int64_t Lower, int64_t Upper, 6506c3fb27SDimitry Andric const Twine &Msg); 6681ad6265SDimitry Andric 6781ad6265SDimitry Andric /// Helper for processing MC instructions that have been successfully matched 6881ad6265SDimitry Andric /// by MatchAndEmitInstruction. 6981ad6265SDimitry Andric bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, 7081ad6265SDimitry Andric MCStreamer &Out); 7181ad6265SDimitry Andric 7281ad6265SDimitry Andric // Auto-generated instruction matching functions. 7381ad6265SDimitry Andric #define GET_ASSEMBLER_HEADER 7481ad6265SDimitry Andric #include "LoongArchGenAsmMatcher.inc" 7581ad6265SDimitry Andric 7606c3fb27SDimitry Andric ParseStatus parseRegister(OperandVector &Operands); 7706c3fb27SDimitry Andric ParseStatus parseImmediate(OperandVector &Operands); 7806c3fb27SDimitry Andric ParseStatus parseOperandWithModifier(OperandVector &Operands); 7906c3fb27SDimitry Andric ParseStatus parseSImm26Operand(OperandVector &Operands); 8006c3fb27SDimitry Andric ParseStatus parseAtomicMemOp(OperandVector &Operands); 8181ad6265SDimitry Andric 8281ad6265SDimitry Andric bool parseOperand(OperandVector &Operands, StringRef Mnemonic); 8381ad6265SDimitry Andric 84bdd1243dSDimitry Andric // Helper to emit the sequence of instructions generated by the 85bdd1243dSDimitry Andric // "emitLoadAddress*" functions. 86bdd1243dSDimitry Andric void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, 87bdd1243dSDimitry Andric const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts, 88647cbc5dSDimitry Andric SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false); 89bdd1243dSDimitry Andric 90bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.abs $rd, sym". 91bdd1243dSDimitry Andric void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 92bdd1243dSDimitry Andric 93bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.pcrel $rd, sym". 94bdd1243dSDimitry Andric void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 95bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym". 96bdd1243dSDimitry Andric void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 97bdd1243dSDimitry Andric 98bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.got $rd, sym". 99bdd1243dSDimitry Andric void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 100bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.got $rd, $rj, sym". 101bdd1243dSDimitry Andric void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 102bdd1243dSDimitry Andric 103bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.le $rd, sym". 104bdd1243dSDimitry Andric void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 105bdd1243dSDimitry Andric 106bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.ie $rd, sym". 107bdd1243dSDimitry Andric void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 108bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym". 109bdd1243dSDimitry Andric void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.ld $rd, sym". 112bdd1243dSDimitry Andric void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 113bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym". 114bdd1243dSDimitry Andric void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 115bdd1243dSDimitry Andric 116bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.gd $rd, sym". 117bdd1243dSDimitry Andric void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 118bdd1243dSDimitry Andric // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym". 119bdd1243dSDimitry Andric void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 120bdd1243dSDimitry Andric 121bdd1243dSDimitry Andric // Helper to emit pseudo instruction "li.w/d $rd, $imm". 122bdd1243dSDimitry Andric void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 123bdd1243dSDimitry Andric 124*1db9f3b2SDimitry Andric // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym". 125*1db9f3b2SDimitry Andric void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, 126*1db9f3b2SDimitry Andric bool IsTailCall); 127*1db9f3b2SDimitry Andric 12881ad6265SDimitry Andric public: 12981ad6265SDimitry Andric enum LoongArchMatchResultTy { 13081ad6265SDimitry Andric Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 13181ad6265SDimitry Andric Match_RequiresMsbNotLessThanLsb, 13281ad6265SDimitry Andric Match_RequiresOpnd2NotR0R1, 133bdd1243dSDimitry Andric Match_RequiresAMORdDifferRkRj, 134bdd1243dSDimitry Andric Match_RequiresLAORdDifferRj, 13581ad6265SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES 13681ad6265SDimitry Andric #include "LoongArchGenAsmMatcher.inc" 13781ad6265SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES 13881ad6265SDimitry Andric }; 13981ad6265SDimitry Andric 140bdd1243dSDimitry Andric static bool classifySymbolRef(const MCExpr *Expr, 141bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind &Kind); 142bdd1243dSDimitry Andric 14381ad6265SDimitry Andric LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 14481ad6265SDimitry Andric const MCInstrInfo &MII, const MCTargetOptions &Options) 14581ad6265SDimitry Andric : MCTargetAsmParser(Options, STI, MII) { 14681ad6265SDimitry Andric Parser.addAliasForDirective(".half", ".2byte"); 14781ad6265SDimitry Andric Parser.addAliasForDirective(".hword", ".2byte"); 14881ad6265SDimitry Andric Parser.addAliasForDirective(".word", ".4byte"); 14981ad6265SDimitry Andric Parser.addAliasForDirective(".dword", ".8byte"); 15081ad6265SDimitry Andric 15181ad6265SDimitry Andric // Initialize the set of available features. 15281ad6265SDimitry Andric setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 15381ad6265SDimitry Andric } 15481ad6265SDimitry Andric }; 15581ad6265SDimitry Andric 15681ad6265SDimitry Andric // Instances of this class represent a parsed LoongArch machine instruction. 15781ad6265SDimitry Andric class LoongArchOperand : public MCParsedAsmOperand { 15881ad6265SDimitry Andric enum class KindTy { 15981ad6265SDimitry Andric Token, 16081ad6265SDimitry Andric Register, 16181ad6265SDimitry Andric Immediate, 16281ad6265SDimitry Andric } Kind; 16381ad6265SDimitry Andric 16481ad6265SDimitry Andric struct RegOp { 16581ad6265SDimitry Andric MCRegister RegNum; 16681ad6265SDimitry Andric }; 16781ad6265SDimitry Andric 16881ad6265SDimitry Andric struct ImmOp { 16981ad6265SDimitry Andric const MCExpr *Val; 17081ad6265SDimitry Andric }; 17181ad6265SDimitry Andric 17281ad6265SDimitry Andric SMLoc StartLoc, EndLoc; 17381ad6265SDimitry Andric union { 17481ad6265SDimitry Andric StringRef Tok; 17581ad6265SDimitry Andric struct RegOp Reg; 17681ad6265SDimitry Andric struct ImmOp Imm; 17781ad6265SDimitry Andric }; 17881ad6265SDimitry Andric 17981ad6265SDimitry Andric public: 18081ad6265SDimitry Andric LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 18181ad6265SDimitry Andric 18281ad6265SDimitry Andric bool isToken() const override { return Kind == KindTy::Token; } 18381ad6265SDimitry Andric bool isReg() const override { return Kind == KindTy::Register; } 18481ad6265SDimitry Andric bool isImm() const override { return Kind == KindTy::Immediate; } 18581ad6265SDimitry Andric bool isMem() const override { return false; } 18681ad6265SDimitry Andric void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; } 187bdd1243dSDimitry Andric bool isGPR() const { 188bdd1243dSDimitry Andric return Kind == KindTy::Register && 189bdd1243dSDimitry Andric LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains( 190bdd1243dSDimitry Andric Reg.RegNum); 191bdd1243dSDimitry Andric } 19281ad6265SDimitry Andric 193bdd1243dSDimitry Andric static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm, 194bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind &VK) { 195bdd1243dSDimitry Andric if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) { 196bdd1243dSDimitry Andric VK = LE->getKind(); 197bdd1243dSDimitry Andric return false; 198bdd1243dSDimitry Andric } 199bdd1243dSDimitry Andric 20081ad6265SDimitry Andric if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { 20181ad6265SDimitry Andric Imm = CE->getValue(); 20281ad6265SDimitry Andric return true; 20381ad6265SDimitry Andric } 20481ad6265SDimitry Andric 20581ad6265SDimitry Andric return false; 20681ad6265SDimitry Andric } 20781ad6265SDimitry Andric 20881ad6265SDimitry Andric template <unsigned N, int P = 0> bool isUImm() const { 20981ad6265SDimitry Andric if (!isImm()) 21081ad6265SDimitry Andric return false; 21181ad6265SDimitry Andric 21281ad6265SDimitry Andric int64_t Imm; 213bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 214bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 215bdd1243dSDimitry Andric return IsConstantImm && isUInt<N>(Imm - P) && 216bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_None; 21781ad6265SDimitry Andric } 21881ad6265SDimitry Andric 21981ad6265SDimitry Andric template <unsigned N, unsigned S = 0> bool isSImm() const { 22081ad6265SDimitry Andric if (!isImm()) 22181ad6265SDimitry Andric return false; 22281ad6265SDimitry Andric 22381ad6265SDimitry Andric int64_t Imm; 224bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 225bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 226bdd1243dSDimitry Andric return IsConstantImm && isShiftedInt<N, S>(Imm) && 227bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_None; 228bdd1243dSDimitry Andric } 229bdd1243dSDimitry Andric 230bdd1243dSDimitry Andric bool isBareSymbol() const { 231bdd1243dSDimitry Andric int64_t Imm; 232bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 233bdd1243dSDimitry Andric // Must be of 'immediate' type but not a constant. 234bdd1243dSDimitry Andric if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 235bdd1243dSDimitry Andric return false; 236bdd1243dSDimitry Andric return LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 237bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_None; 23881ad6265SDimitry Andric } 23981ad6265SDimitry Andric 24006c3fb27SDimitry Andric bool isUImm1() const { return isUImm<1>(); } 24181ad6265SDimitry Andric bool isUImm2() const { return isUImm<2>(); } 24281ad6265SDimitry Andric bool isUImm2plus1() const { return isUImm<2, 1>(); } 24381ad6265SDimitry Andric bool isUImm3() const { return isUImm<3>(); } 24406c3fb27SDimitry Andric bool isUImm4() const { return isUImm<4>(); } 24506c3fb27SDimitry Andric bool isSImm5() const { return isSImm<5>(); } 24681ad6265SDimitry Andric bool isUImm5() const { return isUImm<5>(); } 24781ad6265SDimitry Andric bool isUImm6() const { return isUImm<6>(); } 24806c3fb27SDimitry Andric bool isUImm7() const { return isUImm<7>(); } 24906c3fb27SDimitry Andric bool isSImm8() const { return isSImm<8>(); } 25006c3fb27SDimitry Andric bool isSImm8lsl1() const { return isSImm<8, 1>(); } 25106c3fb27SDimitry Andric bool isSImm8lsl2() const { return isSImm<8, 2>(); } 25206c3fb27SDimitry Andric bool isSImm8lsl3() const { return isSImm<8, 3>(); } 25381ad6265SDimitry Andric bool isUImm8() const { return isUImm<8>(); } 25406c3fb27SDimitry Andric bool isSImm9lsl3() const { return isSImm<9, 3>(); } 25506c3fb27SDimitry Andric bool isSImm10() const { return isSImm<10>(); } 25606c3fb27SDimitry Andric bool isSImm10lsl2() const { return isSImm<10, 2>(); } 25706c3fb27SDimitry Andric bool isSImm11lsl1() const { return isSImm<11, 1>(); } 258bdd1243dSDimitry Andric bool isSImm12() const { return isSImm<12>(); } 259bdd1243dSDimitry Andric 260bdd1243dSDimitry Andric bool isSImm12addlike() const { 261bdd1243dSDimitry Andric if (!isImm()) 262bdd1243dSDimitry Andric return false; 263bdd1243dSDimitry Andric 264bdd1243dSDimitry Andric int64_t Imm; 265bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 266bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 267bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 268bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 269bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 270bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 271bdd1243dSDimitry Andric return IsConstantImm 272bdd1243dSDimitry Andric ? isInt<12>(Imm) && IsValidKind 273bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 274bdd1243dSDimitry Andric IsValidKind; 275bdd1243dSDimitry Andric } 276bdd1243dSDimitry Andric 277bdd1243dSDimitry Andric bool isSImm12lu52id() const { 278bdd1243dSDimitry Andric if (!isImm()) 279bdd1243dSDimitry Andric return false; 280bdd1243dSDimitry Andric 281bdd1243dSDimitry Andric int64_t Imm; 282bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 283bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 284bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 285bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 || 286bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 || 287bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 || 288bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 || 289bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 || 290bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 || 291bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12; 292bdd1243dSDimitry Andric return IsConstantImm 293bdd1243dSDimitry Andric ? isInt<12>(Imm) && IsValidKind 294bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 295bdd1243dSDimitry Andric IsValidKind; 296bdd1243dSDimitry Andric } 297bdd1243dSDimitry Andric 29881ad6265SDimitry Andric bool isUImm12() const { return isUImm<12>(); } 299bdd1243dSDimitry Andric 300bdd1243dSDimitry Andric bool isUImm12ori() const { 301bdd1243dSDimitry Andric if (!isImm()) 302bdd1243dSDimitry Andric return false; 303bdd1243dSDimitry Andric 304bdd1243dSDimitry Andric int64_t Imm; 305bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 306bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 307bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 308bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 || 309bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 310bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 || 311bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 312bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 || 313bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 || 314bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 315bdd1243dSDimitry Andric return IsConstantImm 316bdd1243dSDimitry Andric ? isUInt<12>(Imm) && IsValidKind 317bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 318bdd1243dSDimitry Andric IsValidKind; 319bdd1243dSDimitry Andric } 320bdd1243dSDimitry Andric 32106c3fb27SDimitry Andric bool isSImm13() const { return isSImm<13>(); } 32281ad6265SDimitry Andric bool isUImm14() const { return isUImm<14>(); } 32381ad6265SDimitry Andric bool isUImm15() const { return isUImm<15>(); } 324bdd1243dSDimitry Andric 32581ad6265SDimitry Andric bool isSImm14lsl2() const { return isSImm<14, 2>(); } 32681ad6265SDimitry Andric bool isSImm16() const { return isSImm<16>(); } 327bdd1243dSDimitry Andric 328bdd1243dSDimitry Andric bool isSImm16lsl2() const { 329bdd1243dSDimitry Andric if (!isImm()) 330bdd1243dSDimitry Andric return false; 331bdd1243dSDimitry Andric 332bdd1243dSDimitry Andric int64_t Imm; 333bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 334bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 335bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 336bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_B16 || 337bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12; 338bdd1243dSDimitry Andric return IsConstantImm 339bdd1243dSDimitry Andric ? isShiftedInt<16, 2>(Imm) && IsValidKind 340bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 341bdd1243dSDimitry Andric IsValidKind; 342bdd1243dSDimitry Andric } 343bdd1243dSDimitry Andric 34481ad6265SDimitry Andric bool isSImm20() const { return isSImm<20>(); } 345bdd1243dSDimitry Andric 346bdd1243dSDimitry Andric bool isSImm20pcalau12i() const { 347bdd1243dSDimitry Andric if (!isImm()) 348bdd1243dSDimitry Andric return false; 349bdd1243dSDimitry Andric 350bdd1243dSDimitry Andric int64_t Imm; 351bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 352bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 353bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 354bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 || 355bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 || 356bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 || 357bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 || 358bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20; 359bdd1243dSDimitry Andric return IsConstantImm 360bdd1243dSDimitry Andric ? isInt<20>(Imm) && IsValidKind 361bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 362bdd1243dSDimitry Andric IsValidKind; 363bdd1243dSDimitry Andric } 364bdd1243dSDimitry Andric 365bdd1243dSDimitry Andric bool isSImm20lu12iw() const { 366bdd1243dSDimitry Andric if (!isImm()) 367bdd1243dSDimitry Andric return false; 368bdd1243dSDimitry Andric 369bdd1243dSDimitry Andric int64_t Imm; 370bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 371bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 372bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 373bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 || 374bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 || 375bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 || 376bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 || 377bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 || 378bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20; 379bdd1243dSDimitry Andric return IsConstantImm 380bdd1243dSDimitry Andric ? isInt<20>(Imm) && IsValidKind 381bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 382bdd1243dSDimitry Andric IsValidKind; 383bdd1243dSDimitry Andric } 384bdd1243dSDimitry Andric 385bdd1243dSDimitry Andric bool isSImm20lu32id() const { 386bdd1243dSDimitry Andric if (!isImm()) 387bdd1243dSDimitry Andric return false; 388bdd1243dSDimitry Andric 389bdd1243dSDimitry Andric int64_t Imm; 390bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 391bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 392bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 393bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 || 394bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 || 395bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 || 396bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 || 397bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 || 398bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 || 399bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20; 400bdd1243dSDimitry Andric 401bdd1243dSDimitry Andric return IsConstantImm 402bdd1243dSDimitry Andric ? isInt<20>(Imm) && IsValidKind 403bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 404bdd1243dSDimitry Andric IsValidKind; 405bdd1243dSDimitry Andric } 406bdd1243dSDimitry Andric 407*1db9f3b2SDimitry Andric bool isSImm20pcaddu18i() const { 408*1db9f3b2SDimitry Andric if (!isImm()) 409*1db9f3b2SDimitry Andric return false; 410*1db9f3b2SDimitry Andric 411*1db9f3b2SDimitry Andric int64_t Imm; 412*1db9f3b2SDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 413*1db9f3b2SDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 414*1db9f3b2SDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 415*1db9f3b2SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_CALL36; 416*1db9f3b2SDimitry Andric 417*1db9f3b2SDimitry Andric return IsConstantImm 418*1db9f3b2SDimitry Andric ? isInt<20>(Imm) && IsValidKind 419*1db9f3b2SDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 420*1db9f3b2SDimitry Andric IsValidKind; 421*1db9f3b2SDimitry Andric } 422*1db9f3b2SDimitry Andric 423bdd1243dSDimitry Andric bool isSImm21lsl2() const { 424bdd1243dSDimitry Andric if (!isImm()) 425bdd1243dSDimitry Andric return false; 426bdd1243dSDimitry Andric 427bdd1243dSDimitry Andric int64_t Imm; 428bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 429bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 430bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 431bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_B21; 432bdd1243dSDimitry Andric return IsConstantImm 433bdd1243dSDimitry Andric ? isShiftedInt<21, 2>(Imm) && IsValidKind 434bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 435bdd1243dSDimitry Andric IsValidKind; 436bdd1243dSDimitry Andric } 437bdd1243dSDimitry Andric 438bdd1243dSDimitry Andric bool isSImm26Operand() const { 439bdd1243dSDimitry Andric if (!isImm()) 440bdd1243dSDimitry Andric return false; 441bdd1243dSDimitry Andric 442bdd1243dSDimitry Andric int64_t Imm; 443bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 444bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 445bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 446bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_CALL || 447bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT || 448bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_B26; 449bdd1243dSDimitry Andric return IsConstantImm 450bdd1243dSDimitry Andric ? isShiftedInt<26, 2>(Imm) && IsValidKind 451bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 452bdd1243dSDimitry Andric IsValidKind; 453bdd1243dSDimitry Andric } 454bdd1243dSDimitry Andric 455bdd1243dSDimitry Andric bool isImm32() const { return isSImm<32>() || isUImm<32>(); } 45681ad6265SDimitry Andric 45781ad6265SDimitry Andric /// Gets location of the first token of this operand. 45881ad6265SDimitry Andric SMLoc getStartLoc() const override { return StartLoc; } 45981ad6265SDimitry Andric /// Gets location of the last token of this operand. 46081ad6265SDimitry Andric SMLoc getEndLoc() const override { return EndLoc; } 46181ad6265SDimitry Andric 46281ad6265SDimitry Andric unsigned getReg() const override { 46381ad6265SDimitry Andric assert(Kind == KindTy::Register && "Invalid type access!"); 46481ad6265SDimitry Andric return Reg.RegNum.id(); 46581ad6265SDimitry Andric } 46681ad6265SDimitry Andric 46781ad6265SDimitry Andric const MCExpr *getImm() const { 46881ad6265SDimitry Andric assert(Kind == KindTy::Immediate && "Invalid type access!"); 46981ad6265SDimitry Andric return Imm.Val; 47081ad6265SDimitry Andric } 47181ad6265SDimitry Andric 47281ad6265SDimitry Andric StringRef getToken() const { 47381ad6265SDimitry Andric assert(Kind == KindTy::Token && "Invalid type access!"); 47481ad6265SDimitry Andric return Tok; 47581ad6265SDimitry Andric } 47681ad6265SDimitry Andric 47781ad6265SDimitry Andric void print(raw_ostream &OS) const override { 478bdd1243dSDimitry Andric auto RegName = [](MCRegister Reg) { 47981ad6265SDimitry Andric if (Reg) 48081ad6265SDimitry Andric return LoongArchInstPrinter::getRegisterName(Reg); 48181ad6265SDimitry Andric else 48281ad6265SDimitry Andric return "noreg"; 48381ad6265SDimitry Andric }; 48481ad6265SDimitry Andric 48581ad6265SDimitry Andric switch (Kind) { 48681ad6265SDimitry Andric case KindTy::Immediate: 48781ad6265SDimitry Andric OS << *getImm(); 48881ad6265SDimitry Andric break; 48981ad6265SDimitry Andric case KindTy::Register: 49081ad6265SDimitry Andric OS << "<register " << RegName(getReg()) << ">"; 49181ad6265SDimitry Andric break; 49281ad6265SDimitry Andric case KindTy::Token: 49381ad6265SDimitry Andric OS << "'" << getToken() << "'"; 49481ad6265SDimitry Andric break; 49581ad6265SDimitry Andric } 49681ad6265SDimitry Andric } 49781ad6265SDimitry Andric 49881ad6265SDimitry Andric static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) { 49981ad6265SDimitry Andric auto Op = std::make_unique<LoongArchOperand>(KindTy::Token); 50081ad6265SDimitry Andric Op->Tok = Str; 50181ad6265SDimitry Andric Op->StartLoc = S; 50281ad6265SDimitry Andric Op->EndLoc = S; 50381ad6265SDimitry Andric return Op; 50481ad6265SDimitry Andric } 50581ad6265SDimitry Andric 50681ad6265SDimitry Andric static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S, 50781ad6265SDimitry Andric SMLoc E) { 50881ad6265SDimitry Andric auto Op = std::make_unique<LoongArchOperand>(KindTy::Register); 50981ad6265SDimitry Andric Op->Reg.RegNum = RegNo; 51081ad6265SDimitry Andric Op->StartLoc = S; 51181ad6265SDimitry Andric Op->EndLoc = E; 51281ad6265SDimitry Andric return Op; 51381ad6265SDimitry Andric } 51481ad6265SDimitry Andric 51581ad6265SDimitry Andric static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S, 51681ad6265SDimitry Andric SMLoc E) { 51781ad6265SDimitry Andric auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate); 51881ad6265SDimitry Andric Op->Imm.Val = Val; 51981ad6265SDimitry Andric Op->StartLoc = S; 52081ad6265SDimitry Andric Op->EndLoc = E; 52181ad6265SDimitry Andric return Op; 52281ad6265SDimitry Andric } 52381ad6265SDimitry Andric 52481ad6265SDimitry Andric void addExpr(MCInst &Inst, const MCExpr *Expr) const { 52581ad6265SDimitry Andric if (auto CE = dyn_cast<MCConstantExpr>(Expr)) 52681ad6265SDimitry Andric Inst.addOperand(MCOperand::createImm(CE->getValue())); 52781ad6265SDimitry Andric else 52881ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 52981ad6265SDimitry Andric } 53081ad6265SDimitry Andric 53181ad6265SDimitry Andric // Used by the TableGen Code. 53281ad6265SDimitry Andric void addRegOperands(MCInst &Inst, unsigned N) const { 53381ad6265SDimitry Andric assert(N == 1 && "Invalid number of operands!"); 53481ad6265SDimitry Andric Inst.addOperand(MCOperand::createReg(getReg())); 53581ad6265SDimitry Andric } 53681ad6265SDimitry Andric void addImmOperands(MCInst &Inst, unsigned N) const { 53781ad6265SDimitry Andric assert(N == 1 && "Invalid number of operands!"); 53881ad6265SDimitry Andric addExpr(Inst, getImm()); 53981ad6265SDimitry Andric } 54081ad6265SDimitry Andric }; 541972a253aSDimitry Andric } // end namespace 54281ad6265SDimitry Andric 54381ad6265SDimitry Andric #define GET_REGISTER_MATCHER 54481ad6265SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME 54581ad6265SDimitry Andric #define GET_MATCHER_IMPLEMENTATION 54681ad6265SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER 54781ad6265SDimitry Andric #include "LoongArchGenAsmMatcher.inc" 54881ad6265SDimitry Andric 54981ad6265SDimitry Andric static MCRegister convertFPR32ToFPR64(MCRegister Reg) { 55081ad6265SDimitry Andric assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register"); 55181ad6265SDimitry Andric return Reg - LoongArch::F0 + LoongArch::F0_64; 55281ad6265SDimitry Andric } 55381ad6265SDimitry Andric 55481ad6265SDimitry Andric // Attempts to match Name as a register (either using the default name or 55581ad6265SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon 55681ad6265SDimitry Andric // failure, returns true and sets RegNo to 0. 55781ad6265SDimitry Andric static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) { 55881ad6265SDimitry Andric RegNo = MatchRegisterName(Name); 55981ad6265SDimitry Andric // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial 56081ad6265SDimitry Andric // match always matches the 32-bit variant, and not the 64-bit one. 56181ad6265SDimitry Andric assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64)); 56281ad6265SDimitry Andric // The default FPR register class is based on the tablegen enum ordering. 56381ad6265SDimitry Andric static_assert(LoongArch::F0 < LoongArch::F0_64, 56481ad6265SDimitry Andric "FPR matching must be updated"); 56581ad6265SDimitry Andric if (RegNo == LoongArch::NoRegister) 56681ad6265SDimitry Andric RegNo = MatchRegisterAltName(Name); 56781ad6265SDimitry Andric 56881ad6265SDimitry Andric return RegNo == LoongArch::NoRegister; 56981ad6265SDimitry Andric } 57081ad6265SDimitry Andric 5715f757f3fSDimitry Andric bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, 57281ad6265SDimitry Andric SMLoc &EndLoc) { 57381ad6265SDimitry Andric return Error(getLoc(), "invalid register number"); 57481ad6265SDimitry Andric } 57581ad6265SDimitry Andric 5765f757f3fSDimitry Andric ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg, 57781ad6265SDimitry Andric SMLoc &StartLoc, 57881ad6265SDimitry Andric SMLoc &EndLoc) { 57981ad6265SDimitry Andric llvm_unreachable("Unimplemented function."); 58081ad6265SDimitry Andric } 58181ad6265SDimitry Andric 582bdd1243dSDimitry Andric bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr, 583bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind &Kind) { 584bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_None; 585bdd1243dSDimitry Andric 586bdd1243dSDimitry Andric if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) { 587bdd1243dSDimitry Andric Kind = RE->getKind(); 588bdd1243dSDimitry Andric Expr = RE->getSubExpr(); 589bdd1243dSDimitry Andric } 590bdd1243dSDimitry Andric 591bdd1243dSDimitry Andric MCValue Res; 592bdd1243dSDimitry Andric if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr)) 593bdd1243dSDimitry Andric return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None; 594bdd1243dSDimitry Andric return false; 595bdd1243dSDimitry Andric } 596bdd1243dSDimitry Andric 59706c3fb27SDimitry Andric ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) { 59806c3fb27SDimitry Andric if (!parseOptionalToken(AsmToken::Dollar)) 59906c3fb27SDimitry Andric return ParseStatus::NoMatch; 60081ad6265SDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) 60106c3fb27SDimitry Andric return ParseStatus::NoMatch; 60281ad6265SDimitry Andric 60381ad6265SDimitry Andric StringRef Name = getLexer().getTok().getIdentifier(); 60481ad6265SDimitry Andric MCRegister RegNo; 60581ad6265SDimitry Andric matchRegisterNameHelper(RegNo, Name); 60681ad6265SDimitry Andric if (RegNo == LoongArch::NoRegister) 60706c3fb27SDimitry Andric return ParseStatus::NoMatch; 60881ad6265SDimitry Andric 60981ad6265SDimitry Andric SMLoc S = getLoc(); 61081ad6265SDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); 61181ad6265SDimitry Andric getLexer().Lex(); 61281ad6265SDimitry Andric Operands.push_back(LoongArchOperand::createReg(RegNo, S, E)); 61381ad6265SDimitry Andric 61406c3fb27SDimitry Andric return ParseStatus::Success; 61581ad6265SDimitry Andric } 61681ad6265SDimitry Andric 61706c3fb27SDimitry Andric ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) { 61881ad6265SDimitry Andric SMLoc S = getLoc(); 61981ad6265SDimitry Andric SMLoc E; 62081ad6265SDimitry Andric const MCExpr *Res; 62181ad6265SDimitry Andric 622bdd1243dSDimitry Andric switch (getLexer().getKind()) { 623bdd1243dSDimitry Andric default: 62406c3fb27SDimitry Andric return ParseStatus::NoMatch; 625bdd1243dSDimitry Andric case AsmToken::LParen: 626bdd1243dSDimitry Andric case AsmToken::Dot: 627bdd1243dSDimitry Andric case AsmToken::Minus: 628bdd1243dSDimitry Andric case AsmToken::Plus: 629bdd1243dSDimitry Andric case AsmToken::Exclaim: 630bdd1243dSDimitry Andric case AsmToken::Tilde: 631bdd1243dSDimitry Andric case AsmToken::Integer: 632bdd1243dSDimitry Andric case AsmToken::String: 633bdd1243dSDimitry Andric case AsmToken::Identifier: 63481ad6265SDimitry Andric if (getParser().parseExpression(Res, E)) 63506c3fb27SDimitry Andric return ParseStatus::Failure; 636bdd1243dSDimitry Andric break; 637bdd1243dSDimitry Andric case AsmToken::Percent: 638bdd1243dSDimitry Andric return parseOperandWithModifier(Operands); 639bdd1243dSDimitry Andric } 64081ad6265SDimitry Andric 64181ad6265SDimitry Andric Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 64206c3fb27SDimitry Andric return ParseStatus::Success; 64381ad6265SDimitry Andric } 64481ad6265SDimitry Andric 64506c3fb27SDimitry Andric ParseStatus 646bdd1243dSDimitry Andric LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) { 647bdd1243dSDimitry Andric SMLoc S = getLoc(); 648bdd1243dSDimitry Andric SMLoc E; 649bdd1243dSDimitry Andric 65006c3fb27SDimitry Andric if (getLexer().getKind() != AsmToken::Percent) 65106c3fb27SDimitry Andric return Error(getLoc(), "expected '%' for operand modifier"); 652bdd1243dSDimitry Andric 653bdd1243dSDimitry Andric getParser().Lex(); // Eat '%' 654bdd1243dSDimitry Andric 65506c3fb27SDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) 65606c3fb27SDimitry Andric return Error(getLoc(), "expected valid identifier for operand modifier"); 657bdd1243dSDimitry Andric StringRef Identifier = getParser().getTok().getIdentifier(); 658bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = 659bdd1243dSDimitry Andric LoongArchMCExpr::getVariantKindForName(Identifier); 66006c3fb27SDimitry Andric if (VK == LoongArchMCExpr::VK_LoongArch_Invalid) 66106c3fb27SDimitry Andric return Error(getLoc(), "unrecognized operand modifier"); 662bdd1243dSDimitry Andric 663bdd1243dSDimitry Andric getParser().Lex(); // Eat the identifier 66406c3fb27SDimitry Andric if (getLexer().getKind() != AsmToken::LParen) 66506c3fb27SDimitry Andric return Error(getLoc(), "expected '('"); 666bdd1243dSDimitry Andric getParser().Lex(); // Eat '(' 667bdd1243dSDimitry Andric 668bdd1243dSDimitry Andric const MCExpr *SubExpr; 66906c3fb27SDimitry Andric if (getParser().parseParenExpression(SubExpr, E)) 67006c3fb27SDimitry Andric return ParseStatus::Failure; 671bdd1243dSDimitry Andric 672bdd1243dSDimitry Andric const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext()); 673bdd1243dSDimitry Andric Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E)); 67406c3fb27SDimitry Andric return ParseStatus::Success; 675bdd1243dSDimitry Andric } 676bdd1243dSDimitry Andric 67706c3fb27SDimitry Andric ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) { 678bdd1243dSDimitry Andric SMLoc S = getLoc(); 679bdd1243dSDimitry Andric const MCExpr *Res; 680bdd1243dSDimitry Andric 681bdd1243dSDimitry Andric if (getLexer().getKind() == AsmToken::Percent) 682bdd1243dSDimitry Andric return parseOperandWithModifier(Operands); 683bdd1243dSDimitry Andric 684bdd1243dSDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) 68506c3fb27SDimitry Andric return ParseStatus::NoMatch; 686bdd1243dSDimitry Andric 687bdd1243dSDimitry Andric StringRef Identifier; 688bdd1243dSDimitry Andric if (getParser().parseIdentifier(Identifier)) 68906c3fb27SDimitry Andric return ParseStatus::Failure; 690bdd1243dSDimitry Andric 691bdd1243dSDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size()); 692bdd1243dSDimitry Andric 693bdd1243dSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 694bdd1243dSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 695bdd1243dSDimitry Andric Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL, 696bdd1243dSDimitry Andric getContext()); 697bdd1243dSDimitry Andric Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 69806c3fb27SDimitry Andric return ParseStatus::Success; 699bdd1243dSDimitry Andric } 700bdd1243dSDimitry Andric 70106c3fb27SDimitry Andric ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) { 702bdd1243dSDimitry Andric // Parse "$r*". 70306c3fb27SDimitry Andric if (!parseRegister(Operands).isSuccess()) 70406c3fb27SDimitry Andric return ParseStatus::NoMatch; 705bdd1243dSDimitry Andric 706bdd1243dSDimitry Andric // If there is a next operand and it is 0, ignore it. Otherwise print a 707bdd1243dSDimitry Andric // diagnostic message. 70806c3fb27SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) { 709bdd1243dSDimitry Andric int64_t ImmVal; 710bdd1243dSDimitry Andric SMLoc ImmStart = getLoc(); 711bdd1243dSDimitry Andric if (getParser().parseIntToken(ImmVal, "expected optional integer offset")) 71206c3fb27SDimitry Andric return ParseStatus::Failure; 71306c3fb27SDimitry Andric if (ImmVal) 71406c3fb27SDimitry Andric return Error(ImmStart, "optional integer offset must be 0"); 715bdd1243dSDimitry Andric } 716bdd1243dSDimitry Andric 71706c3fb27SDimitry Andric return ParseStatus::Success; 718bdd1243dSDimitry Andric } 71981ad6265SDimitry Andric /// Looks at a token type and creates the relevant operand from this 72081ad6265SDimitry Andric /// information, adding to Operands. Return true upon an error. 72181ad6265SDimitry Andric bool LoongArchAsmParser::parseOperand(OperandVector &Operands, 72281ad6265SDimitry Andric StringRef Mnemonic) { 723bdd1243dSDimitry Andric // Check if the current operand has a custom associated parser, if so, try to 724bdd1243dSDimitry Andric // custom parse the operand, or fallback to the general approach. 72506c3fb27SDimitry Andric ParseStatus Result = 726bdd1243dSDimitry Andric MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true); 72706c3fb27SDimitry Andric if (Result.isSuccess()) 728bdd1243dSDimitry Andric return false; 72906c3fb27SDimitry Andric if (Result.isFailure()) 730bdd1243dSDimitry Andric return true; 731bdd1243dSDimitry Andric 73206c3fb27SDimitry Andric if (parseRegister(Operands).isSuccess() || 73306c3fb27SDimitry Andric parseImmediate(Operands).isSuccess()) 73481ad6265SDimitry Andric return false; 73581ad6265SDimitry Andric 73681ad6265SDimitry Andric // Finally we have exhausted all options and must declare defeat. 73706c3fb27SDimitry Andric return Error(getLoc(), "unknown operand"); 73881ad6265SDimitry Andric } 73981ad6265SDimitry Andric 74081ad6265SDimitry Andric bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, 74181ad6265SDimitry Andric StringRef Name, SMLoc NameLoc, 74281ad6265SDimitry Andric OperandVector &Operands) { 74381ad6265SDimitry Andric // First operand in MCInst is instruction mnemonic. 74481ad6265SDimitry Andric Operands.push_back(LoongArchOperand::createToken(Name, NameLoc)); 74581ad6265SDimitry Andric 74681ad6265SDimitry Andric // If there are no more operands, then finish. 74781ad6265SDimitry Andric if (parseOptionalToken(AsmToken::EndOfStatement)) 74881ad6265SDimitry Andric return false; 74981ad6265SDimitry Andric 75081ad6265SDimitry Andric // Parse first operand. 75181ad6265SDimitry Andric if (parseOperand(Operands, Name)) 75281ad6265SDimitry Andric return true; 75381ad6265SDimitry Andric 75481ad6265SDimitry Andric // Parse until end of statement, consuming commas between operands. 75581ad6265SDimitry Andric while (parseOptionalToken(AsmToken::Comma)) 75681ad6265SDimitry Andric if (parseOperand(Operands, Name)) 75781ad6265SDimitry Andric return true; 75881ad6265SDimitry Andric 75981ad6265SDimitry Andric // Parse end of statement and return successfully. 76081ad6265SDimitry Andric if (parseOptionalToken(AsmToken::EndOfStatement)) 76181ad6265SDimitry Andric return false; 76281ad6265SDimitry Andric 76381ad6265SDimitry Andric SMLoc Loc = getLexer().getLoc(); 76481ad6265SDimitry Andric getParser().eatToEndOfStatement(); 76581ad6265SDimitry Andric return Error(Loc, "unexpected token"); 76681ad6265SDimitry Andric } 76781ad6265SDimitry Andric 768bdd1243dSDimitry Andric void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, 769bdd1243dSDimitry Andric const MCExpr *Symbol, 770bdd1243dSDimitry Andric SmallVectorImpl<Inst> &Insts, 771647cbc5dSDimitry Andric SMLoc IDLoc, MCStreamer &Out, 772647cbc5dSDimitry Andric bool RelaxHint) { 773bdd1243dSDimitry Andric MCContext &Ctx = getContext(); 774bdd1243dSDimitry Andric for (LoongArchAsmParser::Inst &Inst : Insts) { 775bdd1243dSDimitry Andric unsigned Opc = Inst.Opc; 776bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = Inst.VK; 777647cbc5dSDimitry Andric const LoongArchMCExpr *LE = 778647cbc5dSDimitry Andric LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint); 779bdd1243dSDimitry Andric switch (Opc) { 780bdd1243dSDimitry Andric default: 781bdd1243dSDimitry Andric llvm_unreachable("unexpected opcode"); 782bdd1243dSDimitry Andric case LoongArch::PCALAU12I: 783bdd1243dSDimitry Andric case LoongArch::LU12I_W: 784bdd1243dSDimitry Andric Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE), 785bdd1243dSDimitry Andric getSTI()); 786bdd1243dSDimitry Andric break; 787bdd1243dSDimitry Andric case LoongArch::ORI: 788bdd1243dSDimitry Andric case LoongArch::ADDI_W: 789bdd1243dSDimitry Andric case LoongArch::LD_W: 790bdd1243dSDimitry Andric case LoongArch::LD_D: { 791bdd1243dSDimitry Andric if (VK == LoongArchMCExpr::VK_LoongArch_None) { 792bdd1243dSDimitry Andric Out.emitInstruction( 793bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0), 794bdd1243dSDimitry Andric getSTI()); 795bdd1243dSDimitry Andric continue; 796bdd1243dSDimitry Andric } 797bdd1243dSDimitry Andric Out.emitInstruction( 798bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE), 799bdd1243dSDimitry Andric getSTI()); 800bdd1243dSDimitry Andric break; 801bdd1243dSDimitry Andric } 802bdd1243dSDimitry Andric case LoongArch::LU32I_D: 803bdd1243dSDimitry Andric Out.emitInstruction(MCInstBuilder(Opc) 804bdd1243dSDimitry Andric .addReg(DestReg == TmpReg ? DestReg : TmpReg) 805bdd1243dSDimitry Andric .addReg(DestReg == TmpReg ? DestReg : TmpReg) 806bdd1243dSDimitry Andric .addExpr(LE), 807bdd1243dSDimitry Andric getSTI()); 808bdd1243dSDimitry Andric break; 809bdd1243dSDimitry Andric case LoongArch::LU52I_D: 810bdd1243dSDimitry Andric Out.emitInstruction( 811bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE), 812bdd1243dSDimitry Andric getSTI()); 813bdd1243dSDimitry Andric break; 814bdd1243dSDimitry Andric case LoongArch::ADDI_D: 815bdd1243dSDimitry Andric Out.emitInstruction( 816bdd1243dSDimitry Andric MCInstBuilder(Opc) 817bdd1243dSDimitry Andric .addReg(TmpReg) 818bdd1243dSDimitry Andric .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0) 819bdd1243dSDimitry Andric .addExpr(LE), 820bdd1243dSDimitry Andric getSTI()); 821bdd1243dSDimitry Andric break; 822bdd1243dSDimitry Andric case LoongArch::ADD_D: 823bdd1243dSDimitry Andric case LoongArch::LDX_D: 824bdd1243dSDimitry Andric Out.emitInstruction( 825bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg), 826bdd1243dSDimitry Andric getSTI()); 827bdd1243dSDimitry Andric break; 828bdd1243dSDimitry Andric } 829bdd1243dSDimitry Andric } 830bdd1243dSDimitry Andric } 831bdd1243dSDimitry Andric 832bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, 833bdd1243dSDimitry Andric MCStreamer &Out) { 834bdd1243dSDimitry Andric // la.abs $rd, sym 835bdd1243dSDimitry Andric // expands to: 836bdd1243dSDimitry Andric // lu12i.w $rd, %abs_hi20(sym) 837bdd1243dSDimitry Andric // ori $rd, $rd, %abs_lo12(sym) 838bdd1243dSDimitry Andric // 839bdd1243dSDimitry Andric // for 64bit appends: 840bdd1243dSDimitry Andric // lu32i.d $rd, %abs64_lo20(sym) 841bdd1243dSDimitry Andric // lu52i.d $rd, $rd, %abs64_hi12(sym) 842bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 843bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS 844bdd1243dSDimitry Andric ? Inst.getOperand(1).getExpr() 845bdd1243dSDimitry Andric : Inst.getOperand(2).getExpr(); 846bdd1243dSDimitry Andric InstSeq Insts; 847bdd1243dSDimitry Andric 848bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 849bdd1243dSDimitry Andric LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20)); 850bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 851bdd1243dSDimitry Andric LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12)); 852bdd1243dSDimitry Andric 853bdd1243dSDimitry Andric if (is64Bit()) { 854bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 855bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20)); 856bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 857bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12)); 858bdd1243dSDimitry Andric } 859bdd1243dSDimitry Andric 860bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 861bdd1243dSDimitry Andric } 862bdd1243dSDimitry Andric 863bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, 864bdd1243dSDimitry Andric MCStreamer &Out) { 865bdd1243dSDimitry Andric // la.pcrel $rd, sym 866bdd1243dSDimitry Andric // expands to: 867bdd1243dSDimitry Andric // pcalau12i $rd, %pc_hi20(sym) 868bdd1243dSDimitry Andric // addi.w/d $rd, rd, %pc_lo12(sym) 869bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 870bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 871bdd1243dSDimitry Andric InstSeq Insts; 872bdd1243dSDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 873bdd1243dSDimitry Andric 874bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 875bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 876bdd1243dSDimitry Andric Insts.push_back( 877bdd1243dSDimitry Andric LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 878bdd1243dSDimitry Andric 879647cbc5dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true); 880bdd1243dSDimitry Andric } 881bdd1243dSDimitry Andric 882bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, 883bdd1243dSDimitry Andric MCStreamer &Out) { 884bdd1243dSDimitry Andric // la.pcrel $rd, $rj, sym 885bdd1243dSDimitry Andric // expands to: 886bdd1243dSDimitry Andric // pcalau12i $rd, %pc_hi20(sym) 887bdd1243dSDimitry Andric // addi.d $rj, $r0, %pc_lo12(sym) 888bdd1243dSDimitry Andric // lu32i.d $rj, %pc64_lo20(sym) 889bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %pc64_hi12(sym) 890bdd1243dSDimitry Andric // add.d $rd, $rd, $rj 891bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 892bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 893bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 894bdd1243dSDimitry Andric InstSeq Insts; 895bdd1243dSDimitry Andric 896bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 897bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 898bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 899bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 900bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 901bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20)); 902bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 903bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12)); 904bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 905bdd1243dSDimitry Andric 906bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 907bdd1243dSDimitry Andric } 908bdd1243dSDimitry Andric 909bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, 910bdd1243dSDimitry Andric MCStreamer &Out) { 911bdd1243dSDimitry Andric // la.got $rd, sym 912bdd1243dSDimitry Andric // expands to: 913bdd1243dSDimitry Andric // pcalau12i $rd, %got_pc_hi20(sym) 914bdd1243dSDimitry Andric // ld.w/d $rd, $rd, %got_pc_lo12(sym) 915bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 916bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 917bdd1243dSDimitry Andric InstSeq Insts; 918bdd1243dSDimitry Andric unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 919bdd1243dSDimitry Andric 920bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 921bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 922bdd1243dSDimitry Andric Insts.push_back( 923bdd1243dSDimitry Andric LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 924bdd1243dSDimitry Andric 925647cbc5dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true); 926bdd1243dSDimitry Andric } 927bdd1243dSDimitry Andric 928bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, 929bdd1243dSDimitry Andric MCStreamer &Out) { 930bdd1243dSDimitry Andric // la.got $rd, $rj, sym 931bdd1243dSDimitry Andric // expands to: 932bdd1243dSDimitry Andric // pcalau12i $rd, %got_pc_hi20(sym) 933bdd1243dSDimitry Andric // addi.d $rj, $r0, %got_pc_lo12(sym) 934bdd1243dSDimitry Andric // lu32i.d $rj, %got64_pc_lo20(sym) 935bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 936bdd1243dSDimitry Andric // ldx.d $rd, $rd, $rj 937bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 938bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 939bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 940bdd1243dSDimitry Andric InstSeq Insts; 941bdd1243dSDimitry Andric 942bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 943bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 944bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 945bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 946bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 947bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 948bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 949bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 950bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 951bdd1243dSDimitry Andric 952bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 953bdd1243dSDimitry Andric } 954bdd1243dSDimitry Andric 955bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, 956bdd1243dSDimitry Andric MCStreamer &Out) { 957bdd1243dSDimitry Andric // la.tls.le $rd, sym 958bdd1243dSDimitry Andric // expands to: 959bdd1243dSDimitry Andric // lu12i.w $rd, %le_hi20(sym) 960bdd1243dSDimitry Andric // ori $rd, $rd, %le_lo12(sym) 961bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 962bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 963bdd1243dSDimitry Andric InstSeq Insts; 964bdd1243dSDimitry Andric 965bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 966bdd1243dSDimitry Andric LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20)); 967bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 968bdd1243dSDimitry Andric LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12)); 969bdd1243dSDimitry Andric 970bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 971bdd1243dSDimitry Andric } 972bdd1243dSDimitry Andric 973bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, 974bdd1243dSDimitry Andric MCStreamer &Out) { 975bdd1243dSDimitry Andric // la.tls.ie $rd, sym 976bdd1243dSDimitry Andric // expands to: 977bdd1243dSDimitry Andric // pcalau12i $rd, %ie_pc_hi20(sym) 978bdd1243dSDimitry Andric // ld.w/d $rd, $rd, %ie_pc_lo12(sym) 979bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 980bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 981bdd1243dSDimitry Andric InstSeq Insts; 982bdd1243dSDimitry Andric unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 983bdd1243dSDimitry Andric 984bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 985bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 986bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 987bdd1243dSDimitry Andric LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 988bdd1243dSDimitry Andric 989bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 990bdd1243dSDimitry Andric } 991bdd1243dSDimitry Andric 992bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, 993bdd1243dSDimitry Andric MCStreamer &Out) { 994bdd1243dSDimitry Andric // la.tls.ie $rd, $rj, sym 995bdd1243dSDimitry Andric // expands to: 996bdd1243dSDimitry Andric // pcalau12i $rd, %ie_pc_hi20(sym) 997bdd1243dSDimitry Andric // addi.d $rj, $r0, %ie_pc_lo12(sym) 998bdd1243dSDimitry Andric // lu32i.d $rj, %ie64_pc_lo20(sym) 999bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %ie64_pc_hi12(sym) 1000bdd1243dSDimitry Andric // ldx.d $rd, $rd, $rj 1001bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1002bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 1003bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1004bdd1243dSDimitry Andric InstSeq Insts; 1005bdd1243dSDimitry Andric 1006bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1007bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 1008bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1009bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 1010bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1011bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20)); 1012bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1013bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12)); 1014bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 1015bdd1243dSDimitry Andric 1016bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1017bdd1243dSDimitry Andric } 1018bdd1243dSDimitry Andric 1019bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, 1020bdd1243dSDimitry Andric MCStreamer &Out) { 1021bdd1243dSDimitry Andric // la.tls.ld $rd, sym 1022bdd1243dSDimitry Andric // expands to: 1023bdd1243dSDimitry Andric // pcalau12i $rd, %ld_pc_hi20(sym) 1024bdd1243dSDimitry Andric // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1025bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1026bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1027bdd1243dSDimitry Andric InstSeq Insts; 1028bdd1243dSDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1029bdd1243dSDimitry Andric 1030bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1031bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1032bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1033bdd1243dSDimitry Andric ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1034bdd1243dSDimitry Andric 1035bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1036bdd1243dSDimitry Andric } 1037bdd1243dSDimitry Andric 1038bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, 1039bdd1243dSDimitry Andric MCStreamer &Out) { 1040bdd1243dSDimitry Andric // la.tls.ld $rd, $rj, sym 1041bdd1243dSDimitry Andric // expands to: 1042bdd1243dSDimitry Andric // pcalau12i $rd, %ld_pc_hi20(sym) 1043bdd1243dSDimitry Andric // addi.d $rj, $r0, %got_pc_lo12(sym) 1044bdd1243dSDimitry Andric // lu32i.d $rj, %got64_pc_lo20(sym) 1045bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1046bdd1243dSDimitry Andric // add.d $rd, $rd, $rj 1047bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1048bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 1049bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1050bdd1243dSDimitry Andric InstSeq Insts; 1051bdd1243dSDimitry Andric 1052bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1053bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1054bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1055bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1056bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1057bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1058bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1059bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1060bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1061bdd1243dSDimitry Andric 1062bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1063bdd1243dSDimitry Andric } 1064bdd1243dSDimitry Andric 1065bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, 1066bdd1243dSDimitry Andric MCStreamer &Out) { 1067bdd1243dSDimitry Andric // la.tls.gd $rd, sym 1068bdd1243dSDimitry Andric // expands to: 1069bdd1243dSDimitry Andric // pcalau12i $rd, %gd_pc_hi20(sym) 1070bdd1243dSDimitry Andric // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1071bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1072bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1073bdd1243dSDimitry Andric InstSeq Insts; 1074bdd1243dSDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1075bdd1243dSDimitry Andric 1076bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1077bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1078bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1079bdd1243dSDimitry Andric ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1080bdd1243dSDimitry Andric 1081bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1082bdd1243dSDimitry Andric } 1083bdd1243dSDimitry Andric 1084bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, 1085bdd1243dSDimitry Andric MCStreamer &Out) { 1086bdd1243dSDimitry Andric // la.tls.gd $rd, $rj, sym 1087bdd1243dSDimitry Andric // expands to: 1088bdd1243dSDimitry Andric // pcalau12i $rd, %gd_pc_hi20(sym) 1089bdd1243dSDimitry Andric // addi.d $rj, $r0, %got_pc_lo12(sym) 1090bdd1243dSDimitry Andric // lu32i.d $rj, %got64_pc_lo20(sym) 1091bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1092bdd1243dSDimitry Andric // add.d $rd, $rd, $rj 1093bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1094bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 1095bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1096bdd1243dSDimitry Andric InstSeq Insts; 1097bdd1243dSDimitry Andric 1098bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1099bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1100bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1101bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1102bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1103bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1104bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1105bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1106bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1107bdd1243dSDimitry Andric 1108bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1109bdd1243dSDimitry Andric } 1110bdd1243dSDimitry Andric 1111bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc, 1112bdd1243dSDimitry Andric MCStreamer &Out) { 1113bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1114bdd1243dSDimitry Andric int64_t Imm = Inst.getOperand(1).getImm(); 1115bdd1243dSDimitry Andric MCRegister SrcReg = LoongArch::R0; 1116bdd1243dSDimitry Andric 1117bdd1243dSDimitry Andric if (Inst.getOpcode() == LoongArch::PseudoLI_W) 1118bdd1243dSDimitry Andric Imm = SignExtend64<32>(Imm); 1119bdd1243dSDimitry Andric 1120bdd1243dSDimitry Andric for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) { 1121bdd1243dSDimitry Andric unsigned Opc = Inst.Opc; 1122bdd1243dSDimitry Andric if (Opc == LoongArch::LU12I_W) 1123bdd1243dSDimitry Andric Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm), 1124bdd1243dSDimitry Andric getSTI()); 1125bdd1243dSDimitry Andric else 1126bdd1243dSDimitry Andric Out.emitInstruction( 1127bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm), 1128bdd1243dSDimitry Andric getSTI()); 1129bdd1243dSDimitry Andric SrcReg = DestReg; 1130bdd1243dSDimitry Andric } 1131bdd1243dSDimitry Andric } 1132bdd1243dSDimitry Andric 1133*1db9f3b2SDimitry Andric void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc, 1134*1db9f3b2SDimitry Andric MCStreamer &Out, bool IsTailCall) { 1135*1db9f3b2SDimitry Andric // call36 sym 1136*1db9f3b2SDimitry Andric // expands to: 1137*1db9f3b2SDimitry Andric // pcaddu18i $ra, %call36(sym) 1138*1db9f3b2SDimitry Andric // jirl $ra, $ra, 0 1139*1db9f3b2SDimitry Andric // 1140*1db9f3b2SDimitry Andric // tail36 $rj, sym 1141*1db9f3b2SDimitry Andric // expands to: 1142*1db9f3b2SDimitry Andric // pcaddu18i $rj, %call36(sym) 1143*1db9f3b2SDimitry Andric // jirl $r0, $rj, 0 1144*1db9f3b2SDimitry Andric unsigned ScratchReg = 1145*1db9f3b2SDimitry Andric IsTailCall ? Inst.getOperand(0).getReg() : (unsigned)LoongArch::R1; 1146*1db9f3b2SDimitry Andric const MCExpr *Sym = 1147*1db9f3b2SDimitry Andric IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr(); 1148*1db9f3b2SDimitry Andric const LoongArchMCExpr *LE = LoongArchMCExpr::create( 1149*1db9f3b2SDimitry Andric Sym, llvm::LoongArchMCExpr::VK_LoongArch_CALL36, getContext()); 1150*1db9f3b2SDimitry Andric 1151*1db9f3b2SDimitry Andric Out.emitInstruction( 1152*1db9f3b2SDimitry Andric MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE), 1153*1db9f3b2SDimitry Andric getSTI()); 1154*1db9f3b2SDimitry Andric Out.emitInstruction( 1155*1db9f3b2SDimitry Andric MCInstBuilder(LoongArch::JIRL) 1156*1db9f3b2SDimitry Andric .addReg(IsTailCall ? (unsigned)LoongArch::R0 : ScratchReg) 1157*1db9f3b2SDimitry Andric .addReg(ScratchReg) 1158*1db9f3b2SDimitry Andric .addImm(0), 1159*1db9f3b2SDimitry Andric getSTI()); 1160*1db9f3b2SDimitry Andric } 1161*1db9f3b2SDimitry Andric 116281ad6265SDimitry Andric bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 116381ad6265SDimitry Andric OperandVector &Operands, 116481ad6265SDimitry Andric MCStreamer &Out) { 116581ad6265SDimitry Andric Inst.setLoc(IDLoc); 1166bdd1243dSDimitry Andric switch (Inst.getOpcode()) { 1167bdd1243dSDimitry Andric default: 1168bdd1243dSDimitry Andric break; 1169bdd1243dSDimitry Andric case LoongArch::PseudoLA_ABS: 1170bdd1243dSDimitry Andric case LoongArch::PseudoLA_ABS_LARGE: 1171bdd1243dSDimitry Andric emitLoadAddressAbs(Inst, IDLoc, Out); 1172bdd1243dSDimitry Andric return false; 1173bdd1243dSDimitry Andric case LoongArch::PseudoLA_PCREL: 1174bdd1243dSDimitry Andric emitLoadAddressPcrel(Inst, IDLoc, Out); 1175bdd1243dSDimitry Andric return false; 1176bdd1243dSDimitry Andric case LoongArch::PseudoLA_PCREL_LARGE: 1177bdd1243dSDimitry Andric emitLoadAddressPcrelLarge(Inst, IDLoc, Out); 1178bdd1243dSDimitry Andric return false; 1179bdd1243dSDimitry Andric case LoongArch::PseudoLA_GOT: 1180bdd1243dSDimitry Andric emitLoadAddressGot(Inst, IDLoc, Out); 1181bdd1243dSDimitry Andric return false; 1182bdd1243dSDimitry Andric case LoongArch::PseudoLA_GOT_LARGE: 1183bdd1243dSDimitry Andric emitLoadAddressGotLarge(Inst, IDLoc, Out); 1184bdd1243dSDimitry Andric return false; 1185bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LE: 1186bdd1243dSDimitry Andric emitLoadAddressTLSLE(Inst, IDLoc, Out); 1187bdd1243dSDimitry Andric return false; 1188bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_IE: 1189bdd1243dSDimitry Andric emitLoadAddressTLSIE(Inst, IDLoc, Out); 1190bdd1243dSDimitry Andric return false; 1191bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_IE_LARGE: 1192bdd1243dSDimitry Andric emitLoadAddressTLSIELarge(Inst, IDLoc, Out); 1193bdd1243dSDimitry Andric return false; 1194bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LD: 1195bdd1243dSDimitry Andric emitLoadAddressTLSLD(Inst, IDLoc, Out); 1196bdd1243dSDimitry Andric return false; 1197bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LD_LARGE: 1198bdd1243dSDimitry Andric emitLoadAddressTLSLDLarge(Inst, IDLoc, Out); 1199bdd1243dSDimitry Andric return false; 1200bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_GD: 1201bdd1243dSDimitry Andric emitLoadAddressTLSGD(Inst, IDLoc, Out); 1202bdd1243dSDimitry Andric return false; 1203bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_GD_LARGE: 1204bdd1243dSDimitry Andric emitLoadAddressTLSGDLarge(Inst, IDLoc, Out); 1205bdd1243dSDimitry Andric return false; 1206bdd1243dSDimitry Andric case LoongArch::PseudoLI_W: 1207bdd1243dSDimitry Andric case LoongArch::PseudoLI_D: 1208bdd1243dSDimitry Andric emitLoadImm(Inst, IDLoc, Out); 1209bdd1243dSDimitry Andric return false; 1210*1db9f3b2SDimitry Andric case LoongArch::PseudoCALL36: 1211*1db9f3b2SDimitry Andric emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false); 1212*1db9f3b2SDimitry Andric return false; 1213*1db9f3b2SDimitry Andric case LoongArch::PseudoTAIL36: 1214*1db9f3b2SDimitry Andric emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true); 1215*1db9f3b2SDimitry Andric return false; 1216bdd1243dSDimitry Andric } 121781ad6265SDimitry Andric Out.emitInstruction(Inst, getSTI()); 121881ad6265SDimitry Andric return false; 121981ad6265SDimitry Andric } 122081ad6265SDimitry Andric 122181ad6265SDimitry Andric unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 1222bdd1243dSDimitry Andric unsigned Opc = Inst.getOpcode(); 1223bdd1243dSDimitry Andric switch (Opc) { 122481ad6265SDimitry Andric default: 1225bdd1243dSDimitry Andric if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) { 1226bdd1243dSDimitry Andric unsigned Rd = Inst.getOperand(0).getReg(); 1227bdd1243dSDimitry Andric unsigned Rk = Inst.getOperand(1).getReg(); 1228bdd1243dSDimitry Andric unsigned Rj = Inst.getOperand(2).getReg(); 1229bdd1243dSDimitry Andric if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0) 1230bdd1243dSDimitry Andric return Match_RequiresAMORdDifferRkRj; 1231bdd1243dSDimitry Andric } 123281ad6265SDimitry Andric break; 1233bdd1243dSDimitry Andric case LoongArch::PseudoLA_PCREL_LARGE: 1234bdd1243dSDimitry Andric case LoongArch::PseudoLA_GOT_LARGE: 1235bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_IE_LARGE: 1236bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LD_LARGE: 1237bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_GD_LARGE: { 1238bdd1243dSDimitry Andric unsigned Rd = Inst.getOperand(0).getReg(); 1239bdd1243dSDimitry Andric unsigned Rj = Inst.getOperand(1).getReg(); 1240bdd1243dSDimitry Andric if (Rd == Rj) 1241bdd1243dSDimitry Andric return Match_RequiresLAORdDifferRj; 1242bdd1243dSDimitry Andric break; 1243bdd1243dSDimitry Andric } 124406c3fb27SDimitry Andric case LoongArch::CSRXCHG: 124506c3fb27SDimitry Andric case LoongArch::GCSRXCHG: { 124681ad6265SDimitry Andric unsigned Rj = Inst.getOperand(2).getReg(); 124781ad6265SDimitry Andric if (Rj == LoongArch::R0 || Rj == LoongArch::R1) 124881ad6265SDimitry Andric return Match_RequiresOpnd2NotR0R1; 124981ad6265SDimitry Andric return Match_Success; 125081ad6265SDimitry Andric } 125181ad6265SDimitry Andric case LoongArch::BSTRINS_W: 125281ad6265SDimitry Andric case LoongArch::BSTRINS_D: 125381ad6265SDimitry Andric case LoongArch::BSTRPICK_W: 125481ad6265SDimitry Andric case LoongArch::BSTRPICK_D: { 125581ad6265SDimitry Andric unsigned Opc = Inst.getOpcode(); 125681ad6265SDimitry Andric const signed Msb = 125781ad6265SDimitry Andric (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 125881ad6265SDimitry Andric ? Inst.getOperand(3).getImm() 125981ad6265SDimitry Andric : Inst.getOperand(2).getImm(); 126081ad6265SDimitry Andric const signed Lsb = 126181ad6265SDimitry Andric (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 126281ad6265SDimitry Andric ? Inst.getOperand(4).getImm() 126381ad6265SDimitry Andric : Inst.getOperand(3).getImm(); 126481ad6265SDimitry Andric if (Msb < Lsb) 126581ad6265SDimitry Andric return Match_RequiresMsbNotLessThanLsb; 126681ad6265SDimitry Andric return Match_Success; 126781ad6265SDimitry Andric } 126881ad6265SDimitry Andric } 126981ad6265SDimitry Andric 127081ad6265SDimitry Andric return Match_Success; 127181ad6265SDimitry Andric } 127281ad6265SDimitry Andric 127381ad6265SDimitry Andric unsigned 127481ad6265SDimitry Andric LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 127581ad6265SDimitry Andric unsigned Kind) { 127681ad6265SDimitry Andric LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp); 127781ad6265SDimitry Andric if (!Op.isReg()) 127881ad6265SDimitry Andric return Match_InvalidOperand; 127981ad6265SDimitry Andric 128081ad6265SDimitry Andric MCRegister Reg = Op.getReg(); 128181ad6265SDimitry Andric // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the 128281ad6265SDimitry Andric // register from FPR32 to FPR64 if necessary. 128381ad6265SDimitry Andric if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) && 128481ad6265SDimitry Andric Kind == MCK_FPR64) { 128581ad6265SDimitry Andric Op.setReg(convertFPR32ToFPR64(Reg)); 128681ad6265SDimitry Andric return Match_Success; 128781ad6265SDimitry Andric } 128881ad6265SDimitry Andric 128981ad6265SDimitry Andric return Match_InvalidOperand; 129081ad6265SDimitry Andric } 129181ad6265SDimitry Andric 129281ad6265SDimitry Andric bool LoongArchAsmParser::generateImmOutOfRangeError( 129381ad6265SDimitry Andric OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, 129406c3fb27SDimitry Andric const Twine &Msg = "immediate must be an integer in the range") { 129581ad6265SDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 129681ad6265SDimitry Andric return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 129781ad6265SDimitry Andric } 129881ad6265SDimitry Andric 129981ad6265SDimitry Andric bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 130081ad6265SDimitry Andric OperandVector &Operands, 130181ad6265SDimitry Andric MCStreamer &Out, 130281ad6265SDimitry Andric uint64_t &ErrorInfo, 130381ad6265SDimitry Andric bool MatchingInlineAsm) { 130481ad6265SDimitry Andric MCInst Inst; 130581ad6265SDimitry Andric FeatureBitset MissingFeatures; 130681ad6265SDimitry Andric 130781ad6265SDimitry Andric auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, 130881ad6265SDimitry Andric MatchingInlineAsm); 130981ad6265SDimitry Andric switch (Result) { 131081ad6265SDimitry Andric default: 131181ad6265SDimitry Andric break; 131281ad6265SDimitry Andric case Match_Success: 131381ad6265SDimitry Andric return processInstruction(Inst, IDLoc, Operands, Out); 131481ad6265SDimitry Andric case Match_MissingFeature: { 131581ad6265SDimitry Andric assert(MissingFeatures.any() && "Unknown missing features!"); 131681ad6265SDimitry Andric bool FirstFeature = true; 131781ad6265SDimitry Andric std::string Msg = "instruction requires the following:"; 131881ad6265SDimitry Andric for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { 131981ad6265SDimitry Andric if (MissingFeatures[i]) { 132081ad6265SDimitry Andric Msg += FirstFeature ? " " : ", "; 132181ad6265SDimitry Andric Msg += getSubtargetFeatureName(i); 132281ad6265SDimitry Andric FirstFeature = false; 132381ad6265SDimitry Andric } 132481ad6265SDimitry Andric } 132581ad6265SDimitry Andric return Error(IDLoc, Msg); 132681ad6265SDimitry Andric } 132781ad6265SDimitry Andric case Match_MnemonicFail: { 132881ad6265SDimitry Andric FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 132981ad6265SDimitry Andric std::string Suggestion = LoongArchMnemonicSpellCheck( 133081ad6265SDimitry Andric ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0); 133181ad6265SDimitry Andric return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); 133281ad6265SDimitry Andric } 133381ad6265SDimitry Andric case Match_InvalidOperand: { 133481ad6265SDimitry Andric SMLoc ErrorLoc = IDLoc; 133581ad6265SDimitry Andric if (ErrorInfo != ~0ULL) { 133681ad6265SDimitry Andric if (ErrorInfo >= Operands.size()) 133781ad6265SDimitry Andric return Error(ErrorLoc, "too few operands for instruction"); 133881ad6265SDimitry Andric 133981ad6265SDimitry Andric ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 134081ad6265SDimitry Andric if (ErrorLoc == SMLoc()) 134181ad6265SDimitry Andric ErrorLoc = IDLoc; 134281ad6265SDimitry Andric } 134381ad6265SDimitry Andric return Error(ErrorLoc, "invalid operand for instruction"); 134481ad6265SDimitry Andric } 134581ad6265SDimitry Andric } 134681ad6265SDimitry Andric 134781ad6265SDimitry Andric // Handle the case when the error message is of specific type 134881ad6265SDimitry Andric // other than the generic Match_InvalidOperand, and the 134981ad6265SDimitry Andric // corresponding operand is missing. 135081ad6265SDimitry Andric if (Result > FIRST_TARGET_MATCH_RESULT_TY) { 135181ad6265SDimitry Andric SMLoc ErrorLoc = IDLoc; 135281ad6265SDimitry Andric if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size()) 135381ad6265SDimitry Andric return Error(ErrorLoc, "too few operands for instruction"); 135481ad6265SDimitry Andric } 135581ad6265SDimitry Andric 135681ad6265SDimitry Andric switch (Result) { 135781ad6265SDimitry Andric default: 135881ad6265SDimitry Andric break; 135981ad6265SDimitry Andric case Match_RequiresMsbNotLessThanLsb: { 136081ad6265SDimitry Andric SMLoc ErrorStart = Operands[3]->getStartLoc(); 136181ad6265SDimitry Andric return Error(ErrorStart, "msb is less than lsb", 136281ad6265SDimitry Andric SMRange(ErrorStart, Operands[4]->getEndLoc())); 136381ad6265SDimitry Andric } 136481ad6265SDimitry Andric case Match_RequiresOpnd2NotR0R1: 136581ad6265SDimitry Andric return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1"); 1366bdd1243dSDimitry Andric case Match_RequiresAMORdDifferRkRj: 1367bdd1243dSDimitry Andric return Error(Operands[1]->getStartLoc(), 1368bdd1243dSDimitry Andric "$rd must be different from both $rk and $rj"); 1369bdd1243dSDimitry Andric case Match_RequiresLAORdDifferRj: 1370bdd1243dSDimitry Andric return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj"); 137106c3fb27SDimitry Andric case Match_InvalidUImm1: 137206c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 137306c3fb27SDimitry Andric /*Upper=*/(1 << 1) - 1); 137481ad6265SDimitry Andric case Match_InvalidUImm2: 137581ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 137681ad6265SDimitry Andric /*Upper=*/(1 << 2) - 1); 137781ad6265SDimitry Andric case Match_InvalidUImm2plus1: 137881ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1, 137981ad6265SDimitry Andric /*Upper=*/(1 << 2)); 138081ad6265SDimitry Andric case Match_InvalidUImm3: 138181ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 138281ad6265SDimitry Andric /*Upper=*/(1 << 3) - 1); 138306c3fb27SDimitry Andric case Match_InvalidUImm4: 138406c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 138506c3fb27SDimitry Andric /*Upper=*/(1 << 4) - 1); 138681ad6265SDimitry Andric case Match_InvalidUImm5: 138781ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 138881ad6265SDimitry Andric /*Upper=*/(1 << 5) - 1); 138981ad6265SDimitry Andric case Match_InvalidUImm6: 139081ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 139181ad6265SDimitry Andric /*Upper=*/(1 << 6) - 1); 139206c3fb27SDimitry Andric case Match_InvalidUImm7: 139306c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 139406c3fb27SDimitry Andric /*Upper=*/(1 << 7) - 1); 139506c3fb27SDimitry Andric case Match_InvalidUImm8: 139606c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 139706c3fb27SDimitry Andric /*Upper=*/(1 << 8) - 1); 139881ad6265SDimitry Andric case Match_InvalidUImm12: 139981ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 140081ad6265SDimitry Andric /*Upper=*/(1 << 12) - 1); 1401bdd1243dSDimitry Andric case Match_InvalidUImm12ori: 1402bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1403bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/0, 1404bdd1243dSDimitry Andric /*Upper=*/(1 << 12) - 1, 1405bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %abs_lo12) or an " 1406bdd1243dSDimitry Andric "integer in the range"); 140706c3fb27SDimitry Andric case Match_InvalidUImm14: 140806c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 140906c3fb27SDimitry Andric /*Upper=*/(1 << 14) - 1); 141081ad6265SDimitry Andric case Match_InvalidUImm15: 141181ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 141281ad6265SDimitry Andric /*Upper=*/(1 << 15) - 1); 141306c3fb27SDimitry Andric case Match_InvalidSImm5: 141406c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4), 141506c3fb27SDimitry Andric /*Upper=*/(1 << 4) - 1); 141606c3fb27SDimitry Andric case Match_InvalidSImm8: 141706c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7), 141806c3fb27SDimitry Andric /*Upper=*/(1 << 7) - 1); 141906c3fb27SDimitry Andric case Match_InvalidSImm8lsl1: 142006c3fb27SDimitry Andric return generateImmOutOfRangeError( 142106c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2, 142206c3fb27SDimitry Andric "immediate must be a multiple of 2 in the range"); 142306c3fb27SDimitry Andric case Match_InvalidSImm8lsl2: 142406c3fb27SDimitry Andric return generateImmOutOfRangeError( 142506c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4, 142606c3fb27SDimitry Andric "immediate must be a multiple of 4 in the range"); 142706c3fb27SDimitry Andric case Match_InvalidSImm10: 142806c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9), 142906c3fb27SDimitry Andric /*Upper=*/(1 << 9) - 1); 143006c3fb27SDimitry Andric case Match_InvalidSImm8lsl3: 143106c3fb27SDimitry Andric return generateImmOutOfRangeError( 143206c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8, 143306c3fb27SDimitry Andric "immediate must be a multiple of 8 in the range"); 143406c3fb27SDimitry Andric case Match_InvalidSImm9lsl3: 143506c3fb27SDimitry Andric return generateImmOutOfRangeError( 143606c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8, 143706c3fb27SDimitry Andric "immediate must be a multiple of 8 in the range"); 143806c3fb27SDimitry Andric case Match_InvalidSImm10lsl2: 143906c3fb27SDimitry Andric return generateImmOutOfRangeError( 144006c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4, 144106c3fb27SDimitry Andric "immediate must be a multiple of 4 in the range"); 144206c3fb27SDimitry Andric case Match_InvalidSImm11lsl1: 144306c3fb27SDimitry Andric return generateImmOutOfRangeError( 144406c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2, 144506c3fb27SDimitry Andric "immediate must be a multiple of 2 in the range"); 144681ad6265SDimitry Andric case Match_InvalidSImm12: 144781ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11), 144881ad6265SDimitry Andric /*Upper=*/(1 << 11) - 1); 1449bdd1243dSDimitry Andric case Match_InvalidSImm12addlike: 1450bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1451bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1452bdd1243dSDimitry Andric /*Upper=*/(1 << 11) - 1, 1453bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer " 1454bdd1243dSDimitry Andric "in the range"); 1455bdd1243dSDimitry Andric case Match_InvalidSImm12lu52id: 1456bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1457bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1458bdd1243dSDimitry Andric /*Upper=*/(1 << 11) - 1, 1459bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %pc64_hi12) or an " 1460bdd1243dSDimitry Andric "integer in the range"); 146106c3fb27SDimitry Andric case Match_InvalidSImm13: 146206c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12), 146306c3fb27SDimitry Andric /*Upper=*/(1 << 12) - 1); 146481ad6265SDimitry Andric case Match_InvalidSImm14lsl2: 146581ad6265SDimitry Andric return generateImmOutOfRangeError( 146681ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4, 146781ad6265SDimitry Andric "immediate must be a multiple of 4 in the range"); 146881ad6265SDimitry Andric case Match_InvalidSImm16: 146981ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15), 147081ad6265SDimitry Andric /*Upper=*/(1 << 15) - 1); 147181ad6265SDimitry Andric case Match_InvalidSImm16lsl2: 147281ad6265SDimitry Andric return generateImmOutOfRangeError( 147381ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4, 1474bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %b16) or an integer " 1475bdd1243dSDimitry Andric "in the range"); 147681ad6265SDimitry Andric case Match_InvalidSImm20: 147781ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19), 147881ad6265SDimitry Andric /*Upper=*/(1 << 19) - 1); 1479bdd1243dSDimitry Andric case Match_InvalidSImm20lu12iw: 1480bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1481bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1482bdd1243dSDimitry Andric /*Upper=*/(1 << 19) - 1, 1483bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer " 1484bdd1243dSDimitry Andric "in the range"); 1485bdd1243dSDimitry Andric case Match_InvalidSImm20lu32id: 1486bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1487bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1488bdd1243dSDimitry Andric /*Upper=*/(1 << 19) - 1, 1489bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %abs64_lo20) or an " 1490bdd1243dSDimitry Andric "integer in the range"); 1491bdd1243dSDimitry Andric case Match_InvalidSImm20pcalau12i: 1492bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1493bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1494bdd1243dSDimitry Andric /*Upper=*/(1 << 19) - 1, 1495bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer " 1496bdd1243dSDimitry Andric "in the range"); 1497*1db9f3b2SDimitry Andric case Match_InvalidSImm20pcaddu18i: 1498*1db9f3b2SDimitry Andric return generateImmOutOfRangeError( 1499*1db9f3b2SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1500*1db9f3b2SDimitry Andric /*Upper=*/(1 << 19) - 1, 1501*1db9f3b2SDimitry Andric "operand must be a symbol with modifier (e.g. %call36) or an integer " 1502*1db9f3b2SDimitry Andric "in the range"); 150381ad6265SDimitry Andric case Match_InvalidSImm21lsl2: 150481ad6265SDimitry Andric return generateImmOutOfRangeError( 150581ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4, 1506bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %b21) or an integer " 1507bdd1243dSDimitry Andric "in the range"); 1508bdd1243dSDimitry Andric case Match_InvalidSImm26Operand: 150981ad6265SDimitry Andric return generateImmOutOfRangeError( 151081ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4, 1511bdd1243dSDimitry Andric "operand must be a bare symbol name or an immediate must be a multiple " 1512bdd1243dSDimitry Andric "of 4 in the range"); 1513bdd1243dSDimitry Andric case Match_InvalidImm32: { 1514bdd1243dSDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1515bdd1243dSDimitry Andric return Error(ErrorLoc, "operand must be a 32 bit immediate"); 1516bdd1243dSDimitry Andric } 1517bdd1243dSDimitry Andric case Match_InvalidBareSymbol: { 1518bdd1243dSDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1519bdd1243dSDimitry Andric return Error(ErrorLoc, "operand must be a bare symbol name"); 1520bdd1243dSDimitry Andric } 152181ad6265SDimitry Andric } 152281ad6265SDimitry Andric llvm_unreachable("Unknown match type detected!"); 152381ad6265SDimitry Andric } 152481ad6265SDimitry Andric 152581ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() { 152681ad6265SDimitry Andric RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target()); 152781ad6265SDimitry Andric RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target()); 152881ad6265SDimitry Andric } 1529