1 // LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=//
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
7 //===----------------------------------------------------------------------===//
9 #include "MCTargetDesc/LoongArchBaseInfo.h"
10 #include "MCTargetDesc/LoongArchInstPrinter.h"
11 #include "MCTargetDesc/LoongArchMCExpr.h"
12 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
13 #include "MCTargetDesc/LoongArchMatInt.h"
14 #include "MCTargetDesc/LoongArchTargetStreamer.h"
15 #include "TargetInfo/LoongArchTargetInfo.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCInstBuilder.h"
18 #include "llvm/MC/MCInstrInfo.h"
19 #include "llvm/MC/MCParser/MCAsmLexer.h"
20 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
22 #include "llvm/MC/MCRegisterInfo.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/MC/MCValue.h"
26 #include "llvm/MC/TargetRegistry.h"
27 #include "llvm/Support/Casting.h"
31 #define DEBUG_TYPE "loongarch-asm-parser"
34 class LoongArchAsmParser
: public MCTargetAsmParser
{
35 SmallVector
<FeatureBitset
, 4> FeatureBitStack
;
37 SMLoc
getLoc() const { return getParser().getTok().getLoc(); }
38 bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit
); }
39 LoongArchTargetStreamer
&getTargetStreamer() {
40 assert(getParser().getStreamer().getTargetStreamer() &&
41 "do not have a target streamer");
42 MCTargetStreamer
&TS
= *getParser().getStreamer().getTargetStreamer();
43 return static_cast<LoongArchTargetStreamer
&>(TS
);
48 LoongArchMCExpr::VariantKind VK
;
50 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
)
53 using InstSeq
= SmallVector
<Inst
>;
55 /// Parse a register as used in CFI directives.
56 bool parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
57 ParseStatus
tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
58 SMLoc
&EndLoc
) override
;
60 bool parseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
61 SMLoc NameLoc
, OperandVector
&Operands
) override
;
63 bool matchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
64 OperandVector
&Operands
, MCStreamer
&Out
,
66 bool MatchingInlineAsm
) override
;
68 unsigned checkTargetMatchPredicate(MCInst
&Inst
) override
;
70 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
71 unsigned Kind
) override
;
73 ParseStatus
parseDirective(AsmToken DirectiveID
) override
;
75 bool generateImmOutOfRangeError(OperandVector
&Operands
, uint64_t ErrorInfo
,
76 int64_t Lower
, int64_t Upper
,
79 /// Helper for processing MC instructions that have been successfully matched
80 /// by matchAndEmitInstruction.
81 bool processInstruction(MCInst
&Inst
, SMLoc IDLoc
, OperandVector
&Operands
,
84 // Auto-generated instruction matching functions.
85 #define GET_ASSEMBLER_HEADER
86 #include "LoongArchGenAsmMatcher.inc"
88 ParseStatus
parseRegister(OperandVector
&Operands
);
89 ParseStatus
parseImmediate(OperandVector
&Operands
);
90 ParseStatus
parseOperandWithModifier(OperandVector
&Operands
);
91 ParseStatus
parseSImm26Operand(OperandVector
&Operands
);
92 ParseStatus
parseAtomicMemOp(OperandVector
&Operands
);
94 bool parseOperand(OperandVector
&Operands
, StringRef Mnemonic
);
96 bool parseDirectiveOption();
98 void setFeatureBits(uint64_t Feature
, StringRef FeatureString
) {
99 if (!(getSTI().hasFeature(Feature
))) {
100 MCSubtargetInfo
&STI
= copySTI();
101 setAvailableFeatures(
102 ComputeAvailableFeatures(STI
.ToggleFeature(FeatureString
)));
106 void clearFeatureBits(uint64_t Feature
, StringRef FeatureString
) {
107 if (getSTI().hasFeature(Feature
)) {
108 MCSubtargetInfo
&STI
= copySTI();
109 setAvailableFeatures(
110 ComputeAvailableFeatures(STI
.ToggleFeature(FeatureString
)));
114 void pushFeatureBits() {
115 FeatureBitStack
.push_back(getSTI().getFeatureBits());
118 bool popFeatureBits() {
119 if (FeatureBitStack
.empty())
122 FeatureBitset FeatureBits
= FeatureBitStack
.pop_back_val();
123 copySTI().setFeatureBits(FeatureBits
);
124 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits
));
129 // Helper to emit the sequence of instructions generated by the
130 // "emitLoadAddress*" functions.
131 void emitLAInstSeq(MCRegister DestReg
, MCRegister TmpReg
,
132 const MCExpr
*Symbol
, SmallVectorImpl
<Inst
> &Insts
,
133 SMLoc IDLoc
, MCStreamer
&Out
, bool RelaxHint
= false);
135 // Helper to emit pseudo instruction "la.abs $rd, sym".
136 void emitLoadAddressAbs(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
138 // Helper to emit pseudo instruction "la.pcrel $rd, sym".
139 void emitLoadAddressPcrel(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
140 // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".
141 void emitLoadAddressPcrelLarge(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
143 // Helper to emit pseudo instruction "la.got $rd, sym".
144 void emitLoadAddressGot(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
145 // Helper to emit pseudo instruction "la.got $rd, $rj, sym".
146 void emitLoadAddressGotLarge(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
148 // Helper to emit pseudo instruction "la.tls.le $rd, sym".
149 void emitLoadAddressTLSLE(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
151 // Helper to emit pseudo instruction "la.tls.ie $rd, sym".
152 void emitLoadAddressTLSIE(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
153 // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".
154 void emitLoadAddressTLSIELarge(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
156 // Helper to emit pseudo instruction "la.tls.ld $rd, sym".
157 void emitLoadAddressTLSLD(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
158 // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".
159 void emitLoadAddressTLSLDLarge(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
161 // Helper to emit pseudo instruction "la.tls.gd $rd, sym".
162 void emitLoadAddressTLSGD(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
163 // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
164 void emitLoadAddressTLSGDLarge(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
166 // Helper to emit pseudo instruction "la.tls.desc $rd, sym".
167 void emitLoadAddressTLSDesc(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
168 // Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".
169 void emitLoadAddressTLSDescLarge(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
171 // Helper to emit pseudo instruction "li.w/d $rd, $imm".
172 void emitLoadImm(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
174 // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
175 void emitFuncCall36(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
,
179 enum LoongArchMatchResultTy
{
180 Match_Dummy
= FIRST_TARGET_MATCH_RESULT_TY
,
181 Match_RequiresMsbNotLessThanLsb
,
182 Match_RequiresOpnd2NotR0R1
,
183 Match_RequiresAMORdDifferRkRj
,
184 Match_RequiresLAORdDifferRj
,
185 Match_RequiresLAORdR4
,
186 #define GET_OPERAND_DIAGNOSTIC_TYPES
187 #include "LoongArchGenAsmMatcher.inc"
188 #undef GET_OPERAND_DIAGNOSTIC_TYPES
191 static bool classifySymbolRef(const MCExpr
*Expr
,
192 LoongArchMCExpr::VariantKind
&Kind
);
194 LoongArchAsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
195 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
196 : MCTargetAsmParser(Options
, STI
, MII
) {
197 Parser
.addAliasForDirective(".half", ".2byte");
198 Parser
.addAliasForDirective(".hword", ".2byte");
199 Parser
.addAliasForDirective(".word", ".4byte");
200 Parser
.addAliasForDirective(".dword", ".8byte");
202 // Initialize the set of available features.
203 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
207 // Instances of this class represent a parsed LoongArch machine instruction.
208 class LoongArchOperand
: public MCParsedAsmOperand
{
223 SMLoc StartLoc
, EndLoc
;
231 LoongArchOperand(KindTy K
) : MCParsedAsmOperand(), Kind(K
) {}
233 bool isToken() const override
{ return Kind
== KindTy::Token
; }
234 bool isReg() const override
{ return Kind
== KindTy::Register
; }
235 bool isImm() const override
{ return Kind
== KindTy::Immediate
; }
236 bool isMem() const override
{ return false; }
237 void setReg(MCRegister PhysReg
) { Reg
.RegNum
= PhysReg
; }
239 return Kind
== KindTy::Register
&&
240 LoongArchMCRegisterClasses
[LoongArch::GPRRegClassID
].contains(
244 static bool evaluateConstantImm(const MCExpr
*Expr
, int64_t &Imm
,
245 LoongArchMCExpr::VariantKind
&VK
) {
246 if (auto *LE
= dyn_cast
<LoongArchMCExpr
>(Expr
)) {
251 if (auto CE
= dyn_cast
<MCConstantExpr
>(Expr
)) {
252 Imm
= CE
->getValue();
259 template <unsigned N
, int P
= 0> bool isUImm() const {
264 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
265 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
266 return IsConstantImm
&& isUInt
<N
>(Imm
- P
) &&
267 VK
== LoongArchMCExpr::VK_LoongArch_None
;
270 template <unsigned N
, unsigned S
= 0> bool isSImm() const {
275 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
276 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
277 return IsConstantImm
&& isShiftedInt
<N
, S
>(Imm
) &&
278 VK
== LoongArchMCExpr::VK_LoongArch_None
;
281 bool isBareSymbol() const {
283 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
284 // Must be of 'immediate' type but not a constant.
285 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
287 return LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
288 VK
== LoongArchMCExpr::VK_LoongArch_None
;
291 bool isTPRelAddSymbol() const {
293 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
294 // Must be of 'immediate' type but not a constant.
295 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
297 return LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
298 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R
;
301 bool isUImm1() const { return isUImm
<1>(); }
302 bool isUImm2() const { return isUImm
<2>(); }
303 bool isUImm2plus1() const { return isUImm
<2, 1>(); }
304 bool isUImm3() const { return isUImm
<3>(); }
305 bool isUImm4() const { return isUImm
<4>(); }
306 bool isSImm5() const { return isSImm
<5>(); }
307 bool isUImm5() const { return isUImm
<5>(); }
308 bool isUImm6() const { return isUImm
<6>(); }
309 bool isUImm7() const { return isUImm
<7>(); }
310 bool isSImm8() const { return isSImm
<8>(); }
311 bool isSImm8lsl1() const { return isSImm
<8, 1>(); }
312 bool isSImm8lsl2() const { return isSImm
<8, 2>(); }
313 bool isSImm8lsl3() const { return isSImm
<8, 3>(); }
314 bool isUImm8() const { return isUImm
<8>(); }
315 bool isSImm9lsl3() const { return isSImm
<9, 3>(); }
316 bool isSImm10() const { return isSImm
<10>(); }
317 bool isSImm10lsl2() const { return isSImm
<10, 2>(); }
318 bool isSImm11lsl1() const { return isSImm
<11, 1>(); }
319 bool isSImm12() const { return isSImm
<12>(); }
321 bool isSImm12addlike() const {
326 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
327 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
328 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
329 VK
== LoongArchMCExpr::VK_LoongArch_PCALA_LO12
||
330 VK
== LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12
||
331 VK
== LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12
||
332 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R
||
333 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12
||
334 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD
;
336 ? isInt
<12>(Imm
) && IsValidKind
337 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
341 bool isSImm12lu52id() const {
346 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
347 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
348 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
349 VK
== LoongArchMCExpr::VK_LoongArch_ABS64_HI12
||
350 VK
== LoongArchMCExpr::VK_LoongArch_PCALA64_HI12
||
351 VK
== LoongArchMCExpr::VK_LoongArch_GOT64_HI12
||
352 VK
== LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12
||
353 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12
||
354 VK
== LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12
||
355 VK
== LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12
||
356 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12
||
357 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12
;
359 ? isInt
<12>(Imm
) && IsValidKind
360 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
364 bool isUImm12() const { return isUImm
<12>(); }
366 bool isUImm12ori() const {
371 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
372 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
373 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
374 VK
== LoongArchMCExpr::VK_LoongArch_ABS_LO12
||
375 VK
== LoongArchMCExpr::VK_LoongArch_PCALA_LO12
||
376 VK
== LoongArchMCExpr::VK_LoongArch_GOT_LO12
||
377 VK
== LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12
||
378 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12
||
379 VK
== LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12
||
380 VK
== LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12
||
381 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12
;
383 ? isUInt
<12>(Imm
) && IsValidKind
384 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
388 bool isSImm13() const { return isSImm
<13>(); }
389 bool isUImm14() const { return isUImm
<14>(); }
390 bool isUImm15() const { return isUImm
<15>(); }
392 bool isSImm14lsl2() const { return isSImm
<14, 2>(); }
393 bool isSImm16() const { return isSImm
<16>(); }
395 bool isSImm16lsl2() const {
400 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
401 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
402 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
403 VK
== LoongArchMCExpr::VK_LoongArch_B16
||
404 VK
== LoongArchMCExpr::VK_LoongArch_PCALA_LO12
||
405 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL
;
407 ? isShiftedInt
<16, 2>(Imm
) && IsValidKind
408 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
412 bool isSImm20() const { return isSImm
<20>(); }
414 bool isSImm20pcalau12i() const {
419 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
420 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
421 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
422 VK
== LoongArchMCExpr::VK_LoongArch_PCALA_HI20
||
423 VK
== LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20
||
424 VK
== LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20
||
425 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20
||
426 VK
== LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20
||
427 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20
;
429 ? isInt
<20>(Imm
) && IsValidKind
430 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
434 bool isSImm20lu12iw() const {
439 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
440 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
441 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
442 VK
== LoongArchMCExpr::VK_LoongArch_ABS_HI20
||
443 VK
== LoongArchMCExpr::VK_LoongArch_GOT_HI20
||
444 VK
== LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20
||
445 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20
||
446 VK
== LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20
||
447 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20
||
448 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R
||
449 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20
;
451 ? isInt
<20>(Imm
) && IsValidKind
452 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
456 bool isSImm20lu32id() const {
461 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
462 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
463 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
464 VK
== LoongArchMCExpr::VK_LoongArch_ABS64_LO20
||
465 VK
== LoongArchMCExpr::VK_LoongArch_PCALA64_LO20
||
466 VK
== LoongArchMCExpr::VK_LoongArch_GOT64_LO20
||
467 VK
== LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20
||
468 VK
== LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20
||
469 VK
== LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20
||
470 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20
||
471 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20
||
472 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20
;
475 ? isInt
<20>(Imm
) && IsValidKind
476 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
480 bool isSImm20pcaddu18i() const {
485 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
486 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
487 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
488 VK
== LoongArchMCExpr::VK_LoongArch_CALL36
;
491 ? isInt
<20>(Imm
) && IsValidKind
492 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
496 bool isSImm20pcaddi() const {
501 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
502 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
503 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
504 VK
== LoongArchMCExpr::VK_LoongArch_PCREL20_S2
||
505 VK
== LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2
||
506 VK
== LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2
||
507 VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2
;
509 ? isInt
<20>(Imm
) && IsValidKind
510 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
514 bool isSImm21lsl2() const {
519 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
520 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
521 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
522 VK
== LoongArchMCExpr::VK_LoongArch_B21
;
524 ? isShiftedInt
<21, 2>(Imm
) && IsValidKind
525 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
529 bool isSImm26Operand() const {
534 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
535 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
536 bool IsValidKind
= VK
== LoongArchMCExpr::VK_LoongArch_None
||
537 VK
== LoongArchMCExpr::VK_LoongArch_CALL
||
538 VK
== LoongArchMCExpr::VK_LoongArch_CALL_PLT
||
539 VK
== LoongArchMCExpr::VK_LoongArch_B26
;
541 ? isShiftedInt
<26, 2>(Imm
) && IsValidKind
542 : LoongArchAsmParser::classifySymbolRef(getImm(), VK
) &&
546 bool isImm32() const { return isSImm
<32>() || isUImm
<32>(); }
547 bool isImm64() const {
551 LoongArchMCExpr::VariantKind VK
= LoongArchMCExpr::VK_LoongArch_None
;
552 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
553 return IsConstantImm
&& VK
== LoongArchMCExpr::VK_LoongArch_None
;
556 /// Gets location of the first token of this operand.
557 SMLoc
getStartLoc() const override
{ return StartLoc
; }
558 /// Gets location of the last token of this operand.
559 SMLoc
getEndLoc() const override
{ return EndLoc
; }
561 MCRegister
getReg() const override
{
562 assert(Kind
== KindTy::Register
&& "Invalid type access!");
566 const MCExpr
*getImm() const {
567 assert(Kind
== KindTy::Immediate
&& "Invalid type access!");
571 StringRef
getToken() const {
572 assert(Kind
== KindTy::Token
&& "Invalid type access!");
576 void print(raw_ostream
&OS
) const override
{
577 auto RegName
= [](MCRegister Reg
) {
579 return LoongArchInstPrinter::getRegisterName(Reg
);
585 case KindTy::Immediate
:
588 case KindTy::Register
:
589 OS
<< "<register " << RegName(getReg()) << ">";
592 OS
<< "'" << getToken() << "'";
597 static std::unique_ptr
<LoongArchOperand
> createToken(StringRef Str
, SMLoc S
) {
598 auto Op
= std::make_unique
<LoongArchOperand
>(KindTy::Token
);
605 static std::unique_ptr
<LoongArchOperand
> createReg(MCRegister Reg
, SMLoc S
,
607 auto Op
= std::make_unique
<LoongArchOperand
>(KindTy::Register
);
608 Op
->Reg
.RegNum
= Reg
;
614 static std::unique_ptr
<LoongArchOperand
> createImm(const MCExpr
*Val
, SMLoc S
,
616 auto Op
= std::make_unique
<LoongArchOperand
>(KindTy::Immediate
);
623 void addExpr(MCInst
&Inst
, const MCExpr
*Expr
) const {
624 if (auto CE
= dyn_cast
<MCConstantExpr
>(Expr
))
625 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
627 Inst
.addOperand(MCOperand::createExpr(Expr
));
630 // Used by the TableGen Code.
631 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
632 assert(N
== 1 && "Invalid number of operands!");
633 Inst
.addOperand(MCOperand::createReg(getReg()));
635 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
636 assert(N
== 1 && "Invalid number of operands!");
637 addExpr(Inst
, getImm());
642 #define GET_REGISTER_MATCHER
643 #define GET_SUBTARGET_FEATURE_NAME
644 #define GET_MATCHER_IMPLEMENTATION
645 #define GET_MNEMONIC_SPELL_CHECKER
646 #include "LoongArchGenAsmMatcher.inc"
648 static MCRegister
convertFPR32ToFPR64(MCRegister Reg
) {
649 assert(Reg
>= LoongArch::F0
&& Reg
<= LoongArch::F31
&& "Invalid register");
650 return Reg
- LoongArch::F0
+ LoongArch::F0_64
;
653 // Attempts to match Name as a register (either using the default name or
654 // alternative ABI names), setting RegNo to the matching register. Upon
655 // failure, returns true and sets RegNo to 0.
656 static bool matchRegisterNameHelper(MCRegister
&RegNo
, StringRef Name
) {
657 RegNo
= MatchRegisterName(Name
);
658 // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
659 // match always matches the 32-bit variant, and not the 64-bit one.
660 assert(!(RegNo
>= LoongArch::F0_64
&& RegNo
<= LoongArch::F31_64
));
661 // The default FPR register class is based on the tablegen enum ordering.
662 static_assert(LoongArch::F0
< LoongArch::F0_64
,
663 "FPR matching must be updated");
664 if (RegNo
== LoongArch::NoRegister
)
665 RegNo
= MatchRegisterAltName(Name
);
667 return RegNo
== LoongArch::NoRegister
;
670 bool LoongArchAsmParser::parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
672 if (!tryParseRegister(Reg
, StartLoc
, EndLoc
).isSuccess())
673 return Error(getLoc(), "invalid register name");
675 if (!LoongArchMCRegisterClasses
[LoongArch::GPRRegClassID
].contains(Reg
) &&
676 !LoongArchMCRegisterClasses
[LoongArch::FPR32RegClassID
].contains(Reg
))
677 return Error(getLoc(), "invalid register name");
682 ParseStatus
LoongArchAsmParser::tryParseRegister(MCRegister
&Reg
,
685 const AsmToken
&Tok
= getParser().getTok();
686 StartLoc
= Tok
.getLoc();
687 EndLoc
= Tok
.getEndLoc();
689 parseOptionalToken(AsmToken::Dollar
);
690 if (getLexer().getKind() != AsmToken::Identifier
)
691 return ParseStatus::NoMatch
;
693 StringRef Name
= Tok
.getIdentifier();
694 if (matchRegisterNameHelper(Reg
, Name
))
695 return ParseStatus::NoMatch
;
697 getParser().Lex(); // Eat identifier token.
698 return ParseStatus::Success
;
701 bool LoongArchAsmParser::classifySymbolRef(const MCExpr
*Expr
,
702 LoongArchMCExpr::VariantKind
&Kind
) {
703 Kind
= LoongArchMCExpr::VK_LoongArch_None
;
705 if (const LoongArchMCExpr
*RE
= dyn_cast
<LoongArchMCExpr
>(Expr
)) {
706 Kind
= RE
->getKind();
707 Expr
= RE
->getSubExpr();
711 if (Expr
->evaluateAsRelocatable(Res
, nullptr, nullptr))
712 return Res
.getRefKind() == LoongArchMCExpr::VK_LoongArch_None
;
716 ParseStatus
LoongArchAsmParser::parseRegister(OperandVector
&Operands
) {
717 if (!parseOptionalToken(AsmToken::Dollar
))
718 return ParseStatus::NoMatch
;
719 if (getLexer().getKind() != AsmToken::Identifier
)
720 return ParseStatus::NoMatch
;
722 StringRef Name
= getLexer().getTok().getIdentifier();
724 matchRegisterNameHelper(RegNo
, Name
);
725 if (RegNo
== LoongArch::NoRegister
)
726 return ParseStatus::NoMatch
;
729 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
731 Operands
.push_back(LoongArchOperand::createReg(RegNo
, S
, E
));
733 return ParseStatus::Success
;
736 ParseStatus
LoongArchAsmParser::parseImmediate(OperandVector
&Operands
) {
741 switch (getLexer().getKind()) {
743 return ParseStatus::NoMatch
;
744 case AsmToken::LParen
:
746 case AsmToken::Minus
:
748 case AsmToken::Exclaim
:
749 case AsmToken::Tilde
:
750 case AsmToken::Integer
:
751 case AsmToken::String
:
752 case AsmToken::Identifier
:
753 if (getParser().parseExpression(Res
, E
))
754 return ParseStatus::Failure
;
756 case AsmToken::Percent
:
757 return parseOperandWithModifier(Operands
);
760 Operands
.push_back(LoongArchOperand::createImm(Res
, S
, E
));
761 return ParseStatus::Success
;
765 LoongArchAsmParser::parseOperandWithModifier(OperandVector
&Operands
) {
769 if (getLexer().getKind() != AsmToken::Percent
)
770 return Error(getLoc(), "expected '%' for operand modifier");
772 getParser().Lex(); // Eat '%'
774 if (getLexer().getKind() != AsmToken::Identifier
)
775 return Error(getLoc(), "expected valid identifier for operand modifier");
776 StringRef Identifier
= getParser().getTok().getIdentifier();
777 LoongArchMCExpr::VariantKind VK
=
778 LoongArchMCExpr::getVariantKindForName(Identifier
);
779 if (VK
== LoongArchMCExpr::VK_LoongArch_Invalid
)
780 return Error(getLoc(), "unrecognized operand modifier");
782 getParser().Lex(); // Eat the identifier
783 if (getLexer().getKind() != AsmToken::LParen
)
784 return Error(getLoc(), "expected '('");
785 getParser().Lex(); // Eat '('
787 const MCExpr
*SubExpr
;
788 if (getParser().parseParenExpression(SubExpr
, E
))
789 return ParseStatus::Failure
;
791 const MCExpr
*ModExpr
= LoongArchMCExpr::create(SubExpr
, VK
, getContext());
792 Operands
.push_back(LoongArchOperand::createImm(ModExpr
, S
, E
));
793 return ParseStatus::Success
;
796 ParseStatus
LoongArchAsmParser::parseSImm26Operand(OperandVector
&Operands
) {
800 if (getLexer().getKind() == AsmToken::Percent
)
801 return parseOperandWithModifier(Operands
);
803 if (getLexer().getKind() != AsmToken::Identifier
)
804 return ParseStatus::NoMatch
;
806 StringRef Identifier
;
807 if (getParser().parseIdentifier(Identifier
))
808 return ParseStatus::Failure
;
810 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
812 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Identifier
);
813 Res
= MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, getContext());
814 Res
= LoongArchMCExpr::create(Res
, LoongArchMCExpr::VK_LoongArch_CALL
,
816 Operands
.push_back(LoongArchOperand::createImm(Res
, S
, E
));
817 return ParseStatus::Success
;
820 ParseStatus
LoongArchAsmParser::parseAtomicMemOp(OperandVector
&Operands
) {
822 if (!parseRegister(Operands
).isSuccess())
823 return ParseStatus::NoMatch
;
825 // If there is a next operand and it is 0, ignore it. Otherwise print a
826 // diagnostic message.
827 if (parseOptionalToken(AsmToken::Comma
)) {
829 SMLoc ImmStart
= getLoc();
830 if (getParser().parseIntToken(ImmVal
, "expected optional integer offset"))
831 return ParseStatus::Failure
;
833 return Error(ImmStart
, "optional integer offset must be 0");
836 return ParseStatus::Success
;
838 /// Looks at a token type and creates the relevant operand from this
839 /// information, adding to Operands. Return true upon an error.
840 bool LoongArchAsmParser::parseOperand(OperandVector
&Operands
,
841 StringRef Mnemonic
) {
842 // Check if the current operand has a custom associated parser, if so, try to
843 // custom parse the operand, or fallback to the general approach.
845 MatchOperandParserImpl(Operands
, Mnemonic
, /*ParseForAllFeatures=*/true);
846 if (Result
.isSuccess())
848 if (Result
.isFailure())
851 if (parseRegister(Operands
).isSuccess() ||
852 parseImmediate(Operands
).isSuccess())
855 // Finally we have exhausted all options and must declare defeat.
856 return Error(getLoc(), "unknown operand");
859 bool LoongArchAsmParser::parseInstruction(ParseInstructionInfo
&Info
,
860 StringRef Name
, SMLoc NameLoc
,
861 OperandVector
&Operands
) {
862 // First operand in MCInst is instruction mnemonic.
863 Operands
.push_back(LoongArchOperand::createToken(Name
, NameLoc
));
865 // If there are no more operands, then finish.
866 if (parseOptionalToken(AsmToken::EndOfStatement
))
869 // Parse first operand.
870 if (parseOperand(Operands
, Name
))
873 // Parse until end of statement, consuming commas between operands.
874 while (parseOptionalToken(AsmToken::Comma
))
875 if (parseOperand(Operands
, Name
))
878 // Parse end of statement and return successfully.
879 if (parseOptionalToken(AsmToken::EndOfStatement
))
882 SMLoc Loc
= getLexer().getLoc();
883 getParser().eatToEndOfStatement();
884 return Error(Loc
, "unexpected token");
887 void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg
, MCRegister TmpReg
,
888 const MCExpr
*Symbol
,
889 SmallVectorImpl
<Inst
> &Insts
,
890 SMLoc IDLoc
, MCStreamer
&Out
,
892 MCContext
&Ctx
= getContext();
893 for (LoongArchAsmParser::Inst
&Inst
: Insts
) {
894 unsigned Opc
= Inst
.Opc
;
895 LoongArchMCExpr::VariantKind VK
= Inst
.VK
;
896 const LoongArchMCExpr
*LE
=
897 LoongArchMCExpr::create(Symbol
, VK
, Ctx
, RelaxHint
);
900 llvm_unreachable("unexpected opcode");
901 case LoongArch::PCALAU12I
:
902 case LoongArch::LU12I_W
:
903 Out
.emitInstruction(MCInstBuilder(Opc
).addReg(DestReg
).addExpr(LE
),
907 case LoongArch::ADDI_W
:
908 case LoongArch::LD_W
:
909 case LoongArch::LD_D
: {
910 if (VK
== LoongArchMCExpr::VK_LoongArch_None
) {
912 MCInstBuilder(Opc
).addReg(DestReg
).addReg(DestReg
).addImm(0),
915 } else if (VK
== LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD
) {
916 Out
.emitInstruction(MCInstBuilder(Opc
)
917 .addReg(LoongArch::R1
)
924 MCInstBuilder(Opc
).addReg(DestReg
).addReg(DestReg
).addExpr(LE
),
928 case LoongArch::LU32I_D
:
929 Out
.emitInstruction(MCInstBuilder(Opc
)
930 .addReg(DestReg
== TmpReg
? DestReg
: TmpReg
)
931 .addReg(DestReg
== TmpReg
? DestReg
: TmpReg
)
935 case LoongArch::LU52I_D
:
937 MCInstBuilder(Opc
).addReg(TmpReg
).addReg(TmpReg
).addExpr(LE
),
940 case LoongArch::ADDI_D
:
944 .addReg(DestReg
== TmpReg
? TmpReg
: LoongArch::R0
)
948 case LoongArch::ADD_D
:
949 case LoongArch::LDX_D
:
951 MCInstBuilder(Opc
).addReg(DestReg
).addReg(DestReg
).addReg(TmpReg
),
954 case LoongArch::JIRL
:
955 Out
.emitInstruction(MCInstBuilder(Opc
)
956 .addReg(LoongArch::R1
)
957 .addReg(LoongArch::R1
)
965 void LoongArchAsmParser::emitLoadAddressAbs(MCInst
&Inst
, SMLoc IDLoc
,
969 // lu12i.w $rd, %abs_hi20(sym)
970 // ori $rd, $rd, %abs_lo12(sym)
972 // for 64bit appends:
973 // lu32i.d $rd, %abs64_lo20(sym)
974 // lu52i.d $rd, $rd, %abs64_hi12(sym)
975 MCRegister DestReg
= Inst
.getOperand(0).getReg();
976 const MCExpr
*Symbol
= Inst
.getOpcode() == LoongArch::PseudoLA_ABS
977 ? Inst
.getOperand(1).getExpr()
978 : Inst
.getOperand(2).getExpr();
981 Insts
.push_back(LoongArchAsmParser::Inst(
982 LoongArch::LU12I_W
, LoongArchMCExpr::VK_LoongArch_ABS_HI20
));
983 Insts
.push_back(LoongArchAsmParser::Inst(
984 LoongArch::ORI
, LoongArchMCExpr::VK_LoongArch_ABS_LO12
));
987 Insts
.push_back(LoongArchAsmParser::Inst(
988 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_ABS64_LO20
));
989 Insts
.push_back(LoongArchAsmParser::Inst(
990 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_ABS64_HI12
));
993 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
);
996 void LoongArchAsmParser::emitLoadAddressPcrel(MCInst
&Inst
, SMLoc IDLoc
,
1000 // pcalau12i $rd, %pc_hi20(sym)
1001 // addi.w/d $rd, rd, %pc_lo12(sym)
1002 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1003 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
1005 unsigned ADDI
= is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
1007 Insts
.push_back(LoongArchAsmParser::Inst(
1008 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_PCALA_HI20
));
1010 LoongArchAsmParser::Inst(ADDI
, LoongArchMCExpr::VK_LoongArch_PCALA_LO12
));
1012 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
,
1013 /*RelaxHint=*/true);
1016 void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst
&Inst
, SMLoc IDLoc
,
1018 // la.pcrel $rd, $rj, sym
1020 // pcalau12i $rd, %pc_hi20(sym)
1021 // addi.d $rj, $r0, %pc_lo12(sym)
1022 // lu32i.d $rj, %pc64_lo20(sym)
1023 // lu52i.d $rj, $rj, %pc64_hi12(sym)
1024 // add.d $rd, $rd, $rj
1025 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1026 MCRegister TmpReg
= Inst
.getOperand(1).getReg();
1027 const MCExpr
*Symbol
= Inst
.getOperand(2).getExpr();
1030 Insts
.push_back(LoongArchAsmParser::Inst(
1031 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_PCALA_HI20
));
1032 Insts
.push_back(LoongArchAsmParser::Inst(
1033 LoongArch::ADDI_D
, LoongArchMCExpr::VK_LoongArch_PCALA_LO12
));
1034 Insts
.push_back(LoongArchAsmParser::Inst(
1035 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20
));
1036 Insts
.push_back(LoongArchAsmParser::Inst(
1037 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12
));
1038 Insts
.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D
));
1040 emitLAInstSeq(DestReg
, TmpReg
, Symbol
, Insts
, IDLoc
, Out
);
1043 void LoongArchAsmParser::emitLoadAddressGot(MCInst
&Inst
, SMLoc IDLoc
,
1046 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1047 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
1049 unsigned LD
= is64Bit() ? LoongArch::LD_D
: LoongArch::LD_W
;
1051 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs
)) {
1052 // with feature: +la-glabal-with-abs
1054 // lu12i.w $rd, %got_hi20(sym)
1055 // ori $rd, $rd, %got_lo12(sym)
1059 // lu12i.w $rd, %got_hi20(sym)
1060 // ori $rd, $rd, %got_lo12(sym)
1061 // lu32i.d $rd, %got64_lo20(sym)
1062 // lu52i.d $rd, $rd, %got64_hi12(sym)
1064 Insts
.push_back(LoongArchAsmParser::Inst(
1065 LoongArch::LU12I_W
, LoongArchMCExpr::VK_LoongArch_GOT_HI20
));
1066 Insts
.push_back(LoongArchAsmParser::Inst(
1067 LoongArch::ORI
, LoongArchMCExpr::VK_LoongArch_GOT_LO12
));
1070 Insts
.push_back(LoongArchAsmParser::Inst(
1071 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_LO20
));
1072 Insts
.push_back(LoongArchAsmParser::Inst(
1073 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_HI12
));
1075 Insts
.push_back(LoongArchAsmParser::Inst(LD
));
1076 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
);
1080 // pcalau12i $rd, %got_pc_hi20(sym)
1081 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
1082 Insts
.push_back(LoongArchAsmParser::Inst(
1083 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20
));
1085 LoongArchAsmParser::Inst(LD
, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12
));
1087 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
,
1088 /*RelaxHint=*/true);
1091 void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst
&Inst
, SMLoc IDLoc
,
1093 // la.got $rd, $rj, sym
1095 // pcalau12i $rd, %got_pc_hi20(sym)
1096 // addi.d $rj, $r0, %got_pc_lo12(sym)
1097 // lu32i.d $rj, %got64_pc_lo20(sym)
1098 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1099 // ldx.d $rd, $rd, $rj
1100 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1101 MCRegister TmpReg
= Inst
.getOperand(1).getReg();
1102 const MCExpr
*Symbol
= Inst
.getOperand(2).getExpr();
1105 Insts
.push_back(LoongArchAsmParser::Inst(
1106 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20
));
1107 Insts
.push_back(LoongArchAsmParser::Inst(
1108 LoongArch::ADDI_D
, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12
));
1109 Insts
.push_back(LoongArchAsmParser::Inst(
1110 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20
));
1111 Insts
.push_back(LoongArchAsmParser::Inst(
1112 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12
));
1113 Insts
.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D
));
1115 emitLAInstSeq(DestReg
, TmpReg
, Symbol
, Insts
, IDLoc
, Out
);
1118 void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst
&Inst
, SMLoc IDLoc
,
1120 // la.tls.le $rd, sym
1122 // lu12i.w $rd, %le_hi20(sym)
1123 // ori $rd, $rd, %le_lo12(sym)
1124 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1125 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
1128 Insts
.push_back(LoongArchAsmParser::Inst(
1129 LoongArch::LU12I_W
, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20
));
1130 Insts
.push_back(LoongArchAsmParser::Inst(
1131 LoongArch::ORI
, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12
));
1133 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
);
1136 void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst
&Inst
, SMLoc IDLoc
,
1138 // la.tls.ie $rd, sym
1139 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1140 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
1142 unsigned LD
= is64Bit() ? LoongArch::LD_D
: LoongArch::LD_W
;
1144 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs
)) {
1145 // with feature: +la-glabal-with-abs
1147 // lu12i.w $rd, %ie_hi20(sym)
1148 // ori $rd, $rd, %ie_lo12(sym)
1152 // lu12i.w $rd, %ie_hi20(sym)
1153 // ori $rd, $rd, %ie_lo12(sym)
1154 // lu32i.d $rd, %ie64_lo20(sym)
1155 // lu52i.d $rd, $rd, %ie64_hi12(sym)
1157 Insts
.push_back(LoongArchAsmParser::Inst(
1158 LoongArch::LU12I_W
, LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20
));
1159 Insts
.push_back(LoongArchAsmParser::Inst(
1160 LoongArch::ORI
, LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12
));
1163 Insts
.push_back(LoongArchAsmParser::Inst(
1164 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20
));
1165 Insts
.push_back(LoongArchAsmParser::Inst(
1166 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12
));
1168 Insts
.push_back(LoongArchAsmParser::Inst(LD
));
1169 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
);
1174 // pcalau12i $rd, %ie_pc_hi20(sym)
1175 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
1176 Insts
.push_back(LoongArchAsmParser::Inst(
1177 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20
));
1178 Insts
.push_back(LoongArchAsmParser::Inst(
1179 LD
, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12
));
1181 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
,
1182 /*RelaxHint=*/true);
1185 void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst
&Inst
, SMLoc IDLoc
,
1187 // la.tls.ie $rd, $rj, sym
1189 // pcalau12i $rd, %ie_pc_hi20(sym)
1190 // addi.d $rj, $r0, %ie_pc_lo12(sym)
1191 // lu32i.d $rj, %ie64_pc_lo20(sym)
1192 // lu52i.d $rj, $rj, %ie64_pc_hi12(sym)
1193 // ldx.d $rd, $rd, $rj
1194 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1195 MCRegister TmpReg
= Inst
.getOperand(1).getReg();
1196 const MCExpr
*Symbol
= Inst
.getOperand(2).getExpr();
1199 Insts
.push_back(LoongArchAsmParser::Inst(
1200 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20
));
1201 Insts
.push_back(LoongArchAsmParser::Inst(
1202 LoongArch::ADDI_D
, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12
));
1203 Insts
.push_back(LoongArchAsmParser::Inst(
1204 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20
));
1205 Insts
.push_back(LoongArchAsmParser::Inst(
1206 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12
));
1207 Insts
.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D
));
1209 emitLAInstSeq(DestReg
, TmpReg
, Symbol
, Insts
, IDLoc
, Out
);
1212 void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst
&Inst
, SMLoc IDLoc
,
1214 // la.tls.ld $rd, sym
1215 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1216 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
1218 unsigned ADDI
= is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
1220 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs
)) {
1221 // with feature: +la-glabal-with-abs
1223 // lu12i.w $rd, %ld_hi20(sym)
1224 // ori $rd, $rd, %got_lo12(sym)
1227 // lu12i.w $rd, %ld_hi20(sym)
1228 // ori $rd, $rd, %got_lo12(sym)
1229 // lu32i.d $rd, %got64_lo20(sym)
1230 // lu52i.d $rd, $rd, %got64_hi12(sym)
1231 Insts
.push_back(LoongArchAsmParser::Inst(
1232 LoongArch::LU12I_W
, LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20
));
1233 Insts
.push_back(LoongArchAsmParser::Inst(
1234 LoongArch::ORI
, LoongArchMCExpr::VK_LoongArch_GOT_LO12
));
1237 Insts
.push_back(LoongArchAsmParser::Inst(
1238 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_LO20
));
1239 Insts
.push_back(LoongArchAsmParser::Inst(
1240 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_HI12
));
1242 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
);
1247 // pcalau12i $rd, %ld_pc_hi20(sym)
1248 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1249 Insts
.push_back(LoongArchAsmParser::Inst(
1250 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20
));
1251 Insts
.push_back(LoongArchAsmParser::Inst(
1252 ADDI
, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12
));
1254 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
,
1255 /*RelaxHint=*/true);
1258 void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst
&Inst
, SMLoc IDLoc
,
1260 // la.tls.ld $rd, $rj, sym
1262 // pcalau12i $rd, %ld_pc_hi20(sym)
1263 // addi.d $rj, $r0, %got_pc_lo12(sym)
1264 // lu32i.d $rj, %got64_pc_lo20(sym)
1265 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1266 // add.d $rd, $rd, $rj
1267 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1268 MCRegister TmpReg
= Inst
.getOperand(1).getReg();
1269 const MCExpr
*Symbol
= Inst
.getOperand(2).getExpr();
1272 Insts
.push_back(LoongArchAsmParser::Inst(
1273 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20
));
1274 Insts
.push_back(LoongArchAsmParser::Inst(
1275 LoongArch::ADDI_D
, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12
));
1276 Insts
.push_back(LoongArchAsmParser::Inst(
1277 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20
));
1278 Insts
.push_back(LoongArchAsmParser::Inst(
1279 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12
));
1280 Insts
.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D
));
1282 emitLAInstSeq(DestReg
, TmpReg
, Symbol
, Insts
, IDLoc
, Out
);
1285 void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst
&Inst
, SMLoc IDLoc
,
1287 // la.tls.gd $rd, sym
1288 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1289 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
1291 unsigned ADDI
= is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
1293 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs
)) {
1294 // with feature: +la-glabal-with-abs
1296 // lu12i.w $rd, %gd_hi20(sym)
1297 // ori $rd, $rd, %got_lo12(sym)
1300 // lu12i.w $rd, %gd_hi20(sym)
1301 // ori $rd, $rd, %got_lo12(sym)
1302 // lu32i.d $rd, %got64_lo20(sym)
1303 // lu52i.d $rd, $rd, %got64_hi12(sym)
1304 Insts
.push_back(LoongArchAsmParser::Inst(
1305 LoongArch::LU12I_W
, LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20
));
1306 Insts
.push_back(LoongArchAsmParser::Inst(
1307 LoongArch::ORI
, LoongArchMCExpr::VK_LoongArch_GOT_LO12
));
1310 Insts
.push_back(LoongArchAsmParser::Inst(
1311 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_LO20
));
1312 Insts
.push_back(LoongArchAsmParser::Inst(
1313 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_HI12
));
1315 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
);
1320 // pcalau12i $rd, %gd_pc_hi20(sym)
1321 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1322 Insts
.push_back(LoongArchAsmParser::Inst(
1323 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20
));
1324 Insts
.push_back(LoongArchAsmParser::Inst(
1325 ADDI
, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12
));
1327 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
,
1328 /*RelaxHint=*/true);
1331 void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst
&Inst
, SMLoc IDLoc
,
1333 // la.tls.gd $rd, $rj, sym
1335 // pcalau12i $rd, %gd_pc_hi20(sym)
1336 // addi.d $rj, $r0, %got_pc_lo12(sym)
1337 // lu32i.d $rj, %got64_pc_lo20(sym)
1338 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1339 // add.d $rd, $rd, $rj
1340 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1341 MCRegister TmpReg
= Inst
.getOperand(1).getReg();
1342 const MCExpr
*Symbol
= Inst
.getOperand(2).getExpr();
1345 Insts
.push_back(LoongArchAsmParser::Inst(
1346 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20
));
1347 Insts
.push_back(LoongArchAsmParser::Inst(
1348 LoongArch::ADDI_D
, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12
));
1349 Insts
.push_back(LoongArchAsmParser::Inst(
1350 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20
));
1351 Insts
.push_back(LoongArchAsmParser::Inst(
1352 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12
));
1353 Insts
.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D
));
1355 emitLAInstSeq(DestReg
, TmpReg
, Symbol
, Insts
, IDLoc
, Out
);
1358 void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst
&Inst
, SMLoc IDLoc
,
1360 // la.tls.desc $rd, sym
1361 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1362 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
1363 unsigned ADDI
= is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W
;
1364 unsigned LD
= is64Bit() ? LoongArch::LD_D
: LoongArch::LD_W
;
1367 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs
)) {
1368 // with feature: +la-glabal-with-abs
1369 // for la32 expands to:
1370 // lu12i.w $rd, %desc_hi20(sym)
1371 // ori $rd, $rd, %desc_lo12(sym)
1372 // ld.w $ra, $rd, %desc_ld(sym)
1373 // jirl $ra, $ra, %desc_call(sym)
1375 // for la64 expands to:
1376 // lu12i.w $rd, %desc_hi20(sym)
1377 // ori $rd, $rd, %desc_lo12(sym)
1378 // lu32i.d $rd, %desc64_lo20(sym)
1379 // lu52i.d $rd, $rd, %desc64_hi12(sym)
1380 // ld.d $ra, $rd, %desc_ld(sym)
1381 // jirl $ra, $ra, %desc_call(sym)
1382 Insts
.push_back(LoongArchAsmParser::Inst(
1383 LoongArch::LU12I_W
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20
));
1384 Insts
.push_back(LoongArchAsmParser::Inst(
1385 LoongArch::ORI
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12
));
1388 Insts
.push_back(LoongArchAsmParser::Inst(
1389 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20
));
1390 Insts
.push_back(LoongArchAsmParser::Inst(
1391 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12
));
1394 Insts
.push_back(LoongArchAsmParser::Inst(
1395 LD
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD
));
1396 Insts
.push_back(LoongArchAsmParser::Inst(
1397 LoongArch::JIRL
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL
));
1399 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
);
1404 // pcalau12i $rd, %desc_pc_hi20(sym)
1405 // addi.w/d $rd, $rd, %desc_pc_lo12(sym)
1406 // ld.w/d $ra, $rd, %desc_ld(sym)
1407 // jirl $ra, $ra, %desc_call(sym)
1408 Insts
.push_back(LoongArchAsmParser::Inst(
1409 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20
));
1410 Insts
.push_back(LoongArchAsmParser::Inst(
1411 ADDI
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12
));
1413 LoongArchAsmParser::Inst(LD
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD
));
1414 Insts
.push_back(LoongArchAsmParser::Inst(
1415 LoongArch::JIRL
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL
));
1417 emitLAInstSeq(DestReg
, DestReg
, Symbol
, Insts
, IDLoc
, Out
,
1418 /*RelaxHint=*/true);
1421 void LoongArchAsmParser::emitLoadAddressTLSDescLarge(MCInst
&Inst
, SMLoc IDLoc
,
1423 // la.tls.desc $rd, $rj, sym
1425 // pcalau12i $rd, %desc_pc_hi20(sym)
1426 // addi.d $rj, $r0, %desc_pc_lo12(sym)
1427 // lu32i.d $rj, %desc64_pc_lo20(sym)
1428 // lu52i.d $rj, $rj, %desc64_pc_hi12(sym)
1429 // add.d $rd, $rd, $rj
1430 // ld.w/d $ra, $rd, %desc_ld(sym)
1431 // jirl $ra, $ra, %desc_call(sym)
1432 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1433 MCRegister TmpReg
= Inst
.getOperand(1).getReg();
1434 const MCExpr
*Symbol
= Inst
.getOperand(2).getExpr();
1437 Insts
.push_back(LoongArchAsmParser::Inst(
1438 LoongArch::PCALAU12I
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20
));
1439 Insts
.push_back(LoongArchAsmParser::Inst(
1440 LoongArch::ADDI_D
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12
));
1441 Insts
.push_back(LoongArchAsmParser::Inst(
1442 LoongArch::LU32I_D
, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20
));
1443 Insts
.push_back(LoongArchAsmParser::Inst(
1444 LoongArch::LU52I_D
, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12
));
1445 Insts
.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D
));
1446 Insts
.push_back(LoongArchAsmParser::Inst(
1447 LoongArch::LD_D
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD
));
1448 Insts
.push_back(LoongArchAsmParser::Inst(
1449 LoongArch::JIRL
, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL
));
1451 emitLAInstSeq(DestReg
, TmpReg
, Symbol
, Insts
, IDLoc
, Out
);
1454 void LoongArchAsmParser::emitLoadImm(MCInst
&Inst
, SMLoc IDLoc
,
1456 MCRegister DestReg
= Inst
.getOperand(0).getReg();
1457 int64_t Imm
= Inst
.getOperand(1).getImm();
1458 MCRegister SrcReg
= LoongArch::R0
;
1460 if (Inst
.getOpcode() == LoongArch::PseudoLI_W
)
1461 Imm
= SignExtend64
<32>(Imm
);
1463 for (LoongArchMatInt::Inst
&Inst
: LoongArchMatInt::generateInstSeq(Imm
)) {
1465 case LoongArch::LU12I_W
:
1466 Out
.emitInstruction(
1467 MCInstBuilder(Inst
.Opc
).addReg(DestReg
).addImm(Inst
.Imm
), getSTI());
1469 case LoongArch::ADDI_W
:
1470 case LoongArch::ORI
:
1471 case LoongArch::LU32I_D
:
1472 case LoongArch::LU52I_D
:
1473 Out
.emitInstruction(
1474 MCInstBuilder(Inst
.Opc
).addReg(DestReg
).addReg(SrcReg
).addImm(
1478 case LoongArch::BSTRINS_D
:
1479 Out
.emitInstruction(MCInstBuilder(Inst
.Opc
)
1483 .addImm(Inst
.Imm
>> 32)
1484 .addImm(Inst
.Imm
& 0xFF),
1488 llvm_unreachable("unexpected opcode generated by LoongArchMatInt");
1494 void LoongArchAsmParser::emitFuncCall36(MCInst
&Inst
, SMLoc IDLoc
,
1495 MCStreamer
&Out
, bool IsTailCall
) {
1498 // pcaddu18i $ra, %call36(sym)
1503 // pcaddu18i $rj, %call36(sym)
1505 MCRegister ScratchReg
=
1506 IsTailCall
? Inst
.getOperand(0).getReg() : MCRegister(LoongArch::R1
);
1508 IsTailCall
? Inst
.getOperand(1).getExpr() : Inst
.getOperand(0).getExpr();
1509 const LoongArchMCExpr
*LE
=
1510 LoongArchMCExpr::create(Sym
, llvm::LoongArchMCExpr::VK_LoongArch_CALL36
,
1511 getContext(), /*RelaxHint=*/true);
1513 Out
.emitInstruction(
1514 MCInstBuilder(LoongArch::PCADDU18I
).addReg(ScratchReg
).addExpr(LE
),
1516 Out
.emitInstruction(
1517 MCInstBuilder(LoongArch::JIRL
)
1518 .addReg(IsTailCall
? MCRegister(LoongArch::R0
) : ScratchReg
)
1524 bool LoongArchAsmParser::processInstruction(MCInst
&Inst
, SMLoc IDLoc
,
1525 OperandVector
&Operands
,
1528 switch (Inst
.getOpcode()) {
1531 case LoongArch::PseudoLA_ABS
:
1532 case LoongArch::PseudoLA_ABS_LARGE
:
1533 emitLoadAddressAbs(Inst
, IDLoc
, Out
);
1535 case LoongArch::PseudoLA_PCREL
:
1536 emitLoadAddressPcrel(Inst
, IDLoc
, Out
);
1538 case LoongArch::PseudoLA_PCREL_LARGE
:
1539 emitLoadAddressPcrelLarge(Inst
, IDLoc
, Out
);
1541 case LoongArch::PseudoLA_GOT
:
1542 emitLoadAddressGot(Inst
, IDLoc
, Out
);
1544 case LoongArch::PseudoLA_GOT_LARGE
:
1545 emitLoadAddressGotLarge(Inst
, IDLoc
, Out
);
1547 case LoongArch::PseudoLA_TLS_LE
:
1548 emitLoadAddressTLSLE(Inst
, IDLoc
, Out
);
1550 case LoongArch::PseudoLA_TLS_IE
:
1551 emitLoadAddressTLSIE(Inst
, IDLoc
, Out
);
1553 case LoongArch::PseudoLA_TLS_IE_LARGE
:
1554 emitLoadAddressTLSIELarge(Inst
, IDLoc
, Out
);
1556 case LoongArch::PseudoLA_TLS_LD
:
1557 emitLoadAddressTLSLD(Inst
, IDLoc
, Out
);
1559 case LoongArch::PseudoLA_TLS_LD_LARGE
:
1560 emitLoadAddressTLSLDLarge(Inst
, IDLoc
, Out
);
1562 case LoongArch::PseudoLA_TLS_GD
:
1563 emitLoadAddressTLSGD(Inst
, IDLoc
, Out
);
1565 case LoongArch::PseudoLA_TLS_GD_LARGE
:
1566 emitLoadAddressTLSGDLarge(Inst
, IDLoc
, Out
);
1568 case LoongArch::PseudoLA_TLS_DESC
:
1569 emitLoadAddressTLSDesc(Inst
, IDLoc
, Out
);
1571 case LoongArch::PseudoLA_TLS_DESC_LARGE
:
1572 emitLoadAddressTLSDescLarge(Inst
, IDLoc
, Out
);
1574 case LoongArch::PseudoLI_W
:
1575 case LoongArch::PseudoLI_D
:
1576 emitLoadImm(Inst
, IDLoc
, Out
);
1578 case LoongArch::PseudoCALL36
:
1579 emitFuncCall36(Inst
, IDLoc
, Out
, /*IsTailCall=*/false);
1581 case LoongArch::PseudoTAIL36
:
1582 emitFuncCall36(Inst
, IDLoc
, Out
, /*IsTailCall=*/true);
1585 Out
.emitInstruction(Inst
, getSTI());
1589 unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst
&Inst
) {
1590 unsigned Opc
= Inst
.getOpcode();
1591 const MCInstrDesc
&MCID
= MII
.get(Opc
);
1594 if (LoongArchII::isSubjectToAMORdConstraint(MCID
.TSFlags
)) {
1595 const bool IsAMCAS
= LoongArchII::isAMCAS(MCID
.TSFlags
);
1596 MCRegister Rd
= Inst
.getOperand(0).getReg();
1597 MCRegister Rk
= Inst
.getOperand(IsAMCAS
? 2 : 1).getReg();
1598 MCRegister Rj
= Inst
.getOperand(IsAMCAS
? 3 : 2).getReg();
1599 if ((Rd
== Rk
|| Rd
== Rj
) && Rd
!= LoongArch::R0
)
1600 return Match_RequiresAMORdDifferRkRj
;
1603 case LoongArch::PseudoLA_TLS_DESC
:
1604 case LoongArch::PseudoLA_TLS_DESC_LARGE
: {
1605 MCRegister Rd
= Inst
.getOperand(0).getReg();
1606 if (Rd
!= LoongArch::R4
)
1607 return Match_RequiresLAORdR4
;
1610 case LoongArch::PseudoLA_PCREL_LARGE
:
1611 case LoongArch::PseudoLA_GOT_LARGE
:
1612 case LoongArch::PseudoLA_TLS_IE_LARGE
:
1613 case LoongArch::PseudoLA_TLS_LD_LARGE
:
1614 case LoongArch::PseudoLA_TLS_GD_LARGE
: {
1615 MCRegister Rd
= Inst
.getOperand(0).getReg();
1616 MCRegister Rj
= Inst
.getOperand(1).getReg();
1618 return Match_RequiresLAORdDifferRj
;
1621 case LoongArch::CSRXCHG
:
1622 case LoongArch::GCSRXCHG
: {
1623 MCRegister Rj
= Inst
.getOperand(2).getReg();
1624 if (Rj
== LoongArch::R0
|| Rj
== LoongArch::R1
)
1625 return Match_RequiresOpnd2NotR0R1
;
1626 return Match_Success
;
1628 case LoongArch::BSTRINS_W
:
1629 case LoongArch::BSTRINS_D
:
1630 case LoongArch::BSTRPICK_W
:
1631 case LoongArch::BSTRPICK_D
: {
1632 unsigned Opc
= Inst
.getOpcode();
1634 (Opc
== LoongArch::BSTRINS_W
|| Opc
== LoongArch::BSTRINS_D
)
1635 ? Inst
.getOperand(3).getImm()
1636 : Inst
.getOperand(2).getImm();
1638 (Opc
== LoongArch::BSTRINS_W
|| Opc
== LoongArch::BSTRINS_D
)
1639 ? Inst
.getOperand(4).getImm()
1640 : Inst
.getOperand(3).getImm();
1642 return Match_RequiresMsbNotLessThanLsb
;
1643 return Match_Success
;
1647 return Match_Success
;
1651 LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand
&AsmOp
,
1653 LoongArchOperand
&Op
= static_cast<LoongArchOperand
&>(AsmOp
);
1655 return Match_InvalidOperand
;
1657 MCRegister Reg
= Op
.getReg();
1658 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1659 // register from FPR32 to FPR64 if necessary.
1660 if (LoongArchMCRegisterClasses
[LoongArch::FPR32RegClassID
].contains(Reg
) &&
1661 Kind
== MCK_FPR64
) {
1662 Op
.setReg(convertFPR32ToFPR64(Reg
));
1663 return Match_Success
;
1666 return Match_InvalidOperand
;
1669 bool LoongArchAsmParser::generateImmOutOfRangeError(
1670 OperandVector
&Operands
, uint64_t ErrorInfo
, int64_t Lower
, int64_t Upper
,
1671 const Twine
&Msg
= "immediate must be an integer in the range") {
1672 SMLoc ErrorLoc
= ((LoongArchOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1673 return Error(ErrorLoc
, Msg
+ " [" + Twine(Lower
) + ", " + Twine(Upper
) + "]");
1676 bool LoongArchAsmParser::matchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
1677 OperandVector
&Operands
,
1679 uint64_t &ErrorInfo
,
1680 bool MatchingInlineAsm
) {
1682 FeatureBitset MissingFeatures
;
1684 auto Result
= MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MissingFeatures
,
1690 return processInstruction(Inst
, IDLoc
, Operands
, Out
);
1691 case Match_MissingFeature
: {
1692 assert(MissingFeatures
.any() && "Unknown missing features!");
1693 bool FirstFeature
= true;
1694 std::string Msg
= "instruction requires the following:";
1695 for (unsigned i
= 0, e
= MissingFeatures
.size(); i
!= e
; ++i
) {
1696 if (MissingFeatures
[i
]) {
1697 Msg
+= FirstFeature
? " " : ", ";
1698 Msg
+= getSubtargetFeatureName(i
);
1699 FirstFeature
= false;
1702 return Error(IDLoc
, Msg
);
1704 case Match_MnemonicFail
: {
1705 FeatureBitset FBS
= ComputeAvailableFeatures(getSTI().getFeatureBits());
1706 std::string Suggestion
= LoongArchMnemonicSpellCheck(
1707 ((LoongArchOperand
&)*Operands
[0]).getToken(), FBS
, 0);
1708 return Error(IDLoc
, "unrecognized instruction mnemonic" + Suggestion
);
1710 case Match_InvalidOperand
: {
1711 SMLoc ErrorLoc
= IDLoc
;
1712 if (ErrorInfo
!= ~0ULL) {
1713 if (ErrorInfo
>= Operands
.size())
1714 return Error(ErrorLoc
, "too few operands for instruction");
1716 ErrorLoc
= ((LoongArchOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1717 if (ErrorLoc
== SMLoc())
1720 return Error(ErrorLoc
, "invalid operand for instruction");
1724 // Handle the case when the error message is of specific type
1725 // other than the generic Match_InvalidOperand, and the
1726 // corresponding operand is missing.
1727 if (Result
> FIRST_TARGET_MATCH_RESULT_TY
) {
1728 SMLoc ErrorLoc
= IDLoc
;
1729 if (ErrorInfo
!= ~0ULL && ErrorInfo
>= Operands
.size())
1730 return Error(ErrorLoc
, "too few operands for instruction");
1736 case Match_RequiresMsbNotLessThanLsb
: {
1737 SMLoc ErrorStart
= Operands
[3]->getStartLoc();
1738 return Error(ErrorStart
, "msb is less than lsb",
1739 SMRange(ErrorStart
, Operands
[4]->getEndLoc()));
1741 case Match_RequiresOpnd2NotR0R1
:
1742 return Error(Operands
[2]->getStartLoc(), "must not be $r0 or $r1");
1743 case Match_RequiresAMORdDifferRkRj
:
1744 return Error(Operands
[1]->getStartLoc(),
1745 "$rd must be different from both $rk and $rj");
1746 case Match_RequiresLAORdDifferRj
:
1747 return Error(Operands
[1]->getStartLoc(), "$rd must be different from $rj");
1748 case Match_RequiresLAORdR4
:
1749 return Error(Operands
[1]->getStartLoc(), "$rd must be $r4");
1750 case Match_InvalidUImm1
:
1751 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1752 /*Upper=*/(1 << 1) - 1);
1753 case Match_InvalidUImm2
:
1754 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1755 /*Upper=*/(1 << 2) - 1);
1756 case Match_InvalidUImm2plus1
:
1757 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/1,
1758 /*Upper=*/(1 << 2));
1759 case Match_InvalidUImm3
:
1760 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1761 /*Upper=*/(1 << 3) - 1);
1762 case Match_InvalidUImm4
:
1763 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1764 /*Upper=*/(1 << 4) - 1);
1765 case Match_InvalidUImm5
:
1766 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1767 /*Upper=*/(1 << 5) - 1);
1768 case Match_InvalidUImm6
:
1769 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1770 /*Upper=*/(1 << 6) - 1);
1771 case Match_InvalidUImm7
:
1772 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1773 /*Upper=*/(1 << 7) - 1);
1774 case Match_InvalidUImm8
:
1775 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1776 /*Upper=*/(1 << 8) - 1);
1777 case Match_InvalidUImm12
:
1778 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1779 /*Upper=*/(1 << 12) - 1);
1780 case Match_InvalidUImm12ori
:
1781 return generateImmOutOfRangeError(
1782 Operands
, ErrorInfo
, /*Lower=*/0,
1783 /*Upper=*/(1 << 12) - 1,
1784 "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
1785 "integer in the range");
1786 case Match_InvalidUImm14
:
1787 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1788 /*Upper=*/(1 << 14) - 1);
1789 case Match_InvalidUImm15
:
1790 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/0,
1791 /*Upper=*/(1 << 15) - 1);
1792 case Match_InvalidSImm5
:
1793 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/-(1 << 4),
1794 /*Upper=*/(1 << 4) - 1);
1795 case Match_InvalidSImm8
:
1796 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/-(1 << 7),
1797 /*Upper=*/(1 << 7) - 1);
1798 case Match_InvalidSImm8lsl1
:
1799 return generateImmOutOfRangeError(
1800 Operands
, ErrorInfo
, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,
1801 "immediate must be a multiple of 2 in the range");
1802 case Match_InvalidSImm8lsl2
:
1803 return generateImmOutOfRangeError(
1804 Operands
, ErrorInfo
, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,
1805 "immediate must be a multiple of 4 in the range");
1806 case Match_InvalidSImm10
:
1807 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/-(1 << 9),
1808 /*Upper=*/(1 << 9) - 1);
1809 case Match_InvalidSImm8lsl3
:
1810 return generateImmOutOfRangeError(
1811 Operands
, ErrorInfo
, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,
1812 "immediate must be a multiple of 8 in the range");
1813 case Match_InvalidSImm9lsl3
:
1814 return generateImmOutOfRangeError(
1815 Operands
, ErrorInfo
, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,
1816 "immediate must be a multiple of 8 in the range");
1817 case Match_InvalidSImm10lsl2
:
1818 return generateImmOutOfRangeError(
1819 Operands
, ErrorInfo
, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,
1820 "immediate must be a multiple of 4 in the range");
1821 case Match_InvalidSImm11lsl1
:
1822 return generateImmOutOfRangeError(
1823 Operands
, ErrorInfo
, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,
1824 "immediate must be a multiple of 2 in the range");
1825 case Match_InvalidSImm12
:
1826 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/-(1 << 11),
1827 /*Upper=*/(1 << 11) - 1);
1828 case Match_InvalidSImm12addlike
:
1829 return generateImmOutOfRangeError(
1830 Operands
, ErrorInfo
, /*Lower=*/-(1 << 11),
1831 /*Upper=*/(1 << 11) - 1,
1832 "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
1834 case Match_InvalidSImm12lu52id
:
1835 return generateImmOutOfRangeError(
1836 Operands
, ErrorInfo
, /*Lower=*/-(1 << 11),
1837 /*Upper=*/(1 << 11) - 1,
1838 "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
1839 "integer in the range");
1840 case Match_InvalidSImm13
:
1841 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/-(1 << 12),
1842 /*Upper=*/(1 << 12) - 1);
1843 case Match_InvalidSImm14lsl2
:
1844 return generateImmOutOfRangeError(
1845 Operands
, ErrorInfo
, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
1846 "immediate must be a multiple of 4 in the range");
1847 case Match_InvalidSImm16
:
1848 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/-(1 << 15),
1849 /*Upper=*/(1 << 15) - 1);
1850 case Match_InvalidSImm16lsl2
:
1851 return generateImmOutOfRangeError(
1852 Operands
, ErrorInfo
, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
1853 "operand must be a symbol with modifier (e.g. %b16) or an integer "
1855 case Match_InvalidSImm20
:
1856 return generateImmOutOfRangeError(Operands
, ErrorInfo
, /*Lower=*/-(1 << 19),
1857 /*Upper=*/(1 << 19) - 1);
1858 case Match_InvalidSImm20lu12iw
:
1859 return generateImmOutOfRangeError(
1860 Operands
, ErrorInfo
, /*Lower=*/-(1 << 19),
1861 /*Upper=*/(1 << 19) - 1,
1862 "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
1864 case Match_InvalidSImm20lu32id
:
1865 return generateImmOutOfRangeError(
1866 Operands
, ErrorInfo
, /*Lower=*/-(1 << 19),
1867 /*Upper=*/(1 << 19) - 1,
1868 "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
1869 "integer in the range");
1870 case Match_InvalidSImm20pcalau12i
:
1871 return generateImmOutOfRangeError(
1872 Operands
, ErrorInfo
, /*Lower=*/-(1 << 19),
1873 /*Upper=*/(1 << 19) - 1,
1874 "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
1876 case Match_InvalidSImm20pcaddu18i
:
1877 return generateImmOutOfRangeError(
1878 Operands
, ErrorInfo
, /*Lower=*/-(1 << 19),
1879 /*Upper=*/(1 << 19) - 1,
1880 "operand must be a symbol with modifier (e.g. %call36) or an integer "
1882 case Match_InvalidSImm20pcaddi
:
1883 return generateImmOutOfRangeError(
1884 Operands
, ErrorInfo
, /*Lower=*/-(1 << 19),
1885 /*Upper=*/(1 << 19) - 1,
1886 "operand must be a symbol with modifier (e.g. %pcrel_20) or an integer "
1888 case Match_InvalidSImm21lsl2
:
1889 return generateImmOutOfRangeError(
1890 Operands
, ErrorInfo
, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
1891 "operand must be a symbol with modifier (e.g. %b21) or an integer "
1893 case Match_InvalidSImm26Operand
:
1894 return generateImmOutOfRangeError(
1895 Operands
, ErrorInfo
, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
1896 "operand must be a bare symbol name or an immediate must be a multiple "
1897 "of 4 in the range");
1898 case Match_InvalidImm32
: {
1899 SMLoc ErrorLoc
= ((LoongArchOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1900 return Error(ErrorLoc
, "operand must be a 32 bit immediate");
1902 case Match_InvalidImm64
: {
1903 SMLoc ErrorLoc
= ((LoongArchOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1904 return Error(ErrorLoc
, "operand must be a 64 bit immediate");
1906 case Match_InvalidBareSymbol
: {
1907 SMLoc ErrorLoc
= ((LoongArchOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1908 return Error(ErrorLoc
, "operand must be a bare symbol name");
1910 case Match_InvalidTPRelAddSymbol
: {
1911 SMLoc ErrorLoc
= ((LoongArchOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1912 return Error(ErrorLoc
, "operand must be a symbol with %le_add_r modifier");
1915 llvm_unreachable("Unknown match type detected!");
1918 bool LoongArchAsmParser::parseDirectiveOption() {
1919 MCAsmParser
&Parser
= getParser();
1920 // Get the option token.
1921 AsmToken Tok
= Parser
.getTok();
1923 // At the moment only identifiers are supported.
1924 if (parseToken(AsmToken::Identifier
, "expected identifier"))
1927 StringRef Option
= Tok
.getIdentifier();
1929 if (Option
== "push") {
1930 if (Parser
.parseEOL())
1933 getTargetStreamer().emitDirectiveOptionPush();
1938 if (Option
== "pop") {
1939 SMLoc StartLoc
= Parser
.getTok().getLoc();
1940 if (Parser
.parseEOL())
1943 getTargetStreamer().emitDirectiveOptionPop();
1944 if (popFeatureBits())
1945 return Error(StartLoc
, ".option pop with no .option push");
1950 if (Option
== "relax") {
1951 if (Parser
.parseEOL())
1954 getTargetStreamer().emitDirectiveOptionRelax();
1955 setFeatureBits(LoongArch::FeatureRelax
, "relax");
1959 if (Option
== "norelax") {
1960 if (Parser
.parseEOL())
1963 getTargetStreamer().emitDirectiveOptionNoRelax();
1964 clearFeatureBits(LoongArch::FeatureRelax
, "relax");
1969 Warning(Parser
.getTok().getLoc(),
1970 "unknown option, expected 'push', 'pop', 'relax' or 'norelax'");
1971 Parser
.eatToEndOfStatement();
1975 ParseStatus
LoongArchAsmParser::parseDirective(AsmToken DirectiveID
) {
1976 if (DirectiveID
.getString() == ".option")
1977 return parseDirectiveOption();
1979 return ParseStatus::NoMatch
;
1982 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeLoongArchAsmParser() {
1983 RegisterMCAsmParser
<LoongArchAsmParser
> X(getTheLoongArch32Target());
1984 RegisterMCAsmParser
<LoongArchAsmParser
> Y(getTheLoongArch64Target());