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