LLVM 20.0.0git
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"
18#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCInst.h"
22#include "llvm/MC/MCInstrInfo.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "arc-disassembler"
29
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
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,
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,
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,
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,
80 Size = 2;
81 Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
82 return true;
83}
84
85template <unsigned B>
86static DecodeStatus
87DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
88 const MCDisassembler *Decoder = nullptr);
89
90template <unsigned B>
91static DecodeStatus
92DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
93 const MCDisassembler *Decoder = nullptr);
94
95template <unsigned B>
96static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
97 uint64_t Address,
98 const MCDisassembler *Decoder);
99
100static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
101 const MCDisassembler *);
102
104 const MCDisassembler *);
105
107 const MCDisassembler *);
108
110 const MCDisassembler *);
111
113 const MCDisassembler *);
114
116 const MCDisassembler *);
117
119 const MCDisassembler *);
120
122 const MCDisassembler *);
123
124static const uint16_t GPR32DecoderTable[] = {
125 ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
126 ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13,
127 ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20,
128 ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP,
129 ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK};
130
131static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
132 uint64_t Address,
133 const MCDisassembler *Decoder) {
134 if (RegNo >= 32) {
135 LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
137 }
138
139 unsigned Reg = GPR32DecoderTable[RegNo];
142}
143
144static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
145 uint64_t Address,
146 const MCDisassembler *Decoder) {
147 // Enumerates registers from ranges [r0-r3],[r12-r15].
148 if (RegNo > 3)
149 RegNo += 8; // 4 for r12, etc...
150
151 return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
152}
153
154#include "ARCGenDisassemblerTables.inc"
155
156static unsigned decodeCField(unsigned Insn) {
157 return fieldFromInstruction(Insn, 6, 6);
158}
159
160static unsigned decodeBField(unsigned Insn) {
161 return (fieldFromInstruction(Insn, 12, 3) << 3) |
162 fieldFromInstruction(Insn, 24, 3);
163}
164
165static unsigned decodeAField(unsigned Insn) {
166 return fieldFromInstruction(Insn, 0, 6);
167}
168
169static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
170 const MCDisassembler *Dec) {
171 // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
172 unsigned S9 = Insn & 0x1ff;
173 unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
174 DecodeGPR32RegisterClass(Inst, R, Address, Dec);
175 Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
177}
178
179static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
181 const MCDisassembler *Decoder) {
182 static const uint64_t AtLeast = 2;
183 return (nullptr != Decoder && Decoder->tryAddingSymbolicOperand(
184 Inst, Value, Address, true, 0, AtLeast, 0));
185}
186
187static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
189 const MCDisassembler *Decoder) {
190 uint64_t NextAddress = Address + Offset;
191
192 if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))
194}
195
196template <unsigned B>
197static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
198 uint64_t Address,
199 const MCDisassembler *Decoder) {
200
201 static_assert(B > 0, "field is empty");
202 DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
204}
205
206template <unsigned B>
207static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
208 uint64_t /*Address*/,
209 const MCDisassembler * /*Decoder*/) {
210
211 static_assert(B > 0, "field is empty");
213 SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
215}
216
217template <unsigned B>
218static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
219 uint64_t /*Address*/,
220 const MCDisassembler * /*Decoder*/) {
221
222 static_assert(B > 0, "field is empty");
223 const unsigned max = (1u << B) - 1;
224 Inst.addOperand(
225 MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
227}
228
230 uint64_t Address,
231 const MCDisassembler *Decoder) {
232 unsigned SrcC, DstB, LImm;
233 DstB = decodeBField(Insn);
234 if (DstB != 62) {
235 LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
237 }
238 SrcC = decodeCField(Insn);
239 DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
240 LImm = (Insn >> 32);
244}
245
247 uint64_t Address,
248 const MCDisassembler *Decoder) {
249 unsigned DstA, SrcB, LImm;
250 LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
251 SrcB = decodeBField(Insn);
252 if (SrcB != 62) {
253 LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
255 }
256 DstA = decodeAField(Insn);
257 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
258 LImm = (Insn >> 32);
262}
263
265 uint64_t Address,
266 const MCDisassembler *Decoder) {
267 unsigned DstA, SrcB;
268 LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
269 DstA = decodeAField(Insn);
270 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
271 SrcB = decodeBField(Insn);
272 DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
273 if (decodeCField(Insn) != 62) {
274 LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
276 }
279}
280
282 uint64_t Address,
283 const MCDisassembler *Decoder) {
284 LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
285 using Field = decltype(Insn);
286 Field H = fieldFromInstruction(Insn, 5, 3) |
287 (fieldFromInstruction(Insn, 0, 2) << 3);
288 Field G = fieldFromInstruction(Insn, 8, 3) |
289 (fieldFromInstruction(Insn, 3, 2) << 3);
290
291 auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
292 Field Value) {
293 if (30 == RegNum) {
296 }
297
298 return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
299 };
300
301 if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))
303
304 return DecodeRegisterOrImm(H, Insn >> 16u);
305}
306
308 uint64_t Address,
309 const MCDisassembler *Decoder) {
310 unsigned DstB;
311 LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");
312 DstB = decodeBField(Insn);
313 DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
314 using Field = decltype(Insn);
315 Field U6Field = fieldFromInstruction(Insn, 6, 6);
316 Inst.addOperand(MCOperand::createImm(U6Field));
317 Field CCField = fieldFromInstruction(Insn, 0, 4);
318 Inst.addOperand(MCOperand::createImm(CCField));
320}
321
323 uint64_t Address,
324 const MCDisassembler *Decoder) {
325 unsigned DstB = decodeBField(Insn);
326 DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
327 using Field = decltype(Insn);
328 Field U6 = fieldFromInstruction(Insn, 6, 6);
331}
332
334 uint64_t Address,
335 const MCDisassembler *Decoder) {
336 unsigned DstB = decodeBField(Insn);
337 DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
338 using Field = decltype(Insn);
339 Field Lower = fieldFromInstruction(Insn, 6, 6);
340 Field Upper = fieldFromInstruction(Insn, 0, 5);
341 Field Sign = fieldFromInstruction(Insn, 5, 1) ? -1 : 1;
342 Field Result = Sign * ((Upper << 6) + Lower);
343 Inst.addOperand(MCOperand::createImm(Result));
345}
346
347DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
348 ArrayRef<uint8_t> Bytes,
349 uint64_t Address,
350 raw_ostream &cStream) const {
352 if (Bytes.size() < 2) {
353 Size = 0;
354 return Fail;
355 }
356 uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
357 // 0x00 -> 0x07 are 32-bit instructions.
358 // 0x08 -> 0x1F are 16-bit instructions.
359 if (DecodeByte < 0x08) {
360 // 32-bit instruction.
361 if (Bytes.size() < 4) {
362 // Did we decode garbage?
363 Size = 0;
364 return Fail;
365 }
366 if (Bytes.size() >= 8) {
367 // Attempt to decode 64-bit instruction.
368 uint64_t Insn64;
369 if (!readInstruction64(Bytes, Address, Size, Insn64))
370 return Fail;
371 Result =
372 decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
373 if (Success == Result) {
374 LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
375 return Result;
376 }
377 LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
378 }
379 uint32_t Insn32;
380 if (!readInstruction32(Bytes, Address, Size, Insn32)) {
381 return Fail;
382 }
383 // Calling the auto-generated decoder function.
384 return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
385 } else {
386 if (Bytes.size() >= 6) {
387 // Attempt to treat as instr. with limm data.
388 uint64_t Insn48;
389 if (!readInstruction48(Bytes, Address, Size, Insn48))
390 return Fail;
391 Result =
392 decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
393 if (Success == Result) {
395 dbgs() << "Successfully decoded 16-bit instruction with limm.");
396 return Result;
397 }
399 dbgs() << "Not a 16-bit instruction with limm, try without it.");
400 }
401
402 uint32_t Insn16;
403 if (!readInstruction16(Bytes, Address, Size, Insn16))
404 return Fail;
405
406 // Calling the auto-generated decoder function.
407 return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
408 }
409}
410
412 const MCSubtargetInfo &STI,
413 MCContext &Ctx) {
414 return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
415}
416
418 // Register the disassembler.
421}
#define Fail
#define Success
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t, const MCDisassembler *)
static bool readInstruction48(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint64_t &Insn)
static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t, const MCDisassembler *)
static DecodeStatus DecodeSOPwithRU6(MCInst &, uint64_t, uint64_t, const MCDisassembler *)
static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t, const MCDisassembler *)
static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS, uint64_t Address, const MCDisassembler *Decoder)
static unsigned decodeCField(unsigned Insn)
static bool readInstruction64(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint64_t &Insn)
static unsigned decodeBField(unsigned Insn)
static MCDisassembler * createARCDisassembler(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx)
static DecodeStatus DecodeSOPwithRS12(MCInst &, uint64_t, uint64_t, const MCDisassembler *)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler()
static bool readInstruction16(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint32_t &Insn)
static bool readInstruction32(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint32_t &Insn)
static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const MCDisassembler *)
static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS, uint64_t Address=0, const MCDisassembler *Decoder=nullptr)
static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address=0, const MCDisassembler *Decoder=nullptr)
static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t, const MCDisassembler *)
static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address, uint64_t Offset, const MCDisassembler *Decoder)
static const uint16_t GPR32DecoderTable[]
static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const MCDisassembler *)
static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address, uint64_t Value, const MCDisassembler *Decoder)
static unsigned decodeAField(unsigned Insn)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:131
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Size
#define G(x, y, z)
Definition: MD5.cpp:56
#define H(x, y, z)
Definition: MD5.cpp:57
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
Context object for machine code objects.
Definition: MCContext.h:83
Superclass for all disassemblers.
bool tryAddingSymbolicOperand(MCInst &Inst, int64_t Value, uint64_t Address, bool IsBranch, uint64_t Offset, uint64_t OpSize, uint64_t InstSize) const
DecodeStatus
Ternary decode status.
virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef< uint8_t > Bytes, uint64_t Address, raw_ostream &CStream) const =0
Returns the disassembly of a single instruction.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
Generic base class for all target subtargets.
Target - Wrapper for Target specific information.
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
@ Offset
Definition: DWP.cpp:480
Target & getTheARCTarget()
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:81
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.