xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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;
46bdd1243dSDimitry Andric   bool parseRegisterName(MCRegister &RegNo, SMLoc Loc, StringRef RegisterName);
4706c3fb27SDimitry Andric   ParseStatus parseRegister(MCRegister &RegNo);
48fe6060f1SDimitry Andric 
49fe6060f1SDimitry Andric   // Parser functions.
50fe6060f1SDimitry Andric   void eatComma();
51fe6060f1SDimitry Andric 
52fe6060f1SDimitry Andric   bool isExpr();
5306c3fb27SDimitry Andric   ParseStatus parseImm(OperandVector &Operands);
5406c3fb27SDimitry Andric   ParseStatus parseMemOp(OperandVector &Operands);
5506c3fb27SDimitry Andric   ParseStatus 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;
695f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
705f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, 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 MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
75fe6060f1SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
76fe6060f1SDimitry Andric                                uint64_t &ErrorInfo,
77fe6060f1SDimitry Andric                                bool MatchingInlineAsm) override;
78fe6060f1SDimitry Andric };
79fe6060f1SDimitry Andric 
80fe6060f1SDimitry Andric struct M68kMemOp {
81fe6060f1SDimitry Andric   enum class Kind {
82fe6060f1SDimitry Andric     Addr,
83349cc55cSDimitry Andric     RegMask,
84fe6060f1SDimitry Andric     Reg,
85fe6060f1SDimitry Andric     RegIndirect,
86fe6060f1SDimitry Andric     RegPostIncrement,
87fe6060f1SDimitry Andric     RegPreDecrement,
88fe6060f1SDimitry Andric     RegIndirectDisplacement,
89fe6060f1SDimitry Andric     RegIndirectDisplacementIndex,
90fe6060f1SDimitry Andric   };
91fe6060f1SDimitry Andric 
92fe6060f1SDimitry Andric   // These variables are used for the following forms:
93fe6060f1SDimitry Andric   // Addr: (OuterDisp)
94349cc55cSDimitry Andric   // RegMask: RegMask (as register mask)
95fe6060f1SDimitry Andric   // Reg: %OuterReg
96fe6060f1SDimitry Andric   // RegIndirect: (%OuterReg)
97fe6060f1SDimitry Andric   // RegPostIncrement: (%OuterReg)+
98fe6060f1SDimitry Andric   // RegPreDecrement: -(%OuterReg)
99fe6060f1SDimitry Andric   // RegIndirectDisplacement: OuterDisp(%OuterReg)
100fe6060f1SDimitry Andric   // RegIndirectDisplacementIndex:
101fe6060f1SDimitry Andric   //   OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)
102fe6060f1SDimitry Andric 
103fe6060f1SDimitry Andric   Kind Op;
104bdd1243dSDimitry Andric   MCRegister OuterReg;
105bdd1243dSDimitry Andric   MCRegister InnerReg;
106fe6060f1SDimitry Andric   const MCExpr *OuterDisp;
107fe6060f1SDimitry Andric   const MCExpr *InnerDisp;
108fe6060f1SDimitry Andric   uint8_t Size : 4;
109fe6060f1SDimitry Andric   uint8_t Scale : 4;
110fe6060f1SDimitry Andric   const MCExpr *Expr;
111349cc55cSDimitry Andric   uint16_t RegMask;
112fe6060f1SDimitry Andric 
113fe6060f1SDimitry Andric   M68kMemOp() {}
114fe6060f1SDimitry Andric   M68kMemOp(Kind Op) : Op(Op) {}
115fe6060f1SDimitry Andric 
116fe6060f1SDimitry Andric   void print(raw_ostream &OS) const;
117fe6060f1SDimitry Andric };
118fe6060f1SDimitry Andric 
119fe6060f1SDimitry Andric /// An parsed M68k assembly operand.
120fe6060f1SDimitry Andric class M68kOperand : public MCParsedAsmOperand {
121fe6060f1SDimitry Andric   typedef MCParsedAsmOperand Base;
122fe6060f1SDimitry Andric 
12369ade1e0SDimitry Andric   enum class KindTy {
124fe6060f1SDimitry Andric     Invalid,
125fe6060f1SDimitry Andric     Token,
126fe6060f1SDimitry Andric     Imm,
127fe6060f1SDimitry Andric     MemOp,
128fe6060f1SDimitry Andric   };
129fe6060f1SDimitry Andric 
13069ade1e0SDimitry Andric   KindTy Kind;
131fe6060f1SDimitry Andric   SMLoc Start, End;
132fe6060f1SDimitry Andric   union {
133fe6060f1SDimitry Andric     StringRef Token;
134fe6060f1SDimitry Andric     const MCExpr *Expr;
135fe6060f1SDimitry Andric     M68kMemOp MemOp;
136fe6060f1SDimitry Andric   };
137fe6060f1SDimitry Andric 
138349cc55cSDimitry Andric   template <unsigned N> bool isAddrN() const;
139349cc55cSDimitry Andric 
140fe6060f1SDimitry Andric public:
14169ade1e0SDimitry Andric   M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)
142fe6060f1SDimitry Andric       : Base(), Kind(Kind), Start(Start), End(End) {}
143fe6060f1SDimitry Andric 
144fe6060f1SDimitry Andric   SMLoc getStartLoc() const override { return Start; }
145fe6060f1SDimitry Andric   SMLoc getEndLoc() const override { return End; }
146fe6060f1SDimitry Andric 
147fe6060f1SDimitry Andric   void print(raw_ostream &OS) const override;
148fe6060f1SDimitry Andric 
149fe6060f1SDimitry Andric   bool isMem() const override { return false; }
15069ade1e0SDimitry Andric   bool isMemOp() const { return Kind == KindTy::MemOp; }
151fe6060f1SDimitry Andric 
152fe6060f1SDimitry Andric   static void addExpr(MCInst &Inst, const MCExpr *Expr);
153fe6060f1SDimitry Andric 
154fe6060f1SDimitry Andric   // Reg
155fe6060f1SDimitry Andric   bool isReg() const override;
156349cc55cSDimitry Andric   bool isAReg() const;
157349cc55cSDimitry Andric   bool isDReg() const;
15806c3fb27SDimitry Andric   bool isFPDReg() const;
1595f757f3fSDimitry Andric   bool isFPCReg() const;
160*0fca6ea1SDimitry Andric   MCRegister 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 
17906c3fb27SDimitry Andric   // Imm for TRAP instruction
18006c3fb27SDimitry Andric   bool isTrapImm() const;
18106c3fb27SDimitry Andric   // Imm for BKPT instruction
18206c3fb27SDimitry Andric   bool isBkptImm() const;
18306c3fb27SDimitry Andric 
184349cc55cSDimitry Andric   // MoveMask
185349cc55cSDimitry Andric   bool isMoveMask() const;
186349cc55cSDimitry Andric   void addMoveMaskOperands(MCInst &Inst, unsigned N) const;
187349cc55cSDimitry Andric 
188fe6060f1SDimitry Andric   // Addr
189fe6060f1SDimitry Andric   bool isAddr() const;
190349cc55cSDimitry Andric   bool isAddr8() const { return isAddrN<8>(); }
191349cc55cSDimitry Andric   bool isAddr16() const { return isAddrN<16>(); }
192349cc55cSDimitry Andric   bool isAddr32() const { return isAddrN<32>(); }
193fe6060f1SDimitry Andric   void addAddrOperands(MCInst &Inst, unsigned N) const;
194fe6060f1SDimitry Andric 
195fe6060f1SDimitry Andric   // ARI
196fe6060f1SDimitry Andric   bool isARI() const;
197fe6060f1SDimitry Andric   void addARIOperands(MCInst &Inst, unsigned N) const;
198fe6060f1SDimitry Andric 
199fe6060f1SDimitry Andric   // ARID
200fe6060f1SDimitry Andric   bool isARID() const;
201fe6060f1SDimitry Andric   void addARIDOperands(MCInst &Inst, unsigned N) const;
202fe6060f1SDimitry Andric 
203fe6060f1SDimitry Andric   // ARII
204fe6060f1SDimitry Andric   bool isARII() const;
205fe6060f1SDimitry Andric   void addARIIOperands(MCInst &Inst, unsigned N) const;
206fe6060f1SDimitry Andric 
207fe6060f1SDimitry Andric   // ARIPD
208fe6060f1SDimitry Andric   bool isARIPD() const;
209fe6060f1SDimitry Andric   void addARIPDOperands(MCInst &Inst, unsigned N) const;
210fe6060f1SDimitry Andric 
211fe6060f1SDimitry Andric   // ARIPI
212fe6060f1SDimitry Andric   bool isARIPI() const;
213fe6060f1SDimitry Andric   void addARIPIOperands(MCInst &Inst, unsigned N) const;
214fe6060f1SDimitry Andric 
215fe6060f1SDimitry Andric   // PCD
216fe6060f1SDimitry Andric   bool isPCD() const;
217fe6060f1SDimitry Andric   void addPCDOperands(MCInst &Inst, unsigned N) const;
218fe6060f1SDimitry Andric 
219fe6060f1SDimitry Andric   // PCI
220fe6060f1SDimitry Andric   bool isPCI() const;
221fe6060f1SDimitry Andric   void addPCIOperands(MCInst &Inst, unsigned N) const;
222fe6060f1SDimitry Andric };
223fe6060f1SDimitry Andric 
224fe6060f1SDimitry Andric } // end anonymous namespace.
225fe6060f1SDimitry Andric 
226fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() {
227fe6060f1SDimitry Andric   RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget());
228fe6060f1SDimitry Andric }
229fe6060f1SDimitry Andric 
23006c3fb27SDimitry Andric #define GET_REGISTER_MATCHER
231fe6060f1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
232fe6060f1SDimitry Andric #include "M68kGenAsmMatcher.inc"
233fe6060f1SDimitry Andric 
234349cc55cSDimitry Andric static inline unsigned getRegisterByIndex(unsigned RegisterIndex) {
235349cc55cSDimitry Andric   static unsigned RegistersByIndex[] = {
236349cc55cSDimitry Andric       M68k::D0,  M68k::D1,  M68k::D2,  M68k::D3,  M68k::D4,  M68k::D5,
237349cc55cSDimitry Andric       M68k::D6,  M68k::D7,  M68k::A0,  M68k::A1,  M68k::A2,  M68k::A3,
23806c3fb27SDimitry Andric       M68k::A4,  M68k::A5,  M68k::A6,  M68k::SP,  M68k::FP0, M68k::FP1,
23906c3fb27SDimitry Andric       M68k::FP2, M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7};
240349cc55cSDimitry Andric   assert(RegisterIndex <=
241349cc55cSDimitry Andric          sizeof(RegistersByIndex) / sizeof(RegistersByIndex[0]));
242349cc55cSDimitry Andric   return RegistersByIndex[RegisterIndex];
243349cc55cSDimitry Andric }
244349cc55cSDimitry Andric 
245349cc55cSDimitry Andric static inline unsigned getRegisterIndex(unsigned Register) {
246349cc55cSDimitry Andric   if (Register >= M68k::D0 && Register <= M68k::D7)
247349cc55cSDimitry Andric     return Register - M68k::D0;
248349cc55cSDimitry Andric   if (Register >= M68k::A0 && Register <= M68k::A6)
249349cc55cSDimitry Andric     return Register - M68k::A0 + 8;
25006c3fb27SDimitry Andric   if (Register >= M68k::FP0 && Register <= M68k::FP7)
25106c3fb27SDimitry Andric     return Register - M68k::FP0 + 16;
252349cc55cSDimitry Andric 
253349cc55cSDimitry Andric   switch (Register) {
254349cc55cSDimitry Andric   case M68k::SP:
255349cc55cSDimitry Andric     // SP is sadly not contiguous with the rest of the An registers
256349cc55cSDimitry Andric     return 15;
257349cc55cSDimitry Andric 
2585f757f3fSDimitry Andric   // We don't care about the indices of these registers.
259349cc55cSDimitry Andric   case M68k::PC:
260349cc55cSDimitry Andric   case M68k::CCR:
2615f757f3fSDimitry Andric   case M68k::FPC:
2625f757f3fSDimitry Andric   case M68k::FPS:
2635f757f3fSDimitry Andric   case M68k::FPIAR:
2645f757f3fSDimitry Andric     return UINT_MAX;
265349cc55cSDimitry Andric 
266349cc55cSDimitry Andric   default:
267349cc55cSDimitry Andric     llvm_unreachable("unexpected register number");
268349cc55cSDimitry Andric   }
269349cc55cSDimitry Andric }
270349cc55cSDimitry Andric 
271fe6060f1SDimitry Andric void M68kMemOp::print(raw_ostream &OS) const {
272fe6060f1SDimitry Andric   switch (Op) {
273fe6060f1SDimitry Andric   case Kind::Addr:
274fe6060f1SDimitry Andric     OS << OuterDisp;
275fe6060f1SDimitry Andric     break;
276349cc55cSDimitry Andric   case Kind::RegMask:
277349cc55cSDimitry Andric     OS << "RegMask(" << format("%04x", RegMask) << ")";
278349cc55cSDimitry Andric     break;
279fe6060f1SDimitry Andric   case Kind::Reg:
280fe6060f1SDimitry Andric     OS << '%' << OuterReg;
281fe6060f1SDimitry Andric     break;
282fe6060f1SDimitry Andric   case Kind::RegIndirect:
283fe6060f1SDimitry Andric     OS << "(%" << OuterReg << ')';
284fe6060f1SDimitry Andric     break;
285fe6060f1SDimitry Andric   case Kind::RegPostIncrement:
286fe6060f1SDimitry Andric     OS << "(%" << OuterReg << ")+";
287fe6060f1SDimitry Andric     break;
288fe6060f1SDimitry Andric   case Kind::RegPreDecrement:
289fe6060f1SDimitry Andric     OS << "-(%" << OuterReg << ")";
290fe6060f1SDimitry Andric     break;
291fe6060f1SDimitry Andric   case Kind::RegIndirectDisplacement:
292fe6060f1SDimitry Andric     OS << OuterDisp << "(%" << OuterReg << ")";
293fe6060f1SDimitry Andric     break;
294fe6060f1SDimitry Andric   case Kind::RegIndirectDisplacementIndex:
295fe6060f1SDimitry Andric     OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size
296fe6060f1SDimitry Andric        << ", " << InnerDisp << ")";
297fe6060f1SDimitry Andric     break;
298fe6060f1SDimitry Andric   }
299fe6060f1SDimitry Andric }
300fe6060f1SDimitry Andric 
301fe6060f1SDimitry Andric void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {
302fe6060f1SDimitry Andric   if (auto Const = dyn_cast<MCConstantExpr>(Expr)) {
303fe6060f1SDimitry Andric     Inst.addOperand(MCOperand::createImm(Const->getValue()));
304fe6060f1SDimitry Andric     return;
305fe6060f1SDimitry Andric   }
306fe6060f1SDimitry Andric 
307fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createExpr(Expr));
308fe6060f1SDimitry Andric }
309fe6060f1SDimitry Andric 
310fe6060f1SDimitry Andric // Reg
311fe6060f1SDimitry Andric bool M68kOperand::isReg() const {
31269ade1e0SDimitry Andric   return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
313fe6060f1SDimitry Andric }
314fe6060f1SDimitry Andric 
315*0fca6ea1SDimitry Andric MCRegister M68kOperand::getReg() const {
316fe6060f1SDimitry Andric   assert(isReg());
317fe6060f1SDimitry Andric   return MemOp.OuterReg;
318fe6060f1SDimitry Andric }
319fe6060f1SDimitry Andric 
320fe6060f1SDimitry Andric void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {
321fe6060f1SDimitry Andric   assert(isReg() && "wrong operand kind");
322fe6060f1SDimitry Andric   assert((N == 1) && "can only handle one register operand");
323fe6060f1SDimitry Andric 
324fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(getReg()));
325fe6060f1SDimitry Andric }
326fe6060f1SDimitry Andric 
327fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,
328fe6060f1SDimitry Andric                                                       SMLoc Start, SMLoc End) {
32969ade1e0SDimitry Andric   auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start, End);
330fe6060f1SDimitry Andric   Op->MemOp = MemOp;
331fe6060f1SDimitry Andric   return Op;
332fe6060f1SDimitry Andric }
333fe6060f1SDimitry Andric 
334fe6060f1SDimitry Andric // Token
33569ade1e0SDimitry Andric bool M68kOperand::isToken() const { return Kind == KindTy::Token; }
336fe6060f1SDimitry Andric StringRef M68kOperand::getToken() const {
337fe6060f1SDimitry Andric   assert(isToken());
338fe6060f1SDimitry Andric   return Token;
339fe6060f1SDimitry Andric }
340fe6060f1SDimitry Andric 
341fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,
342fe6060f1SDimitry Andric                                                       SMLoc Start, SMLoc End) {
34369ade1e0SDimitry Andric   auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start, End);
344fe6060f1SDimitry Andric   Op->Token = Token;
345fe6060f1SDimitry Andric   return Op;
346fe6060f1SDimitry Andric }
347fe6060f1SDimitry Andric 
348fe6060f1SDimitry Andric // Imm
34969ade1e0SDimitry Andric bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }
350fe6060f1SDimitry Andric void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {
351349cc55cSDimitry Andric   assert(isImm() && "wrong operand kind");
352fe6060f1SDimitry Andric   assert((N == 1) && "can only handle one register operand");
353fe6060f1SDimitry Andric 
354fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, Expr);
355fe6060f1SDimitry Andric }
356fe6060f1SDimitry Andric 
357fe6060f1SDimitry Andric std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,
358fe6060f1SDimitry Andric                                                     SMLoc Start, SMLoc End) {
35969ade1e0SDimitry Andric   auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start, End);
360fe6060f1SDimitry Andric   Op->Expr = Expr;
361fe6060f1SDimitry Andric   return Op;
362fe6060f1SDimitry Andric }
363fe6060f1SDimitry Andric 
36406c3fb27SDimitry Andric bool M68kOperand::isTrapImm() const {
36506c3fb27SDimitry Andric   int64_t Value;
36606c3fb27SDimitry Andric   if (!isImm() || !Expr->evaluateAsAbsolute(Value))
36706c3fb27SDimitry Andric     return false;
36806c3fb27SDimitry Andric 
36906c3fb27SDimitry Andric   return isUInt<4>(Value);
37006c3fb27SDimitry Andric }
37106c3fb27SDimitry Andric 
37206c3fb27SDimitry Andric bool M68kOperand::isBkptImm() const {
37306c3fb27SDimitry Andric   int64_t Value;
37406c3fb27SDimitry Andric   if (!isImm() || !Expr->evaluateAsAbsolute(Value))
37506c3fb27SDimitry Andric     return false;
37606c3fb27SDimitry Andric 
37706c3fb27SDimitry Andric   return isUInt<3>(Value);
37806c3fb27SDimitry Andric }
37906c3fb27SDimitry Andric 
380349cc55cSDimitry Andric // MoveMask
381349cc55cSDimitry Andric bool M68kOperand::isMoveMask() const {
382349cc55cSDimitry Andric   if (!isMemOp())
383349cc55cSDimitry Andric     return false;
384349cc55cSDimitry Andric 
385349cc55cSDimitry Andric   if (MemOp.Op == M68kMemOp::Kind::RegMask)
386349cc55cSDimitry Andric     return true;
387349cc55cSDimitry Andric 
388349cc55cSDimitry Andric   if (MemOp.Op != M68kMemOp::Kind::Reg)
389349cc55cSDimitry Andric     return false;
390349cc55cSDimitry Andric 
391349cc55cSDimitry Andric   // Only regular address / data registers are allowed to be used
392349cc55cSDimitry Andric   // in register masks.
393349cc55cSDimitry Andric   return getRegisterIndex(MemOp.OuterReg) < 16;
394349cc55cSDimitry Andric }
395349cc55cSDimitry Andric 
396349cc55cSDimitry Andric void M68kOperand::addMoveMaskOperands(MCInst &Inst, unsigned N) const {
397349cc55cSDimitry Andric   assert(isMoveMask() && "wrong operand kind");
398349cc55cSDimitry Andric   assert((N == 1) && "can only handle one immediate operand");
399349cc55cSDimitry Andric 
400349cc55cSDimitry Andric   uint16_t MoveMask = MemOp.RegMask;
401349cc55cSDimitry Andric   if (MemOp.Op == M68kMemOp::Kind::Reg)
402349cc55cSDimitry Andric     MoveMask = 1 << getRegisterIndex(MemOp.OuterReg);
403349cc55cSDimitry Andric 
404349cc55cSDimitry Andric   Inst.addOperand(MCOperand::createImm(MoveMask));
405349cc55cSDimitry Andric }
406349cc55cSDimitry Andric 
407fe6060f1SDimitry Andric // Addr
408fe6060f1SDimitry Andric bool M68kOperand::isAddr() const {
409fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
410fe6060f1SDimitry Andric }
411349cc55cSDimitry Andric // TODO: Maybe we can also store the size of OuterDisp
412349cc55cSDimitry Andric // in Size?
413349cc55cSDimitry Andric template <unsigned N> bool M68kOperand::isAddrN() const {
414349cc55cSDimitry Andric   if (isAddr()) {
415349cc55cSDimitry Andric     int64_t Res;
416349cc55cSDimitry Andric     if (MemOp.OuterDisp->evaluateAsAbsolute(Res))
417349cc55cSDimitry Andric       return isInt<N>(Res);
418349cc55cSDimitry Andric     return true;
419349cc55cSDimitry Andric   }
420349cc55cSDimitry Andric   return false;
421349cc55cSDimitry Andric }
422fe6060f1SDimitry Andric void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
423fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
424fe6060f1SDimitry Andric }
425fe6060f1SDimitry Andric 
426fe6060f1SDimitry Andric // ARI
427fe6060f1SDimitry Andric bool M68kOperand::isARI() const {
428fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
429fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
430fe6060f1SDimitry Andric }
431fe6060f1SDimitry Andric void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
432fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
433fe6060f1SDimitry Andric }
434fe6060f1SDimitry Andric 
435fe6060f1SDimitry Andric // ARID
436fe6060f1SDimitry Andric bool M68kOperand::isARID() const {
437fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
438fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
439fe6060f1SDimitry Andric }
440fe6060f1SDimitry Andric void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {
441fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
442fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
443fe6060f1SDimitry Andric }
444fe6060f1SDimitry Andric 
445fe6060f1SDimitry Andric // ARII
446fe6060f1SDimitry Andric bool M68kOperand::isARII() const {
447fe6060f1SDimitry Andric   return isMemOp() &&
448fe6060f1SDimitry Andric          MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
449fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
450fe6060f1SDimitry Andric }
451fe6060f1SDimitry Andric void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {
452fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
453fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
454fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
455fe6060f1SDimitry Andric }
456fe6060f1SDimitry Andric 
457fe6060f1SDimitry Andric // ARIPD
458fe6060f1SDimitry Andric bool M68kOperand::isARIPD() const {
459fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
460fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
461fe6060f1SDimitry Andric }
462fe6060f1SDimitry Andric void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
463fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
464fe6060f1SDimitry Andric }
465fe6060f1SDimitry Andric 
466fe6060f1SDimitry Andric // ARIPI
467fe6060f1SDimitry Andric bool M68kOperand::isARIPI() const {
468fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
469fe6060f1SDimitry Andric          M68k::AR32RegClass.contains(MemOp.OuterReg);
470fe6060f1SDimitry Andric }
471fe6060f1SDimitry Andric void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
472fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
473fe6060f1SDimitry Andric }
474fe6060f1SDimitry Andric 
475fe6060f1SDimitry Andric // PCD
476fe6060f1SDimitry Andric bool M68kOperand::isPCD() const {
477fe6060f1SDimitry Andric   return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
478fe6060f1SDimitry Andric          MemOp.OuterReg == M68k::PC;
479fe6060f1SDimitry Andric }
480fe6060f1SDimitry Andric void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
481fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
482fe6060f1SDimitry Andric }
483fe6060f1SDimitry Andric 
484fe6060f1SDimitry Andric // PCI
485fe6060f1SDimitry Andric bool M68kOperand::isPCI() const {
486fe6060f1SDimitry Andric   return isMemOp() &&
487fe6060f1SDimitry Andric          MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
488fe6060f1SDimitry Andric          MemOp.OuterReg == M68k::PC;
489fe6060f1SDimitry Andric }
490fe6060f1SDimitry Andric void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
491fe6060f1SDimitry Andric   M68kOperand::addExpr(Inst, MemOp.OuterDisp);
492fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
493fe6060f1SDimitry Andric }
494fe6060f1SDimitry Andric 
495fe6060f1SDimitry Andric static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
4965f757f3fSDimitry Andric                                       bool SP, bool FPDR = false,
4975f757f3fSDimitry Andric                                       bool FPCR = false) {
498fe6060f1SDimitry Andric   switch (RegNo) {
499fe6060f1SDimitry Andric   case M68k::A0:
500fe6060f1SDimitry Andric   case M68k::A1:
501fe6060f1SDimitry Andric   case M68k::A2:
502fe6060f1SDimitry Andric   case M68k::A3:
503fe6060f1SDimitry Andric   case M68k::A4:
504fe6060f1SDimitry Andric   case M68k::A5:
505fe6060f1SDimitry Andric   case M68k::A6:
506fe6060f1SDimitry Andric     return Address;
507fe6060f1SDimitry Andric 
508fe6060f1SDimitry Andric   case M68k::SP:
509fe6060f1SDimitry Andric     return SP;
510fe6060f1SDimitry Andric 
511fe6060f1SDimitry Andric   case M68k::D0:
512fe6060f1SDimitry Andric   case M68k::D1:
513fe6060f1SDimitry Andric   case M68k::D2:
514fe6060f1SDimitry Andric   case M68k::D3:
515fe6060f1SDimitry Andric   case M68k::D4:
516fe6060f1SDimitry Andric   case M68k::D5:
517fe6060f1SDimitry Andric   case M68k::D6:
518fe6060f1SDimitry Andric   case M68k::D7:
519fe6060f1SDimitry Andric     return Data;
520fe6060f1SDimitry Andric 
521fe6060f1SDimitry Andric   case M68k::SR:
522fe6060f1SDimitry Andric   case M68k::CCR:
523fe6060f1SDimitry Andric     return false;
524fe6060f1SDimitry Andric 
52506c3fb27SDimitry Andric   case M68k::FP0:
52606c3fb27SDimitry Andric   case M68k::FP1:
52706c3fb27SDimitry Andric   case M68k::FP2:
52806c3fb27SDimitry Andric   case M68k::FP3:
52906c3fb27SDimitry Andric   case M68k::FP4:
53006c3fb27SDimitry Andric   case M68k::FP5:
53106c3fb27SDimitry Andric   case M68k::FP6:
53206c3fb27SDimitry Andric   case M68k::FP7:
53306c3fb27SDimitry Andric     return FPDR;
53406c3fb27SDimitry Andric 
5355f757f3fSDimitry Andric   case M68k::FPC:
5365f757f3fSDimitry Andric   case M68k::FPS:
5375f757f3fSDimitry Andric   case M68k::FPIAR:
5385f757f3fSDimitry Andric     return FPCR;
5395f757f3fSDimitry Andric 
540fe6060f1SDimitry Andric   default:
541fe6060f1SDimitry Andric     llvm_unreachable("unexpected register type");
542fe6060f1SDimitry Andric     return false;
543fe6060f1SDimitry Andric   }
544fe6060f1SDimitry Andric }
545fe6060f1SDimitry Andric 
546349cc55cSDimitry Andric bool M68kOperand::isAReg() const {
547349cc55cSDimitry Andric   return isReg() && checkRegisterClass(getReg(),
548349cc55cSDimitry Andric                                        /*Data=*/false,
549349cc55cSDimitry Andric                                        /*Address=*/true, /*SP=*/true);
550349cc55cSDimitry Andric }
551349cc55cSDimitry Andric 
552349cc55cSDimitry Andric bool M68kOperand::isDReg() const {
553349cc55cSDimitry Andric   return isReg() && checkRegisterClass(getReg(),
554349cc55cSDimitry Andric                                        /*Data=*/true,
555349cc55cSDimitry Andric                                        /*Address=*/false, /*SP=*/false);
556349cc55cSDimitry Andric }
557349cc55cSDimitry Andric 
55806c3fb27SDimitry Andric bool M68kOperand::isFPDReg() const {
55906c3fb27SDimitry Andric   return isReg() && checkRegisterClass(getReg(),
56006c3fb27SDimitry Andric                                        /*Data=*/false,
56106c3fb27SDimitry Andric                                        /*Address=*/false, /*SP=*/false,
56206c3fb27SDimitry Andric                                        /*FPDR=*/true);
56306c3fb27SDimitry Andric }
56406c3fb27SDimitry Andric 
5655f757f3fSDimitry Andric bool M68kOperand::isFPCReg() const {
5665f757f3fSDimitry Andric   return isReg() && checkRegisterClass(getReg(),
5675f757f3fSDimitry Andric                                        /*Data=*/false,
5685f757f3fSDimitry Andric                                        /*Address=*/false, /*SP=*/false,
5695f757f3fSDimitry Andric                                        /*FPDR=*/false, /*FPCR=*/true);
5705f757f3fSDimitry Andric }
5715f757f3fSDimitry Andric 
572fe6060f1SDimitry Andric unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
573fe6060f1SDimitry Andric                                                    unsigned Kind) {
574fe6060f1SDimitry Andric   M68kOperand &Operand = (M68kOperand &)Op;
575fe6060f1SDimitry Andric 
576fe6060f1SDimitry Andric   switch (Kind) {
577fe6060f1SDimitry Andric   case MCK_XR16:
578fe6060f1SDimitry Andric   case MCK_SPILL:
579fe6060f1SDimitry Andric     if (Operand.isReg() &&
580fe6060f1SDimitry Andric         checkRegisterClass(Operand.getReg(), true, true, true)) {
581fe6060f1SDimitry Andric       return Match_Success;
582fe6060f1SDimitry Andric     }
583fe6060f1SDimitry Andric     break;
584fe6060f1SDimitry Andric 
585fe6060f1SDimitry Andric   case MCK_AR16:
586fe6060f1SDimitry Andric   case MCK_AR32:
587fe6060f1SDimitry Andric     if (Operand.isReg() &&
588fe6060f1SDimitry Andric         checkRegisterClass(Operand.getReg(), false, true, true)) {
589fe6060f1SDimitry Andric       return Match_Success;
590fe6060f1SDimitry Andric     }
591fe6060f1SDimitry Andric     break;
592fe6060f1SDimitry Andric 
593fe6060f1SDimitry Andric   case MCK_AR32_NOSP:
594fe6060f1SDimitry Andric     if (Operand.isReg() &&
595fe6060f1SDimitry Andric         checkRegisterClass(Operand.getReg(), false, true, false)) {
596fe6060f1SDimitry Andric       return Match_Success;
597fe6060f1SDimitry Andric     }
598fe6060f1SDimitry Andric     break;
599fe6060f1SDimitry Andric 
600fe6060f1SDimitry Andric   case MCK_DR8:
601fe6060f1SDimitry Andric   case MCK_DR16:
602fe6060f1SDimitry Andric   case MCK_DR32:
603fe6060f1SDimitry Andric     if (Operand.isReg() &&
604fe6060f1SDimitry Andric         checkRegisterClass(Operand.getReg(), true, false, false)) {
605fe6060f1SDimitry Andric       return Match_Success;
606fe6060f1SDimitry Andric     }
607fe6060f1SDimitry Andric     break;
608fe6060f1SDimitry Andric 
609fe6060f1SDimitry Andric   case MCK_AR16_TC:
610fe6060f1SDimitry Andric     if (Operand.isReg() &&
611fe6060f1SDimitry Andric         ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
612fe6060f1SDimitry Andric       return Match_Success;
613fe6060f1SDimitry Andric     }
614fe6060f1SDimitry Andric     break;
615fe6060f1SDimitry Andric 
616fe6060f1SDimitry Andric   case MCK_DR16_TC:
617fe6060f1SDimitry Andric     if (Operand.isReg() &&
618fe6060f1SDimitry Andric         ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
619fe6060f1SDimitry Andric       return Match_Success;
620fe6060f1SDimitry Andric     }
621fe6060f1SDimitry Andric     break;
622fe6060f1SDimitry Andric 
623fe6060f1SDimitry Andric   case MCK_XR16_TC:
624fe6060f1SDimitry Andric     if (Operand.isReg() &&
625fe6060f1SDimitry Andric         ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
626fe6060f1SDimitry Andric          (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
627fe6060f1SDimitry Andric       return Match_Success;
628fe6060f1SDimitry Andric     }
629fe6060f1SDimitry Andric     break;
630fe6060f1SDimitry Andric   }
631fe6060f1SDimitry Andric 
632fe6060f1SDimitry Andric   return Match_InvalidOperand;
633fe6060f1SDimitry Andric }
634fe6060f1SDimitry Andric 
635bdd1243dSDimitry Andric bool M68kAsmParser::parseRegisterName(MCRegister &RegNo, SMLoc Loc,
636fe6060f1SDimitry Andric                                       StringRef RegisterName) {
637fe6060f1SDimitry Andric   auto RegisterNameLower = RegisterName.lower();
638fe6060f1SDimitry Andric 
639fe6060f1SDimitry Andric   // CCR register
640fe6060f1SDimitry Andric   if (RegisterNameLower == "ccr") {
641fe6060f1SDimitry Andric     RegNo = M68k::CCR;
642fe6060f1SDimitry Andric     return true;
643fe6060f1SDimitry Andric   }
644fe6060f1SDimitry Andric 
645fe6060f1SDimitry Andric   // Parse simple general-purpose registers.
646fe6060f1SDimitry Andric   if (RegisterNameLower.size() == 2) {
647fe6060f1SDimitry Andric 
648fe6060f1SDimitry Andric     switch (RegisterNameLower[0]) {
649fe6060f1SDimitry Andric     case 'd':
650fe6060f1SDimitry Andric     case 'a': {
651fe6060f1SDimitry Andric       if (isdigit(RegisterNameLower[1])) {
652fe6060f1SDimitry Andric         unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
653fe6060f1SDimitry Andric         unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
654fe6060f1SDimitry Andric         if (RegIndex < 8) {
655349cc55cSDimitry Andric           RegNo = getRegisterByIndex(IndexOffset + RegIndex);
656fe6060f1SDimitry Andric           return true;
657fe6060f1SDimitry Andric         }
658fe6060f1SDimitry Andric       }
659fe6060f1SDimitry Andric       break;
660fe6060f1SDimitry Andric     }
661fe6060f1SDimitry Andric 
662fe6060f1SDimitry Andric     case 's':
663fe6060f1SDimitry Andric       if (RegisterNameLower[1] == 'p') {
664fe6060f1SDimitry Andric         RegNo = M68k::SP;
665fe6060f1SDimitry Andric         return true;
666fe6060f1SDimitry Andric       } else if (RegisterNameLower[1] == 'r') {
667fe6060f1SDimitry Andric         RegNo = M68k::SR;
668fe6060f1SDimitry Andric         return true;
669fe6060f1SDimitry Andric       }
670fe6060f1SDimitry Andric       break;
671fe6060f1SDimitry Andric 
672fe6060f1SDimitry Andric     case 'p':
673fe6060f1SDimitry Andric       if (RegisterNameLower[1] == 'c') {
674fe6060f1SDimitry Andric         RegNo = M68k::PC;
675fe6060f1SDimitry Andric         return true;
676fe6060f1SDimitry Andric       }
677fe6060f1SDimitry Andric       break;
678fe6060f1SDimitry Andric     }
67906c3fb27SDimitry Andric   } else if (StringRef(RegisterNameLower).starts_with("fp") &&
68006c3fb27SDimitry Andric              RegisterNameLower.size() > 2) {
68106c3fb27SDimitry Andric     auto RegIndex = unsigned(RegisterNameLower[2] - '0');
6825f757f3fSDimitry Andric     if (RegIndex < 8 && RegisterNameLower.size() == 3) {
6835f757f3fSDimitry Andric       // Floating point data register.
68406c3fb27SDimitry Andric       RegNo = getRegisterByIndex(16 + RegIndex);
68506c3fb27SDimitry Andric       return true;
6865f757f3fSDimitry Andric     } else {
6875f757f3fSDimitry Andric       // Floating point control register.
6885f757f3fSDimitry Andric       RegNo = StringSwitch<unsigned>(RegisterNameLower)
6895f757f3fSDimitry Andric                   .Cases("fpc", "fpcr", M68k::FPC)
6905f757f3fSDimitry Andric                   .Cases("fps", "fpsr", M68k::FPS)
6915f757f3fSDimitry Andric                   .Cases("fpi", "fpiar", M68k::FPIAR)
6925f757f3fSDimitry Andric                   .Default(M68k::NoRegister);
6935f757f3fSDimitry Andric       assert(RegNo != M68k::NoRegister &&
6945f757f3fSDimitry Andric              "Unrecognized FP control register name");
6955f757f3fSDimitry Andric       return true;
6965f757f3fSDimitry Andric     }
697fe6060f1SDimitry Andric   }
698fe6060f1SDimitry Andric 
699fe6060f1SDimitry Andric   return false;
700fe6060f1SDimitry Andric }
701fe6060f1SDimitry Andric 
70206c3fb27SDimitry Andric ParseStatus M68kAsmParser::parseRegister(MCRegister &RegNo) {
703fe6060f1SDimitry Andric   bool HasPercent = false;
704fe6060f1SDimitry Andric   AsmToken PercentToken;
705fe6060f1SDimitry Andric 
706fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
707fe6060f1SDimitry Andric 
708fe6060f1SDimitry Andric   if (getTok().is(AsmToken::Percent)) {
709fe6060f1SDimitry Andric     HasPercent = true;
710fe6060f1SDimitry Andric     PercentToken = Lex();
711fe6060f1SDimitry Andric   } else if (!RegisterPrefixOptional.getValue()) {
71206c3fb27SDimitry Andric     return ParseStatus::NoMatch;
713fe6060f1SDimitry Andric   }
714fe6060f1SDimitry Andric 
715fe6060f1SDimitry Andric   if (!Parser.getTok().is(AsmToken::Identifier)) {
716fe6060f1SDimitry Andric     if (HasPercent) {
717fe6060f1SDimitry Andric       getLexer().UnLex(PercentToken);
718fe6060f1SDimitry Andric     }
71906c3fb27SDimitry Andric     return ParseStatus::NoMatch;
720fe6060f1SDimitry Andric   }
721fe6060f1SDimitry Andric 
722fe6060f1SDimitry Andric   auto RegisterName = Parser.getTok().getString();
723fe6060f1SDimitry Andric   if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
724fe6060f1SDimitry Andric     if (HasPercent) {
725fe6060f1SDimitry Andric       getLexer().UnLex(PercentToken);
726fe6060f1SDimitry Andric     }
72706c3fb27SDimitry Andric     return ParseStatus::NoMatch;
728fe6060f1SDimitry Andric   }
729fe6060f1SDimitry Andric 
730fe6060f1SDimitry Andric   Parser.Lex();
73106c3fb27SDimitry Andric   return ParseStatus::Success;
732fe6060f1SDimitry Andric }
733fe6060f1SDimitry Andric 
7345f757f3fSDimitry Andric bool M68kAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
735fe6060f1SDimitry Andric                                   SMLoc &EndLoc) {
7365f757f3fSDimitry Andric   ParseStatus Result = tryParseRegister(Reg, StartLoc, EndLoc);
7375f757f3fSDimitry Andric   if (!Result.isSuccess())
738fe6060f1SDimitry Andric     return Error(StartLoc, "expected register");
739fe6060f1SDimitry Andric 
740fe6060f1SDimitry Andric   return false;
741fe6060f1SDimitry Andric }
742fe6060f1SDimitry Andric 
7435f757f3fSDimitry Andric ParseStatus M68kAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
744fe6060f1SDimitry Andric                                             SMLoc &EndLoc) {
745fe6060f1SDimitry Andric   StartLoc = getLexer().getLoc();
7465f757f3fSDimitry Andric   ParseStatus Result = parseRegister(Reg);
747fe6060f1SDimitry Andric   EndLoc = getLexer().getLoc();
748fe6060f1SDimitry Andric   return Result;
749fe6060f1SDimitry Andric }
750fe6060f1SDimitry Andric 
751fe6060f1SDimitry Andric bool M68kAsmParser::isExpr() {
752fe6060f1SDimitry Andric   switch (Parser.getTok().getKind()) {
753fe6060f1SDimitry Andric   case AsmToken::Identifier:
754fe6060f1SDimitry Andric   case AsmToken::Integer:
755fe6060f1SDimitry Andric     return true;
756fe6060f1SDimitry Andric   case AsmToken::Minus:
757fe6060f1SDimitry Andric     return getLexer().peekTok().getKind() == AsmToken::Integer;
758fe6060f1SDimitry Andric 
759fe6060f1SDimitry Andric   default:
760fe6060f1SDimitry Andric     return false;
761fe6060f1SDimitry Andric   }
762fe6060f1SDimitry Andric }
763fe6060f1SDimitry Andric 
76406c3fb27SDimitry Andric ParseStatus M68kAsmParser::parseImm(OperandVector &Operands) {
76506c3fb27SDimitry Andric   if (getLexer().isNot(AsmToken::Hash))
76606c3fb27SDimitry Andric     return ParseStatus::NoMatch;
767fe6060f1SDimitry Andric   SMLoc Start = getLexer().getLoc();
768fe6060f1SDimitry Andric   Parser.Lex();
769fe6060f1SDimitry Andric 
770fe6060f1SDimitry Andric   SMLoc End;
771fe6060f1SDimitry Andric   const MCExpr *Expr;
772fe6060f1SDimitry Andric 
77306c3fb27SDimitry Andric   if (getParser().parseExpression(Expr, End))
77406c3fb27SDimitry Andric     return ParseStatus::Failure;
775fe6060f1SDimitry Andric 
776fe6060f1SDimitry Andric   Operands.push_back(M68kOperand::createImm(Expr, Start, End));
77706c3fb27SDimitry Andric   return ParseStatus::Success;
778fe6060f1SDimitry Andric }
779fe6060f1SDimitry Andric 
78006c3fb27SDimitry Andric ParseStatus M68kAsmParser::parseMemOp(OperandVector &Operands) {
781fe6060f1SDimitry Andric   SMLoc Start = getLexer().getLoc();
782fe6060f1SDimitry Andric   bool IsPD = false;
783fe6060f1SDimitry Andric   M68kMemOp MemOp;
784fe6060f1SDimitry Andric 
785349cc55cSDimitry Andric   // Check for a plain register or register mask.
78606c3fb27SDimitry Andric   ParseStatus Result = parseRegOrMoveMask(Operands);
78706c3fb27SDimitry Andric   if (!Result.isNoMatch())
788fe6060f1SDimitry Andric     return Result;
789fe6060f1SDimitry Andric 
790fe6060f1SDimitry Andric   // Check for pre-decrement & outer displacement.
791fe6060f1SDimitry Andric   bool HasDisplacement = false;
792fe6060f1SDimitry Andric   if (getLexer().is(AsmToken::Minus)) {
793fe6060f1SDimitry Andric     IsPD = true;
794fe6060f1SDimitry Andric     Parser.Lex();
795fe6060f1SDimitry Andric   } else if (isExpr()) {
79606c3fb27SDimitry Andric     if (Parser.parseExpression(MemOp.OuterDisp))
79706c3fb27SDimitry Andric       return ParseStatus::Failure;
798fe6060f1SDimitry Andric     HasDisplacement = true;
799fe6060f1SDimitry Andric   }
800fe6060f1SDimitry Andric 
801fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::LParen)) {
802fe6060f1SDimitry Andric     if (HasDisplacement) {
803fe6060f1SDimitry Andric       MemOp.Op = M68kMemOp::Kind::Addr;
804fe6060f1SDimitry Andric       Operands.push_back(
805fe6060f1SDimitry Andric           M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
80606c3fb27SDimitry Andric       return ParseStatus::Success;
807fe6060f1SDimitry Andric     }
80806c3fb27SDimitry Andric     if (IsPD)
80906c3fb27SDimitry Andric       return Error(getLexer().getLoc(), "expected (");
810fe6060f1SDimitry Andric 
81106c3fb27SDimitry Andric     return ParseStatus::NoMatch;
812fe6060f1SDimitry Andric   }
813fe6060f1SDimitry Andric   Parser.Lex();
814fe6060f1SDimitry Andric 
815fe6060f1SDimitry Andric   // Check for constant dereference & MIT-style displacement
816fe6060f1SDimitry Andric   if (!HasDisplacement && isExpr()) {
81706c3fb27SDimitry Andric     if (Parser.parseExpression(MemOp.OuterDisp))
81806c3fb27SDimitry Andric       return ParseStatus::Failure;
819fe6060f1SDimitry Andric     HasDisplacement = true;
820fe6060f1SDimitry Andric 
821fe6060f1SDimitry Andric     // If we're not followed by a comma, we're a constant dereference.
822fe6060f1SDimitry Andric     if (getLexer().isNot(AsmToken::Comma)) {
823fe6060f1SDimitry Andric       MemOp.Op = M68kMemOp::Kind::Addr;
824fe6060f1SDimitry Andric       Operands.push_back(
825fe6060f1SDimitry Andric           M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
82606c3fb27SDimitry Andric       return ParseStatus::Success;
827fe6060f1SDimitry Andric     }
828fe6060f1SDimitry Andric 
829fe6060f1SDimitry Andric     Parser.Lex();
830fe6060f1SDimitry Andric   }
831fe6060f1SDimitry Andric 
832fe6060f1SDimitry Andric   Result = parseRegister(MemOp.OuterReg);
83306c3fb27SDimitry Andric   if (Result.isFailure())
83406c3fb27SDimitry Andric     return ParseStatus::Failure;
835fe6060f1SDimitry Andric 
83606c3fb27SDimitry Andric   if (!Result.isSuccess())
83706c3fb27SDimitry Andric     return Error(getLexer().getLoc(), "expected register");
838fe6060f1SDimitry Andric 
839fe6060f1SDimitry Andric   // Check for Index.
840fe6060f1SDimitry Andric   bool HasIndex = false;
841fe6060f1SDimitry Andric   if (Parser.getTok().is(AsmToken::Comma)) {
842fe6060f1SDimitry Andric     Parser.Lex();
843fe6060f1SDimitry Andric 
844fe6060f1SDimitry Andric     Result = parseRegister(MemOp.InnerReg);
84506c3fb27SDimitry Andric     if (Result.isFailure())
846fe6060f1SDimitry Andric       return Result;
847fe6060f1SDimitry Andric 
84806c3fb27SDimitry Andric     if (Result.isNoMatch())
84906c3fb27SDimitry Andric       return Error(getLexer().getLoc(), "expected register");
850fe6060f1SDimitry Andric 
851fe6060f1SDimitry Andric     // TODO: parse size, scale and inner displacement.
852fe6060f1SDimitry Andric     MemOp.Size = 4;
853fe6060f1SDimitry Andric     MemOp.Scale = 1;
854fe6060f1SDimitry Andric     MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);
855fe6060f1SDimitry Andric     HasIndex = true;
856fe6060f1SDimitry Andric   }
857fe6060f1SDimitry Andric 
85806c3fb27SDimitry Andric   if (Parser.getTok().isNot(AsmToken::RParen))
85906c3fb27SDimitry Andric     return Error(getLexer().getLoc(), "expected )");
860fe6060f1SDimitry Andric   Parser.Lex();
861fe6060f1SDimitry Andric 
862fe6060f1SDimitry Andric   bool IsPI = false;
863fe6060f1SDimitry Andric   if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {
864fe6060f1SDimitry Andric     Parser.Lex();
865fe6060f1SDimitry Andric     IsPI = true;
866fe6060f1SDimitry Andric   }
867fe6060f1SDimitry Andric 
868fe6060f1SDimitry Andric   SMLoc End = getLexer().getLoc();
869fe6060f1SDimitry Andric 
870fe6060f1SDimitry Andric   unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
87106c3fb27SDimitry Andric   if (OpCount > 1)
87206c3fb27SDimitry Andric     return Error(Start, "only one of post-increment, pre-decrement or "
87306c3fb27SDimitry Andric                         "displacement can be used");
874fe6060f1SDimitry Andric 
875fe6060f1SDimitry Andric   if (IsPD) {
876fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
877fe6060f1SDimitry Andric   } else if (IsPI) {
878fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
879fe6060f1SDimitry Andric   } else if (HasIndex) {
880fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
881fe6060f1SDimitry Andric   } else if (HasDisplacement) {
882fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
883fe6060f1SDimitry Andric   } else {
884fe6060f1SDimitry Andric     MemOp.Op = M68kMemOp::Kind::RegIndirect;
885fe6060f1SDimitry Andric   }
886fe6060f1SDimitry Andric 
887fe6060f1SDimitry Andric   Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
88806c3fb27SDimitry Andric   return ParseStatus::Success;
889fe6060f1SDimitry Andric }
890fe6060f1SDimitry Andric 
89106c3fb27SDimitry Andric ParseStatus M68kAsmParser::parseRegOrMoveMask(OperandVector &Operands) {
892349cc55cSDimitry Andric   SMLoc Start = getLexer().getLoc();
893349cc55cSDimitry Andric   M68kMemOp MemOp(M68kMemOp::Kind::RegMask);
894349cc55cSDimitry Andric   MemOp.RegMask = 0;
895349cc55cSDimitry Andric 
896349cc55cSDimitry Andric   for (;;) {
897349cc55cSDimitry Andric     bool IsFirstRegister =
898349cc55cSDimitry Andric         (MemOp.Op == M68kMemOp::Kind::RegMask) && (MemOp.RegMask == 0);
899349cc55cSDimitry Andric 
900bdd1243dSDimitry Andric     MCRegister FirstRegister;
90106c3fb27SDimitry Andric     ParseStatus Result = parseRegister(FirstRegister);
90206c3fb27SDimitry Andric     if (IsFirstRegister && Result.isNoMatch())
90306c3fb27SDimitry Andric       return ParseStatus::NoMatch;
90406c3fb27SDimitry Andric     if (!Result.isSuccess())
90506c3fb27SDimitry Andric       return Error(getLexer().getLoc(), "expected start register");
906349cc55cSDimitry Andric 
907bdd1243dSDimitry Andric     MCRegister LastRegister = FirstRegister;
90806c3fb27SDimitry Andric     if (parseOptionalToken(AsmToken::Minus)) {
909349cc55cSDimitry Andric       Result = parseRegister(LastRegister);
91006c3fb27SDimitry Andric       if (!Result.isSuccess())
91106c3fb27SDimitry Andric         return Error(getLexer().getLoc(), "expected end register");
912349cc55cSDimitry Andric     }
913349cc55cSDimitry Andric 
914349cc55cSDimitry Andric     unsigned FirstRegisterIndex = getRegisterIndex(FirstRegister);
915349cc55cSDimitry Andric     unsigned LastRegisterIndex = getRegisterIndex(LastRegister);
916349cc55cSDimitry Andric 
917349cc55cSDimitry Andric     uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1;
918349cc55cSDimitry Andric     uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex;
919349cc55cSDimitry Andric 
920349cc55cSDimitry Andric     if (IsFirstRegister && (FirstRegister == LastRegister)) {
921349cc55cSDimitry Andric       // First register range is a single register, simplify to just Reg
922349cc55cSDimitry Andric       // so that it matches more operands.
923349cc55cSDimitry Andric       MemOp.Op = M68kMemOp::Kind::Reg;
924349cc55cSDimitry Andric       MemOp.OuterReg = FirstRegister;
925349cc55cSDimitry Andric     } else {
926349cc55cSDimitry Andric       if (MemOp.Op == M68kMemOp::Kind::Reg) {
927349cc55cSDimitry Andric         // This is the second register being specified - expand the Reg operand
928349cc55cSDimitry Andric         // into a mask first.
929349cc55cSDimitry Andric         MemOp.Op = M68kMemOp::Kind::RegMask;
930349cc55cSDimitry Andric         MemOp.RegMask = 1 << getRegisterIndex(MemOp.OuterReg);
931349cc55cSDimitry Andric 
93206c3fb27SDimitry Andric         if (MemOp.RegMask == 0)
93306c3fb27SDimitry Andric           return Error(getLexer().getLoc(),
934349cc55cSDimitry Andric                        "special registers cannot be used in register masks");
935349cc55cSDimitry Andric       }
936349cc55cSDimitry Andric 
93706c3fb27SDimitry Andric       if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16))
93806c3fb27SDimitry Andric         return Error(getLexer().getLoc(),
939349cc55cSDimitry Andric                      "special registers cannot be used in register masks");
940349cc55cSDimitry Andric 
94106c3fb27SDimitry Andric       if (NewMaskBits & MemOp.RegMask)
94206c3fb27SDimitry Andric         return Error(getLexer().getLoc(), "conflicting masked registers");
943349cc55cSDimitry Andric 
944349cc55cSDimitry Andric       MemOp.RegMask |= NewMaskBits;
945349cc55cSDimitry Andric     }
946349cc55cSDimitry Andric 
94706c3fb27SDimitry Andric     if (!parseOptionalToken(AsmToken::Slash))
948349cc55cSDimitry Andric       break;
949349cc55cSDimitry Andric   }
950349cc55cSDimitry Andric 
951349cc55cSDimitry Andric   Operands.push_back(
952349cc55cSDimitry Andric       M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
95306c3fb27SDimitry Andric   return ParseStatus::Success;
954349cc55cSDimitry Andric }
955349cc55cSDimitry Andric 
956fe6060f1SDimitry Andric void M68kAsmParser::eatComma() {
957fe6060f1SDimitry Andric   if (Parser.getTok().is(AsmToken::Comma)) {
958fe6060f1SDimitry Andric     Parser.Lex();
959fe6060f1SDimitry Andric   }
960fe6060f1SDimitry Andric }
961fe6060f1SDimitry Andric 
962fe6060f1SDimitry Andric bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
963fe6060f1SDimitry Andric                                      SMLoc NameLoc, OperandVector &Operands) {
964fe6060f1SDimitry Andric   SMLoc Start = getLexer().getLoc();
965fe6060f1SDimitry Andric   Operands.push_back(M68kOperand::createToken(Name, Start, Start));
966fe6060f1SDimitry Andric 
967fe6060f1SDimitry Andric   bool First = true;
968fe6060f1SDimitry Andric   while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
969fe6060f1SDimitry Andric     if (!First) {
970fe6060f1SDimitry Andric       eatComma();
971fe6060f1SDimitry Andric     } else {
972fe6060f1SDimitry Andric       First = false;
973fe6060f1SDimitry Andric     }
974fe6060f1SDimitry Andric 
97506c3fb27SDimitry Andric     ParseStatus MatchResult = MatchOperandParserImpl(Operands, Name);
97606c3fb27SDimitry Andric     if (MatchResult.isSuccess())
977fe6060f1SDimitry Andric       continue;
978fe6060f1SDimitry Andric 
979fe6060f1SDimitry Andric     // Add custom operand formats here...
980fe6060f1SDimitry Andric     SMLoc Loc = getLexer().getLoc();
981fe6060f1SDimitry Andric     Parser.eatToEndOfStatement();
982fe6060f1SDimitry Andric     return Error(Loc, "unexpected token parsing operands");
983fe6060f1SDimitry Andric   }
984fe6060f1SDimitry Andric 
985fe6060f1SDimitry Andric   // Eat EndOfStatement.
986fe6060f1SDimitry Andric   Parser.Lex();
987fe6060f1SDimitry Andric   return false;
988fe6060f1SDimitry Andric }
989fe6060f1SDimitry Andric 
990fe6060f1SDimitry Andric bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
991fe6060f1SDimitry Andric                                    OperandVector const &Operands,
992fe6060f1SDimitry Andric                                    uint64_t const &ErrorInfo) {
993fe6060f1SDimitry Andric   SMLoc ErrorLoc = Loc;
994fe6060f1SDimitry Andric   char const *Diag = 0;
995fe6060f1SDimitry Andric 
996fe6060f1SDimitry Andric   if (ErrorInfo != ~0U) {
997fe6060f1SDimitry Andric     if (ErrorInfo >= Operands.size()) {
998fe6060f1SDimitry Andric       Diag = "too few operands for instruction.";
999fe6060f1SDimitry Andric     } else {
1000fe6060f1SDimitry Andric       auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
1001fe6060f1SDimitry Andric       if (Op.getStartLoc() != SMLoc()) {
1002fe6060f1SDimitry Andric         ErrorLoc = Op.getStartLoc();
1003fe6060f1SDimitry Andric       }
1004fe6060f1SDimitry Andric     }
1005fe6060f1SDimitry Andric   }
1006fe6060f1SDimitry Andric 
1007fe6060f1SDimitry Andric   if (!Diag) {
1008fe6060f1SDimitry Andric     Diag = "invalid operand for instruction";
1009fe6060f1SDimitry Andric   }
1010fe6060f1SDimitry Andric 
1011fe6060f1SDimitry Andric   return Error(ErrorLoc, Diag);
1012fe6060f1SDimitry Andric }
1013fe6060f1SDimitry Andric 
1014fe6060f1SDimitry Andric bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc,
1015fe6060f1SDimitry Andric                                    uint64_t const &ErrorInfo) {
1016fe6060f1SDimitry Andric   return Error(Loc, "instruction requires a CPU feature not currently enabled");
1017fe6060f1SDimitry Andric }
1018fe6060f1SDimitry Andric 
1019fe6060f1SDimitry Andric bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc,
1020fe6060f1SDimitry Andric                          MCStreamer &Out) const {
1021fe6060f1SDimitry Andric   Inst.setLoc(Loc);
1022fe6060f1SDimitry Andric   Out.emitInstruction(Inst, STI);
1023fe6060f1SDimitry Andric 
1024fe6060f1SDimitry Andric   return false;
1025fe6060f1SDimitry Andric }
1026fe6060f1SDimitry Andric 
1027fe6060f1SDimitry Andric bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
1028fe6060f1SDimitry Andric                                             OperandVector &Operands,
1029fe6060f1SDimitry Andric                                             MCStreamer &Out,
1030fe6060f1SDimitry Andric                                             uint64_t &ErrorInfo,
1031fe6060f1SDimitry Andric                                             bool MatchingInlineAsm) {
1032fe6060f1SDimitry Andric   MCInst Inst;
1033fe6060f1SDimitry Andric   unsigned MatchResult =
1034fe6060f1SDimitry Andric       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
1035fe6060f1SDimitry Andric 
1036fe6060f1SDimitry Andric   switch (MatchResult) {
1037fe6060f1SDimitry Andric   case Match_Success:
1038fe6060f1SDimitry Andric     return emit(Inst, Loc, Out);
1039fe6060f1SDimitry Andric   case Match_MissingFeature:
1040fe6060f1SDimitry Andric     return missingFeature(Loc, ErrorInfo);
1041fe6060f1SDimitry Andric   case Match_InvalidOperand:
1042fe6060f1SDimitry Andric     return invalidOperand(Loc, Operands, ErrorInfo);
1043fe6060f1SDimitry Andric   case Match_MnemonicFail:
1044fe6060f1SDimitry Andric     return Error(Loc, "invalid instruction");
1045fe6060f1SDimitry Andric   default:
1046fe6060f1SDimitry Andric     return true;
1047fe6060f1SDimitry Andric   }
1048fe6060f1SDimitry Andric }
1049fe6060f1SDimitry Andric 
1050fe6060f1SDimitry Andric void M68kOperand::print(raw_ostream &OS) const {
1051fe6060f1SDimitry Andric   switch (Kind) {
105269ade1e0SDimitry Andric   case KindTy::Invalid:
1053fe6060f1SDimitry Andric     OS << "invalid";
1054fe6060f1SDimitry Andric     break;
1055fe6060f1SDimitry Andric 
105669ade1e0SDimitry Andric   case KindTy::Token:
1057fe6060f1SDimitry Andric     OS << "token '" << Token << "'";
1058fe6060f1SDimitry Andric     break;
1059fe6060f1SDimitry Andric 
106006c3fb27SDimitry Andric   case KindTy::Imm: {
106106c3fb27SDimitry Andric     int64_t Value;
106206c3fb27SDimitry Andric     Expr->evaluateAsAbsolute(Value);
106306c3fb27SDimitry Andric     OS << "immediate " << Value;
1064fe6060f1SDimitry Andric     break;
106506c3fb27SDimitry Andric   }
1066fe6060f1SDimitry Andric 
106769ade1e0SDimitry Andric   case KindTy::MemOp:
1068fe6060f1SDimitry Andric     MemOp.print(OS);
1069fe6060f1SDimitry Andric     break;
1070fe6060f1SDimitry Andric   }
1071fe6060f1SDimitry Andric }
1072