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