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 //===----------------------------------------------------------------------===//
8 
9 #include "M68kInstrInfo.h"
10 #include "M68kRegisterInfo.h"
11 #include "TargetInfo/M68kTargetInfo.h"
12 
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"
18 
19 #include <sstream>
20 
21 #define DEBUG_TYPE "m68k-asm-parser"
22 
23 using namespace llvm;
24 
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));
29 
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;
36 
37 #define GET_ASSEMBLER_HEADER
38 #include "M68kGenAsmMatcher.inc"
39 
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);
48 
49   // Parser functions.
50   void eatComma();
51 
52   bool isExpr() const;
53   OperandMatchResultTy parseImm(OperandVector &Operands);
54   OperandMatchResultTy parseMemOp(OperandVector &Operands);
55 
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();
62 
63     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
64   }
65 
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;
78 };
79 
80 struct M68kMemOp {
81   enum class Kind {
82     Addr,
83     Reg,
84     RegIndirect,
85     RegPostIncrement,
86     RegPreDecrement,
87     RegIndirectDisplacement,
88     RegIndirectDisplacementIndex,
89   };
90 
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)
100 
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;
109 
110   M68kMemOp() {}
111   M68kMemOp(Kind Op) : Op(Op) {}
112 
113   void print(raw_ostream &OS) const;
114 };
115 
116 /// An parsed M68k assembly operand.
117 class M68kOperand : public MCParsedAsmOperand {
118   typedef MCParsedAsmOperand Base;
119 
120   enum class Kind {
121     Invalid,
122     Token,
123     Imm,
124     MemOp,
125   };
126 
127   Kind Kind;
128   SMLoc Start, End;
129   union {
130     StringRef Token;
131     int64_t Imm;
132     const MCExpr *Expr;
133     M68kMemOp MemOp;
134   };
135 
136 public:
137   M68kOperand(enum Kind Kind, SMLoc Start, SMLoc End)
138       : Base(), Kind(Kind), Start(Start), End(End) {}
139 
140   SMLoc getStartLoc() const override { return Start; }
141   SMLoc getEndLoc() const override { return End; }
142 
143   void print(raw_ostream &OS) const override;
144 
145   bool isMem() const override { return false; }
146   bool isMemOp() const { return Kind == Kind::MemOp; }
147 
148   static void addExpr(MCInst &Inst, const MCExpr *Expr);
149 
150   // Reg
151   bool isReg() const override;
152   unsigned getReg() const override;
153   void addRegOperands(MCInst &Inst, unsigned N) const;
154 
155   static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start,
156                                                   SMLoc End);
157 
158   // Token
159   bool isToken() const override;
160   StringRef getToken() const;
161   static std::unique_ptr<M68kOperand> createToken(StringRef Token, SMLoc Start,
162                                                   SMLoc End);
163 
164   // Imm
165   bool isImm() const override;
166   void addImmOperands(MCInst &Inst, unsigned N) const;
167 
168   static std::unique_ptr<M68kOperand> createImm(const MCExpr *Expr, SMLoc Start,
169                                                 SMLoc End);
170 
171   // Addr
172   bool isAddr() const;
173   void addAddrOperands(MCInst &Inst, unsigned N) const;
174 
175   // ARI
176   bool isARI() const;
177   void addARIOperands(MCInst &Inst, unsigned N) const;
178 
179   // ARID
180   bool isARID() const;
181   void addARIDOperands(MCInst &Inst, unsigned N) const;
182 
183   // ARII
184   bool isARII() const;
185   void addARIIOperands(MCInst &Inst, unsigned N) const;
186 
187   // ARIPD
188   bool isARIPD() const;
189   void addARIPDOperands(MCInst &Inst, unsigned N) const;
190 
191   // ARIPI
192   bool isARIPI() const;
193   void addARIPIOperands(MCInst &Inst, unsigned N) const;
194 
195   // PCD
196   bool isPCD() const;
197   void addPCDOperands(MCInst &Inst, unsigned N) const;
198 
199   // PCI
200   bool isPCI() const;
201   void addPCIOperands(MCInst &Inst, unsigned N) const;
202 };
203 
204 } // end anonymous namespace.
205 
206 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() {
207   RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget());
208 }
209 
210 #define GET_MATCHER_IMPLEMENTATION
211 #include "M68kGenAsmMatcher.inc"
212 
213 void M68kMemOp::print(raw_ostream &OS) const {
214   switch (Op) {
215   case Kind::Addr:
216     OS << OuterDisp;
217     break;
218   case Kind::Reg:
219     OS << '%' << OuterReg;
220     break;
221   case Kind::RegIndirect:
222     OS << "(%" << OuterReg << ')';
223     break;
224   case Kind::RegPostIncrement:
225     OS << "(%" << OuterReg << ")+";
226     break;
227   case Kind::RegPreDecrement:
228     OS << "-(%" << OuterReg << ")";
229     break;
230   case Kind::RegIndirectDisplacement:
231     OS << OuterDisp << "(%" << OuterReg << ")";
232     break;
233   case Kind::RegIndirectDisplacementIndex:
234     OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size
235        << ", " << InnerDisp << ")";
236     break;
237   }
238 }
239 
240 void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {
241   if (auto Const = dyn_cast<MCConstantExpr>(Expr)) {
242     Inst.addOperand(MCOperand::createImm(Const->getValue()));
243     return;
244   }
245 
246   Inst.addOperand(MCOperand::createExpr(Expr));
247 }
248 
249 // Reg
250 bool M68kOperand::isReg() const {
251   return Kind == Kind::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
252 }
253 
254 unsigned M68kOperand::getReg() const {
255   assert(isReg());
256   return MemOp.OuterReg;
257 }
258 
259 void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {
260   assert(isReg() && "wrong operand kind");
261   assert((N == 1) && "can only handle one register operand");
262 
263   Inst.addOperand(MCOperand::createReg(getReg()));
264 }
265 
266 std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,
267                                                       SMLoc Start, SMLoc End) {
268   auto Op = std::make_unique<M68kOperand>(Kind::MemOp, Start, End);
269   Op->MemOp = MemOp;
270   return Op;
271 }
272 
273 // Token
274 bool M68kOperand::isToken() const { return Kind == Kind::Token; }
275 StringRef M68kOperand::getToken() const {
276   assert(isToken());
277   return Token;
278 }
279 
280 std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,
281                                                       SMLoc Start, SMLoc End) {
282   auto Op = std::make_unique<M68kOperand>(Kind::Token, Start, End);
283   Op->Token = Token;
284   return Op;
285 }
286 
287 // Imm
288 bool M68kOperand::isImm() const { return Kind == Kind::Imm; }
289 void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {
290   assert(isImm() && "wrong oeprand kind");
291   assert((N == 1) && "can only handle one register operand");
292 
293   M68kOperand::addExpr(Inst, Expr);
294 }
295 
296 std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,
297                                                     SMLoc Start, SMLoc End) {
298   auto Op = std::make_unique<M68kOperand>(Kind::Imm, Start, End);
299   Op->Expr = Expr;
300   return Op;
301 }
302 
303 // Addr
304 bool M68kOperand::isAddr() const {
305   return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
306 }
307 void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
308   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
309 }
310 
311 // ARI
312 bool M68kOperand::isARI() const {
313   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
314          M68k::AR32RegClass.contains(MemOp.OuterReg);
315 }
316 void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
317   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
318 }
319 
320 // ARID
321 bool M68kOperand::isARID() const {
322   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
323          M68k::AR32RegClass.contains(MemOp.OuterReg);
324 }
325 void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {
326   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
327   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
328 }
329 
330 // ARII
331 bool M68kOperand::isARII() const {
332   return isMemOp() &&
333          MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
334          M68k::AR32RegClass.contains(MemOp.OuterReg);
335 }
336 void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {
337   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
338   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
339   Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
340 }
341 
342 // ARIPD
343 bool M68kOperand::isARIPD() const {
344   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
345          M68k::AR32RegClass.contains(MemOp.OuterReg);
346 }
347 void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
348   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
349 }
350 
351 // ARIPI
352 bool M68kOperand::isARIPI() const {
353   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
354          M68k::AR32RegClass.contains(MemOp.OuterReg);
355 }
356 void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
357   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
358 }
359 
360 // PCD
361 bool M68kOperand::isPCD() const {
362   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
363          MemOp.OuterReg == M68k::PC;
364 }
365 void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
366   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
367 }
368 
369 // PCI
370 bool M68kOperand::isPCI() const {
371   return isMemOp() &&
372          MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
373          MemOp.OuterReg == M68k::PC;
374 }
375 void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
376   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
377   Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
378 }
379 
380 static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
381                                       bool SP) {
382   switch (RegNo) {
383   case M68k::A0:
384   case M68k::A1:
385   case M68k::A2:
386   case M68k::A3:
387   case M68k::A4:
388   case M68k::A5:
389   case M68k::A6:
390     return Address;
391 
392   case M68k::SP:
393     return SP;
394 
395   case M68k::D0:
396   case M68k::D1:
397   case M68k::D2:
398   case M68k::D3:
399   case M68k::D4:
400   case M68k::D5:
401   case M68k::D6:
402   case M68k::D7:
403     return Data;
404 
405   case M68k::SR:
406   case M68k::CCR:
407     return false;
408 
409   default:
410     llvm_unreachable("unexpected register type");
411     return false;
412   }
413 }
414 
415 unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
416                                                    unsigned Kind) {
417   M68kOperand &Operand = (M68kOperand &)Op;
418 
419   switch (Kind) {
420   case MCK_XR16:
421   case MCK_SPILL:
422     if (Operand.isReg() &&
423         checkRegisterClass(Operand.getReg(), true, true, true)) {
424       return Match_Success;
425     }
426     break;
427 
428   case MCK_AR16:
429   case MCK_AR32:
430     if (Operand.isReg() &&
431         checkRegisterClass(Operand.getReg(), false, true, true)) {
432       return Match_Success;
433     }
434     break;
435 
436   case MCK_AR32_NOSP:
437     if (Operand.isReg() &&
438         checkRegisterClass(Operand.getReg(), false, true, false)) {
439       return Match_Success;
440     }
441     break;
442 
443   case MCK_DR8:
444   case MCK_DR16:
445   case MCK_DR32:
446     if (Operand.isReg() &&
447         checkRegisterClass(Operand.getReg(), true, false, false)) {
448       return Match_Success;
449     }
450     break;
451 
452   case MCK_AR16_TC:
453     if (Operand.isReg() &&
454         ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
455       return Match_Success;
456     }
457     break;
458 
459   case MCK_DR16_TC:
460     if (Operand.isReg() &&
461         ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
462       return Match_Success;
463     }
464     break;
465 
466   case MCK_XR16_TC:
467     if (Operand.isReg() &&
468         ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
469          (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
470       return Match_Success;
471     }
472     break;
473   }
474 
475   return Match_InvalidOperand;
476 }
477 
478 bool M68kAsmParser::parseRegisterName(unsigned &RegNo, SMLoc Loc,
479                                       StringRef RegisterName) {
480   auto RegisterNameLower = RegisterName.lower();
481 
482   // Parse simple general-purpose registers.
483   if (RegisterNameLower.size() == 2) {
484     static unsigned RegistersByIndex[] = {
485         M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
486         M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
487         M68k::A4, M68k::A5, M68k::A6, M68k::SP,
488     };
489 
490     switch (RegisterNameLower[0]) {
491     case 'd':
492     case 'a': {
493       if (isdigit(RegisterNameLower[1])) {
494         unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
495         unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
496         if (RegIndex < 8) {
497           RegNo = RegistersByIndex[IndexOffset + RegIndex];
498           return true;
499         }
500       }
501       break;
502     }
503 
504     case 'c':
505       if (RegisterNameLower[1] == 'c' && RegisterNameLower[2] == 'r') {
506         RegNo = M68k::CCR;
507         return true;
508       }
509       break;
510 
511     case 's':
512       if (RegisterNameLower[1] == 'p') {
513         RegNo = M68k::SP;
514         return true;
515       } else if (RegisterNameLower[1] == 'r') {
516         RegNo = M68k::SR;
517         return true;
518       }
519       break;
520 
521     case 'p':
522       if (RegisterNameLower[1] == 'c') {
523         RegNo = M68k::PC;
524         return true;
525       }
526       break;
527     }
528   }
529 
530   return false;
531 }
532 
533 OperandMatchResultTy M68kAsmParser::parseRegister(unsigned &RegNo) {
534   bool HasPercent = false;
535   AsmToken PercentToken;
536 
537   LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
538 
539   if (getTok().is(AsmToken::Percent)) {
540     HasPercent = true;
541     PercentToken = Lex();
542   } else if (!RegisterPrefixOptional.getValue()) {
543     return MatchOperand_NoMatch;
544   }
545 
546   if (!Parser.getTok().is(AsmToken::Identifier)) {
547     if (HasPercent) {
548       getLexer().UnLex(PercentToken);
549     }
550     return MatchOperand_NoMatch;
551   }
552 
553   auto RegisterName = Parser.getTok().getString();
554   if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
555     if (HasPercent) {
556       getLexer().UnLex(PercentToken);
557     }
558     return MatchOperand_NoMatch;
559   }
560 
561   Parser.Lex();
562   return MatchOperand_Success;
563 }
564 
565 bool M68kAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
566                                   SMLoc &EndLoc) {
567   auto Result = tryParseRegister(RegNo, StartLoc, EndLoc);
568   if (Result != MatchOperand_Success) {
569     return Error(StartLoc, "expected register");
570   }
571 
572   return false;
573 }
574 
575 OperandMatchResultTy M68kAsmParser::tryParseRegister(unsigned &RegNo,
576                                                      SMLoc &StartLoc,
577                                                      SMLoc &EndLoc) {
578   StartLoc = getLexer().getLoc();
579   auto Result = parseRegister(RegNo);
580   EndLoc = getLexer().getLoc();
581   return Result;
582 }
583 
584 bool M68kAsmParser::isExpr() const {
585   switch (Parser.getTok().getKind()) {
586   case AsmToken::Identifier:
587   case AsmToken::Integer:
588     return true;
589 
590   default:
591     return false;
592   }
593 }
594 
595 OperandMatchResultTy M68kAsmParser::parseImm(OperandVector &Operands) {
596   if (getLexer().isNot(AsmToken::Hash)) {
597     return MatchOperand_NoMatch;
598   }
599   SMLoc Start = getLexer().getLoc();
600   Parser.Lex();
601 
602   SMLoc End;
603   const MCExpr *Expr;
604 
605   if (getParser().parseExpression(Expr, End)) {
606     return MatchOperand_ParseFail;
607   }
608 
609   Operands.push_back(M68kOperand::createImm(Expr, Start, End));
610   return MatchOperand_Success;
611 }
612 
613 OperandMatchResultTy M68kAsmParser::parseMemOp(OperandVector &Operands) {
614   SMLoc Start = getLexer().getLoc();
615   bool IsPD = false;
616   M68kMemOp MemOp;
617 
618   // Check for a plain register.
619   auto Result = parseRegister(MemOp.OuterReg);
620   if (Result == MatchOperand_Success) {
621     MemOp.Op = M68kMemOp::Kind::Reg;
622     Operands.push_back(
623         M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
624     return MatchOperand_Success;
625   }
626 
627   if (Result == MatchOperand_ParseFail) {
628     return Result;
629   }
630 
631   // Check for pre-decrement & outer displacement.
632   bool HasDisplacement = false;
633   if (getLexer().is(AsmToken::Minus)) {
634     IsPD = true;
635     Parser.Lex();
636   } else if (isExpr()) {
637     if (Parser.parseExpression(MemOp.OuterDisp)) {
638       return MatchOperand_ParseFail;
639     }
640     HasDisplacement = true;
641   }
642 
643   if (getLexer().isNot(AsmToken::LParen)) {
644     if (HasDisplacement) {
645       MemOp.Op = M68kMemOp::Kind::Addr;
646       Operands.push_back(
647           M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
648       return MatchOperand_Success;
649     } else if (IsPD) {
650       Error(getLexer().getLoc(), "expected (");
651       return MatchOperand_ParseFail;
652     }
653 
654     return MatchOperand_NoMatch;
655   }
656   Parser.Lex();
657 
658   // Check for constant dereference & MIT-style displacement
659   if (!HasDisplacement && isExpr()) {
660     if (Parser.parseExpression(MemOp.OuterDisp)) {
661       return MatchOperand_ParseFail;
662     }
663     HasDisplacement = true;
664 
665     // If we're not followed by a comma, we're a constant dereference.
666     if (getLexer().isNot(AsmToken::Comma)) {
667       MemOp.Op = M68kMemOp::Kind::Addr;
668       Operands.push_back(
669           M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
670       return MatchOperand_Success;
671     }
672 
673     Parser.Lex();
674   }
675 
676   Result = parseRegister(MemOp.OuterReg);
677   if (Result == MatchOperand_ParseFail) {
678     return MatchOperand_ParseFail;
679   }
680 
681   if (Result != MatchOperand_Success) {
682     Error(getLexer().getLoc(), "expected register");
683     return MatchOperand_ParseFail;
684   }
685 
686   // Check for Index.
687   bool HasIndex = false;
688   if (Parser.getTok().is(AsmToken::Comma)) {
689     Parser.Lex();
690 
691     Result = parseRegister(MemOp.InnerReg);
692     if (Result == MatchOperand_ParseFail) {
693       return Result;
694     }
695 
696     if (Result == MatchOperand_NoMatch) {
697       Error(getLexer().getLoc(), "expected register");
698       return MatchOperand_ParseFail;
699     }
700 
701     // TODO: parse size, scale and inner displacement.
702     MemOp.Size = 4;
703     MemOp.Scale = 1;
704     MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);
705     HasIndex = true;
706   }
707 
708   if (Parser.getTok().isNot(AsmToken::RParen)) {
709     Error(getLexer().getLoc(), "expected )");
710     return MatchOperand_ParseFail;
711   }
712   Parser.Lex();
713 
714   bool IsPI = false;
715   if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {
716     Parser.Lex();
717     IsPI = true;
718   }
719 
720   SMLoc End = getLexer().getLoc();
721 
722   unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
723   if (OpCount > 1) {
724     Error(Start, "only one of post-increment, pre-decrement or displacement "
725                  "can be used");
726     return MatchOperand_ParseFail;
727   }
728 
729   if (IsPD) {
730     MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
731   } else if (IsPI) {
732     MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
733   } else if (HasIndex) {
734     MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
735   } else if (HasDisplacement) {
736     MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
737   } else {
738     MemOp.Op = M68kMemOp::Kind::RegIndirect;
739   }
740 
741   Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
742   return MatchOperand_Success;
743 }
744 
745 void M68kAsmParser::eatComma() {
746   if (Parser.getTok().is(AsmToken::Comma)) {
747     Parser.Lex();
748   }
749 }
750 
751 bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
752                                      SMLoc NameLoc, OperandVector &Operands) {
753   SMLoc Start = getLexer().getLoc();
754   Operands.push_back(M68kOperand::createToken(Name, Start, Start));
755 
756   bool First = true;
757   while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
758     if (!First) {
759       eatComma();
760     } else {
761       First = false;
762     }
763 
764     auto MatchResult = MatchOperandParserImpl(Operands, Name);
765     if (MatchResult == MatchOperand_Success) {
766       continue;
767     }
768 
769     // Add custom operand formats here...
770     SMLoc Loc = getLexer().getLoc();
771     Parser.eatToEndOfStatement();
772     return Error(Loc, "unexpected token parsing operands");
773   }
774 
775   // Eat EndOfStatement.
776   Parser.Lex();
777   return false;
778 }
779 
780 bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
781 
782 bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
783                                    OperandVector const &Operands,
784                                    uint64_t const &ErrorInfo) {
785   SMLoc ErrorLoc = Loc;
786   char const *Diag = 0;
787 
788   if (ErrorInfo != ~0U) {
789     if (ErrorInfo >= Operands.size()) {
790       Diag = "too few operands for instruction.";
791     } else {
792       auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
793       if (Op.getStartLoc() != SMLoc()) {
794         ErrorLoc = Op.getStartLoc();
795       }
796     }
797   }
798 
799   if (!Diag) {
800     Diag = "invalid operand for instruction";
801   }
802 
803   return Error(ErrorLoc, Diag);
804 }
805 
806 bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc,
807                                    uint64_t const &ErrorInfo) {
808   return Error(Loc, "instruction requires a CPU feature not currently enabled");
809 }
810 
811 bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc,
812                          MCStreamer &Out) const {
813   Inst.setLoc(Loc);
814   Out.emitInstruction(Inst, STI);
815 
816   return false;
817 }
818 
819 bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
820                                             OperandVector &Operands,
821                                             MCStreamer &Out,
822                                             uint64_t &ErrorInfo,
823                                             bool MatchingInlineAsm) {
824   MCInst Inst;
825   unsigned MatchResult =
826       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
827 
828   switch (MatchResult) {
829   case Match_Success:
830     return emit(Inst, Loc, Out);
831   case Match_MissingFeature:
832     return missingFeature(Loc, ErrorInfo);
833   case Match_InvalidOperand:
834     return invalidOperand(Loc, Operands, ErrorInfo);
835   case Match_MnemonicFail:
836     return Error(Loc, "invalid instruction");
837   default:
838     return true;
839   }
840 }
841 
842 void M68kOperand::print(raw_ostream &OS) const {
843   switch (Kind) {
844   case Kind::Invalid:
845     OS << "invalid";
846     break;
847 
848   case Kind::Token:
849     OS << "token '" << Token << "'";
850     break;
851 
852   case Kind::Imm:
853     OS << "immediate " << Imm;
854     break;
855 
856   case Kind::MemOp:
857     MemOp.print(OS);
858     break;
859   }
860 }
861