Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
35294 views
1
//===-- M68kAsmParser.cpp - Parse M68k 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 "M68kInstrInfo.h"
10
#include "M68kRegisterInfo.h"
11
#include "TargetInfo/M68kTargetInfo.h"
12
13
#include "llvm/MC/MCContext.h"
14
#include "llvm/MC/MCParser/MCAsmLexer.h"
15
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
16
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
17
#include "llvm/MC/MCStreamer.h"
18
#include "llvm/MC/TargetRegistry.h"
19
20
#include <sstream>
21
22
#define DEBUG_TYPE "m68k-asm-parser"
23
24
using namespace llvm;
25
26
static cl::opt<bool> RegisterPrefixOptional(
27
"m68k-register-prefix-optional", cl::Hidden,
28
cl::desc("Enable specifying registers without the % prefix"),
29
cl::init(false));
30
31
namespace {
32
/// Parses M68k assembly from a stream.
33
class M68kAsmParser : public MCTargetAsmParser {
34
const MCSubtargetInfo &STI;
35
MCAsmParser &Parser;
36
const MCRegisterInfo *MRI;
37
38
#define GET_ASSEMBLER_HEADER
39
#include "M68kGenAsmMatcher.inc"
40
41
// Helpers for Match&Emit.
42
bool invalidOperand(const SMLoc &Loc, const OperandVector &Operands,
43
const uint64_t &ErrorInfo);
44
bool missingFeature(const SMLoc &Loc, const uint64_t &ErrorInfo);
45
bool emit(MCInst &Inst, SMLoc const &Loc, MCStreamer &Out) const;
46
bool parseRegisterName(MCRegister &RegNo, SMLoc Loc, StringRef RegisterName);
47
ParseStatus parseRegister(MCRegister &RegNo);
48
49
// Parser functions.
50
void eatComma();
51
52
bool isExpr();
53
ParseStatus parseImm(OperandVector &Operands);
54
ParseStatus parseMemOp(OperandVector &Operands);
55
ParseStatus parseRegOrMoveMask(OperandVector &Operands);
56
57
public:
58
M68kAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
59
const MCInstrInfo &MII, const MCTargetOptions &Options)
60
: MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
61
MCAsmParserExtension::Initialize(Parser);
62
MRI = getContext().getRegisterInfo();
63
64
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
65
}
66
67
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
68
unsigned Kind) override;
69
bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
70
ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
71
SMLoc &EndLoc) override;
72
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
73
SMLoc NameLoc, OperandVector &Operands) override;
74
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
75
OperandVector &Operands, MCStreamer &Out,
76
uint64_t &ErrorInfo,
77
bool MatchingInlineAsm) override;
78
};
79
80
struct M68kMemOp {
81
enum class Kind {
82
Addr,
83
RegMask,
84
Reg,
85
RegIndirect,
86
RegPostIncrement,
87
RegPreDecrement,
88
RegIndirectDisplacement,
89
RegIndirectDisplacementIndex,
90
};
91
92
// These variables are used for the following forms:
93
// Addr: (OuterDisp)
94
// RegMask: RegMask (as register mask)
95
// Reg: %OuterReg
96
// RegIndirect: (%OuterReg)
97
// RegPostIncrement: (%OuterReg)+
98
// RegPreDecrement: -(%OuterReg)
99
// RegIndirectDisplacement: OuterDisp(%OuterReg)
100
// RegIndirectDisplacementIndex:
101
// OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)
102
103
Kind Op;
104
MCRegister OuterReg;
105
MCRegister InnerReg;
106
const MCExpr *OuterDisp;
107
const MCExpr *InnerDisp;
108
uint8_t Size : 4;
109
uint8_t Scale : 4;
110
const MCExpr *Expr;
111
uint16_t RegMask;
112
113
M68kMemOp() {}
114
M68kMemOp(Kind Op) : Op(Op) {}
115
116
void print(raw_ostream &OS) const;
117
};
118
119
/// An parsed M68k assembly operand.
120
class M68kOperand : public MCParsedAsmOperand {
121
typedef MCParsedAsmOperand Base;
122
123
enum class KindTy {
124
Invalid,
125
Token,
126
Imm,
127
MemOp,
128
};
129
130
KindTy Kind;
131
SMLoc Start, End;
132
union {
133
StringRef Token;
134
const MCExpr *Expr;
135
M68kMemOp MemOp;
136
};
137
138
template <unsigned N> bool isAddrN() const;
139
140
public:
141
M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)
142
: Base(), Kind(Kind), Start(Start), End(End) {}
143
144
SMLoc getStartLoc() const override { return Start; }
145
SMLoc getEndLoc() const override { return End; }
146
147
void print(raw_ostream &OS) const override;
148
149
bool isMem() const override { return false; }
150
bool isMemOp() const { return Kind == KindTy::MemOp; }
151
152
static void addExpr(MCInst &Inst, const MCExpr *Expr);
153
154
// Reg
155
bool isReg() const override;
156
bool isAReg() const;
157
bool isDReg() const;
158
bool isFPDReg() const;
159
bool isFPCReg() const;
160
MCRegister getReg() const override;
161
void addRegOperands(MCInst &Inst, unsigned N) const;
162
163
static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start,
164
SMLoc End);
165
166
// Token
167
bool isToken() const override;
168
StringRef getToken() const;
169
static std::unique_ptr<M68kOperand> createToken(StringRef Token, SMLoc Start,
170
SMLoc End);
171
172
// Imm
173
bool isImm() const override;
174
void addImmOperands(MCInst &Inst, unsigned N) const;
175
176
static std::unique_ptr<M68kOperand> createImm(const MCExpr *Expr, SMLoc Start,
177
SMLoc End);
178
179
// Imm for TRAP instruction
180
bool isTrapImm() const;
181
// Imm for BKPT instruction
182
bool isBkptImm() const;
183
184
// MoveMask
185
bool isMoveMask() const;
186
void addMoveMaskOperands(MCInst &Inst, unsigned N) const;
187
188
// Addr
189
bool isAddr() const;
190
bool isAddr8() const { return isAddrN<8>(); }
191
bool isAddr16() const { return isAddrN<16>(); }
192
bool isAddr32() const { return isAddrN<32>(); }
193
void addAddrOperands(MCInst &Inst, unsigned N) const;
194
195
// ARI
196
bool isARI() const;
197
void addARIOperands(MCInst &Inst, unsigned N) const;
198
199
// ARID
200
bool isARID() const;
201
void addARIDOperands(MCInst &Inst, unsigned N) const;
202
203
// ARII
204
bool isARII() const;
205
void addARIIOperands(MCInst &Inst, unsigned N) const;
206
207
// ARIPD
208
bool isARIPD() const;
209
void addARIPDOperands(MCInst &Inst, unsigned N) const;
210
211
// ARIPI
212
bool isARIPI() const;
213
void addARIPIOperands(MCInst &Inst, unsigned N) const;
214
215
// PCD
216
bool isPCD() const;
217
void addPCDOperands(MCInst &Inst, unsigned N) const;
218
219
// PCI
220
bool isPCI() const;
221
void addPCIOperands(MCInst &Inst, unsigned N) const;
222
};
223
224
} // end anonymous namespace.
225
226
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() {
227
RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget());
228
}
229
230
#define GET_REGISTER_MATCHER
231
#define GET_MATCHER_IMPLEMENTATION
232
#include "M68kGenAsmMatcher.inc"
233
234
static inline unsigned getRegisterByIndex(unsigned RegisterIndex) {
235
static unsigned RegistersByIndex[] = {
236
M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
237
M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
238
M68k::A4, M68k::A5, M68k::A6, M68k::SP, M68k::FP0, M68k::FP1,
239
M68k::FP2, M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7};
240
assert(RegisterIndex <=
241
sizeof(RegistersByIndex) / sizeof(RegistersByIndex[0]));
242
return RegistersByIndex[RegisterIndex];
243
}
244
245
static inline unsigned getRegisterIndex(unsigned Register) {
246
if (Register >= M68k::D0 && Register <= M68k::D7)
247
return Register - M68k::D0;
248
if (Register >= M68k::A0 && Register <= M68k::A6)
249
return Register - M68k::A0 + 8;
250
if (Register >= M68k::FP0 && Register <= M68k::FP7)
251
return Register - M68k::FP0 + 16;
252
253
switch (Register) {
254
case M68k::SP:
255
// SP is sadly not contiguous with the rest of the An registers
256
return 15;
257
258
// We don't care about the indices of these registers.
259
case M68k::PC:
260
case M68k::CCR:
261
case M68k::FPC:
262
case M68k::FPS:
263
case M68k::FPIAR:
264
return UINT_MAX;
265
266
default:
267
llvm_unreachable("unexpected register number");
268
}
269
}
270
271
void M68kMemOp::print(raw_ostream &OS) const {
272
switch (Op) {
273
case Kind::Addr:
274
OS << OuterDisp;
275
break;
276
case Kind::RegMask:
277
OS << "RegMask(" << format("%04x", RegMask) << ")";
278
break;
279
case Kind::Reg:
280
OS << '%' << OuterReg;
281
break;
282
case Kind::RegIndirect:
283
OS << "(%" << OuterReg << ')';
284
break;
285
case Kind::RegPostIncrement:
286
OS << "(%" << OuterReg << ")+";
287
break;
288
case Kind::RegPreDecrement:
289
OS << "-(%" << OuterReg << ")";
290
break;
291
case Kind::RegIndirectDisplacement:
292
OS << OuterDisp << "(%" << OuterReg << ")";
293
break;
294
case Kind::RegIndirectDisplacementIndex:
295
OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size
296
<< ", " << InnerDisp << ")";
297
break;
298
}
299
}
300
301
void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {
302
if (auto Const = dyn_cast<MCConstantExpr>(Expr)) {
303
Inst.addOperand(MCOperand::createImm(Const->getValue()));
304
return;
305
}
306
307
Inst.addOperand(MCOperand::createExpr(Expr));
308
}
309
310
// Reg
311
bool M68kOperand::isReg() const {
312
return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
313
}
314
315
MCRegister M68kOperand::getReg() const {
316
assert(isReg());
317
return MemOp.OuterReg;
318
}
319
320
void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {
321
assert(isReg() && "wrong operand kind");
322
assert((N == 1) && "can only handle one register operand");
323
324
Inst.addOperand(MCOperand::createReg(getReg()));
325
}
326
327
std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,
328
SMLoc Start, SMLoc End) {
329
auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start, End);
330
Op->MemOp = MemOp;
331
return Op;
332
}
333
334
// Token
335
bool M68kOperand::isToken() const { return Kind == KindTy::Token; }
336
StringRef M68kOperand::getToken() const {
337
assert(isToken());
338
return Token;
339
}
340
341
std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,
342
SMLoc Start, SMLoc End) {
343
auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start, End);
344
Op->Token = Token;
345
return Op;
346
}
347
348
// Imm
349
bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }
350
void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {
351
assert(isImm() && "wrong operand kind");
352
assert((N == 1) && "can only handle one register operand");
353
354
M68kOperand::addExpr(Inst, Expr);
355
}
356
357
std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,
358
SMLoc Start, SMLoc End) {
359
auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start, End);
360
Op->Expr = Expr;
361
return Op;
362
}
363
364
bool M68kOperand::isTrapImm() const {
365
int64_t Value;
366
if (!isImm() || !Expr->evaluateAsAbsolute(Value))
367
return false;
368
369
return isUInt<4>(Value);
370
}
371
372
bool M68kOperand::isBkptImm() const {
373
int64_t Value;
374
if (!isImm() || !Expr->evaluateAsAbsolute(Value))
375
return false;
376
377
return isUInt<3>(Value);
378
}
379
380
// MoveMask
381
bool M68kOperand::isMoveMask() const {
382
if (!isMemOp())
383
return false;
384
385
if (MemOp.Op == M68kMemOp::Kind::RegMask)
386
return true;
387
388
if (MemOp.Op != M68kMemOp::Kind::Reg)
389
return false;
390
391
// Only regular address / data registers are allowed to be used
392
// in register masks.
393
return getRegisterIndex(MemOp.OuterReg) < 16;
394
}
395
396
void M68kOperand::addMoveMaskOperands(MCInst &Inst, unsigned N) const {
397
assert(isMoveMask() && "wrong operand kind");
398
assert((N == 1) && "can only handle one immediate operand");
399
400
uint16_t MoveMask = MemOp.RegMask;
401
if (MemOp.Op == M68kMemOp::Kind::Reg)
402
MoveMask = 1 << getRegisterIndex(MemOp.OuterReg);
403
404
Inst.addOperand(MCOperand::createImm(MoveMask));
405
}
406
407
// Addr
408
bool M68kOperand::isAddr() const {
409
return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
410
}
411
// TODO: Maybe we can also store the size of OuterDisp
412
// in Size?
413
template <unsigned N> bool M68kOperand::isAddrN() const {
414
if (isAddr()) {
415
int64_t Res;
416
if (MemOp.OuterDisp->evaluateAsAbsolute(Res))
417
return isInt<N>(Res);
418
return true;
419
}
420
return false;
421
}
422
void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
423
M68kOperand::addExpr(Inst, MemOp.OuterDisp);
424
}
425
426
// ARI
427
bool M68kOperand::isARI() const {
428
return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
429
M68k::AR32RegClass.contains(MemOp.OuterReg);
430
}
431
void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
432
Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
433
}
434
435
// ARID
436
bool M68kOperand::isARID() const {
437
return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
438
M68k::AR32RegClass.contains(MemOp.OuterReg);
439
}
440
void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {
441
M68kOperand::addExpr(Inst, MemOp.OuterDisp);
442
Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
443
}
444
445
// ARII
446
bool M68kOperand::isARII() const {
447
return isMemOp() &&
448
MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
449
M68k::AR32RegClass.contains(MemOp.OuterReg);
450
}
451
void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {
452
M68kOperand::addExpr(Inst, MemOp.OuterDisp);
453
Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
454
Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
455
}
456
457
// ARIPD
458
bool M68kOperand::isARIPD() const {
459
return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
460
M68k::AR32RegClass.contains(MemOp.OuterReg);
461
}
462
void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
463
Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
464
}
465
466
// ARIPI
467
bool M68kOperand::isARIPI() const {
468
return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
469
M68k::AR32RegClass.contains(MemOp.OuterReg);
470
}
471
void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
472
Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
473
}
474
475
// PCD
476
bool M68kOperand::isPCD() const {
477
return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
478
MemOp.OuterReg == M68k::PC;
479
}
480
void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
481
M68kOperand::addExpr(Inst, MemOp.OuterDisp);
482
}
483
484
// PCI
485
bool M68kOperand::isPCI() const {
486
return isMemOp() &&
487
MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
488
MemOp.OuterReg == M68k::PC;
489
}
490
void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
491
M68kOperand::addExpr(Inst, MemOp.OuterDisp);
492
Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
493
}
494
495
static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
496
bool SP, bool FPDR = false,
497
bool FPCR = false) {
498
switch (RegNo) {
499
case M68k::A0:
500
case M68k::A1:
501
case M68k::A2:
502
case M68k::A3:
503
case M68k::A4:
504
case M68k::A5:
505
case M68k::A6:
506
return Address;
507
508
case M68k::SP:
509
return SP;
510
511
case M68k::D0:
512
case M68k::D1:
513
case M68k::D2:
514
case M68k::D3:
515
case M68k::D4:
516
case M68k::D5:
517
case M68k::D6:
518
case M68k::D7:
519
return Data;
520
521
case M68k::SR:
522
case M68k::CCR:
523
return false;
524
525
case M68k::FP0:
526
case M68k::FP1:
527
case M68k::FP2:
528
case M68k::FP3:
529
case M68k::FP4:
530
case M68k::FP5:
531
case M68k::FP6:
532
case M68k::FP7:
533
return FPDR;
534
535
case M68k::FPC:
536
case M68k::FPS:
537
case M68k::FPIAR:
538
return FPCR;
539
540
default:
541
llvm_unreachable("unexpected register type");
542
return false;
543
}
544
}
545
546
bool M68kOperand::isAReg() const {
547
return isReg() && checkRegisterClass(getReg(),
548
/*Data=*/false,
549
/*Address=*/true, /*SP=*/true);
550
}
551
552
bool M68kOperand::isDReg() const {
553
return isReg() && checkRegisterClass(getReg(),
554
/*Data=*/true,
555
/*Address=*/false, /*SP=*/false);
556
}
557
558
bool M68kOperand::isFPDReg() const {
559
return isReg() && checkRegisterClass(getReg(),
560
/*Data=*/false,
561
/*Address=*/false, /*SP=*/false,
562
/*FPDR=*/true);
563
}
564
565
bool M68kOperand::isFPCReg() const {
566
return isReg() && checkRegisterClass(getReg(),
567
/*Data=*/false,
568
/*Address=*/false, /*SP=*/false,
569
/*FPDR=*/false, /*FPCR=*/true);
570
}
571
572
unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
573
unsigned Kind) {
574
M68kOperand &Operand = (M68kOperand &)Op;
575
576
switch (Kind) {
577
case MCK_XR16:
578
case MCK_SPILL:
579
if (Operand.isReg() &&
580
checkRegisterClass(Operand.getReg(), true, true, true)) {
581
return Match_Success;
582
}
583
break;
584
585
case MCK_AR16:
586
case MCK_AR32:
587
if (Operand.isReg() &&
588
checkRegisterClass(Operand.getReg(), false, true, true)) {
589
return Match_Success;
590
}
591
break;
592
593
case MCK_AR32_NOSP:
594
if (Operand.isReg() &&
595
checkRegisterClass(Operand.getReg(), false, true, false)) {
596
return Match_Success;
597
}
598
break;
599
600
case MCK_DR8:
601
case MCK_DR16:
602
case MCK_DR32:
603
if (Operand.isReg() &&
604
checkRegisterClass(Operand.getReg(), true, false, false)) {
605
return Match_Success;
606
}
607
break;
608
609
case MCK_AR16_TC:
610
if (Operand.isReg() &&
611
((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
612
return Match_Success;
613
}
614
break;
615
616
case MCK_DR16_TC:
617
if (Operand.isReg() &&
618
((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
619
return Match_Success;
620
}
621
break;
622
623
case MCK_XR16_TC:
624
if (Operand.isReg() &&
625
((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
626
(Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
627
return Match_Success;
628
}
629
break;
630
}
631
632
return Match_InvalidOperand;
633
}
634
635
bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc,
636
StringRef RegisterName) {
637
auto RegisterNameLower = RegisterName.lower();
638
639
// CCR register
640
if (RegisterNameLower == "ccr") {
641
RegNo = M68k::CCR;
642
return true;
643
}
644
645
// Parse simple general-purpose registers.
646
if (RegisterNameLower.size() == 2) {
647
648
switch (RegisterNameLower[0]) {
649
case 'd':
650
case 'a': {
651
if (isdigit(RegisterNameLower[1])) {
652
unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
653
unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
654
if (RegIndex < 8) {
655
RegNo = getRegisterByIndex(IndexOffset + RegIndex);
656
return true;
657
}
658
}
659
break;
660
}
661
662
case 's':
663
if (RegisterNameLower[1] == 'p') {
664
RegNo = M68k::SP;
665
return true;
666
} else if (RegisterNameLower[1] == 'r') {
667
RegNo = M68k::SR;
668
return true;
669
}
670
break;
671
672
case 'p':
673
if (RegisterNameLower[1] == 'c') {
674
RegNo = M68k::PC;
675
return true;
676
}
677
break;
678
}
679
} else if (StringRef(RegisterNameLower).starts_with("fp") &&
680
RegisterNameLower.size() > 2) {
681
auto RegIndex = unsigned(RegisterNameLower[2] - '0');
682
if (RegIndex < 8 && RegisterNameLower.size() == 3) {
683
// Floating point data register.
684
RegNo = getRegisterByIndex(16 + RegIndex);
685
return true;
686
} else {
687
// Floating point control register.
688
RegNo = StringSwitch<unsigned>(RegisterNameLower)
689
.Cases("fpc", "fpcr", M68k::FPC)
690
.Cases("fps", "fpsr", M68k::FPS)
691
.Cases("fpi", "fpiar", M68k::FPIAR)
692
.Default(M68k::NoRegister);
693
assert(RegNo != M68k::NoRegister &&
694
"Unrecognized FP control register name");
695
return true;
696
}
697
}
698
699
return false;
700
}
701
702
ParseStatus M68kAsmParser::parseRegister(MCRegister &RegNo) {
703
bool HasPercent = false;
704
AsmToken PercentToken;
705
706
LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
707
708
if (getTok().is(AsmToken::Percent)) {
709
HasPercent = true;
710
PercentToken = Lex();
711
} else if (!RegisterPrefixOptional.getValue()) {
712
return ParseStatus::NoMatch;
713
}
714
715
if (!Parser.getTok().is(AsmToken::Identifier)) {
716
if (HasPercent) {
717
getLexer().UnLex(PercentToken);
718
}
719
return ParseStatus::NoMatch;
720
}
721
722
auto RegisterName = Parser.getTok().getString();
723
if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
724
if (HasPercent) {
725
getLexer().UnLex(PercentToken);
726
}
727
return ParseStatus::NoMatch;
728
}
729
730
Parser.Lex();
731
return ParseStatus::Success;
732
}
733
734
bool M68kAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
735
SMLoc &EndLoc) {
736
ParseStatus Result = tryParseRegister(Reg, StartLoc, EndLoc);
737
if (!Result.isSuccess())
738
return Error(StartLoc, "expected register");
739
740
return false;
741
}
742
743
ParseStatus M68kAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
744
SMLoc &EndLoc) {
745
StartLoc = getLexer().getLoc();
746
ParseStatus Result = parseRegister(Reg);
747
EndLoc = getLexer().getLoc();
748
return Result;
749
}
750
751
bool M68kAsmParser::isExpr() {
752
switch (Parser.getTok().getKind()) {
753
case AsmToken::Identifier:
754
case AsmToken::Integer:
755
return true;
756
case AsmToken::Minus:
757
return getLexer().peekTok().getKind() == AsmToken::Integer;
758
759
default:
760
return false;
761
}
762
}
763
764
ParseStatus M68kAsmParser::parseImm(OperandVector &Operands) {
765
if (getLexer().isNot(AsmToken::Hash))
766
return ParseStatus::NoMatch;
767
SMLoc Start = getLexer().getLoc();
768
Parser.Lex();
769
770
SMLoc End;
771
const MCExpr *Expr;
772
773
if (getParser().parseExpression(Expr, End))
774
return ParseStatus::Failure;
775
776
Operands.push_back(M68kOperand::createImm(Expr, Start, End));
777
return ParseStatus::Success;
778
}
779
780
ParseStatus M68kAsmParser::parseMemOp(OperandVector &Operands) {
781
SMLoc Start = getLexer().getLoc();
782
bool IsPD = false;
783
M68kMemOp MemOp;
784
785
// Check for a plain register or register mask.
786
ParseStatus Result = parseRegOrMoveMask(Operands);
787
if (!Result.isNoMatch())
788
return Result;
789
790
// Check for pre-decrement & outer displacement.
791
bool HasDisplacement = false;
792
if (getLexer().is(AsmToken::Minus)) {
793
IsPD = true;
794
Parser.Lex();
795
} else if (isExpr()) {
796
if (Parser.parseExpression(MemOp.OuterDisp))
797
return ParseStatus::Failure;
798
HasDisplacement = true;
799
}
800
801
if (getLexer().isNot(AsmToken::LParen)) {
802
if (HasDisplacement) {
803
MemOp.Op = M68kMemOp::Kind::Addr;
804
Operands.push_back(
805
M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
806
return ParseStatus::Success;
807
}
808
if (IsPD)
809
return Error(getLexer().getLoc(), "expected (");
810
811
return ParseStatus::NoMatch;
812
}
813
Parser.Lex();
814
815
// Check for constant dereference & MIT-style displacement
816
if (!HasDisplacement && isExpr()) {
817
if (Parser.parseExpression(MemOp.OuterDisp))
818
return ParseStatus::Failure;
819
HasDisplacement = true;
820
821
// If we're not followed by a comma, we're a constant dereference.
822
if (getLexer().isNot(AsmToken::Comma)) {
823
MemOp.Op = M68kMemOp::Kind::Addr;
824
Operands.push_back(
825
M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
826
return ParseStatus::Success;
827
}
828
829
Parser.Lex();
830
}
831
832
Result = parseRegister(MemOp.OuterReg);
833
if (Result.isFailure())
834
return ParseStatus::Failure;
835
836
if (!Result.isSuccess())
837
return Error(getLexer().getLoc(), "expected register");
838
839
// Check for Index.
840
bool HasIndex = false;
841
if (Parser.getTok().is(AsmToken::Comma)) {
842
Parser.Lex();
843
844
Result = parseRegister(MemOp.InnerReg);
845
if (Result.isFailure())
846
return Result;
847
848
if (Result.isNoMatch())
849
return Error(getLexer().getLoc(), "expected register");
850
851
// TODO: parse size, scale and inner displacement.
852
MemOp.Size = 4;
853
MemOp.Scale = 1;
854
MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);
855
HasIndex = true;
856
}
857
858
if (Parser.getTok().isNot(AsmToken::RParen))
859
return Error(getLexer().getLoc(), "expected )");
860
Parser.Lex();
861
862
bool IsPI = false;
863
if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {
864
Parser.Lex();
865
IsPI = true;
866
}
867
868
SMLoc End = getLexer().getLoc();
869
870
unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
871
if (OpCount > 1)
872
return Error(Start, "only one of post-increment, pre-decrement or "
873
"displacement can be used");
874
875
if (IsPD) {
876
MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
877
} else if (IsPI) {
878
MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
879
} else if (HasIndex) {
880
MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
881
} else if (HasDisplacement) {
882
MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
883
} else {
884
MemOp.Op = M68kMemOp::Kind::RegIndirect;
885
}
886
887
Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
888
return ParseStatus::Success;
889
}
890
891
ParseStatus M68kAsmParser::parseRegOrMoveMask(OperandVector &Operands) {
892
SMLoc Start = getLexer().getLoc();
893
M68kMemOp MemOp(M68kMemOp::Kind::RegMask);
894
MemOp.RegMask = 0;
895
896
for (;;) {
897
bool IsFirstRegister =
898
(MemOp.Op == M68kMemOp::Kind::RegMask) && (MemOp.RegMask == 0);
899
900
MCRegister FirstRegister;
901
ParseStatus Result = parseRegister(FirstRegister);
902
if (IsFirstRegister && Result.isNoMatch())
903
return ParseStatus::NoMatch;
904
if (!Result.isSuccess())
905
return Error(getLexer().getLoc(), "expected start register");
906
907
MCRegister LastRegister = FirstRegister;
908
if (parseOptionalToken(AsmToken::Minus)) {
909
Result = parseRegister(LastRegister);
910
if (!Result.isSuccess())
911
return Error(getLexer().getLoc(), "expected end register");
912
}
913
914
unsigned FirstRegisterIndex = getRegisterIndex(FirstRegister);
915
unsigned LastRegisterIndex = getRegisterIndex(LastRegister);
916
917
uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1;
918
uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex;
919
920
if (IsFirstRegister && (FirstRegister == LastRegister)) {
921
// First register range is a single register, simplify to just Reg
922
// so that it matches more operands.
923
MemOp.Op = M68kMemOp::Kind::Reg;
924
MemOp.OuterReg = FirstRegister;
925
} else {
926
if (MemOp.Op == M68kMemOp::Kind::Reg) {
927
// This is the second register being specified - expand the Reg operand
928
// into a mask first.
929
MemOp.Op = M68kMemOp::Kind::RegMask;
930
MemOp.RegMask = 1 << getRegisterIndex(MemOp.OuterReg);
931
932
if (MemOp.RegMask == 0)
933
return Error(getLexer().getLoc(),
934
"special registers cannot be used in register masks");
935
}
936
937
if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16))
938
return Error(getLexer().getLoc(),
939
"special registers cannot be used in register masks");
940
941
if (NewMaskBits & MemOp.RegMask)
942
return Error(getLexer().getLoc(), "conflicting masked registers");
943
944
MemOp.RegMask |= NewMaskBits;
945
}
946
947
if (!parseOptionalToken(AsmToken::Slash))
948
break;
949
}
950
951
Operands.push_back(
952
M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
953
return ParseStatus::Success;
954
}
955
956
void M68kAsmParser::eatComma() {
957
if (Parser.getTok().is(AsmToken::Comma)) {
958
Parser.Lex();
959
}
960
}
961
962
bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
963
SMLoc NameLoc, OperandVector &Operands) {
964
SMLoc Start = getLexer().getLoc();
965
Operands.push_back(M68kOperand::createToken(Name, Start, Start));
966
967
bool First = true;
968
while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
969
if (!First) {
970
eatComma();
971
} else {
972
First = false;
973
}
974
975
ParseStatus MatchResult = MatchOperandParserImpl(Operands, Name);
976
if (MatchResult.isSuccess())
977
continue;
978
979
// Add custom operand formats here...
980
SMLoc Loc = getLexer().getLoc();
981
Parser.eatToEndOfStatement();
982
return Error(Loc, "unexpected token parsing operands");
983
}
984
985
// Eat EndOfStatement.
986
Parser.Lex();
987
return false;
988
}
989
990
bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
991
OperandVector const &Operands,
992
uint64_t const &ErrorInfo) {
993
SMLoc ErrorLoc = Loc;
994
char const *Diag = 0;
995
996
if (ErrorInfo != ~0U) {
997
if (ErrorInfo >= Operands.size()) {
998
Diag = "too few operands for instruction.";
999
} else {
1000
auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
1001
if (Op.getStartLoc() != SMLoc()) {
1002
ErrorLoc = Op.getStartLoc();
1003
}
1004
}
1005
}
1006
1007
if (!Diag) {
1008
Diag = "invalid operand for instruction";
1009
}
1010
1011
return Error(ErrorLoc, Diag);
1012
}
1013
1014
bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc,
1015
uint64_t const &ErrorInfo) {
1016
return Error(Loc, "instruction requires a CPU feature not currently enabled");
1017
}
1018
1019
bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc,
1020
MCStreamer &Out) const {
1021
Inst.setLoc(Loc);
1022
Out.emitInstruction(Inst, STI);
1023
1024
return false;
1025
}
1026
1027
bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
1028
OperandVector &Operands,
1029
MCStreamer &Out,
1030
uint64_t &ErrorInfo,
1031
bool MatchingInlineAsm) {
1032
MCInst Inst;
1033
unsigned MatchResult =
1034
MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
1035
1036
switch (MatchResult) {
1037
case Match_Success:
1038
return emit(Inst, Loc, Out);
1039
case Match_MissingFeature:
1040
return missingFeature(Loc, ErrorInfo);
1041
case Match_InvalidOperand:
1042
return invalidOperand(Loc, Operands, ErrorInfo);
1043
case Match_MnemonicFail:
1044
return Error(Loc, "invalid instruction");
1045
default:
1046
return true;
1047
}
1048
}
1049
1050
void M68kOperand::print(raw_ostream &OS) const {
1051
switch (Kind) {
1052
case KindTy::Invalid:
1053
OS << "invalid";
1054
break;
1055
1056
case KindTy::Token:
1057
OS << "token '" << Token << "'";
1058
break;
1059
1060
case KindTy::Imm: {
1061
int64_t Value;
1062
Expr->evaluateAsAbsolute(Value);
1063
OS << "immediate " << Value;
1064
break;
1065
}
1066
1067
case KindTy::MemOp:
1068
MemOp.print(OS);
1069
break;
1070
}
1071
}
1072
1073