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
getLoc() const36 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);
tryParseRegister(MCRegister & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)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
XtensaAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)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].
inRange(const MCExpr * Expr,int64_t MinValue,int64_t 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
XtensaOperandXtensaOperand116 XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
117
118 public:
XtensaOperandXtensaOperand119 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
isTokenXtensaOperand136 bool isToken() const override { return Kind == Token; }
isRegXtensaOperand137 bool isReg() const override { return Kind == Register; }
isImmXtensaOperand138 bool isImm() const override { return Kind == Immediate; }
isMemXtensaOperand139 bool isMem() const override { return false; }
140
isImmXtensaOperand141 bool isImm(int64_t MinValue, int64_t MaxValue) const {
142 return Kind == Immediate && inRange(getImm(), MinValue, MaxValue);
143 }
144
isImm8XtensaOperand145 bool isImm8() const { return isImm(-128, 127); }
146
isImm8_sh8XtensaOperand147 bool isImm8_sh8() const {
148 return isImm(-32768, 32512) &&
149 ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);
150 }
151
isImm12XtensaOperand152 bool isImm12() const { return isImm(-2048, 2047); }
153
isImm12mXtensaOperand154 bool isImm12m() const { return isImm(-2048, 2047); }
155
isOffset4m32XtensaOperand156 bool isOffset4m32() const {
157 return isImm(0, 60) &&
158 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
159 }
160
isOffset8m8XtensaOperand161 bool isOffset8m8() const { return isImm(0, 255); }
162
isOffset8m16XtensaOperand163 bool isOffset8m16() const {
164 return isImm(0, 510) &&
165 ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);
166 }
167
isOffset8m32XtensaOperand168 bool isOffset8m32() const {
169 return isImm(0, 1020) &&
170 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
171 }
172
isUimm4XtensaOperand173 bool isUimm4() const { return isImm(0, 15); }
174
isUimm5XtensaOperand175 bool isUimm5() const { return isImm(0, 31); }
176
isImm8n_7XtensaOperand177 bool isImm8n_7() const { return isImm(-8, 7); }
178
isShimm1_31XtensaOperand179 bool isShimm1_31() const { return isImm(1, 31); }
180
isImm16_31XtensaOperand181 bool isImm16_31() const { return isImm(16, 31); }
182
isImm1_16XtensaOperand183 bool isImm1_16() const { return isImm(1, 16); }
184
isB4constXtensaOperand185 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
isB4constuXtensaOperand215 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
getStartLocXtensaOperand246 SMLoc getStartLoc() const override { return StartLoc; }
247 /// getEndLoc - Gets location of the last token of this operand
getEndLocXtensaOperand248 SMLoc getEndLoc() const override { return EndLoc; }
249
getRegXtensaOperand250 unsigned getReg() const override {
251 assert(Kind == Register && "Invalid type access!");
252 return Reg.RegNum;
253 }
254
getImmXtensaOperand255 const MCExpr *getImm() const {
256 assert(Kind == Immediate && "Invalid type access!");
257 return Imm.Val;
258 }
259
getTokenXtensaOperand260 StringRef getToken() const {
261 assert(Kind == Token && "Invalid type access!");
262 return Tok;
263 }
264
printXtensaOperand265 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
createTokenXtensaOperand280 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
createRegXtensaOperand288 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
createImmXtensaOperand297 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
addExprXtensaOperand306 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
addRegOperandsXtensaOperand323 void addRegOperands(MCInst &Inst, unsigned N) const {
324 assert(N == 1 && "Invalid number of operands!");
325 Inst.addOperand(MCOperand::createReg(getReg()));
326 }
327
addImmOperandsXtensaOperand328 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
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)338 unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
339 unsigned Kind) {
340 return Match_InvalidOperand;
341 }
342
RefineErrorLoc(const SMLoc Loc,const OperandVector & Operands,uint64_t ErrorInfo)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
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)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
parsePCRelTarget(OperandVector & Operands)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
parseRegister(MCRegister & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)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
parseRegister(OperandVector & Operands,bool AllowParens,bool SR)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
parseImmediate(OperandVector & Operands)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
parseOperandWithModifier(OperandVector & Operands)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.
parseOperand(OperandVector & Operands,StringRef Mnemonic,bool SR)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
ParseInstructionWithSR(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)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
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)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
ParseDirective(AsmToken DirectiveID)707 bool XtensaAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
708
709 // Force static initialization.
LLVMInitializeXtensaAsmParser()710 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {
711 RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());
712 }
713