LLVM 20.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"
23#include "llvm/MC/MCInst.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "avr-disassembler"
29
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() = default;
40
43 raw_ostream &CStream) const override;
44};
45} // namespace
46
48 const MCSubtargetInfo &STI,
49 MCContext &Ctx) {
50 return new AVRDisassembler(STI, Ctx);
51}
52
54 // Register the disassembler.
57}
58
59static const uint16_t GPRDecoderTable[] = {
60 AVR::R0, AVR::R1, AVR::R2, AVR::R3, AVR::R4, AVR::R5, AVR::R6,
61 AVR::R7, AVR::R8, AVR::R9, AVR::R10, AVR::R11, AVR::R12, AVR::R13,
62 AVR::R14, AVR::R15, AVR::R16, AVR::R17, AVR::R18, AVR::R19, AVR::R20,
63 AVR::R21, AVR::R22, AVR::R23, AVR::R24, AVR::R25, AVR::R26, AVR::R27,
64 AVR::R28, AVR::R29, AVR::R30, AVR::R31,
65};
66
67static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,
68 uint64_t Address,
69 const MCDisassembler *Decoder) {
70 if (RegNo > 31)
72
73 unsigned Register = GPRDecoderTable[RegNo];
76}
77
78static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,
79 uint64_t Address,
80 const MCDisassembler *Decoder) {
81 if (RegNo > 15)
83
84 unsigned Register = GPRDecoderTable[RegNo + 16];
87}
88
89static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
90 const MCDisassembler *Decoder);
91
92static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,
93 const MCDisassembler *Decoder);
94
95static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,
96 const MCDisassembler *Decoder);
97
98static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Insn,
99 uint64_t Address,
100 const MCDisassembler *Decoder);
101
102static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,
103 const MCDisassembler *Decoder);
104
105static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
106 const MCDisassembler *Decoder);
107
108static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
109 uint64_t Address,
110 const MCDisassembler *Decoder);
111
112static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
113 uint64_t Address,
114 const MCDisassembler *Decoder);
115
116static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,
117 const MCDisassembler *Decoder);
118
119static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
120 uint64_t Address,
121 const MCDisassembler *Decoder);
122
123static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
124 const MCDisassembler *Decoder);
125
126static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,
127 const MCDisassembler *Decoder);
128
129static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
130 uint64_t Address,
131 const MCDisassembler *Decoder);
132
133static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
134 uint64_t Address,
135 const MCDisassembler *Decoder);
136
137#include "AVRGenDisassemblerTables.inc"
138
139static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
140 const MCDisassembler *Decoder) {
141 unsigned addr = 0;
142 addr |= fieldFromInstruction(Insn, 0, 4);
143 addr |= fieldFromInstruction(Insn, 9, 2) << 4;
144 unsigned reg = fieldFromInstruction(Insn, 4, 5);
146 if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
150}
151
152static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,
153 const MCDisassembler *Decoder) {
154 unsigned addr = 0;
155 addr |= fieldFromInstruction(Insn, 0, 4);
156 addr |= fieldFromInstruction(Insn, 9, 2) << 4;
157 unsigned reg = fieldFromInstruction(Insn, 4, 5);
158 if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
163}
164
165static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,
166 const MCDisassembler *Decoder) {
167 unsigned addr = fieldFromInstruction(Insn, 3, 5);
168 unsigned b = fieldFromInstruction(Insn, 0, 3);
172}
173
175 uint64_t Address,
176 const MCDisassembler *Decoder) {
177 // Call targets need to be shifted left by one so this needs a custom
178 // decoder.
181}
182
183static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,
184 const MCDisassembler *Decoder) {
185 unsigned d = fieldFromInstruction(Insn, 4, 5);
186 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
190}
191
192static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
193 const MCDisassembler *Decoder) {
194 if (decodeFRd(Inst, Insn, Address, Decoder) == MCDisassembler::Fail)
196 Inst.addOperand(MCOperand::createReg(AVR::R31R30));
198}
199
201 uint64_t Address,
202 const MCDisassembler *Decoder) {
203 unsigned d = fieldFromInstruction(Insn, 4, 3) + 16;
204 unsigned r = fieldFromInstruction(Insn, 0, 3) + 16;
205 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
208 if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
212}
213
215 uint64_t Address,
216 const MCDisassembler *Decoder) {
217 unsigned r = fieldFromInstruction(Insn, 4, 4) * 2;
218 unsigned d = fieldFromInstruction(Insn, 0, 4) * 2;
219 if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
222 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
226}
227
228static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,
229 const MCDisassembler *Decoder) {
230 unsigned d = fieldFromInstruction(Insn, 4, 2) * 2 + 24; // starts at r24:r25
231 unsigned k = 0;
232 k |= fieldFromInstruction(Insn, 0, 4);
233 k |= fieldFromInstruction(Insn, 6, 2) << 4;
234 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
237 if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
242}
243
245 uint64_t Address,
246 const MCDisassembler *Decoder) {
247 unsigned rd = fieldFromInstruction(Insn, 4, 4) + 16;
248 unsigned rr = fieldFromInstruction(Insn, 0, 4) + 16;
249 if (DecodeGPR8RegisterClass(Inst, rd, Address, Decoder) ==
252 if (DecodeGPR8RegisterClass(Inst, rr, Address, Decoder) ==
256}
257
258static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
259 const MCDisassembler *Decoder) {
260 // As in the EncoderMethod `AVRMCCodeEmitter::encodeMemri`, the memory
261 // address is encoded into 7-bit, in which bits 0-5 are the immediate offset,
262 // and the bit-6 is the pointer register bit (Z=0, Y=1).
263 if (Insn > 127)
265
266 // Append the base register operand.
267 Inst.addOperand(
268 MCOperand::createReg((Insn & 0x40) ? AVR::R29R28 : AVR::R31R30));
269 // Append the immediate offset operand.
271
273}
274
275static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,
276 const MCDisassembler *Decoder) {
277 // Decode the opcode.
278 switch (Insn & 0xf000) {
279 case 0xc000:
280 Inst.setOpcode(AVR::RJMPk);
281 break;
282 case 0xd000:
283 Inst.setOpcode(AVR::RCALLk);
284 break;
285 default: // Unknown relative branch instruction.
287 }
288 // Decode the relative offset.
289 int16_t Offset = ((int16_t)((Insn & 0xfff) << 4)) >> 3;
292}
293
295 uint64_t Address,
296 const MCDisassembler *Decoder) {
297 // These 8 instructions are not defined as aliases of BRBS/BRBC.
299 {0x000, AVR::BRLOk}, {0x400, AVR::BRSHk}, {0x001, AVR::BREQk},
300 {0x401, AVR::BRNEk}, {0x002, AVR::BRMIk}, {0x402, AVR::BRPLk},
301 {0x004, AVR::BRLTk}, {0x404, AVR::BRGEk}};
302
303 // Get the relative offset.
304 int16_t Offset = ((int16_t)((Insn & 0x3f8) << 6)) >> 8;
305
306 // Search the instruction pattern.
307 auto NotAlias = [&Insn](const std::pair<unsigned, unsigned> &I) {
308 return (Insn & 0x407) != I.first;
309 };
310 llvm::partition(brInsts, NotAlias);
311 auto It = llvm::partition_point(brInsts, NotAlias);
312
313 // Decode the instruction.
314 if (It != brInsts.end()) {
315 // This instruction is not an alias of BRBC/BRBS.
316 Inst.setOpcode(It->second);
318 } else {
319 // Fall back to an ordinary BRBS/BRBC.
320 Inst.setOpcode(Insn & 0x400 ? AVR::BRBCsk : AVR::BRBSsk);
323 }
324
326}
327
329 uint64_t Address,
330 const MCDisassembler *Decoder) {
331 // Get the register will be loaded or stored.
332 unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
333
334 // Decode LDD/STD with offset less than 8.
335 if ((Insn & 0xf000) == 0x8000) {
336 unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30;
337 unsigned Offset = Insn & 7; // We need not consider offset > 7.
338 if ((Insn & 0x200) == 0) { // Decode LDD.
339 Inst.setOpcode(AVR::LDDRdPtrQ);
340 Inst.addOperand(MCOperand::createReg(RegVal));
341 Inst.addOperand(MCOperand::createReg(RegBase));
343 } else { // Decode STD.
344 Inst.setOpcode(AVR::STDPtrQRr);
345 Inst.addOperand(MCOperand::createReg(RegBase));
347 Inst.addOperand(MCOperand::createReg(RegVal));
348 }
350 }
351
352 // Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),
353 // bits 8~4 indicate the value register, bits 3-2 indicate the base address
354 // register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,
355 // 01-postinc, 10-predec).
356 // ST X, Rr : 1001 001r rrrr 1100
357 // ST X+, Rr : 1001 001r rrrr 1101
358 // ST -X, Rr : 1001 001r rrrr 1110
359 // ST Y+, Rr : 1001 001r rrrr 1001
360 // ST -Y, Rr : 1001 001r rrrr 1010
361 // ST Z+, Rr : 1001 001r rrrr 0001
362 // ST -Z, Rr : 1001 001r rrrr 0010
363 // LD Rd, X : 1001 000d dddd 1100
364 // LD Rd, X+ : 1001 000d dddd 1101
365 // LD Rd, -X : 1001 000d dddd 1110
366 // LD Rd, Y+ : 1001 000d dddd 1001
367 // LD Rd, -Y : 1001 000d dddd 1010
368 // LD Rd, Z+ : 1001 000d dddd 0001
369 // LD Rd, -Z : 1001 000d dddd 0010
370 if ((Insn & 0xfc00) != 0x9000 || (Insn & 0xf) == 0)
372
373 // Get the base address register.
374 unsigned RegBase;
375 switch (Insn & 0xc) {
376 case 0xc:
377 RegBase = AVR::R27R26;
378 break;
379 case 0x8:
380 RegBase = AVR::R29R28;
381 break;
382 case 0x0:
383 RegBase = AVR::R31R30;
384 break;
385 default:
387 }
388
389 // Set the opcode.
390 switch (Insn & 0x203) {
391 case 0x200:
392 Inst.setOpcode(AVR::STPtrRr);
393 Inst.addOperand(MCOperand::createReg(RegBase));
394 Inst.addOperand(MCOperand::createReg(RegVal));
396 case 0x201:
397 Inst.setOpcode(AVR::STPtrPiRr);
398 break;
399 case 0x202:
400 Inst.setOpcode(AVR::STPtrPdRr);
401 break;
402 case 0:
403 Inst.setOpcode(AVR::LDRdPtr);
404 Inst.addOperand(MCOperand::createReg(RegVal));
405 Inst.addOperand(MCOperand::createReg(RegBase));
407 case 1:
408 Inst.setOpcode(AVR::LDRdPtrPi);
409 break;
410 case 2:
411 Inst.setOpcode(AVR::LDRdPtrPd);
412 break;
413 default:
415 }
416
417 // Build postinc/predec machine instructions.
418 if ((Insn & 0x200) == 0) { // This is a load instruction.
419 Inst.addOperand(MCOperand::createReg(RegVal));
420 Inst.addOperand(MCOperand::createReg(RegBase));
421 Inst.addOperand(MCOperand::createReg(RegBase));
422 } else { // This is a store instruction.
423 Inst.addOperand(MCOperand::createReg(RegBase));
424 Inst.addOperand(MCOperand::createReg(RegBase));
425 Inst.addOperand(MCOperand::createReg(RegVal));
426 // STPtrPiRr and STPtrPdRr have an extra immediate operand.
428 }
429
431}
432
435 if (Bytes.size() < 2) {
436 Size = 0;
438 }
439
440 Size = 2;
441 Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
442
444}
445
448
449 if (Bytes.size() < 4) {
450 Size = 0;
452 }
453
454 Size = 4;
455 Insn =
456 (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
457
459}
460
462
463 switch (Size) {
464 case 2:
465 return DecoderTable16;
466 case 4:
467 return DecoderTable32;
468 default:
469 llvm_unreachable("instructions must be 16 or 32-bits");
470 }
471}
472
473DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
474 ArrayRef<uint8_t> Bytes,
475 uint64_t Address,
476 raw_ostream &CStream) const {
478
480
481 // Try decode a 16-bit instruction.
482 {
483 Result = readInstruction16(Bytes, Address, Size, Insn);
484
485 if (Result == MCDisassembler::Fail)
487
488 // Try to decode AVRTiny instructions.
489 if (STI.hasFeature(AVR::FeatureTinyEncoding)) {
490 Result = decodeInstruction(DecoderTableAVRTiny16, Instr, Insn, Address,
491 this, STI);
492 if (Result != MCDisassembler::Fail)
493 return Result;
494 }
495
496 // Try to auto-decode a 16-bit instruction.
497 Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
498 this, STI);
499 if (Result != MCDisassembler::Fail)
500 return Result;
501
502 // Try to decode to a load/store instruction. ST/LD need a specified
503 // DecoderMethod, as they already have a specified PostEncoderMethod.
504 Result = decodeLoadStore(Instr, Insn, Address, this);
505 if (Result != MCDisassembler::Fail)
506 return Result;
507 }
508
509 // Try decode a 32-bit instruction.
510 {
511 Result = readInstruction32(Bytes, Address, Size, Insn);
512
513 if (Result == MCDisassembler::Fail)
515
516 Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
517 this, STI);
518
519 if (Result != MCDisassembler::Fail) {
520 return Result;
521 }
522
524 }
525}
526
527typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
528 const MCDisassembler *Decoder);
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
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 decodeCallTarget(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)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRDisassembler()
static const uint8_t * getDecoderTable(uint64_t Size)
static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder)
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:128
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:168
iterator end()
Definition: DenseMap.h:84
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:185
void addOperand(const MCOperand Op)
Definition: MCInst.h:211
void setOpcode(unsigned Op)
Definition: MCInst.h:198
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:135
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:142
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:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
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:2050
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:1959
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.