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:
M68kAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)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
M68kMemOp__anon8d0ae56c0111::M68kMemOp113 M68kMemOp() {}
M68kMemOp__anon8d0ae56c0111::M68kMemOp114 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:
M68kOperand(KindTy Kind,SMLoc Start,SMLoc End)141 M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)
142 : Base(), Kind(Kind), Start(Start), End(End) {}
143
getStartLoc() const144 SMLoc getStartLoc() const override { return Start; }
getEndLoc() const145 SMLoc getEndLoc() const override { return End; }
146
147 void print(raw_ostream &OS) const override;
148
isMem() const149 bool isMem() const override { return false; }
isMemOp() const150 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;
isAddr8() const190 bool isAddr8() const { return isAddrN<8>(); }
isAddr16() const191 bool isAddr16() const { return isAddrN<16>(); }
isAddr32() const192 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
LLVMInitializeM68kAsmParser()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
getRegisterByIndex(unsigned RegisterIndex)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
getRegisterIndex(unsigned Register)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
print(raw_ostream & OS) const271 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
addExpr(MCInst & Inst,const MCExpr * Expr)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
isReg() const311 bool M68kOperand::isReg() const {
312 return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
313 }
314
getReg() const315 MCRegister M68kOperand::getReg() const {
316 assert(isReg());
317 return MemOp.OuterReg;
318 }
319
addRegOperands(MCInst & Inst,unsigned N) const320 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
createMemOp(M68kMemOp MemOp,SMLoc Start,SMLoc End)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
isToken() const335 bool M68kOperand::isToken() const { return Kind == KindTy::Token; }
getToken() const336 StringRef M68kOperand::getToken() const {
337 assert(isToken());
338 return Token;
339 }
340
createToken(StringRef Token,SMLoc Start,SMLoc End)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
isImm() const349 bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }
addImmOperands(MCInst & Inst,unsigned N) const350 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
createImm(const MCExpr * Expr,SMLoc Start,SMLoc End)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
isTrapImm() const364 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
isBkptImm() const372 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
isMoveMask() const381 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
addMoveMaskOperands(MCInst & Inst,unsigned N) const396 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
isAddr() const408 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?
isAddrN() const413 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 }
addAddrOperands(MCInst & Inst,unsigned N) const422 void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
423 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
424 }
425
426 // ARI
isARI() const427 bool M68kOperand::isARI() const {
428 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
429 M68k::AR32RegClass.contains(MemOp.OuterReg);
430 }
addARIOperands(MCInst & Inst,unsigned N) const431 void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
432 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
433 }
434
435 // ARID
isARID() const436 bool M68kOperand::isARID() const {
437 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
438 M68k::AR32RegClass.contains(MemOp.OuterReg);
439 }
addARIDOperands(MCInst & Inst,unsigned N) const440 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
isARII() const446 bool M68kOperand::isARII() const {
447 return isMemOp() &&
448 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
449 M68k::AR32RegClass.contains(MemOp.OuterReg);
450 }
addARIIOperands(MCInst & Inst,unsigned N) const451 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
isARIPD() const458 bool M68kOperand::isARIPD() const {
459 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
460 M68k::AR32RegClass.contains(MemOp.OuterReg);
461 }
addARIPDOperands(MCInst & Inst,unsigned N) const462 void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
463 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
464 }
465
466 // ARIPI
isARIPI() const467 bool M68kOperand::isARIPI() const {
468 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
469 M68k::AR32RegClass.contains(MemOp.OuterReg);
470 }
addARIPIOperands(MCInst & Inst,unsigned N) const471 void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
472 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
473 }
474
475 // PCD
isPCD() const476 bool M68kOperand::isPCD() const {
477 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
478 MemOp.OuterReg == M68k::PC;
479 }
addPCDOperands(MCInst & Inst,unsigned N) const480 void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
481 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
482 }
483
484 // PCI
isPCI() const485 bool M68kOperand::isPCI() const {
486 return isMemOp() &&
487 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
488 MemOp.OuterReg == M68k::PC;
489 }
addPCIOperands(MCInst & Inst,unsigned N) const490 void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
491 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
492 Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
493 }
494
checkRegisterClass(unsigned RegNo,bool Data,bool Address,bool SP,bool FPDR=false,bool FPCR=false)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
isAReg() const546 bool M68kOperand::isAReg() const {
547 return isReg() && checkRegisterClass(getReg(),
548 /*Data=*/false,
549 /*Address=*/true, /*SP=*/true);
550 }
551
isDReg() const552 bool M68kOperand::isDReg() const {
553 return isReg() && checkRegisterClass(getReg(),
554 /*Data=*/true,
555 /*Address=*/false, /*SP=*/false);
556 }
557
isFPDReg() const558 bool M68kOperand::isFPDReg() const {
559 return isReg() && checkRegisterClass(getReg(),
560 /*Data=*/false,
561 /*Address=*/false, /*SP=*/false,
562 /*FPDR=*/true);
563 }
564
isFPCReg() const565 bool M68kOperand::isFPCReg() const {
566 return isReg() && checkRegisterClass(getReg(),
567 /*Data=*/false,
568 /*Address=*/false, /*SP=*/false,
569 /*FPDR=*/false, /*FPCR=*/true);
570 }
571
validateTargetOperandClass(MCParsedAsmOperand & Op,unsigned Kind)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
parseRegisterName(MCRegister & RegNo,SMLoc Loc,StringRef RegisterName)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
parseRegister(MCRegister & RegNo)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
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)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
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)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
isExpr()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
parseImm(OperandVector & Operands)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
parseMemOp(OperandVector & Operands)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
parseRegOrMoveMask(OperandVector & Operands)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
eatComma()956 void M68kAsmParser::eatComma() {
957 if (Parser.getTok().is(AsmToken::Comma)) {
958 Parser.Lex();
959 }
960 }
961
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)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
invalidOperand(SMLoc const & Loc,OperandVector const & Operands,uint64_t const & ErrorInfo)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
missingFeature(llvm::SMLoc const & Loc,uint64_t const & ErrorInfo)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
emit(MCInst & Inst,SMLoc const & Loc,MCStreamer & Out) const1019 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
MatchAndEmitInstruction(SMLoc Loc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)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
print(raw_ostream & OS) const1050 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