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