LLVM 24.0.0git
CSKYAsmParser.cpp
Go to the documentation of this file.
1//===---- CSKYAsmParser.cpp - Parse CSKY assembly to MCInst instructions --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
14#include "llvm/ADT/STLExtras.h"
15#include "llvm/ADT/Statistic.h"
20#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCExpr.h"
22#include "llvm/MC/MCInst.h"
23#include "llvm/MC/MCInstrInfo.h"
29#include "llvm/MC/MCStreamer.h"
35#include "llvm/Support/Debug.h"
37
38using namespace llvm;
39
40#define DEBUG_TYPE "csky-asm-parser"
41
42// Include the auto-generated portion of the compress emitter.
43#define GEN_COMPRESS_INSTR
44#include "CSKYGenCompressInstEmitter.inc"
45
46STATISTIC(CSKYNumInstrsCompressed,
47 "Number of C-SKY Compressed instructions emitted");
48
49static cl::opt<bool>
50 EnableCompressedInst("enable-csky-asm-compressed-inst", cl::Hidden,
51 cl::init(false),
52 cl::desc("Enable C-SKY asm compressed instruction"));
53
54static cl::opt<bool> AddBuildAttributes("csky-add-build-attributes",
55 cl::init(true));
56
57namespace {
58struct CSKYOperand;
59
60class CSKYAsmParser : public MCTargetAsmParser {
61
62 const MCRegisterInfo *MRI;
63
64 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
65 unsigned Kind) override;
66
67 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
68 int64_t Lower, int64_t Upper,
69 const Twine &Msg);
70
71 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
72
73 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
74 OperandVector &Operands, MCStreamer &Out,
75 uint64_t &ErrorInfo,
76 bool MatchingInlineAsm) override;
77
78 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
79
80 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
81 SMLoc NameLoc, OperandVector &Operands) override;
82
83 ParseStatus parseDirective(AsmToken DirectiveID) override;
84
85 // Helper to actually emit an instruction to the MCStreamer. Also, when
86 // possible, compression of the instruction is performed.
87 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
88
89 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
90 SMLoc &EndLoc) override;
91
92 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
93 MCStreamer &Out);
94 bool processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
95 bool processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
96 bool processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
97
98 CSKYTargetStreamer &getTargetStreamer() {
99 assert(getParser().getStreamer().getTargetStreamer() &&
100 "do not have a target streamer");
101 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
102 return static_cast<CSKYTargetStreamer &>(TS);
103 }
104
105// Auto-generated instruction matching functions
106#define GET_ASSEMBLER_HEADER
107#include "CSKYGenAsmMatcher.inc"
108
110 ParseStatus parseRegister(OperandVector &Operands);
111 ParseStatus parseBaseRegImm(OperandVector &Operands);
112 ParseStatus parseCSKYSymbol(OperandVector &Operands);
113 ParseStatus parseConstpoolSymbol(OperandVector &Operands);
114 ParseStatus parseDataSymbol(OperandVector &Operands);
115 ParseStatus parsePSRFlag(OperandVector &Operands);
116 ParseStatus parseRegSeq(OperandVector &Operands);
117 ParseStatus parseRegList(OperandVector &Operands);
118
119 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
120
121 bool parseDirectiveAttribute();
122
123public:
124 enum CSKYMatchResultTy {
125 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
126 Match_RequiresSameSrcAndDst,
127 Match_InvalidRegOutOfRange,
128#define GET_OPERAND_DIAGNOSTIC_TYPES
129#include "CSKYGenAsmMatcher.inc"
130#undef GET_OPERAND_DIAGNOSTIC_TYPES
131 };
132
133 CSKYAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
134 const MCInstrInfo &MII)
135 : MCTargetAsmParser(STI, MII) {
136
138
139 // Cache the MCRegisterInfo.
140 MRI = getContext().getRegisterInfo();
141
142 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
144 getTargetStreamer().emitTargetAttributes(STI, /*HardFloatABI=*/false);
145 }
146};
147
148/// Instances of this class represent a parsed machine instruction.
149struct CSKYOperand : public MCParsedAsmOperand {
150
151 enum KindTy {
152 Token,
153 Register,
154 Immediate,
155 RegisterSeq,
156 CPOP,
157 RegisterList
158 } Kind;
159
160 struct RegOp {
161 MCRegister RegNum;
162 };
163
164 struct ImmOp {
165 const MCExpr *Val;
166 };
167
168 struct ConstpoolOp {
169 const MCExpr *Val;
170 };
171
172 struct RegSeqOp {
173 MCRegister RegNumFrom;
174 MCRegister RegNumTo;
175 };
176
177 struct RegListOp {
178 MCRegister List1From;
179 MCRegister List1To;
180 MCRegister List2From;
181 MCRegister List2To;
182 MCRegister List3From;
183 MCRegister List3To;
184 MCRegister List4From;
185 MCRegister List4To;
186 };
187
188 SMLoc StartLoc, EndLoc;
189 union {
190 StringRef Tok;
191 RegOp Reg;
192 ImmOp Imm;
193 ConstpoolOp CPool;
194 RegSeqOp RegSeq;
195 RegListOp RegList;
196 };
197
198 CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
199
200public:
201 CSKYOperand(const CSKYOperand &o) : MCParsedAsmOperand() {
202 Kind = o.Kind;
203 StartLoc = o.StartLoc;
204 EndLoc = o.EndLoc;
205 switch (Kind) {
206 case Register:
207 Reg = o.Reg;
208 break;
209 case RegisterSeq:
210 RegSeq = o.RegSeq;
211 break;
212 case CPOP:
213 CPool = o.CPool;
214 break;
215 case Immediate:
216 Imm = o.Imm;
217 break;
218 case Token:
219 Tok = o.Tok;
220 break;
221 case RegisterList:
222 RegList = o.RegList;
223 break;
224 }
225 }
226
227 bool isToken() const override { return Kind == Token; }
228 bool isReg() const override { return Kind == Register; }
229 bool isImm() const override { return Kind == Immediate; }
230 bool isRegisterSeq() const { return Kind == RegisterSeq; }
231 bool isRegisterList() const { return Kind == RegisterList; }
232 bool isConstPoolOp() const { return Kind == CPOP; }
233
234 bool isMem() const override { return false; }
235
236 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
237 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
238 Imm = CE->getValue();
239 return true;
240 }
241
242 return false;
243 }
244
245 template <unsigned num, unsigned shift = 0> bool isUImm() const {
246 if (!isImm())
247 return false;
248
249 int64_t Imm;
250 bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
251 return IsConstantImm && isShiftedUInt<num, shift>(Imm);
252 }
253
254 template <unsigned num> bool isOImm() const {
255 if (!isImm())
256 return false;
257
258 int64_t Imm;
259 bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
260 return IsConstantImm && isUInt<num>(Imm - 1);
261 }
262
263 template <unsigned num, unsigned shift = 0> bool isSImm() const {
264 if (!isImm())
265 return false;
266
267 int64_t Imm;
268 bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
269 return IsConstantImm && isShiftedInt<num, shift>(Imm);
270 }
271
272 bool isUImm1() const { return isUImm<1>(); }
273 bool isUImm2() const { return isUImm<2>(); }
274 bool isUImm3() const { return isUImm<3>(); }
275 bool isUImm4() const { return isUImm<4>(); }
276 bool isUImm5() const { return isUImm<5>(); }
277 bool isUImm6() const { return isUImm<6>(); }
278 bool isUImm7() const { return isUImm<7>(); }
279 bool isUImm8() const { return isUImm<8>(); }
280 bool isUImm12() const { return isUImm<12>(); }
281 bool isUImm16() const { return isUImm<16>(); }
282 bool isUImm20() const { return isUImm<20>(); }
283 bool isUImm24() const { return isUImm<24>(); }
284
285 bool isOImm3() const { return isOImm<3>(); }
286 bool isOImm4() const { return isOImm<4>(); }
287 bool isOImm5() const { return isOImm<5>(); }
288 bool isOImm6() const { return isOImm<6>(); }
289 bool isOImm8() const { return isOImm<8>(); }
290 bool isOImm12() const { return isOImm<12>(); }
291 bool isOImm16() const { return isOImm<16>(); }
292
293 bool isSImm8() const { return isSImm<8>(); }
294
295 bool isUImm5Shift1() { return isUImm<5, 1>(); }
296 bool isUImm5Shift2() { return isUImm<5, 2>(); }
297 bool isUImm7Shift1() { return isUImm<7, 1>(); }
298 bool isUImm7Shift2() { return isUImm<7, 2>(); }
299 bool isUImm7Shift3() { return isUImm<7, 3>(); }
300 bool isUImm8Shift2() { return isUImm<8, 2>(); }
301 bool isUImm8Shift3() { return isUImm<8, 3>(); }
302 bool isUImm8Shift8() { return isUImm<8, 8>(); }
303 bool isUImm8Shift16() { return isUImm<8, 16>(); }
304 bool isUImm8Shift24() { return isUImm<8, 24>(); }
305 bool isUImm12Shift1() { return isUImm<12, 1>(); }
306 bool isUImm12Shift2() { return isUImm<12, 2>(); }
307 bool isUImm16Shift8() { return isUImm<16, 8>(); }
308 bool isUImm16Shift16() { return isUImm<16, 16>(); }
309 bool isUImm24Shift8() { return isUImm<24, 8>(); }
310
311 bool isSImm16Shift1() { return isSImm<16, 1>(); }
312
313 bool isCSKYSymbol() const { return isImm(); }
314
315 bool isConstpool() const { return isConstPoolOp(); }
316 bool isDataSymbol() const { return isConstPoolOp(); }
317
318 bool isPSRFlag() const {
319 int64_t Imm;
320 // Must be of 'immediate' type and a constant.
321 if (!isImm() || !evaluateConstantImm(getImm(), Imm))
322 return false;
323
324 return isUInt<5>(Imm);
325 }
326
327 template <unsigned MIN, unsigned MAX> bool isRegSeqTemplate() const {
328 if (!isRegisterSeq())
329 return false;
330
331 std::pair<unsigned, unsigned> regSeq = getRegSeq();
332
333 return MIN <= regSeq.first && regSeq.first <= regSeq.second &&
334 regSeq.second <= MAX;
335 }
336
337 bool isRegSeq() const { return isRegSeqTemplate<CSKY::R0, CSKY::R31>(); }
338
339 bool isRegSeqV1() const {
340 return isRegSeqTemplate<CSKY::F0_32, CSKY::F15_32>();
341 }
342
343 bool isRegSeqV2() const {
344 return isRegSeqTemplate<CSKY::F0_32, CSKY::F31_32>();
345 }
346
347 static bool isLegalRegList(unsigned from, unsigned to) {
348 if (from == 0 && to == 0)
349 return true;
350
351 if (from == to) {
352 if (from != CSKY::R4 && from != CSKY::R15 && from != CSKY::R16 &&
353 from != CSKY::R28)
354 return false;
355
356 return true;
357 } else {
358 if (from != CSKY::R4 && from != CSKY::R16)
359 return false;
360
361 if (from == CSKY::R4 && to > CSKY::R4 && to < CSKY::R12)
362 return true;
363 else if (from == CSKY::R16 && to > CSKY::R16 && to < CSKY::R18)
364 return true;
365 else
366 return false;
367 }
368 }
369
370 bool isRegList() const {
371 if (!isRegisterList())
372 return false;
373
374 auto regList = getRegList();
375
376 if (!isLegalRegList(regList.List1From, regList.List1To))
377 return false;
378 if (!isLegalRegList(regList.List2From, regList.List2To))
379 return false;
380 if (!isLegalRegList(regList.List3From, regList.List3To))
381 return false;
382 if (!isLegalRegList(regList.List4From, regList.List4To))
383 return false;
384
385 return true;
386 }
387
388 bool isExtImm6() {
389 if (!isImm())
390 return false;
391
392 int64_t Imm;
393 bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
394 if (!IsConstantImm)
395 return false;
396
397 int uimm4 = Imm & 0xf;
398
399 return isShiftedUInt<6, 0>(Imm) && uimm4 >= 0 && uimm4 <= 14;
400 }
401
402 /// Gets location of the first token of this operand.
403 SMLoc getStartLoc() const override { return StartLoc; }
404 /// Gets location of the last token of this operand.
405 SMLoc getEndLoc() const override { return EndLoc; }
406
407 MCRegister getReg() const override {
408 assert(Kind == Register && "Invalid type access!");
409 return Reg.RegNum;
410 }
411
412 std::pair<MCRegister, MCRegister> getRegSeq() const {
413 assert(Kind == RegisterSeq && "Invalid type access!");
414 return {RegSeq.RegNumFrom, RegSeq.RegNumTo};
415 }
416
417 RegListOp getRegList() const {
418 assert(Kind == RegisterList && "Invalid type access!");
419 return RegList;
420 }
421
422 const MCExpr *getImm() const {
423 assert(Kind == Immediate && "Invalid type access!");
424 return Imm.Val;
425 }
426
427 const MCExpr *getConstpoolOp() const {
428 assert(Kind == CPOP && "Invalid type access!");
429 return CPool.Val;
430 }
431
432 StringRef getToken() const {
433 assert(Kind == Token && "Invalid type access!");
434 return Tok;
435 }
436
437 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
438 auto RegName = [](MCRegister Reg) {
439 if (Reg)
441 else
442 return "noreg";
443 };
444
445 switch (Kind) {
446 case CPOP:
447 MAI.printExpr(OS, *getConstpoolOp());
448 break;
449 case Immediate:
450 MAI.printExpr(OS, *getImm());
451 break;
452 case KindTy::Register:
453 OS << "<register " << RegName(getReg()) << ">";
454 break;
455 case RegisterSeq:
456 OS << "<register-seq ";
457 OS << RegName(getRegSeq().first) << "-" << RegName(getRegSeq().second)
458 << ">";
459 break;
460 case RegisterList:
461 OS << "<register-list ";
462 OS << RegName(getRegList().List1From) << "-"
463 << RegName(getRegList().List1To) << ",";
464 OS << RegName(getRegList().List2From) << "-"
465 << RegName(getRegList().List2To) << ",";
466 OS << RegName(getRegList().List3From) << "-"
467 << RegName(getRegList().List3To) << ",";
468 OS << RegName(getRegList().List4From) << "-"
469 << RegName(getRegList().List4To);
470 break;
471 case Token:
472 OS << "'" << getToken() << "'";
473 break;
474 }
475 }
476
477 static std::unique_ptr<CSKYOperand> createToken(StringRef Str, SMLoc S) {
478 auto Op = std::make_unique<CSKYOperand>(Token);
479 Op->Tok = Str;
480 Op->StartLoc = S;
481 Op->EndLoc = S;
482 return Op;
483 }
484
485 static std::unique_ptr<CSKYOperand> createReg(MCRegister RegNo, SMLoc S,
486 SMLoc E) {
487 auto Op = std::make_unique<CSKYOperand>(Register);
488 Op->Reg.RegNum = RegNo;
489 Op->StartLoc = S;
490 Op->EndLoc = E;
491 return Op;
492 }
493
494 static std::unique_ptr<CSKYOperand>
495 createRegSeq(MCRegister RegNoFrom, MCRegister RegNoTo, SMLoc S) {
496 auto Op = std::make_unique<CSKYOperand>(RegisterSeq);
497 Op->RegSeq.RegNumFrom = RegNoFrom;
498 Op->RegSeq.RegNumTo = RegNoTo;
499 Op->StartLoc = S;
500 Op->EndLoc = S;
501 return Op;
502 }
503
504 static std::unique_ptr<CSKYOperand>
505 createRegList(const SmallVector<MCRegister, 4> &reglist, SMLoc S) {
506 auto Op = std::make_unique<CSKYOperand>(RegisterList);
507 Op->RegList.List1From = 0;
508 Op->RegList.List1To = 0;
509 Op->RegList.List2From = 0;
510 Op->RegList.List2To = 0;
511 Op->RegList.List3From = 0;
512 Op->RegList.List3To = 0;
513 Op->RegList.List4From = 0;
514 Op->RegList.List4To = 0;
515
516 for (unsigned i = 0; i < reglist.size(); i += 2) {
517 if (Op->RegList.List1From == 0) {
518 Op->RegList.List1From = reglist[i];
519 Op->RegList.List1To = reglist[i + 1];
520 } else if (Op->RegList.List2From == 0) {
521 Op->RegList.List2From = reglist[i];
522 Op->RegList.List2To = reglist[i + 1];
523 } else if (Op->RegList.List3From == 0) {
524 Op->RegList.List3From = reglist[i];
525 Op->RegList.List3To = reglist[i + 1];
526 } else if (Op->RegList.List4From == 0) {
527 Op->RegList.List4From = reglist[i];
528 Op->RegList.List4To = reglist[i + 1];
529 } else {
530 assert(0);
531 }
532 }
533
534 Op->StartLoc = S;
535 Op->EndLoc = S;
536 return Op;
537 }
538
539 static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S,
540 SMLoc E) {
541 auto Op = std::make_unique<CSKYOperand>(Immediate);
542 Op->Imm.Val = Val;
543 Op->StartLoc = S;
544 Op->EndLoc = E;
545 return Op;
546 }
547
548 static std::unique_ptr<CSKYOperand> createConstpoolOp(const MCExpr *Val,
549 SMLoc S, SMLoc E) {
550 auto Op = std::make_unique<CSKYOperand>(CPOP);
551 Op->CPool.Val = Val;
552 Op->StartLoc = S;
553 Op->EndLoc = E;
554 return Op;
555 }
556
557 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
558 assert(Expr && "Expr shouldn't be null!");
559 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
560 Inst.addOperand(MCOperand::createImm(CE->getValue()));
561 else
563 }
564
565 // Used by the TableGen Code.
566 void addRegOperands(MCInst &Inst, unsigned N) const {
567 assert(N == 1 && "Invalid number of operands!");
569 }
570
571 void addImmOperands(MCInst &Inst, unsigned N) const {
572 assert(N == 1 && "Invalid number of operands!");
573 addExpr(Inst, getImm());
574 }
575
576 void addConstpoolOperands(MCInst &Inst, unsigned N) const {
577 assert(N == 1 && "Invalid number of operands!");
578 Inst.addOperand(MCOperand::createExpr(getConstpoolOp()));
579 }
580
581 void addRegSeqOperands(MCInst &Inst, unsigned N) const {
582 assert(N == 2 && "Invalid number of operands!");
583 auto regSeq = getRegSeq();
584
585 Inst.addOperand(MCOperand::createReg(regSeq.first));
586 Inst.addOperand(MCOperand::createReg(regSeq.second));
587 }
588
589 static unsigned getListValue(unsigned ListFrom, unsigned ListTo) {
590 if (ListFrom == ListTo && ListFrom == CSKY::R15)
591 return (1 << 4);
592 else if (ListFrom == ListTo && ListFrom == CSKY::R28)
593 return (1 << 8);
594 else if (ListFrom == CSKY::R4)
595 return ListTo - ListFrom + 1;
596 else if (ListFrom == CSKY::R16)
597 return ((ListTo - ListFrom + 1) << 5);
598 else
599 return 0;
600 }
601
602 void addRegListOperands(MCInst &Inst, unsigned N) const {
603 assert(N == 1 && "Invalid number of operands!");
604 auto regList = getRegList();
605
606 unsigned V = 0;
607
608 unsigned T = getListValue(regList.List1From, regList.List1To);
609 if (T != 0)
610 V = V | T;
611
612 T = getListValue(regList.List2From, regList.List2To);
613 if (T != 0)
614 V = V | T;
615
616 T = getListValue(regList.List3From, regList.List3To);
617 if (T != 0)
618 V = V | T;
619
620 T = getListValue(regList.List4From, regList.List4To);
621 if (T != 0)
622 V = V | T;
623
625 }
626
627 bool isValidForTie(const CSKYOperand &Other) const {
628 if (Kind != Other.Kind)
629 return false;
630
631 switch (Kind) {
632 default:
633 llvm_unreachable("Unexpected kind");
634 return false;
635 case Register:
636 return Reg.RegNum == Other.Reg.RegNum;
637 }
638 }
639};
640} // end anonymous namespace.
641
642#define GET_REGISTER_MATCHER
643#define GET_SUBTARGET_FEATURE_NAME
644#define GET_MATCHER_IMPLEMENTATION
645#define GET_MNEMONIC_SPELL_CHECKER
646#include "CSKYGenAsmMatcher.inc"
647
649 assert(Reg >= CSKY::F0_32 && Reg <= CSKY::F31_32 && "Invalid register");
650 return Reg - CSKY::F0_32 + CSKY::F0_64;
651}
652
653static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
654 unsigned VariantID = 0);
655
656bool CSKYAsmParser::generateImmOutOfRangeError(
657 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
658 const Twine &Msg = "immediate must be an integer in the range") {
659 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
660 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
661}
662
663bool CSKYAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
664 OperandVector &Operands,
665 MCStreamer &Out,
666 uint64_t &ErrorInfo,
667 bool MatchingInlineAsm) {
668 MCInst Inst;
669 FeatureBitset MissingFeatures;
670
671 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
672 MatchingInlineAsm);
673 switch (Result) {
674 default:
675 break;
676 case Match_Success:
677 return processInstruction(Inst, IDLoc, Operands, Out);
678 case Match_MissingFeature: {
679 assert(MissingFeatures.any() && "Unknown missing features!");
680 ListSeparator LS;
681 std::string Msg = "instruction requires the following: ";
682 for (unsigned Feature : MissingFeatures) {
683 Msg += LS;
684 Msg += getSubtargetFeatureName(Feature);
685 }
686 return Error(IDLoc, Msg);
687 }
688 case Match_MnemonicFail: {
689 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
690 std::string Suggestion =
691 CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS);
692 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
693 }
694 case Match_InvalidTiedOperand:
695 case Match_InvalidOperand: {
696 SMLoc ErrorLoc = IDLoc;
697 if (ErrorInfo != ~0U) {
698 if (ErrorInfo >= Operands.size())
699 return Error(ErrorLoc, "too few operands for instruction");
700
701 ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
702 if (ErrorLoc == SMLoc())
703 ErrorLoc = IDLoc;
704 }
705 return Error(ErrorLoc, "invalid operand for instruction");
706 }
707 }
708
709 // Handle the case when the error message is of specific type
710 // other than the generic Match_InvalidOperand, and the
711 // corresponding operand is missing.
712 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
713 SMLoc ErrorLoc = IDLoc;
714 if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
715 return Error(ErrorLoc, "too few operands for instruction");
716 }
717
718 switch (Result) {
719 default:
720 break;
721 case Match_InvalidSImm8:
722 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 7),
723 (1 << 7) - 1);
724 case Match_InvalidOImm3:
725 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 3));
726 case Match_InvalidOImm4:
727 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 4));
728 case Match_InvalidOImm5:
729 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
730 case Match_InvalidOImm6:
731 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6));
732 case Match_InvalidOImm8:
733 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 8));
734 case Match_InvalidOImm12:
735 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12));
736 case Match_InvalidOImm16:
737 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16));
738 case Match_InvalidUImm1:
739 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
740 case Match_InvalidUImm2:
741 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
742 case Match_InvalidUImm3:
743 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
744 case Match_InvalidUImm4:
745 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
746 case Match_InvalidUImm5:
747 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
748 case Match_InvalidUImm6:
749 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
750 case Match_InvalidUImm7:
751 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
752 case Match_InvalidUImm8:
753 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
754 case Match_InvalidUImm12:
755 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
756 case Match_InvalidUImm16:
757 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
758 case Match_InvalidUImm5Shift1:
759 return generateImmOutOfRangeError(
760 Operands, ErrorInfo, 0, (1 << 5) - 2,
761 "immediate must be a multiple of 2 bytes in the range");
762 case Match_InvalidUImm12Shift1:
763 return generateImmOutOfRangeError(
764 Operands, ErrorInfo, 0, (1 << 12) - 2,
765 "immediate must be a multiple of 2 bytes in the range");
766 case Match_InvalidUImm5Shift2:
767 return generateImmOutOfRangeError(
768 Operands, ErrorInfo, 0, (1 << 5) - 4,
769 "immediate must be a multiple of 4 bytes in the range");
770 case Match_InvalidUImm7Shift1:
771 return generateImmOutOfRangeError(
772 Operands, ErrorInfo, 0, (1 << 7) - 2,
773 "immediate must be a multiple of 2 bytes in the range");
774 case Match_InvalidUImm7Shift2:
775 return generateImmOutOfRangeError(
776 Operands, ErrorInfo, 0, (1 << 7) - 4,
777 "immediate must be a multiple of 4 bytes in the range");
778 case Match_InvalidUImm8Shift2:
779 return generateImmOutOfRangeError(
780 Operands, ErrorInfo, 0, (1 << 8) - 4,
781 "immediate must be a multiple of 4 bytes in the range");
782 case Match_InvalidUImm8Shift3:
783 return generateImmOutOfRangeError(
784 Operands, ErrorInfo, 0, (1 << 8) - 8,
785 "immediate must be a multiple of 8 bytes in the range");
786 case Match_InvalidUImm8Shift8:
787 return generateImmOutOfRangeError(
788 Operands, ErrorInfo, 0, (1 << 8) - 256,
789 "immediate must be a multiple of 256 bytes in the range");
790 case Match_InvalidUImm12Shift2:
791 return generateImmOutOfRangeError(
792 Operands, ErrorInfo, 0, (1 << 12) - 4,
793 "immediate must be a multiple of 4 bytes in the range");
794 case Match_InvalidCSKYSymbol: {
795 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
796 return Error(ErrorLoc, "operand must be a symbol name");
797 }
798 case Match_InvalidConstpool: {
799 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
800 return Error(ErrorLoc, "operand must be a constpool symbol name");
801 }
802 case Match_InvalidPSRFlag: {
803 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
804 return Error(ErrorLoc, "psrset operand is not valid");
805 }
806 case Match_InvalidRegSeq: {
807 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
808 return Error(ErrorLoc, "Register sequence is not valid");
809 }
810 case Match_InvalidRegOutOfRange: {
811 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
812 return Error(ErrorLoc, "register is out of range");
813 }
814 case Match_RequiresSameSrcAndDst: {
815 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
816 return Error(ErrorLoc, "src and dst operand must be same");
817 }
818 case Match_InvalidRegList: {
819 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
820 return Error(ErrorLoc, "invalid register list");
821 }
822 }
823 LLVM_DEBUG(dbgs() << "Result = " << Result);
824 llvm_unreachable("Unknown match type detected!");
825}
826
827bool CSKYAsmParser::processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
828 Inst.setLoc(IDLoc);
829
830 unsigned Opcode;
831 MCOperand Op;
832 if (Inst.getOpcode() == CSKY::PseudoLRW16)
833 Opcode = CSKY::LRW16;
834 else
835 Opcode = CSKY::LRW32;
836
837 if (Inst.getOperand(1).isImm()) {
838 if (isUInt<8>(Inst.getOperand(1).getImm()) &&
839 Inst.getOperand(0).getReg() <= CSKY::R7) {
840 Opcode = CSKY::MOVI16;
841 } else if (getSTI().hasFeature(CSKY::HasE2) &&
842 isUInt<16>(Inst.getOperand(1).getImm())) {
843 Opcode = CSKY::MOVI32;
844 } else {
845 auto *Expr = getTargetStreamer().addConstantPoolEntry(
847 Inst.getLoc());
848 Inst.erase(std::prev(Inst.end()));
850 }
851 } else {
852 const MCExpr *AdjustExpr = nullptr;
853 if (const auto *CSKYExpr =
855 if (CSKYExpr->getSpecifier() == CSKY::S_TLSGD ||
856 CSKYExpr->getSpecifier() == CSKY::S_TLSIE ||
857 CSKYExpr->getSpecifier() == CSKY::S_TLSLDM) {
858 MCSymbol *Dot = getContext().createNamedTempSymbol();
859 Out.emitLabel(Dot);
860 AdjustExpr = MCSymbolRefExpr::create(Dot, getContext());
861 }
862 }
863 auto *Expr = getTargetStreamer().addConstantPoolEntry(
864 Inst.getOperand(1).getExpr(), Inst.getLoc(), AdjustExpr);
865 Inst.erase(std::prev(Inst.end()));
867 }
868
869 Inst.setOpcode(Opcode);
870
871 Out.emitInstruction(Inst, getSTI());
872 return false;
873}
874
875bool CSKYAsmParser::processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
876 Inst.setLoc(IDLoc);
877
878 if (Inst.getOperand(0).isImm()) {
879 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
881 Inst.getLoc());
882 Inst.setOpcode(CSKY::JSRI32);
883 Inst.erase(std::prev(Inst.end()));
885 } else {
886 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
887 Inst.getOperand(0).getExpr(), Inst.getLoc());
888 Inst.setOpcode(CSKY::JBSR32);
890 }
891
892 Out.emitInstruction(Inst, getSTI());
893 return false;
894}
895
896bool CSKYAsmParser::processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
897 Inst.setLoc(IDLoc);
898
899 if (Inst.getOperand(0).isImm()) {
900 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
902 Inst.getLoc());
903 Inst.setOpcode(CSKY::JMPI32);
904 Inst.erase(std::prev(Inst.end()));
906 } else {
907 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
908 Inst.getOperand(0).getExpr(), Inst.getLoc());
909 Inst.setOpcode(CSKY::JBR32);
911 }
912
913 Out.emitInstruction(Inst, getSTI());
914 return false;
915}
916
917bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
918 OperandVector &Operands,
919 MCStreamer &Out) {
920
921 switch (Inst.getOpcode()) {
922 default:
923 break;
924 case CSKY::LDQ32:
925 case CSKY::STQ32:
926 if (Inst.getOperand(1).getReg() != CSKY::R4 ||
927 Inst.getOperand(2).getReg() != CSKY::R7) {
928 return Error(IDLoc, "Register sequence is not valid. 'r4-r7' expected");
929 }
930 Inst.setOpcode(Inst.getOpcode() == CSKY::LDQ32 ? CSKY::LDM32 : CSKY::STM32);
931 break;
932 case CSKY::SEXT32:
933 case CSKY::ZEXT32:
934 if (Inst.getOperand(2).getImm() < Inst.getOperand(3).getImm())
935 return Error(IDLoc, "msb must be greater or equal to lsb");
936 break;
937 case CSKY::INS32:
938 if (Inst.getOperand(3).getImm() < Inst.getOperand(4).getImm())
939 return Error(IDLoc, "msb must be greater or equal to lsb");
940 break;
941 case CSKY::IDLY32:
942 if (Inst.getOperand(0).getImm() > 32 || Inst.getOperand(0).getImm() < 0)
943 return Error(IDLoc, "n must be in range [0,32]");
944 break;
945 case CSKY::ADDC32:
946 case CSKY::SUBC32:
947 case CSKY::ADDC16:
948 case CSKY::SUBC16:
949 Inst.erase(std::next(Inst.begin()));
950 Inst.erase(std::prev(Inst.end()));
951 Inst.insert(std::next(Inst.begin()), MCOperand::createReg(CSKY::C));
952 Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
953 break;
954 case CSKY::CMPNEI32:
955 case CSKY::CMPNEI16:
956 case CSKY::CMPNE32:
957 case CSKY::CMPNE16:
958 case CSKY::CMPHSI32:
959 case CSKY::CMPHSI16:
960 case CSKY::CMPHS32:
961 case CSKY::CMPHS16:
962 case CSKY::CMPLTI32:
963 case CSKY::CMPLTI16:
964 case CSKY::CMPLT32:
965 case CSKY::CMPLT16:
966 case CSKY::BTSTI32:
967 Inst.erase(Inst.begin());
968 Inst.insert(Inst.begin(), MCOperand::createReg(CSKY::C));
969 break;
970 case CSKY::MVCV32:
971 Inst.erase(std::next(Inst.begin()));
972 Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
973 break;
974 case CSKY::PseudoLRW16:
975 case CSKY::PseudoLRW32:
976 return processLRW(Inst, IDLoc, Out);
977 case CSKY::PseudoJSRI32:
978 return processJSRI(Inst, IDLoc, Out);
979 case CSKY::PseudoJMPI32:
980 return processJMPI(Inst, IDLoc, Out);
981 case CSKY::JBSR32:
982 case CSKY::JBR16:
983 case CSKY::JBT16:
984 case CSKY::JBF16:
985 case CSKY::JBR32:
986 case CSKY::JBT32:
987 case CSKY::JBF32:
988 unsigned Num = Inst.getNumOperands() - 1;
989 assert(Inst.getOperand(Num).isExpr());
990
991 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
992 Inst.getOperand(Num).getExpr(), Inst.getLoc());
993
995 break;
996 }
997
998 emitToStreamer(Out, Inst);
999 return false;
1000}
1001
1002// Attempts to match Name as a register (either using the default name or
1003// alternative ABI names), setting RegNo to the matching register. Upon
1004// failure, returns true and sets RegNo to 0.
1006 StringRef Name) {
1007 Reg = MatchRegisterName(Name);
1008
1009 if (Reg == CSKY::NoRegister)
1010 Reg = MatchRegisterAltName(Name);
1011
1012 return Reg == CSKY::NoRegister;
1013}
1014
1015bool CSKYAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1016 SMLoc &EndLoc) {
1017 const AsmToken &Tok = getParser().getTok();
1018 StartLoc = Tok.getLoc();
1019 EndLoc = Tok.getEndLoc();
1020 StringRef Name = getLexer().getTok().getIdentifier();
1021
1022 if (!matchRegisterNameHelper(getSTI(), Reg, Name)) {
1023 getParser().Lex(); // Eat identifier token.
1024 return false;
1025 }
1026
1027 return true;
1028}
1029
1030ParseStatus CSKYAsmParser::parseRegister(OperandVector &Operands) {
1031 SMLoc S = getLoc();
1032 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1033
1034 switch (getLexer().getKind()) {
1035 default:
1036 return ParseStatus::NoMatch;
1037 case AsmToken::Identifier: {
1038 StringRef Name = getLexer().getTok().getIdentifier();
1039 MCRegister Reg;
1040
1041 if (matchRegisterNameHelper(getSTI(), Reg, Name))
1042 return ParseStatus::NoMatch;
1043
1044 getLexer().Lex();
1045 Operands.push_back(CSKYOperand::createReg(Reg, S, E));
1046
1047 return ParseStatus::Success;
1048 }
1049 }
1050}
1051
1052ParseStatus CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) {
1053 assert(getLexer().is(AsmToken::LParen));
1054
1055 Operands.push_back(CSKYOperand::createToken("(", getLoc()));
1056
1057 auto Tok = getParser().Lex(); // Eat '('
1058
1059 if (!parseRegister(Operands).isSuccess()) {
1060 getLexer().UnLex(Tok);
1061 Operands.pop_back();
1062 return ParseStatus::NoMatch;
1063 }
1064
1065 if (getLexer().is(AsmToken::RParen)) {
1066 Operands.push_back(CSKYOperand::createToken(")", getLoc()));
1067 getParser().Lex(); // Eat ')'
1068 return ParseStatus::Success;
1069 }
1070
1071 if (getLexer().isNot(AsmToken::Comma))
1072 return Error(getLoc(), "expected ','");
1073
1074 getParser().Lex(); // Eat ','
1075
1076 if (parseRegister(Operands).isSuccess()) {
1077 if (getLexer().isNot(AsmToken::LessLess))
1078 return Error(getLoc(), "expected '<<'");
1079
1080 Operands.push_back(CSKYOperand::createToken("<<", getLoc()));
1081
1082 getParser().Lex(); // Eat '<<'
1083
1084 if (!parseImmediate(Operands).isSuccess())
1085 return Error(getLoc(), "expected imm");
1086
1087 } else if (!parseImmediate(Operands).isSuccess()) {
1088 return Error(getLoc(), "expected imm");
1089 }
1090
1091 if (getLexer().isNot(AsmToken::RParen))
1092 return Error(getLoc(), "expected ')'");
1093
1094 Operands.push_back(CSKYOperand::createToken(")", getLoc()));
1095
1096 getParser().Lex(); // Eat ')'
1097
1098 return ParseStatus::Success;
1099}
1100
1101ParseStatus CSKYAsmParser::parseImmediate(OperandVector &Operands) {
1102 switch (getLexer().getKind()) {
1103 default:
1104 return ParseStatus::NoMatch;
1105 case AsmToken::LParen:
1106 case AsmToken::Minus:
1107 case AsmToken::Plus:
1108 case AsmToken::Integer:
1109 case AsmToken::String:
1110 break;
1111 }
1112
1113 const MCExpr *IdVal;
1114 SMLoc S = getLoc();
1115 if (getParser().parseExpression(IdVal))
1116 return Error(getLoc(), "unknown expression");
1117
1118 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1119 Operands.push_back(CSKYOperand::createImm(IdVal, S, E));
1120 return ParseStatus::Success;
1121}
1122
1123/// Looks at a token type and creates the relevant operand from this
1124/// information, adding to Operands. If operand was parsed, returns false, else
1125/// true.
1126bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1127 // Check if the current operand has a custom associated parser, if so, try to
1128 // custom parse the operand, or fallback to the general approach.
1129 ParseStatus Result =
1130 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1131 if (Result.isSuccess())
1132 return false;
1133 if (Result.isFailure())
1134 return true;
1135
1136 // Attempt to parse token as register
1137 auto Res = parseRegister(Operands);
1138 if (Res.isSuccess())
1139 return false;
1140 if (Res.isFailure())
1141 return true;
1142
1143 // Attempt to parse token as (register, imm)
1144 if (getLexer().is(AsmToken::LParen)) {
1145 Res = parseBaseRegImm(Operands);
1146 if (Res.isSuccess())
1147 return false;
1148 if (Res.isFailure())
1149 return true;
1150 }
1151
1152 Res = parseImmediate(Operands);
1153 if (Res.isSuccess())
1154 return false;
1155 if (Res.isFailure())
1156 return true;
1157
1158 // Finally we have exhausted all options and must declare defeat.
1159 Error(getLoc(), "unknown operand");
1160 return true;
1161}
1162
1163ParseStatus CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
1164 SMLoc S = getLoc();
1165 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1166 const MCExpr *Res;
1167
1168 if (getLexer().getKind() != AsmToken::Identifier)
1169 return ParseStatus::NoMatch;
1170
1171 StringRef Identifier;
1172 AsmToken Tok = getLexer().getTok();
1173
1174 if (getParser().parseIdentifier(Identifier))
1175 return Error(getLoc(), "unknown identifier");
1176
1178 if (Identifier.consume_back("@GOT"))
1179 Kind = CSKY::S_GOT;
1180 else if (Identifier.consume_back("@GOTOFF"))
1182 else if (Identifier.consume_back("@PLT"))
1183 Kind = CSKY::S_PLT;
1184 else if (Identifier.consume_back("@GOTPC"))
1186 else if (Identifier.consume_back("@TLSGD32"))
1188 else if (Identifier.consume_back("@GOTTPOFF"))
1190 else if (Identifier.consume_back("@TPOFF"))
1192 else if (Identifier.consume_back("@TLSLDM32"))
1194 else if (Identifier.consume_back("@TLSLDO32"))
1196
1197 MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1198
1199 if (!Sym)
1200 Sym = getContext().getOrCreateSymbol(Identifier);
1201
1202 if (Sym->isVariable()) {
1203 const MCExpr *V = Sym->getVariableValue();
1204 if (!isa<MCSymbolRefExpr>(V)) {
1205 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1206 return Error(getLoc(), "unknown symbol");
1207 }
1208 Res = V;
1209 } else
1210 Res = MCSymbolRefExpr::create(Sym, getContext());
1211
1212 MCBinaryExpr::Opcode Opcode;
1213 switch (getLexer().getKind()) {
1214 default:
1215 if (Kind != CSKY::S_None)
1216 Res = MCSpecifierExpr::create(Res, Kind, getContext());
1217
1218 Operands.push_back(CSKYOperand::createImm(Res, S, E));
1219 return ParseStatus::Success;
1220 case AsmToken::Plus:
1221 Opcode = MCBinaryExpr::Add;
1222 break;
1223 case AsmToken::Minus:
1224 Opcode = MCBinaryExpr::Sub;
1225 break;
1226 }
1227
1228 getLexer().Lex(); // eat + or -
1229
1230 const MCExpr *Expr;
1231 if (getParser().parseExpression(Expr))
1232 return Error(getLoc(), "unknown expression");
1233 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1234 Operands.push_back(CSKYOperand::createImm(Res, S, E));
1235 return ParseStatus::Success;
1236}
1237
1238ParseStatus CSKYAsmParser::parseDataSymbol(OperandVector &Operands) {
1239 SMLoc S = getLoc();
1240 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1241 const MCExpr *Res;
1242
1243 if (!parseOptionalToken(AsmToken::LBrac))
1244 return ParseStatus::NoMatch;
1245 if (getLexer().getKind() != AsmToken::Identifier) {
1246 const MCExpr *Expr;
1247 if (getParser().parseExpression(Expr))
1248 return Error(getLoc(), "unknown expression");
1249
1250 if (parseToken(AsmToken::RBrac, "expected ']'"))
1251 return ParseStatus::Failure;
1252
1253 Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1254 return ParseStatus::Success;
1255 }
1256
1257 AsmToken Tok = getLexer().getTok();
1258 StringRef Identifier;
1259
1260 if (getParser().parseIdentifier(Identifier))
1261 return Error(getLoc(), "unknown identifier " + Identifier);
1262
1264 if (Identifier.consume_back("@GOT"))
1266 else if (Identifier.consume_back("@PLT"))
1268
1269 MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1270
1271 if (!Sym)
1272 Sym = getContext().getOrCreateSymbol(Identifier);
1273
1274 if (Sym->isVariable()) {
1275 const MCExpr *V = Sym->getVariableValue();
1276 if (!isa<MCSymbolRefExpr>(V)) {
1277 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1278 return Error(getLoc(), "unknown symbol");
1279 }
1280 Res = V;
1281 } else {
1282 Res = MCSymbolRefExpr::create(Sym, getContext());
1283 }
1284
1285 MCBinaryExpr::Opcode Opcode;
1286 switch (getLexer().getKind()) {
1287 default:
1288 return Error(getLoc(), "unknown symbol");
1289 case AsmToken::RBrac:
1290
1291 getLexer().Lex(); // Eat ']'.
1292
1293 if (Kind != CSKY::S_None)
1294 Res = MCSpecifierExpr::create(Res, Kind, getContext());
1295
1296 Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1297 return ParseStatus::Success;
1298 case AsmToken::Plus:
1299 Opcode = MCBinaryExpr::Add;
1300 break;
1301 case AsmToken::Minus:
1302 Opcode = MCBinaryExpr::Sub;
1303 break;
1304 }
1305
1306 getLexer().Lex(); // eat + or -
1307
1308 const MCExpr *Expr;
1309 if (getParser().parseExpression(Expr))
1310 return Error(getLoc(), "unknown expression");
1311 if (parseToken(AsmToken::RBrac, "expected ']'"))
1312 return ParseStatus::Failure;
1313
1314 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1315 Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1316 return ParseStatus::Success;
1317}
1318
1319ParseStatus CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
1320 SMLoc S = getLoc();
1321 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1322 const MCExpr *Res;
1323
1324 if (!parseOptionalToken(AsmToken::LBrac))
1325 return ParseStatus::NoMatch;
1326
1327 if (getLexer().getKind() != AsmToken::Identifier) {
1328 const MCExpr *Expr;
1329 if (getParser().parseExpression(Expr))
1330 return Error(getLoc(), "unknown expression");
1331 if (parseToken(AsmToken::RBrac))
1332 return ParseStatus::Failure;
1333
1334 Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1335 return ParseStatus::Success;
1336 }
1337
1338 AsmToken Tok = getLexer().getTok();
1339 StringRef Identifier;
1340
1341 if (getParser().parseIdentifier(Identifier))
1342 return Error(getLoc(), "unknown identifier");
1343
1344 MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1345
1346 if (!Sym)
1347 Sym = getContext().getOrCreateSymbol(Identifier);
1348
1349 if (Sym->isVariable()) {
1350 const MCExpr *V = Sym->getVariableValue();
1351 if (!isa<MCSymbolRefExpr>(V)) {
1352 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1353 return Error(getLoc(), "unknown symbol");
1354 }
1355 Res = V;
1356 } else {
1357 Res = MCSymbolRefExpr::create(Sym, getContext());
1358 }
1359
1360 MCBinaryExpr::Opcode Opcode;
1361 switch (getLexer().getKind()) {
1362 default:
1363 return Error(getLoc(), "unknown symbol");
1364 case AsmToken::RBrac:
1365
1366 getLexer().Lex(); // Eat ']'.
1367
1368 Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1369 return ParseStatus::Success;
1370 case AsmToken::Plus:
1371 Opcode = MCBinaryExpr::Add;
1372 break;
1373 case AsmToken::Minus:
1374 Opcode = MCBinaryExpr::Sub;
1375 break;
1376 }
1377
1378 getLexer().Lex(); // eat + or -
1379
1380 const MCExpr *Expr;
1381 if (getParser().parseExpression(Expr))
1382 return Error(getLoc(), "unknown expression");
1383 if (parseToken(AsmToken::RBrac, "expected ']'"))
1384 return ParseStatus::Failure;
1385
1386 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1387 Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1388 return ParseStatus::Success;
1389}
1390
1391ParseStatus CSKYAsmParser::parsePSRFlag(OperandVector &Operands) {
1392 SMLoc S = getLoc();
1393 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1394
1395 unsigned Flag = 0;
1396
1397 while (getLexer().isNot(AsmToken::EndOfStatement)) {
1398 StringRef Identifier;
1399 if (getParser().parseIdentifier(Identifier))
1400 return Error(getLoc(), "unknown identifier " + Identifier);
1401
1402 if (Identifier == "sie")
1403 Flag = (1 << 4) | Flag;
1404 else if (Identifier == "ee")
1405 Flag = (1 << 3) | Flag;
1406 else if (Identifier == "ie")
1407 Flag = (1 << 2) | Flag;
1408 else if (Identifier == "fe")
1409 Flag = (1 << 1) | Flag;
1410 else if (Identifier == "af")
1411 Flag = (1 << 0) | Flag;
1412 else
1413 return Error(getLoc(), "expected " + Identifier);
1414
1415 if (getLexer().is(AsmToken::EndOfStatement))
1416 break;
1417
1418 if (parseToken(AsmToken::Comma, "expected ','"))
1419 return ParseStatus::Failure;
1420 }
1421
1422 Operands.push_back(
1423 CSKYOperand::createImm(MCConstantExpr::create(Flag, getContext()), S, E));
1424 return ParseStatus::Success;
1425}
1426
1427ParseStatus CSKYAsmParser::parseRegSeq(OperandVector &Operands) {
1428 SMLoc S = getLoc();
1429
1430 if (!parseRegister(Operands).isSuccess())
1431 return ParseStatus::NoMatch;
1432
1433 auto Ry = Operands.back()->getReg();
1434 Operands.pop_back();
1435
1436 if (parseToken(AsmToken::Minus, "expected '-'"))
1437 return ParseStatus::Failure;
1438 if (!parseRegister(Operands).isSuccess())
1439 return Error(getLoc(), "invalid register");
1440
1441 auto Rz = Operands.back()->getReg();
1442 Operands.pop_back();
1443
1444 Operands.push_back(CSKYOperand::createRegSeq(Ry, Rz, S));
1445 return ParseStatus::Success;
1446}
1447
1448ParseStatus CSKYAsmParser::parseRegList(OperandVector &Operands) {
1449 SMLoc S = getLoc();
1451 while (true) {
1452
1453 if (!parseRegister(Operands).isSuccess())
1454 return Error(getLoc(), "invalid register");
1455
1456 auto Ry = Operands.back()->getReg();
1457 Operands.pop_back();
1458
1459 if (parseOptionalToken(AsmToken::Minus)) {
1460 if (!parseRegister(Operands).isSuccess())
1461 return Error(getLoc(), "invalid register");
1462
1463 auto Rz = Operands.back()->getReg();
1464 Operands.pop_back();
1465
1466 reglist.push_back(Ry);
1467 reglist.push_back(Rz);
1468
1469 if (getLexer().is(AsmToken::EndOfStatement))
1470 break;
1471 (void)parseOptionalToken(AsmToken::Comma);
1472 } else if (parseOptionalToken(AsmToken::Comma)) {
1473 reglist.push_back(Ry);
1474 reglist.push_back(Ry);
1475 } else if (getLexer().is(AsmToken::EndOfStatement)) {
1476 reglist.push_back(Ry);
1477 reglist.push_back(Ry);
1478 break;
1479 } else {
1480 return Error(getLoc(), "invalid register list");
1481 }
1482 }
1483
1484 Operands.push_back(CSKYOperand::createRegList(reglist, S));
1485 return ParseStatus::Success;
1486}
1487
1488bool CSKYAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
1489 SMLoc NameLoc, OperandVector &Operands) {
1490 // First operand is token for instruction.
1491 Operands.push_back(CSKYOperand::createToken(Name, NameLoc));
1492
1493 // If there are no more operands, then finish.
1494 if (getLexer().is(AsmToken::EndOfStatement))
1495 return false;
1496
1497 // Parse first operand.
1498 if (parseOperand(Operands, Name))
1499 return true;
1500
1501 // Parse until end of statement, consuming commas between operands.
1502 while (parseOptionalToken(AsmToken::Comma))
1503 if (parseOperand(Operands, Name))
1504 return true;
1505
1506 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1507 SMLoc Loc = getLexer().getLoc();
1508 getParser().eatToEndOfStatement();
1509 return Error(Loc, "unexpected token");
1510 }
1511
1512 getParser().Lex(); // Consume the EndOfStatement.
1513 return false;
1514}
1515
1516ParseStatus CSKYAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1517 SMLoc &EndLoc) {
1518 const AsmToken &Tok = getParser().getTok();
1519 StartLoc = Tok.getLoc();
1520 EndLoc = Tok.getEndLoc();
1521
1522 StringRef Name = getLexer().getTok().getIdentifier();
1523
1524 if (matchRegisterNameHelper(getSTI(), Reg, Name))
1525 return ParseStatus::NoMatch;
1526
1527 getParser().Lex(); // Eat identifier token.
1528 return ParseStatus::Success;
1529}
1530
1531ParseStatus CSKYAsmParser::parseDirective(AsmToken DirectiveID) {
1532 StringRef IDVal = DirectiveID.getString();
1533
1534 if (IDVal == ".csky_attribute")
1535 return parseDirectiveAttribute();
1536
1537 return ParseStatus::NoMatch;
1538}
1539
1540/// parseDirectiveAttribute
1541/// ::= .attribute expression ',' ( expression | "string" )
1542bool CSKYAsmParser::parseDirectiveAttribute() {
1543 MCAsmParser &Parser = getParser();
1544 int64_t Tag;
1545 SMLoc TagLoc;
1546 TagLoc = Parser.getTok().getLoc();
1547 if (Parser.getTok().is(AsmToken::Identifier)) {
1548 StringRef Name = Parser.getTok().getIdentifier();
1549 std::optional<unsigned> Ret =
1551 if (!Ret)
1552 return Error(TagLoc, "attribute name not recognised: " + Name);
1553 Tag = *Ret;
1554 Parser.Lex();
1555 } else {
1556 const MCExpr *AttrExpr;
1557
1558 TagLoc = Parser.getTok().getLoc();
1559 if (Parser.parseExpression(AttrExpr))
1560 return true;
1561
1562 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
1563 if (!CE)
1564 return Error(TagLoc, "expected numeric constant");
1565
1566 Tag = CE->getValue();
1567 }
1568
1569 if (Parser.parseComma())
1570 return true;
1571
1572 StringRef StringValue;
1573 int64_t IntegerValue = 0;
1574 bool IsIntegerValue = ((Tag != CSKYAttrs::CSKY_ARCH_NAME) &&
1577
1578 SMLoc ValueExprLoc = Parser.getTok().getLoc();
1579 if (IsIntegerValue) {
1580 const MCExpr *ValueExpr;
1581 if (Parser.parseExpression(ValueExpr))
1582 return true;
1583
1584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
1585 if (!CE)
1586 return Error(ValueExprLoc, "expected numeric constant");
1587 IntegerValue = CE->getValue();
1588 } else {
1589 if (Parser.getTok().isNot(AsmToken::String))
1590 return Error(Parser.getTok().getLoc(), "expected string constant");
1591
1592 StringValue = Parser.getTok().getStringContents();
1593 Parser.Lex();
1594 }
1595
1596 if (Parser.parseEOL())
1597 return true;
1598
1599 if (IsIntegerValue)
1600 getTargetStreamer().emitAttribute(Tag, IntegerValue);
1602 getTargetStreamer().emitTextAttribute(Tag, StringValue);
1603 else {
1605 ? CSKY::parseArch(StringValue)
1606 : CSKY::parseCPUArch(StringValue);
1607 if (ID == CSKY::ArchKind::INVALID)
1608 return Error(ValueExprLoc, (Tag == CSKYAttrs::CSKY_ARCH_NAME)
1609 ? "unknown arch name"
1610 : "unknown cpu name");
1611
1612 getTargetStreamer().emitTextAttribute(Tag, StringValue);
1613 }
1614
1615 return false;
1616}
1617
1618unsigned CSKYAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1619 unsigned Kind) {
1620 CSKYOperand &Op = static_cast<CSKYOperand &>(AsmOp);
1621
1622 if (!Op.isReg())
1623 return Match_InvalidOperand;
1624
1625 MCRegister Reg = Op.getReg();
1626
1627 if (getCSKYMCRegisterClass(CSKY::FPR32RegClassID).contains(Reg)) {
1628 // As the parser couldn't differentiate an FPR64 from an FPR32, coerce the
1629 // register from FPR32 to FPR64 if necessary.
1630 if (Kind == MCK_FPR64 || Kind == MCK_sFPR64) {
1631 Op.Reg.RegNum = convertFPR32ToFPR64(Reg);
1632 if (Kind == MCK_sFPR64 &&
1633 (Op.Reg.RegNum < CSKY::F0_64 || Op.Reg.RegNum > CSKY::F15_64))
1634 return Match_InvalidRegOutOfRange;
1635 if (Kind == MCK_FPR64 &&
1636 (Op.Reg.RegNum < CSKY::F0_64 || Op.Reg.RegNum > CSKY::F31_64))
1637 return Match_InvalidRegOutOfRange;
1638 return Match_Success;
1639 }
1640 }
1641
1642 if (getCSKYMCRegisterClass(CSKY::GPRRegClassID).contains(Reg)) {
1643 if (Kind == MCK_GPRPair) {
1644 Op.Reg.RegNum = MRI->getEncodingValue(Reg) + CSKY::R0_R1;
1645 return Match_Success;
1646 }
1647 }
1648
1649 return Match_InvalidOperand;
1650}
1651
1652void CSKYAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
1653 MCInst CInst;
1654 bool Res = false;
1656 Res = compressInst(CInst, Inst, getSTI());
1657 if (Res)
1658 ++CSKYNumInstrsCompressed;
1659 S.emitInstruction((Res ? CInst : Inst), getSTI());
1660}
1661
static MCRegister MatchRegisterName(StringRef Name)
static const char * getSubtargetFeatureName(uint64_t Val)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool matchRegisterNameHelper(const MCSubtargetInfo &STI, MCRegister &Reg, StringRef Name)
static cl::opt< bool > AddBuildAttributes("csky-add-build-attributes", cl::init(true))
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser()
static MCRegister convertFPR32ToFPR64(MCRegister Reg)
static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID=0)
static cl::opt< bool > EnableCompressedInst("enable-csky-asm-compressed-inst", cl::Hidden, cl::init(false), cl::desc("Enable C-SKY asm compressed instruction"))
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
#define RegName(no)
static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits, ArrayRef< SubtargetFeatureKV > ProcFeatures)
Register Reg
#define T
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
static bool isUImm2(const MachineOperand &MO)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define LLVM_DEBUG(...)
Definition Debug.h:119
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
LLVM_ABI SMLoc getLoc() const
Definition AsmLexer.cpp:31
bool isNot(TokenKind K) const
Definition MCAsmMacro.h:76
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition MCAsmMacro.h:103
StringRef getStringContents() const
Get the contents of a string token (without quotes).
Definition MCAsmMacro.h:83
bool is(TokenKind K) const
Definition MCAsmMacro.h:75
LLVM_ABI SMLoc getEndLoc() const
Definition AsmLexer.cpp:33
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition MCAsmMacro.h:92
static const char * getRegisterName(MCRegister Reg)
Base class for user error types.
Definition Error.h:354
Container class for subtarget features.
void printExpr(raw_ostream &, const MCExpr &) const
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:201
@ Sub
Subtraction.
Definition MCExpr.h:323
@ Add
Addition.
Definition MCExpr.h:301
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
void erase(iterator I)
Definition MCInst.h:224
unsigned getNumOperands() const
Definition MCInst.h:212
SMLoc getLoc() const
Definition MCInst.h:208
void setLoc(SMLoc loc)
Definition MCInst.h:207
unsigned getOpcode() const
Definition MCInst.h:202
iterator insert(iterator I, const MCOperand &Op)
Definition MCInst.h:232
void addOperand(const MCOperand Op)
Definition MCInst.h:215
iterator begin()
Definition MCInst.h:227
iterator end()
Definition MCInst.h:229
void setOpcode(unsigned Op)
Definition MCInst.h:201
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
bool isImm() const
Definition MCInst.h:66
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Generic base class for all target subtargets.
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition MCSymbol.h:267
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
Definition MCSymbol.h:270
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Ternary parse status returned by various parse* methods.
static constexpr StatusTy Failure
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Represents a location in source code.
Definition SMLoc.h:22
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:35
constexpr const char * getPointer() const
Definition SMLoc.h:33
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI const TagNameMap & getCSKYAttributeTags()
uint8_t Specifier
LLVM_ABI ArchKind parseCPUArch(StringRef CPU)
LLVM_ABI ArchKind parseArch(StringRef Arch)
LLVM_ABI std::optional< unsigned > attrTypeFromString(StringRef tag, TagNameMap tagNameMap)
Flag
These should be considered private to the implementation of the MCInstrDesc class.
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
static bool isMem(const MachineInstr &MI, unsigned Op)
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
Target & getTheCSKYTarget()
@ Other
Any other memory.
Definition ModRef.h:68
DWARFExpression::Operation Op
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition MathExtras.h:183
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
Definition MathExtras.h:199
#define N
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...