1 //===- XtensaAsmParser.cpp - Parse Xtensa assembly to MCInst instructions -===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6 // See https://llvm.org/LICENSE.txt for license information. 7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8 // 9 //===----------------------------------------------------------------------===// 10 11 #include "MCTargetDesc/XtensaMCTargetDesc.h" 12 #include "TargetInfo/XtensaTargetInfo.h" 13 #include "llvm/ADT/STLExtras.h" 14 #include "llvm/ADT/StringSwitch.h" 15 #include "llvm/MC/MCContext.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCInst.h" 18 #include "llvm/MC/MCInstrInfo.h" 19 #include "llvm/MC/MCParser/MCAsmLexer.h" 20 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 21 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 22 #include "llvm/MC/MCRegisterInfo.h" 23 #include "llvm/MC/MCStreamer.h" 24 #include "llvm/MC/MCSubtargetInfo.h" 25 #include "llvm/MC/TargetRegistry.h" 26 #include "llvm/Support/Casting.h" 27 28 using namespace llvm; 29 30 #define DEBUG_TYPE "xtensa-asm-parser" 31 32 struct XtensaOperand; 33 34 class XtensaAsmParser : public MCTargetAsmParser { 35 36 SMLoc getLoc() const { return getParser().getTok().getLoc(); } 37 38 // Override MCTargetAsmParser. 39 bool ParseDirective(AsmToken DirectiveID) override; 40 bool parseRegister(MCRegister &RegNo, 41 SMLoc &StartLoc, SMLoc &EndLoc) override; 42 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 43 SMLoc NameLoc, OperandVector &Operands) override; 44 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 45 OperandVector &Operands, MCStreamer &Out, 46 uint64_t &ErrorInfo, 47 bool MatchingInlineAsm) override; 48 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 49 unsigned Kind) override; 50 51 // Auto-generated instruction matching functions 52 #define GET_ASSEMBLER_HEADER 53 #include "XtensaGenAsmMatcher.inc" 54 55 OperandMatchResultTy parseImmediate(OperandVector &Operands); 56 OperandMatchResultTy parseRegister(OperandVector &Operands, 57 bool AllowParens = false, bool SR = false); 58 OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands); 59 bool parseOperand(OperandVector &Operands, StringRef Mnemonic, 60 bool SR = false); 61 bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name, 62 SMLoc NameLoc, OperandVector &Operands); 63 OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, 64 SMLoc &EndLoc) override { 65 return MatchOperand_NoMatch; 66 } 67 OperandMatchResultTy parsePCRelTarget(OperandVector &Operands); 68 69 public: 70 enum XtensaMatchResultTy { 71 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 72 #define GET_OPERAND_DIAGNOSTIC_TYPES 73 #include "XtensaGenAsmMatcher.inc" 74 #undef GET_OPERAND_DIAGNOSTIC_TYPES 75 }; 76 77 XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 78 const MCInstrInfo &MII, const MCTargetOptions &Options) 79 : MCTargetAsmParser(Options, STI, MII) { 80 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 81 } 82 }; 83 84 // Return true if Expr is in the range [MinValue, MaxValue]. 85 static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) { 86 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { 87 int64_t Value = CE->getValue(); 88 return Value >= MinValue && Value <= MaxValue; 89 } 90 return false; 91 } 92 93 struct XtensaOperand : public MCParsedAsmOperand { 94 95 enum KindTy { 96 Token, 97 Register, 98 Immediate, 99 } Kind; 100 101 struct RegOp { 102 unsigned RegNum; 103 }; 104 105 struct ImmOp { 106 const MCExpr *Val; 107 }; 108 109 SMLoc StartLoc, EndLoc; 110 union { 111 StringRef Tok; 112 RegOp Reg; 113 ImmOp Imm; 114 }; 115 116 XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 117 118 public: 119 XtensaOperand(const XtensaOperand &o) : MCParsedAsmOperand() { 120 Kind = o.Kind; 121 StartLoc = o.StartLoc; 122 EndLoc = o.EndLoc; 123 switch (Kind) { 124 case Register: 125 Reg = o.Reg; 126 break; 127 case Immediate: 128 Imm = o.Imm; 129 break; 130 case Token: 131 Tok = o.Tok; 132 break; 133 } 134 } 135 136 bool isToken() const override { return Kind == Token; } 137 bool isReg() const override { return Kind == Register; } 138 bool isImm() const override { return Kind == Immediate; } 139 bool isMem() const override { return false; } 140 141 bool isImm(int64_t MinValue, int64_t MaxValue) const { 142 return Kind == Immediate && inRange(getImm(), MinValue, MaxValue); 143 } 144 145 bool isImm8() const { return isImm(-128, 127); } 146 147 bool isImm8_sh8() const { 148 return isImm(-32768, 32512) && 149 ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0); 150 } 151 152 bool isImm12() const { return isImm(-2048, 2047); } 153 154 bool isImm12m() const { return isImm(-2048, 2047); } 155 156 bool isOffset4m32() const { 157 return isImm(0, 60) && 158 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0); 159 } 160 161 bool isOffset8m8() const { return isImm(0, 255); } 162 163 bool isOffset8m16() const { 164 return isImm(0, 510) && 165 ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0); 166 } 167 168 bool isOffset8m32() const { 169 return isImm(0, 1020) && 170 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0); 171 } 172 173 bool isUimm4() const { return isImm(0, 15); } 174 175 bool isUimm5() const { return isImm(0, 31); } 176 177 bool isImm8n_7() const { return isImm(-8, 7); } 178 179 bool isShimm1_31() const { return isImm(1, 31); } 180 181 bool isImm16_31() const { return isImm(16, 31); } 182 183 bool isImm1_16() const { return isImm(1, 16); } 184 185 bool isB4const() const { 186 if (Kind != Immediate) 187 return false; 188 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) { 189 int64_t Value = CE->getValue(); 190 switch (Value) { 191 case -1: 192 case 1: 193 case 2: 194 case 3: 195 case 4: 196 case 5: 197 case 6: 198 case 7: 199 case 8: 200 case 10: 201 case 12: 202 case 16: 203 case 32: 204 case 64: 205 case 128: 206 case 256: 207 return true; 208 default: 209 return false; 210 } 211 } 212 return false; 213 } 214 215 bool isB4constu() const { 216 if (Kind != Immediate) 217 return false; 218 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) { 219 int64_t Value = CE->getValue(); 220 switch (Value) { 221 case 32768: 222 case 65536: 223 case 2: 224 case 3: 225 case 4: 226 case 5: 227 case 6: 228 case 7: 229 case 8: 230 case 10: 231 case 12: 232 case 16: 233 case 32: 234 case 64: 235 case 128: 236 case 256: 237 return true; 238 default: 239 return false; 240 } 241 } 242 return false; 243 } 244 245 /// getStartLoc - Gets location of the first token of this operand 246 SMLoc getStartLoc() const override { return StartLoc; } 247 /// getEndLoc - Gets location of the last token of this operand 248 SMLoc getEndLoc() const override { return EndLoc; } 249 250 unsigned getReg() const override { 251 assert(Kind == Register && "Invalid type access!"); 252 return Reg.RegNum; 253 } 254 255 const MCExpr *getImm() const { 256 assert(Kind == Immediate && "Invalid type access!"); 257 return Imm.Val; 258 } 259 260 StringRef getToken() const { 261 assert(Kind == Token && "Invalid type access!"); 262 return Tok; 263 } 264 265 void print(raw_ostream &OS) const override { 266 switch (Kind) { 267 case Immediate: 268 OS << *getImm(); 269 break; 270 case Register: 271 OS << "<register x"; 272 OS << getReg() << ">"; 273 break; 274 case Token: 275 OS << "'" << getToken() << "'"; 276 break; 277 } 278 } 279 280 static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) { 281 auto Op = std::make_unique<XtensaOperand>(Token); 282 Op->Tok = Str; 283 Op->StartLoc = S; 284 Op->EndLoc = S; 285 return Op; 286 } 287 288 static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S, 289 SMLoc E) { 290 auto Op = std::make_unique<XtensaOperand>(Register); 291 Op->Reg.RegNum = RegNo; 292 Op->StartLoc = S; 293 Op->EndLoc = E; 294 return Op; 295 } 296 297 static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S, 298 SMLoc E) { 299 auto Op = std::make_unique<XtensaOperand>(Immediate); 300 Op->Imm.Val = Val; 301 Op->StartLoc = S; 302 Op->EndLoc = E; 303 return Op; 304 } 305 306 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 307 assert(Expr && "Expr shouldn't be null!"); 308 int64_t Imm = 0; 309 bool IsConstant = false; 310 311 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { 312 IsConstant = true; 313 Imm = CE->getValue(); 314 } 315 316 if (IsConstant) 317 Inst.addOperand(MCOperand::createImm(Imm)); 318 else 319 Inst.addOperand(MCOperand::createExpr(Expr)); 320 } 321 322 // Used by the TableGen Code 323 void addRegOperands(MCInst &Inst, unsigned N) const { 324 assert(N == 1 && "Invalid number of operands!"); 325 Inst.addOperand(MCOperand::createReg(getReg())); 326 } 327 328 void addImmOperands(MCInst &Inst, unsigned N) const { 329 assert(N == 1 && "Invalid number of operands!"); 330 addExpr(Inst, getImm()); 331 } 332 }; 333 334 #define GET_REGISTER_MATCHER 335 #define GET_MATCHER_IMPLEMENTATION 336 #include "XtensaGenAsmMatcher.inc" 337 338 unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 339 unsigned Kind) { 340 return Match_InvalidOperand; 341 } 342 343 static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, 344 uint64_t ErrorInfo) { 345 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) { 346 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc(); 347 if (ErrorLoc == SMLoc()) 348 return Loc; 349 return ErrorLoc; 350 } 351 return Loc; 352 } 353 354 bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 355 OperandVector &Operands, 356 MCStreamer &Out, 357 uint64_t &ErrorInfo, 358 bool MatchingInlineAsm) { 359 MCInst Inst; 360 auto Result = 361 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); 362 363 switch (Result) { 364 default: 365 break; 366 case Match_Success: 367 Inst.setLoc(IDLoc); 368 Out.emitInstruction(Inst, getSTI()); 369 return false; 370 case Match_MissingFeature: 371 return Error(IDLoc, "instruction use requires an option to be enabled"); 372 case Match_MnemonicFail: 373 return Error(IDLoc, "unrecognized instruction mnemonic"); 374 case Match_InvalidOperand: { 375 SMLoc ErrorLoc = IDLoc; 376 if (ErrorInfo != ~0U) { 377 if (ErrorInfo >= Operands.size()) 378 return Error(ErrorLoc, "too few operands for instruction"); 379 380 ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc(); 381 if (ErrorLoc == SMLoc()) 382 ErrorLoc = IDLoc; 383 } 384 return Error(ErrorLoc, "invalid operand for instruction"); 385 } 386 case Match_InvalidImm8: 387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 388 "expected immediate in range [-128, 127]"); 389 case Match_InvalidImm8_sh8: 390 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 391 "expected immediate in range [-32768, 32512], first 8 bits " 392 "should be zero"); 393 case Match_InvalidB4const: 394 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 395 "expected b4const immediate"); 396 case Match_InvalidB4constu: 397 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 398 "expected b4constu immediate"); 399 case Match_InvalidImm12: 400 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 401 "expected immediate in range [-2048, 2047]"); 402 case Match_InvalidImm12m: 403 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 404 "expected immediate in range [-2048, 2047]"); 405 case Match_InvalidImm1_16: 406 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 407 "expected immediate in range [1, 16]"); 408 case Match_InvalidShimm1_31: 409 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 410 "expected immediate in range [1, 31]"); 411 case Match_InvalidUimm4: 412 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 413 "expected immediate in range [0, 15]"); 414 case Match_InvalidUimm5: 415 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 416 "expected immediate in range [0, 31]"); 417 case Match_InvalidOffset8m8: 418 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 419 "expected immediate in range [0, 255]"); 420 case Match_InvalidOffset8m16: 421 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 422 "expected immediate in range [0, 510], first bit " 423 "should be zero"); 424 case Match_InvalidOffset8m32: 425 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 426 "expected immediate in range [0, 1020], first 2 bits " 427 "should be zero"); 428 case Match_InvalidOffset4m32: 429 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 430 "expected immediate in range [0, 60], first 2 bits " 431 "should be zero"); 432 } 433 434 report_fatal_error("Unknown match type detected!"); 435 } 436 437 OperandMatchResultTy 438 XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) { 439 MCAsmParser &Parser = getParser(); 440 LLVM_DEBUG(dbgs() << "parsePCRelTarget\n"); 441 442 SMLoc S = getLexer().getLoc(); 443 444 // Expressions are acceptable 445 const MCExpr *Expr = nullptr; 446 if (Parser.parseExpression(Expr)) { 447 // We have no way of knowing if a symbol was consumed so we must ParseFail 448 return MatchOperand_ParseFail; 449 } 450 451 // Currently not support constants 452 if (Expr->getKind() == MCExpr::ExprKind::Constant) { 453 Error(getLoc(), "unknown operand"); 454 return MatchOperand_ParseFail; 455 } 456 457 Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc())); 458 return MatchOperand_Success; 459 } 460 461 bool XtensaAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, 462 SMLoc &EndLoc) { 463 const AsmToken &Tok = getParser().getTok(); 464 StartLoc = Tok.getLoc(); 465 EndLoc = Tok.getEndLoc(); 466 RegNo = 0; 467 StringRef Name = getLexer().getTok().getIdentifier(); 468 469 if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) { 470 getParser().Lex(); // Eat identifier token. 471 return false; 472 } 473 474 return Error(StartLoc, "invalid register name"); 475 } 476 477 OperandMatchResultTy XtensaAsmParser::parseRegister(OperandVector &Operands, 478 bool AllowParens, bool SR) { 479 SMLoc FirstS = getLoc(); 480 bool HadParens = false; 481 AsmToken Buf[2]; 482 StringRef RegName; 483 484 // If this a parenthesised register name is allowed, parse it atomically 485 if (AllowParens && getLexer().is(AsmToken::LParen)) { 486 size_t ReadCount = getLexer().peekTokens(Buf); 487 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) { 488 if ((Buf[0].getKind() == AsmToken::Integer) && (!SR)) 489 return MatchOperand_NoMatch; 490 HadParens = true; 491 getParser().Lex(); // Eat '(' 492 } 493 } 494 495 unsigned RegNo = 0; 496 497 switch (getLexer().getKind()) { 498 default: 499 return MatchOperand_NoMatch; 500 case AsmToken::Integer: 501 if (!SR) 502 return MatchOperand_NoMatch; 503 RegName = StringRef(std::to_string(getLexer().getTok().getIntVal())); 504 RegNo = MatchRegisterName(RegName); 505 if (RegNo == 0) 506 RegNo = MatchRegisterAltName(RegName); 507 break; 508 case AsmToken::Identifier: 509 RegName = getLexer().getTok().getIdentifier(); 510 RegNo = MatchRegisterName(RegName); 511 if (RegNo == 0) 512 RegNo = MatchRegisterAltName(RegName); 513 break; 514 } 515 516 if (RegNo == 0) { 517 if (HadParens) 518 getLexer().UnLex(Buf[0]); 519 return MatchOperand_NoMatch; 520 } 521 if (HadParens) 522 Operands.push_back(XtensaOperand::createToken("(", FirstS)); 523 SMLoc S = getLoc(); 524 SMLoc E = getParser().getTok().getEndLoc(); 525 getLexer().Lex(); 526 Operands.push_back(XtensaOperand::createReg(RegNo, S, E)); 527 528 if (HadParens) { 529 getParser().Lex(); // Eat ')' 530 Operands.push_back(XtensaOperand::createToken(")", getLoc())); 531 } 532 533 return MatchOperand_Success; 534 } 535 536 OperandMatchResultTy XtensaAsmParser::parseImmediate(OperandVector &Operands) { 537 SMLoc S = getLoc(); 538 SMLoc E; 539 const MCExpr *Res; 540 541 switch (getLexer().getKind()) { 542 default: 543 return MatchOperand_NoMatch; 544 case AsmToken::LParen: 545 case AsmToken::Minus: 546 case AsmToken::Plus: 547 case AsmToken::Tilde: 548 case AsmToken::Integer: 549 case AsmToken::String: 550 if (getParser().parseExpression(Res)) 551 return MatchOperand_ParseFail; 552 break; 553 case AsmToken::Identifier: { 554 StringRef Identifier; 555 if (getParser().parseIdentifier(Identifier)) 556 return MatchOperand_ParseFail; 557 558 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 559 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 560 break; 561 } 562 case AsmToken::Percent: 563 return parseOperandWithModifier(Operands); 564 } 565 566 E = SMLoc::getFromPointer(S.getPointer() - 1); 567 Operands.push_back(XtensaOperand::createImm(Res, S, E)); 568 return MatchOperand_Success; 569 } 570 571 OperandMatchResultTy 572 XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) { 573 return MatchOperand_ParseFail; 574 } 575 576 /// Looks at a token type and creates the relevant operand 577 /// from this information, adding to Operands. 578 /// If operand was parsed, returns false, else true. 579 bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic, 580 bool SR) { 581 // Check if the current operand has a custom associated parser, if so, try to 582 // custom parse the operand, or fallback to the general approach. 583 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 584 if (ResTy == MatchOperand_Success) 585 return false; 586 587 // If there wasn't a custom match, try the generic matcher below. Otherwise, 588 // there was a match, but an error occurred, in which case, just return that 589 // the operand parsing failed. 590 if (ResTy == MatchOperand_ParseFail) 591 return true; 592 593 // Attempt to parse token as register 594 if (parseRegister(Operands, true, SR) == MatchOperand_Success) 595 return false; 596 597 // Attempt to parse token as an immediate 598 if (parseImmediate(Operands) == MatchOperand_Success) { 599 return false; 600 } 601 602 // Finally we have exhausted all options and must declare defeat. 603 Error(getLoc(), "unknown operand"); 604 return true; 605 } 606 607 bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info, 608 StringRef Name, SMLoc NameLoc, 609 OperandVector &Operands) { 610 if ((Name.startswith("wsr.") || Name.startswith("rsr.") || 611 Name.startswith("xsr.")) && 612 (Name.size() > 4)) { 613 // Parse case when instruction name is concatenated with SR register 614 // name, like "wsr.sar a1" 615 616 // First operand is token for instruction 617 Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc)); 618 619 StringRef RegName = Name.drop_front(4); 620 unsigned RegNo = MatchRegisterName(RegName); 621 622 if (RegNo == 0) 623 RegNo = MatchRegisterAltName(RegName); 624 625 if (RegNo == 0) { 626 Error(NameLoc, "invalid register name"); 627 return true; 628 } 629 630 // Parse operand 631 if (parseOperand(Operands, Name)) 632 return true; 633 634 SMLoc S = getLoc(); 635 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 636 Operands.push_back(XtensaOperand::createReg(RegNo, S, E)); 637 } else { 638 // First operand is token for instruction 639 Operands.push_back(XtensaOperand::createToken(Name, NameLoc)); 640 641 // Parse first operand 642 if (parseOperand(Operands, Name)) 643 return true; 644 645 if (!getLexer().is(AsmToken::Comma)) { 646 SMLoc Loc = getLexer().getLoc(); 647 getParser().eatToEndOfStatement(); 648 return Error(Loc, "unexpected token"); 649 } 650 651 getLexer().Lex(); 652 653 // Parse second operand 654 if (parseOperand(Operands, Name, true)) 655 return true; 656 } 657 658 if (getLexer().isNot(AsmToken::EndOfStatement)) { 659 SMLoc Loc = getLexer().getLoc(); 660 getParser().eatToEndOfStatement(); 661 return Error(Loc, "unexpected token"); 662 } 663 664 getParser().Lex(); // Consume the EndOfStatement. 665 return false; 666 } 667 668 bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info, 669 StringRef Name, SMLoc NameLoc, 670 OperandVector &Operands) { 671 if (Name.startswith("wsr") || Name.startswith("rsr") || 672 Name.startswith("xsr")) { 673 return ParseInstructionWithSR(Info, Name, NameLoc, Operands); 674 } 675 676 // First operand is token for instruction 677 Operands.push_back(XtensaOperand::createToken(Name, NameLoc)); 678 679 // If there are no more operands, then finish 680 if (getLexer().is(AsmToken::EndOfStatement)) 681 return false; 682 683 // Parse first operand 684 if (parseOperand(Operands, Name)) 685 return true; 686 687 // Parse until end of statement, consuming commas between operands 688 while (getLexer().is(AsmToken::Comma)) { 689 // Consume comma token 690 getLexer().Lex(); 691 692 // Parse next operand 693 if (parseOperand(Operands, Name)) 694 return true; 695 } 696 697 if (getLexer().isNot(AsmToken::EndOfStatement)) { 698 SMLoc Loc = getLexer().getLoc(); 699 getParser().eatToEndOfStatement(); 700 return Error(Loc, "unexpected token"); 701 } 702 703 getParser().Lex(); // Consume the EndOfStatement. 704 return false; 705 } 706 707 bool XtensaAsmParser::ParseDirective(AsmToken DirectiveID) { return true; } 708 709 // Force static initialization. 710 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() { 711 RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget()); 712 } 713