xref: /freebsd/contrib/llvm-project/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
1 // LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "MCTargetDesc/LoongArchInstPrinter.h"
10 #include "MCTargetDesc/LoongArchMCExpr.h"
11 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
12 #include "MCTargetDesc/LoongArchMatInt.h"
13 #include "TargetInfo/LoongArchTargetInfo.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCInstBuilder.h"
16 #include "llvm/MC/MCInstrInfo.h"
17 #include "llvm/MC/MCParser/MCAsmLexer.h"
18 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
19 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCStreamer.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/MC/MCValue.h"
24 #include "llvm/MC/TargetRegistry.h"
25 #include "llvm/Support/Casting.h"
26 
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "loongarch-asm-parser"
30 
31 namespace {
32 class LoongArchAsmParser : public MCTargetAsmParser {
33   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
34   bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); }
35 
36   struct Inst {
37     unsigned Opc;
38     LoongArchMCExpr::VariantKind VK;
39     Inst(unsigned Opc,
40          LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None)
41         : Opc(Opc), VK(VK) {}
42   };
43   using InstSeq = SmallVector<Inst>;
44 
45   /// Parse a register as used in CFI directives.
46   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
47   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
48                                SMLoc &EndLoc) override;
49 
50   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
51                         SMLoc NameLoc, OperandVector &Operands) override;
52 
53   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
54                                OperandVector &Operands, MCStreamer &Out,
55                                uint64_t &ErrorInfo,
56                                bool MatchingInlineAsm) override;
57 
58   unsigned checkTargetMatchPredicate(MCInst &Inst) override;
59 
60   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
61                                       unsigned Kind) override;
62 
63   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
64                                   int64_t Lower, int64_t Upper,
65                                   const Twine &Msg);
66 
67   /// Helper for processing MC instructions that have been successfully matched
68   /// by MatchAndEmitInstruction.
69   bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
70                           MCStreamer &Out);
71 
72 // Auto-generated instruction matching functions.
73 #define GET_ASSEMBLER_HEADER
74 #include "LoongArchGenAsmMatcher.inc"
75 
76   ParseStatus parseRegister(OperandVector &Operands);
77   ParseStatus parseImmediate(OperandVector &Operands);
78   ParseStatus parseOperandWithModifier(OperandVector &Operands);
79   ParseStatus parseSImm26Operand(OperandVector &Operands);
80   ParseStatus parseAtomicMemOp(OperandVector &Operands);
81 
82   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
83 
84   // Helper to emit the sequence of instructions generated by the
85   // "emitLoadAddress*" functions.
86   void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
87                      const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,
88                      SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);
89 
90   // Helper to emit pseudo instruction "la.abs $rd, sym".
91   void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
92 
93   // Helper to emit pseudo instruction "la.pcrel $rd, sym".
94   void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
95   // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".
96   void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
97 
98   // Helper to emit pseudo instruction "la.got $rd, sym".
99   void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
100   // Helper to emit pseudo instruction "la.got $rd, $rj, sym".
101   void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
102 
103   // Helper to emit pseudo instruction "la.tls.le $rd, sym".
104   void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
105 
106   // Helper to emit pseudo instruction "la.tls.ie $rd, sym".
107   void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
108   // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".
109   void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
110 
111   // Helper to emit pseudo instruction "la.tls.ld $rd, sym".
112   void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
113   // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".
114   void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
115 
116   // Helper to emit pseudo instruction "la.tls.gd $rd, sym".
117   void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
118   // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
119   void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
120 
121   // Helper to emit pseudo instruction "li.w/d $rd, $imm".
122   void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
123 
124   // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
125   void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
126                       bool IsTailCall);
127 
128 public:
129   enum LoongArchMatchResultTy {
130     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
131     Match_RequiresMsbNotLessThanLsb,
132     Match_RequiresOpnd2NotR0R1,
133     Match_RequiresAMORdDifferRkRj,
134     Match_RequiresLAORdDifferRj,
135 #define GET_OPERAND_DIAGNOSTIC_TYPES
136 #include "LoongArchGenAsmMatcher.inc"
137 #undef GET_OPERAND_DIAGNOSTIC_TYPES
138   };
139 
140   static bool classifySymbolRef(const MCExpr *Expr,
141                                 LoongArchMCExpr::VariantKind &Kind);
142 
143   LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
144                      const MCInstrInfo &MII, const MCTargetOptions &Options)
145       : MCTargetAsmParser(Options, STI, MII) {
146     Parser.addAliasForDirective(".half", ".2byte");
147     Parser.addAliasForDirective(".hword", ".2byte");
148     Parser.addAliasForDirective(".word", ".4byte");
149     Parser.addAliasForDirective(".dword", ".8byte");
150 
151     // Initialize the set of available features.
152     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
153   }
154 };
155 
156 // Instances of this class represent a parsed LoongArch machine instruction.
157 class LoongArchOperand : public MCParsedAsmOperand {
158   enum class KindTy {
159     Token,
160     Register,
161     Immediate,
162   } Kind;
163 
164   struct RegOp {
165     MCRegister RegNum;
166   };
167 
168   struct ImmOp {
169     const MCExpr *Val;
170   };
171 
172   SMLoc StartLoc, EndLoc;
173   union {
174     StringRef Tok;
175     struct RegOp Reg;
176     struct ImmOp Imm;
177   };
178 
179 public:
180   LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
181 
182   bool isToken() const override { return Kind == KindTy::Token; }
183   bool isReg() const override { return Kind == KindTy::Register; }
184   bool isImm() const override { return Kind == KindTy::Immediate; }
185   bool isMem() const override { return false; }
186   void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }
187   bool isGPR() const {
188     return Kind == KindTy::Register &&
189            LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(
190                Reg.RegNum);
191   }
192 
193   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
194                                   LoongArchMCExpr::VariantKind &VK) {
195     if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) {
196       VK = LE->getKind();
197       return false;
198     }
199 
200     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
201       Imm = CE->getValue();
202       return true;
203     }
204 
205     return false;
206   }
207 
208   template <unsigned N, int P = 0> bool isUImm() const {
209     if (!isImm())
210       return false;
211 
212     int64_t Imm;
213     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
214     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
215     return IsConstantImm && isUInt<N>(Imm - P) &&
216            VK == LoongArchMCExpr::VK_LoongArch_None;
217   }
218 
219   template <unsigned N, unsigned S = 0> bool isSImm() const {
220     if (!isImm())
221       return false;
222 
223     int64_t Imm;
224     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
225     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
226     return IsConstantImm && isShiftedInt<N, S>(Imm) &&
227            VK == LoongArchMCExpr::VK_LoongArch_None;
228   }
229 
230   bool isBareSymbol() const {
231     int64_t Imm;
232     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
233     // Must be of 'immediate' type but not a constant.
234     if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
235       return false;
236     return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
237            VK == LoongArchMCExpr::VK_LoongArch_None;
238   }
239 
240   bool isUImm1() const { return isUImm<1>(); }
241   bool isUImm2() const { return isUImm<2>(); }
242   bool isUImm2plus1() const { return isUImm<2, 1>(); }
243   bool isUImm3() const { return isUImm<3>(); }
244   bool isUImm4() const { return isUImm<4>(); }
245   bool isSImm5() const { return isSImm<5>(); }
246   bool isUImm5() const { return isUImm<5>(); }
247   bool isUImm6() const { return isUImm<6>(); }
248   bool isUImm7() const { return isUImm<7>(); }
249   bool isSImm8() const { return isSImm<8>(); }
250   bool isSImm8lsl1() const { return isSImm<8, 1>(); }
251   bool isSImm8lsl2() const { return isSImm<8, 2>(); }
252   bool isSImm8lsl3() const { return isSImm<8, 3>(); }
253   bool isUImm8() const { return isUImm<8>(); }
254   bool isSImm9lsl3() const { return isSImm<9, 3>(); }
255   bool isSImm10() const { return isSImm<10>(); }
256   bool isSImm10lsl2() const { return isSImm<10, 2>(); }
257   bool isSImm11lsl1() const { return isSImm<11, 1>(); }
258   bool isSImm12() const { return isSImm<12>(); }
259 
260   bool isSImm12addlike() const {
261     if (!isImm())
262       return false;
263 
264     int64_t Imm;
265     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
266     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
267     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
268                        VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
269                        VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
270                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
271     return IsConstantImm
272                ? isInt<12>(Imm) && IsValidKind
273                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
274                      IsValidKind;
275   }
276 
277   bool isSImm12lu52id() const {
278     if (!isImm())
279       return false;
280 
281     int64_t Imm;
282     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
283     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
284     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
285                        VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 ||
286                        VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 ||
287                        VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 ||
288                        VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 ||
289                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 ||
290                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 ||
291                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12;
292     return IsConstantImm
293                ? isInt<12>(Imm) && IsValidKind
294                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
295                      IsValidKind;
296   }
297 
298   bool isUImm12() const { return isUImm<12>(); }
299 
300   bool isUImm12ori() const {
301     if (!isImm())
302       return false;
303 
304     int64_t Imm;
305     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
306     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
307     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
308                        VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 ||
309                        VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
310                        VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 ||
311                        VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
312                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 ||
313                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 ||
314                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
315     return IsConstantImm
316                ? isUInt<12>(Imm) && IsValidKind
317                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
318                      IsValidKind;
319   }
320 
321   bool isSImm13() const { return isSImm<13>(); }
322   bool isUImm14() const { return isUImm<14>(); }
323   bool isUImm15() const { return isUImm<15>(); }
324 
325   bool isSImm14lsl2() const { return isSImm<14, 2>(); }
326   bool isSImm16() const { return isSImm<16>(); }
327 
328   bool isSImm16lsl2() const {
329     if (!isImm())
330       return false;
331 
332     int64_t Imm;
333     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
334     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
335     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
336                        VK == LoongArchMCExpr::VK_LoongArch_B16 ||
337                        VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
338     return IsConstantImm
339                ? isShiftedInt<16, 2>(Imm) && IsValidKind
340                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
341                      IsValidKind;
342   }
343 
344   bool isSImm20() const { return isSImm<20>(); }
345 
346   bool isSImm20pcalau12i() const {
347     if (!isImm())
348       return false;
349 
350     int64_t Imm;
351     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
352     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
353     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
354                        VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 ||
355                        VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 ||
356                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 ||
357                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 ||
358                        VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20;
359     return IsConstantImm
360                ? isInt<20>(Imm) && IsValidKind
361                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
362                      IsValidKind;
363   }
364 
365   bool isSImm20lu12iw() const {
366     if (!isImm())
367       return false;
368 
369     int64_t Imm;
370     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
371     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
372     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
373                        VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 ||
374                        VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 ||
375                        VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 ||
376                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 ||
377                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 ||
378                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20;
379     return IsConstantImm
380                ? isInt<20>(Imm) && IsValidKind
381                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
382                      IsValidKind;
383   }
384 
385   bool isSImm20lu32id() const {
386     if (!isImm())
387       return false;
388 
389     int64_t Imm;
390     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
391     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
392     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
393                        VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 ||
394                        VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 ||
395                        VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 ||
396                        VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 ||
397                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 ||
398                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 ||
399                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20;
400 
401     return IsConstantImm
402                ? isInt<20>(Imm) && IsValidKind
403                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
404                      IsValidKind;
405   }
406 
407   bool isSImm20pcaddu18i() const {
408     if (!isImm())
409       return false;
410 
411     int64_t Imm;
412     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
413     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
414     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
415                        VK == LoongArchMCExpr::VK_LoongArch_CALL36;
416 
417     return IsConstantImm
418                ? isInt<20>(Imm) && IsValidKind
419                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
420                      IsValidKind;
421   }
422 
423   bool isSImm21lsl2() const {
424     if (!isImm())
425       return false;
426 
427     int64_t Imm;
428     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
429     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
430     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
431                        VK == LoongArchMCExpr::VK_LoongArch_B21;
432     return IsConstantImm
433                ? isShiftedInt<21, 2>(Imm) && IsValidKind
434                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
435                      IsValidKind;
436   }
437 
438   bool isSImm26Operand() const {
439     if (!isImm())
440       return false;
441 
442     int64_t Imm;
443     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
444     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
445     bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
446                        VK == LoongArchMCExpr::VK_LoongArch_CALL ||
447                        VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT ||
448                        VK == LoongArchMCExpr::VK_LoongArch_B26;
449     return IsConstantImm
450                ? isShiftedInt<26, 2>(Imm) && IsValidKind
451                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
452                      IsValidKind;
453   }
454 
455   bool isImm32() const { return isSImm<32>() || isUImm<32>(); }
456 
457   /// Gets location of the first token of this operand.
458   SMLoc getStartLoc() const override { return StartLoc; }
459   /// Gets location of the last token of this operand.
460   SMLoc getEndLoc() const override { return EndLoc; }
461 
462   unsigned getReg() const override {
463     assert(Kind == KindTy::Register && "Invalid type access!");
464     return Reg.RegNum.id();
465   }
466 
467   const MCExpr *getImm() const {
468     assert(Kind == KindTy::Immediate && "Invalid type access!");
469     return Imm.Val;
470   }
471 
472   StringRef getToken() const {
473     assert(Kind == KindTy::Token && "Invalid type access!");
474     return Tok;
475   }
476 
477   void print(raw_ostream &OS) const override {
478     auto RegName = [](MCRegister Reg) {
479       if (Reg)
480         return LoongArchInstPrinter::getRegisterName(Reg);
481       else
482         return "noreg";
483     };
484 
485     switch (Kind) {
486     case KindTy::Immediate:
487       OS << *getImm();
488       break;
489     case KindTy::Register:
490       OS << "<register " << RegName(getReg()) << ">";
491       break;
492     case KindTy::Token:
493       OS << "'" << getToken() << "'";
494       break;
495     }
496   }
497 
498   static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) {
499     auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);
500     Op->Tok = Str;
501     Op->StartLoc = S;
502     Op->EndLoc = S;
503     return Op;
504   }
505 
506   static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S,
507                                                      SMLoc E) {
508     auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);
509     Op->Reg.RegNum = RegNo;
510     Op->StartLoc = S;
511     Op->EndLoc = E;
512     return Op;
513   }
514 
515   static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S,
516                                                      SMLoc E) {
517     auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);
518     Op->Imm.Val = Val;
519     Op->StartLoc = S;
520     Op->EndLoc = E;
521     return Op;
522   }
523 
524   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
525     if (auto CE = dyn_cast<MCConstantExpr>(Expr))
526       Inst.addOperand(MCOperand::createImm(CE->getValue()));
527     else
528       Inst.addOperand(MCOperand::createExpr(Expr));
529   }
530 
531   // Used by the TableGen Code.
532   void addRegOperands(MCInst &Inst, unsigned N) const {
533     assert(N == 1 && "Invalid number of operands!");
534     Inst.addOperand(MCOperand::createReg(getReg()));
535   }
536   void addImmOperands(MCInst &Inst, unsigned N) const {
537     assert(N == 1 && "Invalid number of operands!");
538     addExpr(Inst, getImm());
539   }
540 };
541 } // end namespace
542 
543 #define GET_REGISTER_MATCHER
544 #define GET_SUBTARGET_FEATURE_NAME
545 #define GET_MATCHER_IMPLEMENTATION
546 #define GET_MNEMONIC_SPELL_CHECKER
547 #include "LoongArchGenAsmMatcher.inc"
548 
549 static MCRegister convertFPR32ToFPR64(MCRegister Reg) {
550   assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
551   return Reg - LoongArch::F0 + LoongArch::F0_64;
552 }
553 
554 // Attempts to match Name as a register (either using the default name or
555 // alternative ABI names), setting RegNo to the matching register. Upon
556 // failure, returns true and sets RegNo to 0.
557 static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
558   RegNo = MatchRegisterName(Name);
559   // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
560   // match always matches the 32-bit variant, and not the 64-bit one.
561   assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
562   // The default FPR register class is based on the tablegen enum ordering.
563   static_assert(LoongArch::F0 < LoongArch::F0_64,
564                 "FPR matching must be updated");
565   if (RegNo == LoongArch::NoRegister)
566     RegNo = MatchRegisterAltName(Name);
567 
568   return RegNo == LoongArch::NoRegister;
569 }
570 
571 bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
572                                        SMLoc &EndLoc) {
573   return Error(getLoc(), "invalid register number");
574 }
575 
576 ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg,
577                                                  SMLoc &StartLoc,
578                                                  SMLoc &EndLoc) {
579   llvm_unreachable("Unimplemented function.");
580 }
581 
582 bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,
583                                            LoongArchMCExpr::VariantKind &Kind) {
584   Kind = LoongArchMCExpr::VK_LoongArch_None;
585 
586   if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {
587     Kind = RE->getKind();
588     Expr = RE->getSubExpr();
589   }
590 
591   MCValue Res;
592   if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr))
593     return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None;
594   return false;
595 }
596 
597 ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {
598   if (!parseOptionalToken(AsmToken::Dollar))
599     return ParseStatus::NoMatch;
600   if (getLexer().getKind() != AsmToken::Identifier)
601     return ParseStatus::NoMatch;
602 
603   StringRef Name = getLexer().getTok().getIdentifier();
604   MCRegister RegNo;
605   matchRegisterNameHelper(RegNo, Name);
606   if (RegNo == LoongArch::NoRegister)
607     return ParseStatus::NoMatch;
608 
609   SMLoc S = getLoc();
610   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
611   getLexer().Lex();
612   Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));
613 
614   return ParseStatus::Success;
615 }
616 
617 ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {
618   SMLoc S = getLoc();
619   SMLoc E;
620   const MCExpr *Res;
621 
622   switch (getLexer().getKind()) {
623   default:
624     return ParseStatus::NoMatch;
625   case AsmToken::LParen:
626   case AsmToken::Dot:
627   case AsmToken::Minus:
628   case AsmToken::Plus:
629   case AsmToken::Exclaim:
630   case AsmToken::Tilde:
631   case AsmToken::Integer:
632   case AsmToken::String:
633   case AsmToken::Identifier:
634     if (getParser().parseExpression(Res, E))
635       return ParseStatus::Failure;
636     break;
637   case AsmToken::Percent:
638     return parseOperandWithModifier(Operands);
639   }
640 
641   Operands.push_back(LoongArchOperand::createImm(Res, S, E));
642   return ParseStatus::Success;
643 }
644 
645 ParseStatus
646 LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {
647   SMLoc S = getLoc();
648   SMLoc E;
649 
650   if (getLexer().getKind() != AsmToken::Percent)
651     return Error(getLoc(), "expected '%' for operand modifier");
652 
653   getParser().Lex(); // Eat '%'
654 
655   if (getLexer().getKind() != AsmToken::Identifier)
656     return Error(getLoc(), "expected valid identifier for operand modifier");
657   StringRef Identifier = getParser().getTok().getIdentifier();
658   LoongArchMCExpr::VariantKind VK =
659       LoongArchMCExpr::getVariantKindForName(Identifier);
660   if (VK == LoongArchMCExpr::VK_LoongArch_Invalid)
661     return Error(getLoc(), "unrecognized operand modifier");
662 
663   getParser().Lex(); // Eat the identifier
664   if (getLexer().getKind() != AsmToken::LParen)
665     return Error(getLoc(), "expected '('");
666   getParser().Lex(); // Eat '('
667 
668   const MCExpr *SubExpr;
669   if (getParser().parseParenExpression(SubExpr, E))
670     return ParseStatus::Failure;
671 
672   const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());
673   Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));
674   return ParseStatus::Success;
675 }
676 
677 ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {
678   SMLoc S = getLoc();
679   const MCExpr *Res;
680 
681   if (getLexer().getKind() == AsmToken::Percent)
682     return parseOperandWithModifier(Operands);
683 
684   if (getLexer().getKind() != AsmToken::Identifier)
685     return ParseStatus::NoMatch;
686 
687   StringRef Identifier;
688   if (getParser().parseIdentifier(Identifier))
689     return ParseStatus::Failure;
690 
691   SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
692 
693   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
694   Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
695   Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL,
696                                 getContext());
697   Operands.push_back(LoongArchOperand::createImm(Res, S, E));
698   return ParseStatus::Success;
699 }
700 
701 ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {
702   // Parse "$r*".
703   if (!parseRegister(Operands).isSuccess())
704     return ParseStatus::NoMatch;
705 
706   // If there is a next operand and it is 0, ignore it. Otherwise print a
707   // diagnostic message.
708   if (parseOptionalToken(AsmToken::Comma)) {
709     int64_t ImmVal;
710     SMLoc ImmStart = getLoc();
711     if (getParser().parseIntToken(ImmVal, "expected optional integer offset"))
712       return ParseStatus::Failure;
713     if (ImmVal)
714       return Error(ImmStart, "optional integer offset must be 0");
715   }
716 
717   return ParseStatus::Success;
718 }
719 /// Looks at a token type and creates the relevant operand from this
720 /// information, adding to Operands. Return true upon an error.
721 bool LoongArchAsmParser::parseOperand(OperandVector &Operands,
722                                       StringRef Mnemonic) {
723   // Check if the current operand has a custom associated parser, if so, try to
724   // custom parse the operand, or fallback to the general approach.
725   ParseStatus Result =
726       MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
727   if (Result.isSuccess())
728     return false;
729   if (Result.isFailure())
730     return true;
731 
732   if (parseRegister(Operands).isSuccess() ||
733       parseImmediate(Operands).isSuccess())
734     return false;
735 
736   // Finally we have exhausted all options and must declare defeat.
737   return Error(getLoc(), "unknown operand");
738 }
739 
740 bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info,
741                                           StringRef Name, SMLoc NameLoc,
742                                           OperandVector &Operands) {
743   // First operand in MCInst is instruction mnemonic.
744   Operands.push_back(LoongArchOperand::createToken(Name, NameLoc));
745 
746   // If there are no more operands, then finish.
747   if (parseOptionalToken(AsmToken::EndOfStatement))
748     return false;
749 
750   // Parse first operand.
751   if (parseOperand(Operands, Name))
752     return true;
753 
754   // Parse until end of statement, consuming commas between operands.
755   while (parseOptionalToken(AsmToken::Comma))
756     if (parseOperand(Operands, Name))
757       return true;
758 
759   // Parse end of statement and return successfully.
760   if (parseOptionalToken(AsmToken::EndOfStatement))
761     return false;
762 
763   SMLoc Loc = getLexer().getLoc();
764   getParser().eatToEndOfStatement();
765   return Error(Loc, "unexpected token");
766 }
767 
768 void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
769                                        const MCExpr *Symbol,
770                                        SmallVectorImpl<Inst> &Insts,
771                                        SMLoc IDLoc, MCStreamer &Out,
772                                        bool RelaxHint) {
773   MCContext &Ctx = getContext();
774   for (LoongArchAsmParser::Inst &Inst : Insts) {
775     unsigned Opc = Inst.Opc;
776     LoongArchMCExpr::VariantKind VK = Inst.VK;
777     const LoongArchMCExpr *LE =
778         LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);
779     switch (Opc) {
780     default:
781       llvm_unreachable("unexpected opcode");
782     case LoongArch::PCALAU12I:
783     case LoongArch::LU12I_W:
784       Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),
785                           getSTI());
786       break;
787     case LoongArch::ORI:
788     case LoongArch::ADDI_W:
789     case LoongArch::LD_W:
790     case LoongArch::LD_D: {
791       if (VK == LoongArchMCExpr::VK_LoongArch_None) {
792         Out.emitInstruction(
793             MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),
794             getSTI());
795         continue;
796       }
797       Out.emitInstruction(
798           MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
799           getSTI());
800       break;
801     }
802     case LoongArch::LU32I_D:
803       Out.emitInstruction(MCInstBuilder(Opc)
804                               .addReg(DestReg == TmpReg ? DestReg : TmpReg)
805                               .addReg(DestReg == TmpReg ? DestReg : TmpReg)
806                               .addExpr(LE),
807                           getSTI());
808       break;
809     case LoongArch::LU52I_D:
810       Out.emitInstruction(
811           MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE),
812           getSTI());
813       break;
814     case LoongArch::ADDI_D:
815       Out.emitInstruction(
816           MCInstBuilder(Opc)
817               .addReg(TmpReg)
818               .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)
819               .addExpr(LE),
820           getSTI());
821       break;
822     case LoongArch::ADD_D:
823     case LoongArch::LDX_D:
824       Out.emitInstruction(
825           MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),
826           getSTI());
827       break;
828     }
829   }
830 }
831 
832 void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,
833                                             MCStreamer &Out) {
834   // la.abs $rd, sym
835   // expands to:
836   //   lu12i.w $rd, %abs_hi20(sym)
837   //   ori     $rd, $rd, %abs_lo12(sym)
838   //
839   // for 64bit appends:
840   //   lu32i.d $rd, %abs64_lo20(sym)
841   //   lu52i.d $rd, $rd, %abs64_hi12(sym)
842   MCRegister DestReg = Inst.getOperand(0).getReg();
843   const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS
844                              ? Inst.getOperand(1).getExpr()
845                              : Inst.getOperand(2).getExpr();
846   InstSeq Insts;
847 
848   Insts.push_back(LoongArchAsmParser::Inst(
849       LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20));
850   Insts.push_back(LoongArchAsmParser::Inst(
851       LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12));
852 
853   if (is64Bit()) {
854     Insts.push_back(LoongArchAsmParser::Inst(
855         LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20));
856     Insts.push_back(LoongArchAsmParser::Inst(
857         LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12));
858   }
859 
860   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
861 }
862 
863 void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
864                                               MCStreamer &Out) {
865   // la.pcrel $rd, sym
866   // expands to:
867   //   pcalau12i $rd, %pc_hi20(sym)
868   //   addi.w/d  $rd, rd, %pc_lo12(sym)
869   MCRegister DestReg = Inst.getOperand(0).getReg();
870   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
871   InstSeq Insts;
872   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
873 
874   Insts.push_back(LoongArchAsmParser::Inst(
875       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
876   Insts.push_back(
877       LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
878 
879   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
880 }
881 
882 void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
883                                                    MCStreamer &Out) {
884   // la.pcrel $rd, $rj, sym
885   // expands to:
886   //   pcalau12i $rd, %pc_hi20(sym)
887   //   addi.d    $rj, $r0, %pc_lo12(sym)
888   //   lu32i.d   $rj, %pc64_lo20(sym)
889   //   lu52i.d   $rj, $rj, %pc64_hi12(sym)
890   //   add.d     $rd, $rd, $rj
891   MCRegister DestReg = Inst.getOperand(0).getReg();
892   MCRegister TmpReg = Inst.getOperand(1).getReg();
893   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
894   InstSeq Insts;
895 
896   Insts.push_back(LoongArchAsmParser::Inst(
897       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
898   Insts.push_back(LoongArchAsmParser::Inst(
899       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
900   Insts.push_back(LoongArchAsmParser::Inst(
901       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20));
902   Insts.push_back(LoongArchAsmParser::Inst(
903       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12));
904   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
905 
906   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
907 }
908 
909 void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
910                                             MCStreamer &Out) {
911   // la.got $rd, sym
912   // expands to:
913   //   pcalau12i $rd, %got_pc_hi20(sym)
914   //   ld.w/d    $rd, $rd, %got_pc_lo12(sym)
915   MCRegister DestReg = Inst.getOperand(0).getReg();
916   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
917   InstSeq Insts;
918   unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
919 
920   Insts.push_back(LoongArchAsmParser::Inst(
921       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
922   Insts.push_back(
923       LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
924 
925   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
926 }
927 
928 void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
929                                                  MCStreamer &Out) {
930   // la.got $rd, $rj, sym
931   // expands to:
932   //   pcalau12i $rd, %got_pc_hi20(sym)
933   //   addi.d    $rj, $r0, %got_pc_lo12(sym)
934   //   lu32i.d   $rj, %got64_pc_lo20(sym)
935   //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)
936   //   ldx.d     $rd, $rd, $rj
937   MCRegister DestReg = Inst.getOperand(0).getReg();
938   MCRegister TmpReg = Inst.getOperand(1).getReg();
939   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
940   InstSeq Insts;
941 
942   Insts.push_back(LoongArchAsmParser::Inst(
943       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
944   Insts.push_back(LoongArchAsmParser::Inst(
945       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
946   Insts.push_back(LoongArchAsmParser::Inst(
947       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
948   Insts.push_back(LoongArchAsmParser::Inst(
949       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
950   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
951 
952   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
953 }
954 
955 void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,
956                                               MCStreamer &Out) {
957   // la.tls.le $rd, sym
958   // expands to:
959   //   lu12i.w $rd, %le_hi20(sym)
960   //   ori     $rd, $rd, %le_lo12(sym)
961   MCRegister DestReg = Inst.getOperand(0).getReg();
962   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
963   InstSeq Insts;
964 
965   Insts.push_back(LoongArchAsmParser::Inst(
966       LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20));
967   Insts.push_back(LoongArchAsmParser::Inst(
968       LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12));
969 
970   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
971 }
972 
973 void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
974                                               MCStreamer &Out) {
975   // la.tls.ie $rd, sym
976   // expands to:
977   //   pcalau12i $rd, %ie_pc_hi20(sym)
978   //   ld.w/d    $rd, $rd, %ie_pc_lo12(sym)
979   MCRegister DestReg = Inst.getOperand(0).getReg();
980   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
981   InstSeq Insts;
982   unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
983 
984   Insts.push_back(LoongArchAsmParser::Inst(
985       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
986   Insts.push_back(LoongArchAsmParser::Inst(
987       LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));
988 
989   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
990 }
991 
992 void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
993                                                    MCStreamer &Out) {
994   // la.tls.ie $rd, $rj, sym
995   // expands to:
996   //   pcalau12i $rd, %ie_pc_hi20(sym)
997   //   addi.d    $rj, $r0, %ie_pc_lo12(sym)
998   //   lu32i.d   $rj, %ie64_pc_lo20(sym)
999   //   lu52i.d   $rj, $rj, %ie64_pc_hi12(sym)
1000   //   ldx.d     $rd, $rd, $rj
1001   MCRegister DestReg = Inst.getOperand(0).getReg();
1002   MCRegister TmpReg = Inst.getOperand(1).getReg();
1003   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1004   InstSeq Insts;
1005 
1006   Insts.push_back(LoongArchAsmParser::Inst(
1007       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
1008   Insts.push_back(LoongArchAsmParser::Inst(
1009       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12));
1010   Insts.push_back(LoongArchAsmParser::Inst(
1011       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20));
1012   Insts.push_back(LoongArchAsmParser::Inst(
1013       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12));
1014   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1015 
1016   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1017 }
1018 
1019 void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
1020                                               MCStreamer &Out) {
1021   // la.tls.ld $rd, sym
1022   // expands to:
1023   //   pcalau12i $rd, %ld_pc_hi20(sym)
1024   //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)
1025   MCRegister DestReg = Inst.getOperand(0).getReg();
1026   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1027   InstSeq Insts;
1028   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1029 
1030   Insts.push_back(LoongArchAsmParser::Inst(
1031       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1032   Insts.push_back(LoongArchAsmParser::Inst(
1033       ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1034 
1035   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1036 }
1037 
1038 void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,
1039                                                    MCStreamer &Out) {
1040   // la.tls.ld $rd, $rj, sym
1041   // expands to:
1042   //   pcalau12i $rd, %ld_pc_hi20(sym)
1043   //   addi.d    $rj, $r0, %got_pc_lo12(sym)
1044   //   lu32i.d   $rj, %got64_pc_lo20(sym)
1045   //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)
1046   //   add.d     $rd, $rd, $rj
1047   MCRegister DestReg = Inst.getOperand(0).getReg();
1048   MCRegister TmpReg = Inst.getOperand(1).getReg();
1049   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1050   InstSeq Insts;
1051 
1052   Insts.push_back(LoongArchAsmParser::Inst(
1053       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1054   Insts.push_back(LoongArchAsmParser::Inst(
1055       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1056   Insts.push_back(LoongArchAsmParser::Inst(
1057       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1058   Insts.push_back(LoongArchAsmParser::Inst(
1059       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1060   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1061 
1062   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1063 }
1064 
1065 void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
1066                                               MCStreamer &Out) {
1067   // la.tls.gd $rd, sym
1068   // expands to:
1069   //   pcalau12i $rd, %gd_pc_hi20(sym)
1070   //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)
1071   MCRegister DestReg = Inst.getOperand(0).getReg();
1072   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1073   InstSeq Insts;
1074   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1075 
1076   Insts.push_back(LoongArchAsmParser::Inst(
1077       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1078   Insts.push_back(LoongArchAsmParser::Inst(
1079       ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1080 
1081   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1082 }
1083 
1084 void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
1085                                                    MCStreamer &Out) {
1086   // la.tls.gd $rd, $rj, sym
1087   // expands to:
1088   //   pcalau12i $rd, %gd_pc_hi20(sym)
1089   //   addi.d    $rj, $r0, %got_pc_lo12(sym)
1090   //   lu32i.d   $rj, %got64_pc_lo20(sym)
1091   //   lu52i.d   $rj, $rj, %got64_pc_hi12(sym)
1092   //   add.d     $rd, $rd, $rj
1093   MCRegister DestReg = Inst.getOperand(0).getReg();
1094   MCRegister TmpReg = Inst.getOperand(1).getReg();
1095   const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1096   InstSeq Insts;
1097 
1098   Insts.push_back(LoongArchAsmParser::Inst(
1099       LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1100   Insts.push_back(LoongArchAsmParser::Inst(
1101       LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1102   Insts.push_back(LoongArchAsmParser::Inst(
1103       LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1104   Insts.push_back(LoongArchAsmParser::Inst(
1105       LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1106   Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1107 
1108   emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1109 }
1110 
1111 void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
1112                                      MCStreamer &Out) {
1113   MCRegister DestReg = Inst.getOperand(0).getReg();
1114   int64_t Imm = Inst.getOperand(1).getImm();
1115   MCRegister SrcReg = LoongArch::R0;
1116 
1117   if (Inst.getOpcode() == LoongArch::PseudoLI_W)
1118     Imm = SignExtend64<32>(Imm);
1119 
1120   for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) {
1121     unsigned Opc = Inst.Opc;
1122     if (Opc == LoongArch::LU12I_W)
1123       Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm),
1124                           getSTI());
1125     else
1126       Out.emitInstruction(
1127           MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm),
1128           getSTI());
1129     SrcReg = DestReg;
1130   }
1131 }
1132 
1133 void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
1134                                         MCStreamer &Out, bool IsTailCall) {
1135   // call36 sym
1136   // expands to:
1137   //   pcaddu18i $ra, %call36(sym)
1138   //   jirl      $ra, $ra, 0
1139   //
1140   // tail36 $rj, sym
1141   // expands to:
1142   //   pcaddu18i $rj, %call36(sym)
1143   //   jirl      $r0, $rj, 0
1144   unsigned ScratchReg =
1145       IsTailCall ? Inst.getOperand(0).getReg() : (unsigned)LoongArch::R1;
1146   const MCExpr *Sym =
1147       IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
1148   const LoongArchMCExpr *LE = LoongArchMCExpr::create(
1149       Sym, llvm::LoongArchMCExpr::VK_LoongArch_CALL36, getContext());
1150 
1151   Out.emitInstruction(
1152       MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),
1153       getSTI());
1154   Out.emitInstruction(
1155       MCInstBuilder(LoongArch::JIRL)
1156           .addReg(IsTailCall ? (unsigned)LoongArch::R0 : ScratchReg)
1157           .addReg(ScratchReg)
1158           .addImm(0),
1159       getSTI());
1160 }
1161 
1162 bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1163                                             OperandVector &Operands,
1164                                             MCStreamer &Out) {
1165   Inst.setLoc(IDLoc);
1166   switch (Inst.getOpcode()) {
1167   default:
1168     break;
1169   case LoongArch::PseudoLA_ABS:
1170   case LoongArch::PseudoLA_ABS_LARGE:
1171     emitLoadAddressAbs(Inst, IDLoc, Out);
1172     return false;
1173   case LoongArch::PseudoLA_PCREL:
1174     emitLoadAddressPcrel(Inst, IDLoc, Out);
1175     return false;
1176   case LoongArch::PseudoLA_PCREL_LARGE:
1177     emitLoadAddressPcrelLarge(Inst, IDLoc, Out);
1178     return false;
1179   case LoongArch::PseudoLA_GOT:
1180     emitLoadAddressGot(Inst, IDLoc, Out);
1181     return false;
1182   case LoongArch::PseudoLA_GOT_LARGE:
1183     emitLoadAddressGotLarge(Inst, IDLoc, Out);
1184     return false;
1185   case LoongArch::PseudoLA_TLS_LE:
1186     emitLoadAddressTLSLE(Inst, IDLoc, Out);
1187     return false;
1188   case LoongArch::PseudoLA_TLS_IE:
1189     emitLoadAddressTLSIE(Inst, IDLoc, Out);
1190     return false;
1191   case LoongArch::PseudoLA_TLS_IE_LARGE:
1192     emitLoadAddressTLSIELarge(Inst, IDLoc, Out);
1193     return false;
1194   case LoongArch::PseudoLA_TLS_LD:
1195     emitLoadAddressTLSLD(Inst, IDLoc, Out);
1196     return false;
1197   case LoongArch::PseudoLA_TLS_LD_LARGE:
1198     emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);
1199     return false;
1200   case LoongArch::PseudoLA_TLS_GD:
1201     emitLoadAddressTLSGD(Inst, IDLoc, Out);
1202     return false;
1203   case LoongArch::PseudoLA_TLS_GD_LARGE:
1204     emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
1205     return false;
1206   case LoongArch::PseudoLI_W:
1207   case LoongArch::PseudoLI_D:
1208     emitLoadImm(Inst, IDLoc, Out);
1209     return false;
1210   case LoongArch::PseudoCALL36:
1211     emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
1212     return false;
1213   case LoongArch::PseudoTAIL36:
1214     emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
1215     return false;
1216   }
1217   Out.emitInstruction(Inst, getSTI());
1218   return false;
1219 }
1220 
1221 unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1222   unsigned Opc = Inst.getOpcode();
1223   switch (Opc) {
1224   default:
1225     if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) {
1226       unsigned Rd = Inst.getOperand(0).getReg();
1227       unsigned Rk = Inst.getOperand(1).getReg();
1228       unsigned Rj = Inst.getOperand(2).getReg();
1229       if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
1230         return Match_RequiresAMORdDifferRkRj;
1231     }
1232     break;
1233   case LoongArch::PseudoLA_PCREL_LARGE:
1234   case LoongArch::PseudoLA_GOT_LARGE:
1235   case LoongArch::PseudoLA_TLS_IE_LARGE:
1236   case LoongArch::PseudoLA_TLS_LD_LARGE:
1237   case LoongArch::PseudoLA_TLS_GD_LARGE: {
1238     unsigned Rd = Inst.getOperand(0).getReg();
1239     unsigned Rj = Inst.getOperand(1).getReg();
1240     if (Rd == Rj)
1241       return Match_RequiresLAORdDifferRj;
1242     break;
1243   }
1244   case LoongArch::CSRXCHG:
1245   case LoongArch::GCSRXCHG: {
1246     unsigned Rj = Inst.getOperand(2).getReg();
1247     if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
1248       return Match_RequiresOpnd2NotR0R1;
1249     return Match_Success;
1250   }
1251   case LoongArch::BSTRINS_W:
1252   case LoongArch::BSTRINS_D:
1253   case LoongArch::BSTRPICK_W:
1254   case LoongArch::BSTRPICK_D: {
1255     unsigned Opc = Inst.getOpcode();
1256     const signed Msb =
1257         (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1258             ? Inst.getOperand(3).getImm()
1259             : Inst.getOperand(2).getImm();
1260     const signed Lsb =
1261         (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1262             ? Inst.getOperand(4).getImm()
1263             : Inst.getOperand(3).getImm();
1264     if (Msb < Lsb)
1265       return Match_RequiresMsbNotLessThanLsb;
1266     return Match_Success;
1267   }
1268   }
1269 
1270   return Match_Success;
1271 }
1272 
1273 unsigned
1274 LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1275                                                unsigned Kind) {
1276   LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
1277   if (!Op.isReg())
1278     return Match_InvalidOperand;
1279 
1280   MCRegister Reg = Op.getReg();
1281   // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1282   // register from FPR32 to FPR64 if necessary.
1283   if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
1284       Kind == MCK_FPR64) {
1285     Op.setReg(convertFPR32ToFPR64(Reg));
1286     return Match_Success;
1287   }
1288 
1289   return Match_InvalidOperand;
1290 }
1291 
1292 bool LoongArchAsmParser::generateImmOutOfRangeError(
1293     OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1294     const Twine &Msg = "immediate must be an integer in the range") {
1295   SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1296   return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1297 }
1298 
1299 bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1300                                                  OperandVector &Operands,
1301                                                  MCStreamer &Out,
1302                                                  uint64_t &ErrorInfo,
1303                                                  bool MatchingInlineAsm) {
1304   MCInst Inst;
1305   FeatureBitset MissingFeatures;
1306 
1307   auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1308                                      MatchingInlineAsm);
1309   switch (Result) {
1310   default:
1311     break;
1312   case Match_Success:
1313     return processInstruction(Inst, IDLoc, Operands, Out);
1314   case Match_MissingFeature: {
1315     assert(MissingFeatures.any() && "Unknown missing features!");
1316     bool FirstFeature = true;
1317     std::string Msg = "instruction requires the following:";
1318     for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1319       if (MissingFeatures[i]) {
1320         Msg += FirstFeature ? " " : ", ";
1321         Msg += getSubtargetFeatureName(i);
1322         FirstFeature = false;
1323       }
1324     }
1325     return Error(IDLoc, Msg);
1326   }
1327   case Match_MnemonicFail: {
1328     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1329     std::string Suggestion = LoongArchMnemonicSpellCheck(
1330         ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0);
1331     return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1332   }
1333   case Match_InvalidOperand: {
1334     SMLoc ErrorLoc = IDLoc;
1335     if (ErrorInfo != ~0ULL) {
1336       if (ErrorInfo >= Operands.size())
1337         return Error(ErrorLoc, "too few operands for instruction");
1338 
1339       ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1340       if (ErrorLoc == SMLoc())
1341         ErrorLoc = IDLoc;
1342     }
1343     return Error(ErrorLoc, "invalid operand for instruction");
1344   }
1345   }
1346 
1347   // Handle the case when the error message is of specific type
1348   // other than the generic Match_InvalidOperand, and the
1349   // corresponding operand is missing.
1350   if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1351     SMLoc ErrorLoc = IDLoc;
1352     if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1353       return Error(ErrorLoc, "too few operands for instruction");
1354   }
1355 
1356   switch (Result) {
1357   default:
1358     break;
1359   case Match_RequiresMsbNotLessThanLsb: {
1360     SMLoc ErrorStart = Operands[3]->getStartLoc();
1361     return Error(ErrorStart, "msb is less than lsb",
1362                  SMRange(ErrorStart, Operands[4]->getEndLoc()));
1363   }
1364   case Match_RequiresOpnd2NotR0R1:
1365     return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");
1366   case Match_RequiresAMORdDifferRkRj:
1367     return Error(Operands[1]->getStartLoc(),
1368                  "$rd must be different from both $rk and $rj");
1369   case Match_RequiresLAORdDifferRj:
1370     return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");
1371   case Match_InvalidUImm1:
1372     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1373                                       /*Upper=*/(1 << 1) - 1);
1374   case Match_InvalidUImm2:
1375     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1376                                       /*Upper=*/(1 << 2) - 1);
1377   case Match_InvalidUImm2plus1:
1378     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,
1379                                       /*Upper=*/(1 << 2));
1380   case Match_InvalidUImm3:
1381     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1382                                       /*Upper=*/(1 << 3) - 1);
1383   case Match_InvalidUImm4:
1384     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1385                                       /*Upper=*/(1 << 4) - 1);
1386   case Match_InvalidUImm5:
1387     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1388                                       /*Upper=*/(1 << 5) - 1);
1389   case Match_InvalidUImm6:
1390     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1391                                       /*Upper=*/(1 << 6) - 1);
1392   case Match_InvalidUImm7:
1393     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1394                                       /*Upper=*/(1 << 7) - 1);
1395   case Match_InvalidUImm8:
1396     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1397                                       /*Upper=*/(1 << 8) - 1);
1398   case Match_InvalidUImm12:
1399     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1400                                       /*Upper=*/(1 << 12) - 1);
1401   case Match_InvalidUImm12ori:
1402     return generateImmOutOfRangeError(
1403         Operands, ErrorInfo, /*Lower=*/0,
1404         /*Upper=*/(1 << 12) - 1,
1405         "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
1406         "integer in the range");
1407   case Match_InvalidUImm14:
1408     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1409                                       /*Upper=*/(1 << 14) - 1);
1410   case Match_InvalidUImm15:
1411     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1412                                       /*Upper=*/(1 << 15) - 1);
1413   case Match_InvalidSImm5:
1414     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),
1415                                       /*Upper=*/(1 << 4) - 1);
1416   case Match_InvalidSImm8:
1417     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),
1418                                       /*Upper=*/(1 << 7) - 1);
1419   case Match_InvalidSImm8lsl1:
1420     return generateImmOutOfRangeError(
1421         Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,
1422         "immediate must be a multiple of 2 in the range");
1423   case Match_InvalidSImm8lsl2:
1424     return generateImmOutOfRangeError(
1425         Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,
1426         "immediate must be a multiple of 4 in the range");
1427   case Match_InvalidSImm10:
1428     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),
1429                                       /*Upper=*/(1 << 9) - 1);
1430   case Match_InvalidSImm8lsl3:
1431     return generateImmOutOfRangeError(
1432         Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,
1433         "immediate must be a multiple of 8 in the range");
1434   case Match_InvalidSImm9lsl3:
1435     return generateImmOutOfRangeError(
1436         Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,
1437         "immediate must be a multiple of 8 in the range");
1438   case Match_InvalidSImm10lsl2:
1439     return generateImmOutOfRangeError(
1440         Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,
1441         "immediate must be a multiple of 4 in the range");
1442   case Match_InvalidSImm11lsl1:
1443     return generateImmOutOfRangeError(
1444         Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,
1445         "immediate must be a multiple of 2 in the range");
1446   case Match_InvalidSImm12:
1447     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1448                                       /*Upper=*/(1 << 11) - 1);
1449   case Match_InvalidSImm12addlike:
1450     return generateImmOutOfRangeError(
1451         Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1452         /*Upper=*/(1 << 11) - 1,
1453         "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
1454         "in the range");
1455   case Match_InvalidSImm12lu52id:
1456     return generateImmOutOfRangeError(
1457         Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1458         /*Upper=*/(1 << 11) - 1,
1459         "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
1460         "integer in the range");
1461   case Match_InvalidSImm13:
1462     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),
1463                                       /*Upper=*/(1 << 12) - 1);
1464   case Match_InvalidSImm14lsl2:
1465     return generateImmOutOfRangeError(
1466         Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
1467         "immediate must be a multiple of 4 in the range");
1468   case Match_InvalidSImm16:
1469     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15),
1470                                       /*Upper=*/(1 << 15) - 1);
1471   case Match_InvalidSImm16lsl2:
1472     return generateImmOutOfRangeError(
1473         Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
1474         "operand must be a symbol with modifier (e.g. %b16) or an integer "
1475         "in the range");
1476   case Match_InvalidSImm20:
1477     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1478                                       /*Upper=*/(1 << 19) - 1);
1479   case Match_InvalidSImm20lu12iw:
1480     return generateImmOutOfRangeError(
1481         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1482         /*Upper=*/(1 << 19) - 1,
1483         "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
1484         "in the range");
1485   case Match_InvalidSImm20lu32id:
1486     return generateImmOutOfRangeError(
1487         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1488         /*Upper=*/(1 << 19) - 1,
1489         "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
1490         "integer in the range");
1491   case Match_InvalidSImm20pcalau12i:
1492     return generateImmOutOfRangeError(
1493         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1494         /*Upper=*/(1 << 19) - 1,
1495         "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
1496         "in the range");
1497   case Match_InvalidSImm20pcaddu18i:
1498     return generateImmOutOfRangeError(
1499         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1500         /*Upper=*/(1 << 19) - 1,
1501         "operand must be a symbol with modifier (e.g. %call36) or an integer "
1502         "in the range");
1503   case Match_InvalidSImm21lsl2:
1504     return generateImmOutOfRangeError(
1505         Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
1506         "operand must be a symbol with modifier (e.g. %b21) or an integer "
1507         "in the range");
1508   case Match_InvalidSImm26Operand:
1509     return generateImmOutOfRangeError(
1510         Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
1511         "operand must be a bare symbol name or an immediate must be a multiple "
1512         "of 4 in the range");
1513   case Match_InvalidImm32: {
1514     SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1515     return Error(ErrorLoc, "operand must be a 32 bit immediate");
1516   }
1517   case Match_InvalidBareSymbol: {
1518     SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1519     return Error(ErrorLoc, "operand must be a bare symbol name");
1520   }
1521   }
1522   llvm_unreachable("Unknown match type detected!");
1523 }
1524 
1525 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() {
1526   RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target());
1527   RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target());
1528 }
1529