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