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
getLoc() const39bdd1243dSDimitry Andric SMLoc getLoc() const { return getParser().getTok().getLoc(); }
40bdd1243dSDimitry Andric
getTargetStreamer()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);
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)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
XtensaAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)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].
inRange(const MCExpr * Expr,int64_t MinValue,int64_t 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
XtensaOperandXtensaOperand126bdd1243dSDimitry Andric XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
127bdd1243dSDimitry Andric
128bdd1243dSDimitry Andric public:
XtensaOperandXtensaOperand129bdd1243dSDimitry 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
isTokenXtensaOperand146bdd1243dSDimitry Andric bool isToken() const override { return Kind == Token; }
isRegXtensaOperand147bdd1243dSDimitry Andric bool isReg() const override { return Kind == Register; }
isImmXtensaOperand148bdd1243dSDimitry Andric bool isImm() const override { return Kind == Immediate; }
isMemXtensaOperand149bdd1243dSDimitry Andric bool isMem() const override { return false; }
150bdd1243dSDimitry Andric
isImmXtensaOperand151bdd1243dSDimitry Andric bool isImm(int64_t MinValue, int64_t MaxValue) const {
152bdd1243dSDimitry Andric return Kind == Immediate && inRange(getImm(), MinValue, MaxValue);
153bdd1243dSDimitry Andric }
154bdd1243dSDimitry Andric
isImm8XtensaOperand155bdd1243dSDimitry Andric bool isImm8() const { return isImm(-128, 127); }
156bdd1243dSDimitry Andric
isImm8_sh8XtensaOperand157bdd1243dSDimitry Andric bool isImm8_sh8() const {
158bdd1243dSDimitry Andric return isImm(-32768, 32512) &&
159bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);
160bdd1243dSDimitry Andric }
161bdd1243dSDimitry Andric
isImm12XtensaOperand162bdd1243dSDimitry 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)
isImm12mXtensaOperand165*0fca6ea1SDimitry Andric bool isImm12m() const { return Kind == Immediate; }
166bdd1243dSDimitry Andric
isOffset4m32XtensaOperand167bdd1243dSDimitry Andric bool isOffset4m32() const {
168bdd1243dSDimitry Andric return isImm(0, 60) &&
169bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
170bdd1243dSDimitry Andric }
171bdd1243dSDimitry Andric
isOffset8m8XtensaOperand172bdd1243dSDimitry Andric bool isOffset8m8() const { return isImm(0, 255); }
173bdd1243dSDimitry Andric
isOffset8m16XtensaOperand174bdd1243dSDimitry Andric bool isOffset8m16() const {
175bdd1243dSDimitry Andric return isImm(0, 510) &&
176bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);
177bdd1243dSDimitry Andric }
178bdd1243dSDimitry Andric
isOffset8m32XtensaOperand179bdd1243dSDimitry Andric bool isOffset8m32() const {
180bdd1243dSDimitry Andric return isImm(0, 1020) &&
181bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
182bdd1243dSDimitry Andric }
183bdd1243dSDimitry Andric
isUimm4XtensaOperand184bdd1243dSDimitry Andric bool isUimm4() const { return isImm(0, 15); }
185bdd1243dSDimitry Andric
isUimm5XtensaOperand186bdd1243dSDimitry Andric bool isUimm5() const { return isImm(0, 31); }
187bdd1243dSDimitry Andric
isImm8n_7XtensaOperand188bdd1243dSDimitry Andric bool isImm8n_7() const { return isImm(-8, 7); }
189bdd1243dSDimitry Andric
isShimm1_31XtensaOperand190bdd1243dSDimitry Andric bool isShimm1_31() const { return isImm(1, 31); }
191bdd1243dSDimitry Andric
isImm16_31XtensaOperand192bdd1243dSDimitry Andric bool isImm16_31() const { return isImm(16, 31); }
193bdd1243dSDimitry Andric
isImm1_16XtensaOperand194bdd1243dSDimitry Andric bool isImm1_16() const { return isImm(1, 16); }
195bdd1243dSDimitry Andric
isB4constXtensaOperand196bdd1243dSDimitry 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
isB4constuXtensaOperand226bdd1243dSDimitry 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
getStartLocXtensaOperand257bdd1243dSDimitry Andric SMLoc getStartLoc() const override { return StartLoc; }
258bdd1243dSDimitry Andric /// getEndLoc - Gets location of the last token of this operand
getEndLocXtensaOperand259bdd1243dSDimitry Andric SMLoc getEndLoc() const override { return EndLoc; }
260bdd1243dSDimitry Andric
getRegXtensaOperand261*0fca6ea1SDimitry Andric MCRegister getReg() const override {
262bdd1243dSDimitry Andric assert(Kind == Register && "Invalid type access!");
263bdd1243dSDimitry Andric return Reg.RegNum;
264bdd1243dSDimitry Andric }
265bdd1243dSDimitry Andric
getImmXtensaOperand266bdd1243dSDimitry Andric const MCExpr *getImm() const {
267bdd1243dSDimitry Andric assert(Kind == Immediate && "Invalid type access!");
268bdd1243dSDimitry Andric return Imm.Val;
269bdd1243dSDimitry Andric }
270bdd1243dSDimitry Andric
getTokenXtensaOperand271bdd1243dSDimitry Andric StringRef getToken() const {
272bdd1243dSDimitry Andric assert(Kind == Token && "Invalid type access!");
273bdd1243dSDimitry Andric return Tok;
274bdd1243dSDimitry Andric }
275bdd1243dSDimitry Andric
printXtensaOperand276bdd1243dSDimitry 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
createTokenXtensaOperand291bdd1243dSDimitry 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
createRegXtensaOperand299bdd1243dSDimitry 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
createImmXtensaOperand308bdd1243dSDimitry 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
addExprXtensaOperand317bdd1243dSDimitry 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
addRegOperandsXtensaOperand334bdd1243dSDimitry 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
addImmOperandsXtensaOperand339bdd1243dSDimitry 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
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)349bdd1243dSDimitry Andric unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
350bdd1243dSDimitry Andric unsigned Kind) {
351bdd1243dSDimitry Andric return Match_InvalidOperand;
352bdd1243dSDimitry Andric }
353bdd1243dSDimitry Andric
RefineErrorLoc(const SMLoc Loc,const OperandVector & Operands,uint64_t ErrorInfo)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
processInstruction(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)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
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)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
parsePCRelTarget(OperandVector & Operands)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
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)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
parseRegister(OperandVector & Operands,bool AllowParens,bool SR)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
parseImmediate(OperandVector & Operands)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
parseOperandWithModifier(OperandVector & Operands)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.
parseOperand(OperandVector & Operands,StringRef Mnemonic,bool SR)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
ParseInstructionWithSR(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)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
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)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
parseLiteralDirective(SMLoc L)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
parseDirective(AsmToken DirectiveID)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.
LLVMInitializeXtensaAsmParser()819bdd1243dSDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {
820bdd1243dSDimitry Andric RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());
821bdd1243dSDimitry Andric }
822