1 //===-- M68kDisassembler.cpp - Disassembler for M68k ------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is part of the M68k Disassembler.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "M68k.h"
14 #include "M68kRegisterInfo.h"
15 #include "M68kSubtarget.h"
16 #include "MCTargetDesc/M68kMCCodeEmitter.h"
17 #include "MCTargetDesc/M68kMCTargetDesc.h"
18 #include "TargetInfo/M68kTargetInfo.h"
19
20 #include "llvm/MC/MCAsmInfo.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
23 #include "llvm/MC/MCDecoderOps.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/TargetRegistry.h"
26 #include "llvm/Support/Endian.h"
27 #include "llvm/Support/ErrorHandling.h"
28
29 using namespace llvm;
30
31 #define DEBUG_TYPE "m68k-disassembler"
32
33 typedef MCDisassembler::DecodeStatus DecodeStatus;
34
35 static const unsigned RegisterDecode[] = {
36 M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
37 M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
38 M68k::A4, M68k::A5, M68k::A6, M68k::SP,
39 };
40
DecodeRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)41 static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo,
42 uint64_t Address, const void *Decoder) {
43 if (RegNo >= 16)
44 return DecodeStatus::Fail;
45 Inst.addOperand(MCOperand::createReg(RegisterDecode[RegNo]));
46 return DecodeStatus::Success;
47 }
48
DecodeDR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)49 static DecodeStatus DecodeDR32RegisterClass(MCInst &Inst, uint64_t RegNo,
50 uint64_t Address,
51 const void *Decoder) {
52 return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
53 }
54
DecodeDR16RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)55 static DecodeStatus DecodeDR16RegisterClass(MCInst &Inst, uint64_t RegNo,
56 uint64_t Address,
57 const void *Decoder) {
58 return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
59 }
60
DecodeDR8RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)61 static DecodeStatus DecodeDR8RegisterClass(MCInst &Inst, uint64_t RegNo,
62 uint64_t Address,
63 const void *Decoder) {
64 return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
65 }
66
DecodeAR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)67 static DecodeStatus DecodeAR32RegisterClass(MCInst &Inst, uint64_t RegNo,
68 uint64_t Address,
69 const void *Decoder) {
70 return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder);
71 }
72
DecodeAR16RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)73 static DecodeStatus DecodeAR16RegisterClass(MCInst &Inst, uint64_t RegNo,
74 uint64_t Address,
75 const void *Decoder) {
76 return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder);
77 }
78
DecodeXR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)79 static DecodeStatus DecodeXR32RegisterClass(MCInst &Inst, uint64_t RegNo,
80 uint64_t Address,
81 const void *Decoder) {
82 return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
83 }
84
DecodeXR16RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)85 static DecodeStatus DecodeXR16RegisterClass(MCInst &Inst, uint64_t RegNo,
86 uint64_t Address,
87 const void *Decoder) {
88 return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
89 }
90
DecodeCCRCRegisterClass(MCInst & Inst,APInt & Insn,uint64_t Address,const void * Decoder)91 static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn,
92 uint64_t Address,
93 const void *Decoder) {
94 llvm_unreachable("unimplemented");
95 }
96
DecodeImm32(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)97 static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address,
98 const void *Decoder) {
99 Inst.addOperand(MCOperand::createImm(M68k::swapWord<uint32_t>(Imm)));
100 return DecodeStatus::Success;
101 }
102
103 #include "M68kGenDisassemblerTable.inc"
104
105 /// A disassembler class for M68k.
106 struct M68kDisassembler : public MCDisassembler {
M68kDisassemblerM68kDisassembler107 M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
108 : MCDisassembler(STI, Ctx) {}
~M68kDisassemblerM68kDisassembler109 virtual ~M68kDisassembler() {}
110
111 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
112 ArrayRef<uint8_t> Bytes, uint64_t Address,
113 raw_ostream &CStream) const override;
114 };
115
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CStream) const116 DecodeStatus M68kDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
117 ArrayRef<uint8_t> Bytes,
118 uint64_t Address,
119 raw_ostream &CStream) const {
120 DecodeStatus Result;
121 auto MakeUp = [&](APInt &Insn, unsigned InstrBits) {
122 unsigned Idx = Insn.getBitWidth() >> 3;
123 unsigned RoundUp = alignTo(InstrBits, Align(16));
124 if (RoundUp > Insn.getBitWidth())
125 Insn = Insn.zext(RoundUp);
126 RoundUp = RoundUp >> 3;
127 for (; Idx < RoundUp; Idx += 2) {
128 Insn.insertBits(support::endian::read16be(&Bytes[Idx]), Idx * 8, 16);
129 }
130 };
131 APInt Insn(16, support::endian::read16be(Bytes.data()));
132 // 2 bytes of data are consumed, so set Size to 2
133 // If we don't do this, disassembler may generate result even
134 // the encoding is invalid. We need to let it fail correctly.
135 Size = 2;
136 Result = decodeInstruction(DecoderTable80, Instr, Insn, Address, this, STI,
137 MakeUp);
138 if (Result == DecodeStatus::Success)
139 Size = InstrLenTable[Instr.getOpcode()] >> 3;
140 return Result;
141 }
142
createM68kDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)143 static MCDisassembler *createM68kDisassembler(const Target &T,
144 const MCSubtargetInfo &STI,
145 MCContext &Ctx) {
146 return new M68kDisassembler(STI, Ctx);
147 }
148
LLVMInitializeM68kDisassembler()149 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kDisassembler() {
150 // Register the disassembler.
151 TargetRegistry::RegisterMCDisassembler(getTheM68kTarget(),
152 createM68kDisassembler);
153 }
154