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