[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / M68k / AsmParser / M68kAsmParser.cpp
blob1e7854b9b79eab4f7961b89d00b8071345127c0e
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/MCParsedAsmOperand.h"
15 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
16 #include "llvm/MC/MCStreamer.h"
17 #include "llvm/Support/TargetRegistry.h"
19 #include <sstream>
21 #define DEBUG_TYPE "m68k-asm-parser"
23 using namespace llvm;
25 static cl::opt<bool> RegisterPrefixOptional(
26 "m68k-register-prefix-optional", cl::Hidden,
27 cl::desc("Enable specifying registers without the % prefix"),
28 cl::init(false));
30 namespace {
31 /// Parses M68k assembly from a stream.
32 class M68kAsmParser : public MCTargetAsmParser {
33 const MCSubtargetInfo &STI;
34 MCAsmParser &Parser;
35 const MCRegisterInfo *MRI;
37 #define GET_ASSEMBLER_HEADER
38 #include "M68kGenAsmMatcher.inc"
40 // Helpers for Match&Emit.
41 bool invalidOperand(const SMLoc &Loc, const OperandVector &Operands,
42 const uint64_t &ErrorInfo);
43 bool missingFeature(const SMLoc &Loc, const uint64_t &ErrorInfo);
44 bool emit(MCInst &Inst, SMLoc const &Loc, MCStreamer &Out) const;
45 bool parseRegisterName(unsigned int &RegNo, SMLoc Loc,
46 StringRef RegisterName);
47 OperandMatchResultTy parseRegister(unsigned int &RegNo);
49 // Parser functions.
50 void eatComma();
52 bool isExpr();
53 OperandMatchResultTy parseImm(OperandVector &Operands);
54 OperandMatchResultTy parseMemOp(OperandVector &Operands);
56 public:
57 M68kAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
58 const MCInstrInfo &MII, const MCTargetOptions &Options)
59 : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
60 MCAsmParserExtension::Initialize(Parser);
61 MRI = getContext().getRegisterInfo();
63 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
66 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
67 unsigned Kind) override;
68 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
69 OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
70 SMLoc &EndLoc) override;
71 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
72 SMLoc NameLoc, OperandVector &Operands) override;
73 bool ParseDirective(AsmToken DirectiveID) 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 Reg,
84 RegIndirect,
85 RegPostIncrement,
86 RegPreDecrement,
87 RegIndirectDisplacement,
88 RegIndirectDisplacementIndex,
91 // These variables are used for the following forms:
92 // Addr: (OuterDisp)
93 // Reg: %OuterReg
94 // RegIndirect: (%OuterReg)
95 // RegPostIncrement: (%OuterReg)+
96 // RegPreDecrement: -(%OuterReg)
97 // RegIndirectDisplacement: OuterDisp(%OuterReg)
98 // RegIndirectDisplacementIndex:
99 // OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)
101 Kind Op;
102 unsigned OuterReg;
103 unsigned InnerReg;
104 const MCExpr *OuterDisp;
105 const MCExpr *InnerDisp;
106 uint8_t Size : 4;
107 uint8_t Scale : 4;
108 const MCExpr *Expr;
110 M68kMemOp() {}
111 M68kMemOp(Kind Op) : Op(Op) {}
113 void print(raw_ostream &OS) const;
116 /// An parsed M68k assembly operand.
117 class M68kOperand : public MCParsedAsmOperand {
118 typedef MCParsedAsmOperand Base;
120 enum class Kind {
121 Invalid,
122 Token,
123 Imm,
124 MemOp,
127 Kind Kind;
128 SMLoc Start, End;
129 union {
130 StringRef Token;
131 int64_t Imm;
132 const MCExpr *Expr;
133 M68kMemOp MemOp;
136 template <unsigned N> bool isAddrN() const;
138 public:
139 M68kOperand(enum Kind Kind, SMLoc Start, SMLoc End)
140 : Base(), Kind(Kind), Start(Start), End(End) {}
142 SMLoc getStartLoc() const override { return Start; }
143 SMLoc getEndLoc() const override { return End; }
145 void print(raw_ostream &OS) const override;
147 bool isMem() const override { return false; }
148 bool isMemOp() const { return Kind == Kind::MemOp; }
150 static void addExpr(MCInst &Inst, const MCExpr *Expr);
152 // Reg
153 bool isReg() const override;
154 bool isAReg() const;
155 bool isDReg() const;
156 unsigned getReg() const override;
157 void addRegOperands(MCInst &Inst, unsigned N) const;
159 static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start,
160 SMLoc End);
162 // Token
163 bool isToken() const override;
164 StringRef getToken() const;
165 static std::unique_ptr<M68kOperand> createToken(StringRef Token, SMLoc Start,
166 SMLoc End);
168 // Imm
169 bool isImm() const override;
170 void addImmOperands(MCInst &Inst, unsigned N) const;
172 static std::unique_ptr<M68kOperand> createImm(const MCExpr *Expr, SMLoc Start,
173 SMLoc End);
175 // Addr
176 bool isAddr() const;
177 bool isAddr8() const { return isAddrN<8>(); }
178 bool isAddr16() const { return isAddrN<16>(); }
179 bool isAddr32() const { return isAddrN<32>(); }
180 void addAddrOperands(MCInst &Inst, unsigned N) const;
182 // ARI
183 bool isARI() const;
184 void addARIOperands(MCInst &Inst, unsigned N) const;
186 // ARID
187 bool isARID() const;
188 void addARIDOperands(MCInst &Inst, unsigned N) const;
190 // ARII
191 bool isARII() const;
192 void addARIIOperands(MCInst &Inst, unsigned N) const;
194 // ARIPD
195 bool isARIPD() const;
196 void addARIPDOperands(MCInst &Inst, unsigned N) const;
198 // ARIPI
199 bool isARIPI() const;
200 void addARIPIOperands(MCInst &Inst, unsigned N) const;
202 // PCD
203 bool isPCD() const;
204 void addPCDOperands(MCInst &Inst, unsigned N) const;
206 // PCI
207 bool isPCI() const;
208 void addPCIOperands(MCInst &Inst, unsigned N) const;
211 } // end anonymous namespace.
213 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() {
214 RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget());
217 #define GET_MATCHER_IMPLEMENTATION
218 #include "M68kGenAsmMatcher.inc"
220 void M68kMemOp::print(raw_ostream &OS) const {
221 switch (Op) {
222 case Kind::Addr:
223 OS << OuterDisp;
224 break;
225 case Kind::Reg:
226 OS << '%' << OuterReg;
227 break;
228 case Kind::RegIndirect:
229 OS << "(%" << OuterReg << ')';
230 break;
231 case Kind::RegPostIncrement:
232 OS << "(%" << OuterReg << ")+";
233 break;
234 case Kind::RegPreDecrement:
235 OS << "-(%" << OuterReg << ")";
236 break;
237 case Kind::RegIndirectDisplacement:
238 OS << OuterDisp << "(%" << OuterReg << ")";
239 break;
240 case Kind::RegIndirectDisplacementIndex:
241 OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size
242 << ", " << InnerDisp << ")";
243 break;
247 void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {
248 if (auto Const = dyn_cast<MCConstantExpr>(Expr)) {
249 Inst.addOperand(MCOperand::createImm(Const->getValue()));
250 return;
253 Inst.addOperand(MCOperand::createExpr(Expr));
256 // Reg
257 bool M68kOperand::isReg() const {
258 return Kind == Kind::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
261 unsigned M68kOperand::getReg() const {
262 assert(isReg());
263 return MemOp.OuterReg;
266 void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {
267 assert(isReg() && "wrong operand kind");
268 assert((N == 1) && "can only handle one register operand");
270 Inst.addOperand(MCOperand::createReg(getReg()));
273 std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,
274 SMLoc Start, SMLoc End) {
275 auto Op = std::make_unique<M68kOperand>(Kind::MemOp, Start, End);
276 Op->MemOp = MemOp;
277 return Op;
280 // Token
281 bool M68kOperand::isToken() const { return Kind == Kind::Token; }
282 StringRef M68kOperand::getToken() const {
283 assert(isToken());
284 return Token;
287 std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,
288 SMLoc Start, SMLoc End) {
289 auto Op = std::make_unique<M68kOperand>(Kind::Token, Start, End);
290 Op->Token = Token;
291 return Op;
294 // Imm
295 bool M68kOperand::isImm() const { return Kind == Kind::Imm; }
296 void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {
297 assert(isImm() && "wrong oeprand kind");
298 assert((N == 1) && "can only handle one register operand");
300 M68kOperand::addExpr(Inst, Expr);
303 std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,
304 SMLoc Start, SMLoc End) {
305 auto Op = std::make_unique<M68kOperand>(Kind::Imm, Start, End);
306 Op->Expr = Expr;
307 return Op;
310 // Addr
311 bool M68kOperand::isAddr() const {
312 return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
314 // TODO: Maybe we can also store the size of OuterDisp
315 // in Size?
316 template <unsigned N> bool M68kOperand::isAddrN() const {
317 if (isAddr()) {
318 int64_t Res;
319 if (MemOp.OuterDisp->evaluateAsAbsolute(Res))
320 return isInt<N>(Res);
321 return true;
323 return false;
325 void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
326 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
329 // ARI
330 bool M68kOperand::isARI() const {
331 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
332 M68k::AR32RegClass.contains(MemOp.OuterReg);
334 void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
335 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
338 // ARID
339 bool M68kOperand::isARID() const {
340 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
341 M68k::AR32RegClass.contains(MemOp.OuterReg);
343 void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {
344 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
345 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
348 // ARII
349 bool M68kOperand::isARII() const {
350 return isMemOp() &&
351 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
352 M68k::AR32RegClass.contains(MemOp.OuterReg);
354 void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {
355 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
356 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
357 Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
360 // ARIPD
361 bool M68kOperand::isARIPD() const {
362 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
363 M68k::AR32RegClass.contains(MemOp.OuterReg);
365 void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
366 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
369 // ARIPI
370 bool M68kOperand::isARIPI() const {
371 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
372 M68k::AR32RegClass.contains(MemOp.OuterReg);
374 void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
375 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
378 // PCD
379 bool M68kOperand::isPCD() const {
380 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
381 MemOp.OuterReg == M68k::PC;
383 void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
384 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
387 // PCI
388 bool M68kOperand::isPCI() const {
389 return isMemOp() &&
390 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
391 MemOp.OuterReg == M68k::PC;
393 void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
394 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
395 Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
398 static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
399 bool SP) {
400 switch (RegNo) {
401 case M68k::A0:
402 case M68k::A1:
403 case M68k::A2:
404 case M68k::A3:
405 case M68k::A4:
406 case M68k::A5:
407 case M68k::A6:
408 return Address;
410 case M68k::SP:
411 return SP;
413 case M68k::D0:
414 case M68k::D1:
415 case M68k::D2:
416 case M68k::D3:
417 case M68k::D4:
418 case M68k::D5:
419 case M68k::D6:
420 case M68k::D7:
421 return Data;
423 case M68k::SR:
424 case M68k::CCR:
425 return false;
427 default:
428 llvm_unreachable("unexpected register type");
429 return false;
433 bool M68kOperand::isAReg() const {
434 return isReg() && checkRegisterClass(getReg(),
435 /*Data=*/false,
436 /*Address=*/true, /*SP=*/true);
439 bool M68kOperand::isDReg() const {
440 return isReg() && checkRegisterClass(getReg(),
441 /*Data=*/true,
442 /*Address=*/false, /*SP=*/false);
445 unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
446 unsigned Kind) {
447 M68kOperand &Operand = (M68kOperand &)Op;
449 switch (Kind) {
450 case MCK_XR16:
451 case MCK_SPILL:
452 if (Operand.isReg() &&
453 checkRegisterClass(Operand.getReg(), true, true, true)) {
454 return Match_Success;
456 break;
458 case MCK_AR16:
459 case MCK_AR32:
460 if (Operand.isReg() &&
461 checkRegisterClass(Operand.getReg(), false, true, true)) {
462 return Match_Success;
464 break;
466 case MCK_AR32_NOSP:
467 if (Operand.isReg() &&
468 checkRegisterClass(Operand.getReg(), false, true, false)) {
469 return Match_Success;
471 break;
473 case MCK_DR8:
474 case MCK_DR16:
475 case MCK_DR32:
476 if (Operand.isReg() &&
477 checkRegisterClass(Operand.getReg(), true, false, false)) {
478 return Match_Success;
480 break;
482 case MCK_AR16_TC:
483 if (Operand.isReg() &&
484 ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
485 return Match_Success;
487 break;
489 case MCK_DR16_TC:
490 if (Operand.isReg() &&
491 ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
492 return Match_Success;
494 break;
496 case MCK_XR16_TC:
497 if (Operand.isReg() &&
498 ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
499 (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
500 return Match_Success;
502 break;
505 return Match_InvalidOperand;
508 bool M68kAsmParser::parseRegisterName(unsigned &RegNo, SMLoc Loc,
509 StringRef RegisterName) {
510 auto RegisterNameLower = RegisterName.lower();
512 // CCR register
513 if (RegisterNameLower == "ccr") {
514 RegNo = M68k::CCR;
515 return true;
518 // Parse simple general-purpose registers.
519 if (RegisterNameLower.size() == 2) {
520 static unsigned RegistersByIndex[] = {
521 M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
522 M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
523 M68k::A4, M68k::A5, M68k::A6, M68k::SP,
526 switch (RegisterNameLower[0]) {
527 case 'd':
528 case 'a': {
529 if (isdigit(RegisterNameLower[1])) {
530 unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
531 unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
532 if (RegIndex < 8) {
533 RegNo = RegistersByIndex[IndexOffset + RegIndex];
534 return true;
537 break;
540 case 's':
541 if (RegisterNameLower[1] == 'p') {
542 RegNo = M68k::SP;
543 return true;
544 } else if (RegisterNameLower[1] == 'r') {
545 RegNo = M68k::SR;
546 return true;
548 break;
550 case 'p':
551 if (RegisterNameLower[1] == 'c') {
552 RegNo = M68k::PC;
553 return true;
555 break;
559 return false;
562 OperandMatchResultTy M68kAsmParser::parseRegister(unsigned &RegNo) {
563 bool HasPercent = false;
564 AsmToken PercentToken;
566 LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
568 if (getTok().is(AsmToken::Percent)) {
569 HasPercent = true;
570 PercentToken = Lex();
571 } else if (!RegisterPrefixOptional.getValue()) {
572 return MatchOperand_NoMatch;
575 if (!Parser.getTok().is(AsmToken::Identifier)) {
576 if (HasPercent) {
577 getLexer().UnLex(PercentToken);
579 return MatchOperand_NoMatch;
582 auto RegisterName = Parser.getTok().getString();
583 if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
584 if (HasPercent) {
585 getLexer().UnLex(PercentToken);
587 return MatchOperand_NoMatch;
590 Parser.Lex();
591 return MatchOperand_Success;
594 bool M68kAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
595 SMLoc &EndLoc) {
596 auto Result = tryParseRegister(RegNo, StartLoc, EndLoc);
597 if (Result != MatchOperand_Success) {
598 return Error(StartLoc, "expected register");
601 return false;
604 OperandMatchResultTy M68kAsmParser::tryParseRegister(unsigned &RegNo,
605 SMLoc &StartLoc,
606 SMLoc &EndLoc) {
607 StartLoc = getLexer().getLoc();
608 auto Result = parseRegister(RegNo);
609 EndLoc = getLexer().getLoc();
610 return Result;
613 bool M68kAsmParser::isExpr() {
614 switch (Parser.getTok().getKind()) {
615 case AsmToken::Identifier:
616 case AsmToken::Integer:
617 return true;
618 case AsmToken::Minus:
619 return getLexer().peekTok().getKind() == AsmToken::Integer;
621 default:
622 return false;
626 OperandMatchResultTy M68kAsmParser::parseImm(OperandVector &Operands) {
627 if (getLexer().isNot(AsmToken::Hash)) {
628 return MatchOperand_NoMatch;
630 SMLoc Start = getLexer().getLoc();
631 Parser.Lex();
633 SMLoc End;
634 const MCExpr *Expr;
636 if (getParser().parseExpression(Expr, End)) {
637 return MatchOperand_ParseFail;
640 Operands.push_back(M68kOperand::createImm(Expr, Start, End));
641 return MatchOperand_Success;
644 OperandMatchResultTy M68kAsmParser::parseMemOp(OperandVector &Operands) {
645 SMLoc Start = getLexer().getLoc();
646 bool IsPD = false;
647 M68kMemOp MemOp;
649 // Check for a plain register.
650 auto Result = parseRegister(MemOp.OuterReg);
651 if (Result == MatchOperand_Success) {
652 MemOp.Op = M68kMemOp::Kind::Reg;
653 Operands.push_back(
654 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
655 return MatchOperand_Success;
658 if (Result == MatchOperand_ParseFail) {
659 return Result;
662 // Check for pre-decrement & outer displacement.
663 bool HasDisplacement = false;
664 if (getLexer().is(AsmToken::Minus)) {
665 IsPD = true;
666 Parser.Lex();
667 } else if (isExpr()) {
668 if (Parser.parseExpression(MemOp.OuterDisp)) {
669 return MatchOperand_ParseFail;
671 HasDisplacement = true;
674 if (getLexer().isNot(AsmToken::LParen)) {
675 if (HasDisplacement) {
676 MemOp.Op = M68kMemOp::Kind::Addr;
677 Operands.push_back(
678 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
679 return MatchOperand_Success;
680 } else if (IsPD) {
681 Error(getLexer().getLoc(), "expected (");
682 return MatchOperand_ParseFail;
685 return MatchOperand_NoMatch;
687 Parser.Lex();
689 // Check for constant dereference & MIT-style displacement
690 if (!HasDisplacement && isExpr()) {
691 if (Parser.parseExpression(MemOp.OuterDisp)) {
692 return MatchOperand_ParseFail;
694 HasDisplacement = true;
696 // If we're not followed by a comma, we're a constant dereference.
697 if (getLexer().isNot(AsmToken::Comma)) {
698 MemOp.Op = M68kMemOp::Kind::Addr;
699 Operands.push_back(
700 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
701 return MatchOperand_Success;
704 Parser.Lex();
707 Result = parseRegister(MemOp.OuterReg);
708 if (Result == MatchOperand_ParseFail) {
709 return MatchOperand_ParseFail;
712 if (Result != MatchOperand_Success) {
713 Error(getLexer().getLoc(), "expected register");
714 return MatchOperand_ParseFail;
717 // Check for Index.
718 bool HasIndex = false;
719 if (Parser.getTok().is(AsmToken::Comma)) {
720 Parser.Lex();
722 Result = parseRegister(MemOp.InnerReg);
723 if (Result == MatchOperand_ParseFail) {
724 return Result;
727 if (Result == MatchOperand_NoMatch) {
728 Error(getLexer().getLoc(), "expected register");
729 return MatchOperand_ParseFail;
732 // TODO: parse size, scale and inner displacement.
733 MemOp.Size = 4;
734 MemOp.Scale = 1;
735 MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);
736 HasIndex = true;
739 if (Parser.getTok().isNot(AsmToken::RParen)) {
740 Error(getLexer().getLoc(), "expected )");
741 return MatchOperand_ParseFail;
743 Parser.Lex();
745 bool IsPI = false;
746 if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {
747 Parser.Lex();
748 IsPI = true;
751 SMLoc End = getLexer().getLoc();
753 unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
754 if (OpCount > 1) {
755 Error(Start, "only one of post-increment, pre-decrement or displacement "
756 "can be used");
757 return MatchOperand_ParseFail;
760 if (IsPD) {
761 MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
762 } else if (IsPI) {
763 MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
764 } else if (HasIndex) {
765 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
766 } else if (HasDisplacement) {
767 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
768 } else {
769 MemOp.Op = M68kMemOp::Kind::RegIndirect;
772 Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
773 return MatchOperand_Success;
776 void M68kAsmParser::eatComma() {
777 if (Parser.getTok().is(AsmToken::Comma)) {
778 Parser.Lex();
782 bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
783 SMLoc NameLoc, OperandVector &Operands) {
784 SMLoc Start = getLexer().getLoc();
785 Operands.push_back(M68kOperand::createToken(Name, Start, Start));
787 bool First = true;
788 while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
789 if (!First) {
790 eatComma();
791 } else {
792 First = false;
795 auto MatchResult = MatchOperandParserImpl(Operands, Name);
796 if (MatchResult == MatchOperand_Success) {
797 continue;
800 // Add custom operand formats here...
801 SMLoc Loc = getLexer().getLoc();
802 Parser.eatToEndOfStatement();
803 return Error(Loc, "unexpected token parsing operands");
806 // Eat EndOfStatement.
807 Parser.Lex();
808 return false;
811 bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
813 bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
814 OperandVector const &Operands,
815 uint64_t const &ErrorInfo) {
816 SMLoc ErrorLoc = Loc;
817 char const *Diag = 0;
819 if (ErrorInfo != ~0U) {
820 if (ErrorInfo >= Operands.size()) {
821 Diag = "too few operands for instruction.";
822 } else {
823 auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
824 if (Op.getStartLoc() != SMLoc()) {
825 ErrorLoc = Op.getStartLoc();
830 if (!Diag) {
831 Diag = "invalid operand for instruction";
834 return Error(ErrorLoc, Diag);
837 bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc,
838 uint64_t const &ErrorInfo) {
839 return Error(Loc, "instruction requires a CPU feature not currently enabled");
842 bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc,
843 MCStreamer &Out) const {
844 Inst.setLoc(Loc);
845 Out.emitInstruction(Inst, STI);
847 return false;
850 bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
851 OperandVector &Operands,
852 MCStreamer &Out,
853 uint64_t &ErrorInfo,
854 bool MatchingInlineAsm) {
855 MCInst Inst;
856 unsigned MatchResult =
857 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
859 switch (MatchResult) {
860 case Match_Success:
861 return emit(Inst, Loc, Out);
862 case Match_MissingFeature:
863 return missingFeature(Loc, ErrorInfo);
864 case Match_InvalidOperand:
865 return invalidOperand(Loc, Operands, ErrorInfo);
866 case Match_MnemonicFail:
867 return Error(Loc, "invalid instruction");
868 default:
869 return true;
873 void M68kOperand::print(raw_ostream &OS) const {
874 switch (Kind) {
875 case Kind::Invalid:
876 OS << "invalid";
877 break;
879 case Kind::Token:
880 OS << "token '" << Token << "'";
881 break;
883 case Kind::Imm:
884 OS << "immediate " << Imm;
885 break;
887 case Kind::MemOp:
888 MemOp.print(OS);
889 break;