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