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