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(unsigned int &RegNo, SMLoc Loc,
47                          StringRef RegisterName);
48   OperandMatchResultTy parseRegister(unsigned int &RegNo);
49 
50   // Parser functions.
51   void eatComma();
52 
53   bool isExpr();
54   OperandMatchResultTy parseImm(OperandVector &Operands);
55   OperandMatchResultTy parseMemOp(OperandVector &Operands);
56   OperandMatchResultTy parseRegOrMoveMask(OperandVector &Operands);
57 
58 public:
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(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
71   OperandMatchResultTy tryParseRegister(unsigned &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   unsigned OuterReg;
107   unsigned 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 
115   M68kMemOp() {}
116   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:
144   M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)
145       : Base(), Kind(Kind), Start(Start), End(End) {}
146 
147   SMLoc getStartLoc() const override { return Start; }
148   SMLoc getEndLoc() const override { return End; }
149 
150   void print(raw_ostream &OS) const override;
151 
152   bool isMem() const override { return false; }
153   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;
186   bool isAddr8() const { return isAddrN<8>(); }
187   bool isAddr16() const { return isAddrN<16>(); }
188   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 
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 
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 
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 
260 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 
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
300 bool M68kOperand::isReg() const {
301   return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
302 }
303 
304 unsigned M68kOperand::getReg() const {
305   assert(isReg());
306   return MemOp.OuterReg;
307 }
308 
309 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 
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
324 bool M68kOperand::isToken() const { return Kind == KindTy::Token; }
325 StringRef M68kOperand::getToken() const {
326   assert(isToken());
327   return Token;
328 }
329 
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
338 bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }
339 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 
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
354 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 
369 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
381 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?
386 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 }
395 void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
396   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
397 }
398 
399 // ARI
400 bool M68kOperand::isARI() const {
401   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
402          M68k::AR32RegClass.contains(MemOp.OuterReg);
403 }
404 void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
405   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
406 }
407 
408 // ARID
409 bool M68kOperand::isARID() const {
410   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
411          M68k::AR32RegClass.contains(MemOp.OuterReg);
412 }
413 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
419 bool M68kOperand::isARII() const {
420   return isMemOp() &&
421          MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
422          M68k::AR32RegClass.contains(MemOp.OuterReg);
423 }
424 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
431 bool M68kOperand::isARIPD() const {
432   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
433          M68k::AR32RegClass.contains(MemOp.OuterReg);
434 }
435 void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
436   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
437 }
438 
439 // ARIPI
440 bool M68kOperand::isARIPI() const {
441   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
442          M68k::AR32RegClass.contains(MemOp.OuterReg);
443 }
444 void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
445   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
446 }
447 
448 // PCD
449 bool M68kOperand::isPCD() const {
450   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
451          MemOp.OuterReg == M68k::PC;
452 }
453 void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
454   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
455 }
456 
457 // PCI
458 bool M68kOperand::isPCI() const {
459   return isMemOp() &&
460          MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
461          MemOp.OuterReg == M68k::PC;
462 }
463 void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
464   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
465   Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
466 }
467 
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 
503 bool M68kOperand::isAReg() const {
504   return isReg() && checkRegisterClass(getReg(),
505                                        /*Data=*/false,
506                                        /*Address=*/true, /*SP=*/true);
507 }
508 
509 bool M68kOperand::isDReg() const {
510   return isReg() && checkRegisterClass(getReg(),
511                                        /*Data=*/true,
512                                        /*Address=*/false, /*SP=*/false);
513 }
514 
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 
578 bool M68kAsmParser::parseRegisterName(unsigned &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 
627 OperandMatchResultTy M68kAsmParser::parseRegister(unsigned &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 
659 bool M68kAsmParser::ParseRegister(unsigned &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 
669 OperandMatchResultTy M68kAsmParser::tryParseRegister(unsigned &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 
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 
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 
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
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     unsigned 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     unsigned 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 
915 void M68kAsmParser::eatComma() {
916   if (Parser.getTok().is(AsmToken::Comma)) {
917     Parser.Lex();
918   }
919 }
920 
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 
950 bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
951 
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 
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 
981 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 
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 
1012 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