1*da58b97aSjoerg //===- M68kDisassembler.cpp - Disassembler for M68k -------------*- C++ -*-===//
2*da58b97aSjoerg //
3*da58b97aSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*da58b97aSjoerg // See https://llvm.org/LICENSE.txt for license information.
5*da58b97aSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*da58b97aSjoerg //
7*da58b97aSjoerg //===----------------------------------------------------------------------===//
8*da58b97aSjoerg //
9*da58b97aSjoerg // This file is part of the M68k Disassembler.
10*da58b97aSjoerg //
11*da58b97aSjoerg //===----------------------------------------------------------------------===//
12*da58b97aSjoerg 
13*da58b97aSjoerg #include "M68k.h"
14*da58b97aSjoerg #include "M68kRegisterInfo.h"
15*da58b97aSjoerg #include "M68kSubtarget.h"
16*da58b97aSjoerg #include "MCTargetDesc/M68kMCCodeEmitter.h"
17*da58b97aSjoerg #include "MCTargetDesc/M68kMCTargetDesc.h"
18*da58b97aSjoerg #include "TargetInfo/M68kTargetInfo.h"
19*da58b97aSjoerg 
20*da58b97aSjoerg #include "llvm/MC/MCAsmInfo.h"
21*da58b97aSjoerg #include "llvm/MC/MCContext.h"
22*da58b97aSjoerg #include "llvm/MC/MCDisassembler/MCDisassembler.h"
23*da58b97aSjoerg #include "llvm/MC/MCInst.h"
24*da58b97aSjoerg #include "llvm/Support/TargetRegistry.h"
25*da58b97aSjoerg 
26*da58b97aSjoerg using namespace llvm;
27*da58b97aSjoerg 
28*da58b97aSjoerg #define DEBUG_TYPE "m68k-disassembler"
29*da58b97aSjoerg 
30*da58b97aSjoerg typedef MCDisassembler::DecodeStatus DecodeStatus;
31*da58b97aSjoerg 
32*da58b97aSjoerg namespace {
33*da58b97aSjoerg constexpr unsigned MaxInstructionWords = 11;
34*da58b97aSjoerg 
35*da58b97aSjoerg class M68kInstructionBuffer {
36*da58b97aSjoerg   typedef SmallVector<uint16_t, MaxInstructionWords> BufferType;
37*da58b97aSjoerg   BufferType Buffer;
38*da58b97aSjoerg 
39*da58b97aSjoerg public:
M68kInstructionBuffer()40*da58b97aSjoerg   M68kInstructionBuffer() {}
41*da58b97aSjoerg 
42*da58b97aSjoerg   template <typename TIt>
M68kInstructionBuffer(TIt Start,TIt End)43*da58b97aSjoerg   M68kInstructionBuffer(TIt Start, TIt End) : Buffer(Start, End) {}
44*da58b97aSjoerg 
size() const45*da58b97aSjoerg   unsigned size() const { return Buffer.size(); }
46*da58b97aSjoerg 
begin() const47*da58b97aSjoerg   BufferType::const_iterator begin() const { return Buffer.begin(); }
end() const48*da58b97aSjoerg   BufferType::const_iterator end() const { return Buffer.end(); }
49*da58b97aSjoerg 
operator [](unsigned Index) const50*da58b97aSjoerg   uint16_t operator[](unsigned Index) const {
51*da58b97aSjoerg     assert((Index < Buffer.size()) && "tried to read out of bounds word");
52*da58b97aSjoerg     return Buffer[Index];
53*da58b97aSjoerg   }
54*da58b97aSjoerg 
truncate(unsigned NewLength)55*da58b97aSjoerg   void truncate(unsigned NewLength) {
56*da58b97aSjoerg     assert((NewLength <= Buffer.size()) &&
57*da58b97aSjoerg            "instruction buffer too short to truncate");
58*da58b97aSjoerg     Buffer.resize(NewLength);
59*da58b97aSjoerg   }
60*da58b97aSjoerg 
61*da58b97aSjoerg   void dump() const;
62*da58b97aSjoerg 
63*da58b97aSjoerg   static M68kInstructionBuffer fill(ArrayRef<uint8_t> Bytes);
64*da58b97aSjoerg };
65*da58b97aSjoerg 
66*da58b97aSjoerg class M68kInstructionReader {
67*da58b97aSjoerg   M68kInstructionBuffer Buffer;
68*da58b97aSjoerg   unsigned NumRead;
69*da58b97aSjoerg 
70*da58b97aSjoerg public:
M68kInstructionReader(M68kInstructionBuffer Buf)71*da58b97aSjoerg   M68kInstructionReader(M68kInstructionBuffer Buf) : Buffer(Buf), NumRead(0) {}
72*da58b97aSjoerg 
size() const73*da58b97aSjoerg   unsigned size() const { return (Buffer.size() * 16) - NumRead; }
74*da58b97aSjoerg 
75*da58b97aSjoerg   uint64_t readBits(unsigned NumBits);
76*da58b97aSjoerg };
77*da58b97aSjoerg 
78*da58b97aSjoerg struct M68kInstructionLookup {
79*da58b97aSjoerg   unsigned OpCode;
80*da58b97aSjoerg   M68kInstructionBuffer Mask;
81*da58b97aSjoerg   M68kInstructionBuffer Value;
82*da58b97aSjoerg 
size__anon07ee2dad0111::M68kInstructionLookup83*da58b97aSjoerg   unsigned size() const { return Mask.size(); }
84*da58b97aSjoerg 
85*da58b97aSjoerg   // Check whether this instruction could possibly match the given bytes.
86*da58b97aSjoerg   bool matches(const M68kInstructionBuffer &Test) const;
87*da58b97aSjoerg   void dump() const;
88*da58b97aSjoerg };
89*da58b97aSjoerg 
90*da58b97aSjoerg class M68kInstructionLookupBuilder {
91*da58b97aSjoerg   std::array<uint16_t, MaxInstructionWords> Mask;
92*da58b97aSjoerg   std::array<uint16_t, MaxInstructionWords> Value;
93*da58b97aSjoerg   unsigned NumWritten;
94*da58b97aSjoerg 
95*da58b97aSjoerg public:
M68kInstructionLookupBuilder()96*da58b97aSjoerg   M68kInstructionLookupBuilder() : NumWritten(0) {
97*da58b97aSjoerg     Mask.fill(0);
98*da58b97aSjoerg     Value.fill(0);
99*da58b97aSjoerg   }
100*da58b97aSjoerg 
numWords() const101*da58b97aSjoerg   unsigned numWords() const {
102*da58b97aSjoerg     assert(!(NumWritten & 0xf) && "instructions must be whole words");
103*da58b97aSjoerg     return NumWritten >> 4;
104*da58b97aSjoerg   }
105*da58b97aSjoerg 
106*da58b97aSjoerg   bool isValid() const;
107*da58b97aSjoerg   M68kInstructionLookup build(unsigned OpCode);
108*da58b97aSjoerg   void addBits(unsigned N, uint64_t Bits);
109*da58b97aSjoerg   void skipBits(unsigned N);
110*da58b97aSjoerg };
111*da58b97aSjoerg 
112*da58b97aSjoerg /// A disassembler class for M68k.
113*da58b97aSjoerg class M68kDisassembler : public MCDisassembler {
114*da58b97aSjoerg   MCInstrInfo *MCII;
115*da58b97aSjoerg   std::vector<M68kInstructionLookup> Lookups;
116*da58b97aSjoerg 
117*da58b97aSjoerg public:
M68kDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,MCInstrInfo * MCII)118*da58b97aSjoerg   M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
119*da58b97aSjoerg                    MCInstrInfo *MCII)
120*da58b97aSjoerg       : MCDisassembler(STI, Ctx), MCII(MCII) {
121*da58b97aSjoerg     buildBeadTable();
122*da58b97aSjoerg   }
~M68kDisassembler()123*da58b97aSjoerg   virtual ~M68kDisassembler() {}
124*da58b97aSjoerg 
125*da58b97aSjoerg   void buildBeadTable();
126*da58b97aSjoerg   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
127*da58b97aSjoerg                               ArrayRef<uint8_t> Bytes, uint64_t Address,
128*da58b97aSjoerg                               raw_ostream &CStream) const override;
129*da58b97aSjoerg   void decodeReg(MCInst &Instr, unsigned int Bead,
130*da58b97aSjoerg                  M68kInstructionReader &Reader, unsigned &Scratch) const;
131*da58b97aSjoerg   void decodeImm(MCInst &Instr, unsigned int Bead,
132*da58b97aSjoerg                  M68kInstructionReader &Reader, unsigned &Scratch) const;
133*da58b97aSjoerg   unsigned int getRegOperandIndex(MCInst &Instr, unsigned int Bead) const;
134*da58b97aSjoerg   unsigned int getImmOperandIndex(MCInst &Instr, unsigned int Bead) const;
135*da58b97aSjoerg };
136*da58b97aSjoerg } // namespace
137*da58b97aSjoerg 
138*da58b97aSjoerg static unsigned RegisterDecode[] = {
139*da58b97aSjoerg     M68k::A0, M68k::A1, M68k::A2, M68k::A3, M68k::A4, M68k::A5,
140*da58b97aSjoerg     M68k::A6, M68k::SP, M68k::D0, M68k::D1, M68k::D2, M68k::D3,
141*da58b97aSjoerg     M68k::D4, M68k::D5, M68k::D6, M68k::D7,
142*da58b97aSjoerg };
143*da58b97aSjoerg 
144*da58b97aSjoerg #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
145*da58b97aSjoerg LLVM_DUMP_METHOD
dump() const146*da58b97aSjoerg void M68kInstructionBuffer::dump() const {
147*da58b97aSjoerg   for (auto Word : Buffer) {
148*da58b97aSjoerg     for (unsigned B = 0; B < 16; ++B) {
149*da58b97aSjoerg       uint16_t Bit = (1 << (16 - B - 1));
150*da58b97aSjoerg       unsigned IsClear = !(Word & Bit);
151*da58b97aSjoerg 
152*da58b97aSjoerg       if (B == 8)
153*da58b97aSjoerg         dbgs() << " ";
154*da58b97aSjoerg 
155*da58b97aSjoerg       char Ch = IsClear ? '0' : '1';
156*da58b97aSjoerg       dbgs() << Ch;
157*da58b97aSjoerg     }
158*da58b97aSjoerg 
159*da58b97aSjoerg     dbgs() << " ";
160*da58b97aSjoerg   }
161*da58b97aSjoerg 
162*da58b97aSjoerg   dbgs() << "\n";
163*da58b97aSjoerg }
164*da58b97aSjoerg #endif
165*da58b97aSjoerg 
fill(ArrayRef<uint8_t> Bytes)166*da58b97aSjoerg M68kInstructionBuffer M68kInstructionBuffer::fill(ArrayRef<uint8_t> Bytes) {
167*da58b97aSjoerg   SmallVector<uint16_t, MaxInstructionWords> Buffer;
168*da58b97aSjoerg   Buffer.resize(std::min(Bytes.size() / 2, Buffer.max_size()));
169*da58b97aSjoerg 
170*da58b97aSjoerg   for (unsigned I = 0, E = Buffer.size(); I < E; ++I) {
171*da58b97aSjoerg     unsigned Offset = I * 2;
172*da58b97aSjoerg     uint64_t Hi = Bytes[Offset];
173*da58b97aSjoerg     uint64_t Lo = Bytes[Offset + 1];
174*da58b97aSjoerg     uint64_t Word = (Hi << 8) | Lo;
175*da58b97aSjoerg     Buffer[I] = Word;
176*da58b97aSjoerg 
177*da58b97aSjoerg     LLVM_DEBUG(
178*da58b97aSjoerg         errs() << format("Read word %x (%d)\n", (unsigned)Word, Buffer.size()));
179*da58b97aSjoerg   }
180*da58b97aSjoerg 
181*da58b97aSjoerg   return M68kInstructionBuffer(Buffer.begin(), Buffer.end());
182*da58b97aSjoerg }
183*da58b97aSjoerg 
readBits(unsigned NumBits)184*da58b97aSjoerg uint64_t M68kInstructionReader::readBits(unsigned NumBits) {
185*da58b97aSjoerg   assert((size() >= NumBits) && "not enough bits to read");
186*da58b97aSjoerg 
187*da58b97aSjoerg   // We have to read the bits in 16-bit chunks because we read them as
188*da58b97aSjoerg   // 16-bit words but they're actually written in big-endian. If a read
189*da58b97aSjoerg   // crosses a word boundary we have to be careful.
190*da58b97aSjoerg 
191*da58b97aSjoerg   uint64_t Value = 0;
192*da58b97aSjoerg   unsigned BitsRead = 0;
193*da58b97aSjoerg 
194*da58b97aSjoerg   while (BitsRead < NumBits) {
195*da58b97aSjoerg     unsigned AvailableThisWord = 16 - (NumRead & 0xf);
196*da58b97aSjoerg     unsigned ToRead = std::min(NumBits, AvailableThisWord);
197*da58b97aSjoerg 
198*da58b97aSjoerg     unsigned WordIndex = NumRead >> 4;
199*da58b97aSjoerg     uint64_t ThisWord = Buffer[WordIndex] >> (NumRead & 0xf);
200*da58b97aSjoerg     uint64_t Mask = (1 << ToRead) - 1;
201*da58b97aSjoerg     Value |= (ThisWord & Mask) << BitsRead;
202*da58b97aSjoerg     NumRead += ToRead;
203*da58b97aSjoerg     BitsRead += ToRead;
204*da58b97aSjoerg   }
205*da58b97aSjoerg   return Value;
206*da58b97aSjoerg }
207*da58b97aSjoerg 
matches(const M68kInstructionBuffer & Test) const208*da58b97aSjoerg bool M68kInstructionLookup::matches(const M68kInstructionBuffer &Test) const {
209*da58b97aSjoerg   if (Test.size() < Value.size())
210*da58b97aSjoerg     return false;
211*da58b97aSjoerg 
212*da58b97aSjoerg   for (unsigned I = 0, E = Value.size(); I < E; ++I) {
213*da58b97aSjoerg     uint16_t Have = Test[I];
214*da58b97aSjoerg     uint16_t Need = Value[I];
215*da58b97aSjoerg     uint16_t WordMask = Mask[I];
216*da58b97aSjoerg 
217*da58b97aSjoerg     if ((Have & WordMask) != Need)
218*da58b97aSjoerg       return false;
219*da58b97aSjoerg   }
220*da58b97aSjoerg 
221*da58b97aSjoerg   return true;
222*da58b97aSjoerg }
223*da58b97aSjoerg 
224*da58b97aSjoerg #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
225*da58b97aSjoerg LLVM_DUMP_METHOD
dump() const226*da58b97aSjoerg void M68kInstructionLookup::dump() const {
227*da58b97aSjoerg   dbgs() << "M68kInstructionLookup " << OpCode << " ";
228*da58b97aSjoerg 
229*da58b97aSjoerg   for (unsigned I = 0, E = Mask.size(); I < E; ++I) {
230*da58b97aSjoerg     uint16_t WordMask = Mask[I];
231*da58b97aSjoerg     uint16_t WordValue = Value[I];
232*da58b97aSjoerg 
233*da58b97aSjoerg     for (unsigned B = 0; B < 16; ++B) {
234*da58b97aSjoerg       uint16_t Bit = (1 << (15 - B));
235*da58b97aSjoerg       unsigned IsMasked = !(WordMask & Bit);
236*da58b97aSjoerg       unsigned IsClear = !(WordValue & Bit);
237*da58b97aSjoerg 
238*da58b97aSjoerg       if (B == 8)
239*da58b97aSjoerg         dbgs() << " ";
240*da58b97aSjoerg 
241*da58b97aSjoerg       char Ch = IsMasked ? '?' : (IsClear ? '0' : '1');
242*da58b97aSjoerg       dbgs() << Ch;
243*da58b97aSjoerg     }
244*da58b97aSjoerg 
245*da58b97aSjoerg     dbgs() << " ";
246*da58b97aSjoerg   }
247*da58b97aSjoerg 
248*da58b97aSjoerg   dbgs() << "\n";
249*da58b97aSjoerg }
250*da58b97aSjoerg #endif
251*da58b97aSjoerg 
isValid() const252*da58b97aSjoerg bool M68kInstructionLookupBuilder::isValid() const {
253*da58b97aSjoerg   for (unsigned I = 0, E = numWords(); I < E; ++I)
254*da58b97aSjoerg     if (Mask[I])
255*da58b97aSjoerg       return true;
256*da58b97aSjoerg 
257*da58b97aSjoerg   return false;
258*da58b97aSjoerg }
259*da58b97aSjoerg 
build(unsigned OpCode)260*da58b97aSjoerg M68kInstructionLookup M68kInstructionLookupBuilder::build(unsigned OpCode) {
261*da58b97aSjoerg   unsigned NumWords = numWords();
262*da58b97aSjoerg   M68kInstructionBuffer MaskBuffer(Mask.begin(), Mask.begin() + NumWords);
263*da58b97aSjoerg   M68kInstructionBuffer ValueBuffer(Value.begin(), Value.begin() + NumWords);
264*da58b97aSjoerg   M68kInstructionLookup Ret;
265*da58b97aSjoerg   Ret.OpCode = OpCode;
266*da58b97aSjoerg   Ret.Mask = MaskBuffer;
267*da58b97aSjoerg   Ret.Value = ValueBuffer;
268*da58b97aSjoerg   return Ret;
269*da58b97aSjoerg }
270*da58b97aSjoerg 
addBits(unsigned N,uint64_t Bits)271*da58b97aSjoerg void M68kInstructionLookupBuilder::addBits(unsigned N, uint64_t Bits) {
272*da58b97aSjoerg   while (N > 0) {
273*da58b97aSjoerg     unsigned WordIndex = NumWritten >> 4;
274*da58b97aSjoerg     unsigned WordOffset = NumWritten & 0xf;
275*da58b97aSjoerg     unsigned AvailableThisWord = 16 - WordOffset;
276*da58b97aSjoerg     unsigned ToWrite = std::min(AvailableThisWord, N);
277*da58b97aSjoerg 
278*da58b97aSjoerg     uint16_t WordMask = (1 << ToWrite) - 1;
279*da58b97aSjoerg     uint16_t BitsToWrite = Bits & WordMask;
280*da58b97aSjoerg 
281*da58b97aSjoerg     Value[WordIndex] |= (BitsToWrite << WordOffset);
282*da58b97aSjoerg     Mask[WordIndex] |= (WordMask << WordOffset);
283*da58b97aSjoerg 
284*da58b97aSjoerg     Bits >>= ToWrite;
285*da58b97aSjoerg     N -= ToWrite;
286*da58b97aSjoerg     NumWritten += ToWrite;
287*da58b97aSjoerg   }
288*da58b97aSjoerg }
289*da58b97aSjoerg 
skipBits(unsigned N)290*da58b97aSjoerg void M68kInstructionLookupBuilder::skipBits(unsigned N) { NumWritten += N; }
291*da58b97aSjoerg 
292*da58b97aSjoerg // This is a bit of a hack: we can't generate this table at table-gen time
293*da58b97aSjoerg // because some of the definitions are in our platform.
buildBeadTable()294*da58b97aSjoerg void M68kDisassembler::buildBeadTable() {
295*da58b97aSjoerg   const unsigned NumInstr = M68k::INSTRUCTION_LIST_END;
296*da58b97aSjoerg   Lookups.reserve(NumInstr);
297*da58b97aSjoerg 
298*da58b97aSjoerg   for (unsigned I = 0; I < NumInstr; ++I) {
299*da58b97aSjoerg     M68kInstructionLookupBuilder Builder;
300*da58b97aSjoerg 
301*da58b97aSjoerg     for (const uint8_t *PartPtr = M68k::getMCInstrBeads(I); *PartPtr;
302*da58b97aSjoerg          ++PartPtr) {
303*da58b97aSjoerg       uint8_t Bead = *PartPtr;
304*da58b97aSjoerg       unsigned Ext = Bead >> 4;
305*da58b97aSjoerg       unsigned Op = Bead & 0xf;
306*da58b97aSjoerg 
307*da58b97aSjoerg       switch (Op) {
308*da58b97aSjoerg       case M68kBeads::Ctrl:
309*da58b97aSjoerg         // Term will have already been skipped by the loop.
310*da58b97aSjoerg         assert((Ext == M68kBeads::Ignore) && "unexpected command bead");
311*da58b97aSjoerg         break;
312*da58b97aSjoerg 
313*da58b97aSjoerg       case M68kBeads::Bits1:
314*da58b97aSjoerg         Builder.addBits(1, Ext);
315*da58b97aSjoerg         break;
316*da58b97aSjoerg 
317*da58b97aSjoerg       case M68kBeads::Bits2:
318*da58b97aSjoerg         Builder.addBits(2, Ext);
319*da58b97aSjoerg         break;
320*da58b97aSjoerg 
321*da58b97aSjoerg       case M68kBeads::Bits3:
322*da58b97aSjoerg         Builder.addBits(3, Ext);
323*da58b97aSjoerg         break;
324*da58b97aSjoerg 
325*da58b97aSjoerg       case M68kBeads::Bits4:
326*da58b97aSjoerg         Builder.addBits(4, Ext);
327*da58b97aSjoerg         break;
328*da58b97aSjoerg 
329*da58b97aSjoerg       case M68kBeads::DAReg:
330*da58b97aSjoerg       case M68kBeads::DA:
331*da58b97aSjoerg       case M68kBeads::DReg:
332*da58b97aSjoerg       case M68kBeads::Reg:
333*da58b97aSjoerg         if (Op != M68kBeads::DA)
334*da58b97aSjoerg           Builder.skipBits(3);
335*da58b97aSjoerg 
336*da58b97aSjoerg         if (Op != M68kBeads::Reg && Op != M68kBeads::DReg)
337*da58b97aSjoerg           Builder.skipBits(1);
338*da58b97aSjoerg 
339*da58b97aSjoerg         break;
340*da58b97aSjoerg 
341*da58b97aSjoerg       case M68kBeads::Disp8:
342*da58b97aSjoerg         Builder.skipBits(8);
343*da58b97aSjoerg         break;
344*da58b97aSjoerg 
345*da58b97aSjoerg       case M68kBeads::Imm8:
346*da58b97aSjoerg       case M68kBeads::Imm16:
347*da58b97aSjoerg         Builder.skipBits(16);
348*da58b97aSjoerg         break;
349*da58b97aSjoerg 
350*da58b97aSjoerg       case M68kBeads::Imm32:
351*da58b97aSjoerg         Builder.skipBits(32);
352*da58b97aSjoerg         break;
353*da58b97aSjoerg 
354*da58b97aSjoerg       case M68kBeads::Imm3:
355*da58b97aSjoerg         Builder.skipBits(3);
356*da58b97aSjoerg         break;
357*da58b97aSjoerg 
358*da58b97aSjoerg       default:
359*da58b97aSjoerg         llvm_unreachable("unhandled bead type");
360*da58b97aSjoerg       }
361*da58b97aSjoerg     }
362*da58b97aSjoerg 
363*da58b97aSjoerg     // Ignore instructions which are unmatchable (usually pseudo instructions).
364*da58b97aSjoerg     if (!Builder.isValid())
365*da58b97aSjoerg       continue;
366*da58b97aSjoerg 
367*da58b97aSjoerg     Lookups.push_back(Builder.build(I));
368*da58b97aSjoerg   }
369*da58b97aSjoerg }
370*da58b97aSjoerg 
getRegOperandIndex(MCInst & Instr,unsigned Bead) const371*da58b97aSjoerg unsigned M68kDisassembler::getRegOperandIndex(MCInst &Instr,
372*da58b97aSjoerg                                               unsigned Bead) const {
373*da58b97aSjoerg   unsigned Ext = Bead >> 4;
374*da58b97aSjoerg 
375*da58b97aSjoerg   const MCInstrDesc &Desc = MCII->get(Instr.getOpcode());
376*da58b97aSjoerg   auto MIOpIdx = M68k::getLogicalOperandIdx(Instr.getOpcode(), Ext & 7);
377*da58b97aSjoerg 
378*da58b97aSjoerg   if (M68kII::hasMultiMIOperands(Instr.getOpcode(), Ext & 7)) {
379*da58b97aSjoerg     bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
380*da58b97aSjoerg     if (IsPCRel)
381*da58b97aSjoerg       MIOpIdx += M68k::PCRelIndex;
382*da58b97aSjoerg     else if (Ext & 8)
383*da58b97aSjoerg       MIOpIdx += M68k::MemIndex;
384*da58b97aSjoerg     else
385*da58b97aSjoerg       MIOpIdx += M68k::MemBase;
386*da58b97aSjoerg   }
387*da58b97aSjoerg 
388*da58b97aSjoerg   return MIOpIdx;
389*da58b97aSjoerg }
390*da58b97aSjoerg 
getImmOperandIndex(MCInst & Instr,unsigned Bead) const391*da58b97aSjoerg unsigned M68kDisassembler::getImmOperandIndex(MCInst &Instr,
392*da58b97aSjoerg                                               unsigned Bead) const {
393*da58b97aSjoerg   unsigned Ext = Bead >> 4;
394*da58b97aSjoerg 
395*da58b97aSjoerg   const MCInstrDesc &Desc = MCII->get(Instr.getOpcode());
396*da58b97aSjoerg   auto MIOpIdx = M68k::getLogicalOperandIdx(Instr.getOpcode(), Ext & 7);
397*da58b97aSjoerg 
398*da58b97aSjoerg   if (M68kII::hasMultiMIOperands(Instr.getOpcode(), Ext & 7)) {
399*da58b97aSjoerg     bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
400*da58b97aSjoerg     if (IsPCRel)
401*da58b97aSjoerg       MIOpIdx += M68k::PCRelDisp;
402*da58b97aSjoerg     else if (Ext & 8)
403*da58b97aSjoerg       MIOpIdx += M68k::MemOuter;
404*da58b97aSjoerg     else
405*da58b97aSjoerg       MIOpIdx += M68k::MemDisp;
406*da58b97aSjoerg   }
407*da58b97aSjoerg 
408*da58b97aSjoerg   return MIOpIdx;
409*da58b97aSjoerg }
410*da58b97aSjoerg 
decodeReg(MCInst & Instr,unsigned Bead,M68kInstructionReader & Reader,unsigned & Scratch) const411*da58b97aSjoerg void M68kDisassembler::decodeReg(MCInst &Instr, unsigned Bead,
412*da58b97aSjoerg                                  M68kInstructionReader &Reader,
413*da58b97aSjoerg                                  unsigned &Scratch) const {
414*da58b97aSjoerg   unsigned Op = Bead & 0xf;
415*da58b97aSjoerg   LLVM_DEBUG(errs() << format("decodeReg %x\n", Bead));
416*da58b97aSjoerg 
417*da58b97aSjoerg   if (Op != M68kBeads::DA)
418*da58b97aSjoerg     Scratch = (Scratch & ~7) | Reader.readBits(3);
419*da58b97aSjoerg 
420*da58b97aSjoerg   if (Op != M68kBeads::Reg) {
421*da58b97aSjoerg     bool DA = (Op != M68kBeads::DReg) && Reader.readBits(1);
422*da58b97aSjoerg     if (!DA)
423*da58b97aSjoerg       Scratch |= 8;
424*da58b97aSjoerg     else
425*da58b97aSjoerg       Scratch &= ~8;
426*da58b97aSjoerg   }
427*da58b97aSjoerg }
428*da58b97aSjoerg 
decodeImm(MCInst & Instr,unsigned Bead,M68kInstructionReader & Reader,unsigned & Scratch) const429*da58b97aSjoerg void M68kDisassembler::decodeImm(MCInst &Instr, unsigned Bead,
430*da58b97aSjoerg                                  M68kInstructionReader &Reader,
431*da58b97aSjoerg                                  unsigned &Scratch) const {
432*da58b97aSjoerg   unsigned Op = Bead & 0xf;
433*da58b97aSjoerg   LLVM_DEBUG(errs() << format("decodeImm %x\n", Bead));
434*da58b97aSjoerg 
435*da58b97aSjoerg   unsigned NumToRead;
436*da58b97aSjoerg   switch (Op) {
437*da58b97aSjoerg   case M68kBeads::Disp8:
438*da58b97aSjoerg     NumToRead = 8;
439*da58b97aSjoerg     break;
440*da58b97aSjoerg   case M68kBeads::Imm8:
441*da58b97aSjoerg   case M68kBeads::Imm16:
442*da58b97aSjoerg     NumToRead = 16;
443*da58b97aSjoerg     break;
444*da58b97aSjoerg   case M68kBeads::Imm32:
445*da58b97aSjoerg     NumToRead = 32;
446*da58b97aSjoerg     break;
447*da58b97aSjoerg   case M68kBeads::Imm3:
448*da58b97aSjoerg     NumToRead = 3;
449*da58b97aSjoerg     break;
450*da58b97aSjoerg   default:
451*da58b97aSjoerg     llvm_unreachable("invalid imm");
452*da58b97aSjoerg   }
453*da58b97aSjoerg 
454*da58b97aSjoerg   Scratch = (Scratch << NumToRead) | Reader.readBits(NumToRead);
455*da58b97aSjoerg }
456*da58b97aSjoerg 
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CStream) const457*da58b97aSjoerg DecodeStatus M68kDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
458*da58b97aSjoerg                                               ArrayRef<uint8_t> Bytes,
459*da58b97aSjoerg                                               uint64_t Address,
460*da58b97aSjoerg                                               raw_ostream &CStream) const {
461*da58b97aSjoerg   // Read and shift the input (fetch as much as we can for now).
462*da58b97aSjoerg   auto Buffer = M68kInstructionBuffer::fill(Bytes);
463*da58b97aSjoerg   if (Buffer.size() == 0)
464*da58b97aSjoerg     return Fail;
465*da58b97aSjoerg 
466*da58b97aSjoerg   // Check through our lookup table.
467*da58b97aSjoerg   bool Found = false;
468*da58b97aSjoerg   for (unsigned I = 0, E = Lookups.size(); I < E; ++I) {
469*da58b97aSjoerg     const M68kInstructionLookup &Lookup = Lookups[I];
470*da58b97aSjoerg     if (!Lookup.matches(Buffer))
471*da58b97aSjoerg       continue;
472*da58b97aSjoerg 
473*da58b97aSjoerg     Found = true;
474*da58b97aSjoerg     Size = Lookup.size() * 2;
475*da58b97aSjoerg     Buffer.truncate(Lookup.size());
476*da58b97aSjoerg     Instr.setOpcode(Lookup.OpCode);
477*da58b97aSjoerg     LLVM_DEBUG(errs() << "decoding instruction " << MCII->getName(Lookup.OpCode)
478*da58b97aSjoerg                       << "\n");
479*da58b97aSjoerg     break;
480*da58b97aSjoerg   }
481*da58b97aSjoerg 
482*da58b97aSjoerg   if (!Found)
483*da58b97aSjoerg     return Fail;
484*da58b97aSjoerg 
485*da58b97aSjoerg   M68kInstructionReader Reader(Buffer);
486*da58b97aSjoerg   const MCInstrDesc &Desc = MCII->get(Instr.getOpcode());
487*da58b97aSjoerg   unsigned NumOperands = Desc.NumOperands;
488*da58b97aSjoerg 
489*da58b97aSjoerg   // Now use the beads to decode the operands.
490*da58b97aSjoerg   enum class OperandType {
491*da58b97aSjoerg     Invalid,
492*da58b97aSjoerg     Reg,
493*da58b97aSjoerg     Imm,
494*da58b97aSjoerg   };
495*da58b97aSjoerg 
496*da58b97aSjoerg   SmallVector<OperandType, 6> OpType(NumOperands, OperandType::Invalid);
497*da58b97aSjoerg   SmallVector<unsigned, 6> Scratch(NumOperands, 0);
498*da58b97aSjoerg   for (const uint8_t *PartPtr = M68k::getMCInstrBeads(Instr.getOpcode());
499*da58b97aSjoerg        *PartPtr; ++PartPtr) {
500*da58b97aSjoerg     uint8_t Bead = *PartPtr;
501*da58b97aSjoerg     unsigned Ext = Bead >> 4;
502*da58b97aSjoerg     unsigned Op = Bead & 0xf;
503*da58b97aSjoerg     unsigned MIOpIdx;
504*da58b97aSjoerg 
505*da58b97aSjoerg     switch (Op) {
506*da58b97aSjoerg     case M68kBeads::Ctrl:
507*da58b97aSjoerg       // Term will have already been skipped by the loop.
508*da58b97aSjoerg       assert((Ext == M68kBeads::Ignore) && "unexpected command bead");
509*da58b97aSjoerg       break;
510*da58b97aSjoerg 
511*da58b97aSjoerg       // These bits are constant - if we're here we've already matched them.
512*da58b97aSjoerg     case M68kBeads::Bits1:
513*da58b97aSjoerg       Reader.readBits(1);
514*da58b97aSjoerg       break;
515*da58b97aSjoerg     case M68kBeads::Bits2:
516*da58b97aSjoerg       Reader.readBits(2);
517*da58b97aSjoerg       break;
518*da58b97aSjoerg     case M68kBeads::Bits3:
519*da58b97aSjoerg       Reader.readBits(3);
520*da58b97aSjoerg       break;
521*da58b97aSjoerg     case M68kBeads::Bits4:
522*da58b97aSjoerg       Reader.readBits(4);
523*da58b97aSjoerg       break;
524*da58b97aSjoerg 
525*da58b97aSjoerg     case M68kBeads::DAReg:
526*da58b97aSjoerg     case M68kBeads::DA:
527*da58b97aSjoerg     case M68kBeads::DReg:
528*da58b97aSjoerg     case M68kBeads::Reg:
529*da58b97aSjoerg       MIOpIdx = getRegOperandIndex(Instr, Bead);
530*da58b97aSjoerg       assert(((OpType[MIOpIdx] == OperandType::Invalid) ||
531*da58b97aSjoerg               (OpType[MIOpIdx] == OperandType::Reg)) &&
532*da58b97aSjoerg              "operands cannot change type");
533*da58b97aSjoerg       OpType[MIOpIdx] = OperandType::Reg;
534*da58b97aSjoerg       decodeReg(Instr, Bead, Reader, Scratch[MIOpIdx]);
535*da58b97aSjoerg       break;
536*da58b97aSjoerg 
537*da58b97aSjoerg     case M68kBeads::Disp8:
538*da58b97aSjoerg     case M68kBeads::Imm8:
539*da58b97aSjoerg     case M68kBeads::Imm16:
540*da58b97aSjoerg     case M68kBeads::Imm32:
541*da58b97aSjoerg     case M68kBeads::Imm3:
542*da58b97aSjoerg       MIOpIdx = getImmOperandIndex(Instr, Bead);
543*da58b97aSjoerg       assert(((OpType[MIOpIdx] == OperandType::Invalid) ||
544*da58b97aSjoerg               (OpType[MIOpIdx] == OperandType::Imm)) &&
545*da58b97aSjoerg              "operands cannot change type");
546*da58b97aSjoerg       OpType[MIOpIdx] = OperandType::Imm;
547*da58b97aSjoerg       decodeImm(Instr, Bead, Reader, Scratch[MIOpIdx]);
548*da58b97aSjoerg       break;
549*da58b97aSjoerg 
550*da58b97aSjoerg     default:
551*da58b97aSjoerg       llvm_unreachable("unhandled bead type");
552*da58b97aSjoerg     }
553*da58b97aSjoerg   }
554*da58b97aSjoerg 
555*da58b97aSjoerg   // Copy constrained operands.
556*da58b97aSjoerg   for (unsigned DstMIOpIdx = 0; DstMIOpIdx < NumOperands; ++DstMIOpIdx) {
557*da58b97aSjoerg     int TiedTo = Desc.getOperandConstraint(DstMIOpIdx, MCOI::TIED_TO);
558*da58b97aSjoerg     if (TiedTo < 0)
559*da58b97aSjoerg       continue;
560*da58b97aSjoerg 
561*da58b97aSjoerg     unsigned SrcMIOpIdx = TiedTo;
562*da58b97aSjoerg 
563*da58b97aSjoerg     unsigned OpCount = 0;
564*da58b97aSjoerg     for (unsigned I = 0;; ++I) {
565*da58b97aSjoerg       unsigned Offset = M68k::getLogicalOperandIdx(Instr.getOpcode(), I);
566*da58b97aSjoerg       assert(Offset <= SrcMIOpIdx && "missing logical operand");
567*da58b97aSjoerg       if (Offset == SrcMIOpIdx) {
568*da58b97aSjoerg         OpCount = M68k::getLogicalOperandSize(Instr.getOpcode(), I);
569*da58b97aSjoerg         break;
570*da58b97aSjoerg       }
571*da58b97aSjoerg     }
572*da58b97aSjoerg     assert(OpCount != 0 && "operand count not found");
573*da58b97aSjoerg 
574*da58b97aSjoerg     for (unsigned I = 0; I < OpCount; ++I) {
575*da58b97aSjoerg       assert(OpType[DstMIOpIdx + I] == OperandType::Invalid &&
576*da58b97aSjoerg              "tried to stomp over operand whilst applying constraints");
577*da58b97aSjoerg       OpType[DstMIOpIdx + I] = OpType[SrcMIOpIdx + I];
578*da58b97aSjoerg       Scratch[DstMIOpIdx + I] = Scratch[SrcMIOpIdx + I];
579*da58b97aSjoerg     }
580*da58b97aSjoerg   }
581*da58b97aSjoerg 
582*da58b97aSjoerg   // Create the operands from our scratch space.
583*da58b97aSjoerg   for (unsigned O = 0; O < NumOperands; ++O) {
584*da58b97aSjoerg     switch (OpType[O]) {
585*da58b97aSjoerg     case OperandType::Invalid:
586*da58b97aSjoerg       assert(false && "operand not parsed");
587*da58b97aSjoerg 
588*da58b97aSjoerg     case OperandType::Imm:
589*da58b97aSjoerg       Instr.addOperand(MCOperand::createImm(Scratch[O]));
590*da58b97aSjoerg       break;
591*da58b97aSjoerg 
592*da58b97aSjoerg     case OperandType::Reg:
593*da58b97aSjoerg       Instr.addOperand(MCOperand::createReg(RegisterDecode[Scratch[O]]));
594*da58b97aSjoerg       break;
595*da58b97aSjoerg     }
596*da58b97aSjoerg   }
597*da58b97aSjoerg 
598*da58b97aSjoerg   assert((Reader.size() == 0) && "wrong number of bits consumed");
599*da58b97aSjoerg   return Success;
600*da58b97aSjoerg }
601*da58b97aSjoerg 
createM68kDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)602*da58b97aSjoerg static MCDisassembler *createM68kDisassembler(const Target &T,
603*da58b97aSjoerg                                               const MCSubtargetInfo &STI,
604*da58b97aSjoerg                                               MCContext &Ctx) {
605*da58b97aSjoerg   return new M68kDisassembler(STI, Ctx, T.createMCInstrInfo());
606*da58b97aSjoerg }
607*da58b97aSjoerg 
LLVMInitializeM68kDisassembler()608*da58b97aSjoerg extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kDisassembler() {
609*da58b97aSjoerg   // Register the disassembler.
610*da58b97aSjoerg   TargetRegistry::RegisterMCDisassembler(getTheM68kTarget(),
611*da58b97aSjoerg                                          createM68kDisassembler);
612*da58b97aSjoerg }
613