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