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