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