xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp (revision 52418fc2be8efa5172b90a3a9e617017173612c4)
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