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