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