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