LLVM 22.0.0git
AVRDisassembler.cpp
Go to the documentation of this file.
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
15
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ADT/STLExtras.h"
18
19#include "llvm/MC/MCAsmInfo.h"
20#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCDecoder.h"
24#include "llvm/MC/MCInst.h"
26
28
29using namespace llvm;
30using namespace llvm::MCD;
31
32#define DEBUG_TYPE "avr-disassembler"
33
35
36namespace {
37
38/// A disassembler class for AVR.
39class AVRDisassembler : public MCDisassembler {
40public:
41 AVRDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
42 : MCDisassembler(STI, Ctx) {}
43 virtual ~AVRDisassembler() = default;
44
47 raw_ostream &CStream) const override;
48};
49} // namespace
50
52 const MCSubtargetInfo &STI,
53 MCContext &Ctx) {
54 return new AVRDisassembler(STI, Ctx);
55}
56
59 // Register the disassembler.
62}
63
64static const uint16_t GPRDecoderTable[] = {
65 AVR::R0, AVR::R1, AVR::R2, AVR::R3, AVR::R4, AVR::R5, AVR::R6,
66 AVR::R7, AVR::R8, AVR::R9, AVR::R10, AVR::R11, AVR::R12, AVR::R13,
67 AVR::R14, AVR::R15, AVR::R16, AVR::R17, AVR::R18, AVR::R19, AVR::R20,
68 AVR::R21, AVR::R22, AVR::R23, AVR::R24, AVR::R25, AVR::R26, AVR::R27,
69 AVR::R28, AVR::R29, AVR::R30, AVR::R31,
70};
71
72static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,
73 uint64_t Address,
74 const MCDisassembler *Decoder) {
75 if (RegNo > 31)
77
78 unsigned Register = GPRDecoderTable[RegNo];
81}
82
83static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,
84 uint64_t Address,
85 const MCDisassembler *Decoder) {
86 if (RegNo > 15)
88
89 unsigned Register = GPRDecoderTable[RegNo + 16];
92}
93
94static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
95 const MCDisassembler *Decoder) {
96 unsigned addr = 0;
97 addr |= fieldFromInstruction(Insn, 0, 4);
98 addr |= fieldFromInstruction(Insn, 9, 2) << 4;
99 unsigned reg = fieldFromInstruction(Insn, 4, 5);
101 if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
105}
106
107static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,
108 const MCDisassembler *Decoder) {
109 unsigned addr = 0;
110 addr |= fieldFromInstruction(Insn, 0, 4);
111 addr |= fieldFromInstruction(Insn, 9, 2) << 4;
112 unsigned reg = fieldFromInstruction(Insn, 4, 5);
113 if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
118}
119
120static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,
121 const MCDisassembler *Decoder) {
122 unsigned addr = fieldFromInstruction(Insn, 3, 5);
123 unsigned b = fieldFromInstruction(Insn, 0, 3);
127}
128
130 uint64_t Address,
131 const MCDisassembler *Decoder) {
132 // Call targets need to be shifted left by one so this needs a custom
133 // decoder.
136}
137
138static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,
139 const MCDisassembler *Decoder) {
140 unsigned d = fieldFromInstruction(Insn, 4, 5);
141 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
145}
146
147static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
148 const MCDisassembler *Decoder) {
149 if (decodeFRd(Inst, Insn, Address, Decoder) == MCDisassembler::Fail)
151 Inst.addOperand(MCOperand::createReg(AVR::R31R30));
153}
154
155static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
156 uint64_t Address,
157 const MCDisassembler *Decoder) {
158 unsigned d = fieldFromInstruction(Insn, 4, 3) + 16;
159 unsigned r = fieldFromInstruction(Insn, 0, 3) + 16;
160 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
163 if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
167}
168
169static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
170 uint64_t Address,
171 const MCDisassembler *Decoder) {
172 unsigned r = fieldFromInstruction(Insn, 4, 4) * 2;
173 unsigned d = fieldFromInstruction(Insn, 0, 4) * 2;
174 if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
177 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
181}
182
183static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,
184 const MCDisassembler *Decoder) {
185 unsigned d = fieldFromInstruction(Insn, 4, 2) * 2 + 24; // starts at r24:r25
186 unsigned k = 0;
187 k |= fieldFromInstruction(Insn, 0, 4);
188 k |= fieldFromInstruction(Insn, 6, 2) << 4;
189 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
192 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
197}
198
199static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
200 uint64_t Address,
201 const MCDisassembler *Decoder) {
202 unsigned rd = fieldFromInstruction(Insn, 4, 4) + 16;
203 unsigned rr = fieldFromInstruction(Insn, 0, 4) + 16;
204 if (DecodeGPR8RegisterClass(Inst, rd, Address, Decoder) ==
207 if (DecodeGPR8RegisterClass(Inst, rr, Address, Decoder) ==
211}
212
213static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
214 const MCDisassembler *Decoder) {
215 // As in the EncoderMethod `AVRMCCodeEmitter::encodeMemri`, the memory
216 // address is encoded into 7-bit, in which bits 0-5 are the immediate offset,
217 // and the bit-6 is the pointer register bit (Z=0, Y=1).
218 if (Insn > 127)
220
221 // Append the base register operand.
222 Inst.addOperand(
223 MCOperand::createReg((Insn & 0x40) ? AVR::R29R28 : AVR::R31R30));
224 // Append the immediate offset operand.
225 Inst.addOperand(MCOperand::createImm(Insn & 0x3f));
226
228}
229
230static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,
231 const MCDisassembler *Decoder) {
232 // Decode the opcode.
233 switch (Insn & 0xf000) {
234 case 0xc000:
235 Inst.setOpcode(AVR::RJMPk);
236 break;
237 case 0xd000:
238 Inst.setOpcode(AVR::RCALLk);
239 break;
240 default: // Unknown relative branch instruction.
242 }
243 // Decode the relative offset.
244 int16_t Offset = ((int16_t)((Insn & 0xfff) << 4)) >> 3;
247}
248
249static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
250 uint64_t Address,
251 const MCDisassembler *Decoder) {
252 // These 8 instructions are not defined as aliases of BRBS/BRBC.
254 {0x000, AVR::BRLOk}, {0x400, AVR::BRSHk}, {0x001, AVR::BREQk},
255 {0x401, AVR::BRNEk}, {0x002, AVR::BRMIk}, {0x402, AVR::BRPLk},
256 {0x004, AVR::BRLTk}, {0x404, AVR::BRGEk}};
257
258 // Get the relative offset.
259 int16_t Offset = ((int16_t)((Insn & 0x3f8) << 6)) >> 8;
260
261 // Search the instruction pattern.
262 auto NotAlias = [&Insn](const std::pair<unsigned, unsigned> &I) {
263 return (Insn & 0x407) != I.first;
264 };
265 llvm::partition(brInsts, NotAlias);
266 auto It = llvm::partition_point(brInsts, NotAlias);
267
268 // Decode the instruction.
269 if (It != brInsts.end()) {
270 // This instruction is not an alias of BRBC/BRBS.
271 Inst.setOpcode(It->second);
273 } else {
274 // Fall back to an ordinary BRBS/BRBC.
275 Inst.setOpcode(Insn & 0x400 ? AVR::BRBCsk : AVR::BRBSsk);
276 Inst.addOperand(MCOperand::createImm(Insn & 7));
278 }
279
281}
282
283static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
284 uint64_t Address,
285 const MCDisassembler *Decoder) {
286 // Get the register will be loaded or stored.
287 unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
288
289 // Decode LDD/STD with offset less than 8.
290 if ((Insn & 0xf000) == 0x8000) {
291 unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30;
292 unsigned Offset = Insn & 7; // We need not consider offset > 7.
293 if ((Insn & 0x200) == 0) { // Decode LDD.
294 Inst.setOpcode(AVR::LDDRdPtrQ);
295 Inst.addOperand(MCOperand::createReg(RegVal));
296 Inst.addOperand(MCOperand::createReg(RegBase));
298 } else { // Decode STD.
299 Inst.setOpcode(AVR::STDPtrQRr);
300 Inst.addOperand(MCOperand::createReg(RegBase));
302 Inst.addOperand(MCOperand::createReg(RegVal));
303 }
305 }
306
307 // Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),
308 // bits 8~4 indicate the value register, bits 3-2 indicate the base address
309 // register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,
310 // 01-postinc, 10-predec).
311 // ST X, Rr : 1001 001r rrrr 1100
312 // ST X+, Rr : 1001 001r rrrr 1101
313 // ST -X, Rr : 1001 001r rrrr 1110
314 // ST Y+, Rr : 1001 001r rrrr 1001
315 // ST -Y, Rr : 1001 001r rrrr 1010
316 // ST Z+, Rr : 1001 001r rrrr 0001
317 // ST -Z, Rr : 1001 001r rrrr 0010
318 // LD Rd, X : 1001 000d dddd 1100
319 // LD Rd, X+ : 1001 000d dddd 1101
320 // LD Rd, -X : 1001 000d dddd 1110
321 // LD Rd, Y+ : 1001 000d dddd 1001
322 // LD Rd, -Y : 1001 000d dddd 1010
323 // LD Rd, Z+ : 1001 000d dddd 0001
324 // LD Rd, -Z : 1001 000d dddd 0010
325 if ((Insn & 0xfc00) != 0x9000 || (Insn & 0xf) == 0)
327
328 // Get the base address register.
329 unsigned RegBase;
330 switch (Insn & 0xc) {
331 case 0xc:
332 RegBase = AVR::R27R26;
333 break;
334 case 0x8:
335 RegBase = AVR::R29R28;
336 break;
337 case 0x0:
338 RegBase = AVR::R31R30;
339 break;
340 default:
342 }
343
344 // Set the opcode.
345 switch (Insn & 0x203) {
346 case 0x200:
347 Inst.setOpcode(AVR::STPtrRr);
348 Inst.addOperand(MCOperand::createReg(RegBase));
349 Inst.addOperand(MCOperand::createReg(RegVal));
351 case 0x201:
352 Inst.setOpcode(AVR::STPtrPiRr);
353 break;
354 case 0x202:
355 Inst.setOpcode(AVR::STPtrPdRr);
356 break;
357 case 0:
358 Inst.setOpcode(AVR::LDRdPtr);
359 Inst.addOperand(MCOperand::createReg(RegVal));
360 Inst.addOperand(MCOperand::createReg(RegBase));
362 case 1:
363 Inst.setOpcode(AVR::LDRdPtrPi);
364 break;
365 case 2:
366 Inst.setOpcode(AVR::LDRdPtrPd);
367 break;
368 default:
370 }
371
372 // Build postinc/predec machine instructions.
373 if ((Insn & 0x200) == 0) { // This is a load instruction.
374 Inst.addOperand(MCOperand::createReg(RegVal));
375 Inst.addOperand(MCOperand::createReg(RegBase));
376 Inst.addOperand(MCOperand::createReg(RegBase));
377 } else { // This is a store instruction.
378 Inst.addOperand(MCOperand::createReg(RegBase));
379 Inst.addOperand(MCOperand::createReg(RegBase));
380 Inst.addOperand(MCOperand::createReg(RegVal));
381 // STPtrPiRr and STPtrPdRr have an extra immediate operand.
383 }
384
386}
387
388#include "AVRGenDisassemblerTables.inc"
389
391 uint64_t &Size, uint32_t &Insn) {
392 if (Bytes.size() < 2) {
393 Size = 0;
395 }
396
397 Size = 2;
398 Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
399
401}
402
404 uint64_t &Size, uint32_t &Insn) {
405
406 if (Bytes.size() < 4) {
407 Size = 0;
409 }
410
411 Size = 4;
412 Insn =
413 (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
414
416}
417
419
420 switch (Size) {
421 case 2:
422 return DecoderTable16;
423 case 4:
424 return DecoderTable32;
425 default:
426 llvm_unreachable("instructions must be 16 or 32-bits");
427 }
428}
429
430DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
431 ArrayRef<uint8_t> Bytes,
432 uint64_t Address,
433 raw_ostream &CStream) const {
434 uint32_t Insn;
435
437
438 // Try decode a 16-bit instruction.
439 {
440 Result = readInstruction16(Bytes, Address, Size, Insn);
441
442 if (Result == MCDisassembler::Fail)
444
445 // Try to decode AVRTiny instructions.
446 if (STI.hasFeature(AVR::FeatureTinyEncoding)) {
447 Result = decodeInstruction(DecoderTableAVRTiny16, Instr, Insn, Address,
448 this, STI);
449 if (Result != MCDisassembler::Fail)
450 return Result;
451 }
452
453 // Try to auto-decode a 16-bit instruction.
454 Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
455 this, STI);
456 if (Result != MCDisassembler::Fail)
457 return Result;
458
459 // Try to decode to a load/store instruction. ST/LD need a specified
460 // DecoderMethod, as they already have a specified PostEncoderMethod.
461 Result = decodeLoadStore(Instr, Insn, Address, this);
462 if (Result != MCDisassembler::Fail)
463 return Result;
464 }
465
466 // Try decode a 32-bit instruction.
467 {
468 Result = readInstruction32(Bytes, Address, Size, Insn);
469
470 if (Result == MCDisassembler::Fail)
472
473 Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
474 this, STI);
475
476 if (Result != MCDisassembler::Fail) {
477 return Result;
478 }
479
481 }
482}
483
484typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
485 const MCDisassembler *Decoder);
static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRDisassembler()
static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
MCDisassembler::DecodeStatus DecodeStatus
static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const MCDisassembler *Decoder)
DecodeStatus(* DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus readInstruction16(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint32_t &Insn)
static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static const uint16_t GPRDecoderTable[]
static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static MCDisassembler * createAVRDisassembler(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx)
static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus readInstruction32(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint32_t &Insn)
static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
static const uint8_t * getDecoderTable(uint64_t Size)
static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
This file defines the DenseMap class.
uint64_t Size
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
This file contains some templates that are useful if you are working with the STL at all.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:147
iterator end()
Definition: DenseMap.h:87
Context object for machine code objects.
Definition: MCContext.h:83
Superclass for all disassemblers.
DecodeStatus
Ternary decode status.
virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef< uint8_t > Bytes, uint64_t Address, raw_ostream &CStream) const =0
Returns the disassembly of a single instruction.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:188
void addOperand(const MCOperand Op)
Definition: MCInst.h:215
void setOpcode(unsigned Op)
Definition: MCInst.h:201
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:145
Generic base class for all target subtargets.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Target - Wrapper for Target specific information.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::enable_if_t< std::is_integral_v< IntType >, IntType > fieldFromInstruction(const IntType &Insn, unsigned StartBit, unsigned NumBits)
Definition: MCDecoder.h:36
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
Target & getTheAVRTarget()
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
Definition: STLExtras.h:2090
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1994
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.