1//===- AVRDisassembler.cpp - Disassembler for AVR ---------------*- 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 AVR Disassembler.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AVR.h"
14#include "AVRRegisterInfo.h"
15#include "AVRSubtarget.h"
16#include "MCTargetDesc/AVRMCTargetDesc.h"
17#include "TargetInfo/AVRTargetInfo.h"
18
19#include "llvm/MC/MCAsmInfo.h"
20#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCDisassembler/MCDisassembler.h"
22#include "llvm/MC/MCFixedLenDisassembler.h"
23#include "llvm/MC/MCInst.h"
24#include "llvm/Support/TargetRegistry.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "avr-disassembler"
29
30typedef MCDisassembler::DecodeStatus DecodeStatus;
31
32namespace {
33
34/// A disassembler class for AVR.
35class AVRDisassembler : public MCDisassembler {
36public:
37  AVRDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
38      : MCDisassembler(STI, Ctx) {}
39  virtual ~AVRDisassembler() {}
40
41  DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
42                              ArrayRef<uint8_t> Bytes, uint64_t Address,
43                              raw_ostream &CStream) const override;
44};
45}
46
47static MCDisassembler *createAVRDisassembler(const Target &T,
48                                             const MCSubtargetInfo &STI,
49                                             MCContext &Ctx) {
50  return new AVRDisassembler(STI, Ctx);
51}
52
53
54extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRDisassembler() {
55  // Register the disassembler.
56  TargetRegistry::RegisterMCDisassembler(getTheAVRTarget(),
57                                         createAVRDisassembler);
58}
59
60static const uint16_t GPRDecoderTable[] = {
61  AVR::R0, AVR::R1, AVR::R2, AVR::R3,
62  AVR::R4, AVR::R5, AVR::R6, AVR::R7,
63  AVR::R8, AVR::R9, AVR::R10, AVR::R11,
64  AVR::R12, AVR::R13, AVR::R14, AVR::R15,
65  AVR::R16, AVR::R17, AVR::R18, AVR::R19,
66  AVR::R20, AVR::R21, AVR::R22, AVR::R23,
67  AVR::R24, AVR::R25, AVR::R26, AVR::R27,
68  AVR::R28, AVR::R29, AVR::R30, AVR::R31,
69};
70
71static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,
72                                            uint64_t Address, const void *Decoder) {
73  if (RegNo > 31)
74    return MCDisassembler::Fail;
75
76  unsigned Register = GPRDecoderTable[RegNo];
77  Inst.addOperand(MCOperand::createReg(Register));
78  return MCDisassembler::Success;
79}
80
81static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,
82                                           uint64_t Address, const void *Decoder) {
83  if (RegNo > 15)
84    return MCDisassembler::Fail;
85
86  unsigned Register = GPRDecoderTable[RegNo+16];
87  Inst.addOperand(MCOperand::createReg(Register));
88  return MCDisassembler::Success;
89}
90
91static DecodeStatus DecodePTRREGSRegisterClass(MCInst &Inst, unsigned RegNo,
92                                               uint64_t Address, const void *Decoder) {
93  // Note: this function must be defined but does not seem to be called.
94  assert(false && "unimplemented: PTRREGS register class");
95  return MCDisassembler::Success;
96}
97
98static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn,
99                                 uint64_t Address, const void *Decoder);
100
101static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn,
102                                 uint64_t Address, const void *Decoder);
103
104static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn,
105                                 uint64_t Address, const void *Decoder);
106
107static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Insn,
108                                     uint64_t Address, const void *Decoder);
109
110static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn,
111                              uint64_t Address, const void *Decoder);
112
113static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn,
114                                uint64_t Address, const void *Decoder);
115
116static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
117                                    uint64_t Address, const void *Decoder);
118
119static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
120                                    uint64_t Address, const void *Decoder);
121
122static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn,
123                                uint64_t Address, const void *Decoder);
124
125static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
126                                    uint64_t Address, const void *Decoder);
127
128#include "AVRGenDisassemblerTables.inc"
129
130static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn,
131                                 uint64_t Address, const void *Decoder) {
132  unsigned addr = 0;
133  addr |= fieldFromInstruction(Insn, 0, 4);
134  addr |= fieldFromInstruction(Insn, 9, 2) << 4;
135  unsigned reg = fieldFromInstruction(Insn, 4, 5);
136  Inst.addOperand(MCOperand::createImm(addr));
137  if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) == MCDisassembler::Fail)
138    return MCDisassembler::Fail;
139  return MCDisassembler::Success;
140}
141
142static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn,
143                                 uint64_t Address, const void *Decoder) {
144  unsigned addr = 0;
145  addr |= fieldFromInstruction(Insn, 0, 4);
146  addr |= fieldFromInstruction(Insn, 9, 2) << 4;
147  unsigned reg = fieldFromInstruction(Insn, 4, 5);
148  if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) == MCDisassembler::Fail)
149    return MCDisassembler::Fail;
150  Inst.addOperand(MCOperand::createImm(addr));
151  return MCDisassembler::Success;
152}
153
154static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn,
155                                 uint64_t Address, const void *Decoder) {
156  unsigned addr = fieldFromInstruction(Insn, 3, 5);
157  unsigned b = fieldFromInstruction(Insn, 0, 3);
158  Inst.addOperand(MCOperand::createImm(addr));
159  Inst.addOperand(MCOperand::createImm(b));
160  return MCDisassembler::Success;
161}
162
163static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field,
164                                     uint64_t Address, const void *Decoder) {
165  // Call targets need to be shifted left by one so this needs a custom
166  // decoder.
167  Inst.addOperand(MCOperand::createImm(Field << 1));
168  return MCDisassembler::Success;
169}
170
171static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn,
172                              uint64_t Address, const void *Decoder) {
173  unsigned d = fieldFromInstruction(Insn, 4, 5);
174  if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
175    return MCDisassembler::Fail;
176  return MCDisassembler::Success;
177}
178
179static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn,
180                                uint64_t Address, const void *Decoder) {
181  if (decodeFRd(Inst, Insn, Address, Decoder) == MCDisassembler::Fail)
182    return MCDisassembler::Fail;
183  Inst.addOperand(MCOperand::createReg(AVR::R31R30));
184  return MCDisassembler::Success;
185}
186
187static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
188                                    uint64_t Address, const void *Decoder) {
189  unsigned d = fieldFromInstruction(Insn, 4, 3) + 16;
190  unsigned r = fieldFromInstruction(Insn, 0, 3) + 16;
191  if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
192    return MCDisassembler::Fail;
193  if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) == MCDisassembler::Fail)
194    return MCDisassembler::Fail;
195  return MCDisassembler::Success;
196}
197
198static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
199                                    uint64_t Address, const void *Decoder) {
200  unsigned r = fieldFromInstruction(Insn, 4, 4) * 2;
201  unsigned d = fieldFromInstruction(Insn, 0, 4) * 2;
202  if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) == MCDisassembler::Fail)
203    return MCDisassembler::Fail;
204  if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
205    return MCDisassembler::Fail;
206  return MCDisassembler::Success;
207}
208
209static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn,
210                                    uint64_t Address, const void *Decoder) {
211  unsigned d = fieldFromInstruction(Insn, 4, 2) * 2 + 24; // starts at r24:r25
212  unsigned k = 0;
213  k |= fieldFromInstruction(Insn, 0, 4);
214  k |= fieldFromInstruction(Insn, 6, 2) << 4;
215  if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
216    return MCDisassembler::Fail;
217  if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) == MCDisassembler::Fail)
218    return MCDisassembler::Fail;
219  Inst.addOperand(MCOperand::createImm(k));
220  return MCDisassembler::Success;
221}
222
223static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
224                                    uint64_t Address, const void *Decoder) {
225  unsigned rd = fieldFromInstruction(Insn, 4, 4) + 16;
226  unsigned rr = fieldFromInstruction(Insn, 0, 4) + 16;
227  if (DecodeGPR8RegisterClass(Inst, rd, Address, Decoder) == MCDisassembler::Fail)
228    return MCDisassembler::Fail;
229  if (DecodeGPR8RegisterClass(Inst, rr, Address, Decoder) == MCDisassembler::Fail)
230    return MCDisassembler::Fail;
231  return MCDisassembler::Success;
232}
233
234static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
235                                      uint64_t &Size, uint32_t &Insn) {
236  if (Bytes.size() < 2) {
237    Size = 0;
238    return MCDisassembler::Fail;
239  }
240
241  Size = 2;
242  Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
243
244  return MCDisassembler::Success;
245}
246
247static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
248                                      uint64_t &Size, uint32_t &Insn) {
249
250  if (Bytes.size() < 4) {
251    Size = 0;
252    return MCDisassembler::Fail;
253  }
254
255  Size = 4;
256  Insn = (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
257
258  return MCDisassembler::Success;
259}
260
261static const uint8_t *getDecoderTable(uint64_t Size) {
262
263  switch (Size) {
264    case 2: return DecoderTable16;
265    case 4: return DecoderTable32;
266    default: llvm_unreachable("instructions must be 16 or 32-bits");
267  }
268}
269
270DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
271                                             ArrayRef<uint8_t> Bytes,
272                                             uint64_t Address,
273                                             raw_ostream &CStream) const {
274  uint32_t Insn;
275
276  DecodeStatus Result;
277
278  // Try decode a 16-bit instruction.
279  {
280    Result = readInstruction16(Bytes, Address, Size, Insn);
281
282    if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
283
284    // Try to auto-decode a 16-bit instruction.
285    Result = decodeInstruction(getDecoderTable(Size), Instr,
286                               Insn, Address, this, STI);
287
288    if (Result != MCDisassembler::Fail)
289      return Result;
290  }
291
292  // Try decode a 32-bit instruction.
293  {
294    Result = readInstruction32(Bytes, Address, Size, Insn);
295
296    if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
297
298    Result = decodeInstruction(getDecoderTable(Size), Instr, Insn,
299                               Address, this, STI);
300
301    if (Result != MCDisassembler::Fail) {
302      return Result;
303    }
304
305    return MCDisassembler::Fail;
306  }
307}
308
309typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
310                                   const void *Decoder);
311
312