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