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(); 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 KindTy { 121 Invalid, 122 Token, 123 Imm, 124 MemOp, 125 }; 126 127 KindTy 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(KindTy 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 == KindTy::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 == KindTy::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>(KindTy::MemOp, Start, End); 269 Op->MemOp = MemOp; 270 return Op; 271 } 272 273 // Token 274 bool M68kOperand::isToken() const { return Kind == KindTy::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>(KindTy::Token, Start, End); 283 Op->Token = Token; 284 return Op; 285 } 286 287 // Imm 288 bool M68kOperand::isImm() const { return Kind == KindTy::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>(KindTy::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 // CCR register 483 if (RegisterNameLower == "ccr") { 484 RegNo = M68k::CCR; 485 return true; 486 } 487 488 // Parse simple general-purpose registers. 489 if (RegisterNameLower.size() == 2) { 490 static unsigned RegistersByIndex[] = { 491 M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5, 492 M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3, 493 M68k::A4, M68k::A5, M68k::A6, M68k::SP, 494 }; 495 496 switch (RegisterNameLower[0]) { 497 case 'd': 498 case 'a': { 499 if (isdigit(RegisterNameLower[1])) { 500 unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0; 501 unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0'); 502 if (RegIndex < 8) { 503 RegNo = RegistersByIndex[IndexOffset + RegIndex]; 504 return true; 505 } 506 } 507 break; 508 } 509 510 case 's': 511 if (RegisterNameLower[1] == 'p') { 512 RegNo = M68k::SP; 513 return true; 514 } else if (RegisterNameLower[1] == 'r') { 515 RegNo = M68k::SR; 516 return true; 517 } 518 break; 519 520 case 'p': 521 if (RegisterNameLower[1] == 'c') { 522 RegNo = M68k::PC; 523 return true; 524 } 525 break; 526 } 527 } 528 529 return false; 530 } 531 532 OperandMatchResultTy M68kAsmParser::parseRegister(unsigned &RegNo) { 533 bool HasPercent = false; 534 AsmToken PercentToken; 535 536 LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n"); 537 538 if (getTok().is(AsmToken::Percent)) { 539 HasPercent = true; 540 PercentToken = Lex(); 541 } else if (!RegisterPrefixOptional.getValue()) { 542 return MatchOperand_NoMatch; 543 } 544 545 if (!Parser.getTok().is(AsmToken::Identifier)) { 546 if (HasPercent) { 547 getLexer().UnLex(PercentToken); 548 } 549 return MatchOperand_NoMatch; 550 } 551 552 auto RegisterName = Parser.getTok().getString(); 553 if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) { 554 if (HasPercent) { 555 getLexer().UnLex(PercentToken); 556 } 557 return MatchOperand_NoMatch; 558 } 559 560 Parser.Lex(); 561 return MatchOperand_Success; 562 } 563 564 bool M68kAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 565 SMLoc &EndLoc) { 566 auto Result = tryParseRegister(RegNo, StartLoc, EndLoc); 567 if (Result != MatchOperand_Success) { 568 return Error(StartLoc, "expected register"); 569 } 570 571 return false; 572 } 573 574 OperandMatchResultTy M68kAsmParser::tryParseRegister(unsigned &RegNo, 575 SMLoc &StartLoc, 576 SMLoc &EndLoc) { 577 StartLoc = getLexer().getLoc(); 578 auto Result = parseRegister(RegNo); 579 EndLoc = getLexer().getLoc(); 580 return Result; 581 } 582 583 bool M68kAsmParser::isExpr() { 584 switch (Parser.getTok().getKind()) { 585 case AsmToken::Identifier: 586 case AsmToken::Integer: 587 return true; 588 case AsmToken::Minus: 589 return getLexer().peekTok().getKind() == AsmToken::Integer; 590 591 default: 592 return false; 593 } 594 } 595 596 OperandMatchResultTy M68kAsmParser::parseImm(OperandVector &Operands) { 597 if (getLexer().isNot(AsmToken::Hash)) { 598 return MatchOperand_NoMatch; 599 } 600 SMLoc Start = getLexer().getLoc(); 601 Parser.Lex(); 602 603 SMLoc End; 604 const MCExpr *Expr; 605 606 if (getParser().parseExpression(Expr, End)) { 607 return MatchOperand_ParseFail; 608 } 609 610 Operands.push_back(M68kOperand::createImm(Expr, Start, End)); 611 return MatchOperand_Success; 612 } 613 614 OperandMatchResultTy M68kAsmParser::parseMemOp(OperandVector &Operands) { 615 SMLoc Start = getLexer().getLoc(); 616 bool IsPD = false; 617 M68kMemOp MemOp; 618 619 // Check for a plain register. 620 auto Result = parseRegister(MemOp.OuterReg); 621 if (Result == MatchOperand_Success) { 622 MemOp.Op = M68kMemOp::Kind::Reg; 623 Operands.push_back( 624 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc())); 625 return MatchOperand_Success; 626 } 627 628 if (Result == MatchOperand_ParseFail) { 629 return Result; 630 } 631 632 // Check for pre-decrement & outer displacement. 633 bool HasDisplacement = false; 634 if (getLexer().is(AsmToken::Minus)) { 635 IsPD = true; 636 Parser.Lex(); 637 } else if (isExpr()) { 638 if (Parser.parseExpression(MemOp.OuterDisp)) { 639 return MatchOperand_ParseFail; 640 } 641 HasDisplacement = true; 642 } 643 644 if (getLexer().isNot(AsmToken::LParen)) { 645 if (HasDisplacement) { 646 MemOp.Op = M68kMemOp::Kind::Addr; 647 Operands.push_back( 648 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc())); 649 return MatchOperand_Success; 650 } else if (IsPD) { 651 Error(getLexer().getLoc(), "expected ("); 652 return MatchOperand_ParseFail; 653 } 654 655 return MatchOperand_NoMatch; 656 } 657 Parser.Lex(); 658 659 // Check for constant dereference & MIT-style displacement 660 if (!HasDisplacement && isExpr()) { 661 if (Parser.parseExpression(MemOp.OuterDisp)) { 662 return MatchOperand_ParseFail; 663 } 664 HasDisplacement = true; 665 666 // If we're not followed by a comma, we're a constant dereference. 667 if (getLexer().isNot(AsmToken::Comma)) { 668 MemOp.Op = M68kMemOp::Kind::Addr; 669 Operands.push_back( 670 M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc())); 671 return MatchOperand_Success; 672 } 673 674 Parser.Lex(); 675 } 676 677 Result = parseRegister(MemOp.OuterReg); 678 if (Result == MatchOperand_ParseFail) { 679 return MatchOperand_ParseFail; 680 } 681 682 if (Result != MatchOperand_Success) { 683 Error(getLexer().getLoc(), "expected register"); 684 return MatchOperand_ParseFail; 685 } 686 687 // Check for Index. 688 bool HasIndex = false; 689 if (Parser.getTok().is(AsmToken::Comma)) { 690 Parser.Lex(); 691 692 Result = parseRegister(MemOp.InnerReg); 693 if (Result == MatchOperand_ParseFail) { 694 return Result; 695 } 696 697 if (Result == MatchOperand_NoMatch) { 698 Error(getLexer().getLoc(), "expected register"); 699 return MatchOperand_ParseFail; 700 } 701 702 // TODO: parse size, scale and inner displacement. 703 MemOp.Size = 4; 704 MemOp.Scale = 1; 705 MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4); 706 HasIndex = true; 707 } 708 709 if (Parser.getTok().isNot(AsmToken::RParen)) { 710 Error(getLexer().getLoc(), "expected )"); 711 return MatchOperand_ParseFail; 712 } 713 Parser.Lex(); 714 715 bool IsPI = false; 716 if (!IsPD && Parser.getTok().is(AsmToken::Plus)) { 717 Parser.Lex(); 718 IsPI = true; 719 } 720 721 SMLoc End = getLexer().getLoc(); 722 723 unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement); 724 if (OpCount > 1) { 725 Error(Start, "only one of post-increment, pre-decrement or displacement " 726 "can be used"); 727 return MatchOperand_ParseFail; 728 } 729 730 if (IsPD) { 731 MemOp.Op = M68kMemOp::Kind::RegPreDecrement; 732 } else if (IsPI) { 733 MemOp.Op = M68kMemOp::Kind::RegPostIncrement; 734 } else if (HasIndex) { 735 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex; 736 } else if (HasDisplacement) { 737 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement; 738 } else { 739 MemOp.Op = M68kMemOp::Kind::RegIndirect; 740 } 741 742 Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End)); 743 return MatchOperand_Success; 744 } 745 746 void M68kAsmParser::eatComma() { 747 if (Parser.getTok().is(AsmToken::Comma)) { 748 Parser.Lex(); 749 } 750 } 751 752 bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 753 SMLoc NameLoc, OperandVector &Operands) { 754 SMLoc Start = getLexer().getLoc(); 755 Operands.push_back(M68kOperand::createToken(Name, Start, Start)); 756 757 bool First = true; 758 while (Parser.getTok().isNot(AsmToken::EndOfStatement)) { 759 if (!First) { 760 eatComma(); 761 } else { 762 First = false; 763 } 764 765 auto MatchResult = MatchOperandParserImpl(Operands, Name); 766 if (MatchResult == MatchOperand_Success) { 767 continue; 768 } 769 770 // Add custom operand formats here... 771 SMLoc Loc = getLexer().getLoc(); 772 Parser.eatToEndOfStatement(); 773 return Error(Loc, "unexpected token parsing operands"); 774 } 775 776 // Eat EndOfStatement. 777 Parser.Lex(); 778 return false; 779 } 780 781 bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; } 782 783 bool M68kAsmParser::invalidOperand(SMLoc const &Loc, 784 OperandVector const &Operands, 785 uint64_t const &ErrorInfo) { 786 SMLoc ErrorLoc = Loc; 787 char const *Diag = 0; 788 789 if (ErrorInfo != ~0U) { 790 if (ErrorInfo >= Operands.size()) { 791 Diag = "too few operands for instruction."; 792 } else { 793 auto const &Op = (M68kOperand const &)*Operands[ErrorInfo]; 794 if (Op.getStartLoc() != SMLoc()) { 795 ErrorLoc = Op.getStartLoc(); 796 } 797 } 798 } 799 800 if (!Diag) { 801 Diag = "invalid operand for instruction"; 802 } 803 804 return Error(ErrorLoc, Diag); 805 } 806 807 bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc, 808 uint64_t const &ErrorInfo) { 809 return Error(Loc, "instruction requires a CPU feature not currently enabled"); 810 } 811 812 bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc, 813 MCStreamer &Out) const { 814 Inst.setLoc(Loc); 815 Out.emitInstruction(Inst, STI); 816 817 return false; 818 } 819 820 bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode, 821 OperandVector &Operands, 822 MCStreamer &Out, 823 uint64_t &ErrorInfo, 824 bool MatchingInlineAsm) { 825 MCInst Inst; 826 unsigned MatchResult = 827 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); 828 829 switch (MatchResult) { 830 case Match_Success: 831 return emit(Inst, Loc, Out); 832 case Match_MissingFeature: 833 return missingFeature(Loc, ErrorInfo); 834 case Match_InvalidOperand: 835 return invalidOperand(Loc, Operands, ErrorInfo); 836 case Match_MnemonicFail: 837 return Error(Loc, "invalid instruction"); 838 default: 839 return true; 840 } 841 } 842 843 void M68kOperand::print(raw_ostream &OS) const { 844 switch (Kind) { 845 case KindTy::Invalid: 846 OS << "invalid"; 847 break; 848 849 case KindTy::Token: 850 OS << "token '" << Token << "'"; 851 break; 852 853 case KindTy::Imm: 854 OS << "immediate " << Imm; 855 break; 856 857 case KindTy::MemOp: 858 MemOp.print(OS); 859 break; 860 } 861 } 862