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