1 //===- AVRDisassembler.cpp - Disassembler for AVR ---------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is part of the AVR Disassembler.
11 //===----------------------------------------------------------------------===//
14 #include "AVRRegisterInfo.h"
15 #include "AVRSubtarget.h"
16 #include "MCTargetDesc/AVRMCTargetDesc.h"
17 #include "TargetInfo/AVRTargetInfo.h"
19 #include "llvm/MC/MCAsmInfo.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCDecoderOps.h"
22 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/MC/TargetRegistry.h"
28 #define DEBUG_TYPE "avr-disassembler"
30 typedef MCDisassembler::DecodeStatus DecodeStatus
;
34 /// A disassembler class for AVR.
35 class AVRDisassembler
: public MCDisassembler
{
37 AVRDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
38 : MCDisassembler(STI
, Ctx
) {}
39 virtual ~AVRDisassembler() = default;
41 DecodeStatus
getInstruction(MCInst
&Instr
, uint64_t &Size
,
42 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
43 raw_ostream
&CStream
) const override
;
47 static MCDisassembler
*createAVRDisassembler(const Target
&T
,
48 const MCSubtargetInfo
&STI
,
50 return new AVRDisassembler(STI
, Ctx
);
53 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeAVRDisassembler() {
54 // Register the disassembler.
55 TargetRegistry::RegisterMCDisassembler(getTheAVRTarget(),
56 createAVRDisassembler
);
59 static 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
,
67 static DecodeStatus
DecodeGPR8RegisterClass(MCInst
&Inst
, unsigned RegNo
,
69 const MCDisassembler
*Decoder
) {
71 return MCDisassembler::Fail
;
73 unsigned Register
= GPRDecoderTable
[RegNo
];
74 Inst
.addOperand(MCOperand::createReg(Register
));
75 return MCDisassembler::Success
;
78 static DecodeStatus
DecodeLD8RegisterClass(MCInst
&Inst
, unsigned RegNo
,
80 const MCDisassembler
*Decoder
) {
82 return MCDisassembler::Fail
;
84 unsigned Register
= GPRDecoderTable
[RegNo
+ 16];
85 Inst
.addOperand(MCOperand::createReg(Register
));
86 return MCDisassembler::Success
;
89 static DecodeStatus
decodeFIOARr(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
90 const MCDisassembler
*Decoder
);
92 static DecodeStatus
decodeFIORdA(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
93 const MCDisassembler
*Decoder
);
95 static DecodeStatus
decodeFIOBIT(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
96 const MCDisassembler
*Decoder
);
98 static DecodeStatus
decodeCallTarget(MCInst
&Inst
, unsigned Insn
,
100 const MCDisassembler
*Decoder
);
102 static DecodeStatus
decodeFRd(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
103 const MCDisassembler
*Decoder
);
105 static DecodeStatus
decodeFLPMX(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
106 const MCDisassembler
*Decoder
);
108 static DecodeStatus
decodeFFMULRdRr(MCInst
&Inst
, unsigned Insn
,
110 const MCDisassembler
*Decoder
);
112 static DecodeStatus
decodeFMOVWRdRr(MCInst
&Inst
, unsigned Insn
,
114 const MCDisassembler
*Decoder
);
116 static DecodeStatus
decodeFWRdK(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
117 const MCDisassembler
*Decoder
);
119 static DecodeStatus
decodeFMUL2RdRr(MCInst
&Inst
, unsigned Insn
,
121 const MCDisassembler
*Decoder
);
123 static DecodeStatus
decodeMemri(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
124 const MCDisassembler
*Decoder
);
126 static DecodeStatus
decodeLoadStore(MCInst
&Inst
, unsigned Insn
,
128 const MCDisassembler
*Decoder
);
130 #include "AVRGenDisassemblerTables.inc"
132 static DecodeStatus
decodeFIOARr(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
133 const MCDisassembler
*Decoder
) {
135 addr
|= fieldFromInstruction(Insn
, 0, 4);
136 addr
|= fieldFromInstruction(Insn
, 9, 2) << 4;
137 unsigned reg
= fieldFromInstruction(Insn
, 4, 5);
138 Inst
.addOperand(MCOperand::createImm(addr
));
139 if (DecodeGPR8RegisterClass(Inst
, reg
, Address
, Decoder
) ==
140 MCDisassembler::Fail
)
141 return MCDisassembler::Fail
;
142 return MCDisassembler::Success
;
145 static DecodeStatus
decodeFIORdA(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
146 const MCDisassembler
*Decoder
) {
148 addr
|= fieldFromInstruction(Insn
, 0, 4);
149 addr
|= fieldFromInstruction(Insn
, 9, 2) << 4;
150 unsigned reg
= fieldFromInstruction(Insn
, 4, 5);
151 if (DecodeGPR8RegisterClass(Inst
, reg
, Address
, Decoder
) ==
152 MCDisassembler::Fail
)
153 return MCDisassembler::Fail
;
154 Inst
.addOperand(MCOperand::createImm(addr
));
155 return MCDisassembler::Success
;
158 static DecodeStatus
decodeFIOBIT(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
159 const MCDisassembler
*Decoder
) {
160 unsigned addr
= fieldFromInstruction(Insn
, 3, 5);
161 unsigned b
= fieldFromInstruction(Insn
, 0, 3);
162 Inst
.addOperand(MCOperand::createImm(addr
));
163 Inst
.addOperand(MCOperand::createImm(b
));
164 return MCDisassembler::Success
;
167 static DecodeStatus
decodeCallTarget(MCInst
&Inst
, unsigned Field
,
169 const MCDisassembler
*Decoder
) {
170 // Call targets need to be shifted left by one so this needs a custom
172 Inst
.addOperand(MCOperand::createImm(Field
<< 1));
173 return MCDisassembler::Success
;
176 static DecodeStatus
decodeFRd(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
177 const MCDisassembler
*Decoder
) {
178 unsigned d
= fieldFromInstruction(Insn
, 4, 5);
179 if (DecodeGPR8RegisterClass(Inst
, d
, Address
, Decoder
) ==
180 MCDisassembler::Fail
)
181 return MCDisassembler::Fail
;
182 return MCDisassembler::Success
;
185 static DecodeStatus
decodeFLPMX(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
186 const MCDisassembler
*Decoder
) {
187 if (decodeFRd(Inst
, Insn
, Address
, Decoder
) == MCDisassembler::Fail
)
188 return MCDisassembler::Fail
;
189 Inst
.addOperand(MCOperand::createReg(AVR::R31R30
));
190 return MCDisassembler::Success
;
193 static DecodeStatus
decodeFFMULRdRr(MCInst
&Inst
, unsigned Insn
,
195 const MCDisassembler
*Decoder
) {
196 unsigned d
= fieldFromInstruction(Insn
, 4, 3) + 16;
197 unsigned r
= fieldFromInstruction(Insn
, 0, 3) + 16;
198 if (DecodeGPR8RegisterClass(Inst
, d
, Address
, Decoder
) ==
199 MCDisassembler::Fail
)
200 return MCDisassembler::Fail
;
201 if (DecodeGPR8RegisterClass(Inst
, r
, Address
, Decoder
) ==
202 MCDisassembler::Fail
)
203 return MCDisassembler::Fail
;
204 return MCDisassembler::Success
;
207 static DecodeStatus
decodeFMOVWRdRr(MCInst
&Inst
, unsigned Insn
,
209 const MCDisassembler
*Decoder
) {
210 unsigned r
= fieldFromInstruction(Insn
, 4, 4) * 2;
211 unsigned d
= fieldFromInstruction(Insn
, 0, 4) * 2;
212 if (DecodeGPR8RegisterClass(Inst
, r
, Address
, Decoder
) ==
213 MCDisassembler::Fail
)
214 return MCDisassembler::Fail
;
215 if (DecodeGPR8RegisterClass(Inst
, d
, Address
, Decoder
) ==
216 MCDisassembler::Fail
)
217 return MCDisassembler::Fail
;
218 return MCDisassembler::Success
;
221 static DecodeStatus
decodeFWRdK(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
222 const MCDisassembler
*Decoder
) {
223 unsigned d
= fieldFromInstruction(Insn
, 4, 2) * 2 + 24; // starts at r24:r25
225 k
|= fieldFromInstruction(Insn
, 0, 4);
226 k
|= fieldFromInstruction(Insn
, 6, 2) << 4;
227 if (DecodeGPR8RegisterClass(Inst
, d
, Address
, Decoder
) ==
228 MCDisassembler::Fail
)
229 return MCDisassembler::Fail
;
230 if (DecodeGPR8RegisterClass(Inst
, d
, Address
, Decoder
) ==
231 MCDisassembler::Fail
)
232 return MCDisassembler::Fail
;
233 Inst
.addOperand(MCOperand::createImm(k
));
234 return MCDisassembler::Success
;
237 static DecodeStatus
decodeFMUL2RdRr(MCInst
&Inst
, unsigned Insn
,
239 const MCDisassembler
*Decoder
) {
240 unsigned rd
= fieldFromInstruction(Insn
, 4, 4) + 16;
241 unsigned rr
= fieldFromInstruction(Insn
, 0, 4) + 16;
242 if (DecodeGPR8RegisterClass(Inst
, rd
, Address
, Decoder
) ==
243 MCDisassembler::Fail
)
244 return MCDisassembler::Fail
;
245 if (DecodeGPR8RegisterClass(Inst
, rr
, Address
, Decoder
) ==
246 MCDisassembler::Fail
)
247 return MCDisassembler::Fail
;
248 return MCDisassembler::Success
;
251 static DecodeStatus
decodeMemri(MCInst
&Inst
, unsigned Insn
, uint64_t Address
,
252 const MCDisassembler
*Decoder
) {
253 // As in the EncoderMethod `AVRMCCodeEmitter::encodeMemri`, the memory
254 // address is encoded into 7-bit, in which bits 0-5 are the immediate offset,
255 // and the bit-6 is the pointer register bit (Z=0, Y=1).
257 return MCDisassembler::Fail
;
259 // Append the base register operand.
261 MCOperand::createReg((Insn
& 0x40) ? AVR::R29R28
: AVR::R31R30
));
262 // Append the immediate offset operand.
263 Inst
.addOperand(MCOperand::createImm(Insn
& 0x3f));
265 return MCDisassembler::Success
;
268 static DecodeStatus
decodeLoadStore(MCInst
&Inst
, unsigned Insn
,
270 const MCDisassembler
*Decoder
) {
271 // Get the register will be loaded or stored.
272 unsigned RegVal
= GPRDecoderTable
[(Insn
>> 4) & 0x1f];
274 // Decode LDD/STD with offset less than 8.
275 if ((Insn
& 0xf000) == 0x8000) {
276 unsigned RegBase
= (Insn
& 0x8) ? AVR::R29R28
: AVR::R31R30
;
277 unsigned Offset
= Insn
& 7; // We need not consider offset > 7.
278 if ((Insn
& 0x200) == 0) { // Decode LDD.
279 Inst
.setOpcode(AVR::LDDRdPtrQ
);
280 Inst
.addOperand(MCOperand::createReg(RegVal
));
281 Inst
.addOperand(MCOperand::createReg(RegBase
));
282 Inst
.addOperand(MCOperand::createImm(Offset
));
283 } else { // Decode STD.
284 Inst
.setOpcode(AVR::STDPtrQRr
);
285 Inst
.addOperand(MCOperand::createReg(RegBase
));
286 Inst
.addOperand(MCOperand::createImm(Offset
));
287 Inst
.addOperand(MCOperand::createReg(RegVal
));
289 return MCDisassembler::Success
;
292 // Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),
293 // bits 8~4 indicate the value register, bits 3-2 indicate the base address
294 // register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,
295 // 01-postinc, 10-predec).
296 // ST X, Rr : 1001 001r rrrr 1100
297 // ST X+, Rr : 1001 001r rrrr 1101
298 // ST -X, Rr : 1001 001r rrrr 1110
299 // ST Y+, Rr : 1001 001r rrrr 1001
300 // ST -Y, Rr : 1001 001r rrrr 1010
301 // ST Z+, Rr : 1001 001r rrrr 0001
302 // ST -Z, Rr : 1001 001r rrrr 0010
303 // LD Rd, X : 1001 000d dddd 1100
304 // LD Rd, X+ : 1001 000d dddd 1101
305 // LD Rd, -X : 1001 000d dddd 1110
306 // LD Rd, Y+ : 1001 000d dddd 1001
307 // LD Rd, -Y : 1001 000d dddd 1010
308 // LD Rd, Z+ : 1001 000d dddd 0001
309 // LD Rd, -Z : 1001 000d dddd 0010
310 if ((Insn
& 0xfc00) != 0x9000 || (Insn
& 0xf) == 0)
311 return MCDisassembler::Fail
;
313 // Get the base address register.
315 switch (Insn
& 0xc) {
317 RegBase
= AVR::R27R26
;
320 RegBase
= AVR::R29R28
;
323 RegBase
= AVR::R31R30
;
326 return MCDisassembler::Fail
;
330 switch (Insn
& 0x203) {
332 Inst
.setOpcode(AVR::STPtrRr
);
333 Inst
.addOperand(MCOperand::createReg(RegBase
));
334 Inst
.addOperand(MCOperand::createReg(RegVal
));
335 return MCDisassembler::Success
;
337 Inst
.setOpcode(AVR::STPtrPiRr
);
340 Inst
.setOpcode(AVR::STPtrPdRr
);
343 Inst
.setOpcode(AVR::LDRdPtr
);
344 Inst
.addOperand(MCOperand::createReg(RegVal
));
345 Inst
.addOperand(MCOperand::createReg(RegBase
));
346 return MCDisassembler::Success
;
348 Inst
.setOpcode(AVR::LDRdPtrPi
);
351 Inst
.setOpcode(AVR::LDRdPtrPd
);
354 return MCDisassembler::Fail
;
357 // Build postinc/predec machine instructions.
358 if ((Insn
& 0x200) == 0) { // This is a load instruction.
359 Inst
.addOperand(MCOperand::createReg(RegVal
));
360 Inst
.addOperand(MCOperand::createReg(RegBase
));
361 Inst
.addOperand(MCOperand::createReg(RegBase
));
362 } else { // This is a store instruction.
363 Inst
.addOperand(MCOperand::createReg(RegBase
));
364 Inst
.addOperand(MCOperand::createReg(RegBase
));
365 Inst
.addOperand(MCOperand::createReg(RegVal
));
366 // STPtrPiRr and STPtrPdRr have an extra immediate operand.
367 Inst
.addOperand(MCOperand::createImm(1));
370 return MCDisassembler::Success
;
373 static DecodeStatus
readInstruction16(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
374 uint64_t &Size
, uint32_t &Insn
) {
375 if (Bytes
.size() < 2) {
377 return MCDisassembler::Fail
;
381 Insn
= (Bytes
[0] << 0) | (Bytes
[1] << 8);
383 return MCDisassembler::Success
;
386 static DecodeStatus
readInstruction32(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
387 uint64_t &Size
, uint32_t &Insn
) {
389 if (Bytes
.size() < 4) {
391 return MCDisassembler::Fail
;
396 (Bytes
[0] << 16) | (Bytes
[1] << 24) | (Bytes
[2] << 0) | (Bytes
[3] << 8);
398 return MCDisassembler::Success
;
401 static const uint8_t *getDecoderTable(uint64_t Size
) {
405 return DecoderTable16
;
407 return DecoderTable32
;
409 llvm_unreachable("instructions must be 16 or 32-bits");
413 DecodeStatus
AVRDisassembler::getInstruction(MCInst
&Instr
, uint64_t &Size
,
414 ArrayRef
<uint8_t> Bytes
,
416 raw_ostream
&CStream
) const {
421 // Try decode a 16-bit instruction.
423 Result
= readInstruction16(Bytes
, Address
, Size
, Insn
);
425 if (Result
== MCDisassembler::Fail
)
426 return MCDisassembler::Fail
;
428 // Try to decode AVRTiny instructions.
429 if (STI
.getFeatureBits()[AVR::FeatureTinyEncoding
]) {
430 Result
= decodeInstruction(DecoderTableAVRTiny16
, Instr
, Insn
, Address
,
432 if (Result
!= MCDisassembler::Fail
)
436 // Try to auto-decode a 16-bit instruction.
437 Result
= decodeInstruction(getDecoderTable(Size
), Instr
, Insn
, Address
,
439 if (Result
!= MCDisassembler::Fail
)
442 // Try to decode to a load/store instruction. ST/LD need a specified
443 // DecoderMethod, as they already have a specified PostEncoderMethod.
444 Result
= decodeLoadStore(Instr
, Insn
, Address
, this);
445 if (Result
!= MCDisassembler::Fail
)
449 // Try decode a 32-bit instruction.
451 Result
= readInstruction32(Bytes
, Address
, Size
, Insn
);
453 if (Result
== MCDisassembler::Fail
)
454 return MCDisassembler::Fail
;
456 Result
= decodeInstruction(getDecoderTable(Size
), Instr
, Insn
, Address
,
459 if (Result
!= MCDisassembler::Fail
) {
463 return MCDisassembler::Fail
;
467 typedef DecodeStatus (*DecodeFunc
)(MCInst
&MI
, unsigned insn
, uint64_t Address
,
468 const MCDisassembler
*Decoder
);