[AMDGPU] Add commute for some VOP3 inst (#121326)
[llvm-project.git] / llvm / lib / Target / LoongArch / AsmParser / LoongArchAsmParser.cpp
blob420b98b8a9c1f36a6296ad3e811678e73019323e
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 //===----------------------------------------------------------------------===//
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"
29 using namespace llvm;
31 #define DEBUG_TYPE "loongarch-asm-parser"
33 namespace {
34 class LoongArchAsmParser : public MCTargetAsmParser {
35 SmallVector<FeatureBitset, 4> FeatureBitStack;
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);
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) {}
53 using InstSeq = SmallVector<Inst>;
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;
60 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
61 SMLoc NameLoc, OperandVector &Operands) override;
63 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
64 OperandVector &Operands, MCStreamer &Out,
65 uint64_t &ErrorInfo,
66 bool MatchingInlineAsm) override;
68 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
70 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
71 unsigned Kind) override;
73 ParseStatus parseDirective(AsmToken DirectiveID) override;
75 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
76 int64_t Lower, int64_t Upper,
77 const Twine &Msg);
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);
84 // Auto-generated instruction matching functions.
85 #define GET_ASSEMBLER_HEADER
86 #include "LoongArchGenAsmMatcher.inc"
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);
94 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
96 bool parseDirectiveOption();
98 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
99 if (!(getSTI().hasFeature(Feature))) {
100 MCSubtargetInfo &STI = copySTI();
101 setAvailableFeatures(
102 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
106 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
107 if (getSTI().hasFeature(Feature)) {
108 MCSubtargetInfo &STI = copySTI();
109 setAvailableFeatures(
110 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
114 void pushFeatureBits() {
115 FeatureBitStack.push_back(getSTI().getFeatureBits());
118 bool popFeatureBits() {
119 if (FeatureBitStack.empty())
120 return true;
122 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
123 copySTI().setFeatureBits(FeatureBits);
124 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
126 return false;
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);
135 // Helper to emit pseudo instruction "la.abs $rd, sym".
136 void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
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);
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);
148 // Helper to emit pseudo instruction "la.tls.le $rd, sym".
149 void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
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);
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);
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);
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);
171 // Helper to emit pseudo instruction "li.w/d $rd, $imm".
172 void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
174 // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
175 void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
176 bool IsTailCall);
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
191 static bool classifySymbolRef(const MCExpr *Expr,
192 LoongArchMCExpr::VariantKind &Kind);
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");
202 // Initialize the set of available features.
203 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
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;
215 struct RegOp {
216 MCRegister RegNum;
219 struct ImmOp {
220 const MCExpr *Val;
223 SMLoc StartLoc, EndLoc;
224 union {
225 StringRef Tok;
226 struct RegOp Reg;
227 struct ImmOp Imm;
230 public:
231 LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
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);
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;
251 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
252 Imm = CE->getValue();
253 return true;
256 return false;
259 template <unsigned N, int P = 0> bool isUImm() const {
260 if (!isImm())
261 return false;
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;
270 template <unsigned N, unsigned S = 0> bool isSImm() const {
271 if (!isImm())
272 return false;
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;
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;
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;
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>(); }
321 bool isSImm12addlike() const {
322 if (!isImm())
323 return false;
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;
341 bool isSImm12lu52id() const {
342 if (!isImm())
343 return false;
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;
364 bool isUImm12() const { return isUImm<12>(); }
366 bool isUImm12ori() const {
367 if (!isImm())
368 return false;
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;
388 bool isSImm13() const { return isSImm<13>(); }
389 bool isUImm14() const { return isUImm<14>(); }
390 bool isUImm15() const { return isUImm<15>(); }
392 bool isSImm14lsl2() const { return isSImm<14, 2>(); }
393 bool isSImm16() const { return isSImm<16>(); }
395 bool isSImm16lsl2() const {
396 if (!isImm())
397 return false;
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;
412 bool isSImm20() const { return isSImm<20>(); }
414 bool isSImm20pcalau12i() const {
415 if (!isImm())
416 return false;
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;
434 bool isSImm20lu12iw() const {
435 if (!isImm())
436 return false;
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;
456 bool isSImm20lu32id() const {
457 if (!isImm())
458 return false;
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;
474 return IsConstantImm
475 ? isInt<20>(Imm) && IsValidKind
476 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
477 IsValidKind;
480 bool isSImm20pcaddu18i() const {
481 if (!isImm())
482 return false;
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;
490 return IsConstantImm
491 ? isInt<20>(Imm) && IsValidKind
492 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
493 IsValidKind;
496 bool isSImm20pcaddi() const {
497 if (!isImm())
498 return false;
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;
514 bool isSImm21lsl2() const {
515 if (!isImm())
516 return false;
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;
529 bool isSImm26Operand() const {
530 if (!isImm())
531 return false;
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;
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;
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; }
561 MCRegister getReg() const override {
562 assert(Kind == KindTy::Register && "Invalid type access!");
563 return Reg.RegNum;
566 const MCExpr *getImm() const {
567 assert(Kind == KindTy::Immediate && "Invalid type access!");
568 return Imm.Val;
571 StringRef getToken() const {
572 assert(Kind == KindTy::Token && "Invalid type access!");
573 return Tok;
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";
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;
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;
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;
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;
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));
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()));
635 void addImmOperands(MCInst &Inst, unsigned N) const {
636 assert(N == 1 && "Invalid number of operands!");
637 addExpr(Inst, getImm());
640 } // end namespace
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"
648 static MCRegister convertFPR32ToFPR64(MCRegister Reg) {
649 assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
650 return Reg - LoongArch::F0 + LoongArch::F0_64;
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);
667 return RegNo == LoongArch::NoRegister;
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");
675 if (!LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(Reg) &&
676 !LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg))
677 return Error(getLoc(), "invalid register name");
679 return false;
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();
689 parseOptionalToken(AsmToken::Dollar);
690 if (getLexer().getKind() != AsmToken::Identifier)
691 return ParseStatus::NoMatch;
693 StringRef Name = Tok.getIdentifier();
694 if (matchRegisterNameHelper(Reg, Name))
695 return ParseStatus::NoMatch;
697 getParser().Lex(); // Eat identifier token.
698 return ParseStatus::Success;
701 bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,
702 LoongArchMCExpr::VariantKind &Kind) {
703 Kind = LoongArchMCExpr::VK_LoongArch_None;
705 if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {
706 Kind = RE->getKind();
707 Expr = RE->getSubExpr();
710 MCValue Res;
711 if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr))
712 return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None;
713 return false;
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;
722 StringRef Name = getLexer().getTok().getIdentifier();
723 MCRegister RegNo;
724 matchRegisterNameHelper(RegNo, Name);
725 if (RegNo == LoongArch::NoRegister)
726 return ParseStatus::NoMatch;
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));
733 return ParseStatus::Success;
736 ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {
737 SMLoc S = getLoc();
738 SMLoc E;
739 const MCExpr *Res;
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);
760 Operands.push_back(LoongArchOperand::createImm(Res, S, E));
761 return ParseStatus::Success;
764 ParseStatus
765 LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {
766 SMLoc S = getLoc();
767 SMLoc E;
769 if (getLexer().getKind() != AsmToken::Percent)
770 return Error(getLoc(), "expected '%' for operand modifier");
772 getParser().Lex(); // Eat '%'
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");
782 getParser().Lex(); // Eat the identifier
783 if (getLexer().getKind() != AsmToken::LParen)
784 return Error(getLoc(), "expected '('");
785 getParser().Lex(); // Eat '('
787 const MCExpr *SubExpr;
788 if (getParser().parseParenExpression(SubExpr, E))
789 return ParseStatus::Failure;
791 const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());
792 Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));
793 return ParseStatus::Success;
796 ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {
797 SMLoc S = getLoc();
798 const MCExpr *Res;
800 if (getLexer().getKind() == AsmToken::Percent)
801 return parseOperandWithModifier(Operands);
803 if (getLexer().getKind() != AsmToken::Identifier)
804 return ParseStatus::NoMatch;
806 StringRef Identifier;
807 if (getParser().parseIdentifier(Identifier))
808 return ParseStatus::Failure;
810 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
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;
820 ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {
821 // Parse "$r*".
822 if (!parseRegister(Operands).isSuccess())
823 return ParseStatus::NoMatch;
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");
836 return ParseStatus::Success;
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;
851 if (parseRegister(Operands).isSuccess() ||
852 parseImmediate(Operands).isSuccess())
853 return false;
855 // Finally we have exhausted all options and must declare defeat.
856 return Error(getLoc(), "unknown operand");
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));
865 // If there are no more operands, then finish.
866 if (parseOptionalToken(AsmToken::EndOfStatement))
867 return false;
869 // Parse first operand.
870 if (parseOperand(Operands, Name))
871 return true;
873 // Parse until end of statement, consuming commas between operands.
874 while (parseOptionalToken(AsmToken::Comma))
875 if (parseOperand(Operands, Name))
876 return true;
878 // Parse end of statement and return successfully.
879 if (parseOptionalToken(AsmToken::EndOfStatement))
880 return false;
882 SMLoc Loc = getLexer().getLoc();
883 getParser().eatToEndOfStatement();
884 return Error(Loc, "unexpected token");
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;
923 Out.emitInstruction(
924 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
925 getSTI());
926 break;
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;
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)
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;
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));
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));
993 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
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;
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));
1012 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1013 /*RelaxHint=*/true);
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;
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));
1040 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
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;
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
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));
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));
1075 Insts.push_back(LoongArchAsmParser::Inst(LD));
1076 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1077 return;
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));
1087 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1088 /*RelaxHint=*/true);
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;
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));
1115 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
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;
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));
1133 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
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;
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
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));
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));
1168 Insts.push_back(LoongArchAsmParser::Inst(LD));
1169 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1170 return;
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));
1181 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1182 /*RelaxHint=*/true);
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;
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));
1209 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
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;
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)
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));
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));
1242 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1243 return;
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));
1254 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1255 /*RelaxHint=*/true);
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;
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));
1282 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
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;
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)
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));
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));
1315 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1316 return;
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));
1327 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1328 /*RelaxHint=*/true);
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;
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));
1355 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
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;
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)
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));
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));
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));
1399 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1400 return;
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));
1417 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1418 /*RelaxHint=*/true);
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;
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));
1451 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
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;
1460 if (Inst.getOpcode() == LoongArch::PseudoLI_W)
1461 Imm = SignExtend64<32>(Imm);
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");
1490 SrcReg = DestReg;
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
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);
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());
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;
1585 Out.emitInstruction(Inst, getSTI());
1586 return false;
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;
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;
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;
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;
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;
1647 return Match_Success;
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;
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;
1666 return Match_InvalidOperand;
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) + "]");
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;
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;
1702 return Error(IDLoc, Msg);
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);
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");
1716 ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1717 if (ErrorLoc == SMLoc())
1718 ErrorLoc = IDLoc;
1720 return Error(ErrorLoc, "invalid operand for instruction");
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");
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()));
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");
1902 case Match_InvalidImm64: {
1903 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1904 return Error(ErrorLoc, "operand must be a 64 bit immediate");
1906 case Match_InvalidBareSymbol: {
1907 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1908 return Error(ErrorLoc, "operand must be a bare symbol name");
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");
1915 llvm_unreachable("Unknown match type detected!");
1918 bool LoongArchAsmParser::parseDirectiveOption() {
1919 MCAsmParser &Parser = getParser();
1920 // Get the option token.
1921 AsmToken Tok = Parser.getTok();
1923 // At the moment only identifiers are supported.
1924 if (parseToken(AsmToken::Identifier, "expected identifier"))
1925 return true;
1927 StringRef Option = Tok.getIdentifier();
1929 if (Option == "push") {
1930 if (Parser.parseEOL())
1931 return true;
1933 getTargetStreamer().emitDirectiveOptionPush();
1934 pushFeatureBits();
1935 return false;
1938 if (Option == "pop") {
1939 SMLoc StartLoc = Parser.getTok().getLoc();
1940 if (Parser.parseEOL())
1941 return true;
1943 getTargetStreamer().emitDirectiveOptionPop();
1944 if (popFeatureBits())
1945 return Error(StartLoc, ".option pop with no .option push");
1947 return false;
1950 if (Option == "relax") {
1951 if (Parser.parseEOL())
1952 return true;
1954 getTargetStreamer().emitDirectiveOptionRelax();
1955 setFeatureBits(LoongArch::FeatureRelax, "relax");
1956 return false;
1959 if (Option == "norelax") {
1960 if (Parser.parseEOL())
1961 return true;
1963 getTargetStreamer().emitDirectiveOptionNoRelax();
1964 clearFeatureBits(LoongArch::FeatureRelax, "relax");
1965 return false;
1968 // Unknown option.
1969 Warning(Parser.getTok().getLoc(),
1970 "unknown option, expected 'push', 'pop', 'relax' or 'norelax'");
1971 Parser.eatToEndOfStatement();
1972 return false;
1975 ParseStatus LoongArchAsmParser::parseDirective(AsmToken DirectiveID) {
1976 if (DirectiveID.getString() == ".option")
1977 return parseDirectiveOption();
1979 return ParseStatus::NoMatch;
1982 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() {
1983 RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target());
1984 RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target());