ARCDisassembler.cpp revision 360784
1//===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- 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/// \file
10/// This file is part of the ARC Disassembler.
11///
12//===----------------------------------------------------------------------===//
13
14#include "ARC.h"
15#include "ARCRegisterInfo.h"
16#include "MCTargetDesc/ARCMCTargetDesc.h"
17#include "TargetInfo/ARCTargetInfo.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/// 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 &CStream) const override;
46};
47
48} // end anonymous namespace
49
50static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
51                              uint64_t &Size, uint32_t &Insn) {
52  Size = 4;
53  // Read 2 16-bit values, but swap hi/lo parts.
54  Insn =
55      (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
56  return true;
57}
58
59static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
60                              uint64_t &Size, uint64_t &Insn) {
61  Size = 8;
62  Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
63         ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
64         ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
65         ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
66  return true;
67}
68
69static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
70                              uint64_t &Size, uint64_t &Insn) {
71  Size = 6;
72  Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
73         ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
74         ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
75  return true;
76}
77
78static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
79                              uint64_t &Size, uint32_t &Insn) {
80  Size = 2;
81  Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
82  return true;
83}
84
85template <unsigned B>
86static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
87                                        uint64_t Address = 0,
88                                        const void *Decoder = nullptr);
89
90template <unsigned B>
91static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
92                                        uint64_t Address = 0,
93                                        const void *Decoder = nullptr);
94
95template <unsigned B>
96static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
97                                        uint64_t Address, const void *Decoder);
98
99static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
100
101static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
102                                            const void *);
103
104static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
105                                            const void *);
106
107static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
108                                             const void *);
109
110static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
111                                              const void *);
112
113static const uint16_t GPR32DecoderTable[] = {
114    ARC::R0,  ARC::R1,    ARC::R2,  ARC::R3,   ARC::R4,  ARC::R5,  ARC::R6,
115    ARC::R7,  ARC::R8,    ARC::R9,  ARC::R10,  ARC::R11, ARC::R12, ARC::R13,
116    ARC::R14, ARC::R15,   ARC::R16, ARC::R17,  ARC::R18, ARC::R19, ARC::R20,
117    ARC::R21, ARC::R22,   ARC::R23, ARC::R24,  ARC::R25, ARC::GP,  ARC::FP,
118    ARC::SP,  ARC::ILINK, ARC::R30, ARC::BLINK};
119
120static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
121                                             uint64_t Address,
122                                             const void *Decoder) {
123  if (RegNo >= 32) {
124    LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
125    return MCDisassembler::Fail;
126  }
127
128  unsigned Reg = GPR32DecoderTable[RegNo];
129  Inst.addOperand(MCOperand::createReg(Reg));
130  return MCDisassembler::Success;
131}
132
133static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
134                                               uint64_t Address,
135                                               const void *Decoder) {
136  // Enumerates registers from ranges [r0-r3],[r12-r15].
137  if (RegNo > 3)
138    RegNo += 8; // 4 for r12, etc...
139
140  return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
141}
142
143#include "ARCGenDisassemblerTables.inc"
144
145static unsigned decodeCField(unsigned Insn) {
146  return fieldFromInstruction(Insn, 6, 6);
147}
148
149static unsigned decodeBField(unsigned Insn) {
150  return (fieldFromInstruction(Insn, 12, 3) << 3) |
151         fieldFromInstruction(Insn, 24, 3);
152}
153
154static unsigned decodeAField(unsigned Insn) {
155  return fieldFromInstruction(Insn, 0, 6);
156}
157
158static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
159                                 const void *Dec) {
160  // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
161  unsigned S9 = Insn & 0x1ff;
162  unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
163  DecodeGPR32RegisterClass(Inst, R, Address, Dec);
164  Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
165  return MCDisassembler::Success;
166}
167
168static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
169                                  uint64_t Value, const void *Decoder) {
170  static const uint64_t atLeast = 2;
171  // TODO: Try to force emitter to use MCDisassembler* instead of void*.
172  auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
173  return (nullptr != Disassembler &&
174          Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
175                                                 atLeast));
176}
177
178static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
179                                     uint64_t Offset, const void *Decoder) {
180  uint64_t nextAddress = Address + Offset;
181
182  if (!DecodeSymbolicOperand(Inst, Address, nextAddress, Decoder))
183    Inst.addOperand(MCOperand::createImm(Offset));
184}
185
186template <unsigned B>
187static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
188                                        uint64_t Address, const void *Decoder) {
189
190  static_assert(B > 0, "field is empty");
191  DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
192  return MCDisassembler::Success;
193}
194
195template <unsigned B>
196static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
197                                        uint64_t /*Address*/,
198                                        const void * /*Decoder*/) {
199
200  static_assert(B > 0, "field is empty");
201  Inst.addOperand(MCOperand::createImm(
202      SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
203  return MCDisassembler::Success;
204}
205
206template <unsigned B>
207static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
208                                          uint64_t /*Address*/,
209                                          const void * /*Decoder*/) {
210
211  static_assert(B > 0, "field is empty");
212  const unsigned max = (1u << B) - 1;
213  Inst.addOperand(
214      MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
215  return MCDisassembler::Success;
216}
217
218static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
219                                            uint64_t Address,
220                                            const void *Decoder) {
221  unsigned SrcC, DstB, LImm;
222  DstB = decodeBField(Insn);
223  if (DstB != 62) {
224    LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
225    return MCDisassembler::Fail;
226  }
227  SrcC = decodeCField(Insn);
228  DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
229  LImm = (Insn >> 32);
230  Inst.addOperand(MCOperand::createImm(LImm));
231  Inst.addOperand(MCOperand::createImm(0));
232  return MCDisassembler::Success;
233}
234
235static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
236                                            uint64_t Address,
237                                            const void *Decoder) {
238  unsigned DstA, SrcB, LImm;
239  LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
240  SrcB = decodeBField(Insn);
241  if (SrcB != 62) {
242    LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
243    return MCDisassembler::Fail;
244  }
245  DstA = decodeAField(Insn);
246  DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
247  LImm = (Insn >> 32);
248  Inst.addOperand(MCOperand::createImm(LImm));
249  Inst.addOperand(MCOperand::createImm(0));
250  return MCDisassembler::Success;
251}
252
253static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
254                                             uint64_t Address,
255                                             const void *Decoder) {
256  unsigned DstA, SrcB;
257  LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
258  DstA = decodeAField(Insn);
259  DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
260  SrcB = decodeBField(Insn);
261  DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
262  if (decodeCField(Insn) != 62) {
263    LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
264    return MCDisassembler::Fail;
265  }
266  Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
267  return MCDisassembler::Success;
268}
269
270static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
271                                              uint64_t Address,
272                                              const void *Decoder) {
273  LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
274  using Field = decltype(Insn);
275  Field h = fieldFromInstruction(Insn, 5, 3) |
276            (fieldFromInstruction(Insn, 0, 2) << 3);
277  Field g = fieldFromInstruction(Insn, 8, 3) |
278            (fieldFromInstruction(Insn, 3, 2) << 3);
279
280  auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
281                                                       Field Value) {
282    if (30 == RegNum) {
283      Inst.addOperand(MCOperand::createImm(Value));
284      return MCDisassembler::Success;
285    }
286
287    return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
288  };
289
290  if (MCDisassembler::Success != DecodeRegisterOrImm(g, 0))
291    return MCDisassembler::Fail;
292
293  return DecodeRegisterOrImm(h, Insn >> 16u);
294}
295
296DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
297                                             ArrayRef<uint8_t> Bytes,
298                                             uint64_t Address,
299                                             raw_ostream &cStream) const {
300  MCDisassembler::DecodeStatus Result;
301  if (Bytes.size() < 2) {
302    Size = 0;
303    return Fail;
304  }
305  uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
306  // 0x00 -> 0x07 are 32-bit instructions.
307  // 0x08 -> 0x1F are 16-bit instructions.
308  if (DecodeByte < 0x08) {
309    // 32-bit instruction.
310    if (Bytes.size() < 4) {
311      // Did we decode garbage?
312      Size = 0;
313      return Fail;
314    }
315    if (Bytes.size() >= 8) {
316      // Attempt to decode 64-bit instruction.
317      uint64_t Insn64;
318      if (!readInstruction64(Bytes, Address, Size, Insn64))
319        return Fail;
320      Result =
321          decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
322      if (Success == Result) {
323        LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
324        return Result;
325      }
326      LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
327    }
328    uint32_t Insn32;
329    if (!readInstruction32(Bytes, Address, Size, Insn32)) {
330      return Fail;
331    }
332    // Calling the auto-generated decoder function.
333    return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
334  } else {
335    if (Bytes.size() >= 6) {
336      // Attempt to treat as instr. with limm data.
337      uint64_t Insn48;
338      if (!readInstruction48(Bytes, Address, Size, Insn48))
339        return Fail;
340      Result =
341          decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
342      if (Success == Result) {
343        LLVM_DEBUG(
344            dbgs() << "Successfully decoded 16-bit instruction with limm.");
345        return Result;
346      }
347      LLVM_DEBUG(
348          dbgs() << "Not a 16-bit instruction with limm, try without it.");
349    }
350
351    uint32_t Insn16;
352    if (!readInstruction16(Bytes, Address, Size, Insn16))
353      return Fail;
354
355    // Calling the auto-generated decoder function.
356    return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
357  }
358}
359
360static MCDisassembler *createARCDisassembler(const Target &T,
361                                             const MCSubtargetInfo &STI,
362                                             MCContext &Ctx) {
363  return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
364}
365
366extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler() {
367  // Register the disassembler.
368  TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
369                                         createARCDisassembler);
370}
371