Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
35295 views
1
//===-- LanaiAsmParser.cpp - Parse Lanai assembly to MCInst instructions --===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "LanaiAluCode.h"
10
#include "LanaiCondCode.h"
11
#include "LanaiInstrInfo.h"
12
#include "MCTargetDesc/LanaiMCExpr.h"
13
#include "TargetInfo/LanaiTargetInfo.h"
14
#include "llvm/ADT/STLExtras.h"
15
#include "llvm/ADT/StringRef.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/MCParser/MCAsmLexer.h"
21
#include "llvm/MC/MCParser/MCAsmParser.h"
22
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
24
#include "llvm/MC/MCStreamer.h"
25
#include "llvm/MC/MCSubtargetInfo.h"
26
#include "llvm/MC/MCSymbol.h"
27
#include "llvm/MC/TargetRegistry.h"
28
#include "llvm/Support/Casting.h"
29
#include "llvm/Support/ErrorHandling.h"
30
#include "llvm/Support/MathExtras.h"
31
#include "llvm/Support/SMLoc.h"
32
#include "llvm/Support/raw_ostream.h"
33
#include <algorithm>
34
#include <cassert>
35
#include <cstddef>
36
#include <cstdint>
37
#include <memory>
38
#include <optional>
39
40
using namespace llvm;
41
42
// Auto-generated by TableGen
43
static MCRegister MatchRegisterName(StringRef Name);
44
45
namespace {
46
47
struct LanaiOperand;
48
49
class LanaiAsmParser : public MCTargetAsmParser {
50
// Parse operands
51
std::unique_ptr<LanaiOperand> parseRegister(bool RestoreOnFailure = false);
52
53
std::unique_ptr<LanaiOperand> parseImmediate();
54
55
std::unique_ptr<LanaiOperand> parseIdentifier();
56
57
unsigned parseAluOperator(bool PreOp, bool PostOp);
58
59
// Split the mnemonic stripping conditional code and quantifiers
60
StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
61
OperandVector *Operands);
62
63
bool parsePrePost(StringRef Type, int *OffsetValue);
64
65
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
66
SMLoc NameLoc, OperandVector &Operands) override;
67
68
bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
69
ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
70
SMLoc &EndLoc) override;
71
72
bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
73
OperandVector &Operands, MCStreamer &Out,
74
uint64_t &ErrorInfo,
75
bool MatchingInlineAsm) override;
76
77
// Auto-generated instruction matching functions
78
#define GET_ASSEMBLER_HEADER
79
#include "LanaiGenAsmMatcher.inc"
80
81
ParseStatus parseOperand(OperandVector *Operands, StringRef Mnemonic);
82
83
ParseStatus parseMemoryOperand(OperandVector &Operands);
84
85
public:
86
LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
87
const MCInstrInfo &MII, const MCTargetOptions &Options)
88
: MCTargetAsmParser(Options, STI, MII), Parser(Parser),
89
Lexer(Parser.getLexer()), SubtargetInfo(STI) {
90
setAvailableFeatures(
91
ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
92
}
93
94
private:
95
MCAsmParser &Parser;
96
MCAsmLexer &Lexer;
97
98
const MCSubtargetInfo &SubtargetInfo;
99
};
100
101
// LanaiOperand - Instances of this class represented a parsed machine
102
// instruction
103
struct LanaiOperand : public MCParsedAsmOperand {
104
enum KindTy {
105
TOKEN,
106
REGISTER,
107
IMMEDIATE,
108
MEMORY_IMM,
109
MEMORY_REG_IMM,
110
MEMORY_REG_REG,
111
} Kind;
112
113
SMLoc StartLoc, EndLoc;
114
115
struct Token {
116
const char *Data;
117
unsigned Length;
118
};
119
120
struct RegOp {
121
unsigned RegNum;
122
};
123
124
struct ImmOp {
125
const MCExpr *Value;
126
};
127
128
struct MemOp {
129
unsigned BaseReg;
130
unsigned OffsetReg;
131
unsigned AluOp;
132
const MCExpr *Offset;
133
};
134
135
union {
136
struct Token Tok;
137
struct RegOp Reg;
138
struct ImmOp Imm;
139
struct MemOp Mem;
140
};
141
142
explicit LanaiOperand(KindTy Kind) : Kind(Kind) {}
143
144
public:
145
// The functions below are used by the autogenerated ASM matcher and hence to
146
// be of the form expected.
147
148
// getStartLoc - Gets location of the first token of this operand
149
SMLoc getStartLoc() const override { return StartLoc; }
150
151
// getEndLoc - Gets location of the last token of this operand
152
SMLoc getEndLoc() const override { return EndLoc; }
153
154
MCRegister getReg() const override {
155
assert(isReg() && "Invalid type access!");
156
return Reg.RegNum;
157
}
158
159
const MCExpr *getImm() const {
160
assert(isImm() && "Invalid type access!");
161
return Imm.Value;
162
}
163
164
StringRef getToken() const {
165
assert(isToken() && "Invalid type access!");
166
return StringRef(Tok.Data, Tok.Length);
167
}
168
169
unsigned getMemBaseReg() const {
170
assert(isMem() && "Invalid type access!");
171
return Mem.BaseReg;
172
}
173
174
unsigned getMemOffsetReg() const {
175
assert(isMem() && "Invalid type access!");
176
return Mem.OffsetReg;
177
}
178
179
const MCExpr *getMemOffset() const {
180
assert(isMem() && "Invalid type access!");
181
return Mem.Offset;
182
}
183
184
unsigned getMemOp() const {
185
assert(isMem() && "Invalid type access!");
186
return Mem.AluOp;
187
}
188
189
// Functions for testing operand type
190
bool isReg() const override { return Kind == REGISTER; }
191
192
bool isImm() const override { return Kind == IMMEDIATE; }
193
194
bool isMem() const override {
195
return isMemImm() || isMemRegImm() || isMemRegReg();
196
}
197
198
bool isMemImm() const { return Kind == MEMORY_IMM; }
199
200
bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
201
202
bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
203
204
bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
205
206
bool isToken() const override { return Kind == TOKEN; }
207
208
bool isBrImm() {
209
if (!isImm())
210
return false;
211
212
// Constant case
213
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value);
214
if (!MCE)
215
return true;
216
int64_t Value = MCE->getValue();
217
// Check if value fits in 25 bits with 2 least significant bits 0.
218
return isShiftedUInt<23, 2>(static_cast<int32_t>(Value));
219
}
220
221
bool isBrTarget() { return isBrImm() || isToken(); }
222
223
bool isCallTarget() { return isImm() || isToken(); }
224
225
bool isHiImm16() {
226
if (!isImm())
227
return false;
228
229
// Constant case
230
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
231
int64_t Value = ConstExpr->getValue();
232
return Value != 0 && isShiftedUInt<16, 16>(Value);
233
}
234
235
// Symbolic reference expression
236
if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
237
return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
238
239
// Binary expression
240
if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
241
if (const LanaiMCExpr *SymbolRefExpr =
242
dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
243
return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
244
245
return false;
246
}
247
248
bool isHiImm16And() {
249
if (!isImm())
250
return false;
251
252
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
253
if (ConstExpr) {
254
int64_t Value = ConstExpr->getValue();
255
// Check if in the form 0xXYZWffff
256
return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);
257
}
258
return false;
259
}
260
261
bool isLoImm16() {
262
if (!isImm())
263
return false;
264
265
// Constant case
266
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
267
int64_t Value = ConstExpr->getValue();
268
// Check if value fits in 16 bits
269
return isUInt<16>(static_cast<int32_t>(Value));
270
}
271
272
// Symbolic reference expression
273
if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
274
return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
275
276
// Binary expression
277
if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
278
if (const LanaiMCExpr *SymbolRefExpr =
279
dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
280
return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
281
282
return false;
283
}
284
285
bool isLoImm16Signed() {
286
if (!isImm())
287
return false;
288
289
// Constant case
290
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
291
int64_t Value = ConstExpr->getValue();
292
// Check if value fits in 16 bits or value of the form 0xffffxyzw
293
return isInt<16>(static_cast<int32_t>(Value));
294
}
295
296
// Symbolic reference expression
297
if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
298
return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
299
300
// Binary expression
301
if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
302
if (const LanaiMCExpr *SymbolRefExpr =
303
dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
304
return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
305
306
return false;
307
}
308
309
bool isLoImm16And() {
310
if (!isImm())
311
return false;
312
313
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
314
if (ConstExpr) {
315
int64_t Value = ConstExpr->getValue();
316
// Check if in the form 0xffffXYZW
317
return ((Value & ~0xffff) == 0xffff0000);
318
}
319
return false;
320
}
321
322
bool isImmShift() {
323
if (!isImm())
324
return false;
325
326
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
327
if (!ConstExpr)
328
return false;
329
int64_t Value = ConstExpr->getValue();
330
return (Value >= -31) && (Value <= 31);
331
}
332
333
bool isLoImm21() {
334
if (!isImm())
335
return false;
336
337
// Constant case
338
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
339
int64_t Value = ConstExpr->getValue();
340
return isUInt<21>(Value);
341
}
342
343
// Symbolic reference expression
344
if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
345
return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
346
if (const MCSymbolRefExpr *SymbolRefExpr =
347
dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
348
return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
349
}
350
351
// Binary expression
352
if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
353
if (const LanaiMCExpr *SymbolRefExpr =
354
dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
355
return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
356
if (const MCSymbolRefExpr *SymbolRefExpr =
357
dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
358
return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
359
}
360
361
return false;
362
}
363
364
bool isImm10() {
365
if (!isImm())
366
return false;
367
368
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
369
if (!ConstExpr)
370
return false;
371
int64_t Value = ConstExpr->getValue();
372
return isInt<10>(Value);
373
}
374
375
bool isCondCode() {
376
if (!isImm())
377
return false;
378
379
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
380
if (!ConstExpr)
381
return false;
382
uint64_t Value = ConstExpr->getValue();
383
// The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the
384
// unsigned value of the immediate is less than LPCC::UNKNOWN (16) then
385
// value corresponds to a valid condition code.
386
return Value < LPCC::UNKNOWN;
387
}
388
389
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
390
// Add as immediates where possible. Null MCExpr = 0
391
if (Expr == nullptr)
392
Inst.addOperand(MCOperand::createImm(0));
393
else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
394
Inst.addOperand(
395
MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
396
else
397
Inst.addOperand(MCOperand::createExpr(Expr));
398
}
399
400
void addRegOperands(MCInst &Inst, unsigned N) const {
401
assert(N == 1 && "Invalid number of operands!");
402
Inst.addOperand(MCOperand::createReg(getReg()));
403
}
404
405
void addImmOperands(MCInst &Inst, unsigned N) const {
406
assert(N == 1 && "Invalid number of operands!");
407
addExpr(Inst, getImm());
408
}
409
410
void addBrTargetOperands(MCInst &Inst, unsigned N) const {
411
assert(N == 1 && "Invalid number of operands!");
412
addExpr(Inst, getImm());
413
}
414
415
void addCallTargetOperands(MCInst &Inst, unsigned N) const {
416
assert(N == 1 && "Invalid number of operands!");
417
addExpr(Inst, getImm());
418
}
419
420
void addCondCodeOperands(MCInst &Inst, unsigned N) const {
421
assert(N == 1 && "Invalid number of operands!");
422
addExpr(Inst, getImm());
423
}
424
425
void addMemImmOperands(MCInst &Inst, unsigned N) const {
426
assert(N == 1 && "Invalid number of operands!");
427
const MCExpr *Expr = getMemOffset();
428
addExpr(Inst, Expr);
429
}
430
431
void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
432
assert(N == 3 && "Invalid number of operands!");
433
Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
434
const MCExpr *Expr = getMemOffset();
435
addExpr(Inst, Expr);
436
Inst.addOperand(MCOperand::createImm(getMemOp()));
437
}
438
439
void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
440
assert(N == 3 && "Invalid number of operands!");
441
Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
442
assert(getMemOffsetReg() != 0 && "Invalid offset");
443
Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
444
Inst.addOperand(MCOperand::createImm(getMemOp()));
445
}
446
447
void addMemSplsOperands(MCInst &Inst, unsigned N) const {
448
if (isMemRegImm())
449
addMemRegImmOperands(Inst, N);
450
if (isMemRegReg())
451
addMemRegRegOperands(Inst, N);
452
}
453
454
void addImmShiftOperands(MCInst &Inst, unsigned N) const {
455
assert(N == 1 && "Invalid number of operands!");
456
addExpr(Inst, getImm());
457
}
458
459
void addImm10Operands(MCInst &Inst, unsigned N) const {
460
assert(N == 1 && "Invalid number of operands!");
461
addExpr(Inst, getImm());
462
}
463
464
void addLoImm16Operands(MCInst &Inst, unsigned N) const {
465
assert(N == 1 && "Invalid number of operands!");
466
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
467
Inst.addOperand(
468
MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
469
else if (isa<LanaiMCExpr>(getImm())) {
470
#ifndef NDEBUG
471
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
472
assert(SymbolRefExpr &&
473
SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
474
#endif
475
Inst.addOperand(MCOperand::createExpr(getImm()));
476
} else if (isa<MCBinaryExpr>(getImm())) {
477
#ifndef NDEBUG
478
const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
479
assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
480
cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
481
LanaiMCExpr::VK_Lanai_ABS_LO);
482
#endif
483
Inst.addOperand(MCOperand::createExpr(getImm()));
484
} else
485
assert(false && "Operand type not supported.");
486
}
487
488
void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
489
assert(N == 1 && "Invalid number of operands!");
490
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
491
Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
492
else
493
assert(false && "Operand type not supported.");
494
}
495
496
void addHiImm16Operands(MCInst &Inst, unsigned N) const {
497
assert(N == 1 && "Invalid number of operands!");
498
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
499
Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
500
else if (isa<LanaiMCExpr>(getImm())) {
501
#ifndef NDEBUG
502
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
503
assert(SymbolRefExpr &&
504
SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
505
#endif
506
Inst.addOperand(MCOperand::createExpr(getImm()));
507
} else if (isa<MCBinaryExpr>(getImm())) {
508
#ifndef NDEBUG
509
const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
510
assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
511
cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
512
LanaiMCExpr::VK_Lanai_ABS_HI);
513
#endif
514
Inst.addOperand(MCOperand::createExpr(getImm()));
515
} else
516
assert(false && "Operand type not supported.");
517
}
518
519
void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
520
assert(N == 1 && "Invalid number of operands!");
521
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
522
Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
523
else
524
assert(false && "Operand type not supported.");
525
}
526
527
void addLoImm21Operands(MCInst &Inst, unsigned N) const {
528
assert(N == 1 && "Invalid number of operands!");
529
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
530
Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
531
else if (isa<LanaiMCExpr>(getImm())) {
532
#ifndef NDEBUG
533
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
534
assert(SymbolRefExpr &&
535
SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
536
#endif
537
Inst.addOperand(MCOperand::createExpr(getImm()));
538
} else if (isa<MCSymbolRefExpr>(getImm())) {
539
#ifndef NDEBUG
540
const MCSymbolRefExpr *SymbolRefExpr =
541
dyn_cast<MCSymbolRefExpr>(getImm());
542
assert(SymbolRefExpr &&
543
SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
544
#endif
545
Inst.addOperand(MCOperand::createExpr(getImm()));
546
} else if (isa<MCBinaryExpr>(getImm())) {
547
#ifndef NDEBUG
548
const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
549
assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
550
cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
551
LanaiMCExpr::VK_Lanai_None);
552
#endif
553
Inst.addOperand(MCOperand::createExpr(getImm()));
554
} else
555
assert(false && "Operand type not supported.");
556
}
557
558
void print(raw_ostream &OS) const override {
559
switch (Kind) {
560
case IMMEDIATE:
561
OS << "Imm: " << getImm() << "\n";
562
break;
563
case TOKEN:
564
OS << "Token: " << getToken() << "\n";
565
break;
566
case REGISTER:
567
OS << "Reg: %r" << getReg() << "\n";
568
break;
569
case MEMORY_IMM:
570
OS << "MemImm: " << *getMemOffset() << "\n";
571
break;
572
case MEMORY_REG_IMM:
573
OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
574
break;
575
case MEMORY_REG_REG:
576
assert(getMemOffset() == nullptr);
577
OS << "MemRegReg: " << getMemBaseReg() << "+"
578
<< "%r" << getMemOffsetReg() << "\n";
579
break;
580
}
581
}
582
583
static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
584
auto Op = std::make_unique<LanaiOperand>(TOKEN);
585
Op->Tok.Data = Str.data();
586
Op->Tok.Length = Str.size();
587
Op->StartLoc = Start;
588
Op->EndLoc = Start;
589
return Op;
590
}
591
592
static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start,
593
SMLoc End) {
594
auto Op = std::make_unique<LanaiOperand>(REGISTER);
595
Op->Reg.RegNum = RegNum;
596
Op->StartLoc = Start;
597
Op->EndLoc = End;
598
return Op;
599
}
600
601
static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
602
SMLoc Start, SMLoc End) {
603
auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
604
Op->Imm.Value = Value;
605
Op->StartLoc = Start;
606
Op->EndLoc = End;
607
return Op;
608
}
609
610
static std::unique_ptr<LanaiOperand>
611
MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
612
const MCExpr *Imm = Op->getImm();
613
Op->Kind = MEMORY_IMM;
614
Op->Mem.BaseReg = 0;
615
Op->Mem.AluOp = LPAC::ADD;
616
Op->Mem.OffsetReg = 0;
617
Op->Mem.Offset = Imm;
618
return Op;
619
}
620
621
static std::unique_ptr<LanaiOperand>
622
MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
623
unsigned AluOp) {
624
unsigned OffsetReg = Op->getReg();
625
Op->Kind = MEMORY_REG_REG;
626
Op->Mem.BaseReg = BaseReg;
627
Op->Mem.AluOp = AluOp;
628
Op->Mem.OffsetReg = OffsetReg;
629
Op->Mem.Offset = nullptr;
630
return Op;
631
}
632
633
static std::unique_ptr<LanaiOperand>
634
MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
635
unsigned AluOp) {
636
const MCExpr *Imm = Op->getImm();
637
Op->Kind = MEMORY_REG_IMM;
638
Op->Mem.BaseReg = BaseReg;
639
Op->Mem.AluOp = AluOp;
640
Op->Mem.OffsetReg = 0;
641
Op->Mem.Offset = Imm;
642
return Op;
643
}
644
};
645
646
} // end anonymous namespace
647
648
bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
649
OperandVector &Operands,
650
MCStreamer &Out,
651
uint64_t &ErrorInfo,
652
bool MatchingInlineAsm) {
653
MCInst Inst;
654
SMLoc ErrorLoc;
655
656
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
657
case Match_Success:
658
Out.emitInstruction(Inst, SubtargetInfo);
659
Opcode = Inst.getOpcode();
660
return false;
661
case Match_MissingFeature:
662
return Error(IdLoc, "Instruction use requires option to be enabled");
663
case Match_MnemonicFail:
664
return Error(IdLoc, "Unrecognized instruction mnemonic");
665
case Match_InvalidOperand: {
666
ErrorLoc = IdLoc;
667
if (ErrorInfo != ~0U) {
668
if (ErrorInfo >= Operands.size())
669
return Error(IdLoc, "Too few operands for instruction");
670
671
ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
672
if (ErrorLoc == SMLoc())
673
ErrorLoc = IdLoc;
674
}
675
return Error(ErrorLoc, "Invalid operand for instruction");
676
}
677
default:
678
break;
679
}
680
681
llvm_unreachable("Unknown match type detected!");
682
}
683
684
// Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
685
// backwards compatible with GCC and the different ways inline assembly is
686
// handled.
687
// TODO: see if there isn't a better way to do this.
688
std::unique_ptr<LanaiOperand>
689
LanaiAsmParser::parseRegister(bool RestoreOnFailure) {
690
SMLoc Start = Parser.getTok().getLoc();
691
SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
692
std::optional<AsmToken> PercentTok;
693
694
unsigned RegNum;
695
// Eat the '%'.
696
if (Lexer.getKind() == AsmToken::Percent) {
697
PercentTok = Parser.getTok();
698
Parser.Lex();
699
}
700
if (Lexer.getKind() == AsmToken::Identifier) {
701
RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
702
if (RegNum == 0) {
703
if (PercentTok && RestoreOnFailure)
704
Lexer.UnLex(*PercentTok);
705
return nullptr;
706
}
707
Parser.Lex(); // Eat identifier token
708
return LanaiOperand::createReg(RegNum, Start, End);
709
}
710
if (PercentTok && RestoreOnFailure)
711
Lexer.UnLex(*PercentTok);
712
return nullptr;
713
}
714
715
bool LanaiAsmParser::parseRegister(MCRegister &RegNum, SMLoc &StartLoc,
716
SMLoc &EndLoc) {
717
const AsmToken &Tok = getParser().getTok();
718
StartLoc = Tok.getLoc();
719
EndLoc = Tok.getEndLoc();
720
std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/false);
721
if (Op != nullptr)
722
RegNum = Op->getReg();
723
return (Op == nullptr);
724
}
725
726
ParseStatus LanaiAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
727
SMLoc &EndLoc) {
728
const AsmToken &Tok = getParser().getTok();
729
StartLoc = Tok.getLoc();
730
EndLoc = Tok.getEndLoc();
731
std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/true);
732
if (Op == nullptr)
733
return ParseStatus::NoMatch;
734
Reg = Op->getReg();
735
return ParseStatus::Success;
736
}
737
738
std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
739
SMLoc Start = Parser.getTok().getLoc();
740
SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
741
const MCExpr *Res, *RHS = nullptr;
742
LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;
743
744
if (Lexer.getKind() != AsmToken::Identifier)
745
return nullptr;
746
747
StringRef Identifier;
748
if (Parser.parseIdentifier(Identifier))
749
return nullptr;
750
751
// Check if identifier has a modifier
752
if (Identifier.equals_insensitive("hi"))
753
Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
754
else if (Identifier.equals_insensitive("lo"))
755
Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
756
757
// If the identifier corresponds to a variant then extract the real
758
// identifier.
759
if (Kind != LanaiMCExpr::VK_Lanai_None) {
760
if (Lexer.getKind() != AsmToken::LParen) {
761
Error(Lexer.getLoc(), "Expected '('");
762
return nullptr;
763
}
764
Lexer.Lex(); // lex '('
765
766
// Parse identifier
767
if (Parser.parseIdentifier(Identifier))
768
return nullptr;
769
}
770
771
// If addition parse the RHS.
772
if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
773
return nullptr;
774
775
// For variants parse the final ')'
776
if (Kind != LanaiMCExpr::VK_Lanai_None) {
777
if (Lexer.getKind() != AsmToken::RParen) {
778
Error(Lexer.getLoc(), "Expected ')'");
779
return nullptr;
780
}
781
Lexer.Lex(); // lex ')'
782
}
783
784
End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
785
MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
786
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
787
Res = LanaiMCExpr::create(Kind, Expr, getContext());
788
789
// Nest if this was an addition
790
if (RHS)
791
Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
792
793
return LanaiOperand::createImm(Res, Start, End);
794
}
795
796
std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
797
SMLoc Start = Parser.getTok().getLoc();
798
SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
799
800
const MCExpr *ExprVal;
801
switch (Lexer.getKind()) {
802
case AsmToken::Identifier:
803
return parseIdentifier();
804
case AsmToken::Plus:
805
case AsmToken::Minus:
806
case AsmToken::Integer:
807
case AsmToken::Dot:
808
if (!Parser.parseExpression(ExprVal))
809
return LanaiOperand::createImm(ExprVal, Start, End);
810
[[fallthrough]];
811
default:
812
return nullptr;
813
}
814
}
815
816
static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
817
if (PreOp)
818
return LPAC::makePreOp(AluCode);
819
if (PostOp)
820
return LPAC::makePostOp(AluCode);
821
return AluCode;
822
}
823
824
unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
825
StringRef IdString;
826
Parser.parseIdentifier(IdString);
827
unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
828
if (AluCode == LPAC::UNKNOWN) {
829
Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
830
return 0;
831
}
832
return AluCode;
833
}
834
835
static int SizeForSuffix(StringRef T) {
836
return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
837
}
838
839
bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
840
bool PreOrPost = false;
841
if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
842
PreOrPost = true;
843
if (Lexer.is(AsmToken::Minus))
844
*OffsetValue = -SizeForSuffix(Type);
845
else if (Lexer.is(AsmToken::Plus))
846
*OffsetValue = SizeForSuffix(Type);
847
else
848
return false;
849
850
// Eat the '-' '-' or '+' '+'
851
Parser.Lex();
852
Parser.Lex();
853
} else if (Lexer.is(AsmToken::Star)) {
854
Parser.Lex(); // Eat the '*'
855
PreOrPost = true;
856
}
857
858
return PreOrPost;
859
}
860
861
bool shouldBeSls(const LanaiOperand &Op) {
862
// The instruction should be encoded as an SLS if the constant is word
863
// aligned and will fit in 21 bits
864
if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
865
int64_t Value = ConstExpr->getValue();
866
return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
867
}
868
// The instruction should be encoded as an SLS if the operand is a symbolic
869
// reference with no variant.
870
if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
871
return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
872
// The instruction should be encoded as an SLS if the operand is a binary
873
// expression with the left-hand side being a symbolic reference with no
874
// variant.
875
if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
876
const LanaiMCExpr *LHSSymbolRefExpr =
877
dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
878
return (LHSSymbolRefExpr &&
879
LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
880
}
881
return false;
882
}
883
884
// Matches memory operand. Returns true if error encountered.
885
ParseStatus LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
886
// Try to match a memory operand.
887
// The memory operands are of the form:
888
// (1) Register|Immediate|'' '[' '*'? Register '*'? ']' or
889
// ^
890
// (2) '[' '*'? Register '*'? AluOperator Register ']'
891
// ^
892
// (3) '[' '--'|'++' Register '--'|'++' ']'
893
//
894
// (4) '[' Immediate ']' (for SLS)
895
896
// Store the type for use in parsing pre/post increment/decrement operators
897
StringRef Type;
898
if (Operands[0]->isToken())
899
Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
900
901
// Use 0 if no offset given
902
int OffsetValue = 0;
903
unsigned BaseReg = 0;
904
unsigned AluOp = LPAC::ADD;
905
bool PostOp = false, PreOp = false;
906
907
// Try to parse the offset
908
std::unique_ptr<LanaiOperand> Op = parseRegister();
909
if (!Op)
910
Op = parseImmediate();
911
912
// Only continue if next token is '['
913
if (Lexer.isNot(AsmToken::LBrac)) {
914
if (!Op)
915
return ParseStatus::NoMatch;
916
917
// The start of this custom parsing overlaps with register/immediate so
918
// consider this as a successful match of an operand of that type as the
919
// token stream can't be rewound to allow them to match separately.
920
Operands.push_back(std::move(Op));
921
return ParseStatus::Success;
922
}
923
924
Parser.Lex(); // Eat the '['.
925
std::unique_ptr<LanaiOperand> Offset = nullptr;
926
if (Op)
927
Offset.swap(Op);
928
929
// Determine if a pre operation
930
PreOp = parsePrePost(Type, &OffsetValue);
931
932
Op = parseRegister();
933
if (!Op) {
934
if (!Offset) {
935
if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
936
Parser.Lex(); // Eat the ']'
937
938
// Memory address operations aligned to word boundary are encoded as
939
// SLS, the rest as RM.
940
if (shouldBeSls(*Op)) {
941
Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
942
} else {
943
if (!Op->isLoImm16Signed())
944
return Error(Parser.getTok().getLoc(),
945
"Memory address is not word aligned and larger than "
946
"class RM can handle");
947
Operands.push_back(LanaiOperand::MorphToMemRegImm(
948
Lanai::R0, std::move(Op), LPAC::ADD));
949
}
950
return ParseStatus::Success;
951
}
952
}
953
954
return Error(Parser.getTok().getLoc(),
955
"Unknown operand, expected register or immediate");
956
}
957
BaseReg = Op->getReg();
958
959
// Determine if a post operation
960
if (!PreOp)
961
PostOp = parsePrePost(Type, &OffsetValue);
962
963
// If ] match form (1) else match form (2)
964
if (Lexer.is(AsmToken::RBrac)) {
965
Parser.Lex(); // Eat the ']'.
966
if (!Offset) {
967
SMLoc Start = Parser.getTok().getLoc();
968
SMLoc End =
969
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
970
const MCConstantExpr *OffsetConstExpr =
971
MCConstantExpr::create(OffsetValue, getContext());
972
Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
973
}
974
} else {
975
if (Offset || OffsetValue != 0)
976
return Error(Parser.getTok().getLoc(), "Expected ']'");
977
978
// Parse operator
979
AluOp = parseAluOperator(PreOp, PostOp);
980
981
// Second form requires offset register
982
Offset = parseRegister();
983
if (!BaseReg || Lexer.isNot(AsmToken::RBrac))
984
return Error(Parser.getTok().getLoc(), "Expected ']'");
985
Parser.Lex(); // Eat the ']'.
986
}
987
988
// First form has addition as operator. Add pre- or post-op indicator as
989
// needed.
990
AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
991
992
// Ensure immediate offset is not too large
993
if (Offset->isImm() && !Offset->isLoImm16Signed())
994
return Error(Parser.getTok().getLoc(),
995
"Memory address is not word aligned and larger than class RM "
996
"can handle");
997
998
Operands.push_back(
999
Offset->isImm()
1000
? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
1001
: LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
1002
1003
return ParseStatus::Success;
1004
}
1005
1006
// Looks at a token type and creates the relevant operand from this
1007
// information, adding to operands.
1008
// If operand was parsed, returns false, else true.
1009
ParseStatus LanaiAsmParser::parseOperand(OperandVector *Operands,
1010
StringRef Mnemonic) {
1011
// Check if the current operand has a custom associated parser, if so, try to
1012
// custom parse the operand, or fallback to the general approach.
1013
ParseStatus Result = MatchOperandParserImpl(*Operands, Mnemonic);
1014
1015
if (Result.isSuccess())
1016
return Result;
1017
if (Result.isFailure()) {
1018
Parser.eatToEndOfStatement();
1019
return Result;
1020
}
1021
1022
// Attempt to parse token as register
1023
std::unique_ptr<LanaiOperand> Op = parseRegister();
1024
1025
// Attempt to parse token as immediate
1026
if (!Op)
1027
Op = parseImmediate();
1028
1029
// If the token could not be parsed then fail
1030
if (!Op) {
1031
Error(Parser.getTok().getLoc(), "Unknown operand");
1032
Parser.eatToEndOfStatement();
1033
return ParseStatus::Failure;
1034
}
1035
1036
// Push back parsed operand into list of operands
1037
Operands->push_back(std::move(Op));
1038
1039
return ParseStatus::Success;
1040
}
1041
1042
// Split the mnemonic into ASM operand, conditional code and instruction
1043
// qualifier (half-word, byte).
1044
StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1045
OperandVector *Operands) {
1046
size_t Next = Name.find('.');
1047
1048
StringRef Mnemonic = Name;
1049
1050
bool IsBRR = Mnemonic.consume_back(".r");
1051
1052
// Match b?? and s?? (BR, BRR, and SCC instruction classes).
1053
if (Mnemonic[0] == 'b' ||
1054
(Mnemonic[0] == 's' && !Mnemonic.starts_with("sel") &&
1055
!Mnemonic.starts_with("st"))) {
1056
// Parse instructions with a conditional code. For example, 'bne' is
1057
// converted into two operands 'b' and 'ne'.
1058
LPCC::CondCode CondCode =
1059
LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1060
if (CondCode != LPCC::UNKNOWN) {
1061
Mnemonic = Mnemonic.slice(0, 1);
1062
Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1063
Operands->push_back(LanaiOperand::createImm(
1064
MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1065
if (IsBRR) {
1066
Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1067
}
1068
return Mnemonic;
1069
}
1070
}
1071
1072
// Parse other instructions with condition codes (RR instructions).
1073
// We ignore .f here and assume they are flag-setting operations, not
1074
// conditional codes (except for select instructions where flag-setting
1075
// variants are not yet implemented).
1076
if (Mnemonic.starts_with("sel") ||
1077
(!Mnemonic.ends_with(".f") && !Mnemonic.starts_with("st"))) {
1078
LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
1079
if (CondCode != LPCC::UNKNOWN) {
1080
size_t Next = Mnemonic.rfind('.', Name.size());
1081
// 'sel' doesn't use a predicate operand whose printer adds the period,
1082
// but instead has the period as part of the identifier (i.e., 'sel.' is
1083
// expected by the generated matcher). If the mnemonic starts with 'sel'
1084
// then include the period as part of the mnemonic, else don't include it
1085
// as part of the mnemonic.
1086
if (Mnemonic.starts_with("sel")) {
1087
Mnemonic = Mnemonic.substr(0, Next + 1);
1088
} else {
1089
Mnemonic = Mnemonic.substr(0, Next);
1090
}
1091
Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1092
Operands->push_back(LanaiOperand::createImm(
1093
MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1094
return Mnemonic;
1095
}
1096
}
1097
1098
Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1099
if (IsBRR) {
1100
Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1101
}
1102
1103
return Mnemonic;
1104
}
1105
1106
static bool IsMemoryAssignmentError(const OperandVector &Operands) {
1107
// Detects if a memory operation has an erroneous base register modification.
1108
// Memory operations are detected by matching the types of operands.
1109
//
1110
// TODO: This test is focussed on one specific instance (ld/st).
1111
// Extend it to handle more cases or be more robust.
1112
bool Modifies = false;
1113
1114
int Offset = 0;
1115
1116
if (Operands.size() < 5)
1117
return false;
1118
else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1119
Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1120
Offset = 0;
1121
else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1122
Operands[2]->isReg() && Operands[3]->isImm() &&
1123
Operands[4]->isImm() && Operands[5]->isReg())
1124
Offset = 1;
1125
else
1126
return false;
1127
1128
int PossibleAluOpIdx = Offset + 3;
1129
int PossibleBaseIdx = Offset + 1;
1130
int PossibleDestIdx = Offset + 4;
1131
if (LanaiOperand *PossibleAluOp =
1132
static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1133
if (PossibleAluOp->isImm())
1134
if (const MCConstantExpr *ConstExpr =
1135
dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1136
Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1137
return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1138
Operands[PossibleDestIdx]->isReg() &&
1139
Operands[PossibleBaseIdx]->getReg() ==
1140
Operands[PossibleDestIdx]->getReg();
1141
}
1142
1143
static bool IsRegister(const MCParsedAsmOperand &op) {
1144
return static_cast<const LanaiOperand &>(op).isReg();
1145
}
1146
1147
static bool MaybePredicatedInst(const OperandVector &Operands) {
1148
if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1149
!IsRegister(*Operands[2]))
1150
return false;
1151
return StringSwitch<bool>(
1152
static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1153
.StartsWith("addc", true)
1154
.StartsWith("add", true)
1155
.StartsWith("and", true)
1156
.StartsWith("sh", true)
1157
.StartsWith("subb", true)
1158
.StartsWith("sub", true)
1159
.StartsWith("or", true)
1160
.StartsWith("xor", true)
1161
.Default(false);
1162
}
1163
1164
bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/,
1165
StringRef Name, SMLoc NameLoc,
1166
OperandVector &Operands) {
1167
// First operand is token for instruction
1168
StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1169
1170
// If there are no more operands, then finish
1171
if (Lexer.is(AsmToken::EndOfStatement))
1172
return false;
1173
1174
// Parse first operand
1175
if (!parseOperand(&Operands, Mnemonic).isSuccess())
1176
return true;
1177
1178
// If it is a st instruction with one 1 operand then it is a "store true".
1179
// Transform <"st"> to <"s">, <LPCC:ICC_T>
1180
if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1181
Operands.size() == 2) {
1182
Operands.erase(Operands.begin(), Operands.begin() + 1);
1183
Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1184
Operands.insert(Operands.begin() + 1,
1185
LanaiOperand::createImm(
1186
MCConstantExpr::create(LPCC::ICC_T, getContext()),
1187
NameLoc, NameLoc));
1188
}
1189
1190
// If the instruction is a bt instruction with 1 operand (in assembly) then it
1191
// is an unconditional branch instruction and the first two elements of
1192
// operands need to be merged.
1193
if (Lexer.is(AsmToken::EndOfStatement) && Name.starts_with("bt") &&
1194
Operands.size() == 3) {
1195
Operands.erase(Operands.begin(), Operands.begin() + 2);
1196
Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1197
}
1198
1199
// Parse until end of statement, consuming commas between operands
1200
while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1201
// Consume comma token
1202
Lex();
1203
1204
// Parse next operand
1205
if (!parseOperand(&Operands, Mnemonic).isSuccess())
1206
return true;
1207
}
1208
1209
if (IsMemoryAssignmentError(Operands)) {
1210
Error(Parser.getTok().getLoc(),
1211
"the destination register can't equal the base register in an "
1212
"instruction that modifies the base register.");
1213
return true;
1214
}
1215
1216
// Insert always true operand for instruction that may be predicated but
1217
// are not. Currently the autogenerated parser always expects a predicate.
1218
if (MaybePredicatedInst(Operands)) {
1219
Operands.insert(Operands.begin() + 1,
1220
LanaiOperand::createImm(
1221
MCConstantExpr::create(LPCC::ICC_T, getContext()),
1222
NameLoc, NameLoc));
1223
}
1224
1225
return false;
1226
}
1227
1228
#define GET_REGISTER_MATCHER
1229
#define GET_MATCHER_IMPLEMENTATION
1230
#include "LanaiGenAsmMatcher.inc"
1231
1232
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmParser() {
1233
RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget());
1234
}
1235
1236