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