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