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