blob: 3fc5a033dd5d74a7bae9020e9afa79b3125bc9e2 [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
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000011/// This file is part of the ARC Disassembler.
Pete Couperus2d1f6d62017-08-24 15:40:33 +000012///
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
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000034/// A disassembler class for ARC.
Pete Couperus2d1f6d62017-08-24 15:40:33 +000035class 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
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +000070static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
71 uint64_t &Size, uint64_t &Insn) {
72 Size = 6;
73 Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
74 ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
75 ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
76 return true;
77}
78
Pete Couperus2d1f6d62017-08-24 15:40:33 +000079static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
80 uint64_t &Size, uint32_t &Insn) {
81 Size = 2;
82 Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
83 return true;
84}
85
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +000086template <unsigned B>
87static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
88 uint64_t Address = 0,
89 const void *Decoder = nullptr);
Pete Couperus2d1f6d62017-08-24 15:40:33 +000090
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +000091template <unsigned B>
92static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
93 uint64_t Address = 0,
94 const void *Decoder = nullptr);
Pete Couperus2d1f6d62017-08-24 15:40:33 +000095
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +000096template <unsigned B>
97static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
98 uint64_t Address, const void *Decoder);
Pete Couperus2d1f6d62017-08-24 15:40:33 +000099
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000100static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000101
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000102static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
103 const void *);
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000104
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000105static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
106 const void *);
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000107
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000108static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
109 const void *);
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000110
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000111static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
112 const void *);
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000113
114static const uint16_t GPR32DecoderTable[] = {
115 ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
116 ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13,
117 ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20,
118 ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP,
119 ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK};
120
121static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
122 uint64_t Address,
123 const void *Decoder) {
124 if (RegNo >= 32) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000125 LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000126 return MCDisassembler::Fail;
127 }
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000128
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000129 unsigned Reg = GPR32DecoderTable[RegNo];
130 Inst.addOperand(MCOperand::createReg(Reg));
131 return MCDisassembler::Success;
132}
133
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000134static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
135 uint64_t Address,
136 const void *Decoder) {
137 // Enumerates registers from ranges [r0-r3],[r12-r15].
138 if (RegNo > 3)
139 RegNo += 8; // 4 for r12, etc...
140
141 return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
142}
143
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000144#include "ARCGenDisassemblerTables.inc"
145
146static unsigned decodeCField(unsigned Insn) {
147 return fieldFromInstruction(Insn, 6, 6);
148}
149
150static unsigned decodeBField(unsigned Insn) {
151 return (fieldFromInstruction(Insn, 12, 3) << 3) |
152 fieldFromInstruction(Insn, 24, 3);
153}
154
155static unsigned decodeAField(unsigned Insn) {
156 return fieldFromInstruction(Insn, 0, 6);
157}
158
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000159static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
160 const void *Dec) {
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000161 // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
162 unsigned S9 = Insn & 0x1ff;
163 unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
164 DecodeGPR32RegisterClass(Inst, R, Address, Dec);
165 Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
166 return MCDisassembler::Success;
167}
168
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000169static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
170 uint64_t Value, const void *Decoder) {
171 static const uint64_t atLeast = 2;
172 // TODO: Try to force emitter to use MCDisassembler* instead of void*.
173 auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
174 return (nullptr != Disassembler &&
175 Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
176 atLeast));
177}
178
179static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
180 uint64_t Offset, const void *Decoder) {
181 uint64_t nextAddress = Address + Offset;
182
183 if (!DecodeSymbolicOperand(Inst, Address, nextAddress, Decoder))
184 Inst.addOperand(MCOperand::createImm(Offset));
185}
186
187template <unsigned B>
188static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
189 uint64_t Address, const void *Decoder) {
190
191 static_assert(B > 0, "field is empty");
192 DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000193 return MCDisassembler::Success;
194}
195
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000196template <unsigned B>
197static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
198 uint64_t /*Address*/,
199 const void * /*Decoder*/) {
200
201 static_assert(B > 0, "field is empty");
202 Inst.addOperand(MCOperand::createImm(
203 SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000204 return MCDisassembler::Success;
205}
206
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000207template <unsigned B>
208static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
209 uint64_t /*Address*/,
210 const void * /*Decoder*/) {
211
212 static_assert(B > 0, "field is empty");
213 const unsigned max = (1u << B) - 1;
214 Inst.addOperand(
215 MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000216 return MCDisassembler::Success;
217}
218
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000219static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
220 uint64_t Address,
221 const void *Decoder) {
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000222 unsigned SrcC, DstB, LImm;
223 DstB = decodeBField(Insn);
224 if (DstB != 62) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000225 LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000226 return MCDisassembler::Fail;
227 }
228 SrcC = decodeCField(Insn);
229 DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
230 LImm = (Insn >> 32);
231 Inst.addOperand(MCOperand::createImm(LImm));
232 Inst.addOperand(MCOperand::createImm(0));
233 return MCDisassembler::Success;
234}
235
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000236static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
237 uint64_t Address,
238 const void *Decoder) {
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000239 unsigned DstA, SrcB, LImm;
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000240 LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000241 SrcB = decodeBField(Insn);
242 if (SrcB != 62) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000243 LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000244 return MCDisassembler::Fail;
245 }
246 DstA = decodeAField(Insn);
247 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
248 LImm = (Insn >> 32);
249 Inst.addOperand(MCOperand::createImm(LImm));
250 Inst.addOperand(MCOperand::createImm(0));
251 return MCDisassembler::Success;
252}
253
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000254static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
255 uint64_t Address,
256 const void *Decoder) {
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000257 unsigned DstA, SrcB;
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000258 LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000259 DstA = decodeAField(Insn);
260 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
261 SrcB = decodeBField(Insn);
262 DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
263 if (decodeCField(Insn) != 62) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000264 LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000265 return MCDisassembler::Fail;
266 }
267 Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
268 return MCDisassembler::Success;
269}
270
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000271static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
272 uint64_t Address,
273 const void *Decoder) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000274 LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000275 using Field = decltype(Insn);
Dimitry Andricca5b0f32017-12-18 18:45:37 +0000276 Field h = fieldFromInstruction(Insn, 5, 3) |
277 (fieldFromInstruction(Insn, 0, 2) << 3);
278 Field g = fieldFromInstruction(Insn, 8, 3) |
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000279 (fieldFromInstruction(Insn, 3, 2) << 3);
280
281 auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
282 Field Value) {
283 if (30 == RegNum) {
284 Inst.addOperand(MCOperand::createImm(Value));
285 return MCDisassembler::Success;
286 }
287
288 return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
289 };
290
291 if (MCDisassembler::Success != DecodeRegisterOrImm(g, 0))
292 return MCDisassembler::Fail;
293
294 return DecodeRegisterOrImm(h, Insn >> 16u);
295}
296
297DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
298 ArrayRef<uint8_t> Bytes,
299 uint64_t Address,
300 raw_ostream &vStream,
301 raw_ostream &cStream) const {
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000302 MCDisassembler::DecodeStatus Result;
303 if (Bytes.size() < 2) {
304 Size = 0;
305 return Fail;
306 }
307 uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
308 // 0x00 -> 0x07 are 32-bit instructions.
309 // 0x08 -> 0x1F are 16-bit instructions.
310 if (DecodeByte < 0x08) {
311 // 32-bit instruction.
312 if (Bytes.size() < 4) {
313 // Did we decode garbage?
314 Size = 0;
315 return Fail;
316 }
317 if (Bytes.size() >= 8) {
318 // Attempt to decode 64-bit instruction.
319 uint64_t Insn64;
320 if (!readInstruction64(Bytes, Address, Size, Insn64))
321 return Fail;
322 Result =
323 decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000324 if (Success == Result) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000325 LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000326 return Result;
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000327 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000328 LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000329 }
330 uint32_t Insn32;
331 if (!readInstruction32(Bytes, Address, Size, Insn32)) {
332 return Fail;
333 }
334 // Calling the auto-generated decoder function.
335 return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000336 } else {
337 if (Bytes.size() >= 6) {
338 // Attempt to treat as instr. with limm data.
339 uint64_t Insn48;
340 if (!readInstruction48(Bytes, Address, Size, Insn48))
341 return Fail;
342 Result =
343 decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
344 if (Success == Result) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000345 LLVM_DEBUG(
346 dbgs() << "Successfully decoded 16-bit instruction with limm.");
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000347 return Result;
348 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000349 LLVM_DEBUG(
350 dbgs() << "Not a 16-bit instruction with limm, try without it.");
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000351 }
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000352
Tatyana Krasnukhaf665f6a2017-12-02 05:25:17 +0000353 uint32_t Insn16;
354 if (!readInstruction16(Bytes, Address, Size, Insn16))
355 return Fail;
356
357 // Calling the auto-generated decoder function.
358 return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000359 }
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000360}
361
362static MCDisassembler *createARCDisassembler(const Target &T,
363 const MCSubtargetInfo &STI,
364 MCContext &Ctx) {
365 return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
366}
367
368extern "C" void LLVMInitializeARCDisassembler() {
369 // Register the disassembler.
370 TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
371 createARCDisassembler);
372}