xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp (revision 833a452e9f082a7982a31c21f0da437dbbe0a39d)
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();
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 KindTy {
121     Invalid,
122     Token,
123     Imm,
124     MemOp,
125   };
126 
127   KindTy 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(KindTy 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 == KindTy::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 == KindTy::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>(KindTy::MemOp, Start, End);
269   Op->MemOp = MemOp;
270   return Op;
271 }
272 
273 // Token
274 bool M68kOperand::isToken() const { return Kind == KindTy::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>(KindTy::Token, Start, End);
283   Op->Token = Token;
284   return Op;
285 }
286 
287 // Imm
288 bool M68kOperand::isImm() const { return Kind == KindTy::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>(KindTy::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   // CCR register
483   if (RegisterNameLower == "ccr") {
484     RegNo = M68k::CCR;
485     return true;
486   }
487 
488   // Parse simple general-purpose registers.
489   if (RegisterNameLower.size() == 2) {
490     static unsigned RegistersByIndex[] = {
491         M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
492         M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
493         M68k::A4, M68k::A5, M68k::A6, M68k::SP,
494     };
495 
496     switch (RegisterNameLower[0]) {
497     case 'd':
498     case 'a': {
499       if (isdigit(RegisterNameLower[1])) {
500         unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
501         unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
502         if (RegIndex < 8) {
503           RegNo = RegistersByIndex[IndexOffset + RegIndex];
504           return true;
505         }
506       }
507       break;
508     }
509 
510     case 's':
511       if (RegisterNameLower[1] == 'p') {
512         RegNo = M68k::SP;
513         return true;
514       } else if (RegisterNameLower[1] == 'r') {
515         RegNo = M68k::SR;
516         return true;
517       }
518       break;
519 
520     case 'p':
521       if (RegisterNameLower[1] == 'c') {
522         RegNo = M68k::PC;
523         return true;
524       }
525       break;
526     }
527   }
528 
529   return false;
530 }
531 
532 OperandMatchResultTy M68kAsmParser::parseRegister(unsigned &RegNo) {
533   bool HasPercent = false;
534   AsmToken PercentToken;
535 
536   LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
537 
538   if (getTok().is(AsmToken::Percent)) {
539     HasPercent = true;
540     PercentToken = Lex();
541   } else if (!RegisterPrefixOptional.getValue()) {
542     return MatchOperand_NoMatch;
543   }
544 
545   if (!Parser.getTok().is(AsmToken::Identifier)) {
546     if (HasPercent) {
547       getLexer().UnLex(PercentToken);
548     }
549     return MatchOperand_NoMatch;
550   }
551 
552   auto RegisterName = Parser.getTok().getString();
553   if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
554     if (HasPercent) {
555       getLexer().UnLex(PercentToken);
556     }
557     return MatchOperand_NoMatch;
558   }
559 
560   Parser.Lex();
561   return MatchOperand_Success;
562 }
563 
564 bool M68kAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
565                                   SMLoc &EndLoc) {
566   auto Result = tryParseRegister(RegNo, StartLoc, EndLoc);
567   if (Result != MatchOperand_Success) {
568     return Error(StartLoc, "expected register");
569   }
570 
571   return false;
572 }
573 
574 OperandMatchResultTy M68kAsmParser::tryParseRegister(unsigned &RegNo,
575                                                      SMLoc &StartLoc,
576                                                      SMLoc &EndLoc) {
577   StartLoc = getLexer().getLoc();
578   auto Result = parseRegister(RegNo);
579   EndLoc = getLexer().getLoc();
580   return Result;
581 }
582 
583 bool M68kAsmParser::isExpr() {
584   switch (Parser.getTok().getKind()) {
585   case AsmToken::Identifier:
586   case AsmToken::Integer:
587     return true;
588   case AsmToken::Minus:
589     return getLexer().peekTok().getKind() == AsmToken::Integer;
590 
591   default:
592     return false;
593   }
594 }
595 
596 OperandMatchResultTy M68kAsmParser::parseImm(OperandVector &Operands) {
597   if (getLexer().isNot(AsmToken::Hash)) {
598     return MatchOperand_NoMatch;
599   }
600   SMLoc Start = getLexer().getLoc();
601   Parser.Lex();
602 
603   SMLoc End;
604   const MCExpr *Expr;
605 
606   if (getParser().parseExpression(Expr, End)) {
607     return MatchOperand_ParseFail;
608   }
609 
610   Operands.push_back(M68kOperand::createImm(Expr, Start, End));
611   return MatchOperand_Success;
612 }
613 
614 OperandMatchResultTy M68kAsmParser::parseMemOp(OperandVector &Operands) {
615   SMLoc Start = getLexer().getLoc();
616   bool IsPD = false;
617   M68kMemOp MemOp;
618 
619   // Check for a plain register.
620   auto Result = parseRegister(MemOp.OuterReg);
621   if (Result == MatchOperand_Success) {
622     MemOp.Op = M68kMemOp::Kind::Reg;
623     Operands.push_back(
624         M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
625     return MatchOperand_Success;
626   }
627 
628   if (Result == MatchOperand_ParseFail) {
629     return Result;
630   }
631 
632   // Check for pre-decrement & outer displacement.
633   bool HasDisplacement = false;
634   if (getLexer().is(AsmToken::Minus)) {
635     IsPD = true;
636     Parser.Lex();
637   } else if (isExpr()) {
638     if (Parser.parseExpression(MemOp.OuterDisp)) {
639       return MatchOperand_ParseFail;
640     }
641     HasDisplacement = true;
642   }
643 
644   if (getLexer().isNot(AsmToken::LParen)) {
645     if (HasDisplacement) {
646       MemOp.Op = M68kMemOp::Kind::Addr;
647       Operands.push_back(
648           M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
649       return MatchOperand_Success;
650     } else if (IsPD) {
651       Error(getLexer().getLoc(), "expected (");
652       return MatchOperand_ParseFail;
653     }
654 
655     return MatchOperand_NoMatch;
656   }
657   Parser.Lex();
658 
659   // Check for constant dereference & MIT-style displacement
660   if (!HasDisplacement && isExpr()) {
661     if (Parser.parseExpression(MemOp.OuterDisp)) {
662       return MatchOperand_ParseFail;
663     }
664     HasDisplacement = true;
665 
666     // If we're not followed by a comma, we're a constant dereference.
667     if (getLexer().isNot(AsmToken::Comma)) {
668       MemOp.Op = M68kMemOp::Kind::Addr;
669       Operands.push_back(
670           M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
671       return MatchOperand_Success;
672     }
673 
674     Parser.Lex();
675   }
676 
677   Result = parseRegister(MemOp.OuterReg);
678   if (Result == MatchOperand_ParseFail) {
679     return MatchOperand_ParseFail;
680   }
681 
682   if (Result != MatchOperand_Success) {
683     Error(getLexer().getLoc(), "expected register");
684     return MatchOperand_ParseFail;
685   }
686 
687   // Check for Index.
688   bool HasIndex = false;
689   if (Parser.getTok().is(AsmToken::Comma)) {
690     Parser.Lex();
691 
692     Result = parseRegister(MemOp.InnerReg);
693     if (Result == MatchOperand_ParseFail) {
694       return Result;
695     }
696 
697     if (Result == MatchOperand_NoMatch) {
698       Error(getLexer().getLoc(), "expected register");
699       return MatchOperand_ParseFail;
700     }
701 
702     // TODO: parse size, scale and inner displacement.
703     MemOp.Size = 4;
704     MemOp.Scale = 1;
705     MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);
706     HasIndex = true;
707   }
708 
709   if (Parser.getTok().isNot(AsmToken::RParen)) {
710     Error(getLexer().getLoc(), "expected )");
711     return MatchOperand_ParseFail;
712   }
713   Parser.Lex();
714 
715   bool IsPI = false;
716   if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {
717     Parser.Lex();
718     IsPI = true;
719   }
720 
721   SMLoc End = getLexer().getLoc();
722 
723   unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
724   if (OpCount > 1) {
725     Error(Start, "only one of post-increment, pre-decrement or displacement "
726                  "can be used");
727     return MatchOperand_ParseFail;
728   }
729 
730   if (IsPD) {
731     MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
732   } else if (IsPI) {
733     MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
734   } else if (HasIndex) {
735     MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
736   } else if (HasDisplacement) {
737     MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
738   } else {
739     MemOp.Op = M68kMemOp::Kind::RegIndirect;
740   }
741 
742   Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
743   return MatchOperand_Success;
744 }
745 
746 void M68kAsmParser::eatComma() {
747   if (Parser.getTok().is(AsmToken::Comma)) {
748     Parser.Lex();
749   }
750 }
751 
752 bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
753                                      SMLoc NameLoc, OperandVector &Operands) {
754   SMLoc Start = getLexer().getLoc();
755   Operands.push_back(M68kOperand::createToken(Name, Start, Start));
756 
757   bool First = true;
758   while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
759     if (!First) {
760       eatComma();
761     } else {
762       First = false;
763     }
764 
765     auto MatchResult = MatchOperandParserImpl(Operands, Name);
766     if (MatchResult == MatchOperand_Success) {
767       continue;
768     }
769 
770     // Add custom operand formats here...
771     SMLoc Loc = getLexer().getLoc();
772     Parser.eatToEndOfStatement();
773     return Error(Loc, "unexpected token parsing operands");
774   }
775 
776   // Eat EndOfStatement.
777   Parser.Lex();
778   return false;
779 }
780 
781 bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
782 
783 bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
784                                    OperandVector const &Operands,
785                                    uint64_t const &ErrorInfo) {
786   SMLoc ErrorLoc = Loc;
787   char const *Diag = 0;
788 
789   if (ErrorInfo != ~0U) {
790     if (ErrorInfo >= Operands.size()) {
791       Diag = "too few operands for instruction.";
792     } else {
793       auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
794       if (Op.getStartLoc() != SMLoc()) {
795         ErrorLoc = Op.getStartLoc();
796       }
797     }
798   }
799 
800   if (!Diag) {
801     Diag = "invalid operand for instruction";
802   }
803 
804   return Error(ErrorLoc, Diag);
805 }
806 
807 bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc,
808                                    uint64_t const &ErrorInfo) {
809   return Error(Loc, "instruction requires a CPU feature not currently enabled");
810 }
811 
812 bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc,
813                          MCStreamer &Out) const {
814   Inst.setLoc(Loc);
815   Out.emitInstruction(Inst, STI);
816 
817   return false;
818 }
819 
820 bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
821                                             OperandVector &Operands,
822                                             MCStreamer &Out,
823                                             uint64_t &ErrorInfo,
824                                             bool MatchingInlineAsm) {
825   MCInst Inst;
826   unsigned MatchResult =
827       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
828 
829   switch (MatchResult) {
830   case Match_Success:
831     return emit(Inst, Loc, Out);
832   case Match_MissingFeature:
833     return missingFeature(Loc, ErrorInfo);
834   case Match_InvalidOperand:
835     return invalidOperand(Loc, Operands, ErrorInfo);
836   case Match_MnemonicFail:
837     return Error(Loc, "invalid instruction");
838   default:
839     return true;
840   }
841 }
842 
843 void M68kOperand::print(raw_ostream &OS) const {
844   switch (Kind) {
845   case KindTy::Invalid:
846     OS << "invalid";
847     break;
848 
849   case KindTy::Token:
850     OS << "token '" << Token << "'";
851     break;
852 
853   case KindTy::Imm:
854     OS << "immediate " << Imm;
855     break;
856 
857   case KindTy::MemOp:
858     MemOp.print(OS);
859     break;
860   }
861 }
862