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