brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.7 KiB · fb5cd5c Raw
1073 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "M68kInstrInfo.h"10#include "M68kRegisterInfo.h"11#include "MCTargetDesc/M68kMCAsmInfo.h"12#include "TargetInfo/M68kTargetInfo.h"13 14#include "llvm/MC/MCContext.h"15#include "llvm/MC/MCParser/AsmLexer.h"16#include "llvm/MC/MCParser/MCParsedAsmOperand.h"17#include "llvm/MC/MCParser/MCTargetAsmParser.h"18#include "llvm/MC/MCStreamer.h"19#include "llvm/MC/TargetRegistry.h"20 21#include <sstream>22 23#define DEBUG_TYPE "m68k-asm-parser"24 25using namespace llvm;26 27static cl::opt<bool> RegisterPrefixOptional(28    "m68k-register-prefix-optional", cl::Hidden,29    cl::desc("Enable specifying registers without the % prefix"),30    cl::init(false));31 32namespace {33/// Parses M68k assembly from a stream.34class M68kAsmParser : public MCTargetAsmParser {35  MCAsmParser &Parser;36  const MCRegisterInfo *MRI;37 38#define GET_ASSEMBLER_HEADER39#include "M68kGenAsmMatcher.inc"40 41  // Helpers for Match&Emit.42  bool invalidOperand(SMLoc Loc, const OperandVector &Operands,43                      const uint64_t &ErrorInfo);44  bool missingFeature(SMLoc Loc, const uint64_t &ErrorInfo);45  bool emit(MCInst &Inst, SMLoc Loc, MCStreamer &Out) const;46  bool parseRegisterName(MCRegister &RegNo, SMLoc Loc, StringRef RegisterName);47  ParseStatus parseRegister(MCRegister &RegNo);48 49  // Parser functions.50  void eatComma();51 52  bool isExpr();53  ParseStatus parseImm(OperandVector &Operands);54  ParseStatus parseMemOp(OperandVector &Operands);55  ParseStatus parseRegOrMoveMask(OperandVector &Operands);56 57public:58  M68kAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,59                const MCInstrInfo &MII, const MCTargetOptions &Options)60      : MCTargetAsmParser(Options, STI, MII), Parser(Parser) {61    MCAsmParserExtension::Initialize(Parser);62    MRI = getContext().getRegisterInfo();63 64    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));65  }66 67  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,68                                      unsigned Kind) override;69  bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;70  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,71                               SMLoc &EndLoc) override;72  bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,73                        SMLoc NameLoc, OperandVector &Operands) override;74  bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,75                               OperandVector &Operands, MCStreamer &Out,76                               uint64_t &ErrorInfo,77                               bool MatchingInlineAsm) override;78};79 80struct M68kMemOp {81  enum class Kind {82    Addr,83    RegMask,84    Reg,85    RegIndirect,86    RegPostIncrement,87    RegPreDecrement,88    RegIndirectDisplacement,89    RegIndirectDisplacementIndex,90  };91 92  // These variables are used for the following forms:93  // Addr: (OuterDisp)94  // RegMask: RegMask (as register mask)95  // Reg: %OuterReg96  // RegIndirect: (%OuterReg)97  // RegPostIncrement: (%OuterReg)+98  // RegPreDecrement: -(%OuterReg)99  // RegIndirectDisplacement: OuterDisp(%OuterReg)100  // RegIndirectDisplacementIndex:101  //   OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)102 103  Kind Op;104  MCRegister OuterReg;105  MCRegister InnerReg;106  const MCExpr *OuterDisp;107  const MCExpr *InnerDisp;108  uint8_t Size : 4;109  uint8_t Scale : 4;110  const MCExpr *Expr;111  uint16_t RegMask;112 113  M68kMemOp() {}114  M68kMemOp(Kind Op) : Op(Op) {}115 116  void print(raw_ostream &OS) const;117};118 119/// An parsed M68k assembly operand.120class M68kOperand : public MCParsedAsmOperand {121  typedef MCParsedAsmOperand Base;122 123  enum class KindTy {124    Invalid,125    Token,126    Imm,127    MemOp,128  };129 130  KindTy Kind;131  SMLoc Start, End;132  union {133    StringRef Token;134    const MCExpr *Expr;135    M68kMemOp MemOp;136  };137 138  template <unsigned N> bool isAddrN() const;139 140public:141  M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)142      : Base(), Kind(Kind), Start(Start), End(End) {}143 144  SMLoc getStartLoc() const override { return Start; }145  SMLoc getEndLoc() const override { return End; }146 147  void print(raw_ostream &OS, const MCAsmInfo &MAI) const override;148 149  bool isMem() const override { return false; }150  bool isMemOp() const { return Kind == KindTy::MemOp; }151 152  static void addExpr(MCInst &Inst, const MCExpr *Expr);153 154  // Reg155  bool isReg() const override;156  bool isAReg() const;157  bool isDReg() const;158  bool isFPDReg() const;159  bool isFPCReg() const;160  MCRegister getReg() const override;161  void addRegOperands(MCInst &Inst, unsigned N) const;162 163  static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start,164                                                  SMLoc End);165 166  // Token167  bool isToken() const override;168  StringRef getToken() const;169  static std::unique_ptr<M68kOperand> createToken(StringRef Token, SMLoc Start,170                                                  SMLoc End);171 172  // Imm173  bool isImm() const override;174  void addImmOperands(MCInst &Inst, unsigned N) const;175 176  static std::unique_ptr<M68kOperand> createImm(const MCExpr *Expr, SMLoc Start,177                                                SMLoc End);178 179  // Imm for TRAP instruction180  bool isTrapImm() const;181  // Imm for BKPT instruction182  bool isBkptImm() const;183 184  // MoveMask185  bool isMoveMask() const;186  void addMoveMaskOperands(MCInst &Inst, unsigned N) const;187 188  // Addr189  bool isAddr() const;190  bool isAddr8() const { return isAddrN<8>(); }191  bool isAddr16() const { return isAddrN<16>(); }192  bool isAddr32() const { return isAddrN<32>(); }193  void addAddrOperands(MCInst &Inst, unsigned N) const;194 195  // ARI196  bool isARI() const;197  void addARIOperands(MCInst &Inst, unsigned N) const;198 199  // ARID200  bool isARID() const;201  void addARIDOperands(MCInst &Inst, unsigned N) const;202 203  // ARII204  bool isARII() const;205  void addARIIOperands(MCInst &Inst, unsigned N) const;206 207  // ARIPD208  bool isARIPD() const;209  void addARIPDOperands(MCInst &Inst, unsigned N) const;210 211  // ARIPI212  bool isARIPI() const;213  void addARIPIOperands(MCInst &Inst, unsigned N) const;214 215  // PCD216  bool isPCD() const;217  void addPCDOperands(MCInst &Inst, unsigned N) const;218 219  // PCI220  bool isPCI() const;221  void addPCIOperands(MCInst &Inst, unsigned N) const;222};223 224} // end anonymous namespace.225 226extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() {227  RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget());228}229 230#define GET_REGISTER_MATCHER231#define GET_MATCHER_IMPLEMENTATION232#include "M68kGenAsmMatcher.inc"233 234static inline unsigned getRegisterByIndex(unsigned RegisterIndex) {235  static unsigned RegistersByIndex[] = {236      M68k::D0,  M68k::D1,  M68k::D2,  M68k::D3,  M68k::D4,  M68k::D5,237      M68k::D6,  M68k::D7,  M68k::A0,  M68k::A1,  M68k::A2,  M68k::A3,238      M68k::A4,  M68k::A5,  M68k::A6,  M68k::SP,  M68k::FP0, M68k::FP1,239      M68k::FP2, M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7};240  assert(RegisterIndex <=241         sizeof(RegistersByIndex) / sizeof(RegistersByIndex[0]));242  return RegistersByIndex[RegisterIndex];243}244 245static inline unsigned getRegisterIndex(unsigned Register) {246  if (Register >= M68k::D0 && Register <= M68k::D7)247    return Register - M68k::D0;248  if (Register >= M68k::A0 && Register <= M68k::A6)249    return Register - M68k::A0 + 8;250  if (Register >= M68k::FP0 && Register <= M68k::FP7)251    return Register - M68k::FP0 + 16;252 253  switch (Register) {254  case M68k::SP:255    // SP is sadly not contiguous with the rest of the An registers256    return 15;257 258  // We don't care about the indices of these registers.259  case M68k::PC:260  case M68k::CCR:261  case M68k::SR:262  case M68k::FPC:263  case M68k::FPS:264  case M68k::FPIAR:265    return UINT_MAX;266 267  default:268    llvm_unreachable("unexpected register number");269  }270}271 272void M68kMemOp::print(raw_ostream &OS) const {273  switch (Op) {274  case Kind::Addr:275    OS << OuterDisp;276    break;277  case Kind::RegMask:278    OS << "RegMask(" << format("%04x", RegMask) << ")";279    break;280  case Kind::Reg:281    OS << '%' << OuterReg;282    break;283  case Kind::RegIndirect:284    OS << "(%" << OuterReg << ')';285    break;286  case Kind::RegPostIncrement:287    OS << "(%" << OuterReg << ")+";288    break;289  case Kind::RegPreDecrement:290    OS << "-(%" << OuterReg << ")";291    break;292  case Kind::RegIndirectDisplacement:293    OS << OuterDisp << "(%" << OuterReg << ")";294    break;295  case Kind::RegIndirectDisplacementIndex:296    OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size297       << ", " << InnerDisp << ")";298    break;299  }300}301 302void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {303  if (auto Const = dyn_cast<MCConstantExpr>(Expr)) {304    Inst.addOperand(MCOperand::createImm(Const->getValue()));305    return;306  }307 308  Inst.addOperand(MCOperand::createExpr(Expr));309}310 311// Reg312bool M68kOperand::isReg() const {313  return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;314}315 316MCRegister M68kOperand::getReg() const {317  assert(isReg());318  return MemOp.OuterReg;319}320 321void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {322  assert(isReg() && "wrong operand kind");323  assert((N == 1) && "can only handle one register operand");324 325  Inst.addOperand(MCOperand::createReg(getReg()));326}327 328std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,329                                                      SMLoc Start, SMLoc End) {330  auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start, End);331  Op->MemOp = MemOp;332  return Op;333}334 335// Token336bool M68kOperand::isToken() const { return Kind == KindTy::Token; }337StringRef M68kOperand::getToken() const {338  assert(isToken());339  return Token;340}341 342std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,343                                                      SMLoc Start, SMLoc End) {344  auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start, End);345  Op->Token = Token;346  return Op;347}348 349// Imm350bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }351void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {352  assert(isImm() && "wrong operand kind");353  assert((N == 1) && "can only handle one register operand");354 355  M68kOperand::addExpr(Inst, Expr);356}357 358std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,359                                                    SMLoc Start, SMLoc End) {360  auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start, End);361  Op->Expr = Expr;362  return Op;363}364 365bool M68kOperand::isTrapImm() const {366  int64_t Value;367  if (!isImm() || !Expr->evaluateAsAbsolute(Value))368    return false;369 370  return isUInt<4>(Value);371}372 373bool M68kOperand::isBkptImm() const {374  int64_t Value;375  if (!isImm() || !Expr->evaluateAsAbsolute(Value))376    return false;377 378  return isUInt<3>(Value);379}380 381// MoveMask382bool M68kOperand::isMoveMask() const {383  if (!isMemOp())384    return false;385 386  if (MemOp.Op == M68kMemOp::Kind::RegMask)387    return true;388 389  if (MemOp.Op != M68kMemOp::Kind::Reg)390    return false;391 392  // Only regular address / data registers are allowed to be used393  // in register masks.394  return getRegisterIndex(MemOp.OuterReg) < 16;395}396 397void M68kOperand::addMoveMaskOperands(MCInst &Inst, unsigned N) const {398  assert(isMoveMask() && "wrong operand kind");399  assert((N == 1) && "can only handle one immediate operand");400 401  uint16_t MoveMask = MemOp.RegMask;402  if (MemOp.Op == M68kMemOp::Kind::Reg)403    MoveMask = 1 << getRegisterIndex(MemOp.OuterReg);404 405  Inst.addOperand(MCOperand::createImm(MoveMask));406}407 408// Addr409bool M68kOperand::isAddr() const {410  return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;411}412// TODO: Maybe we can also store the size of OuterDisp413// in Size?414template <unsigned N> bool M68kOperand::isAddrN() const {415  if (isAddr()) {416    int64_t Res;417    if (MemOp.OuterDisp->evaluateAsAbsolute(Res))418      return isInt<N>(Res);419    return true;420  }421  return false;422}423void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {424  M68kOperand::addExpr(Inst, MemOp.OuterDisp);425}426 427// ARI428bool M68kOperand::isARI() const {429  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&430         M68k::AR32RegClass.contains(MemOp.OuterReg);431}432void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {433  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));434}435 436// ARID437bool M68kOperand::isARID() const {438  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&439         M68k::AR32RegClass.contains(MemOp.OuterReg);440}441void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {442  M68kOperand::addExpr(Inst, MemOp.OuterDisp);443  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));444}445 446// ARII447bool M68kOperand::isARII() const {448  return isMemOp() &&449         MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&450         M68k::AR32RegClass.contains(MemOp.OuterReg);451}452void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {453  M68kOperand::addExpr(Inst, MemOp.OuterDisp);454  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));455  Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));456}457 458// ARIPD459bool M68kOperand::isARIPD() const {460  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&461         M68k::AR32RegClass.contains(MemOp.OuterReg);462}463void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {464  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));465}466 467// ARIPI468bool M68kOperand::isARIPI() const {469  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&470         M68k::AR32RegClass.contains(MemOp.OuterReg);471}472void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {473  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));474}475 476// PCD477bool M68kOperand::isPCD() const {478  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&479         MemOp.OuterReg == M68k::PC;480}481void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {482  M68kOperand::addExpr(Inst, MemOp.OuterDisp);483}484 485// PCI486bool M68kOperand::isPCI() const {487  return isMemOp() &&488         MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&489         MemOp.OuterReg == M68k::PC;490}491void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {492  M68kOperand::addExpr(Inst, MemOp.OuterDisp);493  Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));494}495 496static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,497                                      bool SP, bool FPDR = false,498                                      bool FPCR = false) {499  switch (RegNo) {500  case M68k::A0:501  case M68k::A1:502  case M68k::A2:503  case M68k::A3:504  case M68k::A4:505  case M68k::A5:506  case M68k::A6:507    return Address;508 509  case M68k::SP:510    return SP;511 512  case M68k::D0:513  case M68k::D1:514  case M68k::D2:515  case M68k::D3:516  case M68k::D4:517  case M68k::D5:518  case M68k::D6:519  case M68k::D7:520    return Data;521 522  case M68k::SR:523  case M68k::CCR:524    return false;525 526  case M68k::FP0:527  case M68k::FP1:528  case M68k::FP2:529  case M68k::FP3:530  case M68k::FP4:531  case M68k::FP5:532  case M68k::FP6:533  case M68k::FP7:534    return FPDR;535 536  case M68k::FPC:537  case M68k::FPS:538  case M68k::FPIAR:539    return FPCR;540 541  default:542    llvm_unreachable("unexpected register type");543    return false;544  }545}546 547bool M68kOperand::isAReg() const {548  return isReg() && checkRegisterClass(getReg(),549                                       /*Data=*/false,550                                       /*Address=*/true, /*SP=*/true);551}552 553bool M68kOperand::isDReg() const {554  return isReg() && checkRegisterClass(getReg(),555                                       /*Data=*/true,556                                       /*Address=*/false, /*SP=*/false);557}558 559bool M68kOperand::isFPDReg() const {560  return isReg() && checkRegisterClass(getReg(),561                                       /*Data=*/false,562                                       /*Address=*/false, /*SP=*/false,563                                       /*FPDR=*/true);564}565 566bool M68kOperand::isFPCReg() const {567  return isReg() && checkRegisterClass(getReg(),568                                       /*Data=*/false,569                                       /*Address=*/false, /*SP=*/false,570                                       /*FPDR=*/false, /*FPCR=*/true);571}572 573unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,574                                                   unsigned Kind) {575  M68kOperand &Operand = (M68kOperand &)Op;576 577  switch (Kind) {578  case MCK_XR16:579  case MCK_SPILL:580    if (Operand.isReg() &&581        checkRegisterClass(Operand.getReg(), true, true, true)) {582      return Match_Success;583    }584    break;585 586  case MCK_AR16:587  case MCK_AR32:588    if (Operand.isReg() &&589        checkRegisterClass(Operand.getReg(), false, true, true)) {590      return Match_Success;591    }592    break;593 594  case MCK_AR32_NOSP:595    if (Operand.isReg() &&596        checkRegisterClass(Operand.getReg(), false, true, false)) {597      return Match_Success;598    }599    break;600 601  case MCK_DR8:602  case MCK_DR16:603  case MCK_DR32:604    if (Operand.isReg() &&605        checkRegisterClass(Operand.getReg(), true, false, false)) {606      return Match_Success;607    }608    break;609 610  case MCK_AR16_TC:611    if (Operand.isReg() &&612        ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {613      return Match_Success;614    }615    break;616 617  case MCK_DR16_TC:618    if (Operand.isReg() &&619        ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {620      return Match_Success;621    }622    break;623 624  case MCK_XR16_TC:625    if (Operand.isReg() &&626        ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||627         (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {628      return Match_Success;629    }630    break;631  }632 633  return Match_InvalidOperand;634}635 636bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc,637                                      StringRef RegisterName) {638  auto RegisterNameLower = RegisterName.lower();639 640  // CCR and SR register641  if (RegisterNameLower == "ccr") {642    RegNo = M68k::CCR;643    return true;644  } else if (RegisterNameLower == "sr") {645    RegNo = M68k::SR;646    return true;647  }648 649  // Parse simple general-purpose registers.650  if (RegisterNameLower.size() == 2) {651 652    switch (RegisterNameLower[0]) {653    case 'd':654    case 'a': {655      if (isdigit(RegisterNameLower[1])) {656        unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;657        unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');658        if (RegIndex < 8) {659          RegNo = getRegisterByIndex(IndexOffset + RegIndex);660          return true;661        }662      }663      break;664    }665 666    case 's':667      if (RegisterNameLower[1] == 'p') {668        RegNo = M68k::SP;669        return true;670      } else if (RegisterNameLower[1] == 'r') {671        RegNo = M68k::SR;672        return true;673      }674      break;675 676    case 'p':677      if (RegisterNameLower[1] == 'c') {678        RegNo = M68k::PC;679        return true;680      }681      break;682    }683  } else if (StringRef(RegisterNameLower).starts_with("fp") &&684             RegisterNameLower.size() > 2) {685    auto RegIndex = unsigned(RegisterNameLower[2] - '0');686    if (RegIndex < 8 && RegisterNameLower.size() == 3) {687      // Floating point data register.688      RegNo = getRegisterByIndex(16 + RegIndex);689      return true;690    } else {691      // Floating point control register.692      RegNo = StringSwitch<unsigned>(RegisterNameLower)693                  .Cases({"fpc", "fpcr"}, M68k::FPC)694                  .Cases({"fps", "fpsr"}, M68k::FPS)695                  .Cases({"fpi", "fpiar"}, M68k::FPIAR)696                  .Default(M68k::NoRegister);697      assert(RegNo != M68k::NoRegister &&698             "Unrecognized FP control register name");699      return true;700    }701  }702 703  return false;704}705 706ParseStatus M68kAsmParser::parseRegister(MCRegister &RegNo) {707  bool HasPercent = false;708  AsmToken PercentToken;709 710  LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");711 712  if (getTok().is(AsmToken::Percent)) {713    HasPercent = true;714    PercentToken = Lex();715  } else if (!RegisterPrefixOptional.getValue()) {716    return ParseStatus::NoMatch;717  }718 719  if (!Parser.getTok().is(AsmToken::Identifier)) {720    if (HasPercent) {721      getLexer().UnLex(PercentToken);722    }723    return ParseStatus::NoMatch;724  }725 726  auto RegisterName = Parser.getTok().getString();727  if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {728    if (HasPercent) {729      getLexer().UnLex(PercentToken);730    }731    return ParseStatus::NoMatch;732  }733 734  Parser.Lex();735  return ParseStatus::Success;736}737 738bool M68kAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,739                                  SMLoc &EndLoc) {740  ParseStatus Result = tryParseRegister(Reg, StartLoc, EndLoc);741  if (!Result.isSuccess())742    return Error(StartLoc, "expected register");743 744  return false;745}746 747ParseStatus M68kAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,748                                            SMLoc &EndLoc) {749  StartLoc = getLexer().getLoc();750  ParseStatus Result = parseRegister(Reg);751  EndLoc = getLexer().getLoc();752  return Result;753}754 755bool M68kAsmParser::isExpr() {756  switch (Parser.getTok().getKind()) {757  case AsmToken::Identifier:758  case AsmToken::Integer:759    return true;760  case AsmToken::Minus:761    return getLexer().peekTok().getKind() == AsmToken::Integer;762 763  default:764    return false;765  }766}767 768ParseStatus M68kAsmParser::parseImm(OperandVector &Operands) {769  if (getLexer().isNot(AsmToken::Hash))770    return ParseStatus::NoMatch;771  SMLoc Start = getLexer().getLoc();772  Parser.Lex();773 774  SMLoc End;775  const MCExpr *Expr;776 777  if (getParser().parseExpression(Expr, End))778    return ParseStatus::Failure;779 780  Operands.push_back(M68kOperand::createImm(Expr, Start, End));781  return ParseStatus::Success;782}783 784ParseStatus M68kAsmParser::parseMemOp(OperandVector &Operands) {785  SMLoc Start = getLexer().getLoc();786  bool IsPD = false;787  M68kMemOp MemOp;788 789  // Check for a plain register or register mask.790  ParseStatus Result = parseRegOrMoveMask(Operands);791  if (!Result.isNoMatch())792    return Result;793 794  // Check for pre-decrement & outer displacement.795  bool HasDisplacement = false;796  if (getLexer().is(AsmToken::Minus)) {797    IsPD = true;798    Parser.Lex();799  } else if (isExpr()) {800    if (Parser.parseExpression(MemOp.OuterDisp))801      return ParseStatus::Failure;802    HasDisplacement = true;803  }804 805  if (getLexer().isNot(AsmToken::LParen)) {806    if (HasDisplacement) {807      MemOp.Op = M68kMemOp::Kind::Addr;808      Operands.push_back(809          M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));810      return ParseStatus::Success;811    }812    if (IsPD)813      return Error(getLexer().getLoc(), "expected (");814 815    return ParseStatus::NoMatch;816  }817  Parser.Lex();818 819  // Check for constant dereference & MIT-style displacement820  if (!HasDisplacement && isExpr()) {821    if (Parser.parseExpression(MemOp.OuterDisp))822      return ParseStatus::Failure;823    HasDisplacement = true;824 825    // If we're not followed by a comma, we're a constant dereference.826    if (getLexer().isNot(AsmToken::Comma)) {827      MemOp.Op = M68kMemOp::Kind::Addr;828      Operands.push_back(829          M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));830      return ParseStatus::Success;831    }832 833    Parser.Lex();834  }835 836  Result = parseRegister(MemOp.OuterReg);837  if (Result.isFailure())838    return ParseStatus::Failure;839 840  if (!Result.isSuccess())841    return Error(getLexer().getLoc(), "expected register");842 843  // Check for Index.844  bool HasIndex = false;845  if (Parser.getTok().is(AsmToken::Comma)) {846    Parser.Lex();847 848    Result = parseRegister(MemOp.InnerReg);849    if (Result.isFailure())850      return Result;851 852    if (Result.isNoMatch())853      return Error(getLexer().getLoc(), "expected register");854 855    // TODO: parse size, scale and inner displacement.856    MemOp.Size = 4;857    MemOp.Scale = 1;858    MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);859    HasIndex = true;860  }861 862  if (Parser.getTok().isNot(AsmToken::RParen))863    return Error(getLexer().getLoc(), "expected )");864  Parser.Lex();865 866  bool IsPI = false;867  if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {868    Parser.Lex();869    IsPI = true;870  }871 872  SMLoc End = getLexer().getLoc();873 874  unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);875  if (OpCount > 1)876    return Error(Start, "only one of post-increment, pre-decrement or "877                        "displacement can be used");878 879  if (IsPD) {880    MemOp.Op = M68kMemOp::Kind::RegPreDecrement;881  } else if (IsPI) {882    MemOp.Op = M68kMemOp::Kind::RegPostIncrement;883  } else if (HasIndex) {884    MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;885  } else if (HasDisplacement) {886    MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;887  } else {888    MemOp.Op = M68kMemOp::Kind::RegIndirect;889  }890 891  Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));892  return ParseStatus::Success;893}894 895ParseStatus M68kAsmParser::parseRegOrMoveMask(OperandVector &Operands) {896  SMLoc Start = getLexer().getLoc();897  M68kMemOp MemOp(M68kMemOp::Kind::RegMask);898  MemOp.RegMask = 0;899 900  for (;;) {901    bool IsFirstRegister =902        (MemOp.Op == M68kMemOp::Kind::RegMask) && (MemOp.RegMask == 0);903 904    MCRegister FirstRegister;905    ParseStatus Result = parseRegister(FirstRegister);906    if (IsFirstRegister && Result.isNoMatch())907      return ParseStatus::NoMatch;908    if (!Result.isSuccess())909      return Error(getLexer().getLoc(), "expected start register");910 911    MCRegister LastRegister = FirstRegister;912    if (parseOptionalToken(AsmToken::Minus)) {913      Result = parseRegister(LastRegister);914      if (!Result.isSuccess())915        return Error(getLexer().getLoc(), "expected end register");916    }917 918    unsigned FirstRegisterIndex = getRegisterIndex(FirstRegister);919    unsigned LastRegisterIndex = getRegisterIndex(LastRegister);920 921    uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1;922    uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex;923 924    if (IsFirstRegister && (FirstRegister == LastRegister)) {925      // First register range is a single register, simplify to just Reg926      // so that it matches more operands.927      MemOp.Op = M68kMemOp::Kind::Reg;928      MemOp.OuterReg = FirstRegister;929    } else {930      if (MemOp.Op == M68kMemOp::Kind::Reg) {931        // This is the second register being specified - expand the Reg operand932        // into a mask first.933        MemOp.Op = M68kMemOp::Kind::RegMask;934        MemOp.RegMask = 1 << getRegisterIndex(MemOp.OuterReg);935 936        if (MemOp.RegMask == 0)937          return Error(getLexer().getLoc(),938                       "special registers cannot be used in register masks");939      }940 941      if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16))942        return Error(getLexer().getLoc(),943                     "special registers cannot be used in register masks");944 945      if (NewMaskBits & MemOp.RegMask)946        return Error(getLexer().getLoc(), "conflicting masked registers");947 948      MemOp.RegMask |= NewMaskBits;949    }950 951    if (!parseOptionalToken(AsmToken::Slash))952      break;953  }954 955  Operands.push_back(956      M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));957  return ParseStatus::Success;958}959 960void M68kAsmParser::eatComma() {961  if (Parser.getTok().is(AsmToken::Comma)) {962    Parser.Lex();963  }964}965 966bool M68kAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,967                                     SMLoc NameLoc, OperandVector &Operands) {968  SMLoc Start = getLexer().getLoc();969  Operands.push_back(M68kOperand::createToken(Name, Start, Start));970 971  bool First = true;972  while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {973    if (!First) {974      eatComma();975    } else {976      First = false;977    }978 979    ParseStatus MatchResult = MatchOperandParserImpl(Operands, Name);980    if (MatchResult.isSuccess())981      continue;982 983    // Add custom operand formats here...984    SMLoc Loc = getLexer().getLoc();985    Parser.eatToEndOfStatement();986    return Error(Loc, "unexpected token parsing operands");987  }988 989  // Eat EndOfStatement.990  Parser.Lex();991  return false;992}993 994bool M68kAsmParser::invalidOperand(SMLoc Loc, OperandVector const &Operands,995                                   uint64_t const &ErrorInfo) {996  SMLoc ErrorLoc = Loc;997  char const *Diag = 0;998 999  if (ErrorInfo != ~0U) {1000    if (ErrorInfo >= Operands.size()) {1001      Diag = "too few operands for instruction.";1002    } else {1003      auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];1004      if (Op.getStartLoc() != SMLoc()) {1005        ErrorLoc = Op.getStartLoc();1006      }1007    }1008  }1009 1010  if (!Diag) {1011    Diag = "invalid operand for instruction";1012  }1013 1014  return Error(ErrorLoc, Diag);1015}1016 1017bool M68kAsmParser::missingFeature(SMLoc Loc, uint64_t const &ErrorInfo) {1018  return Error(Loc, "instruction requires a CPU feature not currently enabled");1019}1020 1021bool M68kAsmParser::emit(MCInst &Inst, SMLoc Loc, MCStreamer &Out) const {1022  Inst.setLoc(Loc);1023  Out.emitInstruction(Inst, *STI);1024 1025  return false;1026}1027 1028bool M68kAsmParser::matchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,1029                                            OperandVector &Operands,1030                                            MCStreamer &Out,1031                                            uint64_t &ErrorInfo,1032                                            bool MatchingInlineAsm) {1033  MCInst Inst;1034  unsigned MatchResult =1035      MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);1036 1037  switch (MatchResult) {1038  case Match_Success:1039    return emit(Inst, Loc, Out);1040  case Match_MissingFeature:1041    return missingFeature(Loc, ErrorInfo);1042  case Match_InvalidOperand:1043    return invalidOperand(Loc, Operands, ErrorInfo);1044  case Match_MnemonicFail:1045    return Error(Loc, "invalid instruction");1046  default:1047    return true;1048  }1049}1050 1051void M68kOperand::print(raw_ostream &OS, const MCAsmInfo &MAI) const {1052  switch (Kind) {1053  case KindTy::Invalid:1054    OS << "invalid";1055    break;1056 1057  case KindTy::Token:1058    OS << "token '" << Token << "'";1059    break;1060 1061  case KindTy::Imm: {1062    int64_t Value;1063    Expr->evaluateAsAbsolute(Value);1064    OS << "immediate " << Value;1065    break;1066  }1067 1068  case KindTy::MemOp:1069    MemOp.print(OS);1070    break;1071  }1072}1073