xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
1*04eeddc0SDimitry Andric //===-- M68kAsmParser.cpp - Parse M68k assembly to MCInst instructions ----===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric 
9fe6060f1SDimitry Andric #include "M68kInstrInfo.h"
10fe6060f1SDimitry Andric #include "M68kRegisterInfo.h"
11fe6060f1SDimitry Andric #include "TargetInfo/M68kTargetInfo.h"
12fe6060f1SDimitry Andric 
13fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h"
14fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
15fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
16fe6060f1SDimitry Andric #include "llvm/MC/MCStreamer.h"
17349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
18fe6060f1SDimitry Andric 
19fe6060f1SDimitry Andric #include <sstream>
20fe6060f1SDimitry Andric 
21fe6060f1SDimitry Andric #define DEBUG_TYPE "m68k-asm-parser"
22fe6060f1SDimitry Andric 
23fe6060f1SDimitry Andric using namespace llvm;
24fe6060f1SDimitry Andric 
25fe6060f1SDimitry Andric static cl::opt<bool> RegisterPrefixOptional(
26fe6060f1SDimitry Andric     "m68k-register-prefix-optional", cl::Hidden,
27fe6060f1SDimitry Andric     cl::desc("Enable specifying registers without the % prefix"),
28fe6060f1SDimitry Andric     cl::init(false));
29fe6060f1SDimitry Andric 
30fe6060f1SDimitry Andric namespace {
31fe6060f1SDimitry Andric /// Parses M68k assembly from a stream.
32fe6060f1SDimitry Andric class M68kAsmParser : public MCTargetAsmParser {
33fe6060f1SDimitry Andric   const MCSubtargetInfo &STI;
34fe6060f1SDimitry Andric   MCAsmParser &Parser;
35fe6060f1SDimitry Andric   const MCRegisterInfo *MRI;
36fe6060f1SDimitry Andric 
37fe6060f1SDimitry Andric #define GET_ASSEMBLER_HEADER
38fe6060f1SDimitry Andric #include "M68kGenAsmMatcher.inc"
39fe6060f1SDimitry Andric 
40fe6060f1SDimitry Andric   // Helpers for Match&Emit.
41fe6060f1SDimitry Andric   bool invalidOperand(const SMLoc &Loc, const OperandVector &Operands,
42fe6060f1SDimitry Andric                       const uint64_t &ErrorInfo);
43fe6060f1SDimitry Andric   bool missingFeature(const SMLoc &Loc, const uint64_t &ErrorInfo);
44fe6060f1SDimitry Andric   bool emit(MCInst &Inst, SMLoc const &Loc, MCStreamer &Out) const;
45fe6060f1SDimitry Andric   bool parseRegisterName(unsigned int &RegNo, SMLoc Loc,
46fe6060f1SDimitry Andric                          StringRef RegisterName);
47fe6060f1SDimitry Andric   OperandMatchResultTy parseRegister(unsigned int &RegNo);
48fe6060f1SDimitry Andric 
49fe6060f1SDimitry Andric   // Parser functions.
50fe6060f1SDimitry Andric   void eatComma();
51fe6060f1SDimitry Andric 
52fe6060f1SDimitry Andric   bool isExpr();
53fe6060f1SDimitry Andric   OperandMatchResultTy parseImm(OperandVector &Operands);
54fe6060f1SDimitry Andric   OperandMatchResultTy parseMemOp(OperandVector &Operands);
55349cc55cSDimitry Andric   OperandMatchResultTy parseRegOrMoveMask(OperandVector &Operands);
56fe6060f1SDimitry Andric 
57fe6060f1SDimitry Andric public:
58fe6060f1SDimitry Andric   M68kAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
59fe6060f1SDimitry Andric                 const MCInstrInfo &MII, const MCTargetOptions &Options)
60fe6060f1SDimitry Andric       : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
61fe6060f1SDimitry Andric     MCAsmParserExtension::Initialize(Parser);
62fe6060f1SDimitry Andric     MRI = getContext().getRegisterInfo();
63fe6060f1SDimitry Andric 
64fe6060f1SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
65fe6060f1SDimitry Andric   }
66fe6060f1SDimitry Andric 
67fe6060f1SDimitry Andric   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
68fe6060f1SDimitry Andric                                       unsigned Kind) override;
69fe6060f1SDimitry Andric   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
70fe6060f1SDimitry Andric   OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
71fe6060f1SDimitry Andric                                         SMLoc &EndLoc) override;
72fe6060f1SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
73fe6060f1SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
74fe6060f1SDimitry Andric   bool ParseDirective(AsmToken DirectiveID) override;
75fe6060f1SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
76fe6060f1SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
77fe6060f1SDimitry Andric                                uint64_t &ErrorInfo,
78fe6060f1SDimitry Andric                                bool MatchingInlineAsm) override;
79fe6060f1SDimitry Andric };
80fe6060f1SDimitry Andric 
81fe6060f1SDimitry Andric struct M68kMemOp {
82fe6060f1SDimitry Andric   enum class Kind {
83fe6060f1SDimitry Andric     Addr,
84349cc55cSDimitry Andric     RegMask,
85fe6060f1SDimitry Andric     Reg,
86fe6060f1SDimitry Andric     RegIndirect,
87fe6060f1SDimitry Andric     RegPostIncrement,
88fe6060f1SDimitry Andric     RegPreDecrement,
89fe6060f1SDimitry Andric     RegIndirectDisplacement,
90fe6060f1SDimitry Andric     RegIndirectDisplacementIndex,
91fe6060f1SDimitry Andric   };
92fe6060f1SDimitry Andric 
93fe6060f1SDimitry Andric   // These variables are used for the following forms:
94fe6060f1SDimitry Andric   // Addr: (OuterDisp)
95349cc55cSDimitry Andric   // RegMask: RegMask (as register mask)
96fe6060f1SDimitry Andric   // Reg: %OuterReg
97fe6060f1SDimitry Andric   // RegIndirect: (%OuterReg)
98fe6060f1SDimitry Andric   // RegPostIncrement: (%OuterReg)+
99fe6060f1SDimitry Andric   // RegPreDecrement: -(%OuterReg)
100fe6060f1SDimitry Andric   // RegIndirectDisplacement: OuterDisp(%OuterReg)
101fe6060f1SDimitry Andric   // RegIndirectDisplacementIndex:
102fe6060f1SDimitry Andric   //   OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)
103fe6060f1SDimitry Andric 
104fe6060f1SDimitry Andric   Kind Op;
105fe6060f1SDimitry Andric   unsigned OuterReg;
106fe6060f1SDimitry Andric   unsigned InnerReg;
107fe6060f1SDimitry Andric   const MCExpr *OuterDisp;
108fe6060f1SDimitry Andric   const MCExpr *InnerDisp;
109fe6060f1SDimitry Andric   uint8_t Size : 4;
110fe6060f1SDimitry Andric   uint8_t Scale : 4;
111fe6060f1SDimitry Andric   const MCExpr *Expr;
112349cc55cSDimitry Andric   uint16_t RegMask;
113fe6060f1SDimitry Andric 
114fe6060f1SDimitry Andric   M68kMemOp() {}
115fe6060f1SDimitry Andric   M68kMemOp(Kind Op) : Op(Op) {}
116fe6060f1SDimitry Andric 
117fe6060f1SDimitry Andric   void print(raw_ostream &OS) const;
118fe6060f1SDimitry Andric };
119fe6060f1SDimitry Andric 
120fe6060f1SDimitry Andric /// An parsed M68k assembly operand.
121fe6060f1SDimitry Andric class M68kOperand : public MCParsedAsmOperand {
122fe6060f1SDimitry Andric   typedef MCParsedAsmOperand Base;
123fe6060f1SDimitry Andric 
12469ade1e0SDimitry Andric   enum class KindTy {
125fe6060f1SDimitry Andric     Invalid,
126fe6060f1SDimitry Andric     Token,
127fe6060f1SDimitry Andric     Imm,
128fe6060f1SDimitry Andric     MemOp,
129fe6060f1SDimitry Andric   };
130fe6060f1SDimitry Andric 
13169ade1e0SDimitry Andric   KindTy Kind;
132fe6060f1SDimitry Andric   SMLoc Start, End;
133fe6060f1SDimitry Andric   union {
134fe6060f1SDimitry Andric     StringRef Token;
135fe6060f1SDimitry Andric     int64_t Imm;
136fe6060f1SDimitry Andric     const MCExpr *Expr;
137fe6060f1SDimitry Andric     M68kMemOp MemOp;
138fe6060f1SDimitry Andric   };
139fe6060f1SDimitry Andric 
140349cc55cSDimitry Andric   template <unsigned N> bool isAddrN() const;
141349cc55cSDimitry Andric 
142fe6060f1SDimitry Andric public:
14369ade1e0SDimitry Andric   M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)
144fe6060f1SDimitry Andric       : Base(), Kind(Kind), Start(Start), End(End) {}
145fe6060f1SDimitry Andric 
146fe6060f1SDimitry Andric   SMLoc getStartLoc() const override { return Start; }
147fe6060f1SDimitry Andric   SMLoc getEndLoc() const override { return End; }
148fe6060f1SDimitry Andric 
149fe6060f1SDimitry Andric   void print(raw_ostream &OS) const override;
150fe6060f1SDimitry Andric 
151fe6060f1SDimitry Andric   bool isMem() const override { return false; }
15269ade1e0SDimitry Andric   bool isMemOp() const { return Kind == KindTy::MemOp; }
153fe6060f1SDimitry Andric 
154fe6060f1SDimitry Andric   static void addExpr(MCInst &Inst, const MCExpr *Expr);
155fe6060f1SDimitry Andric 
156fe6060f1SDimitry Andric   // Reg
157fe6060f1SDimitry Andric   bool isReg() const override;
158349cc55cSDimitry Andric   bool isAReg() const;
159349cc55cSDimitry Andric   bool isDReg() const;
160fe6060f1SDimitry Andric   unsigned getReg() const override;
161fe6060f1SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const;
162fe6060f1SDimitry Andric 
163fe6060f1SDimitry Andric   static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start,
164fe6060f1SDimitry Andric                                                   SMLoc End);
165fe6060f1SDimitry Andric 
166fe6060f1SDimitry Andric   // Token
167fe6060f1SDimitry Andric   bool isToken() const override;
168fe6060f1SDimitry Andric   StringRef getToken() const;
169fe6060f1SDimitry Andric   static std::unique_ptr<M68kOperand> createToken(StringRef Token, SMLoc Start,
170fe6060f1SDimitry Andric                                                   SMLoc End);
171fe6060f1SDimitry Andric 
172fe6060f1SDimitry Andric   // Imm
173fe6060f1SDimitry Andric   bool isImm() const override;
174fe6060f1SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const;
175fe6060f1SDimitry Andric 
176fe6060f1SDimitry Andric   static std::unique_ptr<M68kOperand> createImm(const MCExpr *Expr, SMLoc Start,
177fe6060f1SDimitry Andric                                                 SMLoc End);
178fe6060f1SDimitry Andric 
179349cc55cSDimitry Andric   // MoveMask
180349cc55cSDimitry Andric   bool isMoveMask() const;
181349cc55cSDimitry Andric   void addMoveMaskOperands(MCInst &Inst, unsigned N) const;
182349cc55cSDimitry Andric 
183fe6060f1SDimitry Andric   // Addr
184fe6060f1SDimitry Andric   bool isAddr() const;
185349cc55cSDimitry Andric   bool isAddr8() const { return isAddrN<8>(); }
186349cc55cSDimitry Andric   bool isAddr16() const { return isAddrN<16>(); }
187349cc55cSDimitry Andric   bool isAddr32() const { return isAddrN<32>(); }
188fe6060f1SDimitry Andric   void addAddrOperands(MCInst &Inst, unsigned N) const;
189fe6060f1SDimitry Andric 
190fe6060f1SDimitry Andric   // ARI
191fe6060f1SDimitry Andric   bool isARI() const;
192fe6060f1SDimitry Andric   void addARIOperands(MCInst &Inst, unsigned N) const;
193fe6060f1SDimitry Andric 
194fe6060f1SDimitry Andric   // ARID
195fe6060f1SDimitry Andric   bool isARID() const;
196fe6060f1SDimitry Andric   void addARIDOperands(MCInst &Inst, unsigned N) const;
197fe6060f1SDimitry Andric 
198fe6060f1SDimitry Andric   // ARII
199fe6060f1SDimitry Andric   bool isARII() const;
200fe6060f1SDimitry Andric   void addARIIOperands(MCInst &Inst, unsigned N) const;
201fe6060f1SDimitry Andric 
202fe6060f1SDimitry Andric   // ARIPD
203fe6060f1SDimitry Andric   bool isARIPD() const;
204fe6060f1SDimitry Andric   void addARIPDOperands(MCInst &Inst, unsigned N) const;
205fe6060f1SDimitry Andric 
206fe6060f1SDimitry Andric   // ARIPI
207fe6060f1SDimitry Andric   bool isARIPI() const;
208fe6060f1SDimitry Andric   void addARIPIOperands(MCInst &Inst, unsigned N) const;
209fe6060f1SDimitry Andric 
210fe6060f1SDimitry Andric   // PCD
211fe6060f1SDimitry Andric   bool isPCD() const;
212fe6060f1SDimitry Andric   void addPCDOperands(MCInst &Inst, unsigned N) const;
213fe6060f1SDimitry Andric 
214fe6060f1SDimitry Andric   // PCI
215fe6060f1SDimitry Andric   bool isPCI() const;
216fe6060f1SDimitry Andric   void addPCIOperands(MCInst &Inst, unsigned N) const;
217fe6060f1SDimitry Andric };
218fe6060f1SDimitry Andric 
219fe6060f1SDimitry Andric } // end anonymous namespace.
220fe6060f1SDimitry Andric 
221fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() {
222fe6060f1SDimitry Andric   RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget());
223fe6060f1SDimitry Andric }
224fe6060f1SDimitry Andric 
225fe6060f1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
226fe6060f1SDimitry Andric #include "M68kGenAsmMatcher.inc"
227fe6060f1SDimitry Andric 
228349cc55cSDimitry Andric static inline unsigned getRegisterByIndex(unsigned RegisterIndex) {
229349cc55cSDimitry Andric   static unsigned RegistersByIndex[] = {
230349cc55cSDimitry Andric       M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
231349cc55cSDimitry Andric       M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
232349cc55cSDimitry Andric       M68k::A4, M68k::A5, M68k::A6, M68k::SP,
233349cc55cSDimitry Andric   };
234349cc55cSDimitry Andric   assert(RegisterIndex <=
235349cc55cSDimitry Andric          sizeof(RegistersByIndex) / sizeof(RegistersByIndex[0]));
236349cc55cSDimitry Andric   return RegistersByIndex[RegisterIndex];
237349cc55cSDimitry Andric }
238349cc55cSDimitry Andric 
239349cc55cSDimitry Andric static inline unsigned getRegisterIndex(unsigned Register) {
240349cc55cSDimitry Andric   if (Register >= M68k::D0 && Register <= M68k::D7)
241349cc55cSDimitry Andric     return Register - M68k::D0;
242349cc55cSDimitry Andric   if (Register >= M68k::A0 && Register <= M68k::A6)
243349cc55cSDimitry Andric     return Register - M68k::A0 + 8;
244349cc55cSDimitry Andric 
245349cc55cSDimitry Andric   switch (Register) {
246349cc55cSDimitry Andric   case M68k::SP:
247349cc55cSDimitry Andric     // SP is sadly not contiguous with the rest of the An registers
248349cc55cSDimitry Andric     return 15;
249349cc55cSDimitry Andric 
250349cc55cSDimitry Andric   case M68k::PC:
251349cc55cSDimitry Andric   case M68k::CCR:
252349cc55cSDimitry Andric     return 16;
253349cc55cSDimitry Andric 
254349cc55cSDimitry Andric   default:
255349cc55cSDimitry Andric     llvm_unreachable("unexpected register number");
256349cc55cSDimitry Andric   }
257349cc55cSDimitry Andric }
258349cc55cSDimitry Andric 
259fe6060f1SDimitry Andric void M68kMemOp::print(raw_ostream &OS) const {
260fe6060f1SDimitry Andric   switch (Op) {
261fe6060f1SDimitry Andric   case Kind::Addr:
262fe6060f1SDimitry Andric     OS << OuterDisp;
263fe6060f1SDimitry Andric     break;
264349cc55cSDimitry Andric   case Kind::RegMask:
265349cc55cSDimitry Andric     OS << "RegMask(" << format("%04x", RegMask) << ")";
266349cc55cSDimitry Andric     break;
267fe6060f1SDimitry Andric   case Kind::Reg:
268fe6060f1SDimitry Andric     OS << '%' << OuterReg;
269fe6060f1SDimitry Andric     break;
270fe6060f1SDimitry Andric   case Kind::RegIndirect:
271fe6060f1SDimitry Andric     OS << "(%" << OuterReg << ')';
272fe6060f1SDimitry Andric     break;
273fe6060f1SDimitry Andric   case Kind::RegPostIncrement:
274fe6060f1SDimitry Andric     OS << "(%" << OuterReg << ")+";
275fe6060f1SDimitry Andric     break;
276fe6060f1SDimitry Andric   case Kind::RegPreDecrement:
277fe6060f1SDimitry Andric     OS << "-(%" << OuterReg << ")";
278fe6060f1SDimitry Andric     break;
279fe6060f1SDimitry Andric   case Kind::RegIndirectDisplacement:
280fe6060f1SDimitry Andric     OS << OuterDisp << "(%" << OuterReg << ")";
281fe6060f1SDimitry Andric     break;
282fe6060f1SDimitry Andric   case Kind::RegIndirectDisplacementIndex:
283fe6060f1SDimitry Andric     OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size
284fe6060f1SDimitry Andric        << ", " << InnerDisp << ")";
285fe6060f1SDimitry Andric     break;
286fe6060f1SDimitry Andric   }
287fe6060f1SDimitry Andric }
288fe6060f1SDimitry Andric 
289fe6060f1SDimitry Andric void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {
290fe6060f1SDimitry Andric   if (auto Const = dyn_cast<MCConstantExpr>(Expr)) {
291fe6060f1SDimitry Andric     Inst.addOperand(MCOperand::createImm(Const->getValue()));
292fe6060f1SDimitry Andric     return;
293fe6060f1SDimitry Andric   }
294fe6060f1SDimitry Andric 
295fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createExpr(Expr));
296fe6060f1SDimitry Andric }
297fe6060f1SDimitry Andric 
298fe6060f1SDimitry Andric // Reg
299fe6060f1SDimitry Andric bool M68kOperand::isReg() const {
30069ade1e0SDimitry Andric   return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
301fe6060f1SDimitry Andric }
302fe6060f1SDimitry Andric 
303fe6060f1SDimitry Andric unsigned M68kOperand::getReg() const {
304fe6060f1SDimitry Andric   assert(isReg());
305fe6060f1SDimitry Andric   return MemOp.OuterReg;
306fe6060f1SDimitry Andric }
307fe6060f1SDimitry Andric 
308fe6060f1SDimitry Andric void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {
309fe6060f1SDimitry Andric   assert(isReg() && "wrong operand kind");
310fe6060f1SDimitry Andric   assert((N == 1) && "can only handle one register operand");
311fe6060f1SDimitry Andric 
312fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(getReg()));
313fe6060f1SDimitry Andric }
314fe6060f1SDimitry Andric 
315fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,
316fe6060f1SDimitry Andric                                                       SMLoc Start, SMLoc End) {
31769ade1e0SDimitry Andric   auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start, End);
318fe6060f1SDimitry Andric   Op->MemOp = MemOp;
319fe6060f1SDimitry Andric   return Op;
320fe6060f1SDimitry Andric }
321fe6060f1SDimitry Andric 
322fe6060f1SDimitry Andric // Token
32369ade1e0SDimitry Andric bool M68kOperand::isToken() const { return Kind == KindTy::Token; }
324fe6060f1SDimitry Andric StringRef M68kOperand::getToken() const {
325fe6060f1SDimitry Andric   assert(isToken());
326fe6060f1SDimitry Andric   return Token;
327fe6060f1SDimitry Andric }
328fe6060f1SDimitry Andric 
329fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,
330fe6060f1SDimitry Andric                                                       SMLoc Start, SMLoc End) {
33169ade1e0SDimitry Andric   auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start, End);
332fe6060f1SDimitry Andric   Op->Token = Token;
333fe6060f1SDimitry Andric   return Op;
334fe6060f1SDimitry Andric }
335fe6060f1SDimitry Andric 
336fe6060f1SDimitry Andric // Imm
33769ade1e0SDimitry Andric bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }
338fe6060f1SDimitry Andric void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {
339349cc55cSDimitry Andric   assert(isImm() && "wrong operand kind");
340fe6060f1SDimitry Andric   assert((N == 1) && "can only handle one register operand");
341fe6060f1SDimitry Andric 
342fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, Expr);
343fe6060f1SDimitry Andric }
344fe6060f1SDimitry Andric 
345fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,
346fe6060f1SDimitry Andric                                                     SMLoc Start, SMLoc End) {
34769ade1e0SDimitry Andric   auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start, End);
348fe6060f1SDimitry Andric   Op->Expr = Expr;
349fe6060f1SDimitry Andric   return Op;
350fe6060f1SDimitry Andric }
351fe6060f1SDimitry Andric 
352349cc55cSDimitry Andric // MoveMask
353349cc55cSDimitry Andric bool M68kOperand::isMoveMask() const {
354349cc55cSDimitry Andric   if (!isMemOp())
355349cc55cSDimitry Andric     return false;
356349cc55cSDimitry Andric 
357349cc55cSDimitry Andric   if (MemOp.Op == M68kMemOp::Kind::RegMask)
358349cc55cSDimitry Andric     return true;
359349cc55cSDimitry Andric 
360349cc55cSDimitry Andric   if (MemOp.Op != M68kMemOp::Kind::Reg)
361349cc55cSDimitry Andric     return false;
362349cc55cSDimitry Andric 
363349cc55cSDimitry Andric   // Only regular address / data registers are allowed to be used
364349cc55cSDimitry Andric   // in register masks.
365349cc55cSDimitry Andric   return getRegisterIndex(MemOp.OuterReg) < 16;
366349cc55cSDimitry Andric }
367349cc55cSDimitry Andric 
368349cc55cSDimitry Andric void M68kOperand::addMoveMaskOperands(MCInst &Inst, unsigned N) const {
369349cc55cSDimitry Andric   assert(isMoveMask() && "wrong operand kind");
370349cc55cSDimitry Andric   assert((N == 1) && "can only handle one immediate operand");
371349cc55cSDimitry Andric 
372349cc55cSDimitry Andric   uint16_t MoveMask = MemOp.RegMask;
373349cc55cSDimitry Andric   if (MemOp.Op == M68kMemOp::Kind::Reg)
374349cc55cSDimitry Andric     MoveMask = 1 << getRegisterIndex(MemOp.OuterReg);
375349cc55cSDimitry Andric 
376349cc55cSDimitry Andric   Inst.addOperand(MCOperand::createImm(MoveMask));
377349cc55cSDimitry Andric }
378349cc55cSDimitry Andric 
379fe6060f1SDimitry Andric // Addr
380fe6060f1SDimitry Andric bool M68kOperand::isAddr() const {
381fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
382fe6060f1SDimitry Andric }
383349cc55cSDimitry Andric // TODO: Maybe we can also store the size of OuterDisp
384349cc55cSDimitry Andric // in Size?
385349cc55cSDimitry Andric template <unsigned N> bool M68kOperand::isAddrN() const {
386349cc55cSDimitry Andric   if (isAddr()) {
387349cc55cSDimitry Andric     int64_t Res;
388349cc55cSDimitry Andric     if (MemOp.OuterDisp->evaluateAsAbsolute(Res))
389349cc55cSDimitry Andric       return isInt<N>(Res);
390349cc55cSDimitry Andric     return true;
391349cc55cSDimitry Andric   }
392349cc55cSDimitry Andric   return false;
393349cc55cSDimitry Andric }
394fe6060f1SDimitry Andric void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
395fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
396fe6060f1SDimitry Andric }
397fe6060f1SDimitry Andric 
398fe6060f1SDimitry Andric // ARI
399fe6060f1SDimitry Andric bool M68kOperand::isARI() const {
400fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
401fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
402fe6060f1SDimitry Andric }
403fe6060f1SDimitry Andric void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
404fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
405fe6060f1SDimitry Andric }
406fe6060f1SDimitry Andric 
407fe6060f1SDimitry Andric // ARID
408fe6060f1SDimitry Andric bool M68kOperand::isARID() const {
409fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
410fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
411fe6060f1SDimitry Andric }
412fe6060f1SDimitry Andric void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {
413fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
414fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
415fe6060f1SDimitry Andric }
416fe6060f1SDimitry Andric 
417fe6060f1SDimitry Andric // ARII
418fe6060f1SDimitry Andric bool M68kOperand::isARII() const {
419fe6060f1SDimitry Andric   return isMemOp() &&
420fe6060f1SDimitry Andric          MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
421fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
422fe6060f1SDimitry Andric }
423fe6060f1SDimitry Andric void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {
424fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
425fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
426fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
427fe6060f1SDimitry Andric }
428fe6060f1SDimitry Andric 
429fe6060f1SDimitry Andric // ARIPD
430fe6060f1SDimitry Andric bool M68kOperand::isARIPD() const {
431fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
432fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
433fe6060f1SDimitry Andric }
434fe6060f1SDimitry Andric void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
435fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
436fe6060f1SDimitry Andric }
437fe6060f1SDimitry Andric 
438fe6060f1SDimitry Andric // ARIPI
439fe6060f1SDimitry Andric bool M68kOperand::isARIPI() const {
440fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
441fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
442fe6060f1SDimitry Andric }
443fe6060f1SDimitry Andric void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
444fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
445fe6060f1SDimitry Andric }
446fe6060f1SDimitry Andric 
447fe6060f1SDimitry Andric // PCD
448fe6060f1SDimitry Andric bool M68kOperand::isPCD() const {
449fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
450fe6060f1SDimitry Andric          MemOp.OuterReg == M68k::PC;
451fe6060f1SDimitry Andric }
452fe6060f1SDimitry Andric void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
453fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
454fe6060f1SDimitry Andric }
455fe6060f1SDimitry Andric 
456fe6060f1SDimitry Andric // PCI
457fe6060f1SDimitry Andric bool M68kOperand::isPCI() const {
458fe6060f1SDimitry Andric   return isMemOp() &&
459fe6060f1SDimitry Andric          MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
460fe6060f1SDimitry Andric          MemOp.OuterReg == M68k::PC;
461fe6060f1SDimitry Andric }
462fe6060f1SDimitry Andric void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
463fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
464fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
465fe6060f1SDimitry Andric }
466fe6060f1SDimitry Andric 
467fe6060f1SDimitry Andric static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
468fe6060f1SDimitry Andric                                       bool SP) {
469fe6060f1SDimitry Andric   switch (RegNo) {
470fe6060f1SDimitry Andric   case M68k::A0:
471fe6060f1SDimitry Andric   case M68k::A1:
472fe6060f1SDimitry Andric   case M68k::A2:
473fe6060f1SDimitry Andric   case M68k::A3:
474fe6060f1SDimitry Andric   case M68k::A4:
475fe6060f1SDimitry Andric   case M68k::A5:
476fe6060f1SDimitry Andric   case M68k::A6:
477fe6060f1SDimitry Andric     return Address;
478fe6060f1SDimitry Andric 
479fe6060f1SDimitry Andric   case M68k::SP:
480fe6060f1SDimitry Andric     return SP;
481fe6060f1SDimitry Andric 
482fe6060f1SDimitry Andric   case M68k::D0:
483fe6060f1SDimitry Andric   case M68k::D1:
484fe6060f1SDimitry Andric   case M68k::D2:
485fe6060f1SDimitry Andric   case M68k::D3:
486fe6060f1SDimitry Andric   case M68k::D4:
487fe6060f1SDimitry Andric   case M68k::D5:
488fe6060f1SDimitry Andric   case M68k::D6:
489fe6060f1SDimitry Andric   case M68k::D7:
490fe6060f1SDimitry Andric     return Data;
491fe6060f1SDimitry Andric 
492fe6060f1SDimitry Andric   case M68k::SR:
493fe6060f1SDimitry Andric   case M68k::CCR:
494fe6060f1SDimitry Andric     return false;
495fe6060f1SDimitry Andric 
496fe6060f1SDimitry Andric   default:
497fe6060f1SDimitry Andric     llvm_unreachable("unexpected register type");
498fe6060f1SDimitry Andric     return false;
499fe6060f1SDimitry Andric   }
500fe6060f1SDimitry Andric }
501fe6060f1SDimitry Andric 
502349cc55cSDimitry Andric bool M68kOperand::isAReg() const {
503349cc55cSDimitry Andric   return isReg() && checkRegisterClass(getReg(),
504349cc55cSDimitry Andric                                        /*Data=*/false,
505349cc55cSDimitry Andric                                        /*Address=*/true, /*SP=*/true);
506349cc55cSDimitry Andric }
507349cc55cSDimitry Andric 
508349cc55cSDimitry Andric bool M68kOperand::isDReg() const {
509349cc55cSDimitry Andric   return isReg() && checkRegisterClass(getReg(),
510349cc55cSDimitry Andric                                        /*Data=*/true,
511349cc55cSDimitry Andric                                        /*Address=*/false, /*SP=*/false);
512349cc55cSDimitry Andric }
513349cc55cSDimitry Andric 
514fe6060f1SDimitry Andric unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
515fe6060f1SDimitry Andric                                                    unsigned Kind) {
516fe6060f1SDimitry Andric   M68kOperand &Operand = (M68kOperand &)Op;
517fe6060f1SDimitry Andric 
518fe6060f1SDimitry Andric   switch (Kind) {
519fe6060f1SDimitry Andric   case MCK_XR16:
520fe6060f1SDimitry Andric   case MCK_SPILL:
521fe6060f1SDimitry Andric     if (Operand.isReg() &&
522fe6060f1SDimitry Andric         checkRegisterClass(Operand.getReg(), true, true, true)) {
523fe6060f1SDimitry Andric       return Match_Success;
524fe6060f1SDimitry Andric     }
525fe6060f1SDimitry Andric     break;
526fe6060f1SDimitry Andric 
527fe6060f1SDimitry Andric   case MCK_AR16:
528fe6060f1SDimitry Andric   case MCK_AR32:
529fe6060f1SDimitry Andric     if (Operand.isReg() &&
530fe6060f1SDimitry Andric         checkRegisterClass(Operand.getReg(), false, true, true)) {
531fe6060f1SDimitry Andric       return Match_Success;
532fe6060f1SDimitry Andric     }
533fe6060f1SDimitry Andric     break;
534fe6060f1SDimitry Andric 
535fe6060f1SDimitry Andric   case MCK_AR32_NOSP:
536fe6060f1SDimitry Andric     if (Operand.isReg() &&
537fe6060f1SDimitry Andric         checkRegisterClass(Operand.getReg(), false, true, false)) {
538fe6060f1SDimitry Andric       return Match_Success;
539fe6060f1SDimitry Andric     }
540fe6060f1SDimitry Andric     break;
541fe6060f1SDimitry Andric 
542fe6060f1SDimitry Andric   case MCK_DR8:
543fe6060f1SDimitry Andric   case MCK_DR16:
544fe6060f1SDimitry Andric   case MCK_DR32:
545fe6060f1SDimitry Andric     if (Operand.isReg() &&
546fe6060f1SDimitry Andric         checkRegisterClass(Operand.getReg(), true, false, false)) {
547fe6060f1SDimitry Andric       return Match_Success;
548fe6060f1SDimitry Andric     }
549fe6060f1SDimitry Andric     break;
550fe6060f1SDimitry Andric 
551fe6060f1SDimitry Andric   case MCK_AR16_TC:
552fe6060f1SDimitry Andric     if (Operand.isReg() &&
553fe6060f1SDimitry Andric         ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
554fe6060f1SDimitry Andric       return Match_Success;
555fe6060f1SDimitry Andric     }
556fe6060f1SDimitry Andric     break;
557fe6060f1SDimitry Andric 
558fe6060f1SDimitry Andric   case MCK_DR16_TC:
559fe6060f1SDimitry Andric     if (Operand.isReg() &&
560fe6060f1SDimitry Andric         ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
561fe6060f1SDimitry Andric       return Match_Success;
562fe6060f1SDimitry Andric     }
563fe6060f1SDimitry Andric     break;
564fe6060f1SDimitry Andric 
565fe6060f1SDimitry Andric   case MCK_XR16_TC:
566fe6060f1SDimitry Andric     if (Operand.isReg() &&
567fe6060f1SDimitry Andric         ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
568fe6060f1SDimitry Andric          (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
569fe6060f1SDimitry Andric       return Match_Success;
570fe6060f1SDimitry Andric     }
571fe6060f1SDimitry Andric     break;
572fe6060f1SDimitry Andric   }
573fe6060f1SDimitry Andric 
574fe6060f1SDimitry Andric   return Match_InvalidOperand;
575fe6060f1SDimitry Andric }
576fe6060f1SDimitry Andric 
577fe6060f1SDimitry Andric bool M68kAsmParser::parseRegisterName(unsigned &RegNo, SMLoc Loc,
578fe6060f1SDimitry Andric                                       StringRef RegisterName) {
579fe6060f1SDimitry Andric   auto RegisterNameLower = RegisterName.lower();
580fe6060f1SDimitry Andric 
581fe6060f1SDimitry Andric   // CCR register
582fe6060f1SDimitry Andric   if (RegisterNameLower == "ccr") {
583fe6060f1SDimitry Andric     RegNo = M68k::CCR;
584fe6060f1SDimitry Andric     return true;
585fe6060f1SDimitry Andric   }
586fe6060f1SDimitry Andric 
587fe6060f1SDimitry Andric   // Parse simple general-purpose registers.
588fe6060f1SDimitry Andric   if (RegisterNameLower.size() == 2) {
589fe6060f1SDimitry Andric 
590fe6060f1SDimitry Andric     switch (RegisterNameLower[0]) {
591fe6060f1SDimitry Andric     case 'd':
592fe6060f1SDimitry Andric     case 'a': {
593fe6060f1SDimitry Andric       if (isdigit(RegisterNameLower[1])) {
594fe6060f1SDimitry Andric         unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
595fe6060f1SDimitry Andric         unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
596fe6060f1SDimitry Andric         if (RegIndex < 8) {
597349cc55cSDimitry Andric           RegNo = getRegisterByIndex(IndexOffset + RegIndex);
598fe6060f1SDimitry Andric           return true;
599fe6060f1SDimitry Andric         }
600fe6060f1SDimitry Andric       }
601fe6060f1SDimitry Andric       break;
602fe6060f1SDimitry Andric     }
603fe6060f1SDimitry Andric 
604fe6060f1SDimitry Andric     case 's':
605fe6060f1SDimitry Andric       if (RegisterNameLower[1] == 'p') {
606fe6060f1SDimitry Andric         RegNo = M68k::SP;
607fe6060f1SDimitry Andric         return true;
608fe6060f1SDimitry Andric       } else if (RegisterNameLower[1] == 'r') {
609fe6060f1SDimitry Andric         RegNo = M68k::SR;
610fe6060f1SDimitry Andric         return true;
611fe6060f1SDimitry Andric       }
612fe6060f1SDimitry Andric       break;
613fe6060f1SDimitry Andric 
614fe6060f1SDimitry Andric     case 'p':
615fe6060f1SDimitry Andric       if (RegisterNameLower[1] == 'c') {
616fe6060f1SDimitry Andric         RegNo = M68k::PC;
617fe6060f1SDimitry Andric         return true;
618fe6060f1SDimitry Andric       }
619fe6060f1SDimitry Andric       break;
620fe6060f1SDimitry Andric     }
621fe6060f1SDimitry Andric   }
622fe6060f1SDimitry Andric 
623fe6060f1SDimitry Andric   return false;
624fe6060f1SDimitry Andric }
625fe6060f1SDimitry Andric 
626fe6060f1SDimitry Andric OperandMatchResultTy M68kAsmParser::parseRegister(unsigned &RegNo) {
627fe6060f1SDimitry Andric   bool HasPercent = false;
628fe6060f1SDimitry Andric   AsmToken PercentToken;
629fe6060f1SDimitry Andric 
630fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
631fe6060f1SDimitry Andric 
632fe6060f1SDimitry Andric   if (getTok().is(AsmToken::Percent)) {
633fe6060f1SDimitry Andric     HasPercent = true;
634fe6060f1SDimitry Andric     PercentToken = Lex();
635fe6060f1SDimitry Andric   } else if (!RegisterPrefixOptional.getValue()) {
636fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
637fe6060f1SDimitry Andric   }
638fe6060f1SDimitry Andric 
639fe6060f1SDimitry Andric   if (!Parser.getTok().is(AsmToken::Identifier)) {
640fe6060f1SDimitry Andric     if (HasPercent) {
641fe6060f1SDimitry Andric       getLexer().UnLex(PercentToken);
642fe6060f1SDimitry Andric     }
643fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
644fe6060f1SDimitry Andric   }
645fe6060f1SDimitry Andric 
646fe6060f1SDimitry Andric   auto RegisterName = Parser.getTok().getString();
647fe6060f1SDimitry Andric   if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
648fe6060f1SDimitry Andric     if (HasPercent) {
649fe6060f1SDimitry Andric       getLexer().UnLex(PercentToken);
650fe6060f1SDimitry Andric     }
651fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
652fe6060f1SDimitry Andric   }
653fe6060f1SDimitry Andric 
654fe6060f1SDimitry Andric   Parser.Lex();
655fe6060f1SDimitry Andric   return MatchOperand_Success;
656fe6060f1SDimitry Andric }
657fe6060f1SDimitry Andric 
658fe6060f1SDimitry Andric bool M68kAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
659fe6060f1SDimitry Andric                                   SMLoc &EndLoc) {
660fe6060f1SDimitry Andric   auto Result = tryParseRegister(RegNo, StartLoc, EndLoc);
661fe6060f1SDimitry Andric   if (Result != MatchOperand_Success) {
662fe6060f1SDimitry Andric     return Error(StartLoc, "expected register");
663fe6060f1SDimitry Andric   }
664fe6060f1SDimitry Andric 
665fe6060f1SDimitry Andric   return false;
666fe6060f1SDimitry Andric }
667fe6060f1SDimitry Andric 
668fe6060f1SDimitry Andric OperandMatchResultTy M68kAsmParser::tryParseRegister(unsigned &RegNo,
669fe6060f1SDimitry Andric                                                      SMLoc &StartLoc,
670fe6060f1SDimitry Andric                                                      SMLoc &EndLoc) {
671fe6060f1SDimitry Andric   StartLoc = getLexer().getLoc();
672fe6060f1SDimitry Andric   auto Result = parseRegister(RegNo);
673fe6060f1SDimitry Andric   EndLoc = getLexer().getLoc();
674fe6060f1SDimitry Andric   return Result;
675fe6060f1SDimitry Andric }
676fe6060f1SDimitry Andric 
677fe6060f1SDimitry Andric bool M68kAsmParser::isExpr() {
678fe6060f1SDimitry Andric   switch (Parser.getTok().getKind()) {
679fe6060f1SDimitry Andric   case AsmToken::Identifier:
680fe6060f1SDimitry Andric   case AsmToken::Integer:
681fe6060f1SDimitry Andric     return true;
682fe6060f1SDimitry Andric   case AsmToken::Minus:
683fe6060f1SDimitry Andric     return getLexer().peekTok().getKind() == AsmToken::Integer;
684fe6060f1SDimitry Andric 
685fe6060f1SDimitry Andric   default:
686fe6060f1SDimitry Andric     return false;
687fe6060f1SDimitry Andric   }
688fe6060f1SDimitry Andric }
689fe6060f1SDimitry Andric 
690fe6060f1SDimitry Andric OperandMatchResultTy M68kAsmParser::parseImm(OperandVector &Operands) {
691fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::Hash)) {
692fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
693fe6060f1SDimitry Andric   }
694fe6060f1SDimitry Andric   SMLoc Start = getLexer().getLoc();
695fe6060f1SDimitry Andric   Parser.Lex();
696fe6060f1SDimitry Andric 
697fe6060f1SDimitry Andric   SMLoc End;
698fe6060f1SDimitry Andric   const MCExpr *Expr;
699fe6060f1SDimitry Andric 
700fe6060f1SDimitry Andric   if (getParser().parseExpression(Expr, End)) {
701fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
702fe6060f1SDimitry Andric   }
703fe6060f1SDimitry Andric 
704fe6060f1SDimitry Andric   Operands.push_back(M68kOperand::createImm(Expr, Start, End));
705fe6060f1SDimitry Andric   return MatchOperand_Success;
706fe6060f1SDimitry Andric }
707fe6060f1SDimitry Andric 
708fe6060f1SDimitry Andric OperandMatchResultTy M68kAsmParser::parseMemOp(OperandVector &Operands) {
709fe6060f1SDimitry Andric   SMLoc Start = getLexer().getLoc();
710fe6060f1SDimitry Andric   bool IsPD = false;
711fe6060f1SDimitry Andric   M68kMemOp MemOp;
712fe6060f1SDimitry Andric 
713349cc55cSDimitry Andric   // Check for a plain register or register mask.
714349cc55cSDimitry Andric   auto Result = parseRegOrMoveMask(Operands);
715349cc55cSDimitry Andric   if (Result != llvm::MatchOperand_NoMatch) {
716fe6060f1SDimitry Andric     return Result;
717fe6060f1SDimitry Andric   }
718fe6060f1SDimitry Andric 
719fe6060f1SDimitry Andric   // Check for pre-decrement & outer displacement.
720fe6060f1SDimitry Andric   bool HasDisplacement = false;
721fe6060f1SDimitry Andric   if (getLexer().is(AsmToken::Minus)) {
722fe6060f1SDimitry Andric     IsPD = true;
723fe6060f1SDimitry Andric     Parser.Lex();
724fe6060f1SDimitry Andric   } else if (isExpr()) {
725fe6060f1SDimitry Andric     if (Parser.parseExpression(MemOp.OuterDisp)) {
726fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
727fe6060f1SDimitry Andric     }
728fe6060f1SDimitry Andric     HasDisplacement = true;
729fe6060f1SDimitry Andric   }
730fe6060f1SDimitry Andric 
731fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::LParen)) {
732fe6060f1SDimitry Andric     if (HasDisplacement) {
733fe6060f1SDimitry Andric       MemOp.Op = M68kMemOp::Kind::Addr;
734fe6060f1SDimitry Andric       Operands.push_back(
735fe6060f1SDimitry Andric           M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
736fe6060f1SDimitry Andric       return MatchOperand_Success;
737fe6060f1SDimitry Andric     } else if (IsPD) {
738fe6060f1SDimitry Andric       Error(getLexer().getLoc(), "expected (");
739fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
740fe6060f1SDimitry Andric     }
741fe6060f1SDimitry Andric 
742fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
743fe6060f1SDimitry Andric   }
744fe6060f1SDimitry Andric   Parser.Lex();
745fe6060f1SDimitry Andric 
746fe6060f1SDimitry Andric   // Check for constant dereference & MIT-style displacement
747fe6060f1SDimitry Andric   if (!HasDisplacement && isExpr()) {
748fe6060f1SDimitry Andric     if (Parser.parseExpression(MemOp.OuterDisp)) {
749fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
750fe6060f1SDimitry Andric     }
751fe6060f1SDimitry Andric     HasDisplacement = true;
752fe6060f1SDimitry Andric 
753fe6060f1SDimitry Andric     // If we're not followed by a comma, we're a constant dereference.
754fe6060f1SDimitry Andric     if (getLexer().isNot(AsmToken::Comma)) {
755fe6060f1SDimitry Andric       MemOp.Op = M68kMemOp::Kind::Addr;
756fe6060f1SDimitry Andric       Operands.push_back(
757fe6060f1SDimitry Andric           M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
758fe6060f1SDimitry Andric       return MatchOperand_Success;
759fe6060f1SDimitry Andric     }
760fe6060f1SDimitry Andric 
761fe6060f1SDimitry Andric     Parser.Lex();
762fe6060f1SDimitry Andric   }
763fe6060f1SDimitry Andric 
764fe6060f1SDimitry Andric   Result = parseRegister(MemOp.OuterReg);
765fe6060f1SDimitry Andric   if (Result == MatchOperand_ParseFail) {
766fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
767fe6060f1SDimitry Andric   }
768fe6060f1SDimitry Andric 
769fe6060f1SDimitry Andric   if (Result != MatchOperand_Success) {
770fe6060f1SDimitry Andric     Error(getLexer().getLoc(), "expected register");
771fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
772fe6060f1SDimitry Andric   }
773fe6060f1SDimitry Andric 
774fe6060f1SDimitry Andric   // Check for Index.
775fe6060f1SDimitry Andric   bool HasIndex = false;
776fe6060f1SDimitry Andric   if (Parser.getTok().is(AsmToken::Comma)) {
777fe6060f1SDimitry Andric     Parser.Lex();
778fe6060f1SDimitry Andric 
779fe6060f1SDimitry Andric     Result = parseRegister(MemOp.InnerReg);
780fe6060f1SDimitry Andric     if (Result == MatchOperand_ParseFail) {
781fe6060f1SDimitry Andric       return Result;
782fe6060f1SDimitry Andric     }
783fe6060f1SDimitry Andric 
784fe6060f1SDimitry Andric     if (Result == MatchOperand_NoMatch) {
785fe6060f1SDimitry Andric       Error(getLexer().getLoc(), "expected register");
786fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
787fe6060f1SDimitry Andric     }
788fe6060f1SDimitry Andric 
789fe6060f1SDimitry Andric     // TODO: parse size, scale and inner displacement.
790fe6060f1SDimitry Andric     MemOp.Size = 4;
791fe6060f1SDimitry Andric     MemOp.Scale = 1;
792fe6060f1SDimitry Andric     MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);
793fe6060f1SDimitry Andric     HasIndex = true;
794fe6060f1SDimitry Andric   }
795fe6060f1SDimitry Andric 
796fe6060f1SDimitry Andric   if (Parser.getTok().isNot(AsmToken::RParen)) {
797fe6060f1SDimitry Andric     Error(getLexer().getLoc(), "expected )");
798fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
799fe6060f1SDimitry Andric   }
800fe6060f1SDimitry Andric   Parser.Lex();
801fe6060f1SDimitry Andric 
802fe6060f1SDimitry Andric   bool IsPI = false;
803fe6060f1SDimitry Andric   if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {
804fe6060f1SDimitry Andric     Parser.Lex();
805fe6060f1SDimitry Andric     IsPI = true;
806fe6060f1SDimitry Andric   }
807fe6060f1SDimitry Andric 
808fe6060f1SDimitry Andric   SMLoc End = getLexer().getLoc();
809fe6060f1SDimitry Andric 
810fe6060f1SDimitry Andric   unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
811fe6060f1SDimitry Andric   if (OpCount > 1) {
812fe6060f1SDimitry Andric     Error(Start, "only one of post-increment, pre-decrement or displacement "
813fe6060f1SDimitry Andric                  "can be used");
814fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
815fe6060f1SDimitry Andric   }
816fe6060f1SDimitry Andric 
817fe6060f1SDimitry Andric   if (IsPD) {
818fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
819fe6060f1SDimitry Andric   } else if (IsPI) {
820fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
821fe6060f1SDimitry Andric   } else if (HasIndex) {
822fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
823fe6060f1SDimitry Andric   } else if (HasDisplacement) {
824fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
825fe6060f1SDimitry Andric   } else {
826fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegIndirect;
827fe6060f1SDimitry Andric   }
828fe6060f1SDimitry Andric 
829fe6060f1SDimitry Andric   Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
830fe6060f1SDimitry Andric   return MatchOperand_Success;
831fe6060f1SDimitry Andric }
832fe6060f1SDimitry Andric 
833349cc55cSDimitry Andric OperandMatchResultTy
834349cc55cSDimitry Andric M68kAsmParser::parseRegOrMoveMask(OperandVector &Operands) {
835349cc55cSDimitry Andric   SMLoc Start = getLexer().getLoc();
836349cc55cSDimitry Andric   M68kMemOp MemOp(M68kMemOp::Kind::RegMask);
837349cc55cSDimitry Andric   MemOp.RegMask = 0;
838349cc55cSDimitry Andric 
839349cc55cSDimitry Andric   for (;;) {
840349cc55cSDimitry Andric     bool IsFirstRegister =
841349cc55cSDimitry Andric         (MemOp.Op == M68kMemOp::Kind::RegMask) && (MemOp.RegMask == 0);
842349cc55cSDimitry Andric 
843349cc55cSDimitry Andric     unsigned FirstRegister;
844349cc55cSDimitry Andric     auto Result = parseRegister(FirstRegister);
845349cc55cSDimitry Andric     if (IsFirstRegister && (Result == llvm::MatchOperand_NoMatch)) {
846349cc55cSDimitry Andric       return MatchOperand_NoMatch;
847349cc55cSDimitry Andric     }
848349cc55cSDimitry Andric     if (Result != llvm::MatchOperand_Success) {
849349cc55cSDimitry Andric       Error(getLexer().getLoc(), "expected start register");
850349cc55cSDimitry Andric       return MatchOperand_ParseFail;
851349cc55cSDimitry Andric     }
852349cc55cSDimitry Andric 
853349cc55cSDimitry Andric     unsigned LastRegister = FirstRegister;
854349cc55cSDimitry Andric     if (getLexer().is(AsmToken::Minus)) {
855349cc55cSDimitry Andric       getLexer().Lex();
856349cc55cSDimitry Andric       Result = parseRegister(LastRegister);
857349cc55cSDimitry Andric       if (Result != llvm::MatchOperand_Success) {
858349cc55cSDimitry Andric         Error(getLexer().getLoc(), "expected end register");
859349cc55cSDimitry Andric         return MatchOperand_ParseFail;
860349cc55cSDimitry Andric       }
861349cc55cSDimitry Andric     }
862349cc55cSDimitry Andric 
863349cc55cSDimitry Andric     unsigned FirstRegisterIndex = getRegisterIndex(FirstRegister);
864349cc55cSDimitry Andric     unsigned LastRegisterIndex = getRegisterIndex(LastRegister);
865349cc55cSDimitry Andric 
866349cc55cSDimitry Andric     uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1;
867349cc55cSDimitry Andric     uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex;
868349cc55cSDimitry Andric 
869349cc55cSDimitry Andric     if (IsFirstRegister && (FirstRegister == LastRegister)) {
870349cc55cSDimitry Andric       // First register range is a single register, simplify to just Reg
871349cc55cSDimitry Andric       // so that it matches more operands.
872349cc55cSDimitry Andric       MemOp.Op = M68kMemOp::Kind::Reg;
873349cc55cSDimitry Andric       MemOp.OuterReg = FirstRegister;
874349cc55cSDimitry Andric     } else {
875349cc55cSDimitry Andric       if (MemOp.Op == M68kMemOp::Kind::Reg) {
876349cc55cSDimitry Andric         // This is the second register being specified - expand the Reg operand
877349cc55cSDimitry Andric         // into a mask first.
878349cc55cSDimitry Andric         MemOp.Op = M68kMemOp::Kind::RegMask;
879349cc55cSDimitry Andric         MemOp.RegMask = 1 << getRegisterIndex(MemOp.OuterReg);
880349cc55cSDimitry Andric 
881349cc55cSDimitry Andric         if (MemOp.RegMask == 0) {
882349cc55cSDimitry Andric           Error(getLexer().getLoc(),
883349cc55cSDimitry Andric                 "special registers cannot be used in register masks");
884349cc55cSDimitry Andric           return MatchOperand_ParseFail;
885349cc55cSDimitry Andric         }
886349cc55cSDimitry Andric       }
887349cc55cSDimitry Andric 
888349cc55cSDimitry Andric       if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16)) {
889349cc55cSDimitry Andric         Error(getLexer().getLoc(),
890349cc55cSDimitry Andric               "special registers cannot be used in register masks");
891349cc55cSDimitry Andric         return MatchOperand_ParseFail;
892349cc55cSDimitry Andric       }
893349cc55cSDimitry Andric 
894349cc55cSDimitry Andric       if (NewMaskBits & MemOp.RegMask) {
895349cc55cSDimitry Andric         Error(getLexer().getLoc(), "conflicting masked registers");
896349cc55cSDimitry Andric         return MatchOperand_ParseFail;
897349cc55cSDimitry Andric       }
898349cc55cSDimitry Andric 
899349cc55cSDimitry Andric       MemOp.RegMask |= NewMaskBits;
900349cc55cSDimitry Andric     }
901349cc55cSDimitry Andric 
902349cc55cSDimitry Andric     if (getLexer().isNot(AsmToken::Slash)) {
903349cc55cSDimitry Andric       break;
904349cc55cSDimitry Andric     }
905349cc55cSDimitry Andric 
906349cc55cSDimitry Andric     getLexer().Lex();
907349cc55cSDimitry Andric   }
908349cc55cSDimitry Andric 
909349cc55cSDimitry Andric   Operands.push_back(
910349cc55cSDimitry Andric       M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
911349cc55cSDimitry Andric   return MatchOperand_Success;
912349cc55cSDimitry Andric }
913349cc55cSDimitry Andric 
914fe6060f1SDimitry Andric void M68kAsmParser::eatComma() {
915fe6060f1SDimitry Andric   if (Parser.getTok().is(AsmToken::Comma)) {
916fe6060f1SDimitry Andric     Parser.Lex();
917fe6060f1SDimitry Andric   }
918fe6060f1SDimitry Andric }
919fe6060f1SDimitry Andric 
920fe6060f1SDimitry Andric bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
921fe6060f1SDimitry Andric                                      SMLoc NameLoc, OperandVector &Operands) {
922fe6060f1SDimitry Andric   SMLoc Start = getLexer().getLoc();
923fe6060f1SDimitry Andric   Operands.push_back(M68kOperand::createToken(Name, Start, Start));
924fe6060f1SDimitry Andric 
925fe6060f1SDimitry Andric   bool First = true;
926fe6060f1SDimitry Andric   while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
927fe6060f1SDimitry Andric     if (!First) {
928fe6060f1SDimitry Andric       eatComma();
929fe6060f1SDimitry Andric     } else {
930fe6060f1SDimitry Andric       First = false;
931fe6060f1SDimitry Andric     }
932fe6060f1SDimitry Andric 
933fe6060f1SDimitry Andric     auto MatchResult = MatchOperandParserImpl(Operands, Name);
934fe6060f1SDimitry Andric     if (MatchResult == MatchOperand_Success) {
935fe6060f1SDimitry Andric       continue;
936fe6060f1SDimitry Andric     }
937fe6060f1SDimitry Andric 
938fe6060f1SDimitry Andric     // Add custom operand formats here...
939fe6060f1SDimitry Andric     SMLoc Loc = getLexer().getLoc();
940fe6060f1SDimitry Andric     Parser.eatToEndOfStatement();
941fe6060f1SDimitry Andric     return Error(Loc, "unexpected token parsing operands");
942fe6060f1SDimitry Andric   }
943fe6060f1SDimitry Andric 
944fe6060f1SDimitry Andric   // Eat EndOfStatement.
945fe6060f1SDimitry Andric   Parser.Lex();
946fe6060f1SDimitry Andric   return false;
947fe6060f1SDimitry Andric }
948fe6060f1SDimitry Andric 
949fe6060f1SDimitry Andric bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
950fe6060f1SDimitry Andric 
951fe6060f1SDimitry Andric bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
952fe6060f1SDimitry Andric                                    OperandVector const &Operands,
953fe6060f1SDimitry Andric                                    uint64_t const &ErrorInfo) {
954fe6060f1SDimitry Andric   SMLoc ErrorLoc = Loc;
955fe6060f1SDimitry Andric   char const *Diag = 0;
956fe6060f1SDimitry Andric 
957fe6060f1SDimitry Andric   if (ErrorInfo != ~0U) {
958fe6060f1SDimitry Andric     if (ErrorInfo >= Operands.size()) {
959fe6060f1SDimitry Andric       Diag = "too few operands for instruction.";
960fe6060f1SDimitry Andric     } else {
961fe6060f1SDimitry Andric       auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
962fe6060f1SDimitry Andric       if (Op.getStartLoc() != SMLoc()) {
963fe6060f1SDimitry Andric         ErrorLoc = Op.getStartLoc();
964fe6060f1SDimitry Andric       }
965fe6060f1SDimitry Andric     }
966fe6060f1SDimitry Andric   }
967fe6060f1SDimitry Andric 
968fe6060f1SDimitry Andric   if (!Diag) {
969fe6060f1SDimitry Andric     Diag = "invalid operand for instruction";
970fe6060f1SDimitry Andric   }
971fe6060f1SDimitry Andric 
972fe6060f1SDimitry Andric   return Error(ErrorLoc, Diag);
973fe6060f1SDimitry Andric }
974fe6060f1SDimitry Andric 
975fe6060f1SDimitry Andric bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc,
976fe6060f1SDimitry Andric                                    uint64_t const &ErrorInfo) {
977fe6060f1SDimitry Andric   return Error(Loc, "instruction requires a CPU feature not currently enabled");
978fe6060f1SDimitry Andric }
979fe6060f1SDimitry Andric 
980fe6060f1SDimitry Andric bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc,
981fe6060f1SDimitry Andric                          MCStreamer &Out) const {
982fe6060f1SDimitry Andric   Inst.setLoc(Loc);
983fe6060f1SDimitry Andric   Out.emitInstruction(Inst, STI);
984fe6060f1SDimitry Andric 
985fe6060f1SDimitry Andric   return false;
986fe6060f1SDimitry Andric }
987fe6060f1SDimitry Andric 
988fe6060f1SDimitry Andric bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
989fe6060f1SDimitry Andric                                             OperandVector &Operands,
990fe6060f1SDimitry Andric                                             MCStreamer &Out,
991fe6060f1SDimitry Andric                                             uint64_t &ErrorInfo,
992fe6060f1SDimitry Andric                                             bool MatchingInlineAsm) {
993fe6060f1SDimitry Andric   MCInst Inst;
994fe6060f1SDimitry Andric   unsigned MatchResult =
995fe6060f1SDimitry Andric       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
996fe6060f1SDimitry Andric 
997fe6060f1SDimitry Andric   switch (MatchResult) {
998fe6060f1SDimitry Andric   case Match_Success:
999fe6060f1SDimitry Andric     return emit(Inst, Loc, Out);
1000fe6060f1SDimitry Andric   case Match_MissingFeature:
1001fe6060f1SDimitry Andric     return missingFeature(Loc, ErrorInfo);
1002fe6060f1SDimitry Andric   case Match_InvalidOperand:
1003fe6060f1SDimitry Andric     return invalidOperand(Loc, Operands, ErrorInfo);
1004fe6060f1SDimitry Andric   case Match_MnemonicFail:
1005fe6060f1SDimitry Andric     return Error(Loc, "invalid instruction");
1006fe6060f1SDimitry Andric   default:
1007fe6060f1SDimitry Andric     return true;
1008fe6060f1SDimitry Andric   }
1009fe6060f1SDimitry Andric }
1010fe6060f1SDimitry Andric 
1011fe6060f1SDimitry Andric void M68kOperand::print(raw_ostream &OS) const {
1012fe6060f1SDimitry Andric   switch (Kind) {
101369ade1e0SDimitry Andric   case KindTy::Invalid:
1014fe6060f1SDimitry Andric     OS << "invalid";
1015fe6060f1SDimitry Andric     break;
1016fe6060f1SDimitry Andric 
101769ade1e0SDimitry Andric   case KindTy::Token:
1018fe6060f1SDimitry Andric     OS << "token '" << Token << "'";
1019fe6060f1SDimitry Andric     break;
1020fe6060f1SDimitry Andric 
102169ade1e0SDimitry Andric   case KindTy::Imm:
1022fe6060f1SDimitry Andric     OS << "immediate " << Imm;
1023fe6060f1SDimitry Andric     break;
1024fe6060f1SDimitry Andric 
102569ade1e0SDimitry Andric   case KindTy::MemOp:
1026fe6060f1SDimitry Andric     MemOp.print(OS);
1027fe6060f1SDimitry Andric     break;
1028fe6060f1SDimitry Andric   }
1029fe6060f1SDimitry Andric }
1030