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