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