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