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