[Darwin][Driver][clang] apple-none-macho orders the resource directory after internal...
[llvm-project.git] / llvm / lib / Target / M68k / AsmParser / M68kAsmParser.cpp
blob3a0d9dd316d824496b29440eb35ccc36bdb58ed7
1 //===-- M68kAsmParser.cpp - Parse M68k 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 //===----------------------------------------------------------------------===//
9 #include "M68kInstrInfo.h"
10 #include "M68kRegisterInfo.h"
11 #include "TargetInfo/M68kTargetInfo.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCParser/MCAsmLexer.h"
15 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
16 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
17 #include "llvm/MC/MCStreamer.h"
18 #include "llvm/MC/TargetRegistry.h"
20 #include <sstream>
22 #define DEBUG_TYPE "m68k-asm-parser"
24 using namespace llvm;
26 static cl::opt<bool> RegisterPrefixOptional(
27 "m68k-register-prefix-optional", cl::Hidden,
28 cl::desc("Enable specifying registers without the % prefix"),
29 cl::init(false));
31 namespace {
32 /// Parses M68k assembly from a stream.
33 class M68kAsmParser : public MCTargetAsmParser {
34 const MCSubtargetInfo &STI;
35 MCAsmParser &Parser;
36 const MCRegisterInfo *MRI;
38 #define GET_ASSEMBLER_HEADER
39 #include "M68kGenAsmMatcher.inc"
41 // Helpers for Match&Emit.
42 bool invalidOperand(const SMLoc &Loc, const OperandVector &Operands,
43 const uint64_t &ErrorInfo);
44 bool missingFeature(const SMLoc &Loc, const uint64_t &ErrorInfo);
45 bool emit(MCInst &Inst, SMLoc const &Loc, MCStreamer &Out) const;
46 bool parseRegisterName(MCRegister &RegNo, SMLoc Loc, StringRef RegisterName);
47 ParseStatus parseRegister(MCRegister &RegNo);
49 // Parser functions.
50 void eatComma();
52 bool isExpr();
53 ParseStatus parseImm(OperandVector &Operands);
54 ParseStatus parseMemOp(OperandVector &Operands);
55 ParseStatus parseRegOrMoveMask(OperandVector &Operands);
57 public:
58 M68kAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
59 const MCInstrInfo &MII, const MCTargetOptions &Options)
60 : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
61 MCAsmParserExtension::Initialize(Parser);
62 MRI = getContext().getRegisterInfo();
64 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
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,
73 SMLoc NameLoc, OperandVector &Operands) override;
74 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
75 OperandVector &Operands, MCStreamer &Out,
76 uint64_t &ErrorInfo,
77 bool MatchingInlineAsm) override;
80 struct M68kMemOp {
81 enum class Kind {
82 Addr,
83 RegMask,
84 Reg,
85 RegIndirect,
86 RegPostIncrement,
87 RegPreDecrement,
88 RegIndirectDisplacement,
89 RegIndirectDisplacementIndex,
92 // These variables are used for the following forms:
93 // Addr: (OuterDisp)
94 // RegMask: RegMask (as register mask)
95 // Reg: %OuterReg
96 // RegIndirect: (%OuterReg)
97 // RegPostIncrement: (%OuterReg)+
98 // RegPreDecrement: -(%OuterReg)
99 // RegIndirectDisplacement: OuterDisp(%OuterReg)
100 // RegIndirectDisplacementIndex:
101 // OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)
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;
113 M68kMemOp() {}
114 M68kMemOp(Kind Op) : Op(Op) {}
116 void print(raw_ostream &OS) const;
119 /// An parsed M68k assembly operand.
120 class M68kOperand : public MCParsedAsmOperand {
121 typedef MCParsedAsmOperand Base;
123 enum class KindTy {
124 Invalid,
125 Token,
126 Imm,
127 MemOp,
130 KindTy Kind;
131 SMLoc Start, End;
132 union {
133 StringRef Token;
134 const MCExpr *Expr;
135 M68kMemOp MemOp;
138 template <unsigned N> bool isAddrN() const;
140 public:
141 M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)
142 : Base(), Kind(Kind), Start(Start), End(End) {}
144 SMLoc getStartLoc() const override { return Start; }
145 SMLoc getEndLoc() const override { return End; }
147 void print(raw_ostream &OS) const override;
149 bool isMem() const override { return false; }
150 bool isMemOp() const { return Kind == KindTy::MemOp; }
152 static void addExpr(MCInst &Inst, const MCExpr *Expr);
154 // Reg
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;
163 static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start,
164 SMLoc End);
166 // Token
167 bool isToken() const override;
168 StringRef getToken() const;
169 static std::unique_ptr<M68kOperand> createToken(StringRef Token, SMLoc Start,
170 SMLoc End);
172 // Imm
173 bool isImm() const override;
174 void addImmOperands(MCInst &Inst, unsigned N) const;
176 static std::unique_ptr<M68kOperand> createImm(const MCExpr *Expr, SMLoc Start,
177 SMLoc End);
179 // Imm for TRAP instruction
180 bool isTrapImm() const;
181 // Imm for BKPT instruction
182 bool isBkptImm() const;
184 // MoveMask
185 bool isMoveMask() const;
186 void addMoveMaskOperands(MCInst &Inst, unsigned N) const;
188 // Addr
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;
195 // ARI
196 bool isARI() const;
197 void addARIOperands(MCInst &Inst, unsigned N) const;
199 // ARID
200 bool isARID() const;
201 void addARIDOperands(MCInst &Inst, unsigned N) const;
203 // ARII
204 bool isARII() const;
205 void addARIIOperands(MCInst &Inst, unsigned N) const;
207 // ARIPD
208 bool isARIPD() const;
209 void addARIPDOperands(MCInst &Inst, unsigned N) const;
211 // ARIPI
212 bool isARIPI() const;
213 void addARIPIOperands(MCInst &Inst, unsigned N) const;
215 // PCD
216 bool isPCD() const;
217 void addPCDOperands(MCInst &Inst, unsigned N) const;
219 // PCI
220 bool isPCI() const;
221 void addPCIOperands(MCInst &Inst, unsigned N) const;
224 } // end anonymous namespace.
226 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() {
227 RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget());
230 #define GET_REGISTER_MATCHER
231 #define GET_MATCHER_IMPLEMENTATION
232 #include "M68kGenAsmMatcher.inc"
234 static inline unsigned getRegisterByIndex(unsigned RegisterIndex) {
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];
245 static inline unsigned getRegisterIndex(unsigned Register) {
246 if (Register >= M68k::D0 && Register <= M68k::D7)
247 return Register - M68k::D0;
248 if (Register >= M68k::A0 && Register <= M68k::A6)
249 return Register - M68k::A0 + 8;
250 if (Register >= M68k::FP0 && Register <= M68k::FP7)
251 return Register - M68k::FP0 + 16;
253 switch (Register) {
254 case M68k::SP:
255 // SP is sadly not contiguous with the rest of the An registers
256 return 15;
258 // We don't care about the indices of these registers.
259 case M68k::PC:
260 case M68k::CCR:
261 case M68k::FPC:
262 case M68k::FPS:
263 case M68k::FPIAR:
264 return UINT_MAX;
266 default:
267 llvm_unreachable("unexpected register number");
271 void M68kMemOp::print(raw_ostream &OS) const {
272 switch (Op) {
273 case Kind::Addr:
274 OS << OuterDisp;
275 break;
276 case Kind::RegMask:
277 OS << "RegMask(" << format("%04x", RegMask) << ")";
278 break;
279 case Kind::Reg:
280 OS << '%' << OuterReg;
281 break;
282 case Kind::RegIndirect:
283 OS << "(%" << OuterReg << ')';
284 break;
285 case Kind::RegPostIncrement:
286 OS << "(%" << OuterReg << ")+";
287 break;
288 case Kind::RegPreDecrement:
289 OS << "-(%" << OuterReg << ")";
290 break;
291 case Kind::RegIndirectDisplacement:
292 OS << OuterDisp << "(%" << OuterReg << ")";
293 break;
294 case Kind::RegIndirectDisplacementIndex:
295 OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size
296 << ", " << InnerDisp << ")";
297 break;
301 void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {
302 if (auto Const = dyn_cast<MCConstantExpr>(Expr)) {
303 Inst.addOperand(MCOperand::createImm(Const->getValue()));
304 return;
307 Inst.addOperand(MCOperand::createExpr(Expr));
310 // Reg
311 bool M68kOperand::isReg() const {
312 return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
315 MCRegister M68kOperand::getReg() const {
316 assert(isReg());
317 return MemOp.OuterReg;
320 void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {
321 assert(isReg() && "wrong operand kind");
322 assert((N == 1) && "can only handle one register operand");
324 Inst.addOperand(MCOperand::createReg(getReg()));
327 std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,
328 SMLoc Start, SMLoc End) {
329 auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start, End);
330 Op->MemOp = MemOp;
331 return Op;
334 // Token
335 bool M68kOperand::isToken() const { return Kind == KindTy::Token; }
336 StringRef M68kOperand::getToken() const {
337 assert(isToken());
338 return Token;
341 std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,
342 SMLoc Start, SMLoc End) {
343 auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start, End);
344 Op->Token = Token;
345 return Op;
348 // Imm
349 bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }
350 void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {
351 assert(isImm() && "wrong operand kind");
352 assert((N == 1) && "can only handle one register operand");
354 M68kOperand::addExpr(Inst, Expr);
357 std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,
358 SMLoc Start, SMLoc End) {
359 auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start, End);
360 Op->Expr = Expr;
361 return Op;
364 bool M68kOperand::isTrapImm() const {
365 int64_t Value;
366 if (!isImm() || !Expr->evaluateAsAbsolute(Value))
367 return false;
369 return isUInt<4>(Value);
372 bool M68kOperand::isBkptImm() const {
373 int64_t Value;
374 if (!isImm() || !Expr->evaluateAsAbsolute(Value))
375 return false;
377 return isUInt<3>(Value);
380 // MoveMask
381 bool M68kOperand::isMoveMask() const {
382 if (!isMemOp())
383 return false;
385 if (MemOp.Op == M68kMemOp::Kind::RegMask)
386 return true;
388 if (MemOp.Op != M68kMemOp::Kind::Reg)
389 return false;
391 // Only regular address / data registers are allowed to be used
392 // in register masks.
393 return getRegisterIndex(MemOp.OuterReg) < 16;
396 void M68kOperand::addMoveMaskOperands(MCInst &Inst, unsigned N) const {
397 assert(isMoveMask() && "wrong operand kind");
398 assert((N == 1) && "can only handle one immediate operand");
400 uint16_t MoveMask = MemOp.RegMask;
401 if (MemOp.Op == M68kMemOp::Kind::Reg)
402 MoveMask = 1 << getRegisterIndex(MemOp.OuterReg);
404 Inst.addOperand(MCOperand::createImm(MoveMask));
407 // Addr
408 bool M68kOperand::isAddr() const {
409 return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
411 // TODO: Maybe we can also store the size of OuterDisp
412 // in Size?
413 template <unsigned N> bool M68kOperand::isAddrN() const {
414 if (isAddr()) {
415 int64_t Res;
416 if (MemOp.OuterDisp->evaluateAsAbsolute(Res))
417 return isInt<N>(Res);
418 return true;
420 return false;
422 void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
423 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
426 // ARI
427 bool M68kOperand::isARI() const {
428 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
429 M68k::AR32RegClass.contains(MemOp.OuterReg);
431 void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
432 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
435 // ARID
436 bool M68kOperand::isARID() const {
437 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
438 M68k::AR32RegClass.contains(MemOp.OuterReg);
440 void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {
441 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
442 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
445 // ARII
446 bool M68kOperand::isARII() const {
447 return isMemOp() &&
448 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
449 M68k::AR32RegClass.contains(MemOp.OuterReg);
451 void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {
452 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
453 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
454 Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
457 // ARIPD
458 bool M68kOperand::isARIPD() const {
459 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
460 M68k::AR32RegClass.contains(MemOp.OuterReg);
462 void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
463 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
466 // ARIPI
467 bool M68kOperand::isARIPI() const {
468 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
469 M68k::AR32RegClass.contains(MemOp.OuterReg);
471 void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
472 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
475 // PCD
476 bool M68kOperand::isPCD() const {
477 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
478 MemOp.OuterReg == M68k::PC;
480 void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
481 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
484 // PCI
485 bool M68kOperand::isPCI() const {
486 return isMemOp() &&
487 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
488 MemOp.OuterReg == M68k::PC;
490 void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
491 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
492 Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
495 static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
496 bool SP, bool FPDR = false,
497 bool FPCR = false) {
498 switch (RegNo) {
499 case M68k::A0:
500 case M68k::A1:
501 case M68k::A2:
502 case M68k::A3:
503 case M68k::A4:
504 case M68k::A5:
505 case M68k::A6:
506 return Address;
508 case M68k::SP:
509 return SP;
511 case M68k::D0:
512 case M68k::D1:
513 case M68k::D2:
514 case M68k::D3:
515 case M68k::D4:
516 case M68k::D5:
517 case M68k::D6:
518 case M68k::D7:
519 return Data;
521 case M68k::SR:
522 case M68k::CCR:
523 return false;
525 case M68k::FP0:
526 case M68k::FP1:
527 case M68k::FP2:
528 case M68k::FP3:
529 case M68k::FP4:
530 case M68k::FP5:
531 case M68k::FP6:
532 case M68k::FP7:
533 return FPDR;
535 case M68k::FPC:
536 case M68k::FPS:
537 case M68k::FPIAR:
538 return FPCR;
540 default:
541 llvm_unreachable("unexpected register type");
542 return false;
546 bool M68kOperand::isAReg() const {
547 return isReg() && checkRegisterClass(getReg(),
548 /*Data=*/false,
549 /*Address=*/true, /*SP=*/true);
552 bool M68kOperand::isDReg() const {
553 return isReg() && checkRegisterClass(getReg(),
554 /*Data=*/true,
555 /*Address=*/false, /*SP=*/false);
558 bool M68kOperand::isFPDReg() const {
559 return isReg() && checkRegisterClass(getReg(),
560 /*Data=*/false,
561 /*Address=*/false, /*SP=*/false,
562 /*FPDR=*/true);
565 bool M68kOperand::isFPCReg() const {
566 return isReg() && checkRegisterClass(getReg(),
567 /*Data=*/false,
568 /*Address=*/false, /*SP=*/false,
569 /*FPDR=*/false, /*FPCR=*/true);
572 unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
573 unsigned Kind) {
574 M68kOperand &Operand = (M68kOperand &)Op;
576 switch (Kind) {
577 case MCK_XR16:
578 case MCK_SPILL:
579 if (Operand.isReg() &&
580 checkRegisterClass(Operand.getReg(), true, true, true)) {
581 return Match_Success;
583 break;
585 case MCK_AR16:
586 case MCK_AR32:
587 if (Operand.isReg() &&
588 checkRegisterClass(Operand.getReg(), false, true, true)) {
589 return Match_Success;
591 break;
593 case MCK_AR32_NOSP:
594 if (Operand.isReg() &&
595 checkRegisterClass(Operand.getReg(), false, true, false)) {
596 return Match_Success;
598 break;
600 case MCK_DR8:
601 case MCK_DR16:
602 case MCK_DR32:
603 if (Operand.isReg() &&
604 checkRegisterClass(Operand.getReg(), true, false, false)) {
605 return Match_Success;
607 break;
609 case MCK_AR16_TC:
610 if (Operand.isReg() &&
611 ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
612 return Match_Success;
614 break;
616 case MCK_DR16_TC:
617 if (Operand.isReg() &&
618 ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
619 return Match_Success;
621 break;
623 case MCK_XR16_TC:
624 if (Operand.isReg() &&
625 ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
626 (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
627 return Match_Success;
629 break;
632 return Match_InvalidOperand;
635 bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc,
636 StringRef RegisterName) {
637 auto RegisterNameLower = RegisterName.lower();
639 // CCR register
640 if (RegisterNameLower == "ccr") {
641 RegNo = M68k::CCR;
642 return true;
645 // Parse simple general-purpose registers.
646 if (RegisterNameLower.size() == 2) {
648 switch (RegisterNameLower[0]) {
649 case 'd':
650 case 'a': {
651 if (isdigit(RegisterNameLower[1])) {
652 unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
653 unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
654 if (RegIndex < 8) {
655 RegNo = getRegisterByIndex(IndexOffset + RegIndex);
656 return true;
659 break;
662 case 's':
663 if (RegisterNameLower[1] == 'p') {
664 RegNo = M68k::SP;
665 return true;
666 } else if (RegisterNameLower[1] == 'r') {
667 RegNo = M68k::SR;
668 return true;
670 break;
672 case 'p':
673 if (RegisterNameLower[1] == 'c') {
674 RegNo = M68k::PC;
675 return true;
677 break;
679 } else if (StringRef(RegisterNameLower).starts_with("fp") &&
680 RegisterNameLower.size() > 2) {
681 auto RegIndex = unsigned(RegisterNameLower[2] - '0');
682 if (RegIndex < 8 && RegisterNameLower.size() == 3) {
683 // Floating point data register.
684 RegNo = getRegisterByIndex(16 + RegIndex);
685 return true;
686 } else {
687 // Floating point control register.
688 RegNo = StringSwitch<unsigned>(RegisterNameLower)
689 .Cases("fpc", "fpcr", M68k::FPC)
690 .Cases("fps", "fpsr", M68k::FPS)
691 .Cases("fpi", "fpiar", M68k::FPIAR)
692 .Default(M68k::NoRegister);
693 assert(RegNo != M68k::NoRegister &&
694 "Unrecognized FP control register name");
695 return true;
699 return false;
702 ParseStatus M68kAsmParser::parseRegister(MCRegister &RegNo) {
703 bool HasPercent = false;
704 AsmToken PercentToken;
706 LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
708 if (getTok().is(AsmToken::Percent)) {
709 HasPercent = true;
710 PercentToken = Lex();
711 } else if (!RegisterPrefixOptional.getValue()) {
712 return ParseStatus::NoMatch;
715 if (!Parser.getTok().is(AsmToken::Identifier)) {
716 if (HasPercent) {
717 getLexer().UnLex(PercentToken);
719 return ParseStatus::NoMatch;
722 auto RegisterName = Parser.getTok().getString();
723 if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
724 if (HasPercent) {
725 getLexer().UnLex(PercentToken);
727 return ParseStatus::NoMatch;
730 Parser.Lex();
731 return ParseStatus::Success;
734 bool M68kAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
735 SMLoc &EndLoc) {
736 ParseStatus Result = tryParseRegister(Reg, StartLoc, EndLoc);
737 if (!Result.isSuccess())
738 return Error(StartLoc, "expected register");
740 return false;
743 ParseStatus M68kAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
744 SMLoc &EndLoc) {
745 StartLoc = getLexer().getLoc();
746 ParseStatus Result = parseRegister(Reg);
747 EndLoc = getLexer().getLoc();
748 return Result;
751 bool M68kAsmParser::isExpr() {
752 switch (Parser.getTok().getKind()) {
753 case AsmToken::Identifier:
754 case AsmToken::Integer:
755 return true;
756 case AsmToken::Minus:
757 return getLexer().peekTok().getKind() == AsmToken::Integer;
759 default:
760 return false;
764 ParseStatus M68kAsmParser::parseImm(OperandVector &Operands) {
765 if (getLexer().isNot(AsmToken::Hash))
766 return ParseStatus::NoMatch;
767 SMLoc Start = getLexer().getLoc();
768 Parser.Lex();
770 SMLoc End;
771 const MCExpr *Expr;
773 if (getParser().parseExpression(Expr, End))
774 return ParseStatus::Failure;
776 Operands.push_back(M68kOperand::createImm(Expr, Start, End));
777 return ParseStatus::Success;
780 ParseStatus M68kAsmParser::parseMemOp(OperandVector &Operands) {
781 SMLoc Start = getLexer().getLoc();
782 bool IsPD = false;
783 M68kMemOp MemOp;
785 // Check for a plain register or register mask.
786 ParseStatus Result = parseRegOrMoveMask(Operands);
787 if (!Result.isNoMatch())
788 return Result;
790 // Check for pre-decrement & outer displacement.
791 bool HasDisplacement = false;
792 if (getLexer().is(AsmToken::Minus)) {
793 IsPD = true;
794 Parser.Lex();
795 } else if (isExpr()) {
796 if (Parser.parseExpression(MemOp.OuterDisp))
797 return ParseStatus::Failure;
798 HasDisplacement = true;
801 if (getLexer().isNot(AsmToken::LParen)) {
802 if (HasDisplacement) {
803 MemOp.Op = M68kMemOp::Kind::Addr;
804 Operands.push_back(
805 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
806 return ParseStatus::Success;
808 if (IsPD)
809 return Error(getLexer().getLoc(), "expected (");
811 return ParseStatus::NoMatch;
813 Parser.Lex();
815 // Check for constant dereference & MIT-style displacement
816 if (!HasDisplacement && isExpr()) {
817 if (Parser.parseExpression(MemOp.OuterDisp))
818 return ParseStatus::Failure;
819 HasDisplacement = true;
821 // If we're not followed by a comma, we're a constant dereference.
822 if (getLexer().isNot(AsmToken::Comma)) {
823 MemOp.Op = M68kMemOp::Kind::Addr;
824 Operands.push_back(
825 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
826 return ParseStatus::Success;
829 Parser.Lex();
832 Result = parseRegister(MemOp.OuterReg);
833 if (Result.isFailure())
834 return ParseStatus::Failure;
836 if (!Result.isSuccess())
837 return Error(getLexer().getLoc(), "expected register");
839 // Check for Index.
840 bool HasIndex = false;
841 if (Parser.getTok().is(AsmToken::Comma)) {
842 Parser.Lex();
844 Result = parseRegister(MemOp.InnerReg);
845 if (Result.isFailure())
846 return Result;
848 if (Result.isNoMatch())
849 return Error(getLexer().getLoc(), "expected register");
851 // TODO: parse size, scale and inner displacement.
852 MemOp.Size = 4;
853 MemOp.Scale = 1;
854 MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);
855 HasIndex = true;
858 if (Parser.getTok().isNot(AsmToken::RParen))
859 return Error(getLexer().getLoc(), "expected )");
860 Parser.Lex();
862 bool IsPI = false;
863 if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {
864 Parser.Lex();
865 IsPI = true;
868 SMLoc End = getLexer().getLoc();
870 unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
871 if (OpCount > 1)
872 return Error(Start, "only one of post-increment, pre-decrement or "
873 "displacement can be used");
875 if (IsPD) {
876 MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
877 } else if (IsPI) {
878 MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
879 } else if (HasIndex) {
880 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
881 } else if (HasDisplacement) {
882 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
883 } else {
884 MemOp.Op = M68kMemOp::Kind::RegIndirect;
887 Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
888 return ParseStatus::Success;
891 ParseStatus M68kAsmParser::parseRegOrMoveMask(OperandVector &Operands) {
892 SMLoc Start = getLexer().getLoc();
893 M68kMemOp MemOp(M68kMemOp::Kind::RegMask);
894 MemOp.RegMask = 0;
896 for (;;) {
897 bool IsFirstRegister =
898 (MemOp.Op == M68kMemOp::Kind::RegMask) && (MemOp.RegMask == 0);
900 MCRegister FirstRegister;
901 ParseStatus Result = parseRegister(FirstRegister);
902 if (IsFirstRegister && Result.isNoMatch())
903 return ParseStatus::NoMatch;
904 if (!Result.isSuccess())
905 return Error(getLexer().getLoc(), "expected start register");
907 MCRegister LastRegister = FirstRegister;
908 if (parseOptionalToken(AsmToken::Minus)) {
909 Result = parseRegister(LastRegister);
910 if (!Result.isSuccess())
911 return Error(getLexer().getLoc(), "expected end register");
914 unsigned FirstRegisterIndex = getRegisterIndex(FirstRegister);
915 unsigned LastRegisterIndex = getRegisterIndex(LastRegister);
917 uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1;
918 uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex;
920 if (IsFirstRegister && (FirstRegister == LastRegister)) {
921 // First register range is a single register, simplify to just Reg
922 // so that it matches more operands.
923 MemOp.Op = M68kMemOp::Kind::Reg;
924 MemOp.OuterReg = FirstRegister;
925 } else {
926 if (MemOp.Op == M68kMemOp::Kind::Reg) {
927 // This is the second register being specified - expand the Reg operand
928 // into a mask first.
929 MemOp.Op = M68kMemOp::Kind::RegMask;
930 MemOp.RegMask = 1 << getRegisterIndex(MemOp.OuterReg);
932 if (MemOp.RegMask == 0)
933 return Error(getLexer().getLoc(),
934 "special registers cannot be used in register masks");
937 if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16))
938 return Error(getLexer().getLoc(),
939 "special registers cannot be used in register masks");
941 if (NewMaskBits & MemOp.RegMask)
942 return Error(getLexer().getLoc(), "conflicting masked registers");
944 MemOp.RegMask |= NewMaskBits;
947 if (!parseOptionalToken(AsmToken::Slash))
948 break;
951 Operands.push_back(
952 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
953 return ParseStatus::Success;
956 void M68kAsmParser::eatComma() {
957 if (Parser.getTok().is(AsmToken::Comma)) {
958 Parser.Lex();
962 bool M68kAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
963 SMLoc NameLoc, OperandVector &Operands) {
964 SMLoc Start = getLexer().getLoc();
965 Operands.push_back(M68kOperand::createToken(Name, Start, Start));
967 bool First = true;
968 while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
969 if (!First) {
970 eatComma();
971 } else {
972 First = false;
975 ParseStatus MatchResult = MatchOperandParserImpl(Operands, Name);
976 if (MatchResult.isSuccess())
977 continue;
979 // Add custom operand formats here...
980 SMLoc Loc = getLexer().getLoc();
981 Parser.eatToEndOfStatement();
982 return Error(Loc, "unexpected token parsing operands");
985 // Eat EndOfStatement.
986 Parser.Lex();
987 return false;
990 bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
991 OperandVector const &Operands,
992 uint64_t const &ErrorInfo) {
993 SMLoc ErrorLoc = Loc;
994 char const *Diag = 0;
996 if (ErrorInfo != ~0U) {
997 if (ErrorInfo >= Operands.size()) {
998 Diag = "too few operands for instruction.";
999 } else {
1000 auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
1001 if (Op.getStartLoc() != SMLoc()) {
1002 ErrorLoc = Op.getStartLoc();
1007 if (!Diag) {
1008 Diag = "invalid operand for instruction";
1011 return Error(ErrorLoc, Diag);
1014 bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc,
1015 uint64_t const &ErrorInfo) {
1016 return Error(Loc, "instruction requires a CPU feature not currently enabled");
1019 bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc,
1020 MCStreamer &Out) const {
1021 Inst.setLoc(Loc);
1022 Out.emitInstruction(Inst, STI);
1024 return false;
1027 bool M68kAsmParser::matchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
1028 OperandVector &Operands,
1029 MCStreamer &Out,
1030 uint64_t &ErrorInfo,
1031 bool MatchingInlineAsm) {
1032 MCInst Inst;
1033 unsigned MatchResult =
1034 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
1036 switch (MatchResult) {
1037 case Match_Success:
1038 return emit(Inst, Loc, Out);
1039 case Match_MissingFeature:
1040 return missingFeature(Loc, ErrorInfo);
1041 case Match_InvalidOperand:
1042 return invalidOperand(Loc, Operands, ErrorInfo);
1043 case Match_MnemonicFail:
1044 return Error(Loc, "invalid instruction");
1045 default:
1046 return true;
1050 void M68kOperand::print(raw_ostream &OS) const {
1051 switch (Kind) {
1052 case KindTy::Invalid:
1053 OS << "invalid";
1054 break;
1056 case KindTy::Token:
1057 OS << "token '" << Token << "'";
1058 break;
1060 case KindTy::Imm: {
1061 int64_t Value;
1062 Expr->evaluateAsAbsolute(Value);
1063 OS << "immediate " << Value;
1064 break;
1067 case KindTy::MemOp:
1068 MemOp.print(OS);
1069 break;