1 //===- AVRDisassembler.cpp - Disassembler for AVR ---------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is part of the AVR Disassembler.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "AVR.h"
15 #include "AVRRegisterInfo.h"
16 #include "AVRSubtarget.h"
17 #include "MCTargetDesc/AVRMCTargetDesc.h"
18 
19 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
20 #include "llvm/MC/MCFixedLenDisassembler.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCContext.h"
23 #include "llvm/MC/MCAsmInfo.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 &VStream,
44                               raw_ostream &CStream) const override;
45 };
46 }
47 
48 namespace llvm {
49 extern Target TheAVRTarget;
50 }
51 
52 static MCDisassembler *createAVRDisassembler(const Target &T,
53                                              const MCSubtargetInfo &STI,
54                                              MCContext &Ctx) {
55   return new AVRDisassembler(STI, Ctx);
56 }
57 
58 
59 extern "C" void LLVMInitializeAVRDisassembler() {
60   // Register the disassembler.
61   TargetRegistry::RegisterMCDisassembler(TheAVRTarget,
62                                          createAVRDisassembler);
63 }
64 
65 static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,
66                                             uint64_t Address, const void *Decoder) {
67   return MCDisassembler::Success;
68 }
69 
70 static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,
71                                            uint64_t Address, const void *Decoder) {
72   return MCDisassembler::Success;
73 }
74 
75 static DecodeStatus DecodePTRREGSRegisterClass(MCInst &Inst, unsigned RegNo,
76                                                uint64_t Address, const void *Decoder) {
77   return MCDisassembler::Success;
78 }
79 
80 #include "AVRGenDisassemblerTables.inc"
81 
82 static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
83                                       uint64_t &Size, uint32_t &Insn) {
84   if (Bytes.size() < 2) {
85     Size = 0;
86     return MCDisassembler::Fail;
87   }
88 
89   Size = 2;
90   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
91 
92   return MCDisassembler::Success;
93 }
94 
95 static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
96                                       uint64_t &Size, uint32_t &Insn) {
97 
98   if (Bytes.size() < 4) {
99     Size = 0;
100     return MCDisassembler::Fail;
101   }
102 
103   Size = 4;
104   Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | (Bytes[3] << 24);
105 
106   return MCDisassembler::Success;
107 }
108 
109 static const uint8_t *getDecoderTable(uint64_t Size) {
110 
111   switch (Size) {
112     case 2: return DecoderTable16;
113     case 4: return DecoderTable32;
114     default: llvm_unreachable("instructions must be 16 or 32-bits");
115   }
116 }
117 
118 DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
119                                              ArrayRef<uint8_t> Bytes,
120                                              uint64_t Address,
121                                              raw_ostream &VStream,
122                                              raw_ostream &CStream) const {
123   uint32_t Insn;
124 
125   DecodeStatus Result;
126 
127   // Try decode a 16-bit instruction.
128   {
129     Result = readInstruction16(Bytes, Address, Size, Insn);
130 
131     if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
132 
133     // Try to auto-decode a 16-bit instruction.
134     Result = decodeInstruction(getDecoderTable(Size), Instr,
135                                Insn, Address, this, STI);
136 
137     if (Result != MCDisassembler::Fail)
138       return Result;
139   }
140 
141   // Try decode a 32-bit instruction.
142   {
143     Result = readInstruction32(Bytes, Address, Size, Insn);
144 
145     if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
146 
147     Result = decodeInstruction(getDecoderTable(Size), Instr, Insn,
148                                Address, this, STI);
149 
150     if (Result != MCDisassembler::Fail) {
151       return Result;
152     }
153 
154     return MCDisassembler::Fail;
155   }
156 }
157 
158 typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
159                                    const void *Decoder);
160 
161