LLVM  8.0.1
ARCDisassembler.cpp
Go to the documentation of this file.
1 //===- 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 /// This file is part of the ARC Disassembler.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "ARC.h"
16 #include "ARCRegisterInfo.h"
18 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCInstrInfo.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "arc-disassembler"
29 
31 
32 namespace {
33 
34 /// A disassembler class for ARC.
35 class ARCDisassembler : public MCDisassembler {
36 public:
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 
51 static 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 
60 static 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 
70 static 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 
79 static 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 
86 template <unsigned B>
87 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
88  uint64_t Address = 0,
89  const void *Decoder = nullptr);
90 
91 template <unsigned B>
92 static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
93  uint64_t Address = 0,
94  const void *Decoder = nullptr);
95 
96 template <unsigned B>
97 static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
98  uint64_t Address, const void *Decoder);
99 
100 static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
101 
102 static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
103  const void *);
104 
105 static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
106  const void *);
107 
108 static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
109  const void *);
110 
111 static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
112  const void *);
113 
114 static 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 
121 static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
122  uint64_t Address,
123  const void *Decoder) {
124  if (RegNo >= 32) {
125  LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
126  return MCDisassembler::Fail;
127  }
128 
129  unsigned Reg = GPR32DecoderTable[RegNo];
130  Inst.addOperand(MCOperand::createReg(Reg));
132 }
133 
134 static 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 
144 #include "ARCGenDisassemblerTables.inc"
145 
146 static unsigned decodeCField(unsigned Insn) {
147  return fieldFromInstruction(Insn, 6, 6);
148 }
149 
150 static unsigned decodeBField(unsigned Insn) {
151  return (fieldFromInstruction(Insn, 12, 3) << 3) |
152  fieldFromInstruction(Insn, 24, 3);
153 }
154 
155 static unsigned decodeAField(unsigned Insn) {
156  return fieldFromInstruction(Insn, 0, 6);
157 }
158 
159 static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
160  const void *Dec) {
161  // 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)));
167 }
168 
169 static 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 
179 static 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 
187 template <unsigned B>
188 static 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);
194 }
195 
196 template <unsigned B>
197 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
198  uint64_t /*Address*/,
199  const void * /*Decoder*/) {
200 
201  static_assert(B > 0, "field is empty");
203  SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
205 }
206 
207 template <unsigned B>
208 static 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));
217 }
218 
219 static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
220  uint64_t Address,
221  const void *Decoder) {
222  unsigned SrcC, DstB, LImm;
223  DstB = decodeBField(Insn);
224  if (DstB != 62) {
225  LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
226  return MCDisassembler::Fail;
227  }
228  SrcC = decodeCField(Insn);
229  DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
230  LImm = (Insn >> 32);
231  Inst.addOperand(MCOperand::createImm(LImm));
234 }
235 
236 static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
237  uint64_t Address,
238  const void *Decoder) {
239  unsigned DstA, SrcB, LImm;
240  LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
241  SrcB = decodeBField(Insn);
242  if (SrcB != 62) {
243  LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
244  return MCDisassembler::Fail;
245  }
246  DstA = decodeAField(Insn);
247  DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
248  LImm = (Insn >> 32);
249  Inst.addOperand(MCOperand::createImm(LImm));
252 }
253 
254 static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
255  uint64_t Address,
256  const void *Decoder) {
257  unsigned DstA, SrcB;
258  LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
259  DstA = decodeAField(Insn);
260  DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
261  SrcB = decodeBField(Insn);
262  DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
263  if (decodeCField(Insn) != 62) {
264  LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
265  return MCDisassembler::Fail;
266  }
267  Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
269 }
270 
271 static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
272  uint64_t Address,
273  const void *Decoder) {
274  LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
275  using Field = decltype(Insn);
276  Field h = fieldFromInstruction(Insn, 5, 3) |
277  (fieldFromInstruction(Insn, 0, 2) << 3);
278  Field g = fieldFromInstruction(Insn, 8, 3) |
279  (fieldFromInstruction(Insn, 3, 2) << 3);
280 
281  auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
282  Field Value) {
283  if (30 == RegNum) {
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 
297 DecodeStatus 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 {
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);
324  if (Success == Result) {
325  LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
326  return Result;
327  }
328  LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
329  }
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);
336  } 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) {
345  LLVM_DEBUG(
346  dbgs() << "Successfully decoded 16-bit instruction with limm.");
347  return Result;
348  }
349  LLVM_DEBUG(
350  dbgs() << "Not a 16-bit instruction with limm, try without it.");
351  }
352 
353  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);
359  }
360 }
361 
363  const MCSubtargetInfo &STI,
364  MCContext &Ctx) {
365  return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
366 }
367 
368 extern "C" void LLVMInitializeARCDisassembler() {
369  // Register the disassembler.
372 }
static unsigned decodeCField(unsigned Insn)
#define R4(n)
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
Definition: AllocatorList.h:24
static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address, uint64_t Value, const void *Decoder)
DecodeStatus
Ternary decode status.
static const uint16_t GPR32DecoderTable[]
Superclass for all disassemblers.
unsigned Reg
MCInstrInfo * createMCInstrInfo() const
createMCInstrInfo - Create a MCInstrInfo implementation.
static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address=0, const void *Decoder=nullptr)
static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS, uint64_t Address=0, const void *Decoder=nullptr)
static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS, uint64_t Address, const void *Decoder)
Target & getTheARCTarget()
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.
#define R2(n)
T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition: MathExtras.h:212
static bool readInstruction64(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint64_t &Insn)
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:116
static bool readInstruction16(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint32_t &Insn)
#define Fail
void LLVMInitializeARCDisassembler()
static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address, uint64_t Offset, const void *Decoder)
static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t, const void *)
Context object for machine code objects.
Definition: MCContext.h:63
int decodeInstruction(InternalInstruction *insn, byteReader_t reader, const void *readerArg, dlog_t logger, void *loggerArg, const void *miiArg, uint64_t startLoc, DisassemblerMode mode)
Decode one instruction and store the decoding results in a buffer provided by the consumer...
static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t, const void *)
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
static bool readInstruction48(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint64_t &Insn)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:149
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder)
#define R6(n)
static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t, const void *)
static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
Target - Wrapper for Target specific information.
#define Success
static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder)
static bool readInstruction32(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint32_t &Insn)
static MCDisassembler * createARCDisassembler(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx)
Generic base class for all target subtargets.
uint32_t Size
Definition: Profile.cpp:47
static unsigned decodeBField(unsigned Insn)
LLVM Value Representation.
Definition: Value.h:73
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
void addOperand(const MCOperand &Op)
Definition: MCInst.h:186
#define LLVM_DEBUG(X)
Definition: Debug.h:123
static unsigned decodeAField(unsigned Insn)
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:123
static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const void *)