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