25 #define DEBUG_TYPE "loongarch-asm-parser"
29 SMLoc getLoc()
const {
return getParser().getTok().getLoc(); }
32 bool ParseRegister(
unsigned &RegNo,
SMLoc &StartLoc,
SMLoc &EndLoc)
override;
34 SMLoc &EndLoc)
override;
39 bool ParseDirective(
AsmToken DirectiveID)
override {
return true; }
41 bool MatchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
44 bool MatchingInlineAsm)
override;
46 unsigned checkTargetMatchPredicate(
MCInst &Inst)
override;
49 unsigned Kind)
override;
60 #define GET_ASSEMBLER_HEADER
61 #include "LoongArchGenAsmMatcher.inc"
69 enum LoongArchMatchResultTy {
70 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
71 Match_RequiresMsbNotLessThanLsb,
72 Match_RequiresOpnd2NotR0R1,
73 #define GET_OPERAND_DIAGNOSTIC_TYPES
74 #include "LoongArchGenAsmMatcher.inc"
75 #undef GET_OPERAND_DIAGNOSTIC_TYPES
87 setAvailableFeatures(ComputeAvailableFeatures(STI.
getFeatureBits()));
107 SMLoc StartLoc, EndLoc;
117 bool isToken()
const override {
return Kind == KindTy::Token; }
119 bool isImm()
const override {
return Kind == KindTy::Immediate; }
120 bool isMem()
const override {
return false; }
123 static bool evaluateConstantImm(
const MCExpr *Expr, int64_t &
Imm) {
124 if (
auto CE = dyn_cast<MCConstantExpr>(Expr)) {
125 Imm =
CE->getValue();
132 template <
unsigned N,
int P = 0>
bool isUImm()
const {
137 bool IsConstantImm = evaluateConstantImm(getImm(),
Imm);
138 return IsConstantImm && isUInt<N>(
Imm -
P);
141 template <
unsigned N,
unsigned S = 0>
bool isSImm()
const {
146 bool IsConstantImm = evaluateConstantImm(getImm(),
Imm);
147 return IsConstantImm && isShiftedInt<N, S>(
Imm);
150 bool isUImm2()
const {
return isUImm<2>(); }
151 bool isUImm2plus1()
const {
return isUImm<2, 1>(); }
152 bool isUImm3()
const {
return isUImm<3>(); }
153 bool isUImm5()
const {
return isUImm<5>(); }
154 bool isUImm6()
const {
return isUImm<6>(); }
155 bool isUImm8()
const {
return isUImm<8>(); }
156 bool isUImm12()
const {
return isUImm<12>(); }
157 bool isUImm14()
const {
return isUImm<14>(); }
158 bool isUImm15()
const {
return isUImm<15>(); }
159 bool isSImm12()
const {
return isSImm<12>(); }
160 bool isSImm14lsl2()
const {
return isSImm<14, 2>(); }
161 bool isSImm16()
const {
return isSImm<16>(); }
162 bool isSImm16lsl2()
const {
return isSImm<16, 2>(); }
163 bool isSImm20()
const {
return isSImm<20>(); }
164 bool isSImm21lsl2()
const {
return isSImm<21, 2>(); }
165 bool isSImm26lsl2()
const {
return isSImm<26, 2>(); }
168 SMLoc getStartLoc()
const override {
return StartLoc; }
170 SMLoc getEndLoc()
const override {
return EndLoc; }
172 unsigned getReg()
const override {
174 return Reg.RegNum.id();
177 const MCExpr *getImm()
const {
178 assert(
Kind == KindTy::Immediate &&
"Invalid type access!");
183 assert(
Kind == KindTy::Token &&
"Invalid type access!");
196 case KindTy::Immediate:
203 OS <<
"'" << getToken() <<
"'";
208 static std::unique_ptr<LoongArchOperand> createToken(
StringRef Str,
SMLoc S) {
209 auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);
216 static std::unique_ptr<LoongArchOperand> createReg(
unsigned RegNo,
SMLoc S,
219 Op->Reg.RegNum = RegNo;
225 static std::unique_ptr<LoongArchOperand> createImm(
const MCExpr *Val,
SMLoc S,
227 auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);
235 if (
auto CE = dyn_cast<MCConstantExpr>(Expr))
242 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
243 assert(
N == 1 &&
"Invalid number of operands!");
246 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
247 assert(
N == 1 &&
"Invalid number of operands!");
248 addExpr(Inst, getImm());
253 #define GET_REGISTER_MATCHER
254 #define GET_SUBTARGET_FEATURE_NAME
255 #define GET_MATCHER_IMPLEMENTATION
256 #define GET_MNEMONIC_SPELL_CHECKER
257 #include "LoongArchGenAsmMatcher.inc"
260 assert(
Reg >= LoongArch::F0 &&
Reg <= LoongArch::F31 &&
"Invalid register");
261 return Reg - LoongArch::F0 + LoongArch::F0_64;
271 assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
273 static_assert(LoongArch::F0 < LoongArch::F0_64,
274 "FPR matching must be updated");
275 if (RegNo == LoongArch::NoRegister)
278 return RegNo == LoongArch::NoRegister;
281 bool LoongArchAsmParser::ParseRegister(
unsigned &RegNo,
SMLoc &StartLoc,
283 return Error(getLoc(),
"invalid register number");
305 if (RegNo == LoongArch::NoRegister)
311 Operands.push_back(LoongArchOperand::createReg(RegNo,
S,
E));
322 if (getParser().parseExpression(Res,
E))
325 Operands.push_back(LoongArchOperand::createImm(Res,
S,
E));
338 Error(getLoc(),
"unknown operand");
346 Operands.push_back(LoongArchOperand::createToken(
Name, NameLoc));
365 SMLoc Loc = getLexer().getLoc();
366 getParser().eatToEndOfStatement();
367 return Error(Loc,
"unexpected token");
370 bool LoongArchAsmParser::processInstruction(
MCInst &Inst,
SMLoc IDLoc,
378 unsigned LoongArchAsmParser::checkTargetMatchPredicate(
MCInst &Inst) {
382 case LoongArch::CSRXCHG: {
384 if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
385 return Match_RequiresOpnd2NotR0R1;
386 return Match_Success;
388 case LoongArch::BSTRINS_W:
389 case LoongArch::BSTRINS_D:
390 case LoongArch::BSTRPICK_W:
391 case LoongArch::BSTRPICK_D: {
394 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
398 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
402 return Match_RequiresMsbNotLessThanLsb;
403 return Match_Success;
407 return Match_Success;
413 LoongArchOperand &
Op =
static_cast<LoongArchOperand &
>(AsmOp);
415 return Match_InvalidOperand;
420 if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].
contains(
Reg) &&
423 return Match_Success;
426 return Match_InvalidOperand;
429 bool LoongArchAsmParser::generateImmOutOfRangeError(
431 Twine Msg =
"immediate must be an integer in the range") {
436 bool LoongArchAsmParser::MatchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
440 bool MatchingInlineAsm) {
450 return processInstruction(Inst, IDLoc,
Operands, Out);
451 case Match_MissingFeature: {
452 assert(MissingFeatures.
any() &&
"Unknown missing features!");
453 bool FirstFeature =
true;
454 std::string
Msg =
"instruction requires the following:";
455 for (
unsigned i = 0,
e = MissingFeatures.
size();
i !=
e; ++
i) {
456 if (MissingFeatures[
i]) {
457 Msg += FirstFeature ?
" " :
", ";
459 FirstFeature =
false;
464 case Match_MnemonicFail: {
465 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
466 std::string Suggestion = LoongArchMnemonicSpellCheck(
467 ((LoongArchOperand &)*
Operands[0]).getToken(), FBS, 0);
468 return Error(IDLoc,
"unrecognized instruction mnemonic" + Suggestion);
470 case Match_InvalidOperand: {
471 SMLoc ErrorLoc = IDLoc;
474 return Error(ErrorLoc,
"too few operands for instruction");
477 if (ErrorLoc ==
SMLoc())
480 return Error(ErrorLoc,
"invalid operand for instruction");
487 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
488 SMLoc ErrorLoc = IDLoc;
490 return Error(ErrorLoc,
"too few operands for instruction");
496 case Match_RequiresMsbNotLessThanLsb: {
498 return Error(ErrorStart,
"msb is less than lsb",
501 case Match_RequiresOpnd2NotR0R1:
502 return Error(
Operands[2]->getStartLoc(),
"must not be $r0 or $r1");
503 case Match_InvalidUImm2:
506 case Match_InvalidUImm2plus1:
509 case Match_InvalidUImm3:
512 case Match_InvalidUImm5:
515 case Match_InvalidUImm6:
518 case Match_InvalidUImm12:
521 case Match_InvalidUImm15:
524 case Match_InvalidSImm12:
527 case Match_InvalidSImm14lsl2:
528 return generateImmOutOfRangeError(
530 "immediate must be a multiple of 4 in the range");
531 case Match_InvalidSImm16:
534 case Match_InvalidSImm16lsl2:
535 return generateImmOutOfRangeError(
537 "immediate must be a multiple of 4 in the range");
538 case Match_InvalidSImm20:
541 case Match_InvalidSImm21lsl2:
542 return generateImmOutOfRangeError(
544 "immediate must be a multiple of 4 in the range");
545 case Match_InvalidSImm26lsl2:
546 return generateImmOutOfRangeError(
548 "immediate must be a multiple of 4 in the range");