104eeddc0SDimitry Andric //===-- M68kAsmParser.cpp - Parse M68k assembly to MCInst instructions ----===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric 9fe6060f1SDimitry Andric #include "M68kInstrInfo.h" 10fe6060f1SDimitry Andric #include "M68kRegisterInfo.h" 11fe6060f1SDimitry Andric #include "TargetInfo/M68kTargetInfo.h" 12fe6060f1SDimitry Andric 13fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h" 1481ad6265SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 15fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 16fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h" 17fe6060f1SDimitry Andric #include "llvm/MC/MCStreamer.h" 18349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 19fe6060f1SDimitry Andric 20fe6060f1SDimitry Andric #include <sstream> 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric #define DEBUG_TYPE "m68k-asm-parser" 23fe6060f1SDimitry Andric 24fe6060f1SDimitry Andric using namespace llvm; 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric static cl::opt<bool> RegisterPrefixOptional( 27fe6060f1SDimitry Andric "m68k-register-prefix-optional", cl::Hidden, 28fe6060f1SDimitry Andric cl::desc("Enable specifying registers without the % prefix"), 29fe6060f1SDimitry Andric cl::init(false)); 30fe6060f1SDimitry Andric 31fe6060f1SDimitry Andric namespace { 32fe6060f1SDimitry Andric /// Parses M68k assembly from a stream. 33fe6060f1SDimitry Andric class M68kAsmParser : public MCTargetAsmParser { 34fe6060f1SDimitry Andric const MCSubtargetInfo &STI; 35fe6060f1SDimitry Andric MCAsmParser &Parser; 36fe6060f1SDimitry Andric const MCRegisterInfo *MRI; 37fe6060f1SDimitry Andric 38fe6060f1SDimitry Andric #define GET_ASSEMBLER_HEADER 39fe6060f1SDimitry Andric #include "M68kGenAsmMatcher.inc" 40fe6060f1SDimitry Andric 41fe6060f1SDimitry Andric // Helpers for Match&Emit. 42fe6060f1SDimitry Andric bool invalidOperand(const SMLoc &Loc, const OperandVector &Operands, 43fe6060f1SDimitry Andric const uint64_t &ErrorInfo); 44fe6060f1SDimitry Andric bool missingFeature(const SMLoc &Loc, const uint64_t &ErrorInfo); 45fe6060f1SDimitry Andric bool emit(MCInst &Inst, SMLoc const &Loc, MCStreamer &Out) const; 46*bdd1243dSDimitry Andric bool parseRegisterName(MCRegister &RegNo, SMLoc Loc, StringRef RegisterName); 47*bdd1243dSDimitry Andric OperandMatchResultTy parseRegister(MCRegister &RegNo); 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric // Parser functions. 50fe6060f1SDimitry Andric void eatComma(); 51fe6060f1SDimitry Andric 52fe6060f1SDimitry Andric bool isExpr(); 53fe6060f1SDimitry Andric OperandMatchResultTy parseImm(OperandVector &Operands); 54fe6060f1SDimitry Andric OperandMatchResultTy parseMemOp(OperandVector &Operands); 55349cc55cSDimitry Andric OperandMatchResultTy parseRegOrMoveMask(OperandVector &Operands); 56fe6060f1SDimitry Andric 57fe6060f1SDimitry Andric public: 58fe6060f1SDimitry Andric M68kAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 59fe6060f1SDimitry Andric const MCInstrInfo &MII, const MCTargetOptions &Options) 60fe6060f1SDimitry Andric : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) { 61fe6060f1SDimitry Andric MCAsmParserExtension::Initialize(Parser); 62fe6060f1SDimitry Andric MRI = getContext().getRegisterInfo(); 63fe6060f1SDimitry Andric 64fe6060f1SDimitry Andric setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 65fe6060f1SDimitry Andric } 66fe6060f1SDimitry Andric 67fe6060f1SDimitry Andric unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 68fe6060f1SDimitry Andric unsigned Kind) override; 69*bdd1243dSDimitry Andric bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc, 70*bdd1243dSDimitry Andric SMLoc &EndLoc) override; 71*bdd1243dSDimitry Andric OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, 72fe6060f1SDimitry Andric SMLoc &EndLoc) override; 73fe6060f1SDimitry Andric bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 74fe6060f1SDimitry Andric SMLoc NameLoc, OperandVector &Operands) override; 75fe6060f1SDimitry Andric bool ParseDirective(AsmToken DirectiveID) override; 76fe6060f1SDimitry Andric bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 77fe6060f1SDimitry Andric OperandVector &Operands, MCStreamer &Out, 78fe6060f1SDimitry Andric uint64_t &ErrorInfo, 79fe6060f1SDimitry Andric bool MatchingInlineAsm) override; 80fe6060f1SDimitry Andric }; 81fe6060f1SDimitry Andric 82fe6060f1SDimitry Andric struct M68kMemOp { 83fe6060f1SDimitry Andric enum class Kind { 84fe6060f1SDimitry Andric Addr, 85349cc55cSDimitry Andric RegMask, 86fe6060f1SDimitry Andric Reg, 87fe6060f1SDimitry Andric RegIndirect, 88fe6060f1SDimitry Andric RegPostIncrement, 89fe6060f1SDimitry Andric RegPreDecrement, 90fe6060f1SDimitry Andric RegIndirectDisplacement, 91fe6060f1SDimitry Andric RegIndirectDisplacementIndex, 92fe6060f1SDimitry Andric }; 93fe6060f1SDimitry Andric 94fe6060f1SDimitry Andric // These variables are used for the following forms: 95fe6060f1SDimitry Andric // Addr: (OuterDisp) 96349cc55cSDimitry Andric // RegMask: RegMask (as register mask) 97fe6060f1SDimitry Andric // Reg: %OuterReg 98fe6060f1SDimitry Andric // RegIndirect: (%OuterReg) 99fe6060f1SDimitry Andric // RegPostIncrement: (%OuterReg)+ 100fe6060f1SDimitry Andric // RegPreDecrement: -(%OuterReg) 101fe6060f1SDimitry Andric // RegIndirectDisplacement: OuterDisp(%OuterReg) 102fe6060f1SDimitry Andric // RegIndirectDisplacementIndex: 103fe6060f1SDimitry Andric // OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp) 104fe6060f1SDimitry Andric 105fe6060f1SDimitry Andric Kind Op; 106*bdd1243dSDimitry Andric MCRegister OuterReg; 107*bdd1243dSDimitry Andric MCRegister InnerReg; 108fe6060f1SDimitry Andric const MCExpr *OuterDisp; 109fe6060f1SDimitry Andric const MCExpr *InnerDisp; 110fe6060f1SDimitry Andric uint8_t Size : 4; 111fe6060f1SDimitry Andric uint8_t Scale : 4; 112fe6060f1SDimitry Andric const MCExpr *Expr; 113349cc55cSDimitry Andric uint16_t RegMask; 114fe6060f1SDimitry Andric 115fe6060f1SDimitry Andric M68kMemOp() {} 116fe6060f1SDimitry Andric M68kMemOp(Kind Op) : Op(Op) {} 117fe6060f1SDimitry Andric 118fe6060f1SDimitry Andric void print(raw_ostream &OS) const; 119fe6060f1SDimitry Andric }; 120fe6060f1SDimitry Andric 121fe6060f1SDimitry Andric /// An parsed M68k assembly operand. 122fe6060f1SDimitry Andric class M68kOperand : public MCParsedAsmOperand { 123fe6060f1SDimitry Andric typedef MCParsedAsmOperand Base; 124fe6060f1SDimitry Andric 12569ade1e0SDimitry Andric enum class KindTy { 126fe6060f1SDimitry Andric Invalid, 127fe6060f1SDimitry Andric Token, 128fe6060f1SDimitry Andric Imm, 129fe6060f1SDimitry Andric MemOp, 130fe6060f1SDimitry Andric }; 131fe6060f1SDimitry Andric 13269ade1e0SDimitry Andric KindTy Kind; 133fe6060f1SDimitry Andric SMLoc Start, End; 134fe6060f1SDimitry Andric union { 135fe6060f1SDimitry Andric StringRef Token; 136fe6060f1SDimitry Andric int64_t Imm; 137fe6060f1SDimitry Andric const MCExpr *Expr; 138fe6060f1SDimitry Andric M68kMemOp MemOp; 139fe6060f1SDimitry Andric }; 140fe6060f1SDimitry Andric 141349cc55cSDimitry Andric template <unsigned N> bool isAddrN() const; 142349cc55cSDimitry Andric 143fe6060f1SDimitry Andric public: 14469ade1e0SDimitry Andric M68kOperand(KindTy Kind, SMLoc Start, SMLoc End) 145fe6060f1SDimitry Andric : Base(), Kind(Kind), Start(Start), End(End) {} 146fe6060f1SDimitry Andric 147fe6060f1SDimitry Andric SMLoc getStartLoc() const override { return Start; } 148fe6060f1SDimitry Andric SMLoc getEndLoc() const override { return End; } 149fe6060f1SDimitry Andric 150fe6060f1SDimitry Andric void print(raw_ostream &OS) const override; 151fe6060f1SDimitry Andric 152fe6060f1SDimitry Andric bool isMem() const override { return false; } 15369ade1e0SDimitry Andric bool isMemOp() const { return Kind == KindTy::MemOp; } 154fe6060f1SDimitry Andric 155fe6060f1SDimitry Andric static void addExpr(MCInst &Inst, const MCExpr *Expr); 156fe6060f1SDimitry Andric 157fe6060f1SDimitry Andric // Reg 158fe6060f1SDimitry Andric bool isReg() const override; 159349cc55cSDimitry Andric bool isAReg() const; 160349cc55cSDimitry Andric bool isDReg() const; 161fe6060f1SDimitry Andric unsigned getReg() const override; 162fe6060f1SDimitry Andric void addRegOperands(MCInst &Inst, unsigned N) const; 163fe6060f1SDimitry Andric 164fe6060f1SDimitry Andric static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start, 165fe6060f1SDimitry Andric SMLoc End); 166fe6060f1SDimitry Andric 167fe6060f1SDimitry Andric // Token 168fe6060f1SDimitry Andric bool isToken() const override; 169fe6060f1SDimitry Andric StringRef getToken() const; 170fe6060f1SDimitry Andric static std::unique_ptr<M68kOperand> createToken(StringRef Token, SMLoc Start, 171fe6060f1SDimitry Andric SMLoc End); 172fe6060f1SDimitry Andric 173fe6060f1SDimitry Andric // Imm 174fe6060f1SDimitry Andric bool isImm() const override; 175fe6060f1SDimitry Andric void addImmOperands(MCInst &Inst, unsigned N) const; 176fe6060f1SDimitry Andric 177fe6060f1SDimitry Andric static std::unique_ptr<M68kOperand> createImm(const MCExpr *Expr, SMLoc Start, 178fe6060f1SDimitry Andric SMLoc End); 179fe6060f1SDimitry Andric 180349cc55cSDimitry Andric // MoveMask 181349cc55cSDimitry Andric bool isMoveMask() const; 182349cc55cSDimitry Andric void addMoveMaskOperands(MCInst &Inst, unsigned N) const; 183349cc55cSDimitry Andric 184fe6060f1SDimitry Andric // Addr 185fe6060f1SDimitry Andric bool isAddr() const; 186349cc55cSDimitry Andric bool isAddr8() const { return isAddrN<8>(); } 187349cc55cSDimitry Andric bool isAddr16() const { return isAddrN<16>(); } 188349cc55cSDimitry Andric bool isAddr32() const { return isAddrN<32>(); } 189fe6060f1SDimitry Andric void addAddrOperands(MCInst &Inst, unsigned N) const; 190fe6060f1SDimitry Andric 191fe6060f1SDimitry Andric // ARI 192fe6060f1SDimitry Andric bool isARI() const; 193fe6060f1SDimitry Andric void addARIOperands(MCInst &Inst, unsigned N) const; 194fe6060f1SDimitry Andric 195fe6060f1SDimitry Andric // ARID 196fe6060f1SDimitry Andric bool isARID() const; 197fe6060f1SDimitry Andric void addARIDOperands(MCInst &Inst, unsigned N) const; 198fe6060f1SDimitry Andric 199fe6060f1SDimitry Andric // ARII 200fe6060f1SDimitry Andric bool isARII() const; 201fe6060f1SDimitry Andric void addARIIOperands(MCInst &Inst, unsigned N) const; 202fe6060f1SDimitry Andric 203fe6060f1SDimitry Andric // ARIPD 204fe6060f1SDimitry Andric bool isARIPD() const; 205fe6060f1SDimitry Andric void addARIPDOperands(MCInst &Inst, unsigned N) const; 206fe6060f1SDimitry Andric 207fe6060f1SDimitry Andric // ARIPI 208fe6060f1SDimitry Andric bool isARIPI() const; 209fe6060f1SDimitry Andric void addARIPIOperands(MCInst &Inst, unsigned N) const; 210fe6060f1SDimitry Andric 211fe6060f1SDimitry Andric // PCD 212fe6060f1SDimitry Andric bool isPCD() const; 213fe6060f1SDimitry Andric void addPCDOperands(MCInst &Inst, unsigned N) const; 214fe6060f1SDimitry Andric 215fe6060f1SDimitry Andric // PCI 216fe6060f1SDimitry Andric bool isPCI() const; 217fe6060f1SDimitry Andric void addPCIOperands(MCInst &Inst, unsigned N) const; 218fe6060f1SDimitry Andric }; 219fe6060f1SDimitry Andric 220fe6060f1SDimitry Andric } // end anonymous namespace. 221fe6060f1SDimitry Andric 222fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() { 223fe6060f1SDimitry Andric RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget()); 224fe6060f1SDimitry Andric } 225fe6060f1SDimitry Andric 226fe6060f1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION 227fe6060f1SDimitry Andric #include "M68kGenAsmMatcher.inc" 228fe6060f1SDimitry Andric 229349cc55cSDimitry Andric static inline unsigned getRegisterByIndex(unsigned RegisterIndex) { 230349cc55cSDimitry Andric static unsigned RegistersByIndex[] = { 231349cc55cSDimitry Andric M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5, 232349cc55cSDimitry Andric M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3, 233349cc55cSDimitry Andric M68k::A4, M68k::A5, M68k::A6, M68k::SP, 234349cc55cSDimitry Andric }; 235349cc55cSDimitry Andric assert(RegisterIndex <= 236349cc55cSDimitry Andric sizeof(RegistersByIndex) / sizeof(RegistersByIndex[0])); 237349cc55cSDimitry Andric return RegistersByIndex[RegisterIndex]; 238349cc55cSDimitry Andric } 239349cc55cSDimitry Andric 240349cc55cSDimitry Andric static inline unsigned getRegisterIndex(unsigned Register) { 241349cc55cSDimitry Andric if (Register >= M68k::D0 && Register <= M68k::D7) 242349cc55cSDimitry Andric return Register - M68k::D0; 243349cc55cSDimitry Andric if (Register >= M68k::A0 && Register <= M68k::A6) 244349cc55cSDimitry Andric return Register - M68k::A0 + 8; 245349cc55cSDimitry Andric 246349cc55cSDimitry Andric switch (Register) { 247349cc55cSDimitry Andric case M68k::SP: 248349cc55cSDimitry Andric // SP is sadly not contiguous with the rest of the An registers 249349cc55cSDimitry Andric return 15; 250349cc55cSDimitry Andric 251349cc55cSDimitry Andric case M68k::PC: 252349cc55cSDimitry Andric case M68k::CCR: 253349cc55cSDimitry Andric return 16; 254349cc55cSDimitry Andric 255349cc55cSDimitry Andric default: 256349cc55cSDimitry Andric llvm_unreachable("unexpected register number"); 257349cc55cSDimitry Andric } 258349cc55cSDimitry Andric } 259349cc55cSDimitry Andric 260fe6060f1SDimitry Andric void M68kMemOp::print(raw_ostream &OS) const { 261fe6060f1SDimitry Andric switch (Op) { 262fe6060f1SDimitry Andric case Kind::Addr: 263fe6060f1SDimitry Andric OS << OuterDisp; 264fe6060f1SDimitry Andric break; 265349cc55cSDimitry Andric case Kind::RegMask: 266349cc55cSDimitry Andric OS << "RegMask(" << format("%04x", RegMask) << ")"; 267349cc55cSDimitry Andric break; 268fe6060f1SDimitry Andric case Kind::Reg: 269fe6060f1SDimitry Andric OS << '%' << OuterReg; 270fe6060f1SDimitry Andric break; 271fe6060f1SDimitry Andric case Kind::RegIndirect: 272fe6060f1SDimitry Andric OS << "(%" << OuterReg << ')'; 273fe6060f1SDimitry Andric break; 274fe6060f1SDimitry Andric case Kind::RegPostIncrement: 275fe6060f1SDimitry Andric OS << "(%" << OuterReg << ")+"; 276fe6060f1SDimitry Andric break; 277fe6060f1SDimitry Andric case Kind::RegPreDecrement: 278fe6060f1SDimitry Andric OS << "-(%" << OuterReg << ")"; 279fe6060f1SDimitry Andric break; 280fe6060f1SDimitry Andric case Kind::RegIndirectDisplacement: 281fe6060f1SDimitry Andric OS << OuterDisp << "(%" << OuterReg << ")"; 282fe6060f1SDimitry Andric break; 283fe6060f1SDimitry Andric case Kind::RegIndirectDisplacementIndex: 284fe6060f1SDimitry Andric OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size 285fe6060f1SDimitry Andric << ", " << InnerDisp << ")"; 286fe6060f1SDimitry Andric break; 287fe6060f1SDimitry Andric } 288fe6060f1SDimitry Andric } 289fe6060f1SDimitry Andric 290fe6060f1SDimitry Andric void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) { 291fe6060f1SDimitry Andric if (auto Const = dyn_cast<MCConstantExpr>(Expr)) { 292fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createImm(Const->getValue())); 293fe6060f1SDimitry Andric return; 294fe6060f1SDimitry Andric } 295fe6060f1SDimitry Andric 296fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 297fe6060f1SDimitry Andric } 298fe6060f1SDimitry Andric 299fe6060f1SDimitry Andric // Reg 300fe6060f1SDimitry Andric bool M68kOperand::isReg() const { 30169ade1e0SDimitry Andric return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg; 302fe6060f1SDimitry Andric } 303fe6060f1SDimitry Andric 304fe6060f1SDimitry Andric unsigned M68kOperand::getReg() const { 305fe6060f1SDimitry Andric assert(isReg()); 306fe6060f1SDimitry Andric return MemOp.OuterReg; 307fe6060f1SDimitry Andric } 308fe6060f1SDimitry Andric 309fe6060f1SDimitry Andric void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const { 310fe6060f1SDimitry Andric assert(isReg() && "wrong operand kind"); 311fe6060f1SDimitry Andric assert((N == 1) && "can only handle one register operand"); 312fe6060f1SDimitry Andric 313fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(getReg())); 314fe6060f1SDimitry Andric } 315fe6060f1SDimitry Andric 316fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp, 317fe6060f1SDimitry Andric SMLoc Start, SMLoc End) { 31869ade1e0SDimitry Andric auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start, End); 319fe6060f1SDimitry Andric Op->MemOp = MemOp; 320fe6060f1SDimitry Andric return Op; 321fe6060f1SDimitry Andric } 322fe6060f1SDimitry Andric 323fe6060f1SDimitry Andric // Token 32469ade1e0SDimitry Andric bool M68kOperand::isToken() const { return Kind == KindTy::Token; } 325fe6060f1SDimitry Andric StringRef M68kOperand::getToken() const { 326fe6060f1SDimitry Andric assert(isToken()); 327fe6060f1SDimitry Andric return Token; 328fe6060f1SDimitry Andric } 329fe6060f1SDimitry Andric 330fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token, 331fe6060f1SDimitry Andric SMLoc Start, SMLoc End) { 33269ade1e0SDimitry Andric auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start, End); 333fe6060f1SDimitry Andric Op->Token = Token; 334fe6060f1SDimitry Andric return Op; 335fe6060f1SDimitry Andric } 336fe6060f1SDimitry Andric 337fe6060f1SDimitry Andric // Imm 33869ade1e0SDimitry Andric bool M68kOperand::isImm() const { return Kind == KindTy::Imm; } 339fe6060f1SDimitry Andric void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const { 340349cc55cSDimitry Andric assert(isImm() && "wrong operand kind"); 341fe6060f1SDimitry Andric assert((N == 1) && "can only handle one register operand"); 342fe6060f1SDimitry Andric 343fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, Expr); 344fe6060f1SDimitry Andric } 345fe6060f1SDimitry Andric 346fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr, 347fe6060f1SDimitry Andric SMLoc Start, SMLoc End) { 34869ade1e0SDimitry Andric auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start, End); 349fe6060f1SDimitry Andric Op->Expr = Expr; 350fe6060f1SDimitry Andric return Op; 351fe6060f1SDimitry Andric } 352fe6060f1SDimitry Andric 353349cc55cSDimitry Andric // MoveMask 354349cc55cSDimitry Andric bool M68kOperand::isMoveMask() const { 355349cc55cSDimitry Andric if (!isMemOp()) 356349cc55cSDimitry Andric return false; 357349cc55cSDimitry Andric 358349cc55cSDimitry Andric if (MemOp.Op == M68kMemOp::Kind::RegMask) 359349cc55cSDimitry Andric return true; 360349cc55cSDimitry Andric 361349cc55cSDimitry Andric if (MemOp.Op != M68kMemOp::Kind::Reg) 362349cc55cSDimitry Andric return false; 363349cc55cSDimitry Andric 364349cc55cSDimitry Andric // Only regular address / data registers are allowed to be used 365349cc55cSDimitry Andric // in register masks. 366349cc55cSDimitry Andric return getRegisterIndex(MemOp.OuterReg) < 16; 367349cc55cSDimitry Andric } 368349cc55cSDimitry Andric 369349cc55cSDimitry Andric void M68kOperand::addMoveMaskOperands(MCInst &Inst, unsigned N) const { 370349cc55cSDimitry Andric assert(isMoveMask() && "wrong operand kind"); 371349cc55cSDimitry Andric assert((N == 1) && "can only handle one immediate operand"); 372349cc55cSDimitry Andric 373349cc55cSDimitry Andric uint16_t MoveMask = MemOp.RegMask; 374349cc55cSDimitry Andric if (MemOp.Op == M68kMemOp::Kind::Reg) 375349cc55cSDimitry Andric MoveMask = 1 << getRegisterIndex(MemOp.OuterReg); 376349cc55cSDimitry Andric 377349cc55cSDimitry Andric Inst.addOperand(MCOperand::createImm(MoveMask)); 378349cc55cSDimitry Andric } 379349cc55cSDimitry Andric 380fe6060f1SDimitry Andric // Addr 381fe6060f1SDimitry Andric bool M68kOperand::isAddr() const { 382fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr; 383fe6060f1SDimitry Andric } 384349cc55cSDimitry Andric // TODO: Maybe we can also store the size of OuterDisp 385349cc55cSDimitry Andric // in Size? 386349cc55cSDimitry Andric template <unsigned N> bool M68kOperand::isAddrN() const { 387349cc55cSDimitry Andric if (isAddr()) { 388349cc55cSDimitry Andric int64_t Res; 389349cc55cSDimitry Andric if (MemOp.OuterDisp->evaluateAsAbsolute(Res)) 390349cc55cSDimitry Andric return isInt<N>(Res); 391349cc55cSDimitry Andric return true; 392349cc55cSDimitry Andric } 393349cc55cSDimitry Andric return false; 394349cc55cSDimitry Andric } 395fe6060f1SDimitry Andric void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const { 396fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 397fe6060f1SDimitry Andric } 398fe6060f1SDimitry Andric 399fe6060f1SDimitry Andric // ARI 400fe6060f1SDimitry Andric bool M68kOperand::isARI() const { 401fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect && 402fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 403fe6060f1SDimitry Andric } 404fe6060f1SDimitry Andric void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const { 405fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 406fe6060f1SDimitry Andric } 407fe6060f1SDimitry Andric 408fe6060f1SDimitry Andric // ARID 409fe6060f1SDimitry Andric bool M68kOperand::isARID() const { 410fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement && 411fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 412fe6060f1SDimitry Andric } 413fe6060f1SDimitry Andric void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const { 414fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 415fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 416fe6060f1SDimitry Andric } 417fe6060f1SDimitry Andric 418fe6060f1SDimitry Andric // ARII 419fe6060f1SDimitry Andric bool M68kOperand::isARII() const { 420fe6060f1SDimitry Andric return isMemOp() && 421fe6060f1SDimitry Andric MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex && 422fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 423fe6060f1SDimitry Andric } 424fe6060f1SDimitry Andric void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const { 425fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 426fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 427fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.InnerReg)); 428fe6060f1SDimitry Andric } 429fe6060f1SDimitry Andric 430fe6060f1SDimitry Andric // ARIPD 431fe6060f1SDimitry Andric bool M68kOperand::isARIPD() const { 432fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement && 433fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 434fe6060f1SDimitry Andric } 435fe6060f1SDimitry Andric void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const { 436fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 437fe6060f1SDimitry Andric } 438fe6060f1SDimitry Andric 439fe6060f1SDimitry Andric // ARIPI 440fe6060f1SDimitry Andric bool M68kOperand::isARIPI() const { 441fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement && 442fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 443fe6060f1SDimitry Andric } 444fe6060f1SDimitry Andric void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const { 445fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 446fe6060f1SDimitry Andric } 447fe6060f1SDimitry Andric 448fe6060f1SDimitry Andric // PCD 449fe6060f1SDimitry Andric bool M68kOperand::isPCD() const { 450fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement && 451fe6060f1SDimitry Andric MemOp.OuterReg == M68k::PC; 452fe6060f1SDimitry Andric } 453fe6060f1SDimitry Andric void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const { 454fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 455fe6060f1SDimitry Andric } 456fe6060f1SDimitry Andric 457fe6060f1SDimitry Andric // PCI 458fe6060f1SDimitry Andric bool M68kOperand::isPCI() const { 459fe6060f1SDimitry Andric return isMemOp() && 460fe6060f1SDimitry Andric MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex && 461fe6060f1SDimitry Andric MemOp.OuterReg == M68k::PC; 462fe6060f1SDimitry Andric } 463fe6060f1SDimitry Andric void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const { 464fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 465fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.InnerReg)); 466fe6060f1SDimitry Andric } 467fe6060f1SDimitry Andric 468fe6060f1SDimitry Andric static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address, 469fe6060f1SDimitry Andric bool SP) { 470fe6060f1SDimitry Andric switch (RegNo) { 471fe6060f1SDimitry Andric case M68k::A0: 472fe6060f1SDimitry Andric case M68k::A1: 473fe6060f1SDimitry Andric case M68k::A2: 474fe6060f1SDimitry Andric case M68k::A3: 475fe6060f1SDimitry Andric case M68k::A4: 476fe6060f1SDimitry Andric case M68k::A5: 477fe6060f1SDimitry Andric case M68k::A6: 478fe6060f1SDimitry Andric return Address; 479fe6060f1SDimitry Andric 480fe6060f1SDimitry Andric case M68k::SP: 481fe6060f1SDimitry Andric return SP; 482fe6060f1SDimitry Andric 483fe6060f1SDimitry Andric case M68k::D0: 484fe6060f1SDimitry Andric case M68k::D1: 485fe6060f1SDimitry Andric case M68k::D2: 486fe6060f1SDimitry Andric case M68k::D3: 487fe6060f1SDimitry Andric case M68k::D4: 488fe6060f1SDimitry Andric case M68k::D5: 489fe6060f1SDimitry Andric case M68k::D6: 490fe6060f1SDimitry Andric case M68k::D7: 491fe6060f1SDimitry Andric return Data; 492fe6060f1SDimitry Andric 493fe6060f1SDimitry Andric case M68k::SR: 494fe6060f1SDimitry Andric case M68k::CCR: 495fe6060f1SDimitry Andric return false; 496fe6060f1SDimitry Andric 497fe6060f1SDimitry Andric default: 498fe6060f1SDimitry Andric llvm_unreachable("unexpected register type"); 499fe6060f1SDimitry Andric return false; 500fe6060f1SDimitry Andric } 501fe6060f1SDimitry Andric } 502fe6060f1SDimitry Andric 503349cc55cSDimitry Andric bool M68kOperand::isAReg() const { 504349cc55cSDimitry Andric return isReg() && checkRegisterClass(getReg(), 505349cc55cSDimitry Andric /*Data=*/false, 506349cc55cSDimitry Andric /*Address=*/true, /*SP=*/true); 507349cc55cSDimitry Andric } 508349cc55cSDimitry Andric 509349cc55cSDimitry Andric bool M68kOperand::isDReg() const { 510349cc55cSDimitry Andric return isReg() && checkRegisterClass(getReg(), 511349cc55cSDimitry Andric /*Data=*/true, 512349cc55cSDimitry Andric /*Address=*/false, /*SP=*/false); 513349cc55cSDimitry Andric } 514349cc55cSDimitry Andric 515fe6060f1SDimitry Andric unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op, 516fe6060f1SDimitry Andric unsigned Kind) { 517fe6060f1SDimitry Andric M68kOperand &Operand = (M68kOperand &)Op; 518fe6060f1SDimitry Andric 519fe6060f1SDimitry Andric switch (Kind) { 520fe6060f1SDimitry Andric case MCK_XR16: 521fe6060f1SDimitry Andric case MCK_SPILL: 522fe6060f1SDimitry Andric if (Operand.isReg() && 523fe6060f1SDimitry Andric checkRegisterClass(Operand.getReg(), true, true, true)) { 524fe6060f1SDimitry Andric return Match_Success; 525fe6060f1SDimitry Andric } 526fe6060f1SDimitry Andric break; 527fe6060f1SDimitry Andric 528fe6060f1SDimitry Andric case MCK_AR16: 529fe6060f1SDimitry Andric case MCK_AR32: 530fe6060f1SDimitry Andric if (Operand.isReg() && 531fe6060f1SDimitry Andric checkRegisterClass(Operand.getReg(), false, true, true)) { 532fe6060f1SDimitry Andric return Match_Success; 533fe6060f1SDimitry Andric } 534fe6060f1SDimitry Andric break; 535fe6060f1SDimitry Andric 536fe6060f1SDimitry Andric case MCK_AR32_NOSP: 537fe6060f1SDimitry Andric if (Operand.isReg() && 538fe6060f1SDimitry Andric checkRegisterClass(Operand.getReg(), false, true, false)) { 539fe6060f1SDimitry Andric return Match_Success; 540fe6060f1SDimitry Andric } 541fe6060f1SDimitry Andric break; 542fe6060f1SDimitry Andric 543fe6060f1SDimitry Andric case MCK_DR8: 544fe6060f1SDimitry Andric case MCK_DR16: 545fe6060f1SDimitry Andric case MCK_DR32: 546fe6060f1SDimitry Andric if (Operand.isReg() && 547fe6060f1SDimitry Andric checkRegisterClass(Operand.getReg(), true, false, false)) { 548fe6060f1SDimitry Andric return Match_Success; 549fe6060f1SDimitry Andric } 550fe6060f1SDimitry Andric break; 551fe6060f1SDimitry Andric 552fe6060f1SDimitry Andric case MCK_AR16_TC: 553fe6060f1SDimitry Andric if (Operand.isReg() && 554fe6060f1SDimitry Andric ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) { 555fe6060f1SDimitry Andric return Match_Success; 556fe6060f1SDimitry Andric } 557fe6060f1SDimitry Andric break; 558fe6060f1SDimitry Andric 559fe6060f1SDimitry Andric case MCK_DR16_TC: 560fe6060f1SDimitry Andric if (Operand.isReg() && 561fe6060f1SDimitry Andric ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) { 562fe6060f1SDimitry Andric return Match_Success; 563fe6060f1SDimitry Andric } 564fe6060f1SDimitry Andric break; 565fe6060f1SDimitry Andric 566fe6060f1SDimitry Andric case MCK_XR16_TC: 567fe6060f1SDimitry Andric if (Operand.isReg() && 568fe6060f1SDimitry Andric ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) || 569fe6060f1SDimitry Andric (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) { 570fe6060f1SDimitry Andric return Match_Success; 571fe6060f1SDimitry Andric } 572fe6060f1SDimitry Andric break; 573fe6060f1SDimitry Andric } 574fe6060f1SDimitry Andric 575fe6060f1SDimitry Andric return Match_InvalidOperand; 576fe6060f1SDimitry Andric } 577fe6060f1SDimitry Andric 578*bdd1243dSDimitry Andric bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc, 579fe6060f1SDimitry Andric StringRef RegisterName) { 580fe6060f1SDimitry Andric auto RegisterNameLower = RegisterName.lower(); 581fe6060f1SDimitry Andric 582fe6060f1SDimitry Andric // CCR register 583fe6060f1SDimitry Andric if (RegisterNameLower == "ccr") { 584fe6060f1SDimitry Andric RegNo = M68k::CCR; 585fe6060f1SDimitry Andric return true; 586fe6060f1SDimitry Andric } 587fe6060f1SDimitry Andric 588fe6060f1SDimitry Andric // Parse simple general-purpose registers. 589fe6060f1SDimitry Andric if (RegisterNameLower.size() == 2) { 590fe6060f1SDimitry Andric 591fe6060f1SDimitry Andric switch (RegisterNameLower[0]) { 592fe6060f1SDimitry Andric case 'd': 593fe6060f1SDimitry Andric case 'a': { 594fe6060f1SDimitry Andric if (isdigit(RegisterNameLower[1])) { 595fe6060f1SDimitry Andric unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0; 596fe6060f1SDimitry Andric unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0'); 597fe6060f1SDimitry Andric if (RegIndex < 8) { 598349cc55cSDimitry Andric RegNo = getRegisterByIndex(IndexOffset + RegIndex); 599fe6060f1SDimitry Andric return true; 600fe6060f1SDimitry Andric } 601fe6060f1SDimitry Andric } 602fe6060f1SDimitry Andric break; 603fe6060f1SDimitry Andric } 604fe6060f1SDimitry Andric 605fe6060f1SDimitry Andric case 's': 606fe6060f1SDimitry Andric if (RegisterNameLower[1] == 'p') { 607fe6060f1SDimitry Andric RegNo = M68k::SP; 608fe6060f1SDimitry Andric return true; 609fe6060f1SDimitry Andric } else if (RegisterNameLower[1] == 'r') { 610fe6060f1SDimitry Andric RegNo = M68k::SR; 611fe6060f1SDimitry Andric return true; 612fe6060f1SDimitry Andric } 613fe6060f1SDimitry Andric break; 614fe6060f1SDimitry Andric 615fe6060f1SDimitry Andric case 'p': 616fe6060f1SDimitry Andric if (RegisterNameLower[1] == 'c') { 617fe6060f1SDimitry Andric RegNo = M68k::PC; 618fe6060f1SDimitry Andric return true; 619fe6060f1SDimitry Andric } 620fe6060f1SDimitry Andric break; 621fe6060f1SDimitry Andric } 622fe6060f1SDimitry Andric } 623fe6060f1SDimitry Andric 624fe6060f1SDimitry Andric return false; 625fe6060f1SDimitry Andric } 626fe6060f1SDimitry Andric 627*bdd1243dSDimitry Andric OperandMatchResultTy M68kAsmParser::parseRegister(MCRegister &RegNo) { 628fe6060f1SDimitry Andric bool HasPercent = false; 629fe6060f1SDimitry Andric AsmToken PercentToken; 630fe6060f1SDimitry Andric 631fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n"); 632fe6060f1SDimitry Andric 633fe6060f1SDimitry Andric if (getTok().is(AsmToken::Percent)) { 634fe6060f1SDimitry Andric HasPercent = true; 635fe6060f1SDimitry Andric PercentToken = Lex(); 636fe6060f1SDimitry Andric } else if (!RegisterPrefixOptional.getValue()) { 637fe6060f1SDimitry Andric return MatchOperand_NoMatch; 638fe6060f1SDimitry Andric } 639fe6060f1SDimitry Andric 640fe6060f1SDimitry Andric if (!Parser.getTok().is(AsmToken::Identifier)) { 641fe6060f1SDimitry Andric if (HasPercent) { 642fe6060f1SDimitry Andric getLexer().UnLex(PercentToken); 643fe6060f1SDimitry Andric } 644fe6060f1SDimitry Andric return MatchOperand_NoMatch; 645fe6060f1SDimitry Andric } 646fe6060f1SDimitry Andric 647fe6060f1SDimitry Andric auto RegisterName = Parser.getTok().getString(); 648fe6060f1SDimitry Andric if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) { 649fe6060f1SDimitry Andric if (HasPercent) { 650fe6060f1SDimitry Andric getLexer().UnLex(PercentToken); 651fe6060f1SDimitry Andric } 652fe6060f1SDimitry Andric return MatchOperand_NoMatch; 653fe6060f1SDimitry Andric } 654fe6060f1SDimitry Andric 655fe6060f1SDimitry Andric Parser.Lex(); 656fe6060f1SDimitry Andric return MatchOperand_Success; 657fe6060f1SDimitry Andric } 658fe6060f1SDimitry Andric 659*bdd1243dSDimitry Andric bool M68kAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, 660fe6060f1SDimitry Andric SMLoc &EndLoc) { 661fe6060f1SDimitry Andric auto Result = tryParseRegister(RegNo, StartLoc, EndLoc); 662fe6060f1SDimitry Andric if (Result != MatchOperand_Success) { 663fe6060f1SDimitry Andric return Error(StartLoc, "expected register"); 664fe6060f1SDimitry Andric } 665fe6060f1SDimitry Andric 666fe6060f1SDimitry Andric return false; 667fe6060f1SDimitry Andric } 668fe6060f1SDimitry Andric 669*bdd1243dSDimitry Andric OperandMatchResultTy M68kAsmParser::tryParseRegister(MCRegister &RegNo, 670fe6060f1SDimitry Andric SMLoc &StartLoc, 671fe6060f1SDimitry Andric SMLoc &EndLoc) { 672fe6060f1SDimitry Andric StartLoc = getLexer().getLoc(); 673fe6060f1SDimitry Andric auto Result = parseRegister(RegNo); 674fe6060f1SDimitry Andric EndLoc = getLexer().getLoc(); 675fe6060f1SDimitry Andric return Result; 676fe6060f1SDimitry Andric } 677fe6060f1SDimitry Andric 678fe6060f1SDimitry Andric bool M68kAsmParser::isExpr() { 679fe6060f1SDimitry Andric switch (Parser.getTok().getKind()) { 680fe6060f1SDimitry Andric case AsmToken::Identifier: 681fe6060f1SDimitry Andric case AsmToken::Integer: 682fe6060f1SDimitry Andric return true; 683fe6060f1SDimitry Andric case AsmToken::Minus: 684fe6060f1SDimitry Andric return getLexer().peekTok().getKind() == AsmToken::Integer; 685fe6060f1SDimitry Andric 686fe6060f1SDimitry Andric default: 687fe6060f1SDimitry Andric return false; 688fe6060f1SDimitry Andric } 689fe6060f1SDimitry Andric } 690fe6060f1SDimitry Andric 691fe6060f1SDimitry Andric OperandMatchResultTy M68kAsmParser::parseImm(OperandVector &Operands) { 692fe6060f1SDimitry Andric if (getLexer().isNot(AsmToken::Hash)) { 693fe6060f1SDimitry Andric return MatchOperand_NoMatch; 694fe6060f1SDimitry Andric } 695fe6060f1SDimitry Andric SMLoc Start = getLexer().getLoc(); 696fe6060f1SDimitry Andric Parser.Lex(); 697fe6060f1SDimitry Andric 698fe6060f1SDimitry Andric SMLoc End; 699fe6060f1SDimitry Andric const MCExpr *Expr; 700fe6060f1SDimitry Andric 701fe6060f1SDimitry Andric if (getParser().parseExpression(Expr, End)) { 702fe6060f1SDimitry Andric return MatchOperand_ParseFail; 703fe6060f1SDimitry Andric } 704fe6060f1SDimitry Andric 705fe6060f1SDimitry Andric Operands.push_back(M68kOperand::createImm(Expr, Start, End)); 706fe6060f1SDimitry Andric return MatchOperand_Success; 707fe6060f1SDimitry Andric } 708fe6060f1SDimitry Andric 709fe6060f1SDimitry Andric OperandMatchResultTy M68kAsmParser::parseMemOp(OperandVector &Operands) { 710fe6060f1SDimitry Andric SMLoc Start = getLexer().getLoc(); 711fe6060f1SDimitry Andric bool IsPD = false; 712fe6060f1SDimitry Andric M68kMemOp MemOp; 713fe6060f1SDimitry Andric 714349cc55cSDimitry Andric // Check for a plain register or register mask. 715349cc55cSDimitry Andric auto Result = parseRegOrMoveMask(Operands); 716349cc55cSDimitry Andric if (Result != llvm::MatchOperand_NoMatch) { 717fe6060f1SDimitry Andric return Result; 718fe6060f1SDimitry Andric } 719fe6060f1SDimitry Andric 720fe6060f1SDimitry Andric // Check for pre-decrement & outer displacement. 721fe6060f1SDimitry Andric bool HasDisplacement = false; 722fe6060f1SDimitry Andric if (getLexer().is(AsmToken::Minus)) { 723fe6060f1SDimitry Andric IsPD = true; 724fe6060f1SDimitry Andric Parser.Lex(); 725fe6060f1SDimitry Andric } else if (isExpr()) { 726fe6060f1SDimitry Andric if (Parser.parseExpression(MemOp.OuterDisp)) { 727fe6060f1SDimitry Andric return MatchOperand_ParseFail; 728fe6060f1SDimitry Andric } 729fe6060f1SDimitry Andric HasDisplacement = true; 730fe6060f1SDimitry Andric } 731fe6060f1SDimitry Andric 732fe6060f1SDimitry Andric if (getLexer().isNot(AsmToken::LParen)) { 733fe6060f1SDimitry Andric if (HasDisplacement) { 734fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::Addr; 735fe6060f1SDimitry Andric Operands.push_back( 736fe6060f1SDimitry Andric M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc())); 737fe6060f1SDimitry Andric return MatchOperand_Success; 738fe6060f1SDimitry Andric } else if (IsPD) { 739fe6060f1SDimitry Andric Error(getLexer().getLoc(), "expected ("); 740fe6060f1SDimitry Andric return MatchOperand_ParseFail; 741fe6060f1SDimitry Andric } 742fe6060f1SDimitry Andric 743fe6060f1SDimitry Andric return MatchOperand_NoMatch; 744fe6060f1SDimitry Andric } 745fe6060f1SDimitry Andric Parser.Lex(); 746fe6060f1SDimitry Andric 747fe6060f1SDimitry Andric // Check for constant dereference & MIT-style displacement 748fe6060f1SDimitry Andric if (!HasDisplacement && isExpr()) { 749fe6060f1SDimitry Andric if (Parser.parseExpression(MemOp.OuterDisp)) { 750fe6060f1SDimitry Andric return MatchOperand_ParseFail; 751fe6060f1SDimitry Andric } 752fe6060f1SDimitry Andric HasDisplacement = true; 753fe6060f1SDimitry Andric 754fe6060f1SDimitry Andric // If we're not followed by a comma, we're a constant dereference. 755fe6060f1SDimitry Andric if (getLexer().isNot(AsmToken::Comma)) { 756fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::Addr; 757fe6060f1SDimitry Andric Operands.push_back( 758fe6060f1SDimitry Andric M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc())); 759fe6060f1SDimitry Andric return MatchOperand_Success; 760fe6060f1SDimitry Andric } 761fe6060f1SDimitry Andric 762fe6060f1SDimitry Andric Parser.Lex(); 763fe6060f1SDimitry Andric } 764fe6060f1SDimitry Andric 765fe6060f1SDimitry Andric Result = parseRegister(MemOp.OuterReg); 766fe6060f1SDimitry Andric if (Result == MatchOperand_ParseFail) { 767fe6060f1SDimitry Andric return MatchOperand_ParseFail; 768fe6060f1SDimitry Andric } 769fe6060f1SDimitry Andric 770fe6060f1SDimitry Andric if (Result != MatchOperand_Success) { 771fe6060f1SDimitry Andric Error(getLexer().getLoc(), "expected register"); 772fe6060f1SDimitry Andric return MatchOperand_ParseFail; 773fe6060f1SDimitry Andric } 774fe6060f1SDimitry Andric 775fe6060f1SDimitry Andric // Check for Index. 776fe6060f1SDimitry Andric bool HasIndex = false; 777fe6060f1SDimitry Andric if (Parser.getTok().is(AsmToken::Comma)) { 778fe6060f1SDimitry Andric Parser.Lex(); 779fe6060f1SDimitry Andric 780fe6060f1SDimitry Andric Result = parseRegister(MemOp.InnerReg); 781fe6060f1SDimitry Andric if (Result == MatchOperand_ParseFail) { 782fe6060f1SDimitry Andric return Result; 783fe6060f1SDimitry Andric } 784fe6060f1SDimitry Andric 785fe6060f1SDimitry Andric if (Result == MatchOperand_NoMatch) { 786fe6060f1SDimitry Andric Error(getLexer().getLoc(), "expected register"); 787fe6060f1SDimitry Andric return MatchOperand_ParseFail; 788fe6060f1SDimitry Andric } 789fe6060f1SDimitry Andric 790fe6060f1SDimitry Andric // TODO: parse size, scale and inner displacement. 791fe6060f1SDimitry Andric MemOp.Size = 4; 792fe6060f1SDimitry Andric MemOp.Scale = 1; 793fe6060f1SDimitry Andric MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4); 794fe6060f1SDimitry Andric HasIndex = true; 795fe6060f1SDimitry Andric } 796fe6060f1SDimitry Andric 797fe6060f1SDimitry Andric if (Parser.getTok().isNot(AsmToken::RParen)) { 798fe6060f1SDimitry Andric Error(getLexer().getLoc(), "expected )"); 799fe6060f1SDimitry Andric return MatchOperand_ParseFail; 800fe6060f1SDimitry Andric } 801fe6060f1SDimitry Andric Parser.Lex(); 802fe6060f1SDimitry Andric 803fe6060f1SDimitry Andric bool IsPI = false; 804fe6060f1SDimitry Andric if (!IsPD && Parser.getTok().is(AsmToken::Plus)) { 805fe6060f1SDimitry Andric Parser.Lex(); 806fe6060f1SDimitry Andric IsPI = true; 807fe6060f1SDimitry Andric } 808fe6060f1SDimitry Andric 809fe6060f1SDimitry Andric SMLoc End = getLexer().getLoc(); 810fe6060f1SDimitry Andric 811fe6060f1SDimitry Andric unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement); 812fe6060f1SDimitry Andric if (OpCount > 1) { 813fe6060f1SDimitry Andric Error(Start, "only one of post-increment, pre-decrement or displacement " 814fe6060f1SDimitry Andric "can be used"); 815fe6060f1SDimitry Andric return MatchOperand_ParseFail; 816fe6060f1SDimitry Andric } 817fe6060f1SDimitry Andric 818fe6060f1SDimitry Andric if (IsPD) { 819fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegPreDecrement; 820fe6060f1SDimitry Andric } else if (IsPI) { 821fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegPostIncrement; 822fe6060f1SDimitry Andric } else if (HasIndex) { 823fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex; 824fe6060f1SDimitry Andric } else if (HasDisplacement) { 825fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement; 826fe6060f1SDimitry Andric } else { 827fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegIndirect; 828fe6060f1SDimitry Andric } 829fe6060f1SDimitry Andric 830fe6060f1SDimitry Andric Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End)); 831fe6060f1SDimitry Andric return MatchOperand_Success; 832fe6060f1SDimitry Andric } 833fe6060f1SDimitry Andric 834349cc55cSDimitry Andric OperandMatchResultTy 835349cc55cSDimitry Andric M68kAsmParser::parseRegOrMoveMask(OperandVector &Operands) { 836349cc55cSDimitry Andric SMLoc Start = getLexer().getLoc(); 837349cc55cSDimitry Andric M68kMemOp MemOp(M68kMemOp::Kind::RegMask); 838349cc55cSDimitry Andric MemOp.RegMask = 0; 839349cc55cSDimitry Andric 840349cc55cSDimitry Andric for (;;) { 841349cc55cSDimitry Andric bool IsFirstRegister = 842349cc55cSDimitry Andric (MemOp.Op == M68kMemOp::Kind::RegMask) && (MemOp.RegMask == 0); 843349cc55cSDimitry Andric 844*bdd1243dSDimitry Andric MCRegister FirstRegister; 845349cc55cSDimitry Andric auto Result = parseRegister(FirstRegister); 846349cc55cSDimitry Andric if (IsFirstRegister && (Result == llvm::MatchOperand_NoMatch)) { 847349cc55cSDimitry Andric return MatchOperand_NoMatch; 848349cc55cSDimitry Andric } 849349cc55cSDimitry Andric if (Result != llvm::MatchOperand_Success) { 850349cc55cSDimitry Andric Error(getLexer().getLoc(), "expected start register"); 851349cc55cSDimitry Andric return MatchOperand_ParseFail; 852349cc55cSDimitry Andric } 853349cc55cSDimitry Andric 854*bdd1243dSDimitry Andric MCRegister LastRegister = FirstRegister; 855349cc55cSDimitry Andric if (getLexer().is(AsmToken::Minus)) { 856349cc55cSDimitry Andric getLexer().Lex(); 857349cc55cSDimitry Andric Result = parseRegister(LastRegister); 858349cc55cSDimitry Andric if (Result != llvm::MatchOperand_Success) { 859349cc55cSDimitry Andric Error(getLexer().getLoc(), "expected end register"); 860349cc55cSDimitry Andric return MatchOperand_ParseFail; 861349cc55cSDimitry Andric } 862349cc55cSDimitry Andric } 863349cc55cSDimitry Andric 864349cc55cSDimitry Andric unsigned FirstRegisterIndex = getRegisterIndex(FirstRegister); 865349cc55cSDimitry Andric unsigned LastRegisterIndex = getRegisterIndex(LastRegister); 866349cc55cSDimitry Andric 867349cc55cSDimitry Andric uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1; 868349cc55cSDimitry Andric uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex; 869349cc55cSDimitry Andric 870349cc55cSDimitry Andric if (IsFirstRegister && (FirstRegister == LastRegister)) { 871349cc55cSDimitry Andric // First register range is a single register, simplify to just Reg 872349cc55cSDimitry Andric // so that it matches more operands. 873349cc55cSDimitry Andric MemOp.Op = M68kMemOp::Kind::Reg; 874349cc55cSDimitry Andric MemOp.OuterReg = FirstRegister; 875349cc55cSDimitry Andric } else { 876349cc55cSDimitry Andric if (MemOp.Op == M68kMemOp::Kind::Reg) { 877349cc55cSDimitry Andric // This is the second register being specified - expand the Reg operand 878349cc55cSDimitry Andric // into a mask first. 879349cc55cSDimitry Andric MemOp.Op = M68kMemOp::Kind::RegMask; 880349cc55cSDimitry Andric MemOp.RegMask = 1 << getRegisterIndex(MemOp.OuterReg); 881349cc55cSDimitry Andric 882349cc55cSDimitry Andric if (MemOp.RegMask == 0) { 883349cc55cSDimitry Andric Error(getLexer().getLoc(), 884349cc55cSDimitry Andric "special registers cannot be used in register masks"); 885349cc55cSDimitry Andric return MatchOperand_ParseFail; 886349cc55cSDimitry Andric } 887349cc55cSDimitry Andric } 888349cc55cSDimitry Andric 889349cc55cSDimitry Andric if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16)) { 890349cc55cSDimitry Andric Error(getLexer().getLoc(), 891349cc55cSDimitry Andric "special registers cannot be used in register masks"); 892349cc55cSDimitry Andric return MatchOperand_ParseFail; 893349cc55cSDimitry Andric } 894349cc55cSDimitry Andric 895349cc55cSDimitry Andric if (NewMaskBits & MemOp.RegMask) { 896349cc55cSDimitry Andric Error(getLexer().getLoc(), "conflicting masked registers"); 897349cc55cSDimitry Andric return MatchOperand_ParseFail; 898349cc55cSDimitry Andric } 899349cc55cSDimitry Andric 900349cc55cSDimitry Andric MemOp.RegMask |= NewMaskBits; 901349cc55cSDimitry Andric } 902349cc55cSDimitry Andric 903349cc55cSDimitry Andric if (getLexer().isNot(AsmToken::Slash)) { 904349cc55cSDimitry Andric break; 905349cc55cSDimitry Andric } 906349cc55cSDimitry Andric 907349cc55cSDimitry Andric getLexer().Lex(); 908349cc55cSDimitry Andric } 909349cc55cSDimitry Andric 910349cc55cSDimitry Andric Operands.push_back( 911349cc55cSDimitry Andric M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc())); 912349cc55cSDimitry Andric return MatchOperand_Success; 913349cc55cSDimitry Andric } 914349cc55cSDimitry Andric 915fe6060f1SDimitry Andric void M68kAsmParser::eatComma() { 916fe6060f1SDimitry Andric if (Parser.getTok().is(AsmToken::Comma)) { 917fe6060f1SDimitry Andric Parser.Lex(); 918fe6060f1SDimitry Andric } 919fe6060f1SDimitry Andric } 920fe6060f1SDimitry Andric 921fe6060f1SDimitry Andric bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 922fe6060f1SDimitry Andric SMLoc NameLoc, OperandVector &Operands) { 923fe6060f1SDimitry Andric SMLoc Start = getLexer().getLoc(); 924fe6060f1SDimitry Andric Operands.push_back(M68kOperand::createToken(Name, Start, Start)); 925fe6060f1SDimitry Andric 926fe6060f1SDimitry Andric bool First = true; 927fe6060f1SDimitry Andric while (Parser.getTok().isNot(AsmToken::EndOfStatement)) { 928fe6060f1SDimitry Andric if (!First) { 929fe6060f1SDimitry Andric eatComma(); 930fe6060f1SDimitry Andric } else { 931fe6060f1SDimitry Andric First = false; 932fe6060f1SDimitry Andric } 933fe6060f1SDimitry Andric 934fe6060f1SDimitry Andric auto MatchResult = MatchOperandParserImpl(Operands, Name); 935fe6060f1SDimitry Andric if (MatchResult == MatchOperand_Success) { 936fe6060f1SDimitry Andric continue; 937fe6060f1SDimitry Andric } 938fe6060f1SDimitry Andric 939fe6060f1SDimitry Andric // Add custom operand formats here... 940fe6060f1SDimitry Andric SMLoc Loc = getLexer().getLoc(); 941fe6060f1SDimitry Andric Parser.eatToEndOfStatement(); 942fe6060f1SDimitry Andric return Error(Loc, "unexpected token parsing operands"); 943fe6060f1SDimitry Andric } 944fe6060f1SDimitry Andric 945fe6060f1SDimitry Andric // Eat EndOfStatement. 946fe6060f1SDimitry Andric Parser.Lex(); 947fe6060f1SDimitry Andric return false; 948fe6060f1SDimitry Andric } 949fe6060f1SDimitry Andric 950fe6060f1SDimitry Andric bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; } 951fe6060f1SDimitry Andric 952fe6060f1SDimitry Andric bool M68kAsmParser::invalidOperand(SMLoc const &Loc, 953fe6060f1SDimitry Andric OperandVector const &Operands, 954fe6060f1SDimitry Andric uint64_t const &ErrorInfo) { 955fe6060f1SDimitry Andric SMLoc ErrorLoc = Loc; 956fe6060f1SDimitry Andric char const *Diag = 0; 957fe6060f1SDimitry Andric 958fe6060f1SDimitry Andric if (ErrorInfo != ~0U) { 959fe6060f1SDimitry Andric if (ErrorInfo >= Operands.size()) { 960fe6060f1SDimitry Andric Diag = "too few operands for instruction."; 961fe6060f1SDimitry Andric } else { 962fe6060f1SDimitry Andric auto const &Op = (M68kOperand const &)*Operands[ErrorInfo]; 963fe6060f1SDimitry Andric if (Op.getStartLoc() != SMLoc()) { 964fe6060f1SDimitry Andric ErrorLoc = Op.getStartLoc(); 965fe6060f1SDimitry Andric } 966fe6060f1SDimitry Andric } 967fe6060f1SDimitry Andric } 968fe6060f1SDimitry Andric 969fe6060f1SDimitry Andric if (!Diag) { 970fe6060f1SDimitry Andric Diag = "invalid operand for instruction"; 971fe6060f1SDimitry Andric } 972fe6060f1SDimitry Andric 973fe6060f1SDimitry Andric return Error(ErrorLoc, Diag); 974fe6060f1SDimitry Andric } 975fe6060f1SDimitry Andric 976fe6060f1SDimitry Andric bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc, 977fe6060f1SDimitry Andric uint64_t const &ErrorInfo) { 978fe6060f1SDimitry Andric return Error(Loc, "instruction requires a CPU feature not currently enabled"); 979fe6060f1SDimitry Andric } 980fe6060f1SDimitry Andric 981fe6060f1SDimitry Andric bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc, 982fe6060f1SDimitry Andric MCStreamer &Out) const { 983fe6060f1SDimitry Andric Inst.setLoc(Loc); 984fe6060f1SDimitry Andric Out.emitInstruction(Inst, STI); 985fe6060f1SDimitry Andric 986fe6060f1SDimitry Andric return false; 987fe6060f1SDimitry Andric } 988fe6060f1SDimitry Andric 989fe6060f1SDimitry Andric bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode, 990fe6060f1SDimitry Andric OperandVector &Operands, 991fe6060f1SDimitry Andric MCStreamer &Out, 992fe6060f1SDimitry Andric uint64_t &ErrorInfo, 993fe6060f1SDimitry Andric bool MatchingInlineAsm) { 994fe6060f1SDimitry Andric MCInst Inst; 995fe6060f1SDimitry Andric unsigned MatchResult = 996fe6060f1SDimitry Andric MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); 997fe6060f1SDimitry Andric 998fe6060f1SDimitry Andric switch (MatchResult) { 999fe6060f1SDimitry Andric case Match_Success: 1000fe6060f1SDimitry Andric return emit(Inst, Loc, Out); 1001fe6060f1SDimitry Andric case Match_MissingFeature: 1002fe6060f1SDimitry Andric return missingFeature(Loc, ErrorInfo); 1003fe6060f1SDimitry Andric case Match_InvalidOperand: 1004fe6060f1SDimitry Andric return invalidOperand(Loc, Operands, ErrorInfo); 1005fe6060f1SDimitry Andric case Match_MnemonicFail: 1006fe6060f1SDimitry Andric return Error(Loc, "invalid instruction"); 1007fe6060f1SDimitry Andric default: 1008fe6060f1SDimitry Andric return true; 1009fe6060f1SDimitry Andric } 1010fe6060f1SDimitry Andric } 1011fe6060f1SDimitry Andric 1012fe6060f1SDimitry Andric void M68kOperand::print(raw_ostream &OS) const { 1013fe6060f1SDimitry Andric switch (Kind) { 101469ade1e0SDimitry Andric case KindTy::Invalid: 1015fe6060f1SDimitry Andric OS << "invalid"; 1016fe6060f1SDimitry Andric break; 1017fe6060f1SDimitry Andric 101869ade1e0SDimitry Andric case KindTy::Token: 1019fe6060f1SDimitry Andric OS << "token '" << Token << "'"; 1020fe6060f1SDimitry Andric break; 1021fe6060f1SDimitry Andric 102269ade1e0SDimitry Andric case KindTy::Imm: 1023fe6060f1SDimitry Andric OS << "immediate " << Imm; 1024fe6060f1SDimitry Andric break; 1025fe6060f1SDimitry Andric 102669ade1e0SDimitry Andric case KindTy::MemOp: 1027fe6060f1SDimitry Andric MemOp.print(OS); 1028fe6060f1SDimitry Andric break; 1029fe6060f1SDimitry Andric } 1030fe6060f1SDimitry Andric } 1031