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