LLVM  9.0.0svn
ARCDisassembler.cpp
Go to the documentation of this file.
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"
17 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCInstrInfo.h"
24 
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "arc-disassembler"
28 
30 
31 namespace {
32 
33 /// A disassembler class for ARC.
34 class ARCDisassembler : public MCDisassembler {
35 public:
36  std::unique_ptr<MCInstrInfo const> const MCII;
37 
38  ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
39  MCInstrInfo const *MCII)
40  : MCDisassembler(STI, Ctx), MCII(MCII) {}
41 
42  DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
43  ArrayRef<uint8_t> Bytes, uint64_t Address,
44  raw_ostream &VStream,
45  raw_ostream &CStream) const override;
46 };
47 
48 } // end anonymous namespace
49 
50 static 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 
59 static 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 
69 static 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 
78 static 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 
85 template <unsigned B>
86 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
87  uint64_t Address = 0,
88  const void *Decoder = nullptr);
89 
90 template <unsigned B>
91 static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
92  uint64_t Address = 0,
93  const void *Decoder = nullptr);
94 
95 template <unsigned B>
96 static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
97  uint64_t Address, const void *Decoder);
98 
99 static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
100 
101 static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
102  const void *);
103 
104 static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
105  const void *);
106 
107 static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
108  const void *);
109 
110 static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
111  const void *);
112 
113 static 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 
120 static 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));
131 }
132 
133 static 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 
145 static unsigned decodeCField(unsigned Insn) {
146  return fieldFromInstruction(Insn, 6, 6);
147 }
148 
149 static unsigned decodeBField(unsigned Insn) {
150  return (fieldFromInstruction(Insn, 12, 3) << 3) |
151  fieldFromInstruction(Insn, 24, 3);
152 }
153 
154 static unsigned decodeAField(unsigned Insn) {
155  return fieldFromInstruction(Insn, 0, 6);
156 }
157 
158 static 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)));
166 }
167 
168 static 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 
178 static 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 
186 template <unsigned B>
187 static 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);
193 }
194 
195 template <unsigned B>
196 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
197  uint64_t /*Address*/,
198  const void * /*Decoder*/) {
199 
200  static_assert(B > 0, "field is empty");
202  SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
204 }
205 
206 template <unsigned B>
207 static 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));
216 }
217 
218 static 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));
233 }
234 
235 static 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));
251 }
252 
253 static 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)));
268 }
269 
270 static 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) {
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 
296 DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
297  ArrayRef<uint8_t> Bytes,
298  uint64_t Address,
299  raw_ostream &vStream,
300  raw_ostream &cStream) const {
302  if (Bytes.size() < 2) {
303  Size = 0;
304  return Fail;
305  }
306  uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
307  // 0x00 -> 0x07 are 32-bit instructions.
308  // 0x08 -> 0x1F are 16-bit instructions.
309  if (DecodeByte < 0x08) {
310  // 32-bit instruction.
311  if (Bytes.size() < 4) {
312  // Did we decode garbage?
313  Size = 0;
314  return Fail;
315  }
316  if (Bytes.size() >= 8) {
317  // Attempt to decode 64-bit instruction.
318  uint64_t Insn64;
319  if (!readInstruction64(Bytes, Address, Size, Insn64))
320  return Fail;
321  Result =
322  decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
323  if (Success == Result) {
324  LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
325  return Result;
326  }
327  LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
328  }
329  uint32_t Insn32;
330  if (!readInstruction32(Bytes, Address, Size, Insn32)) {
331  return Fail;
332  }
333  // Calling the auto-generated decoder function.
334  return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
335  } else {
336  if (Bytes.size() >= 6) {
337  // Attempt to treat as instr. with limm data.
338  uint64_t Insn48;
339  if (!readInstruction48(Bytes, Address, Size, Insn48))
340  return Fail;
341  Result =
342  decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
343  if (Success == Result) {
344  LLVM_DEBUG(
345  dbgs() << "Successfully decoded 16-bit instruction with limm.");
346  return Result;
347  }
348  LLVM_DEBUG(
349  dbgs() << "Not a 16-bit instruction with limm, try without it.");
350  }
351 
352  uint32_t Insn16;
353  if (!readInstruction16(Bytes, Address, Size, Insn16))
354  return Fail;
355 
356  // Calling the auto-generated decoder function.
357  return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
358  }
359 }
360 
362  const MCSubtargetInfo &STI,
363  MCContext &Ctx) {
364  return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
365 }
366 
367 extern "C" void LLVMInitializeARCDisassembler() {
368  // Register the disassembler.
371 }
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:23
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:211
static bool readInstruction64(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint64_t &Insn)
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:115
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:62
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:158
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:148
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:23
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:132
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:46
static unsigned decodeBField(unsigned Insn)
LLVM Value Representation.
Definition: Value.h:72
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
void addOperand(const MCOperand &Op)
Definition: MCInst.h:183
#define LLVM_DEBUG(X)
Definition: Debug.h:122
static unsigned decodeAField(unsigned Insn)
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:122
static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const void *)