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