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