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