Home | History | Annotate | Line # | Download | only in AsmParser
      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 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   // 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 Kind::Invalid:
    846     OS << "invalid";
    847     break;
    848 
    849   case Kind::Token:
    850     OS << "token '" << Token << "'";
    851     break;
    852 
    853   case Kind::Imm:
    854     OS << "immediate " << Imm;
    855     break;
    856 
    857   case Kind::MemOp:
    858     MemOp.print(OS);
    859     break;
    860   }
    861 }
    862