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 1210fca6ea1SDimitry Andric // Helper to emit pseudo instruction "la.tls.desc $rd, sym". 1220fca6ea1SDimitry Andric void emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 1230fca6ea1SDimitry Andric void emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 1240fca6ea1SDimitry Andric // Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym". 1250fca6ea1SDimitry Andric void emitLoadAddressTLSDescPcrelLarge(MCInst &Inst, SMLoc IDLoc, 1260fca6ea1SDimitry Andric MCStreamer &Out); 1270fca6ea1SDimitry Andric 128bdd1243dSDimitry Andric // Helper to emit pseudo instruction "li.w/d $rd, $imm". 129bdd1243dSDimitry Andric void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 130bdd1243dSDimitry Andric 1311db9f3b2SDimitry Andric // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym". 1321db9f3b2SDimitry Andric void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, 1331db9f3b2SDimitry Andric bool IsTailCall); 1341db9f3b2SDimitry Andric 13581ad6265SDimitry Andric public: 13681ad6265SDimitry Andric enum LoongArchMatchResultTy { 13781ad6265SDimitry Andric Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 13881ad6265SDimitry Andric Match_RequiresMsbNotLessThanLsb, 13981ad6265SDimitry Andric Match_RequiresOpnd2NotR0R1, 140bdd1243dSDimitry Andric Match_RequiresAMORdDifferRkRj, 141bdd1243dSDimitry Andric Match_RequiresLAORdDifferRj, 1420fca6ea1SDimitry Andric Match_RequiresLAORdR4, 14381ad6265SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES 14481ad6265SDimitry Andric #include "LoongArchGenAsmMatcher.inc" 14581ad6265SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES 14681ad6265SDimitry Andric }; 14781ad6265SDimitry Andric 148bdd1243dSDimitry Andric static bool classifySymbolRef(const MCExpr *Expr, 149bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind &Kind); 150bdd1243dSDimitry Andric 15181ad6265SDimitry Andric LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 15281ad6265SDimitry Andric const MCInstrInfo &MII, const MCTargetOptions &Options) 15381ad6265SDimitry Andric : MCTargetAsmParser(Options, STI, MII) { 15481ad6265SDimitry Andric Parser.addAliasForDirective(".half", ".2byte"); 15581ad6265SDimitry Andric Parser.addAliasForDirective(".hword", ".2byte"); 15681ad6265SDimitry Andric Parser.addAliasForDirective(".word", ".4byte"); 15781ad6265SDimitry Andric Parser.addAliasForDirective(".dword", ".8byte"); 15881ad6265SDimitry Andric 15981ad6265SDimitry Andric // Initialize the set of available features. 16081ad6265SDimitry Andric setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 16181ad6265SDimitry Andric } 16281ad6265SDimitry Andric }; 16381ad6265SDimitry Andric 16481ad6265SDimitry Andric // Instances of this class represent a parsed LoongArch machine instruction. 16581ad6265SDimitry Andric class LoongArchOperand : public MCParsedAsmOperand { 16681ad6265SDimitry Andric enum class KindTy { 16781ad6265SDimitry Andric Token, 16881ad6265SDimitry Andric Register, 16981ad6265SDimitry Andric Immediate, 17081ad6265SDimitry Andric } Kind; 17181ad6265SDimitry Andric 17281ad6265SDimitry Andric struct RegOp { 17381ad6265SDimitry Andric MCRegister RegNum; 17481ad6265SDimitry Andric }; 17581ad6265SDimitry Andric 17681ad6265SDimitry Andric struct ImmOp { 17781ad6265SDimitry Andric const MCExpr *Val; 17881ad6265SDimitry Andric }; 17981ad6265SDimitry Andric 18081ad6265SDimitry Andric SMLoc StartLoc, EndLoc; 18181ad6265SDimitry Andric union { 18281ad6265SDimitry Andric StringRef Tok; 18381ad6265SDimitry Andric struct RegOp Reg; 18481ad6265SDimitry Andric struct ImmOp Imm; 18581ad6265SDimitry Andric }; 18681ad6265SDimitry Andric 18781ad6265SDimitry Andric public: 18881ad6265SDimitry Andric LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 18981ad6265SDimitry Andric 19081ad6265SDimitry Andric bool isToken() const override { return Kind == KindTy::Token; } 19181ad6265SDimitry Andric bool isReg() const override { return Kind == KindTy::Register; } 19281ad6265SDimitry Andric bool isImm() const override { return Kind == KindTy::Immediate; } 19381ad6265SDimitry Andric bool isMem() const override { return false; } 19481ad6265SDimitry Andric void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; } 195bdd1243dSDimitry Andric bool isGPR() const { 196bdd1243dSDimitry Andric return Kind == KindTy::Register && 197bdd1243dSDimitry Andric LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains( 198bdd1243dSDimitry Andric Reg.RegNum); 199bdd1243dSDimitry Andric } 20081ad6265SDimitry Andric 201bdd1243dSDimitry Andric static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm, 202bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind &VK) { 203bdd1243dSDimitry Andric if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) { 204bdd1243dSDimitry Andric VK = LE->getKind(); 205bdd1243dSDimitry Andric return false; 206bdd1243dSDimitry Andric } 207bdd1243dSDimitry Andric 20881ad6265SDimitry Andric if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { 20981ad6265SDimitry Andric Imm = CE->getValue(); 21081ad6265SDimitry Andric return true; 21181ad6265SDimitry Andric } 21281ad6265SDimitry Andric 21381ad6265SDimitry Andric return false; 21481ad6265SDimitry Andric } 21581ad6265SDimitry Andric 21681ad6265SDimitry Andric template <unsigned N, int P = 0> bool isUImm() const { 21781ad6265SDimitry Andric if (!isImm()) 21881ad6265SDimitry Andric return false; 21981ad6265SDimitry Andric 22081ad6265SDimitry Andric int64_t Imm; 221bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 222bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 223bdd1243dSDimitry Andric return IsConstantImm && isUInt<N>(Imm - P) && 224bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_None; 22581ad6265SDimitry Andric } 22681ad6265SDimitry Andric 22781ad6265SDimitry Andric template <unsigned N, unsigned S = 0> bool isSImm() const { 22881ad6265SDimitry Andric if (!isImm()) 22981ad6265SDimitry Andric return false; 23081ad6265SDimitry Andric 23181ad6265SDimitry Andric int64_t Imm; 232bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 233bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 234bdd1243dSDimitry Andric return IsConstantImm && isShiftedInt<N, S>(Imm) && 235bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_None; 236bdd1243dSDimitry Andric } 237bdd1243dSDimitry Andric 238bdd1243dSDimitry Andric bool isBareSymbol() const { 239bdd1243dSDimitry Andric int64_t Imm; 240bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 241bdd1243dSDimitry Andric // Must be of 'immediate' type but not a constant. 242bdd1243dSDimitry Andric if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 243bdd1243dSDimitry Andric return false; 244bdd1243dSDimitry Andric return LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 245bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_None; 24681ad6265SDimitry Andric } 24781ad6265SDimitry Andric 2480fca6ea1SDimitry Andric bool isTPRelAddSymbol() const { 2490fca6ea1SDimitry Andric int64_t Imm; 2500fca6ea1SDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 2510fca6ea1SDimitry Andric // Must be of 'immediate' type but not a constant. 2520fca6ea1SDimitry Andric if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 2530fca6ea1SDimitry Andric return false; 2540fca6ea1SDimitry Andric return LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 2550fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R; 2560fca6ea1SDimitry Andric } 2570fca6ea1SDimitry Andric 25806c3fb27SDimitry Andric bool isUImm1() const { return isUImm<1>(); } 25981ad6265SDimitry Andric bool isUImm2() const { return isUImm<2>(); } 26081ad6265SDimitry Andric bool isUImm2plus1() const { return isUImm<2, 1>(); } 26181ad6265SDimitry Andric bool isUImm3() const { return isUImm<3>(); } 26206c3fb27SDimitry Andric bool isUImm4() const { return isUImm<4>(); } 26306c3fb27SDimitry Andric bool isSImm5() const { return isSImm<5>(); } 26481ad6265SDimitry Andric bool isUImm5() const { return isUImm<5>(); } 26581ad6265SDimitry Andric bool isUImm6() const { return isUImm<6>(); } 26606c3fb27SDimitry Andric bool isUImm7() const { return isUImm<7>(); } 26706c3fb27SDimitry Andric bool isSImm8() const { return isSImm<8>(); } 26806c3fb27SDimitry Andric bool isSImm8lsl1() const { return isSImm<8, 1>(); } 26906c3fb27SDimitry Andric bool isSImm8lsl2() const { return isSImm<8, 2>(); } 27006c3fb27SDimitry Andric bool isSImm8lsl3() const { return isSImm<8, 3>(); } 27181ad6265SDimitry Andric bool isUImm8() const { return isUImm<8>(); } 27206c3fb27SDimitry Andric bool isSImm9lsl3() const { return isSImm<9, 3>(); } 27306c3fb27SDimitry Andric bool isSImm10() const { return isSImm<10>(); } 27406c3fb27SDimitry Andric bool isSImm10lsl2() const { return isSImm<10, 2>(); } 27506c3fb27SDimitry Andric bool isSImm11lsl1() const { return isSImm<11, 1>(); } 276bdd1243dSDimitry Andric bool isSImm12() const { return isSImm<12>(); } 277bdd1243dSDimitry Andric 278bdd1243dSDimitry Andric bool isSImm12addlike() const { 279bdd1243dSDimitry Andric if (!isImm()) 280bdd1243dSDimitry Andric return false; 281bdd1243dSDimitry Andric 282bdd1243dSDimitry Andric int64_t Imm; 283bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 284bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 285bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 286bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 287bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 2880fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 || 2890fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R || 2900fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12 || 2910fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD; 292bdd1243dSDimitry Andric return IsConstantImm 293bdd1243dSDimitry Andric ? isInt<12>(Imm) && IsValidKind 294bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 295bdd1243dSDimitry Andric IsValidKind; 296bdd1243dSDimitry Andric } 297bdd1243dSDimitry Andric 298bdd1243dSDimitry Andric bool isSImm12lu52id() const { 299bdd1243dSDimitry Andric if (!isImm()) 300bdd1243dSDimitry Andric return false; 301bdd1243dSDimitry Andric 302bdd1243dSDimitry Andric int64_t Imm; 303bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 304bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 305bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 306bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 || 307bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 || 308bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 || 309bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 || 310bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 || 311bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 || 3120fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12 || 3130fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12 || 3140fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12; 315bdd1243dSDimitry Andric return IsConstantImm 316bdd1243dSDimitry Andric ? isInt<12>(Imm) && IsValidKind 317bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 318bdd1243dSDimitry Andric IsValidKind; 319bdd1243dSDimitry Andric } 320bdd1243dSDimitry Andric 32181ad6265SDimitry Andric bool isUImm12() const { return isUImm<12>(); } 322bdd1243dSDimitry Andric 323bdd1243dSDimitry Andric bool isUImm12ori() const { 324bdd1243dSDimitry Andric if (!isImm()) 325bdd1243dSDimitry Andric return false; 326bdd1243dSDimitry Andric 327bdd1243dSDimitry Andric int64_t Imm; 328bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 329bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 330bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 331bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 || 332bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 333bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 || 334bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 335bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 || 336bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 || 3370fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 || 3380fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12; 339bdd1243dSDimitry Andric return IsConstantImm 340bdd1243dSDimitry Andric ? isUInt<12>(Imm) && IsValidKind 341bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 342bdd1243dSDimitry Andric IsValidKind; 343bdd1243dSDimitry Andric } 344bdd1243dSDimitry Andric 34506c3fb27SDimitry Andric bool isSImm13() const { return isSImm<13>(); } 34681ad6265SDimitry Andric bool isUImm14() const { return isUImm<14>(); } 34781ad6265SDimitry Andric bool isUImm15() const { return isUImm<15>(); } 348bdd1243dSDimitry Andric 34981ad6265SDimitry Andric bool isSImm14lsl2() const { return isSImm<14, 2>(); } 35081ad6265SDimitry Andric bool isSImm16() const { return isSImm<16>(); } 351bdd1243dSDimitry Andric 352bdd1243dSDimitry Andric bool isSImm16lsl2() const { 353bdd1243dSDimitry Andric if (!isImm()) 354bdd1243dSDimitry Andric return false; 355bdd1243dSDimitry Andric 356bdd1243dSDimitry Andric int64_t Imm; 357bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 358bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 359bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 360bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_B16 || 3610fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 3620fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL; 363bdd1243dSDimitry Andric return IsConstantImm 364bdd1243dSDimitry Andric ? isShiftedInt<16, 2>(Imm) && IsValidKind 365bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 366bdd1243dSDimitry Andric IsValidKind; 367bdd1243dSDimitry Andric } 368bdd1243dSDimitry Andric 36981ad6265SDimitry Andric bool isSImm20() const { return isSImm<20>(); } 370bdd1243dSDimitry Andric 371bdd1243dSDimitry Andric bool isSImm20pcalau12i() const { 372bdd1243dSDimitry Andric if (!isImm()) 373bdd1243dSDimitry Andric return false; 374bdd1243dSDimitry Andric 375bdd1243dSDimitry Andric int64_t Imm; 376bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 377bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 378bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 379bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 || 380bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 || 381bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 || 382bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 || 3830fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20 || 3840fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20; 385bdd1243dSDimitry Andric return IsConstantImm 386bdd1243dSDimitry Andric ? isInt<20>(Imm) && IsValidKind 387bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 388bdd1243dSDimitry Andric IsValidKind; 389bdd1243dSDimitry Andric } 390bdd1243dSDimitry Andric 391bdd1243dSDimitry Andric bool isSImm20lu12iw() const { 392bdd1243dSDimitry Andric if (!isImm()) 393bdd1243dSDimitry Andric return false; 394bdd1243dSDimitry Andric 395bdd1243dSDimitry Andric int64_t Imm; 396bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 397bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 398bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 399bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 || 400bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 || 401bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 || 402bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 || 403bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 || 4040fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20 || 4050fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R || 4060fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20; 407bdd1243dSDimitry Andric return IsConstantImm 408bdd1243dSDimitry Andric ? isInt<20>(Imm) && IsValidKind 409bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 410bdd1243dSDimitry Andric IsValidKind; 411bdd1243dSDimitry Andric } 412bdd1243dSDimitry Andric 413bdd1243dSDimitry Andric bool isSImm20lu32id() const { 414bdd1243dSDimitry Andric if (!isImm()) 415bdd1243dSDimitry Andric return false; 416bdd1243dSDimitry Andric 417bdd1243dSDimitry Andric int64_t Imm; 418bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 419bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 420bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 421bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 || 422bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 || 423bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 || 424bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 || 425bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 || 426bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 || 4270fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20 || 4280fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20 || 4290fca6ea1SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20; 430bdd1243dSDimitry Andric 431bdd1243dSDimitry Andric return IsConstantImm 432bdd1243dSDimitry Andric ? isInt<20>(Imm) && IsValidKind 433bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 434bdd1243dSDimitry Andric IsValidKind; 435bdd1243dSDimitry Andric } 436bdd1243dSDimitry Andric 4371db9f3b2SDimitry Andric bool isSImm20pcaddu18i() const { 4381db9f3b2SDimitry Andric if (!isImm()) 4391db9f3b2SDimitry Andric return false; 4401db9f3b2SDimitry Andric 4411db9f3b2SDimitry Andric int64_t Imm; 4421db9f3b2SDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 4431db9f3b2SDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 4441db9f3b2SDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 4451db9f3b2SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_CALL36; 4461db9f3b2SDimitry Andric 4471db9f3b2SDimitry Andric return IsConstantImm 4481db9f3b2SDimitry Andric ? isInt<20>(Imm) && IsValidKind 4491db9f3b2SDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 4501db9f3b2SDimitry Andric IsValidKind; 4511db9f3b2SDimitry Andric } 4521db9f3b2SDimitry Andric 453*52418fc2SDimitry Andric bool isSImm20pcaddi() const { 454*52418fc2SDimitry Andric if (!isImm()) 455*52418fc2SDimitry Andric return false; 456*52418fc2SDimitry Andric 457*52418fc2SDimitry Andric int64_t Imm; 458*52418fc2SDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 459*52418fc2SDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 460*52418fc2SDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 461*52418fc2SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_PCREL20_S2 || 462*52418fc2SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2 || 463*52418fc2SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2 || 464*52418fc2SDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2; 465*52418fc2SDimitry Andric return IsConstantImm 466*52418fc2SDimitry Andric ? isInt<20>(Imm) && IsValidKind 467*52418fc2SDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 468*52418fc2SDimitry Andric IsValidKind; 469*52418fc2SDimitry Andric } 470*52418fc2SDimitry Andric 471bdd1243dSDimitry Andric bool isSImm21lsl2() const { 472bdd1243dSDimitry Andric if (!isImm()) 473bdd1243dSDimitry Andric return false; 474bdd1243dSDimitry Andric 475bdd1243dSDimitry Andric int64_t Imm; 476bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 477bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 478bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 479bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_B21; 480bdd1243dSDimitry Andric return IsConstantImm 481bdd1243dSDimitry Andric ? isShiftedInt<21, 2>(Imm) && IsValidKind 482bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 483bdd1243dSDimitry Andric IsValidKind; 484bdd1243dSDimitry Andric } 485bdd1243dSDimitry Andric 486bdd1243dSDimitry Andric bool isSImm26Operand() const { 487bdd1243dSDimitry Andric if (!isImm()) 488bdd1243dSDimitry Andric return false; 489bdd1243dSDimitry Andric 490bdd1243dSDimitry Andric int64_t Imm; 491bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 492bdd1243dSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 493bdd1243dSDimitry Andric bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 494bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_CALL || 495bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT || 496bdd1243dSDimitry Andric VK == LoongArchMCExpr::VK_LoongArch_B26; 497bdd1243dSDimitry Andric return IsConstantImm 498bdd1243dSDimitry Andric ? isShiftedInt<26, 2>(Imm) && IsValidKind 499bdd1243dSDimitry Andric : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 500bdd1243dSDimitry Andric IsValidKind; 501bdd1243dSDimitry Andric } 502bdd1243dSDimitry Andric 503bdd1243dSDimitry Andric bool isImm32() const { return isSImm<32>() || isUImm<32>(); } 5040fca6ea1SDimitry Andric bool isImm64() const { 5050fca6ea1SDimitry Andric if (!isImm()) 5060fca6ea1SDimitry Andric return false; 5070fca6ea1SDimitry Andric int64_t Imm; 5080fca6ea1SDimitry Andric LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 5090fca6ea1SDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 5100fca6ea1SDimitry Andric return IsConstantImm && VK == LoongArchMCExpr::VK_LoongArch_None; 5110fca6ea1SDimitry Andric } 51281ad6265SDimitry Andric 51381ad6265SDimitry Andric /// Gets location of the first token of this operand. 51481ad6265SDimitry Andric SMLoc getStartLoc() const override { return StartLoc; } 51581ad6265SDimitry Andric /// Gets location of the last token of this operand. 51681ad6265SDimitry Andric SMLoc getEndLoc() const override { return EndLoc; } 51781ad6265SDimitry Andric 5180fca6ea1SDimitry Andric MCRegister getReg() const override { 51981ad6265SDimitry Andric assert(Kind == KindTy::Register && "Invalid type access!"); 5200fca6ea1SDimitry Andric return Reg.RegNum; 52181ad6265SDimitry Andric } 52281ad6265SDimitry Andric 52381ad6265SDimitry Andric const MCExpr *getImm() const { 52481ad6265SDimitry Andric assert(Kind == KindTy::Immediate && "Invalid type access!"); 52581ad6265SDimitry Andric return Imm.Val; 52681ad6265SDimitry Andric } 52781ad6265SDimitry Andric 52881ad6265SDimitry Andric StringRef getToken() const { 52981ad6265SDimitry Andric assert(Kind == KindTy::Token && "Invalid type access!"); 53081ad6265SDimitry Andric return Tok; 53181ad6265SDimitry Andric } 53281ad6265SDimitry Andric 53381ad6265SDimitry Andric void print(raw_ostream &OS) const override { 534bdd1243dSDimitry Andric auto RegName = [](MCRegister Reg) { 53581ad6265SDimitry Andric if (Reg) 53681ad6265SDimitry Andric return LoongArchInstPrinter::getRegisterName(Reg); 53781ad6265SDimitry Andric else 53881ad6265SDimitry Andric return "noreg"; 53981ad6265SDimitry Andric }; 54081ad6265SDimitry Andric 54181ad6265SDimitry Andric switch (Kind) { 54281ad6265SDimitry Andric case KindTy::Immediate: 54381ad6265SDimitry Andric OS << *getImm(); 54481ad6265SDimitry Andric break; 54581ad6265SDimitry Andric case KindTy::Register: 54681ad6265SDimitry Andric OS << "<register " << RegName(getReg()) << ">"; 54781ad6265SDimitry Andric break; 54881ad6265SDimitry Andric case KindTy::Token: 54981ad6265SDimitry Andric OS << "'" << getToken() << "'"; 55081ad6265SDimitry Andric break; 55181ad6265SDimitry Andric } 55281ad6265SDimitry Andric } 55381ad6265SDimitry Andric 55481ad6265SDimitry Andric static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) { 55581ad6265SDimitry Andric auto Op = std::make_unique<LoongArchOperand>(KindTy::Token); 55681ad6265SDimitry Andric Op->Tok = Str; 55781ad6265SDimitry Andric Op->StartLoc = S; 55881ad6265SDimitry Andric Op->EndLoc = S; 55981ad6265SDimitry Andric return Op; 56081ad6265SDimitry Andric } 56181ad6265SDimitry Andric 56281ad6265SDimitry Andric static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S, 56381ad6265SDimitry Andric SMLoc E) { 56481ad6265SDimitry Andric auto Op = std::make_unique<LoongArchOperand>(KindTy::Register); 56581ad6265SDimitry Andric Op->Reg.RegNum = RegNo; 56681ad6265SDimitry Andric Op->StartLoc = S; 56781ad6265SDimitry Andric Op->EndLoc = E; 56881ad6265SDimitry Andric return Op; 56981ad6265SDimitry Andric } 57081ad6265SDimitry Andric 57181ad6265SDimitry Andric static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S, 57281ad6265SDimitry Andric SMLoc E) { 57381ad6265SDimitry Andric auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate); 57481ad6265SDimitry Andric Op->Imm.Val = Val; 57581ad6265SDimitry Andric Op->StartLoc = S; 57681ad6265SDimitry Andric Op->EndLoc = E; 57781ad6265SDimitry Andric return Op; 57881ad6265SDimitry Andric } 57981ad6265SDimitry Andric 58081ad6265SDimitry Andric void addExpr(MCInst &Inst, const MCExpr *Expr) const { 58181ad6265SDimitry Andric if (auto CE = dyn_cast<MCConstantExpr>(Expr)) 58281ad6265SDimitry Andric Inst.addOperand(MCOperand::createImm(CE->getValue())); 58381ad6265SDimitry Andric else 58481ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 58581ad6265SDimitry Andric } 58681ad6265SDimitry Andric 58781ad6265SDimitry Andric // Used by the TableGen Code. 58881ad6265SDimitry Andric void addRegOperands(MCInst &Inst, unsigned N) const { 58981ad6265SDimitry Andric assert(N == 1 && "Invalid number of operands!"); 59081ad6265SDimitry Andric Inst.addOperand(MCOperand::createReg(getReg())); 59181ad6265SDimitry Andric } 59281ad6265SDimitry Andric void addImmOperands(MCInst &Inst, unsigned N) const { 59381ad6265SDimitry Andric assert(N == 1 && "Invalid number of operands!"); 59481ad6265SDimitry Andric addExpr(Inst, getImm()); 59581ad6265SDimitry Andric } 59681ad6265SDimitry Andric }; 597972a253aSDimitry Andric } // end namespace 59881ad6265SDimitry Andric 59981ad6265SDimitry Andric #define GET_REGISTER_MATCHER 60081ad6265SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME 60181ad6265SDimitry Andric #define GET_MATCHER_IMPLEMENTATION 60281ad6265SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER 60381ad6265SDimitry Andric #include "LoongArchGenAsmMatcher.inc" 60481ad6265SDimitry Andric 60581ad6265SDimitry Andric static MCRegister convertFPR32ToFPR64(MCRegister Reg) { 60681ad6265SDimitry Andric assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register"); 60781ad6265SDimitry Andric return Reg - LoongArch::F0 + LoongArch::F0_64; 60881ad6265SDimitry Andric } 60981ad6265SDimitry Andric 61081ad6265SDimitry Andric // Attempts to match Name as a register (either using the default name or 61181ad6265SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon 61281ad6265SDimitry Andric // failure, returns true and sets RegNo to 0. 61381ad6265SDimitry Andric static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) { 61481ad6265SDimitry Andric RegNo = MatchRegisterName(Name); 61581ad6265SDimitry Andric // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial 61681ad6265SDimitry Andric // match always matches the 32-bit variant, and not the 64-bit one. 61781ad6265SDimitry Andric assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64)); 61881ad6265SDimitry Andric // The default FPR register class is based on the tablegen enum ordering. 61981ad6265SDimitry Andric static_assert(LoongArch::F0 < LoongArch::F0_64, 62081ad6265SDimitry Andric "FPR matching must be updated"); 62181ad6265SDimitry Andric if (RegNo == LoongArch::NoRegister) 62281ad6265SDimitry Andric RegNo = MatchRegisterAltName(Name); 62381ad6265SDimitry Andric 62481ad6265SDimitry Andric return RegNo == LoongArch::NoRegister; 62581ad6265SDimitry Andric } 62681ad6265SDimitry Andric 6275f757f3fSDimitry Andric bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, 62881ad6265SDimitry Andric SMLoc &EndLoc) { 62981ad6265SDimitry Andric return Error(getLoc(), "invalid register number"); 63081ad6265SDimitry Andric } 63181ad6265SDimitry Andric 6325f757f3fSDimitry Andric ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg, 63381ad6265SDimitry Andric SMLoc &StartLoc, 63481ad6265SDimitry Andric SMLoc &EndLoc) { 63581ad6265SDimitry Andric llvm_unreachable("Unimplemented function."); 63681ad6265SDimitry Andric } 63781ad6265SDimitry Andric 638bdd1243dSDimitry Andric bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr, 639bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind &Kind) { 640bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_None; 641bdd1243dSDimitry Andric 642bdd1243dSDimitry Andric if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) { 643bdd1243dSDimitry Andric Kind = RE->getKind(); 644bdd1243dSDimitry Andric Expr = RE->getSubExpr(); 645bdd1243dSDimitry Andric } 646bdd1243dSDimitry Andric 647bdd1243dSDimitry Andric MCValue Res; 648bdd1243dSDimitry Andric if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr)) 649bdd1243dSDimitry Andric return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None; 650bdd1243dSDimitry Andric return false; 651bdd1243dSDimitry Andric } 652bdd1243dSDimitry Andric 65306c3fb27SDimitry Andric ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) { 65406c3fb27SDimitry Andric if (!parseOptionalToken(AsmToken::Dollar)) 65506c3fb27SDimitry Andric return ParseStatus::NoMatch; 65681ad6265SDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) 65706c3fb27SDimitry Andric return ParseStatus::NoMatch; 65881ad6265SDimitry Andric 65981ad6265SDimitry Andric StringRef Name = getLexer().getTok().getIdentifier(); 66081ad6265SDimitry Andric MCRegister RegNo; 66181ad6265SDimitry Andric matchRegisterNameHelper(RegNo, Name); 66281ad6265SDimitry Andric if (RegNo == LoongArch::NoRegister) 66306c3fb27SDimitry Andric return ParseStatus::NoMatch; 66481ad6265SDimitry Andric 66581ad6265SDimitry Andric SMLoc S = getLoc(); 66681ad6265SDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); 66781ad6265SDimitry Andric getLexer().Lex(); 66881ad6265SDimitry Andric Operands.push_back(LoongArchOperand::createReg(RegNo, S, E)); 66981ad6265SDimitry Andric 67006c3fb27SDimitry Andric return ParseStatus::Success; 67181ad6265SDimitry Andric } 67281ad6265SDimitry Andric 67306c3fb27SDimitry Andric ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) { 67481ad6265SDimitry Andric SMLoc S = getLoc(); 67581ad6265SDimitry Andric SMLoc E; 67681ad6265SDimitry Andric const MCExpr *Res; 67781ad6265SDimitry Andric 678bdd1243dSDimitry Andric switch (getLexer().getKind()) { 679bdd1243dSDimitry Andric default: 68006c3fb27SDimitry Andric return ParseStatus::NoMatch; 681bdd1243dSDimitry Andric case AsmToken::LParen: 682bdd1243dSDimitry Andric case AsmToken::Dot: 683bdd1243dSDimitry Andric case AsmToken::Minus: 684bdd1243dSDimitry Andric case AsmToken::Plus: 685bdd1243dSDimitry Andric case AsmToken::Exclaim: 686bdd1243dSDimitry Andric case AsmToken::Tilde: 687bdd1243dSDimitry Andric case AsmToken::Integer: 688bdd1243dSDimitry Andric case AsmToken::String: 689bdd1243dSDimitry Andric case AsmToken::Identifier: 69081ad6265SDimitry Andric if (getParser().parseExpression(Res, E)) 69106c3fb27SDimitry Andric return ParseStatus::Failure; 692bdd1243dSDimitry Andric break; 693bdd1243dSDimitry Andric case AsmToken::Percent: 694bdd1243dSDimitry Andric return parseOperandWithModifier(Operands); 695bdd1243dSDimitry Andric } 69681ad6265SDimitry Andric 69781ad6265SDimitry Andric Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 69806c3fb27SDimitry Andric return ParseStatus::Success; 69981ad6265SDimitry Andric } 70081ad6265SDimitry Andric 70106c3fb27SDimitry Andric ParseStatus 702bdd1243dSDimitry Andric LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) { 703bdd1243dSDimitry Andric SMLoc S = getLoc(); 704bdd1243dSDimitry Andric SMLoc E; 705bdd1243dSDimitry Andric 70606c3fb27SDimitry Andric if (getLexer().getKind() != AsmToken::Percent) 70706c3fb27SDimitry Andric return Error(getLoc(), "expected '%' for operand modifier"); 708bdd1243dSDimitry Andric 709bdd1243dSDimitry Andric getParser().Lex(); // Eat '%' 710bdd1243dSDimitry Andric 71106c3fb27SDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) 71206c3fb27SDimitry Andric return Error(getLoc(), "expected valid identifier for operand modifier"); 713bdd1243dSDimitry Andric StringRef Identifier = getParser().getTok().getIdentifier(); 714bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = 715bdd1243dSDimitry Andric LoongArchMCExpr::getVariantKindForName(Identifier); 71606c3fb27SDimitry Andric if (VK == LoongArchMCExpr::VK_LoongArch_Invalid) 71706c3fb27SDimitry Andric return Error(getLoc(), "unrecognized operand modifier"); 718bdd1243dSDimitry Andric 719bdd1243dSDimitry Andric getParser().Lex(); // Eat the identifier 72006c3fb27SDimitry Andric if (getLexer().getKind() != AsmToken::LParen) 72106c3fb27SDimitry Andric return Error(getLoc(), "expected '('"); 722bdd1243dSDimitry Andric getParser().Lex(); // Eat '(' 723bdd1243dSDimitry Andric 724bdd1243dSDimitry Andric const MCExpr *SubExpr; 72506c3fb27SDimitry Andric if (getParser().parseParenExpression(SubExpr, E)) 72606c3fb27SDimitry Andric return ParseStatus::Failure; 727bdd1243dSDimitry Andric 728bdd1243dSDimitry Andric const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext()); 729bdd1243dSDimitry Andric Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E)); 73006c3fb27SDimitry Andric return ParseStatus::Success; 731bdd1243dSDimitry Andric } 732bdd1243dSDimitry Andric 73306c3fb27SDimitry Andric ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) { 734bdd1243dSDimitry Andric SMLoc S = getLoc(); 735bdd1243dSDimitry Andric const MCExpr *Res; 736bdd1243dSDimitry Andric 737bdd1243dSDimitry Andric if (getLexer().getKind() == AsmToken::Percent) 738bdd1243dSDimitry Andric return parseOperandWithModifier(Operands); 739bdd1243dSDimitry Andric 740bdd1243dSDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) 74106c3fb27SDimitry Andric return ParseStatus::NoMatch; 742bdd1243dSDimitry Andric 743bdd1243dSDimitry Andric StringRef Identifier; 744bdd1243dSDimitry Andric if (getParser().parseIdentifier(Identifier)) 74506c3fb27SDimitry Andric return ParseStatus::Failure; 746bdd1243dSDimitry Andric 747bdd1243dSDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size()); 748bdd1243dSDimitry Andric 749bdd1243dSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 750bdd1243dSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 751bdd1243dSDimitry Andric Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL, 752bdd1243dSDimitry Andric getContext()); 753bdd1243dSDimitry Andric Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 75406c3fb27SDimitry Andric return ParseStatus::Success; 755bdd1243dSDimitry Andric } 756bdd1243dSDimitry Andric 75706c3fb27SDimitry Andric ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) { 758bdd1243dSDimitry Andric // Parse "$r*". 75906c3fb27SDimitry Andric if (!parseRegister(Operands).isSuccess()) 76006c3fb27SDimitry Andric return ParseStatus::NoMatch; 761bdd1243dSDimitry Andric 762bdd1243dSDimitry Andric // If there is a next operand and it is 0, ignore it. Otherwise print a 763bdd1243dSDimitry Andric // diagnostic message. 76406c3fb27SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) { 765bdd1243dSDimitry Andric int64_t ImmVal; 766bdd1243dSDimitry Andric SMLoc ImmStart = getLoc(); 767bdd1243dSDimitry Andric if (getParser().parseIntToken(ImmVal, "expected optional integer offset")) 76806c3fb27SDimitry Andric return ParseStatus::Failure; 76906c3fb27SDimitry Andric if (ImmVal) 77006c3fb27SDimitry Andric return Error(ImmStart, "optional integer offset must be 0"); 771bdd1243dSDimitry Andric } 772bdd1243dSDimitry Andric 77306c3fb27SDimitry Andric return ParseStatus::Success; 774bdd1243dSDimitry Andric } 77581ad6265SDimitry Andric /// Looks at a token type and creates the relevant operand from this 77681ad6265SDimitry Andric /// information, adding to Operands. Return true upon an error. 77781ad6265SDimitry Andric bool LoongArchAsmParser::parseOperand(OperandVector &Operands, 77881ad6265SDimitry Andric StringRef Mnemonic) { 779bdd1243dSDimitry Andric // Check if the current operand has a custom associated parser, if so, try to 780bdd1243dSDimitry Andric // custom parse the operand, or fallback to the general approach. 78106c3fb27SDimitry Andric ParseStatus Result = 782bdd1243dSDimitry Andric MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true); 78306c3fb27SDimitry Andric if (Result.isSuccess()) 784bdd1243dSDimitry Andric return false; 78506c3fb27SDimitry Andric if (Result.isFailure()) 786bdd1243dSDimitry Andric return true; 787bdd1243dSDimitry Andric 78806c3fb27SDimitry Andric if (parseRegister(Operands).isSuccess() || 78906c3fb27SDimitry Andric parseImmediate(Operands).isSuccess()) 79081ad6265SDimitry Andric return false; 79181ad6265SDimitry Andric 79281ad6265SDimitry Andric // Finally we have exhausted all options and must declare defeat. 79306c3fb27SDimitry Andric return Error(getLoc(), "unknown operand"); 79481ad6265SDimitry Andric } 79581ad6265SDimitry Andric 79681ad6265SDimitry Andric bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, 79781ad6265SDimitry Andric StringRef Name, SMLoc NameLoc, 79881ad6265SDimitry Andric OperandVector &Operands) { 79981ad6265SDimitry Andric // First operand in MCInst is instruction mnemonic. 80081ad6265SDimitry Andric Operands.push_back(LoongArchOperand::createToken(Name, NameLoc)); 80181ad6265SDimitry Andric 80281ad6265SDimitry Andric // If there are no more operands, then finish. 80381ad6265SDimitry Andric if (parseOptionalToken(AsmToken::EndOfStatement)) 80481ad6265SDimitry Andric return false; 80581ad6265SDimitry Andric 80681ad6265SDimitry Andric // Parse first operand. 80781ad6265SDimitry Andric if (parseOperand(Operands, Name)) 80881ad6265SDimitry Andric return true; 80981ad6265SDimitry Andric 81081ad6265SDimitry Andric // Parse until end of statement, consuming commas between operands. 81181ad6265SDimitry Andric while (parseOptionalToken(AsmToken::Comma)) 81281ad6265SDimitry Andric if (parseOperand(Operands, Name)) 81381ad6265SDimitry Andric return true; 81481ad6265SDimitry Andric 81581ad6265SDimitry Andric // Parse end of statement and return successfully. 81681ad6265SDimitry Andric if (parseOptionalToken(AsmToken::EndOfStatement)) 81781ad6265SDimitry Andric return false; 81881ad6265SDimitry Andric 81981ad6265SDimitry Andric SMLoc Loc = getLexer().getLoc(); 82081ad6265SDimitry Andric getParser().eatToEndOfStatement(); 82181ad6265SDimitry Andric return Error(Loc, "unexpected token"); 82281ad6265SDimitry Andric } 82381ad6265SDimitry Andric 824bdd1243dSDimitry Andric void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, 825bdd1243dSDimitry Andric const MCExpr *Symbol, 826bdd1243dSDimitry Andric SmallVectorImpl<Inst> &Insts, 827647cbc5dSDimitry Andric SMLoc IDLoc, MCStreamer &Out, 828647cbc5dSDimitry Andric bool RelaxHint) { 829bdd1243dSDimitry Andric MCContext &Ctx = getContext(); 830bdd1243dSDimitry Andric for (LoongArchAsmParser::Inst &Inst : Insts) { 831bdd1243dSDimitry Andric unsigned Opc = Inst.Opc; 832bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind VK = Inst.VK; 833647cbc5dSDimitry Andric const LoongArchMCExpr *LE = 834647cbc5dSDimitry Andric LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint); 835bdd1243dSDimitry Andric switch (Opc) { 836bdd1243dSDimitry Andric default: 837bdd1243dSDimitry Andric llvm_unreachable("unexpected opcode"); 838bdd1243dSDimitry Andric case LoongArch::PCALAU12I: 839bdd1243dSDimitry Andric case LoongArch::LU12I_W: 840bdd1243dSDimitry Andric Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE), 841bdd1243dSDimitry Andric getSTI()); 842bdd1243dSDimitry Andric break; 843bdd1243dSDimitry Andric case LoongArch::ORI: 844bdd1243dSDimitry Andric case LoongArch::ADDI_W: 845bdd1243dSDimitry Andric case LoongArch::LD_W: 846bdd1243dSDimitry Andric case LoongArch::LD_D: { 847bdd1243dSDimitry Andric if (VK == LoongArchMCExpr::VK_LoongArch_None) { 848bdd1243dSDimitry Andric Out.emitInstruction( 849bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0), 850bdd1243dSDimitry Andric getSTI()); 851bdd1243dSDimitry Andric continue; 8520fca6ea1SDimitry Andric } else if (VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD) { 8530fca6ea1SDimitry Andric Out.emitInstruction(MCInstBuilder(Opc) 8540fca6ea1SDimitry Andric .addReg(LoongArch::R1) 8550fca6ea1SDimitry Andric .addReg(DestReg) 8560fca6ea1SDimitry Andric .addExpr(LE), 8570fca6ea1SDimitry Andric getSTI()); 8580fca6ea1SDimitry Andric continue; 859bdd1243dSDimitry Andric } 860bdd1243dSDimitry Andric Out.emitInstruction( 861bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE), 862bdd1243dSDimitry Andric getSTI()); 863bdd1243dSDimitry Andric break; 864bdd1243dSDimitry Andric } 865bdd1243dSDimitry Andric case LoongArch::LU32I_D: 866bdd1243dSDimitry Andric Out.emitInstruction(MCInstBuilder(Opc) 867bdd1243dSDimitry Andric .addReg(DestReg == TmpReg ? DestReg : TmpReg) 868bdd1243dSDimitry Andric .addReg(DestReg == TmpReg ? DestReg : TmpReg) 869bdd1243dSDimitry Andric .addExpr(LE), 870bdd1243dSDimitry Andric getSTI()); 871bdd1243dSDimitry Andric break; 872bdd1243dSDimitry Andric case LoongArch::LU52I_D: 873bdd1243dSDimitry Andric Out.emitInstruction( 874bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE), 875bdd1243dSDimitry Andric getSTI()); 876bdd1243dSDimitry Andric break; 877bdd1243dSDimitry Andric case LoongArch::ADDI_D: 878bdd1243dSDimitry Andric Out.emitInstruction( 879bdd1243dSDimitry Andric MCInstBuilder(Opc) 880bdd1243dSDimitry Andric .addReg(TmpReg) 881bdd1243dSDimitry Andric .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0) 882bdd1243dSDimitry Andric .addExpr(LE), 883bdd1243dSDimitry Andric getSTI()); 884bdd1243dSDimitry Andric break; 885bdd1243dSDimitry Andric case LoongArch::ADD_D: 886bdd1243dSDimitry Andric case LoongArch::LDX_D: 887bdd1243dSDimitry Andric Out.emitInstruction( 888bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg), 889bdd1243dSDimitry Andric getSTI()); 890bdd1243dSDimitry Andric break; 8910fca6ea1SDimitry Andric case LoongArch::JIRL: 8920fca6ea1SDimitry Andric Out.emitInstruction(MCInstBuilder(Opc) 8930fca6ea1SDimitry Andric .addReg(LoongArch::R1) 8940fca6ea1SDimitry Andric .addReg(LoongArch::R1) 8950fca6ea1SDimitry Andric .addExpr(LE), 8960fca6ea1SDimitry Andric getSTI()); 8970fca6ea1SDimitry Andric break; 898bdd1243dSDimitry Andric } 899bdd1243dSDimitry Andric } 900bdd1243dSDimitry Andric } 901bdd1243dSDimitry Andric 902bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, 903bdd1243dSDimitry Andric MCStreamer &Out) { 904bdd1243dSDimitry Andric // la.abs $rd, sym 905bdd1243dSDimitry Andric // expands to: 906bdd1243dSDimitry Andric // lu12i.w $rd, %abs_hi20(sym) 907bdd1243dSDimitry Andric // ori $rd, $rd, %abs_lo12(sym) 908bdd1243dSDimitry Andric // 909bdd1243dSDimitry Andric // for 64bit appends: 910bdd1243dSDimitry Andric // lu32i.d $rd, %abs64_lo20(sym) 911bdd1243dSDimitry Andric // lu52i.d $rd, $rd, %abs64_hi12(sym) 912bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 913bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS 914bdd1243dSDimitry Andric ? Inst.getOperand(1).getExpr() 915bdd1243dSDimitry Andric : Inst.getOperand(2).getExpr(); 916bdd1243dSDimitry Andric InstSeq Insts; 917bdd1243dSDimitry Andric 918bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 919bdd1243dSDimitry Andric LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20)); 920bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 921bdd1243dSDimitry Andric LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12)); 922bdd1243dSDimitry Andric 923bdd1243dSDimitry Andric if (is64Bit()) { 924bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 925bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20)); 926bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 927bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12)); 928bdd1243dSDimitry Andric } 929bdd1243dSDimitry Andric 930bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 931bdd1243dSDimitry Andric } 932bdd1243dSDimitry Andric 933bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, 934bdd1243dSDimitry Andric MCStreamer &Out) { 935bdd1243dSDimitry Andric // la.pcrel $rd, sym 936bdd1243dSDimitry Andric // expands to: 937bdd1243dSDimitry Andric // pcalau12i $rd, %pc_hi20(sym) 938bdd1243dSDimitry Andric // addi.w/d $rd, rd, %pc_lo12(sym) 939bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 940bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 941bdd1243dSDimitry Andric InstSeq Insts; 942bdd1243dSDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 943bdd1243dSDimitry Andric 944bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 945bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 946bdd1243dSDimitry Andric Insts.push_back( 947bdd1243dSDimitry Andric LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 948bdd1243dSDimitry Andric 949647cbc5dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true); 950bdd1243dSDimitry Andric } 951bdd1243dSDimitry Andric 952bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, 953bdd1243dSDimitry Andric MCStreamer &Out) { 954bdd1243dSDimitry Andric // la.pcrel $rd, $rj, sym 955bdd1243dSDimitry Andric // expands to: 956bdd1243dSDimitry Andric // pcalau12i $rd, %pc_hi20(sym) 957bdd1243dSDimitry Andric // addi.d $rj, $r0, %pc_lo12(sym) 958bdd1243dSDimitry Andric // lu32i.d $rj, %pc64_lo20(sym) 959bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %pc64_hi12(sym) 960bdd1243dSDimitry Andric // add.d $rd, $rd, $rj 961bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 962bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 963bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 964bdd1243dSDimitry Andric InstSeq Insts; 965bdd1243dSDimitry Andric 966bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 967bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 968bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 969bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 970bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 971bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20)); 972bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 973bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12)); 974bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 975bdd1243dSDimitry Andric 976bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 977bdd1243dSDimitry Andric } 978bdd1243dSDimitry Andric 979bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, 980bdd1243dSDimitry Andric MCStreamer &Out) { 981bdd1243dSDimitry Andric // la.got $rd, sym 982bdd1243dSDimitry Andric // expands to: 983bdd1243dSDimitry Andric // pcalau12i $rd, %got_pc_hi20(sym) 984bdd1243dSDimitry Andric // ld.w/d $rd, $rd, %got_pc_lo12(sym) 985bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 986bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 987bdd1243dSDimitry Andric InstSeq Insts; 988bdd1243dSDimitry Andric unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 989bdd1243dSDimitry Andric 990bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 991bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 992bdd1243dSDimitry Andric Insts.push_back( 993bdd1243dSDimitry Andric LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 994bdd1243dSDimitry Andric 995647cbc5dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true); 996bdd1243dSDimitry Andric } 997bdd1243dSDimitry Andric 998bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, 999bdd1243dSDimitry Andric MCStreamer &Out) { 1000bdd1243dSDimitry Andric // la.got $rd, $rj, sym 1001bdd1243dSDimitry Andric // expands to: 1002bdd1243dSDimitry Andric // pcalau12i $rd, %got_pc_hi20(sym) 1003bdd1243dSDimitry Andric // addi.d $rj, $r0, %got_pc_lo12(sym) 1004bdd1243dSDimitry Andric // lu32i.d $rj, %got64_pc_lo20(sym) 1005bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1006bdd1243dSDimitry Andric // ldx.d $rd, $rd, $rj 1007bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1008bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 1009bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1010bdd1243dSDimitry Andric InstSeq Insts; 1011bdd1243dSDimitry Andric 1012bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1013bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 1014bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1015bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1016bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1017bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1018bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1019bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1020bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 1021bdd1243dSDimitry Andric 1022bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1023bdd1243dSDimitry Andric } 1024bdd1243dSDimitry Andric 1025bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, 1026bdd1243dSDimitry Andric MCStreamer &Out) { 1027bdd1243dSDimitry Andric // la.tls.le $rd, sym 1028bdd1243dSDimitry Andric // expands to: 1029bdd1243dSDimitry Andric // lu12i.w $rd, %le_hi20(sym) 1030bdd1243dSDimitry Andric // ori $rd, $rd, %le_lo12(sym) 1031bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1032bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1033bdd1243dSDimitry Andric InstSeq Insts; 1034bdd1243dSDimitry Andric 1035bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1036bdd1243dSDimitry Andric LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20)); 1037bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1038bdd1243dSDimitry Andric LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12)); 1039bdd1243dSDimitry Andric 1040bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1041bdd1243dSDimitry Andric } 1042bdd1243dSDimitry Andric 1043bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, 1044bdd1243dSDimitry Andric MCStreamer &Out) { 1045bdd1243dSDimitry Andric // la.tls.ie $rd, sym 1046bdd1243dSDimitry Andric // expands to: 1047bdd1243dSDimitry Andric // pcalau12i $rd, %ie_pc_hi20(sym) 1048bdd1243dSDimitry Andric // ld.w/d $rd, $rd, %ie_pc_lo12(sym) 1049bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1050bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1051bdd1243dSDimitry Andric InstSeq Insts; 1052bdd1243dSDimitry Andric unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 1053bdd1243dSDimitry Andric 1054bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1055bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 1056bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1057bdd1243dSDimitry Andric LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 1058bdd1243dSDimitry Andric 1059bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1060bdd1243dSDimitry Andric } 1061bdd1243dSDimitry Andric 1062bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, 1063bdd1243dSDimitry Andric MCStreamer &Out) { 1064bdd1243dSDimitry Andric // la.tls.ie $rd, $rj, sym 1065bdd1243dSDimitry Andric // expands to: 1066bdd1243dSDimitry Andric // pcalau12i $rd, %ie_pc_hi20(sym) 1067bdd1243dSDimitry Andric // addi.d $rj, $r0, %ie_pc_lo12(sym) 1068bdd1243dSDimitry Andric // lu32i.d $rj, %ie64_pc_lo20(sym) 1069bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %ie64_pc_hi12(sym) 1070bdd1243dSDimitry Andric // ldx.d $rd, $rd, $rj 1071bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1072bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 1073bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1074bdd1243dSDimitry Andric InstSeq Insts; 1075bdd1243dSDimitry Andric 1076bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1077bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 1078bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1079bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 1080bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1081bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20)); 1082bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1083bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12)); 1084bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 1085bdd1243dSDimitry Andric 1086bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1087bdd1243dSDimitry Andric } 1088bdd1243dSDimitry Andric 1089bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, 1090bdd1243dSDimitry Andric MCStreamer &Out) { 1091bdd1243dSDimitry Andric // la.tls.ld $rd, sym 1092bdd1243dSDimitry Andric // expands to: 1093bdd1243dSDimitry Andric // pcalau12i $rd, %ld_pc_hi20(sym) 1094bdd1243dSDimitry Andric // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1095bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1096bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1097bdd1243dSDimitry Andric InstSeq Insts; 1098bdd1243dSDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1099bdd1243dSDimitry Andric 1100bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1101bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1102bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1103bdd1243dSDimitry Andric ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1104bdd1243dSDimitry Andric 1105bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1106bdd1243dSDimitry Andric } 1107bdd1243dSDimitry Andric 1108bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, 1109bdd1243dSDimitry Andric MCStreamer &Out) { 1110bdd1243dSDimitry Andric // la.tls.ld $rd, $rj, sym 1111bdd1243dSDimitry Andric // expands to: 1112bdd1243dSDimitry Andric // pcalau12i $rd, %ld_pc_hi20(sym) 1113bdd1243dSDimitry Andric // addi.d $rj, $r0, %got_pc_lo12(sym) 1114bdd1243dSDimitry Andric // lu32i.d $rj, %got64_pc_lo20(sym) 1115bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1116bdd1243dSDimitry Andric // add.d $rd, $rd, $rj 1117bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1118bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 1119bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1120bdd1243dSDimitry Andric InstSeq Insts; 1121bdd1243dSDimitry Andric 1122bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1123bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1124bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1125bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1126bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1127bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1128bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1129bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1130bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1131bdd1243dSDimitry Andric 1132bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1133bdd1243dSDimitry Andric } 1134bdd1243dSDimitry Andric 1135bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, 1136bdd1243dSDimitry Andric MCStreamer &Out) { 1137bdd1243dSDimitry Andric // la.tls.gd $rd, sym 1138bdd1243dSDimitry Andric // expands to: 1139bdd1243dSDimitry Andric // pcalau12i $rd, %gd_pc_hi20(sym) 1140bdd1243dSDimitry Andric // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1141bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1142bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1143bdd1243dSDimitry Andric InstSeq Insts; 1144bdd1243dSDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1145bdd1243dSDimitry Andric 1146bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1147bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1148bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1149bdd1243dSDimitry Andric ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1150bdd1243dSDimitry Andric 1151bdd1243dSDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1152bdd1243dSDimitry Andric } 1153bdd1243dSDimitry Andric 1154bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, 1155bdd1243dSDimitry Andric MCStreamer &Out) { 1156bdd1243dSDimitry Andric // la.tls.gd $rd, $rj, sym 1157bdd1243dSDimitry Andric // expands to: 1158bdd1243dSDimitry Andric // pcalau12i $rd, %gd_pc_hi20(sym) 1159bdd1243dSDimitry Andric // addi.d $rj, $r0, %got_pc_lo12(sym) 1160bdd1243dSDimitry Andric // lu32i.d $rj, %got64_pc_lo20(sym) 1161bdd1243dSDimitry Andric // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1162bdd1243dSDimitry Andric // add.d $rd, $rd, $rj 1163bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1164bdd1243dSDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 1165bdd1243dSDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1166bdd1243dSDimitry Andric InstSeq Insts; 1167bdd1243dSDimitry Andric 1168bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1169bdd1243dSDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1170bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1171bdd1243dSDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1172bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1173bdd1243dSDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1174bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 1175bdd1243dSDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1176bdd1243dSDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1177bdd1243dSDimitry Andric 1178bdd1243dSDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1179bdd1243dSDimitry Andric } 1180bdd1243dSDimitry Andric 11810fca6ea1SDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc, 11820fca6ea1SDimitry Andric MCStreamer &Out) { 11830fca6ea1SDimitry Andric // `la.tls.desc $rd, sym` with `la-global-with-abs` feature 11840fca6ea1SDimitry Andric // for la32 expands to: 11850fca6ea1SDimitry Andric // lu12i.w $rd, %desc_hi20(sym) 11860fca6ea1SDimitry Andric // ori $rd, $rd, %desc_lo12(sym) 11870fca6ea1SDimitry Andric // ld.w $ra, $rd, %desc_ld(sym) 11880fca6ea1SDimitry Andric // jirl $ra, $ra, %desc_call(sym) 11890fca6ea1SDimitry Andric // 11900fca6ea1SDimitry Andric // for la64 expands to: 11910fca6ea1SDimitry Andric // lu12i.w $rd, %desc_hi20(sym) 11920fca6ea1SDimitry Andric // ori $rd, $rd, %desc_lo12(sym) 11930fca6ea1SDimitry Andric // lu32i.d $rd, %desc64_lo20(sym) 11940fca6ea1SDimitry Andric // lu52i.d $rd, $rd, %desc64_hi12(sym) 11950fca6ea1SDimitry Andric // ld.d $ra, $rd, %desc_ld(sym) 11960fca6ea1SDimitry Andric // jirl $ra, $ra, %desc_call(sym) 11970fca6ea1SDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 11980fca6ea1SDimitry Andric const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_TLS_DESC_ABS 11990fca6ea1SDimitry Andric ? Inst.getOperand(1).getExpr() 12000fca6ea1SDimitry Andric : Inst.getOperand(2).getExpr(); 12010fca6ea1SDimitry Andric unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 12020fca6ea1SDimitry Andric InstSeq Insts; 12030fca6ea1SDimitry Andric 12040fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12050fca6ea1SDimitry Andric LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20)); 12060fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12070fca6ea1SDimitry Andric LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12)); 12080fca6ea1SDimitry Andric 12090fca6ea1SDimitry Andric if (is64Bit()) { 12100fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12110fca6ea1SDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20)); 12120fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12130fca6ea1SDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12)); 12140fca6ea1SDimitry Andric } 12150fca6ea1SDimitry Andric 12160fca6ea1SDimitry Andric Insts.push_back( 12170fca6ea1SDimitry Andric LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD)); 12180fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12190fca6ea1SDimitry Andric LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL)); 12200fca6ea1SDimitry Andric 12210fca6ea1SDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 12220fca6ea1SDimitry Andric } 12230fca6ea1SDimitry Andric 12240fca6ea1SDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc, 12250fca6ea1SDimitry Andric MCStreamer &Out) { 12260fca6ea1SDimitry Andric // la.tls.desc $rd, sym 12270fca6ea1SDimitry Andric // expands to: 12280fca6ea1SDimitry Andric // pcalau12i $rd, %desc_pc_hi20(sym) 12290fca6ea1SDimitry Andric // addi.w/d $rd, $rd, %desc_pc_lo12(sym) 12300fca6ea1SDimitry Andric // ld.w/d $ra, $rd, %desc_ld(sym) 12310fca6ea1SDimitry Andric // jirl $ra, $ra, %desc_call(sym) 12320fca6ea1SDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 12330fca6ea1SDimitry Andric const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 12340fca6ea1SDimitry Andric unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 12350fca6ea1SDimitry Andric unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 12360fca6ea1SDimitry Andric InstSeq Insts; 12370fca6ea1SDimitry Andric 12380fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12390fca6ea1SDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20)); 12400fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12410fca6ea1SDimitry Andric ADDI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12)); 12420fca6ea1SDimitry Andric Insts.push_back( 12430fca6ea1SDimitry Andric LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD)); 12440fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12450fca6ea1SDimitry Andric LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL)); 12460fca6ea1SDimitry Andric 12470fca6ea1SDimitry Andric emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 12480fca6ea1SDimitry Andric } 12490fca6ea1SDimitry Andric 12500fca6ea1SDimitry Andric void LoongArchAsmParser::emitLoadAddressTLSDescPcrelLarge(MCInst &Inst, 12510fca6ea1SDimitry Andric SMLoc IDLoc, 12520fca6ea1SDimitry Andric MCStreamer &Out) { 12530fca6ea1SDimitry Andric // la.tls.desc $rd, $rj, sym 12540fca6ea1SDimitry Andric // expands to: 12550fca6ea1SDimitry Andric // pcalau12i $rd, %desc_pc_hi20(sym) 12560fca6ea1SDimitry Andric // addi.d $rj, $r0, %desc_pc_lo12(sym) 12570fca6ea1SDimitry Andric // lu32i.d $rj, %desc64_pc_lo20(sym) 12580fca6ea1SDimitry Andric // lu52i.d $rj, $rj, %desc64_pc_hi12(sym) 12590fca6ea1SDimitry Andric // add.d $rd, $rd, $rj 12600fca6ea1SDimitry Andric // ld.w/d $ra, $rd, %desc_ld(sym) 12610fca6ea1SDimitry Andric // jirl $ra, $ra, %desc_call(sym) 12620fca6ea1SDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 12630fca6ea1SDimitry Andric MCRegister TmpReg = Inst.getOperand(1).getReg(); 12640fca6ea1SDimitry Andric const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 12650fca6ea1SDimitry Andric InstSeq Insts; 12660fca6ea1SDimitry Andric 12670fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12680fca6ea1SDimitry Andric LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20)); 12690fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12700fca6ea1SDimitry Andric LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12)); 12710fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12720fca6ea1SDimitry Andric LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20)); 12730fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12740fca6ea1SDimitry Andric LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12)); 12750fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 12760fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12770fca6ea1SDimitry Andric LoongArch::LD_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD)); 12780fca6ea1SDimitry Andric Insts.push_back(LoongArchAsmParser::Inst( 12790fca6ea1SDimitry Andric LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL)); 12800fca6ea1SDimitry Andric 12810fca6ea1SDimitry Andric emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 12820fca6ea1SDimitry Andric } 12830fca6ea1SDimitry Andric 1284bdd1243dSDimitry Andric void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc, 1285bdd1243dSDimitry Andric MCStreamer &Out) { 1286bdd1243dSDimitry Andric MCRegister DestReg = Inst.getOperand(0).getReg(); 1287bdd1243dSDimitry Andric int64_t Imm = Inst.getOperand(1).getImm(); 1288bdd1243dSDimitry Andric MCRegister SrcReg = LoongArch::R0; 1289bdd1243dSDimitry Andric 1290bdd1243dSDimitry Andric if (Inst.getOpcode() == LoongArch::PseudoLI_W) 1291bdd1243dSDimitry Andric Imm = SignExtend64<32>(Imm); 1292bdd1243dSDimitry Andric 1293bdd1243dSDimitry Andric for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) { 1294bdd1243dSDimitry Andric unsigned Opc = Inst.Opc; 1295bdd1243dSDimitry Andric if (Opc == LoongArch::LU12I_W) 1296bdd1243dSDimitry Andric Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm), 1297bdd1243dSDimitry Andric getSTI()); 1298bdd1243dSDimitry Andric else 1299bdd1243dSDimitry Andric Out.emitInstruction( 1300bdd1243dSDimitry Andric MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm), 1301bdd1243dSDimitry Andric getSTI()); 1302bdd1243dSDimitry Andric SrcReg = DestReg; 1303bdd1243dSDimitry Andric } 1304bdd1243dSDimitry Andric } 1305bdd1243dSDimitry Andric 13061db9f3b2SDimitry Andric void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc, 13071db9f3b2SDimitry Andric MCStreamer &Out, bool IsTailCall) { 13081db9f3b2SDimitry Andric // call36 sym 13091db9f3b2SDimitry Andric // expands to: 13101db9f3b2SDimitry Andric // pcaddu18i $ra, %call36(sym) 13111db9f3b2SDimitry Andric // jirl $ra, $ra, 0 13121db9f3b2SDimitry Andric // 13131db9f3b2SDimitry Andric // tail36 $rj, sym 13141db9f3b2SDimitry Andric // expands to: 13151db9f3b2SDimitry Andric // pcaddu18i $rj, %call36(sym) 13161db9f3b2SDimitry Andric // jirl $r0, $rj, 0 13171db9f3b2SDimitry Andric unsigned ScratchReg = 13181db9f3b2SDimitry Andric IsTailCall ? Inst.getOperand(0).getReg() : (unsigned)LoongArch::R1; 13191db9f3b2SDimitry Andric const MCExpr *Sym = 13201db9f3b2SDimitry Andric IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr(); 13211db9f3b2SDimitry Andric const LoongArchMCExpr *LE = LoongArchMCExpr::create( 13221db9f3b2SDimitry Andric Sym, llvm::LoongArchMCExpr::VK_LoongArch_CALL36, getContext()); 13231db9f3b2SDimitry Andric 13241db9f3b2SDimitry Andric Out.emitInstruction( 13251db9f3b2SDimitry Andric MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE), 13261db9f3b2SDimitry Andric getSTI()); 13271db9f3b2SDimitry Andric Out.emitInstruction( 13281db9f3b2SDimitry Andric MCInstBuilder(LoongArch::JIRL) 13291db9f3b2SDimitry Andric .addReg(IsTailCall ? (unsigned)LoongArch::R0 : ScratchReg) 13301db9f3b2SDimitry Andric .addReg(ScratchReg) 13311db9f3b2SDimitry Andric .addImm(0), 13321db9f3b2SDimitry Andric getSTI()); 13331db9f3b2SDimitry Andric } 13341db9f3b2SDimitry Andric 133581ad6265SDimitry Andric bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 133681ad6265SDimitry Andric OperandVector &Operands, 133781ad6265SDimitry Andric MCStreamer &Out) { 133881ad6265SDimitry Andric Inst.setLoc(IDLoc); 1339bdd1243dSDimitry Andric switch (Inst.getOpcode()) { 1340bdd1243dSDimitry Andric default: 1341bdd1243dSDimitry Andric break; 1342bdd1243dSDimitry Andric case LoongArch::PseudoLA_ABS: 1343bdd1243dSDimitry Andric case LoongArch::PseudoLA_ABS_LARGE: 1344bdd1243dSDimitry Andric emitLoadAddressAbs(Inst, IDLoc, Out); 1345bdd1243dSDimitry Andric return false; 1346bdd1243dSDimitry Andric case LoongArch::PseudoLA_PCREL: 1347bdd1243dSDimitry Andric emitLoadAddressPcrel(Inst, IDLoc, Out); 1348bdd1243dSDimitry Andric return false; 1349bdd1243dSDimitry Andric case LoongArch::PseudoLA_PCREL_LARGE: 1350bdd1243dSDimitry Andric emitLoadAddressPcrelLarge(Inst, IDLoc, Out); 1351bdd1243dSDimitry Andric return false; 1352bdd1243dSDimitry Andric case LoongArch::PseudoLA_GOT: 1353bdd1243dSDimitry Andric emitLoadAddressGot(Inst, IDLoc, Out); 1354bdd1243dSDimitry Andric return false; 1355bdd1243dSDimitry Andric case LoongArch::PseudoLA_GOT_LARGE: 1356bdd1243dSDimitry Andric emitLoadAddressGotLarge(Inst, IDLoc, Out); 1357bdd1243dSDimitry Andric return false; 1358bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LE: 1359bdd1243dSDimitry Andric emitLoadAddressTLSLE(Inst, IDLoc, Out); 1360bdd1243dSDimitry Andric return false; 1361bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_IE: 1362bdd1243dSDimitry Andric emitLoadAddressTLSIE(Inst, IDLoc, Out); 1363bdd1243dSDimitry Andric return false; 1364bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_IE_LARGE: 1365bdd1243dSDimitry Andric emitLoadAddressTLSIELarge(Inst, IDLoc, Out); 1366bdd1243dSDimitry Andric return false; 1367bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LD: 1368bdd1243dSDimitry Andric emitLoadAddressTLSLD(Inst, IDLoc, Out); 1369bdd1243dSDimitry Andric return false; 1370bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LD_LARGE: 1371bdd1243dSDimitry Andric emitLoadAddressTLSLDLarge(Inst, IDLoc, Out); 1372bdd1243dSDimitry Andric return false; 1373bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_GD: 1374bdd1243dSDimitry Andric emitLoadAddressTLSGD(Inst, IDLoc, Out); 1375bdd1243dSDimitry Andric return false; 1376bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_GD_LARGE: 1377bdd1243dSDimitry Andric emitLoadAddressTLSGDLarge(Inst, IDLoc, Out); 1378bdd1243dSDimitry Andric return false; 13790fca6ea1SDimitry Andric case LoongArch::PseudoLA_TLS_DESC_ABS: 13800fca6ea1SDimitry Andric case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE: 13810fca6ea1SDimitry Andric emitLoadAddressTLSDescAbs(Inst, IDLoc, Out); 13820fca6ea1SDimitry Andric return false; 13830fca6ea1SDimitry Andric case LoongArch::PseudoLA_TLS_DESC_PC: 13840fca6ea1SDimitry Andric emitLoadAddressTLSDescPcrel(Inst, IDLoc, Out); 13850fca6ea1SDimitry Andric return false; 13860fca6ea1SDimitry Andric case LoongArch::PseudoLA_TLS_DESC_PC_LARGE: 13870fca6ea1SDimitry Andric emitLoadAddressTLSDescPcrelLarge(Inst, IDLoc, Out); 13880fca6ea1SDimitry Andric return false; 1389bdd1243dSDimitry Andric case LoongArch::PseudoLI_W: 1390bdd1243dSDimitry Andric case LoongArch::PseudoLI_D: 1391bdd1243dSDimitry Andric emitLoadImm(Inst, IDLoc, Out); 1392bdd1243dSDimitry Andric return false; 13931db9f3b2SDimitry Andric case LoongArch::PseudoCALL36: 13941db9f3b2SDimitry Andric emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false); 13951db9f3b2SDimitry Andric return false; 13961db9f3b2SDimitry Andric case LoongArch::PseudoTAIL36: 13971db9f3b2SDimitry Andric emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true); 13981db9f3b2SDimitry Andric return false; 1399bdd1243dSDimitry Andric } 140081ad6265SDimitry Andric Out.emitInstruction(Inst, getSTI()); 140181ad6265SDimitry Andric return false; 140281ad6265SDimitry Andric } 140381ad6265SDimitry Andric 140481ad6265SDimitry Andric unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 1405bdd1243dSDimitry Andric unsigned Opc = Inst.getOpcode(); 1406bdd1243dSDimitry Andric switch (Opc) { 140781ad6265SDimitry Andric default: 1408bdd1243dSDimitry Andric if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) { 1409bdd1243dSDimitry Andric unsigned Rd = Inst.getOperand(0).getReg(); 1410bdd1243dSDimitry Andric unsigned Rk = Inst.getOperand(1).getReg(); 1411bdd1243dSDimitry Andric unsigned Rj = Inst.getOperand(2).getReg(); 1412bdd1243dSDimitry Andric if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0) 1413bdd1243dSDimitry Andric return Match_RequiresAMORdDifferRkRj; 1414bdd1243dSDimitry Andric } 141581ad6265SDimitry Andric break; 14160fca6ea1SDimitry Andric case LoongArch::PseudoLA_TLS_DESC_ABS: 14170fca6ea1SDimitry Andric case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE: 14180fca6ea1SDimitry Andric case LoongArch::PseudoLA_TLS_DESC_PC: 14190fca6ea1SDimitry Andric case LoongArch::PseudoLA_TLS_DESC_PC_LARGE: { 14200fca6ea1SDimitry Andric unsigned Rd = Inst.getOperand(0).getReg(); 14210fca6ea1SDimitry Andric if (Rd != LoongArch::R4) 14220fca6ea1SDimitry Andric return Match_RequiresLAORdR4; 14230fca6ea1SDimitry Andric break; 14240fca6ea1SDimitry Andric } 1425bdd1243dSDimitry Andric case LoongArch::PseudoLA_PCREL_LARGE: 1426bdd1243dSDimitry Andric case LoongArch::PseudoLA_GOT_LARGE: 1427bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_IE_LARGE: 1428bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_LD_LARGE: 1429bdd1243dSDimitry Andric case LoongArch::PseudoLA_TLS_GD_LARGE: { 1430bdd1243dSDimitry Andric unsigned Rd = Inst.getOperand(0).getReg(); 1431bdd1243dSDimitry Andric unsigned Rj = Inst.getOperand(1).getReg(); 1432bdd1243dSDimitry Andric if (Rd == Rj) 1433bdd1243dSDimitry Andric return Match_RequiresLAORdDifferRj; 1434bdd1243dSDimitry Andric break; 1435bdd1243dSDimitry Andric } 143606c3fb27SDimitry Andric case LoongArch::CSRXCHG: 143706c3fb27SDimitry Andric case LoongArch::GCSRXCHG: { 143881ad6265SDimitry Andric unsigned Rj = Inst.getOperand(2).getReg(); 143981ad6265SDimitry Andric if (Rj == LoongArch::R0 || Rj == LoongArch::R1) 144081ad6265SDimitry Andric return Match_RequiresOpnd2NotR0R1; 144181ad6265SDimitry Andric return Match_Success; 144281ad6265SDimitry Andric } 144381ad6265SDimitry Andric case LoongArch::BSTRINS_W: 144481ad6265SDimitry Andric case LoongArch::BSTRINS_D: 144581ad6265SDimitry Andric case LoongArch::BSTRPICK_W: 144681ad6265SDimitry Andric case LoongArch::BSTRPICK_D: { 144781ad6265SDimitry Andric unsigned Opc = Inst.getOpcode(); 144881ad6265SDimitry Andric const signed Msb = 144981ad6265SDimitry Andric (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 145081ad6265SDimitry Andric ? Inst.getOperand(3).getImm() 145181ad6265SDimitry Andric : Inst.getOperand(2).getImm(); 145281ad6265SDimitry Andric const signed Lsb = 145381ad6265SDimitry Andric (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 145481ad6265SDimitry Andric ? Inst.getOperand(4).getImm() 145581ad6265SDimitry Andric : Inst.getOperand(3).getImm(); 145681ad6265SDimitry Andric if (Msb < Lsb) 145781ad6265SDimitry Andric return Match_RequiresMsbNotLessThanLsb; 145881ad6265SDimitry Andric return Match_Success; 145981ad6265SDimitry Andric } 146081ad6265SDimitry Andric } 146181ad6265SDimitry Andric 146281ad6265SDimitry Andric return Match_Success; 146381ad6265SDimitry Andric } 146481ad6265SDimitry Andric 146581ad6265SDimitry Andric unsigned 146681ad6265SDimitry Andric LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 146781ad6265SDimitry Andric unsigned Kind) { 146881ad6265SDimitry Andric LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp); 146981ad6265SDimitry Andric if (!Op.isReg()) 147081ad6265SDimitry Andric return Match_InvalidOperand; 147181ad6265SDimitry Andric 147281ad6265SDimitry Andric MCRegister Reg = Op.getReg(); 147381ad6265SDimitry Andric // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the 147481ad6265SDimitry Andric // register from FPR32 to FPR64 if necessary. 147581ad6265SDimitry Andric if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) && 147681ad6265SDimitry Andric Kind == MCK_FPR64) { 147781ad6265SDimitry Andric Op.setReg(convertFPR32ToFPR64(Reg)); 147881ad6265SDimitry Andric return Match_Success; 147981ad6265SDimitry Andric } 148081ad6265SDimitry Andric 148181ad6265SDimitry Andric return Match_InvalidOperand; 148281ad6265SDimitry Andric } 148381ad6265SDimitry Andric 148481ad6265SDimitry Andric bool LoongArchAsmParser::generateImmOutOfRangeError( 148581ad6265SDimitry Andric OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, 148606c3fb27SDimitry Andric const Twine &Msg = "immediate must be an integer in the range") { 148781ad6265SDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 148881ad6265SDimitry Andric return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 148981ad6265SDimitry Andric } 149081ad6265SDimitry Andric 149181ad6265SDimitry Andric bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 149281ad6265SDimitry Andric OperandVector &Operands, 149381ad6265SDimitry Andric MCStreamer &Out, 149481ad6265SDimitry Andric uint64_t &ErrorInfo, 149581ad6265SDimitry Andric bool MatchingInlineAsm) { 149681ad6265SDimitry Andric MCInst Inst; 149781ad6265SDimitry Andric FeatureBitset MissingFeatures; 149881ad6265SDimitry Andric 149981ad6265SDimitry Andric auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, 150081ad6265SDimitry Andric MatchingInlineAsm); 150181ad6265SDimitry Andric switch (Result) { 150281ad6265SDimitry Andric default: 150381ad6265SDimitry Andric break; 150481ad6265SDimitry Andric case Match_Success: 150581ad6265SDimitry Andric return processInstruction(Inst, IDLoc, Operands, Out); 150681ad6265SDimitry Andric case Match_MissingFeature: { 150781ad6265SDimitry Andric assert(MissingFeatures.any() && "Unknown missing features!"); 150881ad6265SDimitry Andric bool FirstFeature = true; 150981ad6265SDimitry Andric std::string Msg = "instruction requires the following:"; 151081ad6265SDimitry Andric for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { 151181ad6265SDimitry Andric if (MissingFeatures[i]) { 151281ad6265SDimitry Andric Msg += FirstFeature ? " " : ", "; 151381ad6265SDimitry Andric Msg += getSubtargetFeatureName(i); 151481ad6265SDimitry Andric FirstFeature = false; 151581ad6265SDimitry Andric } 151681ad6265SDimitry Andric } 151781ad6265SDimitry Andric return Error(IDLoc, Msg); 151881ad6265SDimitry Andric } 151981ad6265SDimitry Andric case Match_MnemonicFail: { 152081ad6265SDimitry Andric FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 152181ad6265SDimitry Andric std::string Suggestion = LoongArchMnemonicSpellCheck( 152281ad6265SDimitry Andric ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0); 152381ad6265SDimitry Andric return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); 152481ad6265SDimitry Andric } 152581ad6265SDimitry Andric case Match_InvalidOperand: { 152681ad6265SDimitry Andric SMLoc ErrorLoc = IDLoc; 152781ad6265SDimitry Andric if (ErrorInfo != ~0ULL) { 152881ad6265SDimitry Andric if (ErrorInfo >= Operands.size()) 152981ad6265SDimitry Andric return Error(ErrorLoc, "too few operands for instruction"); 153081ad6265SDimitry Andric 153181ad6265SDimitry Andric ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 153281ad6265SDimitry Andric if (ErrorLoc == SMLoc()) 153381ad6265SDimitry Andric ErrorLoc = IDLoc; 153481ad6265SDimitry Andric } 153581ad6265SDimitry Andric return Error(ErrorLoc, "invalid operand for instruction"); 153681ad6265SDimitry Andric } 153781ad6265SDimitry Andric } 153881ad6265SDimitry Andric 153981ad6265SDimitry Andric // Handle the case when the error message is of specific type 154081ad6265SDimitry Andric // other than the generic Match_InvalidOperand, and the 154181ad6265SDimitry Andric // corresponding operand is missing. 154281ad6265SDimitry Andric if (Result > FIRST_TARGET_MATCH_RESULT_TY) { 154381ad6265SDimitry Andric SMLoc ErrorLoc = IDLoc; 154481ad6265SDimitry Andric if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size()) 154581ad6265SDimitry Andric return Error(ErrorLoc, "too few operands for instruction"); 154681ad6265SDimitry Andric } 154781ad6265SDimitry Andric 154881ad6265SDimitry Andric switch (Result) { 154981ad6265SDimitry Andric default: 155081ad6265SDimitry Andric break; 155181ad6265SDimitry Andric case Match_RequiresMsbNotLessThanLsb: { 155281ad6265SDimitry Andric SMLoc ErrorStart = Operands[3]->getStartLoc(); 155381ad6265SDimitry Andric return Error(ErrorStart, "msb is less than lsb", 155481ad6265SDimitry Andric SMRange(ErrorStart, Operands[4]->getEndLoc())); 155581ad6265SDimitry Andric } 155681ad6265SDimitry Andric case Match_RequiresOpnd2NotR0R1: 155781ad6265SDimitry Andric return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1"); 1558bdd1243dSDimitry Andric case Match_RequiresAMORdDifferRkRj: 1559bdd1243dSDimitry Andric return Error(Operands[1]->getStartLoc(), 1560bdd1243dSDimitry Andric "$rd must be different from both $rk and $rj"); 1561bdd1243dSDimitry Andric case Match_RequiresLAORdDifferRj: 1562bdd1243dSDimitry Andric return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj"); 15630fca6ea1SDimitry Andric case Match_RequiresLAORdR4: 15640fca6ea1SDimitry Andric return Error(Operands[1]->getStartLoc(), "$rd must be $r4"); 156506c3fb27SDimitry Andric case Match_InvalidUImm1: 156606c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 156706c3fb27SDimitry Andric /*Upper=*/(1 << 1) - 1); 156881ad6265SDimitry Andric case Match_InvalidUImm2: 156981ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 157081ad6265SDimitry Andric /*Upper=*/(1 << 2) - 1); 157181ad6265SDimitry Andric case Match_InvalidUImm2plus1: 157281ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1, 157381ad6265SDimitry Andric /*Upper=*/(1 << 2)); 157481ad6265SDimitry Andric case Match_InvalidUImm3: 157581ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 157681ad6265SDimitry Andric /*Upper=*/(1 << 3) - 1); 157706c3fb27SDimitry Andric case Match_InvalidUImm4: 157806c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 157906c3fb27SDimitry Andric /*Upper=*/(1 << 4) - 1); 158081ad6265SDimitry Andric case Match_InvalidUImm5: 158181ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 158281ad6265SDimitry Andric /*Upper=*/(1 << 5) - 1); 158381ad6265SDimitry Andric case Match_InvalidUImm6: 158481ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 158581ad6265SDimitry Andric /*Upper=*/(1 << 6) - 1); 158606c3fb27SDimitry Andric case Match_InvalidUImm7: 158706c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 158806c3fb27SDimitry Andric /*Upper=*/(1 << 7) - 1); 158906c3fb27SDimitry Andric case Match_InvalidUImm8: 159006c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 159106c3fb27SDimitry Andric /*Upper=*/(1 << 8) - 1); 159281ad6265SDimitry Andric case Match_InvalidUImm12: 159381ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 159481ad6265SDimitry Andric /*Upper=*/(1 << 12) - 1); 1595bdd1243dSDimitry Andric case Match_InvalidUImm12ori: 1596bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1597bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/0, 1598bdd1243dSDimitry Andric /*Upper=*/(1 << 12) - 1, 1599bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %abs_lo12) or an " 1600bdd1243dSDimitry Andric "integer in the range"); 160106c3fb27SDimitry Andric case Match_InvalidUImm14: 160206c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 160306c3fb27SDimitry Andric /*Upper=*/(1 << 14) - 1); 160481ad6265SDimitry Andric case Match_InvalidUImm15: 160581ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 160681ad6265SDimitry Andric /*Upper=*/(1 << 15) - 1); 160706c3fb27SDimitry Andric case Match_InvalidSImm5: 160806c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4), 160906c3fb27SDimitry Andric /*Upper=*/(1 << 4) - 1); 161006c3fb27SDimitry Andric case Match_InvalidSImm8: 161106c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7), 161206c3fb27SDimitry Andric /*Upper=*/(1 << 7) - 1); 161306c3fb27SDimitry Andric case Match_InvalidSImm8lsl1: 161406c3fb27SDimitry Andric return generateImmOutOfRangeError( 161506c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2, 161606c3fb27SDimitry Andric "immediate must be a multiple of 2 in the range"); 161706c3fb27SDimitry Andric case Match_InvalidSImm8lsl2: 161806c3fb27SDimitry Andric return generateImmOutOfRangeError( 161906c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4, 162006c3fb27SDimitry Andric "immediate must be a multiple of 4 in the range"); 162106c3fb27SDimitry Andric case Match_InvalidSImm10: 162206c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9), 162306c3fb27SDimitry Andric /*Upper=*/(1 << 9) - 1); 162406c3fb27SDimitry Andric case Match_InvalidSImm8lsl3: 162506c3fb27SDimitry Andric return generateImmOutOfRangeError( 162606c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8, 162706c3fb27SDimitry Andric "immediate must be a multiple of 8 in the range"); 162806c3fb27SDimitry Andric case Match_InvalidSImm9lsl3: 162906c3fb27SDimitry Andric return generateImmOutOfRangeError( 163006c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8, 163106c3fb27SDimitry Andric "immediate must be a multiple of 8 in the range"); 163206c3fb27SDimitry Andric case Match_InvalidSImm10lsl2: 163306c3fb27SDimitry Andric return generateImmOutOfRangeError( 163406c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4, 163506c3fb27SDimitry Andric "immediate must be a multiple of 4 in the range"); 163606c3fb27SDimitry Andric case Match_InvalidSImm11lsl1: 163706c3fb27SDimitry Andric return generateImmOutOfRangeError( 163806c3fb27SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2, 163906c3fb27SDimitry Andric "immediate must be a multiple of 2 in the range"); 164081ad6265SDimitry Andric case Match_InvalidSImm12: 164181ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11), 164281ad6265SDimitry Andric /*Upper=*/(1 << 11) - 1); 1643bdd1243dSDimitry Andric case Match_InvalidSImm12addlike: 1644bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1645bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1646bdd1243dSDimitry Andric /*Upper=*/(1 << 11) - 1, 1647bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer " 1648bdd1243dSDimitry Andric "in the range"); 1649bdd1243dSDimitry Andric case Match_InvalidSImm12lu52id: 1650bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1651bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1652bdd1243dSDimitry Andric /*Upper=*/(1 << 11) - 1, 1653bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %pc64_hi12) or an " 1654bdd1243dSDimitry Andric "integer in the range"); 165506c3fb27SDimitry Andric case Match_InvalidSImm13: 165606c3fb27SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12), 165706c3fb27SDimitry Andric /*Upper=*/(1 << 12) - 1); 165881ad6265SDimitry Andric case Match_InvalidSImm14lsl2: 165981ad6265SDimitry Andric return generateImmOutOfRangeError( 166081ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4, 166181ad6265SDimitry Andric "immediate must be a multiple of 4 in the range"); 166281ad6265SDimitry Andric case Match_InvalidSImm16: 166381ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15), 166481ad6265SDimitry Andric /*Upper=*/(1 << 15) - 1); 166581ad6265SDimitry Andric case Match_InvalidSImm16lsl2: 166681ad6265SDimitry Andric return generateImmOutOfRangeError( 166781ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4, 1668bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %b16) or an integer " 1669bdd1243dSDimitry Andric "in the range"); 167081ad6265SDimitry Andric case Match_InvalidSImm20: 167181ad6265SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19), 167281ad6265SDimitry Andric /*Upper=*/(1 << 19) - 1); 1673bdd1243dSDimitry Andric case Match_InvalidSImm20lu12iw: 1674bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1675bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1676bdd1243dSDimitry Andric /*Upper=*/(1 << 19) - 1, 1677bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer " 1678bdd1243dSDimitry Andric "in the range"); 1679bdd1243dSDimitry Andric case Match_InvalidSImm20lu32id: 1680bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1681bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1682bdd1243dSDimitry Andric /*Upper=*/(1 << 19) - 1, 1683bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %abs64_lo20) or an " 1684bdd1243dSDimitry Andric "integer in the range"); 1685bdd1243dSDimitry Andric case Match_InvalidSImm20pcalau12i: 1686bdd1243dSDimitry Andric return generateImmOutOfRangeError( 1687bdd1243dSDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1688bdd1243dSDimitry Andric /*Upper=*/(1 << 19) - 1, 1689bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer " 1690bdd1243dSDimitry Andric "in the range"); 16911db9f3b2SDimitry Andric case Match_InvalidSImm20pcaddu18i: 16921db9f3b2SDimitry Andric return generateImmOutOfRangeError( 16931db9f3b2SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 16941db9f3b2SDimitry Andric /*Upper=*/(1 << 19) - 1, 16951db9f3b2SDimitry Andric "operand must be a symbol with modifier (e.g. %call36) or an integer " 16961db9f3b2SDimitry Andric "in the range"); 1697*52418fc2SDimitry Andric case Match_InvalidSImm20pcaddi: 1698*52418fc2SDimitry Andric return generateImmOutOfRangeError( 1699*52418fc2SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1700*52418fc2SDimitry Andric /*Upper=*/(1 << 19) - 1, 1701*52418fc2SDimitry Andric "operand must be a symbol with modifier (e.g. %pcrel_20) or an integer " 1702*52418fc2SDimitry Andric "in the range"); 170381ad6265SDimitry Andric case Match_InvalidSImm21lsl2: 170481ad6265SDimitry Andric return generateImmOutOfRangeError( 170581ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4, 1706bdd1243dSDimitry Andric "operand must be a symbol with modifier (e.g. %b21) or an integer " 1707bdd1243dSDimitry Andric "in the range"); 1708bdd1243dSDimitry Andric case Match_InvalidSImm26Operand: 170981ad6265SDimitry Andric return generateImmOutOfRangeError( 171081ad6265SDimitry Andric Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4, 1711bdd1243dSDimitry Andric "operand must be a bare symbol name or an immediate must be a multiple " 1712bdd1243dSDimitry Andric "of 4 in the range"); 1713bdd1243dSDimitry Andric case Match_InvalidImm32: { 1714bdd1243dSDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1715bdd1243dSDimitry Andric return Error(ErrorLoc, "operand must be a 32 bit immediate"); 1716bdd1243dSDimitry Andric } 17170fca6ea1SDimitry Andric case Match_InvalidImm64: { 17180fca6ea1SDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 17190fca6ea1SDimitry Andric return Error(ErrorLoc, "operand must be a 64 bit immediate"); 17200fca6ea1SDimitry Andric } 1721bdd1243dSDimitry Andric case Match_InvalidBareSymbol: { 1722bdd1243dSDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1723bdd1243dSDimitry Andric return Error(ErrorLoc, "operand must be a bare symbol name"); 1724bdd1243dSDimitry Andric } 17250fca6ea1SDimitry Andric case Match_InvalidTPRelAddSymbol: { 17260fca6ea1SDimitry Andric SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 17270fca6ea1SDimitry Andric return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier"); 17280fca6ea1SDimitry Andric } 172981ad6265SDimitry Andric } 173081ad6265SDimitry Andric llvm_unreachable("Unknown match type detected!"); 173181ad6265SDimitry Andric } 173281ad6265SDimitry Andric 173381ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() { 173481ad6265SDimitry Andric RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target()); 173581ad6265SDimitry Andric RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target()); 173681ad6265SDimitry Andric } 1737