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