LLVM: lib/Target/M68k/AsmParser/M68kAsmParser.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
13
20
21#include
22
23#define DEBUG_TYPE "m68k-asm-parser"
24
25using namespace llvm;
26
28 "m68k-register-prefix-optional", cl::Hidden,
29 cl::desc("Enable specifying registers without the % prefix"),
31
32namespace {
33
37
38#define GET_ASSEMBLER_HEADER
39#include "M68kGenAsmMatcher.inc"
40
41
48
49
50 void eatComma();
51
52 bool isExpr();
56
57public:
62 MRI = getContext().getRegisterInfo();
63
64 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
65 }
66
67 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
68 unsigned Kind) override;
69 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
70 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
71 SMLoc &EndLoc) override;
72 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
74 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
76 uint64_t &ErrorInfo,
77 bool MatchingInlineAsm) override;
78};
79
80struct M68kMemOp {
81 enum class Kind {
82 Addr,
83 RegMask,
85 RegIndirect,
86 RegPostIncrement,
87 RegPreDecrement,
88 RegIndirectDisplacement,
89 RegIndirectDisplacementIndex,
90 };
91
92
93
94
95
96
97
98
99
100
101
102
103 Kind Op;
104 MCRegister OuterReg;
105 MCRegister InnerReg;
106 const MCExpr *OuterDisp;
107 const MCExpr *InnerDisp;
108 uint8_t Size : 4;
109 uint8_t Scale : 4;
110 const MCExpr *Expr;
111 uint16_t RegMask;
112
113 M68kMemOp() {}
114 M68kMemOp(Kind Op) : Op(Op) {}
115
116 void print(raw_ostream &OS) const;
117};
118
119
121 typedef MCParsedAsmOperand Base;
122
123 enum class KindTy {
125 Token,
127 MemOp,
128 };
129
130 KindTy Kind;
131 SMLoc Start, End;
132 union {
133 StringRef Token;
134 const MCExpr *Expr;
135 M68kMemOp MemOp;
136 };
137
138 template bool isAddrN() const;
139
140public:
141 M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)
142 : Base(), Kind(Kind), Start(Start), End(End) {}
143
144 SMLoc getStartLoc() const override { return Start; }
145 SMLoc getEndLoc() const override { return End; }
146
147 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override;
148
149 bool isMem() const override { return false; }
150 bool isMemOp() const { return Kind == KindTy::MemOp; }
151
152 static void addExpr(MCInst &Inst, const MCExpr *Expr);
153
154
155 bool isReg() const override;
156 bool isAReg() const;
157 bool isDReg() const;
158 bool isFPDReg() const;
159 bool isFPCReg() const;
160 MCRegister getReg() const override;
161 void addRegOperands(MCInst &Inst, unsigned N) const;
162
163 static std::unique_ptr createMemOp(M68kMemOp MemOp, SMLoc Start,
164 SMLoc End);
165
166
167 bool isToken() const override;
169 static std::unique_ptr createToken(StringRef Token, SMLoc Start,
170 SMLoc End);
171
172
173 bool isImm() const override;
174 void addImmOperands(MCInst &Inst, unsigned N) const;
175
176 static std::unique_ptr createImm(const MCExpr *Expr, SMLoc Start,
177 SMLoc End);
178
179
180 bool isTrapImm() const;
181
182 bool isBkptImm() const;
183
184
185 bool isMoveMask() const;
186 void addMoveMaskOperands(MCInst &Inst, unsigned N) const;
187
188
189 bool isAddr() const;
190 bool isAddr8() const { return isAddrN<8>(); }
191 bool isAddr16() const { return isAddrN<16>(); }
192 bool isAddr32() const { return isAddrN<32>(); }
193 void addAddrOperands(MCInst &Inst, unsigned N) const;
194
195
196 bool isARI() const;
197 void addARIOperands(MCInst &Inst, unsigned N) const;
198
199
200 bool isARID() const;
201 void addARIDOperands(MCInst &Inst, unsigned N) const;
202
203
204 bool isARII() const;
205 void addARIIOperands(MCInst &Inst, unsigned N) const;
206
207
208 bool isARIPD() const;
209 void addARIPDOperands(MCInst &Inst, unsigned N) const;
210
211
212 bool isARIPI() const;
213 void addARIPIOperands(MCInst &Inst, unsigned N) const;
214
215
216 bool isPCD() const;
217 void addPCDOperands(MCInst &Inst, unsigned N) const;
218
219
220 bool isPCI() const;
221 void addPCIOperands(MCInst &Inst, unsigned N) const;
222};
223
224}
225
229
230#define GET_REGISTER_MATCHER
231#define GET_MATCHER_IMPLEMENTATION
232#include "M68kGenAsmMatcher.inc"
233
235 static unsigned RegistersByIndex[] = {
236 M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
237 M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
238 M68k::A4, M68k::A5, M68k::A6, M68k::SP, M68k::FP0, M68k::FP1,
239 M68k::FP2, M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7};
240 assert(RegisterIndex <=
241 sizeof(RegistersByIndex) / sizeof(RegistersByIndex[0]));
242 return RegistersByIndex[RegisterIndex];
243}
244
249 return Register - M68k::A0 + 8;
251 return Register - M68k::FP0 + 16;
252
254 case M68k::SP:
255
256 return 15;
257
258
259 case M68k::PC:
260 case M68k::CCR:
261 case M68k::SR:
262 case M68k::FPC:
263 case M68k::FPS:
264 case M68k::FPIAR:
265 return UINT_MAX;
266
267 default:
269 }
270}
271
272void M68kMemOp::print(raw_ostream &OS) const {
273 switch (Op) {
274 case Kind::Addr:
275 OS << OuterDisp;
276 break;
277 case Kind::RegMask:
278 OS << "RegMask(" << format("%04x", RegMask) << ")";
279 break;
280 case Kind::Reg:
281 OS << '%' << OuterReg;
282 break;
283 case Kind::RegIndirect:
284 OS << "(%" << OuterReg << ')';
285 break;
286 case Kind::RegPostIncrement:
287 OS << "(%" << OuterReg << ")+";
288 break;
289 case Kind::RegPreDecrement:
290 OS << "-(%" << OuterReg << ")";
291 break;
292 case Kind::RegIndirectDisplacement:
293 OS << OuterDisp << "(%" << OuterReg << ")";
294 break;
295 case Kind::RegIndirectDisplacementIndex:
296 OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size
297 << ", " << InnerDisp << ")";
298 break;
299 }
300}
301
302void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {
305 return;
306 }
307
309}
310
311
312bool M68kOperand::isReg() const {
313 return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
314}
315
316MCRegister M68kOperand::getReg() const {
318 return MemOp.OuterReg;
319}
320
321void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {
323 assert((N == 1) && "can only handle one register operand");
324
326}
327
328std::unique_ptr M68kOperand::createMemOp(M68kMemOp MemOp,
329 SMLoc Start, SMLoc End) {
330 auto Op = std::make_unique(KindTy::MemOp, Start, End);
331 Op->MemOp = MemOp;
332 return Op;
333}
334
335
336bool M68kOperand::isToken() const { return Kind == KindTy::Token; }
337StringRef M68kOperand::getToken() const {
339 return Token;
340}
341
342std::unique_ptr M68kOperand::createToken(StringRef Token,
343 SMLoc Start, SMLoc End) {
344 auto Op = std::make_unique(KindTy::Token, Start, End);
345 Op->Token = Token;
346 return Op;
347}
348
349
350bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }
351void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {
352 assert(isImm() && "wrong operand kind");
353 assert((N == 1) && "can only handle one register operand");
354
355 M68kOperand::addExpr(Inst, Expr);
356}
357
358std::unique_ptr M68kOperand::createImm(const MCExpr *Expr,
359 SMLoc Start, SMLoc End) {
360 auto Op = std::make_unique(KindTy::Imm, Start, End);
361 Op->Expr = Expr;
362 return Op;
363}
364
365bool M68kOperand::isTrapImm() const {
367 if (!isImm() || !Expr->evaluateAsAbsolute(Value))
368 return false;
369
371}
372
373bool M68kOperand::isBkptImm() const {
375 if (!isImm() || !Expr->evaluateAsAbsolute(Value))
376 return false;
377
379}
380
381
382bool M68kOperand::isMoveMask() const {
383 if (!isMemOp())
384 return false;
385
386 if (MemOp.Op == M68kMemOp::Kind::RegMask)
387 return true;
388
389 if (MemOp.Op != M68kMemOp::Kind::Reg)
390 return false;
391
392
393
395}
396
397void M68kOperand::addMoveMaskOperands(MCInst &Inst, unsigned N) const {
398 assert(isMoveMask() && "wrong operand kind");
399 assert((N == 1) && "can only handle one immediate operand");
400
401 uint16_t MoveMask = MemOp.RegMask;
402 if (MemOp.Op == M68kMemOp::Kind::Reg)
404
406}
407
408
409bool M68kOperand::isAddr() const {
410 return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
411}
412
413
414template bool M68kOperand::isAddrN() const {
415 if (isAddr()) {
416 int64_t Res;
417 if (MemOp.OuterDisp->evaluateAsAbsolute(Res))
419 return true;
420 }
421 return false;
422}
423void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
424 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
425}
426
427
428bool M68kOperand::isARI() const {
429 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
430 M68k::AR32RegClass.contains(MemOp.OuterReg);
431}
432void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
434}
435
436
437bool M68kOperand::isARID() const {
438 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
439 M68k::AR32RegClass.contains(MemOp.OuterReg);
440}
441void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {
442 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
444}
445
446
447bool M68kOperand::isARII() const {
448 return isMemOp() &&
449 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
450 M68k::AR32RegClass.contains(MemOp.OuterReg);
451}
452void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {
453 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
456}
457
458
459bool M68kOperand::isARIPD() const {
460 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
461 M68k::AR32RegClass.contains(MemOp.OuterReg);
462}
463void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
465}
466
467
468bool M68kOperand::isARIPI() const {
469 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
470 M68k::AR32RegClass.contains(MemOp.OuterReg);
471}
472void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
474}
475
476
477bool M68kOperand::isPCD() const {
478 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
479 MemOp.OuterReg == M68k::PC;
480}
481void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
482 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
483}
484
485
486bool M68kOperand::isPCI() const {
487 return isMemOp() &&
488 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
489 MemOp.OuterReg == M68k::PC;
490}
491void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
492 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
494}
495
497 bool SP, bool FPDR = false,
498 bool FPCR = false) {
499 switch (RegNo) {
500 case M68k::A0:
501 case M68k::A1:
502 case M68k::A2:
503 case M68k::A3:
504 case M68k::A4:
505 case M68k::A5:
506 case M68k::A6:
507 return Address;
508
509 case M68k::SP:
510 return SP;
511
512 case M68k::D0:
513 case M68k::D1:
514 case M68k::D2:
515 case M68k::D3:
516 case M68k::D4:
517 case M68k::D5:
518 case M68k::D6:
519 case M68k::D7:
521
522 case M68k::SR:
523 case M68k::CCR:
524 return false;
525
526 case M68k::FP0:
527 case M68k::FP1:
528 case M68k::FP2:
529 case M68k::FP3:
530 case M68k::FP4:
531 case M68k::FP5:
532 case M68k::FP6:
533 case M68k::FP7:
534 return FPDR;
535
536 case M68k::FPC:
537 case M68k::FPS:
538 case M68k::FPIAR:
539 return FPCR;
540
541 default:
543 return false;
544 }
545}
546
547bool M68kOperand::isAReg() const {
549 false,
550 true, true);
551}
552
553bool M68kOperand::isDReg() const {
555 true,
556 false, false);
557}
558
559bool M68kOperand::isFPDReg() const {
561 false,
562 false, false,
563 true);
564}
565
566bool M68kOperand::isFPCReg() const {
568 false,
569 false, false,
570 false, true);
571}
572
573unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
574 unsigned Kind) {
575 M68kOperand &Operand = (M68kOperand &)Op;
576
577 switch (Kind) {
578 case MCK_XR16:
579 case MCK_SPILL:
580 if (Operand.isReg() &&
582 return Match_Success;
583 }
584 break;
585
586 case MCK_AR16:
587 case MCK_AR32:
588 if (Operand.isReg() &&
590 return Match_Success;
591 }
592 break;
593
594 case MCK_AR32_NOSP:
595 if (Operand.isReg() &&
597 return Match_Success;
598 }
599 break;
600
601 case MCK_DR8:
602 case MCK_DR16:
603 case MCK_DR32:
604 if (Operand.isReg() &&
606 return Match_Success;
607 }
608 break;
609
610 case MCK_AR16_TC:
611 if (Operand.isReg() &&
612 ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
613 return Match_Success;
614 }
615 break;
616
617 case MCK_DR16_TC:
618 if (Operand.isReg() &&
619 ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
620 return Match_Success;
621 }
622 break;
623
624 case MCK_XR16_TC:
625 if (Operand.isReg() &&
626 ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
627 (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
628 return Match_Success;
629 }
630 break;
631 }
632
633 return Match_InvalidOperand;
634}
635
636bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc,
637 StringRef RegisterName) {
638 auto RegisterNameLower = RegisterName.lower();
639
640
641 if (RegisterNameLower == "ccr") {
642 RegNo = M68k::CCR;
643 return true;
644 } else if (RegisterNameLower == "sr") {
645 RegNo = M68k::SR;
646 return true;
647 }
648
649
650 if (RegisterNameLower.size() == 2) {
651
652 switch (RegisterNameLower[0]) {
653 case 'd':
654 case 'a': {
655 if (isdigit(RegisterNameLower[1])) {
656 unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
657 unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
658 if (RegIndex < 8) {
660 return true;
661 }
662 }
663 break;
664 }
665
666 case 's':
667 if (RegisterNameLower[1] == 'p') {
668 RegNo = M68k::SP;
669 return true;
670 } else if (RegisterNameLower[1] == 'r') {
671 RegNo = M68k::SR;
672 return true;
673 }
674 break;
675
676 case 'p':
677 if (RegisterNameLower[1] == 'c') {
678 RegNo = M68k::PC;
679 return true;
680 }
681 break;
682 }
683 } else if (StringRef(RegisterNameLower).starts_with("fp") &&
684 RegisterNameLower.size() > 2) {
685 auto RegIndex = unsigned(RegisterNameLower[2] - '0');
686 if (RegIndex < 8 && RegisterNameLower.size() == 3) {
687
689 return true;
690 } else {
691
692 RegNo = StringSwitch(RegisterNameLower)
693 .Cases({"fpc", "fpcr"}, M68k::FPC)
694 .Cases({"fps", "fpsr"}, M68k::FPS)
695 .Cases({"fpi", "fpiar"}, M68k::FPIAR)
696 .Default(M68k::NoRegister);
697 assert(RegNo != M68k::NoRegister &&
698 "Unrecognized FP control register name");
699 return true;
700 }
701 }
702
703 return false;
704}
705
706ParseStatus M68kAsmParser::parseRegister(MCRegister &RegNo) {
707 bool HasPercent = false;
708 AsmToken PercentToken;
709
711
713 HasPercent = true;
714 PercentToken = Lex();
717 }
718
720 if (HasPercent) {
721 getLexer().UnLex(PercentToken);
722 }
724 }
725
727 if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
728 if (HasPercent) {
729 getLexer().UnLex(PercentToken);
730 }
732 }
733
734 Parser.Lex();
736}
737
738bool M68kAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
739 SMLoc &EndLoc) {
740 ParseStatus Result = tryParseRegister(Reg, StartLoc, EndLoc);
741 if (.isSuccess())
742 return Error(StartLoc, "expected register");
743
744 return false;
745}
746
747ParseStatus M68kAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
748 SMLoc &EndLoc) {
749 StartLoc = getLexer().getLoc();
750 ParseStatus Result = parseRegister(Reg);
751 EndLoc = getLexer().getLoc();
753}
754
755bool M68kAsmParser::isExpr() {
759 return true;
762
763 default:
764 return false;
765 }
766}
767
768ParseStatus M68kAsmParser::parseImm(OperandVector &Operands) {
771 SMLoc Start = getLexer().getLoc();
772 Parser.Lex();
773
774 SMLoc End;
775 const MCExpr *Expr;
776
777 if (getParser().parseExpression(Expr, End))
779
780 Operands.push_back(M68kOperand::createImm(Expr, Start, End));
782}
783
784ParseStatus M68kAsmParser::parseMemOp(OperandVector &Operands) {
785 SMLoc Start = getLexer().getLoc();
786 bool IsPD = false;
787 M68kMemOp MemOp;
788
789
790 ParseStatus Result = parseRegOrMoveMask(Operands);
791 if (.isNoMatch())
793
794
795 bool HasDisplacement = false;
797 IsPD = true;
798 Parser.Lex();
799 } else if (isExpr()) {
802 HasDisplacement = true;
803 }
804
806 if (HasDisplacement) {
807 MemOp.Op = M68kMemOp::Kind::Addr;
809 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
811 }
812 if (IsPD)
813 return Error(getLexer().getLoc(), "expected (");
814
816 }
817 Parser.Lex();
818
819
820 if (!HasDisplacement && isExpr()) {
823 HasDisplacement = true;
824
825
827 MemOp.Op = M68kMemOp::Kind::Addr;
829 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
831 }
832
833 Parser.Lex();
834 }
835
836 Result = parseRegister(MemOp.OuterReg);
837 if (Result.isFailure())
839
840 if (.isSuccess())
841 return Error(getLexer().getLoc(), "expected register");
842
843
846 Parser.Lex();
847
848 Result = parseRegister(MemOp.InnerReg);
849 if (Result.isFailure())
851
852 if (Result.isNoMatch())
853 return Error(getLexer().getLoc(), "expected register");
854
855
856 MemOp.Size = 4;
857 MemOp.Scale = 1;
860 }
861
863 return Error(getLexer().getLoc(), "expected )");
864 Parser.Lex();
865
866 bool IsPI = false;
868 Parser.Lex();
869 IsPI = true;
870 }
871
872 SMLoc End = getLexer().getLoc();
873
874 unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
875 if (OpCount > 1)
876 return Error(Start, "only one of post-increment, pre-decrement or "
877 "displacement can be used");
878
879 if (IsPD) {
880 MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
881 } else if (IsPI) {
882 MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
883 } else if (HasIndex) {
884 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
885 } else if (HasDisplacement) {
886 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
887 } else {
888 MemOp.Op = M68kMemOp::Kind::RegIndirect;
889 }
890
891 Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
893}
894
895ParseStatus M68kAsmParser::parseRegOrMoveMask(OperandVector &Operands) {
896 SMLoc Start = getLexer().getLoc();
897 M68kMemOp MemOp(M68kMemOp::Kind::RegMask);
898 MemOp.RegMask = 0;
899
900 for (;;) {
901 bool IsFirstRegister =
902 (MemOp.Op == M68kMemOp::Kind::RegMask) && (MemOp.RegMask == 0);
903
904 MCRegister FirstRegister;
905 ParseStatus Result = parseRegister(FirstRegister);
906 if (IsFirstRegister && Result.isNoMatch())
908 if (.isSuccess())
909 return Error(getLexer().getLoc(), "expected start register");
910
911 MCRegister LastRegister = FirstRegister;
913 Result = parseRegister(LastRegister);
914 if (.isSuccess())
915 return Error(getLexer().getLoc(), "expected end register");
916 }
917
918 unsigned FirstRegisterIndex = getRegisterIndex(FirstRegister);
920
921 uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1;
922 uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex;
923
924 if (IsFirstRegister && (FirstRegister == LastRegister)) {
925
926
927 MemOp.Op = M68kMemOp::Kind::Reg;
928 MemOp.OuterReg = FirstRegister;
929 } else {
930 if (MemOp.Op == M68kMemOp::Kind::Reg) {
931
932
933 MemOp.Op = M68kMemOp::Kind::RegMask;
935
936 if (MemOp.RegMask == 0)
937 return Error(getLexer().getLoc(),
938 "special registers cannot be used in register masks");
939 }
940
941 if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16))
942 return Error(getLexer().getLoc(),
943 "special registers cannot be used in register masks");
944
945 if (NewMaskBits & MemOp.RegMask)
946 return Error(getLexer().getLoc(), "conflicting masked registers");
947
948 MemOp.RegMask |= NewMaskBits;
949 }
950
952 break;
953 }
954
956 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
958}
959
960void M68kAsmParser::eatComma() {
962 Parser.Lex();
963 }
964}
965
966bool M68kAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
968 SMLoc Start = getLexer().getLoc();
969 Operands.push_back(M68kOperand::createToken(Name, Start, Start));
970
971 bool First = true;
974 eatComma();
975 } else {
977 }
978
979 ParseStatus MatchResult = MatchOperandParserImpl(Operands, Name);
981 continue;
982
983
984 SMLoc Loc = getLexer().getLoc();
986 return Error(Loc, "unexpected token parsing operands");
987 }
988
989
990 Parser.Lex();
991 return false;
992}
993
994bool M68kAsmParser::invalidOperand(SMLoc Loc, OperandVector const &Operands,
995 uint64_t const &ErrorInfo) {
996 SMLoc ErrorLoc = Loc;
997 char const *Diag = 0;
998
999 if (ErrorInfo != ~0U) {
1000 if (ErrorInfo >= Operands.size()) {
1001 Diag = "too few operands for instruction.";
1002 } else {
1003 auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
1004 if (Op.getStartLoc() != SMLoc()) {
1005 ErrorLoc = Op.getStartLoc();
1006 }
1007 }
1008 }
1009
1010 if (!Diag) {
1011 Diag = "invalid operand for instruction";
1012 }
1013
1014 return Error(ErrorLoc, Diag);
1015}
1016
1017bool M68kAsmParser::missingFeature(SMLoc Loc, uint64_t const &ErrorInfo) {
1018 return Error(Loc, "instruction requires a CPU feature not currently enabled");
1019}
1020
1021bool M68kAsmParser::emit(MCInst &Inst, SMLoc Loc, MCStreamer &Out) const {
1024
1025 return false;
1026}
1027
1028bool M68kAsmParser::matchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
1030 MCStreamer &Out,
1031 uint64_t &ErrorInfo,
1032 bool MatchingInlineAsm) {
1033 MCInst Inst;
1034 unsigned MatchResult =
1035 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
1036
1037 switch (MatchResult) {
1038 case Match_Success:
1039 return emit(Inst, Loc, Out);
1040 case Match_MissingFeature:
1041 return missingFeature(Loc, ErrorInfo);
1042 case Match_InvalidOperand:
1043 return invalidOperand(Loc, Operands, ErrorInfo);
1044 case Match_MnemonicFail:
1045 return Error(Loc, "invalid instruction");
1046 default:
1047 return true;
1048 }
1049}
1050
1051void M68kOperand::print(raw_ostream &OS, const MCAsmInfo &MAI) const {
1052 switch (Kind) {
1053 case KindTy::Invalid:
1054 OS << "invalid";
1055 break;
1056
1057 case KindTy::Token:
1058 OS << "token '" << Token << "'";
1059 break;
1060
1061 case KindTy::Imm: {
1063 Expr->evaluateAsAbsolute(Value);
1064 OS << "immediate " << Value;
1065 break;
1066 }
1067
1068 case KindTy::MemOp:
1069 MemOp.print(OS);
1070 break;
1071 }
1072}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
Analysis containing CSE Info
#define LLVM_EXTERNAL_VISIBILITY
static bool checkRegisterClass(unsigned RegNo, bool Data, bool Address, bool SP, bool FPDR=false, bool FPCR=false)
Definition M68kAsmParser.cpp:496
static cl::opt< bool > RegisterPrefixOptional("m68k-register-prefix-optional", cl::Hidden, cl::desc("Enable specifying registers without the % prefix"), cl::init(false))
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser()
Definition M68kAsmParser.cpp:226
static unsigned getRegisterByIndex(unsigned RegisterIndex)
Definition M68kAsmParser.cpp:234
static unsigned getRegisterIndex(unsigned Register)
Definition M68kAsmParser.cpp:245
This file contains the M68k implementation of the TargetInstrInfo class.
This file contains the declarations of the M68k MCAsmInfo properties.
This file contains the M68k implementation of the TargetRegisterInfo class.
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
SMLoc getLoc() const
Get the current source location.
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
bool is(TokenKind K) const
TokenKind getKind() const
Base class for user error types.
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
Generic assembler parser interface, for use by target specific assembly parsers.
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
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 MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
Interface to description of machine instruction set.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
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...
Wrapper class representing physical registers. Should be passed by value.
Streaming machine code generation interface.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
const FeatureBitset & getFeatureBits() const
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Ternary parse status returned by various parse* methods.
static constexpr StatusTy Failure
constexpr bool isSuccess() const
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Wrapper class representing virtual and physical registers.
Represents a location in source code.
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
LLVM_ABI std::string lower() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
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 - Return the argument parameter cast to the specified type.
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
DWARFExpression::Operation Op
Target & getTheM68kTarget()
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...