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:
AVRDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)37 AVRDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
38 : MCDisassembler(STI, Ctx) {}
~AVRDisassembler()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
createAVRDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)47 static MCDisassembler *createAVRDisassembler(const Target &T,
48 const MCSubtargetInfo &STI,
49 MCContext &Ctx) {
50 return new AVRDisassembler(STI, Ctx);
51 }
52
53
LLVMInitializeAVRDisassembler()54 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRDisassembler() {
55 // Register the disassembler.
56 TargetRegistry::RegisterMCDisassembler(getTheAVRTarget(),
57 createAVRDisassembler);
58 }
59
DecodeGPR8RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)60 static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,
61 uint64_t Address, const void *Decoder) {
62 return MCDisassembler::Success;
63 }
64
DecodeLD8RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)65 static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,
66 uint64_t Address, const void *Decoder) {
67 return MCDisassembler::Success;
68 }
69
DecodePTRREGSRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)70 static DecodeStatus DecodePTRREGSRegisterClass(MCInst &Inst, unsigned RegNo,
71 uint64_t Address, const void *Decoder) {
72 return MCDisassembler::Success;
73 }
74
75 #include "AVRGenDisassemblerTables.inc"
76
readInstruction16(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)77 static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
78 uint64_t &Size, uint32_t &Insn) {
79 if (Bytes.size() < 2) {
80 Size = 0;
81 return MCDisassembler::Fail;
82 }
83
84 Size = 2;
85 Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
86
87 return MCDisassembler::Success;
88 }
89
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)90 static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
91 uint64_t &Size, uint32_t &Insn) {
92
93 if (Bytes.size() < 4) {
94 Size = 0;
95 return MCDisassembler::Fail;
96 }
97
98 Size = 4;
99 Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | (Bytes[3] << 24);
100
101 return MCDisassembler::Success;
102 }
103
getDecoderTable(uint64_t Size)104 static const uint8_t *getDecoderTable(uint64_t Size) {
105
106 switch (Size) {
107 case 2: return DecoderTable16;
108 case 4: return DecoderTable32;
109 default: llvm_unreachable("instructions must be 16 or 32-bits");
110 }
111 }
112
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CStream) const113 DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
114 ArrayRef<uint8_t> Bytes,
115 uint64_t Address,
116 raw_ostream &CStream) const {
117 uint32_t Insn;
118
119 DecodeStatus Result;
120
121 // Try decode a 16-bit instruction.
122 {
123 Result = readInstruction16(Bytes, Address, Size, Insn);
124
125 if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
126
127 // Try to auto-decode a 16-bit instruction.
128 Result = decodeInstruction(getDecoderTable(Size), Instr,
129 Insn, Address, this, STI);
130
131 if (Result != MCDisassembler::Fail)
132 return Result;
133 }
134
135 // Try decode a 32-bit instruction.
136 {
137 Result = readInstruction32(Bytes, Address, Size, Insn);
138
139 if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
140
141 Result = decodeInstruction(getDecoderTable(Size), Instr, Insn,
142 Address, this, STI);
143
144 if (Result != MCDisassembler::Fail) {
145 return Result;
146 }
147
148 return MCDisassembler::Fail;
149 }
150 }
151
152 typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
153 const void *Decoder);
154
155