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