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 "MCTargetDesc/AVRMCTargetDesc.h"
14#include "TargetInfo/AVRTargetInfo.h"
15
16#include "llvm/MC/MCAsmInfo.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCDecoder.h"
19#include "llvm/MC/MCDecoderOps.h"
20#include "llvm/MC/MCDisassembler/MCDisassembler.h"
21#include "llvm/MC/MCInst.h"
22#include "llvm/MC/TargetRegistry.h"
23
24#include "llvm/Support/Compiler.h"
25
26using namespace llvm;
27using namespace llvm::MCD;
28
29#define DEBUG_TYPE "avr-disassembler"
30
31typedef MCDisassembler::DecodeStatus DecodeStatus;
32
33namespace {
34
35/// A disassembler class for AVR.
36class AVRDisassembler : public MCDisassembler {
37public:
38 AVRDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
39 : MCDisassembler(STI, Ctx) {}
40 ~AVRDisassembler() override = default;
41
42 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
43 ArrayRef<uint8_t> Bytes, uint64_t Address,
44 raw_ostream &CStream) const override;
45};
46} // namespace
47
48static MCDisassembler *createAVRDisassembler(const Target &T,
49 const MCSubtargetInfo &STI,
50 MCContext &Ctx) {
51 return new AVRDisassembler(STI, Ctx);
52}
53
54extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
55LLVMInitializeAVRDisassembler() {
56 // Register the disassembler.
57 TargetRegistry::RegisterMCDisassembler(T&: getTheAVRTarget(),
58 Fn: createAVRDisassembler);
59}
60
61static constexpr MCRegister GPRDecoderTable[] = {
62 AVR::R0, AVR::R1, AVR::R2, AVR::R3, AVR::R4, AVR::R5, AVR::R6,
63 AVR::R7, AVR::R8, AVR::R9, AVR::R10, AVR::R11, AVR::R12, AVR::R13,
64 AVR::R14, AVR::R15, AVR::R16, AVR::R17, AVR::R18, AVR::R19, AVR::R20,
65 AVR::R21, AVR::R22, AVR::R23, AVR::R24, AVR::R25, AVR::R26, AVR::R27,
66 AVR::R28, AVR::R29, AVR::R30, AVR::R31,
67};
68
69static constexpr MCRegister GPRPairDecoderTable[] = {
70 AVR::R1R0, AVR::R3R2, AVR::R5R4, AVR::R7R6,
71 AVR::R9R8, AVR::R11R10, AVR::R13R12, AVR::R15R14,
72 AVR::R17R16, AVR::R19R18, AVR::R21R20, AVR::R23R22,
73 AVR::R25R24, AVR::R27R26, AVR::R29R28, AVR::R31R30,
74};
75
76static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,
77 uint64_t Address,
78 const MCDisassembler *Decoder) {
79 if (RegNo > 31)
80 return MCDisassembler::Fail;
81
82 MCRegister Register = GPRDecoderTable[RegNo];
83 Inst.addOperand(Op: MCOperand::createReg(Reg: Register));
84 return MCDisassembler::Success;
85}
86
87static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,
88 uint64_t Address,
89 const MCDisassembler *Decoder) {
90 assert(isUInt<4>(RegNo));
91 // Only r16...r31 are legal.
92 Inst.addOperand(Op: MCOperand::createReg(Reg: GPRDecoderTable[16 + RegNo]));
93 return MCDisassembler::Success;
94}
95
96static DecodeStatus DecodeLD8loRegisterClass(MCInst &Inst, unsigned RegNo,
97 uint64_t Address,
98 const MCDisassembler *Decoder) {
99 assert(isUInt<3>(RegNo));
100 // Only r16...r23 are legal.
101 Inst.addOperand(Op: MCOperand::createReg(Reg: GPRDecoderTable[16 + RegNo]));
102 return MCDisassembler::Success;
103}
104
105static DecodeStatus DecodeDREGSRegisterClass(MCInst &Inst, unsigned RegNo,
106 uint64_t Address,
107 const MCDisassembler *Decoder) {
108 assert(isUInt<4>(RegNo));
109 Inst.addOperand(Op: MCOperand::createReg(Reg: GPRPairDecoderTable[RegNo]));
110 return MCDisassembler::Success;
111}
112
113static DecodeStatus DecodeIWREGSRegisterClass(MCInst &Inst, unsigned RegNo,
114 uint64_t Address,
115 const MCDisassembler *Decoder) {
116 assert(isUInt<2>(RegNo));
117 // Only AVR::R25R24, AVR::R27R26, AVR::R29R28, AVR::R31R30 are legal.
118 Inst.addOperand(Op: MCOperand::createReg(Reg: GPRPairDecoderTable[12 + RegNo]));
119 return MCDisassembler::Success;
120}
121
122static DecodeStatus DecodeZREGRegisterClass(MCInst &Inst,
123 const MCDisassembler *Decoder) {
124 Inst.addOperand(Op: MCOperand::createReg(Reg: AVR::R31R30));
125 return MCDisassembler::Success;
126}
127
128static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field,
129 uint64_t Address,
130 const MCDisassembler *Decoder) {
131 // Call targets need to be shifted left by one so this needs a custom
132 // decoder.
133 Inst.addOperand(Op: MCOperand::createImm(Val: Field << 1));
134 return MCDisassembler::Success;
135}
136
137static DecodeStatus decodeRelCondBrTarget7(MCInst &Inst, unsigned Field,
138 uint64_t Address,
139 const MCDisassembler *Decoder) {
140 // The legal range is [-128, 126] (in bytes).
141 Inst.addOperand(Op: MCOperand::createImm(Val: SignExtend32(X: Field, B: 7) * 2));
142 return MCDisassembler::Success;
143}
144
145static DecodeStatus decodeRelCondBrTarget13(MCInst &Inst, unsigned Field,
146 uint64_t Address,
147 const MCDisassembler *Decoder) {
148 // The legal range is [-4096, 4094] (in bytes).
149 Inst.addOperand(Op: MCOperand::createImm(Val: SignExtend32(X: Field, B: 12) * 2));
150 return MCDisassembler::Success;
151}
152
153static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
154 const MCDisassembler *Decoder) {
155 // As in the EncoderMethod `AVRMCCodeEmitter::encodeMemri`, the memory
156 // address is encoded into 7-bit, in which bits 0-5 are the immediate offset,
157 // and the bit-6 is the pointer register bit (Z=0, Y=1).
158 if (Insn > 127)
159 return MCDisassembler::Fail;
160
161 // Append the base register operand.
162 Inst.addOperand(
163 Op: MCOperand::createReg(Reg: (Insn & 0x40) ? AVR::R29R28 : AVR::R31R30));
164 // Append the immediate offset operand.
165 Inst.addOperand(Op: MCOperand::createImm(Val: Insn & 0x3f));
166
167 return MCDisassembler::Success;
168}
169
170static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
171 uint64_t Address,
172 const MCDisassembler *Decoder) {
173 // Get the register will be loaded or stored.
174 MCRegister RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
175
176 // Decode LDD/STD with offset less than 8.
177 if ((Insn & 0xf000) == 0x8000) {
178 unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30;
179 unsigned Offset = Insn & 7; // We need not consider offset > 7.
180 if ((Insn & 0x200) == 0) { // Decode LDD.
181 Inst.setOpcode(AVR::LDDRdPtrQ);
182 Inst.addOperand(Op: MCOperand::createReg(Reg: RegVal));
183 Inst.addOperand(Op: MCOperand::createReg(Reg: RegBase));
184 Inst.addOperand(Op: MCOperand::createImm(Val: Offset));
185 } else { // Decode STD.
186 Inst.setOpcode(AVR::STDPtrQRr);
187 Inst.addOperand(Op: MCOperand::createReg(Reg: RegBase));
188 Inst.addOperand(Op: MCOperand::createImm(Val: Offset));
189 Inst.addOperand(Op: MCOperand::createReg(Reg: RegVal));
190 }
191 return MCDisassembler::Success;
192 }
193
194 // Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),
195 // bits 8~4 indicate the value register, bits 3-2 indicate the base address
196 // register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,
197 // 01-postinc, 10-predec).
198 // ST X, Rr : 1001 001r rrrr 1100
199 // ST X+, Rr : 1001 001r rrrr 1101
200 // ST -X, Rr : 1001 001r rrrr 1110
201 // ST Y+, Rr : 1001 001r rrrr 1001
202 // ST -Y, Rr : 1001 001r rrrr 1010
203 // ST Z+, Rr : 1001 001r rrrr 0001
204 // ST -Z, Rr : 1001 001r rrrr 0010
205 // LD Rd, X : 1001 000d dddd 1100
206 // LD Rd, X+ : 1001 000d dddd 1101
207 // LD Rd, -X : 1001 000d dddd 1110
208 // LD Rd, Y+ : 1001 000d dddd 1001
209 // LD Rd, -Y : 1001 000d dddd 1010
210 // LD Rd, Z+ : 1001 000d dddd 0001
211 // LD Rd, -Z : 1001 000d dddd 0010
212 if ((Insn & 0xfc00) != 0x9000 || (Insn & 0xf) == 0)
213 return MCDisassembler::Fail;
214
215 // Get the base address register.
216 unsigned RegBase;
217 switch (Insn & 0xc) {
218 case 0xc:
219 RegBase = AVR::R27R26;
220 break;
221 case 0x8:
222 RegBase = AVR::R29R28;
223 break;
224 case 0x0:
225 RegBase = AVR::R31R30;
226 break;
227 default:
228 return MCDisassembler::Fail;
229 }
230
231 // Set the opcode.
232 switch (Insn & 0x203) {
233 case 0x200:
234 Inst.setOpcode(AVR::STPtrRr);
235 Inst.addOperand(Op: MCOperand::createReg(Reg: RegBase));
236 Inst.addOperand(Op: MCOperand::createReg(Reg: RegVal));
237 return MCDisassembler::Success;
238 case 0x201:
239 Inst.setOpcode(AVR::STPtrPiRr);
240 break;
241 case 0x202:
242 Inst.setOpcode(AVR::STPtrPdRr);
243 break;
244 case 0:
245 Inst.setOpcode(AVR::LDRdPtr);
246 Inst.addOperand(Op: MCOperand::createReg(Reg: RegVal));
247 Inst.addOperand(Op: MCOperand::createReg(Reg: RegBase));
248 return MCDisassembler::Success;
249 case 1:
250 Inst.setOpcode(AVR::LDRdPtrPi);
251 break;
252 case 2:
253 Inst.setOpcode(AVR::LDRdPtrPd);
254 break;
255 default:
256 return MCDisassembler::Fail;
257 }
258
259 // Build postinc/predec machine instructions.
260 if ((Insn & 0x200) == 0) { // This is a load instruction.
261 Inst.addOperand(Op: MCOperand::createReg(Reg: RegVal));
262 Inst.addOperand(Op: MCOperand::createReg(Reg: RegBase));
263 Inst.addOperand(Op: MCOperand::createReg(Reg: RegBase));
264 } else { // This is a store instruction.
265 Inst.addOperand(Op: MCOperand::createReg(Reg: RegBase));
266 Inst.addOperand(Op: MCOperand::createReg(Reg: RegBase));
267 Inst.addOperand(Op: MCOperand::createReg(Reg: RegVal));
268 // STPtrPiRr and STPtrPdRr have an extra immediate operand.
269 Inst.addOperand(Op: MCOperand::createImm(Val: 1));
270 }
271
272 return MCDisassembler::Success;
273}
274
275#include "AVRGenDisassemblerTables.inc"
276
277static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
278 uint64_t &Size, uint32_t &Insn) {
279 if (Bytes.size() < 2) {
280 Size = 0;
281 return MCDisassembler::Fail;
282 }
283
284 Size = 2;
285 Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
286
287 return MCDisassembler::Success;
288}
289
290static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
291 uint64_t &Size, uint32_t &Insn) {
292
293 if (Bytes.size() < 4) {
294 Size = 0;
295 return MCDisassembler::Fail;
296 }
297
298 Size = 4;
299 Insn =
300 (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
301
302 return MCDisassembler::Success;
303}
304
305static const uint8_t *getDecoderTable(uint64_t Size) {
306
307 switch (Size) {
308 case 2:
309 return DecoderTable16;
310 case 4:
311 return DecoderTable32;
312 default:
313 llvm_unreachable("instructions must be 16 or 32-bits");
314 }
315}
316
317DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
318 ArrayRef<uint8_t> Bytes,
319 uint64_t Address,
320 raw_ostream &CStream) const {
321 uint32_t Insn;
322
323 DecodeStatus Result;
324
325 // Try decode a 16-bit instruction.
326 {
327 Result = readInstruction16(Bytes, Address, Size, Insn);
328
329 if (Result == MCDisassembler::Fail)
330 return MCDisassembler::Fail;
331
332 // Try to decode AVRTiny instructions.
333 if (STI.hasFeature(Feature: AVR::FeatureTinyEncoding)) {
334 Result = decodeInstruction(DecodeTable: DecoderTableAVRTiny16, MI&: Instr, insn: Insn, Address,
335 DisAsm: this, STI);
336 if (Result != MCDisassembler::Fail)
337 return Result;
338 }
339
340 // Try to auto-decode a 16-bit instruction.
341 Result = decodeInstruction(DecodeTable: getDecoderTable(Size), MI&: Instr, insn: Insn, Address,
342 DisAsm: this, STI);
343 if (Result != MCDisassembler::Fail)
344 return Result;
345
346 // Try to decode to a load/store instruction. ST/LD need a specified
347 // DecoderMethod, as they already have a specified PostEncoderMethod.
348 Result = decodeLoadStore(Inst&: Instr, Insn, Address, Decoder: this);
349 if (Result != MCDisassembler::Fail)
350 return Result;
351 }
352
353 // Try decode a 32-bit instruction.
354 {
355 Result = readInstruction32(Bytes, Address, Size, Insn);
356
357 if (Result == MCDisassembler::Fail)
358 return MCDisassembler::Fail;
359
360 Result = decodeInstruction(DecodeTable: getDecoderTable(Size), MI&: Instr, insn: Insn, Address,
361 DisAsm: this, STI);
362
363 if (Result != MCDisassembler::Fail) {
364 return Result;
365 }
366
367 return MCDisassembler::Fail;
368 }
369}
370
371typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
372 const MCDisassembler *Decoder);
373