881 lines · cpp
1//===- XtensaAsmParser.cpp - Parse Xtensa assembly to MCInst instructions -===//2//3// The LLVM Compiler Infrastructure4//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-exception8//9//===----------------------------------------------------------------------===//10 11#include "MCTargetDesc/XtensaMCAsmInfo.h"12#include "MCTargetDesc/XtensaMCTargetDesc.h"13#include "MCTargetDesc/XtensaTargetStreamer.h"14#include "TargetInfo/XtensaTargetInfo.h"15#include "llvm/ADT/STLExtras.h"16#include "llvm/ADT/StringSwitch.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCExpr.h"19#include "llvm/MC/MCInst.h"20#include "llvm/MC/MCInstrInfo.h"21#include "llvm/MC/MCParser/AsmLexer.h"22#include "llvm/MC/MCParser/MCParsedAsmOperand.h"23#include "llvm/MC/MCParser/MCTargetAsmParser.h"24#include "llvm/MC/MCRegisterInfo.h"25#include "llvm/MC/MCStreamer.h"26#include "llvm/MC/MCSubtargetInfo.h"27#include "llvm/MC/MCSymbol.h"28#include "llvm/MC/TargetRegistry.h"29#include "llvm/Support/Casting.h"30 31using namespace llvm;32 33#define DEBUG_TYPE "xtensa-asm-parser"34 35struct XtensaOperand;36 37class XtensaAsmParser : public MCTargetAsmParser {38 const MCRegisterInfo &MRI;39 40 enum XtensaRegisterType { Xtensa_Generic, Xtensa_SR, Xtensa_UR };41 SMLoc getLoc() const { return getParser().getTok().getLoc(); }42 43 XtensaTargetStreamer &getTargetStreamer() {44 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();45 return static_cast<XtensaTargetStreamer &>(TS);46 }47 48 ParseStatus parseDirective(AsmToken DirectiveID) override;49 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;50 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,51 SMLoc NameLoc, OperandVector &Operands) override;52 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,53 OperandVector &Operands, MCStreamer &Out,54 uint64_t &ErrorInfo,55 bool MatchingInlineAsm) override;56 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,57 unsigned Kind) override;58 59 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,60 const MCSubtargetInfo *STI);61 62// Auto-generated instruction matching functions63#define GET_ASSEMBLER_HEADER64#include "XtensaGenAsmMatcher.inc"65 66 ParseStatus parseImmediate(OperandVector &Operands);67 ParseStatus68 parseRegister(OperandVector &Operands, bool AllowParens = false,69 XtensaRegisterType SR = Xtensa_Generic,70 Xtensa::RegisterAccessType RAType = Xtensa::REGISTER_EXCHANGE);71 ParseStatus parseOperandWithModifier(OperandVector &Operands);72 bool73 parseOperand(OperandVector &Operands, StringRef Mnemonic,74 XtensaRegisterType SR = Xtensa_Generic,75 Xtensa::RegisterAccessType RAType = Xtensa::REGISTER_EXCHANGE);76 bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,77 SMLoc NameLoc, OperandVector &Operands);78 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,79 SMLoc &EndLoc) override {80 return ParseStatus::NoMatch;81 }82 83 ParseStatus parsePCRelTarget(OperandVector &Operands);84 bool parseLiteralDirective(SMLoc L);85 86public:87 enum XtensaMatchResultTy {88 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,89#define GET_OPERAND_DIAGNOSTIC_TYPES90#include "XtensaGenAsmMatcher.inc"91#undef GET_OPERAND_DIAGNOSTIC_TYPES92 };93 94 XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,95 const MCInstrInfo &MII, const MCTargetOptions &Options)96 : MCTargetAsmParser(Options, STI, MII),97 MRI(*Parser.getContext().getRegisterInfo()) {98 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));99 }100 101 bool hasWindowed() const {102 return getSTI().getFeatureBits()[Xtensa::FeatureWindowed];103 };104};105 106// Return true if Expr is in the range [MinValue, MaxValue].107static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) {108 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {109 int64_t Value = CE->getValue();110 return Value >= MinValue && Value <= MaxValue;111 }112 return false;113}114 115struct XtensaOperand : public MCParsedAsmOperand {116 117 enum KindTy {118 Token,119 Register,120 Immediate,121 } Kind;122 123 struct RegOp {124 unsigned RegNum;125 };126 127 struct ImmOp {128 const MCExpr *Val;129 };130 131 SMLoc StartLoc, EndLoc;132 union {133 StringRef Tok;134 RegOp Reg;135 ImmOp Imm;136 };137 138 XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}139 140public:141 XtensaOperand(const XtensaOperand &o) : MCParsedAsmOperand() {142 Kind = o.Kind;143 StartLoc = o.StartLoc;144 EndLoc = o.EndLoc;145 switch (Kind) {146 case Register:147 Reg = o.Reg;148 break;149 case Immediate:150 Imm = o.Imm;151 break;152 case Token:153 Tok = o.Tok;154 break;155 }156 }157 158 bool isToken() const override { return Kind == Token; }159 bool isReg() const override { return Kind == Register; }160 bool isImm() const override { return Kind == Immediate; }161 bool isMem() const override { return false; }162 163 bool isImm(int64_t MinValue, int64_t MaxValue) const {164 return Kind == Immediate && inRange(getImm(), MinValue, MaxValue);165 }166 167 bool isImm8() const { return isImm(-128, 127); }168 169 bool isImm8_sh8() const {170 return isImm(-32768, 32512) &&171 ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);172 }173 174 bool isImm12() const { return isImm(-2048, 2047); }175 176 // Convert MOVI to literal load, when immediate is not in range (-2048, 2047)177 bool isImm12m() const { return Kind == Immediate; }178 179 bool isOffset4m32() const {180 return isImm(0, 60) &&181 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);182 }183 184 bool isOffset8m8() const { return isImm(0, 255); }185 186 bool isOffset8m16() const {187 return isImm(0, 510) &&188 ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);189 }190 191 bool isOffset8m32() const {192 return isImm(0, 1020) &&193 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);194 }195 196 bool isentry_imm12() const {197 return isImm(0, 32760) &&198 ((cast<MCConstantExpr>(getImm())->getValue() % 8) == 0);199 }200 201 bool isUimm4() const { return isImm(0, 15); }202 203 bool isUimm5() const { return isImm(0, 31); }204 205 bool isImm8n_7() const { return isImm(-8, 7); }206 207 bool isShimm1_31() const { return isImm(1, 31); }208 209 bool isImm16_31() const { return isImm(16, 31); }210 211 bool isImm1_16() const { return isImm(1, 16); }212 213 // Check that value is either equals (-1) or from [1,15] range.214 bool isImm1n_15() const { return isImm(1, 15) || isImm(-1, -1); }215 216 bool isImm32n_95() const { return isImm(-32, 95); }217 218 bool isImm64n_4n() const {219 return isImm(-64, -4) &&220 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);221 }222 223 bool isB4const() const {224 if (Kind != Immediate)225 return false;226 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {227 int64_t Value = CE->getValue();228 switch (Value) {229 case -1:230 case 1:231 case 2:232 case 3:233 case 4:234 case 5:235 case 6:236 case 7:237 case 8:238 case 10:239 case 12:240 case 16:241 case 32:242 case 64:243 case 128:244 case 256:245 return true;246 default:247 return false;248 }249 }250 return false;251 }252 253 bool isB4constu() const {254 if (Kind != Immediate)255 return false;256 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {257 int64_t Value = CE->getValue();258 switch (Value) {259 case 32768:260 case 65536:261 case 2:262 case 3:263 case 4:264 case 5:265 case 6:266 case 7:267 case 8:268 case 10:269 case 12:270 case 16:271 case 32:272 case 64:273 case 128:274 case 256:275 return true;276 default:277 return false;278 }279 }280 return false;281 }282 283 bool isimm7_22() const { return isImm(7, 22); }284 285 /// getStartLoc - Gets location of the first token of this operand286 SMLoc getStartLoc() const override { return StartLoc; }287 /// getEndLoc - Gets location of the last token of this operand288 SMLoc getEndLoc() const override { return EndLoc; }289 290 MCRegister getReg() const override {291 assert(Kind == Register && "Invalid type access!");292 return Reg.RegNum;293 }294 295 const MCExpr *getImm() const {296 assert(Kind == Immediate && "Invalid type access!");297 return Imm.Val;298 }299 300 StringRef getToken() const {301 assert(Kind == Token && "Invalid type access!");302 return Tok;303 }304 305 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {306 switch (Kind) {307 case Immediate:308 MAI.printExpr(OS, *getImm());309 break;310 case Register:311 OS << "<register x";312 OS << getReg() << ">";313 break;314 case Token:315 OS << "'" << getToken() << "'";316 break;317 }318 }319 320 static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) {321 auto Op = std::make_unique<XtensaOperand>(Token);322 Op->Tok = Str;323 Op->StartLoc = S;324 Op->EndLoc = S;325 return Op;326 }327 328 static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S,329 SMLoc E) {330 auto Op = std::make_unique<XtensaOperand>(Register);331 Op->Reg.RegNum = RegNo;332 Op->StartLoc = S;333 Op->EndLoc = E;334 return Op;335 }336 337 static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S,338 SMLoc E) {339 auto Op = std::make_unique<XtensaOperand>(Immediate);340 Op->Imm.Val = Val;341 Op->StartLoc = S;342 Op->EndLoc = E;343 return Op;344 }345 346 void addExpr(MCInst &Inst, const MCExpr *Expr) const {347 assert(Expr && "Expr shouldn't be null!");348 int64_t Imm = 0;349 bool IsConstant = false;350 351 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {352 IsConstant = true;353 Imm = CE->getValue();354 }355 356 if (IsConstant)357 Inst.addOperand(MCOperand::createImm(Imm));358 else359 Inst.addOperand(MCOperand::createExpr(Expr));360 }361 362 // Used by the TableGen Code363 void addRegOperands(MCInst &Inst, unsigned N) const {364 assert(N == 1 && "Invalid number of operands!");365 Inst.addOperand(MCOperand::createReg(getReg()));366 }367 368 void addImmOperands(MCInst &Inst, unsigned N) const {369 assert(N == 1 && "Invalid number of operands!");370 addExpr(Inst, getImm());371 }372};373 374#define GET_REGISTER_MATCHER375#define GET_MATCHER_IMPLEMENTATION376#include "XtensaGenAsmMatcher.inc"377 378unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,379 unsigned Kind) {380 return Match_InvalidOperand;381}382 383static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,384 uint64_t ErrorInfo) {385 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {386 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();387 if (ErrorLoc == SMLoc())388 return Loc;389 return ErrorLoc;390 }391 return Loc;392}393 394bool XtensaAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,395 MCStreamer &Out,396 const MCSubtargetInfo *STI) {397 Inst.setLoc(IDLoc);398 const unsigned Opcode = Inst.getOpcode();399 switch (Opcode) {400 case Xtensa::L32R: {401 const MCSymbolRefExpr *OpExpr =402 static_cast<const MCSymbolRefExpr *>(Inst.getOperand(1).getExpr());403 Inst.getOperand(1).setExpr(OpExpr);404 break;405 }406 case Xtensa::MOVI: {407 XtensaTargetStreamer &TS = this->getTargetStreamer();408 409 // Expand MOVI operand410 if (!Inst.getOperand(1).isExpr()) {411 uint64_t ImmOp64 = Inst.getOperand(1).getImm();412 int32_t Imm = ImmOp64;413 if (!isInt<12>(Imm)) {414 XtensaTargetStreamer &TS = this->getTargetStreamer();415 MCInst TmpInst;416 TmpInst.setLoc(IDLoc);417 TmpInst.setOpcode(Xtensa::L32R);418 const MCExpr *Value = MCConstantExpr::create(ImmOp64, getContext());419 MCSymbol *Sym = getContext().createTempSymbol();420 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());421 TmpInst.addOperand(Inst.getOperand(0));422 MCOperand Op1 = MCOperand::createExpr(Expr);423 TmpInst.addOperand(Op1);424 TS.emitLiteral(Sym, Value, true, IDLoc);425 Inst = TmpInst;426 }427 } else {428 MCInst TmpInst;429 TmpInst.setLoc(IDLoc);430 TmpInst.setOpcode(Xtensa::L32R);431 const MCExpr *Value = Inst.getOperand(1).getExpr();432 MCSymbol *Sym = getContext().createTempSymbol();433 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());434 TmpInst.addOperand(Inst.getOperand(0));435 MCOperand Op1 = MCOperand::createExpr(Expr);436 TmpInst.addOperand(Op1);437 Inst = TmpInst;438 TS.emitLiteral(Sym, Value, true, IDLoc);439 }440 break;441 }442 default:443 break;444 }445 446 return true;447}448 449bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,450 OperandVector &Operands,451 MCStreamer &Out,452 uint64_t &ErrorInfo,453 bool MatchingInlineAsm) {454 MCInst Inst;455 auto Result =456 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);457 458 switch (Result) {459 default:460 break;461 case Match_Success:462 processInstruction(Inst, IDLoc, Out, STI);463 Inst.setLoc(IDLoc);464 Out.emitInstruction(Inst, getSTI());465 return false;466 case Match_MissingFeature:467 return Error(IDLoc, "instruction use requires an option to be enabled");468 case Match_MnemonicFail:469 return Error(IDLoc, "unrecognized instruction mnemonic");470 case Match_InvalidOperand: {471 SMLoc ErrorLoc = IDLoc;472 if (ErrorInfo != ~0U) {473 if (ErrorInfo >= Operands.size())474 return Error(ErrorLoc, "too few operands for instruction");475 476 ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc();477 if (ErrorLoc == SMLoc())478 ErrorLoc = IDLoc;479 }480 return Error(ErrorLoc, "invalid operand for instruction");481 }482 case Match_InvalidImm8:483 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),484 "expected immediate in range [-128, 127]");485 case Match_InvalidImm8_sh8:486 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),487 "expected immediate in range [-32768, 32512], first 8 bits "488 "should be zero");489 case Match_InvalidB4const:490 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),491 "expected b4const immediate");492 case Match_InvalidB4constu:493 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),494 "expected b4constu immediate");495 case Match_InvalidImm12:496 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),497 "expected immediate in range [-2048, 2047]");498 case Match_InvalidImm12m:499 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),500 "expected immediate in range [-2048, 2047]");501 case Match_InvalidImm1_16:502 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),503 "expected immediate in range [1, 16]");504 case Match_InvalidImm1n_15:505 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),506 "expected immediate in range [-1, 15] except 0");507 case Match_InvalidImm32n_95:508 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),509 "expected immediate in range [-32, 95]");510 case Match_InvalidImm64n_4n:511 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),512 "expected immediate in range [-64, -4]");513 case Match_InvalidImm8n_7:514 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),515 "expected immediate in range [-8, 7]");516 case Match_InvalidShimm1_31:517 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),518 "expected immediate in range [1, 31]");519 case Match_InvalidUimm4:520 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),521 "expected immediate in range [0, 15]");522 case Match_InvalidUimm5:523 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),524 "expected immediate in range [0, 31]");525 case Match_InvalidOffset8m8:526 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),527 "expected immediate in range [0, 255]");528 case Match_InvalidOffset8m16:529 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),530 "expected immediate in range [0, 510], first bit "531 "should be zero");532 case Match_InvalidOffset8m32:533 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),534 "expected immediate in range [0, 1020], first 2 bits "535 "should be zero");536 case Match_InvalidOffset4m32:537 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),538 "expected immediate in range [0, 60], first 2 bits "539 "should be zero");540 case Match_Invalidentry_imm12:541 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),542 "expected immediate in range [0, 32760], first 3 bits "543 "should be zero");544 case Match_Invalidimm7_22:545 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),546 "expected immediate in range [7, 22]");547 }548 549 report_fatal_error("Unknown match type detected!");550}551 552ParseStatus XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) {553 MCAsmParser &Parser = getParser();554 LLVM_DEBUG(dbgs() << "parsePCRelTarget\n");555 556 SMLoc S = getLexer().getLoc();557 558 // Expressions are acceptable559 const MCExpr *Expr = nullptr;560 if (Parser.parseExpression(Expr)) {561 // We have no way of knowing if a symbol was consumed so we must ParseFail562 return ParseStatus::Failure;563 }564 565 // Currently not support constants566 if (Expr->getKind() == MCExpr::ExprKind::Constant)567 return Error(getLoc(), "unknown operand");568 569 Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc()));570 return ParseStatus::Success;571}572 573bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,574 SMLoc &EndLoc) {575 const AsmToken &Tok = getParser().getTok();576 StartLoc = Tok.getLoc();577 EndLoc = Tok.getEndLoc();578 Reg = Xtensa::NoRegister;579 StringRef Name = getLexer().getTok().getIdentifier();580 581 if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) {582 getParser().Lex(); // Eat identifier token.583 return false;584 }585 586 return Error(StartLoc, "invalid register name");587}588 589ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,590 bool AllowParens,591 XtensaRegisterType RegType,592 Xtensa::RegisterAccessType RAType) {593 SMLoc FirstS = getLoc();594 bool HadParens = false;595 AsmToken Buf[2];596 StringRef RegName;597 598 // If this a parenthesised register name is allowed, parse it atomically599 if (AllowParens && getLexer().is(AsmToken::LParen)) {600 size_t ReadCount = getLexer().peekTokens(Buf);601 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {602 if (Buf[0].getKind() == AsmToken::Integer && RegType == Xtensa_Generic)603 return ParseStatus::NoMatch;604 HadParens = true;605 getParser().Lex(); // Eat '('606 }607 }608 609 MCRegister RegNo = 0;610 611 switch (getLexer().getKind()) {612 default:613 return ParseStatus::NoMatch;614 case AsmToken::Integer:615 if (RegType == Xtensa_Generic)616 return ParseStatus::NoMatch;617 618 // Parse case when we expect UR register code as special case,619 // because SR and UR registers may have the same number620 // and such situation may lead to confilct621 if (RegType == Xtensa_UR) {622 int64_t RegCode = getLexer().getTok().getIntVal();623 RegNo = Xtensa::getUserRegister(RegCode, MRI);624 } else {625 RegName = getLexer().getTok().getString();626 RegNo = MatchRegisterAltName(RegName);627 }628 break;629 case AsmToken::Identifier:630 RegName = getLexer().getTok().getIdentifier();631 RegNo = MatchRegisterName(RegName);632 if (RegNo == 0)633 RegNo = MatchRegisterAltName(RegName);634 break;635 }636 637 if (RegNo == 0) {638 if (HadParens)639 getLexer().UnLex(Buf[0]);640 return ParseStatus::NoMatch;641 }642 643 if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits(), RAType))644 return ParseStatus::NoMatch;645 646 if (HadParens)647 Operands.push_back(XtensaOperand::createToken("(", FirstS));648 SMLoc S = getLoc();649 SMLoc E = getParser().getTok().getEndLoc();650 getLexer().Lex();651 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));652 653 if (HadParens) {654 getParser().Lex(); // Eat ')'655 Operands.push_back(XtensaOperand::createToken(")", getLoc()));656 }657 658 return ParseStatus::Success;659}660 661ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) {662 SMLoc S = getLoc();663 SMLoc E;664 const MCExpr *Res;665 666 switch (getLexer().getKind()) {667 default:668 return ParseStatus::NoMatch;669 case AsmToken::LParen:670 case AsmToken::Minus:671 case AsmToken::Plus:672 case AsmToken::Tilde:673 case AsmToken::Integer:674 case AsmToken::String:675 if (getParser().parseExpression(Res))676 return ParseStatus::Failure;677 break;678 case AsmToken::Identifier: {679 StringRef Identifier;680 if (getParser().parseIdentifier(Identifier))681 return ParseStatus::Failure;682 683 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);684 Res = MCSymbolRefExpr::create(Sym, getContext());685 break;686 }687 case AsmToken::Percent:688 return parseOperandWithModifier(Operands);689 }690 691 E = SMLoc::getFromPointer(S.getPointer() - 1);692 Operands.push_back(XtensaOperand::createImm(Res, S, E));693 return ParseStatus::Success;694}695 696ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {697 return ParseStatus::Failure;698}699 700/// Looks at a token type and creates the relevant operand701/// from this information, adding to Operands.702/// If operand was parsed, returns false, else true.703bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,704 XtensaRegisterType RegType,705 Xtensa::RegisterAccessType RAType) {706 // Check if the current operand has a custom associated parser, if so, try to707 // custom parse the operand, or fallback to the general approach.708 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);709 if (Res.isSuccess())710 return false;711 712 // If there wasn't a custom match, try the generic matcher below. Otherwise,713 // there was a match, but an error occurred, in which case, just return that714 // the operand parsing failed.715 if (Res.isFailure())716 return true;717 718 // Attempt to parse token as register719 if (parseRegister(Operands, true, RegType, RAType).isSuccess())720 return false;721 722 // Attempt to parse token as an immediate723 if (parseImmediate(Operands).isSuccess())724 return false;725 726 // Finally we have exhausted all options and must declare defeat.727 return Error(getLoc(), "unknown operand");728}729 730bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,731 StringRef Name, SMLoc NameLoc,732 OperandVector &Operands) {733 Xtensa::RegisterAccessType RAType =734 Name[0] == 'w' ? Xtensa::REGISTER_WRITE735 : (Name[0] == 'r' ? Xtensa::REGISTER_READ736 : Xtensa::REGISTER_EXCHANGE);737 738 if ((Name.size() > 4) && Name[3] == '.') {739 // Parse case when instruction name is concatenated with SR/UR register740 // name, like "wsr.sar a1" or "wur.fcr a1"741 742 // First operand is token for instruction743 Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));744 745 StringRef RegName = Name.drop_front(4);746 unsigned RegNo = MatchRegisterName(RegName);747 748 if (RegNo == 0)749 RegNo = MatchRegisterAltName(RegName);750 751 if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits(), RAType))752 return Error(NameLoc, "invalid register name");753 754 // Parse operand755 if (parseOperand(Operands, Name))756 return true;757 758 SMLoc S = getLoc();759 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);760 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));761 } else {762 // First operand is token for instruction763 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));764 765 // Parse first operand766 if (parseOperand(Operands, Name))767 return true;768 769 if (!parseOptionalToken(AsmToken::Comma)) {770 SMLoc Loc = getLexer().getLoc();771 getParser().eatToEndOfStatement();772 return Error(Loc, "unexpected token");773 }774 775 // Parse second operand776 if (parseOperand(Operands, Name, Name[1] == 's' ? Xtensa_SR : Xtensa_UR,777 RAType))778 return true;779 }780 781 if (getLexer().isNot(AsmToken::EndOfStatement)) {782 SMLoc Loc = getLexer().getLoc();783 getParser().eatToEndOfStatement();784 return Error(Loc, "unexpected token");785 }786 787 getParser().Lex(); // Consume the EndOfStatement.788 return false;789}790 791bool XtensaAsmParser::parseInstruction(ParseInstructionInfo &Info,792 StringRef Name, SMLoc NameLoc,793 OperandVector &Operands) {794 if (Name.starts_with("wsr") || Name.starts_with("rsr") ||795 Name.starts_with("xsr") || Name.starts_with("rur") ||796 Name.starts_with("wur")) {797 return ParseInstructionWithSR(Info, Name, NameLoc, Operands);798 }799 800 // First operand is token for instruction801 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));802 803 // If there are no more operands, then finish804 if (getLexer().is(AsmToken::EndOfStatement))805 return false;806 807 // Parse first operand808 if (parseOperand(Operands, Name))809 return true;810 811 // Parse until end of statement, consuming commas between operands812 while (parseOptionalToken(AsmToken::Comma))813 if (parseOperand(Operands, Name))814 return true;815 816 if (getLexer().isNot(AsmToken::EndOfStatement)) {817 SMLoc Loc = getLexer().getLoc();818 getParser().eatToEndOfStatement();819 return Error(Loc, "unexpected token");820 }821 822 getParser().Lex(); // Consume the EndOfStatement.823 return false;824}825 826bool XtensaAsmParser::parseLiteralDirective(SMLoc L) {827 MCAsmParser &Parser = getParser();828 const MCExpr *Value;829 SMLoc LiteralLoc = getLexer().getLoc();830 XtensaTargetStreamer &TS = this->getTargetStreamer();831 832 if (Parser.parseExpression(Value))833 return true;834 835 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Value);836 837 if (!SE)838 return Error(LiteralLoc, "literal label must be a symbol");839 840 if (Parser.parseComma())841 return true;842 843 SMLoc OpcodeLoc = getLexer().getLoc();844 if (parseOptionalToken(AsmToken::EndOfStatement))845 return Error(OpcodeLoc, "expected value");846 847 if (Parser.parseExpression(Value))848 return true;849 850 if (parseEOL())851 return true;852 853 MCSymbol *Sym = getContext().getOrCreateSymbol(SE->getSymbol().getName());854 855 TS.emitLiteral(Sym, Value, true, LiteralLoc);856 857 return false;858}859 860ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) {861 StringRef IDVal = DirectiveID.getString();862 SMLoc Loc = getLexer().getLoc();863 864 if (IDVal == ".literal_position") {865 XtensaTargetStreamer &TS = this->getTargetStreamer();866 TS.emitLiteralPosition();867 return parseEOL();868 }869 870 if (IDVal == ".literal") {871 return parseLiteralDirective(Loc);872 }873 874 return ParseStatus::NoMatch;875}876 877// Force static initialization.878extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {879 RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());880}881