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