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