xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp (revision c66a499e037efd268a744e487e7d0c45a4944a9b)
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/MCDecoderOps.h"
22 #include "llvm/MC/MCDisassembler/MCDisassembler.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 decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
90                                  const MCDisassembler *Decoder);
91 
92 static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,
93                                  const MCDisassembler *Decoder);
94 
95 static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,
96                                  const MCDisassembler *Decoder);
97 
98 static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Insn,
99                                      uint64_t Address,
100                                      const MCDisassembler *Decoder);
101 
102 static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,
103                               const MCDisassembler *Decoder);
104 
105 static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
106                                 const MCDisassembler *Decoder);
107 
108 static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
109                                     uint64_t Address,
110                                     const MCDisassembler *Decoder);
111 
112 static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
113                                     uint64_t Address,
114                                     const MCDisassembler *Decoder);
115 
116 static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,
117                                 const MCDisassembler *Decoder);
118 
119 static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
120                                     uint64_t Address,
121                                     const MCDisassembler *Decoder);
122 
123 static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
124                                 const MCDisassembler *Decoder);
125 
126 static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,
127                                const MCDisassembler *Decoder);
128 
129 static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
130                                     uint64_t Address,
131                                     const MCDisassembler *Decoder);
132 
133 #include "AVRGenDisassemblerTables.inc"
134 
135 static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
136                                  const MCDisassembler *Decoder) {
137   unsigned addr = 0;
138   addr |= fieldFromInstruction(Insn, 0, 4);
139   addr |= fieldFromInstruction(Insn, 9, 2) << 4;
140   unsigned reg = fieldFromInstruction(Insn, 4, 5);
141   Inst.addOperand(MCOperand::createImm(addr));
142   if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
143       MCDisassembler::Fail)
144     return MCDisassembler::Fail;
145   return MCDisassembler::Success;
146 }
147 
148 static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,
149                                  const MCDisassembler *Decoder) {
150   unsigned addr = 0;
151   addr |= fieldFromInstruction(Insn, 0, 4);
152   addr |= fieldFromInstruction(Insn, 9, 2) << 4;
153   unsigned reg = fieldFromInstruction(Insn, 4, 5);
154   if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
155       MCDisassembler::Fail)
156     return MCDisassembler::Fail;
157   Inst.addOperand(MCOperand::createImm(addr));
158   return MCDisassembler::Success;
159 }
160 
161 static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,
162                                  const MCDisassembler *Decoder) {
163   unsigned addr = fieldFromInstruction(Insn, 3, 5);
164   unsigned b = fieldFromInstruction(Insn, 0, 3);
165   Inst.addOperand(MCOperand::createImm(addr));
166   Inst.addOperand(MCOperand::createImm(b));
167   return MCDisassembler::Success;
168 }
169 
170 static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field,
171                                      uint64_t Address,
172                                      const MCDisassembler *Decoder) {
173   // Call targets need to be shifted left by one so this needs a custom
174   // decoder.
175   Inst.addOperand(MCOperand::createImm(Field << 1));
176   return MCDisassembler::Success;
177 }
178 
179 static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,
180                               const MCDisassembler *Decoder) {
181   unsigned d = fieldFromInstruction(Insn, 4, 5);
182   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
183       MCDisassembler::Fail)
184     return MCDisassembler::Fail;
185   return MCDisassembler::Success;
186 }
187 
188 static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
189                                 const MCDisassembler *Decoder) {
190   if (decodeFRd(Inst, Insn, Address, Decoder) == MCDisassembler::Fail)
191     return MCDisassembler::Fail;
192   Inst.addOperand(MCOperand::createReg(AVR::R31R30));
193   return MCDisassembler::Success;
194 }
195 
196 static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
197                                     uint64_t Address,
198                                     const MCDisassembler *Decoder) {
199   unsigned d = fieldFromInstruction(Insn, 4, 3) + 16;
200   unsigned r = fieldFromInstruction(Insn, 0, 3) + 16;
201   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
202       MCDisassembler::Fail)
203     return MCDisassembler::Fail;
204   if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
205       MCDisassembler::Fail)
206     return MCDisassembler::Fail;
207   return MCDisassembler::Success;
208 }
209 
210 static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
211                                     uint64_t Address,
212                                     const MCDisassembler *Decoder) {
213   unsigned r = fieldFromInstruction(Insn, 4, 4) * 2;
214   unsigned d = fieldFromInstruction(Insn, 0, 4) * 2;
215   if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
216       MCDisassembler::Fail)
217     return MCDisassembler::Fail;
218   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
219       MCDisassembler::Fail)
220     return MCDisassembler::Fail;
221   return MCDisassembler::Success;
222 }
223 
224 static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,
225                                 const MCDisassembler *Decoder) {
226   unsigned d = fieldFromInstruction(Insn, 4, 2) * 2 + 24; // starts at r24:r25
227   unsigned k = 0;
228   k |= fieldFromInstruction(Insn, 0, 4);
229   k |= fieldFromInstruction(Insn, 6, 2) << 4;
230   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
231       MCDisassembler::Fail)
232     return MCDisassembler::Fail;
233   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
234       MCDisassembler::Fail)
235     return MCDisassembler::Fail;
236   Inst.addOperand(MCOperand::createImm(k));
237   return MCDisassembler::Success;
238 }
239 
240 static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
241                                     uint64_t Address,
242                                     const MCDisassembler *Decoder) {
243   unsigned rd = fieldFromInstruction(Insn, 4, 4) + 16;
244   unsigned rr = fieldFromInstruction(Insn, 0, 4) + 16;
245   if (DecodeGPR8RegisterClass(Inst, rd, Address, Decoder) ==
246       MCDisassembler::Fail)
247     return MCDisassembler::Fail;
248   if (DecodeGPR8RegisterClass(Inst, rr, Address, Decoder) ==
249       MCDisassembler::Fail)
250     return MCDisassembler::Fail;
251   return MCDisassembler::Success;
252 }
253 
254 static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
255                                 const MCDisassembler *Decoder) {
256   // As in the EncoderMethod `AVRMCCodeEmitter::encodeMemri`, the memory
257   // address is encoded into 7-bit, in which bits 0-5 are the immediate offset,
258   // and the bit-6 is the pointer register bit (Z=0, Y=1).
259   if (Insn > 127)
260     return MCDisassembler::Fail;
261 
262   // Append the base register operand.
263   Inst.addOperand(
264       MCOperand::createReg((Insn & 0x40) ? AVR::R29R28 : AVR::R31R30));
265   // Append the immediate offset operand.
266   Inst.addOperand(MCOperand::createImm(Insn & 0x3f));
267 
268   return MCDisassembler::Success;
269 }
270 
271 static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,
272                                const MCDisassembler *Decoder) {
273   // Decode the opcode.
274   switch (Insn & 0xf000) {
275   case 0xc000:
276     Inst.setOpcode(AVR::RJMPk);
277     break;
278   case 0xd000:
279     Inst.setOpcode(AVR::RCALLk);
280     break;
281   default: // Unknown relative branch instruction.
282     return MCDisassembler::Fail;
283   }
284   // Decode the relative offset.
285   int16_t Offset = ((int16_t)((Insn & 0xfff) << 4)) >> 3;
286   Inst.addOperand(MCOperand::createImm(Offset));
287   return MCDisassembler::Success;
288 }
289 
290 static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
291                                     uint64_t Address,
292                                     const MCDisassembler *Decoder) {
293   // Get the register will be loaded or stored.
294   unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
295 
296   // Decode LDD/STD with offset less than 8.
297   if ((Insn & 0xf000) == 0x8000) {
298     unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30;
299     unsigned Offset = Insn & 7; // We need not consider offset > 7.
300     if ((Insn & 0x200) == 0) {  // Decode LDD.
301       Inst.setOpcode(AVR::LDDRdPtrQ);
302       Inst.addOperand(MCOperand::createReg(RegVal));
303       Inst.addOperand(MCOperand::createReg(RegBase));
304       Inst.addOperand(MCOperand::createImm(Offset));
305     } else { // Decode STD.
306       Inst.setOpcode(AVR::STDPtrQRr);
307       Inst.addOperand(MCOperand::createReg(RegBase));
308       Inst.addOperand(MCOperand::createImm(Offset));
309       Inst.addOperand(MCOperand::createReg(RegVal));
310     }
311     return MCDisassembler::Success;
312   }
313 
314   // Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),
315   // bits 8~4 indicate the value register, bits 3-2 indicate the base address
316   // register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,
317   // 01-postinc, 10-predec).
318   // ST X,  Rr : 1001 001r rrrr 1100
319   // ST X+, Rr : 1001 001r rrrr 1101
320   // ST -X, Rr : 1001 001r rrrr 1110
321   // ST Y+, Rr : 1001 001r rrrr 1001
322   // ST -Y, Rr : 1001 001r rrrr 1010
323   // ST Z+, Rr : 1001 001r rrrr 0001
324   // ST -Z, Rr : 1001 001r rrrr 0010
325   // LD Rd, X  : 1001 000d dddd 1100
326   // LD Rd, X+ : 1001 000d dddd 1101
327   // LD Rd, -X : 1001 000d dddd 1110
328   // LD Rd, Y+ : 1001 000d dddd 1001
329   // LD Rd, -Y : 1001 000d dddd 1010
330   // LD Rd, Z+ : 1001 000d dddd 0001
331   // LD Rd, -Z : 1001 000d dddd 0010
332   if ((Insn & 0xfc00) != 0x9000 || (Insn & 0xf) == 0)
333     return MCDisassembler::Fail;
334 
335   // Get the base address register.
336   unsigned RegBase;
337   switch (Insn & 0xc) {
338   case 0xc:
339     RegBase = AVR::R27R26;
340     break;
341   case 0x8:
342     RegBase = AVR::R29R28;
343     break;
344   case 0x0:
345     RegBase = AVR::R31R30;
346     break;
347   default:
348     return MCDisassembler::Fail;
349   }
350 
351   // Set the opcode.
352   switch (Insn & 0x203) {
353   case 0x200:
354     Inst.setOpcode(AVR::STPtrRr);
355     Inst.addOperand(MCOperand::createReg(RegBase));
356     Inst.addOperand(MCOperand::createReg(RegVal));
357     return MCDisassembler::Success;
358   case 0x201:
359     Inst.setOpcode(AVR::STPtrPiRr);
360     break;
361   case 0x202:
362     Inst.setOpcode(AVR::STPtrPdRr);
363     break;
364   case 0:
365     Inst.setOpcode(AVR::LDRdPtr);
366     Inst.addOperand(MCOperand::createReg(RegVal));
367     Inst.addOperand(MCOperand::createReg(RegBase));
368     return MCDisassembler::Success;
369   case 1:
370     Inst.setOpcode(AVR::LDRdPtrPi);
371     break;
372   case 2:
373     Inst.setOpcode(AVR::LDRdPtrPd);
374     break;
375   default:
376     return MCDisassembler::Fail;
377   }
378 
379   // Build postinc/predec machine instructions.
380   if ((Insn & 0x200) == 0) { // This is a load instruction.
381     Inst.addOperand(MCOperand::createReg(RegVal));
382     Inst.addOperand(MCOperand::createReg(RegBase));
383     Inst.addOperand(MCOperand::createReg(RegBase));
384   } else { // This is a store instruction.
385     Inst.addOperand(MCOperand::createReg(RegBase));
386     Inst.addOperand(MCOperand::createReg(RegBase));
387     Inst.addOperand(MCOperand::createReg(RegVal));
388     // STPtrPiRr and STPtrPdRr have an extra immediate operand.
389     Inst.addOperand(MCOperand::createImm(1));
390   }
391 
392   return MCDisassembler::Success;
393 }
394 
395 static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
396                                       uint64_t &Size, uint32_t &Insn) {
397   if (Bytes.size() < 2) {
398     Size = 0;
399     return MCDisassembler::Fail;
400   }
401 
402   Size = 2;
403   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
404 
405   return MCDisassembler::Success;
406 }
407 
408 static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
409                                       uint64_t &Size, uint32_t &Insn) {
410 
411   if (Bytes.size() < 4) {
412     Size = 0;
413     return MCDisassembler::Fail;
414   }
415 
416   Size = 4;
417   Insn =
418       (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
419 
420   return MCDisassembler::Success;
421 }
422 
423 static const uint8_t *getDecoderTable(uint64_t Size) {
424 
425   switch (Size) {
426   case 2:
427     return DecoderTable16;
428   case 4:
429     return DecoderTable32;
430   default:
431     llvm_unreachable("instructions must be 16 or 32-bits");
432   }
433 }
434 
435 DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
436                                              ArrayRef<uint8_t> Bytes,
437                                              uint64_t Address,
438                                              raw_ostream &CStream) const {
439   uint32_t Insn;
440 
441   DecodeStatus Result;
442 
443   // Try decode a 16-bit instruction.
444   {
445     Result = readInstruction16(Bytes, Address, Size, Insn);
446 
447     if (Result == MCDisassembler::Fail)
448       return MCDisassembler::Fail;
449 
450     // Try to decode AVRTiny instructions.
451     if (STI.getFeatureBits()[AVR::FeatureTinyEncoding]) {
452       Result = decodeInstruction(DecoderTableAVRTiny16, Instr, Insn, Address,
453                                  this, STI);
454       if (Result != MCDisassembler::Fail)
455         return Result;
456     }
457 
458     // Try to auto-decode a 16-bit instruction.
459     Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
460                                this, STI);
461     if (Result != MCDisassembler::Fail)
462       return Result;
463 
464     // Try to decode to a load/store instruction. ST/LD need a specified
465     // DecoderMethod, as they already have a specified PostEncoderMethod.
466     Result = decodeLoadStore(Instr, Insn, Address, this);
467     if (Result != MCDisassembler::Fail)
468       return Result;
469   }
470 
471   // Try decode a 32-bit instruction.
472   {
473     Result = readInstruction32(Bytes, Address, Size, Insn);
474 
475     if (Result == MCDisassembler::Fail)
476       return MCDisassembler::Fail;
477 
478     Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
479                                this, STI);
480 
481     if (Result != MCDisassembler::Fail) {
482       return Result;
483     }
484 
485     return MCDisassembler::Fail;
486   }
487 }
488 
489 typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
490                                    const MCDisassembler *Decoder);
491