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; 46bdd1243dSDimitry Andric bool parseRegisterName(MCRegister &RegNo, SMLoc Loc, StringRef RegisterName); 4706c3fb27SDimitry Andric ParseStatus parseRegister(MCRegister &RegNo); 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric // Parser functions. 50fe6060f1SDimitry Andric void eatComma(); 51fe6060f1SDimitry Andric 52fe6060f1SDimitry Andric bool isExpr(); 5306c3fb27SDimitry Andric ParseStatus parseImm(OperandVector &Operands); 5406c3fb27SDimitry Andric ParseStatus parseMemOp(OperandVector &Operands); 5506c3fb27SDimitry Andric ParseStatus 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; 695f757f3fSDimitry Andric bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; 705f757f3fSDimitry Andric ParseStatus tryParseRegister(MCRegister &Reg, 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 MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 75fe6060f1SDimitry Andric OperandVector &Operands, MCStreamer &Out, 76fe6060f1SDimitry Andric uint64_t &ErrorInfo, 77fe6060f1SDimitry Andric bool MatchingInlineAsm) override; 78fe6060f1SDimitry Andric }; 79fe6060f1SDimitry Andric 80fe6060f1SDimitry Andric struct M68kMemOp { 81fe6060f1SDimitry Andric enum class Kind { 82fe6060f1SDimitry Andric Addr, 83349cc55cSDimitry Andric RegMask, 84fe6060f1SDimitry Andric Reg, 85fe6060f1SDimitry Andric RegIndirect, 86fe6060f1SDimitry Andric RegPostIncrement, 87fe6060f1SDimitry Andric RegPreDecrement, 88fe6060f1SDimitry Andric RegIndirectDisplacement, 89fe6060f1SDimitry Andric RegIndirectDisplacementIndex, 90fe6060f1SDimitry Andric }; 91fe6060f1SDimitry Andric 92fe6060f1SDimitry Andric // These variables are used for the following forms: 93fe6060f1SDimitry Andric // Addr: (OuterDisp) 94349cc55cSDimitry Andric // RegMask: RegMask (as register mask) 95fe6060f1SDimitry Andric // Reg: %OuterReg 96fe6060f1SDimitry Andric // RegIndirect: (%OuterReg) 97fe6060f1SDimitry Andric // RegPostIncrement: (%OuterReg)+ 98fe6060f1SDimitry Andric // RegPreDecrement: -(%OuterReg) 99fe6060f1SDimitry Andric // RegIndirectDisplacement: OuterDisp(%OuterReg) 100fe6060f1SDimitry Andric // RegIndirectDisplacementIndex: 101fe6060f1SDimitry Andric // OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp) 102fe6060f1SDimitry Andric 103fe6060f1SDimitry Andric Kind Op; 104bdd1243dSDimitry Andric MCRegister OuterReg; 105bdd1243dSDimitry Andric MCRegister InnerReg; 106fe6060f1SDimitry Andric const MCExpr *OuterDisp; 107fe6060f1SDimitry Andric const MCExpr *InnerDisp; 108fe6060f1SDimitry Andric uint8_t Size : 4; 109fe6060f1SDimitry Andric uint8_t Scale : 4; 110fe6060f1SDimitry Andric const MCExpr *Expr; 111349cc55cSDimitry Andric uint16_t RegMask; 112fe6060f1SDimitry Andric 113fe6060f1SDimitry Andric M68kMemOp() {} 114fe6060f1SDimitry Andric M68kMemOp(Kind Op) : Op(Op) {} 115fe6060f1SDimitry Andric 116fe6060f1SDimitry Andric void print(raw_ostream &OS) const; 117fe6060f1SDimitry Andric }; 118fe6060f1SDimitry Andric 119fe6060f1SDimitry Andric /// An parsed M68k assembly operand. 120fe6060f1SDimitry Andric class M68kOperand : public MCParsedAsmOperand { 121fe6060f1SDimitry Andric typedef MCParsedAsmOperand Base; 122fe6060f1SDimitry Andric 12369ade1e0SDimitry Andric enum class KindTy { 124fe6060f1SDimitry Andric Invalid, 125fe6060f1SDimitry Andric Token, 126fe6060f1SDimitry Andric Imm, 127fe6060f1SDimitry Andric MemOp, 128fe6060f1SDimitry Andric }; 129fe6060f1SDimitry Andric 13069ade1e0SDimitry Andric KindTy Kind; 131fe6060f1SDimitry Andric SMLoc Start, End; 132fe6060f1SDimitry Andric union { 133fe6060f1SDimitry Andric StringRef Token; 134fe6060f1SDimitry Andric const MCExpr *Expr; 135fe6060f1SDimitry Andric M68kMemOp MemOp; 136fe6060f1SDimitry Andric }; 137fe6060f1SDimitry Andric 138349cc55cSDimitry Andric template <unsigned N> bool isAddrN() const; 139349cc55cSDimitry Andric 140fe6060f1SDimitry Andric public: 14169ade1e0SDimitry Andric M68kOperand(KindTy Kind, SMLoc Start, SMLoc End) 142fe6060f1SDimitry Andric : Base(), Kind(Kind), Start(Start), End(End) {} 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric SMLoc getStartLoc() const override { return Start; } 145fe6060f1SDimitry Andric SMLoc getEndLoc() const override { return End; } 146fe6060f1SDimitry Andric 147fe6060f1SDimitry Andric void print(raw_ostream &OS) const override; 148fe6060f1SDimitry Andric 149fe6060f1SDimitry Andric bool isMem() const override { return false; } 15069ade1e0SDimitry Andric bool isMemOp() const { return Kind == KindTy::MemOp; } 151fe6060f1SDimitry Andric 152fe6060f1SDimitry Andric static void addExpr(MCInst &Inst, const MCExpr *Expr); 153fe6060f1SDimitry Andric 154fe6060f1SDimitry Andric // Reg 155fe6060f1SDimitry Andric bool isReg() const override; 156349cc55cSDimitry Andric bool isAReg() const; 157349cc55cSDimitry Andric bool isDReg() const; 15806c3fb27SDimitry Andric bool isFPDReg() const; 1595f757f3fSDimitry Andric bool isFPCReg() const; 160*0fca6ea1SDimitry Andric MCRegister 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 17906c3fb27SDimitry Andric // Imm for TRAP instruction 18006c3fb27SDimitry Andric bool isTrapImm() const; 18106c3fb27SDimitry Andric // Imm for BKPT instruction 18206c3fb27SDimitry Andric bool isBkptImm() const; 18306c3fb27SDimitry Andric 184349cc55cSDimitry Andric // MoveMask 185349cc55cSDimitry Andric bool isMoveMask() const; 186349cc55cSDimitry Andric void addMoveMaskOperands(MCInst &Inst, unsigned N) const; 187349cc55cSDimitry Andric 188fe6060f1SDimitry Andric // Addr 189fe6060f1SDimitry Andric bool isAddr() const; 190349cc55cSDimitry Andric bool isAddr8() const { return isAddrN<8>(); } 191349cc55cSDimitry Andric bool isAddr16() const { return isAddrN<16>(); } 192349cc55cSDimitry Andric bool isAddr32() const { return isAddrN<32>(); } 193fe6060f1SDimitry Andric void addAddrOperands(MCInst &Inst, unsigned N) const; 194fe6060f1SDimitry Andric 195fe6060f1SDimitry Andric // ARI 196fe6060f1SDimitry Andric bool isARI() const; 197fe6060f1SDimitry Andric void addARIOperands(MCInst &Inst, unsigned N) const; 198fe6060f1SDimitry Andric 199fe6060f1SDimitry Andric // ARID 200fe6060f1SDimitry Andric bool isARID() const; 201fe6060f1SDimitry Andric void addARIDOperands(MCInst &Inst, unsigned N) const; 202fe6060f1SDimitry Andric 203fe6060f1SDimitry Andric // ARII 204fe6060f1SDimitry Andric bool isARII() const; 205fe6060f1SDimitry Andric void addARIIOperands(MCInst &Inst, unsigned N) const; 206fe6060f1SDimitry Andric 207fe6060f1SDimitry Andric // ARIPD 208fe6060f1SDimitry Andric bool isARIPD() const; 209fe6060f1SDimitry Andric void addARIPDOperands(MCInst &Inst, unsigned N) const; 210fe6060f1SDimitry Andric 211fe6060f1SDimitry Andric // ARIPI 212fe6060f1SDimitry Andric bool isARIPI() const; 213fe6060f1SDimitry Andric void addARIPIOperands(MCInst &Inst, unsigned N) const; 214fe6060f1SDimitry Andric 215fe6060f1SDimitry Andric // PCD 216fe6060f1SDimitry Andric bool isPCD() const; 217fe6060f1SDimitry Andric void addPCDOperands(MCInst &Inst, unsigned N) const; 218fe6060f1SDimitry Andric 219fe6060f1SDimitry Andric // PCI 220fe6060f1SDimitry Andric bool isPCI() const; 221fe6060f1SDimitry Andric void addPCIOperands(MCInst &Inst, unsigned N) const; 222fe6060f1SDimitry Andric }; 223fe6060f1SDimitry Andric 224fe6060f1SDimitry Andric } // end anonymous namespace. 225fe6060f1SDimitry Andric 226fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() { 227fe6060f1SDimitry Andric RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget()); 228fe6060f1SDimitry Andric } 229fe6060f1SDimitry Andric 23006c3fb27SDimitry Andric #define GET_REGISTER_MATCHER 231fe6060f1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION 232fe6060f1SDimitry Andric #include "M68kGenAsmMatcher.inc" 233fe6060f1SDimitry Andric 234349cc55cSDimitry Andric static inline unsigned getRegisterByIndex(unsigned RegisterIndex) { 235349cc55cSDimitry Andric static unsigned RegistersByIndex[] = { 236349cc55cSDimitry Andric M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5, 237349cc55cSDimitry Andric M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3, 23806c3fb27SDimitry Andric M68k::A4, M68k::A5, M68k::A6, M68k::SP, M68k::FP0, M68k::FP1, 23906c3fb27SDimitry Andric M68k::FP2, M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7}; 240349cc55cSDimitry Andric assert(RegisterIndex <= 241349cc55cSDimitry Andric sizeof(RegistersByIndex) / sizeof(RegistersByIndex[0])); 242349cc55cSDimitry Andric return RegistersByIndex[RegisterIndex]; 243349cc55cSDimitry Andric } 244349cc55cSDimitry Andric 245349cc55cSDimitry Andric static inline unsigned getRegisterIndex(unsigned Register) { 246349cc55cSDimitry Andric if (Register >= M68k::D0 && Register <= M68k::D7) 247349cc55cSDimitry Andric return Register - M68k::D0; 248349cc55cSDimitry Andric if (Register >= M68k::A0 && Register <= M68k::A6) 249349cc55cSDimitry Andric return Register - M68k::A0 + 8; 25006c3fb27SDimitry Andric if (Register >= M68k::FP0 && Register <= M68k::FP7) 25106c3fb27SDimitry Andric return Register - M68k::FP0 + 16; 252349cc55cSDimitry Andric 253349cc55cSDimitry Andric switch (Register) { 254349cc55cSDimitry Andric case M68k::SP: 255349cc55cSDimitry Andric // SP is sadly not contiguous with the rest of the An registers 256349cc55cSDimitry Andric return 15; 257349cc55cSDimitry Andric 2585f757f3fSDimitry Andric // We don't care about the indices of these registers. 259349cc55cSDimitry Andric case M68k::PC: 260349cc55cSDimitry Andric case M68k::CCR: 2615f757f3fSDimitry Andric case M68k::FPC: 2625f757f3fSDimitry Andric case M68k::FPS: 2635f757f3fSDimitry Andric case M68k::FPIAR: 2645f757f3fSDimitry Andric return UINT_MAX; 265349cc55cSDimitry Andric 266349cc55cSDimitry Andric default: 267349cc55cSDimitry Andric llvm_unreachable("unexpected register number"); 268349cc55cSDimitry Andric } 269349cc55cSDimitry Andric } 270349cc55cSDimitry Andric 271fe6060f1SDimitry Andric void M68kMemOp::print(raw_ostream &OS) const { 272fe6060f1SDimitry Andric switch (Op) { 273fe6060f1SDimitry Andric case Kind::Addr: 274fe6060f1SDimitry Andric OS << OuterDisp; 275fe6060f1SDimitry Andric break; 276349cc55cSDimitry Andric case Kind::RegMask: 277349cc55cSDimitry Andric OS << "RegMask(" << format("%04x", RegMask) << ")"; 278349cc55cSDimitry Andric break; 279fe6060f1SDimitry Andric case Kind::Reg: 280fe6060f1SDimitry Andric OS << '%' << OuterReg; 281fe6060f1SDimitry Andric break; 282fe6060f1SDimitry Andric case Kind::RegIndirect: 283fe6060f1SDimitry Andric OS << "(%" << OuterReg << ')'; 284fe6060f1SDimitry Andric break; 285fe6060f1SDimitry Andric case Kind::RegPostIncrement: 286fe6060f1SDimitry Andric OS << "(%" << OuterReg << ")+"; 287fe6060f1SDimitry Andric break; 288fe6060f1SDimitry Andric case Kind::RegPreDecrement: 289fe6060f1SDimitry Andric OS << "-(%" << OuterReg << ")"; 290fe6060f1SDimitry Andric break; 291fe6060f1SDimitry Andric case Kind::RegIndirectDisplacement: 292fe6060f1SDimitry Andric OS << OuterDisp << "(%" << OuterReg << ")"; 293fe6060f1SDimitry Andric break; 294fe6060f1SDimitry Andric case Kind::RegIndirectDisplacementIndex: 295fe6060f1SDimitry Andric OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size 296fe6060f1SDimitry Andric << ", " << InnerDisp << ")"; 297fe6060f1SDimitry Andric break; 298fe6060f1SDimitry Andric } 299fe6060f1SDimitry Andric } 300fe6060f1SDimitry Andric 301fe6060f1SDimitry Andric void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) { 302fe6060f1SDimitry Andric if (auto Const = dyn_cast<MCConstantExpr>(Expr)) { 303fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createImm(Const->getValue())); 304fe6060f1SDimitry Andric return; 305fe6060f1SDimitry Andric } 306fe6060f1SDimitry Andric 307fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 308fe6060f1SDimitry Andric } 309fe6060f1SDimitry Andric 310fe6060f1SDimitry Andric // Reg 311fe6060f1SDimitry Andric bool M68kOperand::isReg() const { 31269ade1e0SDimitry Andric return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg; 313fe6060f1SDimitry Andric } 314fe6060f1SDimitry Andric 315*0fca6ea1SDimitry Andric MCRegister M68kOperand::getReg() const { 316fe6060f1SDimitry Andric assert(isReg()); 317fe6060f1SDimitry Andric return MemOp.OuterReg; 318fe6060f1SDimitry Andric } 319fe6060f1SDimitry Andric 320fe6060f1SDimitry Andric void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const { 321fe6060f1SDimitry Andric assert(isReg() && "wrong operand kind"); 322fe6060f1SDimitry Andric assert((N == 1) && "can only handle one register operand"); 323fe6060f1SDimitry Andric 324fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(getReg())); 325fe6060f1SDimitry Andric } 326fe6060f1SDimitry Andric 327fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp, 328fe6060f1SDimitry Andric SMLoc Start, SMLoc End) { 32969ade1e0SDimitry Andric auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start, End); 330fe6060f1SDimitry Andric Op->MemOp = MemOp; 331fe6060f1SDimitry Andric return Op; 332fe6060f1SDimitry Andric } 333fe6060f1SDimitry Andric 334fe6060f1SDimitry Andric // Token 33569ade1e0SDimitry Andric bool M68kOperand::isToken() const { return Kind == KindTy::Token; } 336fe6060f1SDimitry Andric StringRef M68kOperand::getToken() const { 337fe6060f1SDimitry Andric assert(isToken()); 338fe6060f1SDimitry Andric return Token; 339fe6060f1SDimitry Andric } 340fe6060f1SDimitry Andric 341fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token, 342fe6060f1SDimitry Andric SMLoc Start, SMLoc End) { 34369ade1e0SDimitry Andric auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start, End); 344fe6060f1SDimitry Andric Op->Token = Token; 345fe6060f1SDimitry Andric return Op; 346fe6060f1SDimitry Andric } 347fe6060f1SDimitry Andric 348fe6060f1SDimitry Andric // Imm 34969ade1e0SDimitry Andric bool M68kOperand::isImm() const { return Kind == KindTy::Imm; } 350fe6060f1SDimitry Andric void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const { 351349cc55cSDimitry Andric assert(isImm() && "wrong operand kind"); 352fe6060f1SDimitry Andric assert((N == 1) && "can only handle one register operand"); 353fe6060f1SDimitry Andric 354fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, Expr); 355fe6060f1SDimitry Andric } 356fe6060f1SDimitry Andric 357fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr, 358fe6060f1SDimitry Andric SMLoc Start, SMLoc End) { 35969ade1e0SDimitry Andric auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start, End); 360fe6060f1SDimitry Andric Op->Expr = Expr; 361fe6060f1SDimitry Andric return Op; 362fe6060f1SDimitry Andric } 363fe6060f1SDimitry Andric 36406c3fb27SDimitry Andric bool M68kOperand::isTrapImm() const { 36506c3fb27SDimitry Andric int64_t Value; 36606c3fb27SDimitry Andric if (!isImm() || !Expr->evaluateAsAbsolute(Value)) 36706c3fb27SDimitry Andric return false; 36806c3fb27SDimitry Andric 36906c3fb27SDimitry Andric return isUInt<4>(Value); 37006c3fb27SDimitry Andric } 37106c3fb27SDimitry Andric 37206c3fb27SDimitry Andric bool M68kOperand::isBkptImm() const { 37306c3fb27SDimitry Andric int64_t Value; 37406c3fb27SDimitry Andric if (!isImm() || !Expr->evaluateAsAbsolute(Value)) 37506c3fb27SDimitry Andric return false; 37606c3fb27SDimitry Andric 37706c3fb27SDimitry Andric return isUInt<3>(Value); 37806c3fb27SDimitry Andric } 37906c3fb27SDimitry Andric 380349cc55cSDimitry Andric // MoveMask 381349cc55cSDimitry Andric bool M68kOperand::isMoveMask() const { 382349cc55cSDimitry Andric if (!isMemOp()) 383349cc55cSDimitry Andric return false; 384349cc55cSDimitry Andric 385349cc55cSDimitry Andric if (MemOp.Op == M68kMemOp::Kind::RegMask) 386349cc55cSDimitry Andric return true; 387349cc55cSDimitry Andric 388349cc55cSDimitry Andric if (MemOp.Op != M68kMemOp::Kind::Reg) 389349cc55cSDimitry Andric return false; 390349cc55cSDimitry Andric 391349cc55cSDimitry Andric // Only regular address / data registers are allowed to be used 392349cc55cSDimitry Andric // in register masks. 393349cc55cSDimitry Andric return getRegisterIndex(MemOp.OuterReg) < 16; 394349cc55cSDimitry Andric } 395349cc55cSDimitry Andric 396349cc55cSDimitry Andric void M68kOperand::addMoveMaskOperands(MCInst &Inst, unsigned N) const { 397349cc55cSDimitry Andric assert(isMoveMask() && "wrong operand kind"); 398349cc55cSDimitry Andric assert((N == 1) && "can only handle one immediate operand"); 399349cc55cSDimitry Andric 400349cc55cSDimitry Andric uint16_t MoveMask = MemOp.RegMask; 401349cc55cSDimitry Andric if (MemOp.Op == M68kMemOp::Kind::Reg) 402349cc55cSDimitry Andric MoveMask = 1 << getRegisterIndex(MemOp.OuterReg); 403349cc55cSDimitry Andric 404349cc55cSDimitry Andric Inst.addOperand(MCOperand::createImm(MoveMask)); 405349cc55cSDimitry Andric } 406349cc55cSDimitry Andric 407fe6060f1SDimitry Andric // Addr 408fe6060f1SDimitry Andric bool M68kOperand::isAddr() const { 409fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr; 410fe6060f1SDimitry Andric } 411349cc55cSDimitry Andric // TODO: Maybe we can also store the size of OuterDisp 412349cc55cSDimitry Andric // in Size? 413349cc55cSDimitry Andric template <unsigned N> bool M68kOperand::isAddrN() const { 414349cc55cSDimitry Andric if (isAddr()) { 415349cc55cSDimitry Andric int64_t Res; 416349cc55cSDimitry Andric if (MemOp.OuterDisp->evaluateAsAbsolute(Res)) 417349cc55cSDimitry Andric return isInt<N>(Res); 418349cc55cSDimitry Andric return true; 419349cc55cSDimitry Andric } 420349cc55cSDimitry Andric return false; 421349cc55cSDimitry Andric } 422fe6060f1SDimitry Andric void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const { 423fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 424fe6060f1SDimitry Andric } 425fe6060f1SDimitry Andric 426fe6060f1SDimitry Andric // ARI 427fe6060f1SDimitry Andric bool M68kOperand::isARI() const { 428fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect && 429fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 430fe6060f1SDimitry Andric } 431fe6060f1SDimitry Andric void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const { 432fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 433fe6060f1SDimitry Andric } 434fe6060f1SDimitry Andric 435fe6060f1SDimitry Andric // ARID 436fe6060f1SDimitry Andric bool M68kOperand::isARID() const { 437fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement && 438fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 439fe6060f1SDimitry Andric } 440fe6060f1SDimitry Andric void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const { 441fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 442fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 443fe6060f1SDimitry Andric } 444fe6060f1SDimitry Andric 445fe6060f1SDimitry Andric // ARII 446fe6060f1SDimitry Andric bool M68kOperand::isARII() const { 447fe6060f1SDimitry Andric return isMemOp() && 448fe6060f1SDimitry Andric MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex && 449fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 450fe6060f1SDimitry Andric } 451fe6060f1SDimitry Andric void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const { 452fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 453fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 454fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.InnerReg)); 455fe6060f1SDimitry Andric } 456fe6060f1SDimitry Andric 457fe6060f1SDimitry Andric // ARIPD 458fe6060f1SDimitry Andric bool M68kOperand::isARIPD() const { 459fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement && 460fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 461fe6060f1SDimitry Andric } 462fe6060f1SDimitry Andric void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const { 463fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 464fe6060f1SDimitry Andric } 465fe6060f1SDimitry Andric 466fe6060f1SDimitry Andric // ARIPI 467fe6060f1SDimitry Andric bool M68kOperand::isARIPI() const { 468fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement && 469fe6060f1SDimitry Andric M68k::AR32RegClass.contains(MemOp.OuterReg); 470fe6060f1SDimitry Andric } 471fe6060f1SDimitry Andric void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const { 472fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.OuterReg)); 473fe6060f1SDimitry Andric } 474fe6060f1SDimitry Andric 475fe6060f1SDimitry Andric // PCD 476fe6060f1SDimitry Andric bool M68kOperand::isPCD() const { 477fe6060f1SDimitry Andric return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement && 478fe6060f1SDimitry Andric MemOp.OuterReg == M68k::PC; 479fe6060f1SDimitry Andric } 480fe6060f1SDimitry Andric void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const { 481fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 482fe6060f1SDimitry Andric } 483fe6060f1SDimitry Andric 484fe6060f1SDimitry Andric // PCI 485fe6060f1SDimitry Andric bool M68kOperand::isPCI() const { 486fe6060f1SDimitry Andric return isMemOp() && 487fe6060f1SDimitry Andric MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex && 488fe6060f1SDimitry Andric MemOp.OuterReg == M68k::PC; 489fe6060f1SDimitry Andric } 490fe6060f1SDimitry Andric void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const { 491fe6060f1SDimitry Andric M68kOperand::addExpr(Inst, MemOp.OuterDisp); 492fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(MemOp.InnerReg)); 493fe6060f1SDimitry Andric } 494fe6060f1SDimitry Andric 495fe6060f1SDimitry Andric static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address, 4965f757f3fSDimitry Andric bool SP, bool FPDR = false, 4975f757f3fSDimitry Andric bool FPCR = false) { 498fe6060f1SDimitry Andric switch (RegNo) { 499fe6060f1SDimitry Andric case M68k::A0: 500fe6060f1SDimitry Andric case M68k::A1: 501fe6060f1SDimitry Andric case M68k::A2: 502fe6060f1SDimitry Andric case M68k::A3: 503fe6060f1SDimitry Andric case M68k::A4: 504fe6060f1SDimitry Andric case M68k::A5: 505fe6060f1SDimitry Andric case M68k::A6: 506fe6060f1SDimitry Andric return Address; 507fe6060f1SDimitry Andric 508fe6060f1SDimitry Andric case M68k::SP: 509fe6060f1SDimitry Andric return SP; 510fe6060f1SDimitry Andric 511fe6060f1SDimitry Andric case M68k::D0: 512fe6060f1SDimitry Andric case M68k::D1: 513fe6060f1SDimitry Andric case M68k::D2: 514fe6060f1SDimitry Andric case M68k::D3: 515fe6060f1SDimitry Andric case M68k::D4: 516fe6060f1SDimitry Andric case M68k::D5: 517fe6060f1SDimitry Andric case M68k::D6: 518fe6060f1SDimitry Andric case M68k::D7: 519fe6060f1SDimitry Andric return Data; 520fe6060f1SDimitry Andric 521fe6060f1SDimitry Andric case M68k::SR: 522fe6060f1SDimitry Andric case M68k::CCR: 523fe6060f1SDimitry Andric return false; 524fe6060f1SDimitry Andric 52506c3fb27SDimitry Andric case M68k::FP0: 52606c3fb27SDimitry Andric case M68k::FP1: 52706c3fb27SDimitry Andric case M68k::FP2: 52806c3fb27SDimitry Andric case M68k::FP3: 52906c3fb27SDimitry Andric case M68k::FP4: 53006c3fb27SDimitry Andric case M68k::FP5: 53106c3fb27SDimitry Andric case M68k::FP6: 53206c3fb27SDimitry Andric case M68k::FP7: 53306c3fb27SDimitry Andric return FPDR; 53406c3fb27SDimitry Andric 5355f757f3fSDimitry Andric case M68k::FPC: 5365f757f3fSDimitry Andric case M68k::FPS: 5375f757f3fSDimitry Andric case M68k::FPIAR: 5385f757f3fSDimitry Andric return FPCR; 5395f757f3fSDimitry Andric 540fe6060f1SDimitry Andric default: 541fe6060f1SDimitry Andric llvm_unreachable("unexpected register type"); 542fe6060f1SDimitry Andric return false; 543fe6060f1SDimitry Andric } 544fe6060f1SDimitry Andric } 545fe6060f1SDimitry Andric 546349cc55cSDimitry Andric bool M68kOperand::isAReg() const { 547349cc55cSDimitry Andric return isReg() && checkRegisterClass(getReg(), 548349cc55cSDimitry Andric /*Data=*/false, 549349cc55cSDimitry Andric /*Address=*/true, /*SP=*/true); 550349cc55cSDimitry Andric } 551349cc55cSDimitry Andric 552349cc55cSDimitry Andric bool M68kOperand::isDReg() const { 553349cc55cSDimitry Andric return isReg() && checkRegisterClass(getReg(), 554349cc55cSDimitry Andric /*Data=*/true, 555349cc55cSDimitry Andric /*Address=*/false, /*SP=*/false); 556349cc55cSDimitry Andric } 557349cc55cSDimitry Andric 55806c3fb27SDimitry Andric bool M68kOperand::isFPDReg() const { 55906c3fb27SDimitry Andric return isReg() && checkRegisterClass(getReg(), 56006c3fb27SDimitry Andric /*Data=*/false, 56106c3fb27SDimitry Andric /*Address=*/false, /*SP=*/false, 56206c3fb27SDimitry Andric /*FPDR=*/true); 56306c3fb27SDimitry Andric } 56406c3fb27SDimitry Andric 5655f757f3fSDimitry Andric bool M68kOperand::isFPCReg() const { 5665f757f3fSDimitry Andric return isReg() && checkRegisterClass(getReg(), 5675f757f3fSDimitry Andric /*Data=*/false, 5685f757f3fSDimitry Andric /*Address=*/false, /*SP=*/false, 5695f757f3fSDimitry Andric /*FPDR=*/false, /*FPCR=*/true); 5705f757f3fSDimitry Andric } 5715f757f3fSDimitry Andric 572fe6060f1SDimitry Andric unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op, 573fe6060f1SDimitry Andric unsigned Kind) { 574fe6060f1SDimitry Andric M68kOperand &Operand = (M68kOperand &)Op; 575fe6060f1SDimitry Andric 576fe6060f1SDimitry Andric switch (Kind) { 577fe6060f1SDimitry Andric case MCK_XR16: 578fe6060f1SDimitry Andric case MCK_SPILL: 579fe6060f1SDimitry Andric if (Operand.isReg() && 580fe6060f1SDimitry Andric checkRegisterClass(Operand.getReg(), true, true, true)) { 581fe6060f1SDimitry Andric return Match_Success; 582fe6060f1SDimitry Andric } 583fe6060f1SDimitry Andric break; 584fe6060f1SDimitry Andric 585fe6060f1SDimitry Andric case MCK_AR16: 586fe6060f1SDimitry Andric case MCK_AR32: 587fe6060f1SDimitry Andric if (Operand.isReg() && 588fe6060f1SDimitry Andric checkRegisterClass(Operand.getReg(), false, true, true)) { 589fe6060f1SDimitry Andric return Match_Success; 590fe6060f1SDimitry Andric } 591fe6060f1SDimitry Andric break; 592fe6060f1SDimitry Andric 593fe6060f1SDimitry Andric case MCK_AR32_NOSP: 594fe6060f1SDimitry Andric if (Operand.isReg() && 595fe6060f1SDimitry Andric checkRegisterClass(Operand.getReg(), false, true, false)) { 596fe6060f1SDimitry Andric return Match_Success; 597fe6060f1SDimitry Andric } 598fe6060f1SDimitry Andric break; 599fe6060f1SDimitry Andric 600fe6060f1SDimitry Andric case MCK_DR8: 601fe6060f1SDimitry Andric case MCK_DR16: 602fe6060f1SDimitry Andric case MCK_DR32: 603fe6060f1SDimitry Andric if (Operand.isReg() && 604fe6060f1SDimitry Andric checkRegisterClass(Operand.getReg(), true, false, false)) { 605fe6060f1SDimitry Andric return Match_Success; 606fe6060f1SDimitry Andric } 607fe6060f1SDimitry Andric break; 608fe6060f1SDimitry Andric 609fe6060f1SDimitry Andric case MCK_AR16_TC: 610fe6060f1SDimitry Andric if (Operand.isReg() && 611fe6060f1SDimitry Andric ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) { 612fe6060f1SDimitry Andric return Match_Success; 613fe6060f1SDimitry Andric } 614fe6060f1SDimitry Andric break; 615fe6060f1SDimitry Andric 616fe6060f1SDimitry Andric case MCK_DR16_TC: 617fe6060f1SDimitry Andric if (Operand.isReg() && 618fe6060f1SDimitry Andric ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) { 619fe6060f1SDimitry Andric return Match_Success; 620fe6060f1SDimitry Andric } 621fe6060f1SDimitry Andric break; 622fe6060f1SDimitry Andric 623fe6060f1SDimitry Andric case MCK_XR16_TC: 624fe6060f1SDimitry Andric if (Operand.isReg() && 625fe6060f1SDimitry Andric ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) || 626fe6060f1SDimitry Andric (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) { 627fe6060f1SDimitry Andric return Match_Success; 628fe6060f1SDimitry Andric } 629fe6060f1SDimitry Andric break; 630fe6060f1SDimitry Andric } 631fe6060f1SDimitry Andric 632fe6060f1SDimitry Andric return Match_InvalidOperand; 633fe6060f1SDimitry Andric } 634fe6060f1SDimitry Andric 635bdd1243dSDimitry Andric bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc, 636fe6060f1SDimitry Andric StringRef RegisterName) { 637fe6060f1SDimitry Andric auto RegisterNameLower = RegisterName.lower(); 638fe6060f1SDimitry Andric 639fe6060f1SDimitry Andric // CCR register 640fe6060f1SDimitry Andric if (RegisterNameLower == "ccr") { 641fe6060f1SDimitry Andric RegNo = M68k::CCR; 642fe6060f1SDimitry Andric return true; 643fe6060f1SDimitry Andric } 644fe6060f1SDimitry Andric 645fe6060f1SDimitry Andric // Parse simple general-purpose registers. 646fe6060f1SDimitry Andric if (RegisterNameLower.size() == 2) { 647fe6060f1SDimitry Andric 648fe6060f1SDimitry Andric switch (RegisterNameLower[0]) { 649fe6060f1SDimitry Andric case 'd': 650fe6060f1SDimitry Andric case 'a': { 651fe6060f1SDimitry Andric if (isdigit(RegisterNameLower[1])) { 652fe6060f1SDimitry Andric unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0; 653fe6060f1SDimitry Andric unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0'); 654fe6060f1SDimitry Andric if (RegIndex < 8) { 655349cc55cSDimitry Andric RegNo = getRegisterByIndex(IndexOffset + RegIndex); 656fe6060f1SDimitry Andric return true; 657fe6060f1SDimitry Andric } 658fe6060f1SDimitry Andric } 659fe6060f1SDimitry Andric break; 660fe6060f1SDimitry Andric } 661fe6060f1SDimitry Andric 662fe6060f1SDimitry Andric case 's': 663fe6060f1SDimitry Andric if (RegisterNameLower[1] == 'p') { 664fe6060f1SDimitry Andric RegNo = M68k::SP; 665fe6060f1SDimitry Andric return true; 666fe6060f1SDimitry Andric } else if (RegisterNameLower[1] == 'r') { 667fe6060f1SDimitry Andric RegNo = M68k::SR; 668fe6060f1SDimitry Andric return true; 669fe6060f1SDimitry Andric } 670fe6060f1SDimitry Andric break; 671fe6060f1SDimitry Andric 672fe6060f1SDimitry Andric case 'p': 673fe6060f1SDimitry Andric if (RegisterNameLower[1] == 'c') { 674fe6060f1SDimitry Andric RegNo = M68k::PC; 675fe6060f1SDimitry Andric return true; 676fe6060f1SDimitry Andric } 677fe6060f1SDimitry Andric break; 678fe6060f1SDimitry Andric } 67906c3fb27SDimitry Andric } else if (StringRef(RegisterNameLower).starts_with("fp") && 68006c3fb27SDimitry Andric RegisterNameLower.size() > 2) { 68106c3fb27SDimitry Andric auto RegIndex = unsigned(RegisterNameLower[2] - '0'); 6825f757f3fSDimitry Andric if (RegIndex < 8 && RegisterNameLower.size() == 3) { 6835f757f3fSDimitry Andric // Floating point data register. 68406c3fb27SDimitry Andric RegNo = getRegisterByIndex(16 + RegIndex); 68506c3fb27SDimitry Andric return true; 6865f757f3fSDimitry Andric } else { 6875f757f3fSDimitry Andric // Floating point control register. 6885f757f3fSDimitry Andric RegNo = StringSwitch<unsigned>(RegisterNameLower) 6895f757f3fSDimitry Andric .Cases("fpc", "fpcr", M68k::FPC) 6905f757f3fSDimitry Andric .Cases("fps", "fpsr", M68k::FPS) 6915f757f3fSDimitry Andric .Cases("fpi", "fpiar", M68k::FPIAR) 6925f757f3fSDimitry Andric .Default(M68k::NoRegister); 6935f757f3fSDimitry Andric assert(RegNo != M68k::NoRegister && 6945f757f3fSDimitry Andric "Unrecognized FP control register name"); 6955f757f3fSDimitry Andric return true; 6965f757f3fSDimitry Andric } 697fe6060f1SDimitry Andric } 698fe6060f1SDimitry Andric 699fe6060f1SDimitry Andric return false; 700fe6060f1SDimitry Andric } 701fe6060f1SDimitry Andric 70206c3fb27SDimitry Andric ParseStatus M68kAsmParser::parseRegister(MCRegister &RegNo) { 703fe6060f1SDimitry Andric bool HasPercent = false; 704fe6060f1SDimitry Andric AsmToken PercentToken; 705fe6060f1SDimitry Andric 706fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n"); 707fe6060f1SDimitry Andric 708fe6060f1SDimitry Andric if (getTok().is(AsmToken::Percent)) { 709fe6060f1SDimitry Andric HasPercent = true; 710fe6060f1SDimitry Andric PercentToken = Lex(); 711fe6060f1SDimitry Andric } else if (!RegisterPrefixOptional.getValue()) { 71206c3fb27SDimitry Andric return ParseStatus::NoMatch; 713fe6060f1SDimitry Andric } 714fe6060f1SDimitry Andric 715fe6060f1SDimitry Andric if (!Parser.getTok().is(AsmToken::Identifier)) { 716fe6060f1SDimitry Andric if (HasPercent) { 717fe6060f1SDimitry Andric getLexer().UnLex(PercentToken); 718fe6060f1SDimitry Andric } 71906c3fb27SDimitry Andric return ParseStatus::NoMatch; 720fe6060f1SDimitry Andric } 721fe6060f1SDimitry Andric 722fe6060f1SDimitry Andric auto RegisterName = Parser.getTok().getString(); 723fe6060f1SDimitry Andric if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) { 724fe6060f1SDimitry Andric if (HasPercent) { 725fe6060f1SDimitry Andric getLexer().UnLex(PercentToken); 726fe6060f1SDimitry Andric } 72706c3fb27SDimitry Andric return ParseStatus::NoMatch; 728fe6060f1SDimitry Andric } 729fe6060f1SDimitry Andric 730fe6060f1SDimitry Andric Parser.Lex(); 73106c3fb27SDimitry Andric return ParseStatus::Success; 732fe6060f1SDimitry Andric } 733fe6060f1SDimitry Andric 7345f757f3fSDimitry Andric bool M68kAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, 735fe6060f1SDimitry Andric SMLoc &EndLoc) { 7365f757f3fSDimitry Andric ParseStatus Result = tryParseRegister(Reg, StartLoc, EndLoc); 7375f757f3fSDimitry Andric if (!Result.isSuccess()) 738fe6060f1SDimitry Andric return Error(StartLoc, "expected register"); 739fe6060f1SDimitry Andric 740fe6060f1SDimitry Andric return false; 741fe6060f1SDimitry Andric } 742fe6060f1SDimitry Andric 7435f757f3fSDimitry Andric ParseStatus M68kAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 744fe6060f1SDimitry Andric SMLoc &EndLoc) { 745fe6060f1SDimitry Andric StartLoc = getLexer().getLoc(); 7465f757f3fSDimitry Andric ParseStatus Result = parseRegister(Reg); 747fe6060f1SDimitry Andric EndLoc = getLexer().getLoc(); 748fe6060f1SDimitry Andric return Result; 749fe6060f1SDimitry Andric } 750fe6060f1SDimitry Andric 751fe6060f1SDimitry Andric bool M68kAsmParser::isExpr() { 752fe6060f1SDimitry Andric switch (Parser.getTok().getKind()) { 753fe6060f1SDimitry Andric case AsmToken::Identifier: 754fe6060f1SDimitry Andric case AsmToken::Integer: 755fe6060f1SDimitry Andric return true; 756fe6060f1SDimitry Andric case AsmToken::Minus: 757fe6060f1SDimitry Andric return getLexer().peekTok().getKind() == AsmToken::Integer; 758fe6060f1SDimitry Andric 759fe6060f1SDimitry Andric default: 760fe6060f1SDimitry Andric return false; 761fe6060f1SDimitry Andric } 762fe6060f1SDimitry Andric } 763fe6060f1SDimitry Andric 76406c3fb27SDimitry Andric ParseStatus M68kAsmParser::parseImm(OperandVector &Operands) { 76506c3fb27SDimitry Andric if (getLexer().isNot(AsmToken::Hash)) 76606c3fb27SDimitry Andric return ParseStatus::NoMatch; 767fe6060f1SDimitry Andric SMLoc Start = getLexer().getLoc(); 768fe6060f1SDimitry Andric Parser.Lex(); 769fe6060f1SDimitry Andric 770fe6060f1SDimitry Andric SMLoc End; 771fe6060f1SDimitry Andric const MCExpr *Expr; 772fe6060f1SDimitry Andric 77306c3fb27SDimitry Andric if (getParser().parseExpression(Expr, End)) 77406c3fb27SDimitry Andric return ParseStatus::Failure; 775fe6060f1SDimitry Andric 776fe6060f1SDimitry Andric Operands.push_back(M68kOperand::createImm(Expr, Start, End)); 77706c3fb27SDimitry Andric return ParseStatus::Success; 778fe6060f1SDimitry Andric } 779fe6060f1SDimitry Andric 78006c3fb27SDimitry Andric ParseStatus M68kAsmParser::parseMemOp(OperandVector &Operands) { 781fe6060f1SDimitry Andric SMLoc Start = getLexer().getLoc(); 782fe6060f1SDimitry Andric bool IsPD = false; 783fe6060f1SDimitry Andric M68kMemOp MemOp; 784fe6060f1SDimitry Andric 785349cc55cSDimitry Andric // Check for a plain register or register mask. 78606c3fb27SDimitry Andric ParseStatus Result = parseRegOrMoveMask(Operands); 78706c3fb27SDimitry Andric if (!Result.isNoMatch()) 788fe6060f1SDimitry Andric return Result; 789fe6060f1SDimitry Andric 790fe6060f1SDimitry Andric // Check for pre-decrement & outer displacement. 791fe6060f1SDimitry Andric bool HasDisplacement = false; 792fe6060f1SDimitry Andric if (getLexer().is(AsmToken::Minus)) { 793fe6060f1SDimitry Andric IsPD = true; 794fe6060f1SDimitry Andric Parser.Lex(); 795fe6060f1SDimitry Andric } else if (isExpr()) { 79606c3fb27SDimitry Andric if (Parser.parseExpression(MemOp.OuterDisp)) 79706c3fb27SDimitry Andric return ParseStatus::Failure; 798fe6060f1SDimitry Andric HasDisplacement = true; 799fe6060f1SDimitry Andric } 800fe6060f1SDimitry Andric 801fe6060f1SDimitry Andric if (getLexer().isNot(AsmToken::LParen)) { 802fe6060f1SDimitry Andric if (HasDisplacement) { 803fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::Addr; 804fe6060f1SDimitry Andric Operands.push_back( 805fe6060f1SDimitry Andric M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc())); 80606c3fb27SDimitry Andric return ParseStatus::Success; 807fe6060f1SDimitry Andric } 80806c3fb27SDimitry Andric if (IsPD) 80906c3fb27SDimitry Andric return Error(getLexer().getLoc(), "expected ("); 810fe6060f1SDimitry Andric 81106c3fb27SDimitry Andric return ParseStatus::NoMatch; 812fe6060f1SDimitry Andric } 813fe6060f1SDimitry Andric Parser.Lex(); 814fe6060f1SDimitry Andric 815fe6060f1SDimitry Andric // Check for constant dereference & MIT-style displacement 816fe6060f1SDimitry Andric if (!HasDisplacement && isExpr()) { 81706c3fb27SDimitry Andric if (Parser.parseExpression(MemOp.OuterDisp)) 81806c3fb27SDimitry Andric return ParseStatus::Failure; 819fe6060f1SDimitry Andric HasDisplacement = true; 820fe6060f1SDimitry Andric 821fe6060f1SDimitry Andric // If we're not followed by a comma, we're a constant dereference. 822fe6060f1SDimitry Andric if (getLexer().isNot(AsmToken::Comma)) { 823fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::Addr; 824fe6060f1SDimitry Andric Operands.push_back( 825fe6060f1SDimitry Andric M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc())); 82606c3fb27SDimitry Andric return ParseStatus::Success; 827fe6060f1SDimitry Andric } 828fe6060f1SDimitry Andric 829fe6060f1SDimitry Andric Parser.Lex(); 830fe6060f1SDimitry Andric } 831fe6060f1SDimitry Andric 832fe6060f1SDimitry Andric Result = parseRegister(MemOp.OuterReg); 83306c3fb27SDimitry Andric if (Result.isFailure()) 83406c3fb27SDimitry Andric return ParseStatus::Failure; 835fe6060f1SDimitry Andric 83606c3fb27SDimitry Andric if (!Result.isSuccess()) 83706c3fb27SDimitry Andric return Error(getLexer().getLoc(), "expected register"); 838fe6060f1SDimitry Andric 839fe6060f1SDimitry Andric // Check for Index. 840fe6060f1SDimitry Andric bool HasIndex = false; 841fe6060f1SDimitry Andric if (Parser.getTok().is(AsmToken::Comma)) { 842fe6060f1SDimitry Andric Parser.Lex(); 843fe6060f1SDimitry Andric 844fe6060f1SDimitry Andric Result = parseRegister(MemOp.InnerReg); 84506c3fb27SDimitry Andric if (Result.isFailure()) 846fe6060f1SDimitry Andric return Result; 847fe6060f1SDimitry Andric 84806c3fb27SDimitry Andric if (Result.isNoMatch()) 84906c3fb27SDimitry Andric return Error(getLexer().getLoc(), "expected register"); 850fe6060f1SDimitry Andric 851fe6060f1SDimitry Andric // TODO: parse size, scale and inner displacement. 852fe6060f1SDimitry Andric MemOp.Size = 4; 853fe6060f1SDimitry Andric MemOp.Scale = 1; 854fe6060f1SDimitry Andric MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4); 855fe6060f1SDimitry Andric HasIndex = true; 856fe6060f1SDimitry Andric } 857fe6060f1SDimitry Andric 85806c3fb27SDimitry Andric if (Parser.getTok().isNot(AsmToken::RParen)) 85906c3fb27SDimitry Andric return Error(getLexer().getLoc(), "expected )"); 860fe6060f1SDimitry Andric Parser.Lex(); 861fe6060f1SDimitry Andric 862fe6060f1SDimitry Andric bool IsPI = false; 863fe6060f1SDimitry Andric if (!IsPD && Parser.getTok().is(AsmToken::Plus)) { 864fe6060f1SDimitry Andric Parser.Lex(); 865fe6060f1SDimitry Andric IsPI = true; 866fe6060f1SDimitry Andric } 867fe6060f1SDimitry Andric 868fe6060f1SDimitry Andric SMLoc End = getLexer().getLoc(); 869fe6060f1SDimitry Andric 870fe6060f1SDimitry Andric unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement); 87106c3fb27SDimitry Andric if (OpCount > 1) 87206c3fb27SDimitry Andric return Error(Start, "only one of post-increment, pre-decrement or " 87306c3fb27SDimitry Andric "displacement can be used"); 874fe6060f1SDimitry Andric 875fe6060f1SDimitry Andric if (IsPD) { 876fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegPreDecrement; 877fe6060f1SDimitry Andric } else if (IsPI) { 878fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegPostIncrement; 879fe6060f1SDimitry Andric } else if (HasIndex) { 880fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex; 881fe6060f1SDimitry Andric } else if (HasDisplacement) { 882fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement; 883fe6060f1SDimitry Andric } else { 884fe6060f1SDimitry Andric MemOp.Op = M68kMemOp::Kind::RegIndirect; 885fe6060f1SDimitry Andric } 886fe6060f1SDimitry Andric 887fe6060f1SDimitry Andric Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End)); 88806c3fb27SDimitry Andric return ParseStatus::Success; 889fe6060f1SDimitry Andric } 890fe6060f1SDimitry Andric 89106c3fb27SDimitry Andric ParseStatus M68kAsmParser::parseRegOrMoveMask(OperandVector &Operands) { 892349cc55cSDimitry Andric SMLoc Start = getLexer().getLoc(); 893349cc55cSDimitry Andric M68kMemOp MemOp(M68kMemOp::Kind::RegMask); 894349cc55cSDimitry Andric MemOp.RegMask = 0; 895349cc55cSDimitry Andric 896349cc55cSDimitry Andric for (;;) { 897349cc55cSDimitry Andric bool IsFirstRegister = 898349cc55cSDimitry Andric (MemOp.Op == M68kMemOp::Kind::RegMask) && (MemOp.RegMask == 0); 899349cc55cSDimitry Andric 900bdd1243dSDimitry Andric MCRegister FirstRegister; 90106c3fb27SDimitry Andric ParseStatus Result = parseRegister(FirstRegister); 90206c3fb27SDimitry Andric if (IsFirstRegister && Result.isNoMatch()) 90306c3fb27SDimitry Andric return ParseStatus::NoMatch; 90406c3fb27SDimitry Andric if (!Result.isSuccess()) 90506c3fb27SDimitry Andric return Error(getLexer().getLoc(), "expected start register"); 906349cc55cSDimitry Andric 907bdd1243dSDimitry Andric MCRegister LastRegister = FirstRegister; 90806c3fb27SDimitry Andric if (parseOptionalToken(AsmToken::Minus)) { 909349cc55cSDimitry Andric Result = parseRegister(LastRegister); 91006c3fb27SDimitry Andric if (!Result.isSuccess()) 91106c3fb27SDimitry Andric return Error(getLexer().getLoc(), "expected end register"); 912349cc55cSDimitry Andric } 913349cc55cSDimitry Andric 914349cc55cSDimitry Andric unsigned FirstRegisterIndex = getRegisterIndex(FirstRegister); 915349cc55cSDimitry Andric unsigned LastRegisterIndex = getRegisterIndex(LastRegister); 916349cc55cSDimitry Andric 917349cc55cSDimitry Andric uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1; 918349cc55cSDimitry Andric uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex; 919349cc55cSDimitry Andric 920349cc55cSDimitry Andric if (IsFirstRegister && (FirstRegister == LastRegister)) { 921349cc55cSDimitry Andric // First register range is a single register, simplify to just Reg 922349cc55cSDimitry Andric // so that it matches more operands. 923349cc55cSDimitry Andric MemOp.Op = M68kMemOp::Kind::Reg; 924349cc55cSDimitry Andric MemOp.OuterReg = FirstRegister; 925349cc55cSDimitry Andric } else { 926349cc55cSDimitry Andric if (MemOp.Op == M68kMemOp::Kind::Reg) { 927349cc55cSDimitry Andric // This is the second register being specified - expand the Reg operand 928349cc55cSDimitry Andric // into a mask first. 929349cc55cSDimitry Andric MemOp.Op = M68kMemOp::Kind::RegMask; 930349cc55cSDimitry Andric MemOp.RegMask = 1 << getRegisterIndex(MemOp.OuterReg); 931349cc55cSDimitry Andric 93206c3fb27SDimitry Andric if (MemOp.RegMask == 0) 93306c3fb27SDimitry Andric return Error(getLexer().getLoc(), 934349cc55cSDimitry Andric "special registers cannot be used in register masks"); 935349cc55cSDimitry Andric } 936349cc55cSDimitry Andric 93706c3fb27SDimitry Andric if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16)) 93806c3fb27SDimitry Andric return Error(getLexer().getLoc(), 939349cc55cSDimitry Andric "special registers cannot be used in register masks"); 940349cc55cSDimitry Andric 94106c3fb27SDimitry Andric if (NewMaskBits & MemOp.RegMask) 94206c3fb27SDimitry Andric return Error(getLexer().getLoc(), "conflicting masked registers"); 943349cc55cSDimitry Andric 944349cc55cSDimitry Andric MemOp.RegMask |= NewMaskBits; 945349cc55cSDimitry Andric } 946349cc55cSDimitry Andric 94706c3fb27SDimitry Andric if (!parseOptionalToken(AsmToken::Slash)) 948349cc55cSDimitry Andric break; 949349cc55cSDimitry Andric } 950349cc55cSDimitry Andric 951349cc55cSDimitry Andric Operands.push_back( 952349cc55cSDimitry Andric M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc())); 95306c3fb27SDimitry Andric return ParseStatus::Success; 954349cc55cSDimitry Andric } 955349cc55cSDimitry Andric 956fe6060f1SDimitry Andric void M68kAsmParser::eatComma() { 957fe6060f1SDimitry Andric if (Parser.getTok().is(AsmToken::Comma)) { 958fe6060f1SDimitry Andric Parser.Lex(); 959fe6060f1SDimitry Andric } 960fe6060f1SDimitry Andric } 961fe6060f1SDimitry Andric 962fe6060f1SDimitry Andric bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 963fe6060f1SDimitry Andric SMLoc NameLoc, OperandVector &Operands) { 964fe6060f1SDimitry Andric SMLoc Start = getLexer().getLoc(); 965fe6060f1SDimitry Andric Operands.push_back(M68kOperand::createToken(Name, Start, Start)); 966fe6060f1SDimitry Andric 967fe6060f1SDimitry Andric bool First = true; 968fe6060f1SDimitry Andric while (Parser.getTok().isNot(AsmToken::EndOfStatement)) { 969fe6060f1SDimitry Andric if (!First) { 970fe6060f1SDimitry Andric eatComma(); 971fe6060f1SDimitry Andric } else { 972fe6060f1SDimitry Andric First = false; 973fe6060f1SDimitry Andric } 974fe6060f1SDimitry Andric 97506c3fb27SDimitry Andric ParseStatus MatchResult = MatchOperandParserImpl(Operands, Name); 97606c3fb27SDimitry Andric if (MatchResult.isSuccess()) 977fe6060f1SDimitry Andric continue; 978fe6060f1SDimitry Andric 979fe6060f1SDimitry Andric // Add custom operand formats here... 980fe6060f1SDimitry Andric SMLoc Loc = getLexer().getLoc(); 981fe6060f1SDimitry Andric Parser.eatToEndOfStatement(); 982fe6060f1SDimitry Andric return Error(Loc, "unexpected token parsing operands"); 983fe6060f1SDimitry Andric } 984fe6060f1SDimitry Andric 985fe6060f1SDimitry Andric // Eat EndOfStatement. 986fe6060f1SDimitry Andric Parser.Lex(); 987fe6060f1SDimitry Andric return false; 988fe6060f1SDimitry Andric } 989fe6060f1SDimitry Andric 990fe6060f1SDimitry Andric bool M68kAsmParser::invalidOperand(SMLoc const &Loc, 991fe6060f1SDimitry Andric OperandVector const &Operands, 992fe6060f1SDimitry Andric uint64_t const &ErrorInfo) { 993fe6060f1SDimitry Andric SMLoc ErrorLoc = Loc; 994fe6060f1SDimitry Andric char const *Diag = 0; 995fe6060f1SDimitry Andric 996fe6060f1SDimitry Andric if (ErrorInfo != ~0U) { 997fe6060f1SDimitry Andric if (ErrorInfo >= Operands.size()) { 998fe6060f1SDimitry Andric Diag = "too few operands for instruction."; 999fe6060f1SDimitry Andric } else { 1000fe6060f1SDimitry Andric auto const &Op = (M68kOperand const &)*Operands[ErrorInfo]; 1001fe6060f1SDimitry Andric if (Op.getStartLoc() != SMLoc()) { 1002fe6060f1SDimitry Andric ErrorLoc = Op.getStartLoc(); 1003fe6060f1SDimitry Andric } 1004fe6060f1SDimitry Andric } 1005fe6060f1SDimitry Andric } 1006fe6060f1SDimitry Andric 1007fe6060f1SDimitry Andric if (!Diag) { 1008fe6060f1SDimitry Andric Diag = "invalid operand for instruction"; 1009fe6060f1SDimitry Andric } 1010fe6060f1SDimitry Andric 1011fe6060f1SDimitry Andric return Error(ErrorLoc, Diag); 1012fe6060f1SDimitry Andric } 1013fe6060f1SDimitry Andric 1014fe6060f1SDimitry Andric bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc, 1015fe6060f1SDimitry Andric uint64_t const &ErrorInfo) { 1016fe6060f1SDimitry Andric return Error(Loc, "instruction requires a CPU feature not currently enabled"); 1017fe6060f1SDimitry Andric } 1018fe6060f1SDimitry Andric 1019fe6060f1SDimitry Andric bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc, 1020fe6060f1SDimitry Andric MCStreamer &Out) const { 1021fe6060f1SDimitry Andric Inst.setLoc(Loc); 1022fe6060f1SDimitry Andric Out.emitInstruction(Inst, STI); 1023fe6060f1SDimitry Andric 1024fe6060f1SDimitry Andric return false; 1025fe6060f1SDimitry Andric } 1026fe6060f1SDimitry Andric 1027fe6060f1SDimitry Andric bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode, 1028fe6060f1SDimitry Andric OperandVector &Operands, 1029fe6060f1SDimitry Andric MCStreamer &Out, 1030fe6060f1SDimitry Andric uint64_t &ErrorInfo, 1031fe6060f1SDimitry Andric bool MatchingInlineAsm) { 1032fe6060f1SDimitry Andric MCInst Inst; 1033fe6060f1SDimitry Andric unsigned MatchResult = 1034fe6060f1SDimitry Andric MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); 1035fe6060f1SDimitry Andric 1036fe6060f1SDimitry Andric switch (MatchResult) { 1037fe6060f1SDimitry Andric case Match_Success: 1038fe6060f1SDimitry Andric return emit(Inst, Loc, Out); 1039fe6060f1SDimitry Andric case Match_MissingFeature: 1040fe6060f1SDimitry Andric return missingFeature(Loc, ErrorInfo); 1041fe6060f1SDimitry Andric case Match_InvalidOperand: 1042fe6060f1SDimitry Andric return invalidOperand(Loc, Operands, ErrorInfo); 1043fe6060f1SDimitry Andric case Match_MnemonicFail: 1044fe6060f1SDimitry Andric return Error(Loc, "invalid instruction"); 1045fe6060f1SDimitry Andric default: 1046fe6060f1SDimitry Andric return true; 1047fe6060f1SDimitry Andric } 1048fe6060f1SDimitry Andric } 1049fe6060f1SDimitry Andric 1050fe6060f1SDimitry Andric void M68kOperand::print(raw_ostream &OS) const { 1051fe6060f1SDimitry Andric switch (Kind) { 105269ade1e0SDimitry Andric case KindTy::Invalid: 1053fe6060f1SDimitry Andric OS << "invalid"; 1054fe6060f1SDimitry Andric break; 1055fe6060f1SDimitry Andric 105669ade1e0SDimitry Andric case KindTy::Token: 1057fe6060f1SDimitry Andric OS << "token '" << Token << "'"; 1058fe6060f1SDimitry Andric break; 1059fe6060f1SDimitry Andric 106006c3fb27SDimitry Andric case KindTy::Imm: { 106106c3fb27SDimitry Andric int64_t Value; 106206c3fb27SDimitry Andric Expr->evaluateAsAbsolute(Value); 106306c3fb27SDimitry Andric OS << "immediate " << Value; 1064fe6060f1SDimitry Andric break; 106506c3fb27SDimitry Andric } 1066fe6060f1SDimitry Andric 106769ade1e0SDimitry Andric case KindTy::MemOp: 1068fe6060f1SDimitry Andric MemOp.print(OS); 1069fe6060f1SDimitry Andric break; 1070fe6060f1SDimitry Andric } 1071fe6060f1SDimitry Andric } 1072