xref: /llvm-project/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp (revision ed8019d9fbed2e6a6b08f8f73e9fa54a24f3ed52)
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 "MCTargetDesc/AVRMCTargetDesc.h"
14 #include "TargetInfo/AVRTargetInfo.h"
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"
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 decodeCondBranch(MCInst &Inst, unsigned Insn,
130                                      uint64_t Address,
131                                      const MCDisassembler *Decoder);
132 
133 static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
134                                     uint64_t Address,
135                                     const MCDisassembler *Decoder);
136 
137 #include "AVRGenDisassemblerTables.inc"
138 
139 static 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);
145   Inst.addOperand(MCOperand::createImm(addr));
146   if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
147       MCDisassembler::Fail)
148     return MCDisassembler::Fail;
149   return MCDisassembler::Success;
150 }
151 
152 static 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) ==
159       MCDisassembler::Fail)
160     return MCDisassembler::Fail;
161   Inst.addOperand(MCOperand::createImm(addr));
162   return MCDisassembler::Success;
163 }
164 
165 static 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);
169   Inst.addOperand(MCOperand::createImm(addr));
170   Inst.addOperand(MCOperand::createImm(b));
171   return MCDisassembler::Success;
172 }
173 
174 static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field,
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.
179   Inst.addOperand(MCOperand::createImm(Field << 1));
180   return MCDisassembler::Success;
181 }
182 
183 static 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) ==
187       MCDisassembler::Fail)
188     return MCDisassembler::Fail;
189   return MCDisassembler::Success;
190 }
191 
192 static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
193                                 const MCDisassembler *Decoder) {
194   if (decodeFRd(Inst, Insn, Address, Decoder) == MCDisassembler::Fail)
195     return MCDisassembler::Fail;
196   Inst.addOperand(MCOperand::createReg(AVR::R31R30));
197   return MCDisassembler::Success;
198 }
199 
200 static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
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) ==
206       MCDisassembler::Fail)
207     return MCDisassembler::Fail;
208   if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
209       MCDisassembler::Fail)
210     return MCDisassembler::Fail;
211   return MCDisassembler::Success;
212 }
213 
214 static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
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) ==
220       MCDisassembler::Fail)
221     return MCDisassembler::Fail;
222   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
223       MCDisassembler::Fail)
224     return MCDisassembler::Fail;
225   return MCDisassembler::Success;
226 }
227 
228 static 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) ==
235       MCDisassembler::Fail)
236     return MCDisassembler::Fail;
237   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
238       MCDisassembler::Fail)
239     return MCDisassembler::Fail;
240   Inst.addOperand(MCOperand::createImm(k));
241   return MCDisassembler::Success;
242 }
243 
244 static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
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) ==
250       MCDisassembler::Fail)
251     return MCDisassembler::Fail;
252   if (DecodeGPR8RegisterClass(Inst, rr, Address, Decoder) ==
253       MCDisassembler::Fail)
254     return MCDisassembler::Fail;
255   return MCDisassembler::Success;
256 }
257 
258 static 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)
264     return MCDisassembler::Fail;
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.
270   Inst.addOperand(MCOperand::createImm(Insn & 0x3f));
271 
272   return MCDisassembler::Success;
273 }
274 
275 static 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.
286     return MCDisassembler::Fail;
287   }
288   // Decode the relative offset.
289   int16_t Offset = ((int16_t)((Insn & 0xfff) << 4)) >> 3;
290   Inst.addOperand(MCOperand::createImm(Offset));
291   return MCDisassembler::Success;
292 }
293 
294 static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
295                                      uint64_t Address,
296                                      const MCDisassembler *Decoder) {
297   // These 8 instructions are not defined as aliases of BRBS/BRBC.
298   DenseMap<unsigned, unsigned> brInsts = {
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);
317     Inst.addOperand(MCOperand::createImm(Offset));
318   } else {
319     // Fall back to an ordinary BRBS/BRBC.
320     Inst.setOpcode(Insn & 0x400 ? AVR::BRBCsk : AVR::BRBSsk);
321     Inst.addOperand(MCOperand::createImm(Insn & 7));
322     Inst.addOperand(MCOperand::createImm(Offset));
323   }
324 
325   return MCDisassembler::Success;
326 }
327 
328 static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
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));
342       Inst.addOperand(MCOperand::createImm(Offset));
343     } else { // Decode STD.
344       Inst.setOpcode(AVR::STDPtrQRr);
345       Inst.addOperand(MCOperand::createReg(RegBase));
346       Inst.addOperand(MCOperand::createImm(Offset));
347       Inst.addOperand(MCOperand::createReg(RegVal));
348     }
349     return MCDisassembler::Success;
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)
371     return MCDisassembler::Fail;
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:
386     return MCDisassembler::Fail;
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));
395     return MCDisassembler::Success;
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));
406     return MCDisassembler::Success;
407   case 1:
408     Inst.setOpcode(AVR::LDRdPtrPi);
409     break;
410   case 2:
411     Inst.setOpcode(AVR::LDRdPtrPd);
412     break;
413   default:
414     return MCDisassembler::Fail;
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.
427     Inst.addOperand(MCOperand::createImm(1));
428   }
429 
430   return MCDisassembler::Success;
431 }
432 
433 static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
434                                       uint64_t &Size, uint32_t &Insn) {
435   if (Bytes.size() < 2) {
436     Size = 0;
437     return MCDisassembler::Fail;
438   }
439 
440   Size = 2;
441   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
442 
443   return MCDisassembler::Success;
444 }
445 
446 static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
447                                       uint64_t &Size, uint32_t &Insn) {
448 
449   if (Bytes.size() < 4) {
450     Size = 0;
451     return MCDisassembler::Fail;
452   }
453 
454   Size = 4;
455   Insn =
456       (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
457 
458   return MCDisassembler::Success;
459 }
460 
461 static const uint8_t *getDecoderTable(uint64_t Size) {
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 
473 DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
474                                              ArrayRef<uint8_t> Bytes,
475                                              uint64_t Address,
476                                              raw_ostream &CStream) const {
477   uint32_t Insn;
478 
479   DecodeStatus Result;
480 
481   // Try decode a 16-bit instruction.
482   {
483     Result = readInstruction16(Bytes, Address, Size, Insn);
484 
485     if (Result == MCDisassembler::Fail)
486       return 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)
514       return 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 
523     return MCDisassembler::Fail;
524   }
525 }
526 
527 typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
528                                    const MCDisassembler *Decoder);
529