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