blob: b49658004f7ad8e19aebc57f63f9a5b258288a68 [file] [log] [blame]
Pete Couperus2d1f6d62017-08-24 15:40:33 +00001//===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- 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/// \file
11/// \brief This file is part of the ARC Disassembler.
12///
13//===----------------------------------------------------------------------===//
14
15#include "ARC.h"
16#include "ARCRegisterInfo.h"
17#include "MCTargetDesc/ARCMCTargetDesc.h"
18#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCDisassembler/MCDisassembler.h"
20#include "llvm/MC/MCFixedLenDisassembler.h"
21#include "llvm/MC/MCInst.h"
22#include "llvm/MC/MCInstrInfo.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/Support/TargetRegistry.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "arc-disassembler"
29
30using DecodeStatus = MCDisassembler::DecodeStatus;
31
32namespace {
33
34/// \brief A disassembler class for ARC.
35class ARCDisassembler : public MCDisassembler {
36public:
37 std::unique_ptr<MCInstrInfo const> const MCII;
38
39 ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
40 MCInstrInfo const *MCII)
41 : MCDisassembler(STI, Ctx), MCII(MCII) {}
42
43 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
44 ArrayRef<uint8_t> Bytes, uint64_t Address,
45 raw_ostream &VStream,
46 raw_ostream &CStream) const override;
47};
48
49} // end anonymous namespace
50
51static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
52 uint64_t &Size, uint32_t &Insn) {
53 Size = 4;
54 // Read 2 16-bit values, but swap hi/lo parts.
55 Insn =
56 (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
57 return true;
58}
59
60static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
61 uint64_t &Size, uint64_t &Insn) {
62 Size = 8;
63 Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
64 ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
65 ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
66 ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
67 return true;
68}
69
70static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
71 uint64_t &Size, uint32_t &Insn) {
72 Size = 2;
73 Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
74 return true;
75}
76
77static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &, unsigned,
78 uint64_t, const void *);
79
80static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &, unsigned,
81 uint64_t, const void *);
82
83static MCDisassembler::DecodeStatus
84DecodeBranchTargetS9(MCInst &, unsigned, uint64_t, const void *);
85
86static MCDisassembler::DecodeStatus
87DecodeBranchTargetS21(MCInst &, unsigned, uint64_t, const void *);
88
89static MCDisassembler::DecodeStatus
90DecodeBranchTargetS25(MCInst &, unsigned, uint64_t, const void *);
91
92static MCDisassembler::DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
93 const void *);
94
95static MCDisassembler::DecodeStatus
96DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
97
98static MCDisassembler::DecodeStatus
99DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
100
101static MCDisassembler::DecodeStatus
102DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
103
104static const uint16_t GPR32DecoderTable[] = {
105 ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
106 ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13,
107 ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20,
108 ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP,
109 ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK};
110
111static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
112 uint64_t Address,
113 const void *Decoder) {
114 if (RegNo >= 32) {
115 DEBUG(dbgs() << "Not a GPR32 register.");
116 return MCDisassembler::Fail;
117 }
118 unsigned Reg = GPR32DecoderTable[RegNo];
119 Inst.addOperand(MCOperand::createReg(Reg));
120 return MCDisassembler::Success;
121}
122
123#include "ARCGenDisassemblerTables.inc"
124
125static unsigned decodeCField(unsigned Insn) {
126 return fieldFromInstruction(Insn, 6, 6);
127}
128
129static unsigned decodeBField(unsigned Insn) {
130 return (fieldFromInstruction(Insn, 12, 3) << 3) |
131 fieldFromInstruction(Insn, 24, 3);
132}
133
134static unsigned decodeAField(unsigned Insn) {
135 return fieldFromInstruction(Insn, 0, 6);
136}
137
138static MCDisassembler::DecodeStatus
139DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Dec) {
140 // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
141 unsigned S9 = Insn & 0x1ff;
142 unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
143 DecodeGPR32RegisterClass(Inst, R, Address, Dec);
144 Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
145 return MCDisassembler::Success;
146}
147
148static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &Inst,
149 unsigned InsnS9,
150 uint64_t Address,
151 const void *Decoder) {
152 Inst.addOperand(MCOperand::createImm(SignExtend32<9>(0x1ff & InsnS9)));
153 return MCDisassembler::Success;
154}
155
156static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &Inst,
157 unsigned InsnS12,
158 uint64_t Address,
159 const void *Decoder) {
160 Inst.addOperand(MCOperand::createImm(SignExtend32<12>(0xfff & InsnS12)));
161 return MCDisassembler::Success;
162}
163
164static MCDisassembler::DecodeStatus DecodeBranchTargetS9(MCInst &Inst,
165 unsigned S,
166 uint64_t Address,
167 const void *Decoder) {
168 Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S)));
169 return MCDisassembler::Success;
170}
171
172static MCDisassembler::DecodeStatus DecodeBranchTargetS21(MCInst &Inst,
173 unsigned S,
174 uint64_t Address,
175 const void *Decoder) {
176 Inst.addOperand(MCOperand::createImm(SignExtend32<21>(S)));
177 return MCDisassembler::Success;
178}
179
180static MCDisassembler::DecodeStatus DecodeBranchTargetS25(MCInst &Inst,
181 unsigned S,
182 uint64_t Address,
183 const void *Decoder) {
184 Inst.addOperand(MCOperand::createImm(SignExtend32<25>(S)));
185 return MCDisassembler::Success;
186}
187
188static MCDisassembler::DecodeStatus
189DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
190 const void *Decoder) {
191 unsigned SrcC, DstB, LImm;
192 DstB = decodeBField(Insn);
193 if (DstB != 62) {
194 DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
195 return MCDisassembler::Fail;
196 }
197 SrcC = decodeCField(Insn);
198 DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
199 LImm = (Insn >> 32);
200 Inst.addOperand(MCOperand::createImm(LImm));
201 Inst.addOperand(MCOperand::createImm(0));
202 return MCDisassembler::Success;
203}
204
205static MCDisassembler::DecodeStatus
206DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
207 const void *Decoder) {
208 unsigned DstA, SrcB, LImm;
209 DEBUG(dbgs() << "Decoding LdLImm:\n");
210 SrcB = decodeBField(Insn);
211 if (SrcB != 62) {
212 DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
213 return MCDisassembler::Fail;
214 }
215 DstA = decodeAField(Insn);
216 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
217 LImm = (Insn >> 32);
218 Inst.addOperand(MCOperand::createImm(LImm));
219 Inst.addOperand(MCOperand::createImm(0));
220 return MCDisassembler::Success;
221}
222
223static MCDisassembler::DecodeStatus
224DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
225 const void *Decoder) {
226 unsigned DstA, SrcB;
227 DEBUG(dbgs() << "Decoding LdRLimm\n");
228 DstA = decodeAField(Insn);
229 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
230 SrcB = decodeBField(Insn);
231 DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
232 if (decodeCField(Insn) != 62) {
233 DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
234 return MCDisassembler::Fail;
235 }
236 Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
237 return MCDisassembler::Success;
238}
239
240MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
241 MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
242 raw_ostream &vStream, raw_ostream &cStream) const {
243 MCDisassembler::DecodeStatus Result;
244 if (Bytes.size() < 2) {
245 Size = 0;
246 return Fail;
247 }
248 uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
249 // 0x00 -> 0x07 are 32-bit instructions.
250 // 0x08 -> 0x1F are 16-bit instructions.
251 if (DecodeByte < 0x08) {
252 // 32-bit instruction.
253 if (Bytes.size() < 4) {
254 // Did we decode garbage?
255 Size = 0;
256 return Fail;
257 }
258 if (Bytes.size() >= 8) {
259 // Attempt to decode 64-bit instruction.
260 uint64_t Insn64;
261 if (!readInstruction64(Bytes, Address, Size, Insn64))
262 return Fail;
263 Result =
264 decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
265 if (Result == MCDisassembler::Success) {
266 DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
267 return MCDisassembler::Success;
268 }
269 DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
270 }
271 uint32_t Insn32;
272 if (!readInstruction32(Bytes, Address, Size, Insn32)) {
273 return Fail;
274 }
275 // Calling the auto-generated decoder function.
276 return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
277 }
278
279 // 16-bit instruction.
280 uint32_t Insn16;
281 if (!readInstruction16(Bytes, Address, Size, Insn16)) {
282 return Fail;
283 }
284 // Calling the auto-generated decoder function.
285 return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
286}
287
288static MCDisassembler *createARCDisassembler(const Target &T,
289 const MCSubtargetInfo &STI,
290 MCContext &Ctx) {
291 return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
292}
293
294extern "C" void LLVMInitializeARCDisassembler() {
295 // Register the disassembler.
296 TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
297 createARCDisassembler);
298}