[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / ARC / Disassembler / ARCDisassembler.cpp
blob404d12d0dd1339cf0295e1bb2e508efe6e4e37dd
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 //===----------------------------------------------------------------------===//
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"
26 using namespace llvm;
28 #define DEBUG_TYPE "arc-disassembler"
30 using DecodeStatus = MCDisassembler::DecodeStatus;
32 namespace {
34 /// A disassembler class for ARC.
35 class ARCDisassembler : public MCDisassembler {
36 public:
37 std::unique_ptr<MCInstrInfo const> const MCII;
39 ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
40 MCInstrInfo const *MCII)
41 : MCDisassembler(STI, Ctx), MCII(MCII) {}
43 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
44 ArrayRef<uint8_t> Bytes, uint64_t Address,
45 raw_ostream &CStream) const override;
48 } // end anonymous namespace
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;
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;
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;
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;
85 template <unsigned B>
86 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
87 uint64_t Address = 0,
88 const void *Decoder = nullptr);
90 template <unsigned B>
91 static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
92 uint64_t Address = 0,
93 const void *Decoder = nullptr);
95 template <unsigned B>
96 static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
97 uint64_t Address, const void *Decoder);
99 static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
101 static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
102 const void *);
104 static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
105 const void *);
107 static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
108 const void *);
110 static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,
111 const void *);
113 static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
114 const void *);
116 static const uint16_t GPR32DecoderTable[] = {
117 ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
118 ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13,
119 ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20,
120 ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP,
121 ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK};
123 static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
124 uint64_t Address,
125 const void *Decoder) {
126 if (RegNo >= 32) {
127 LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
128 return MCDisassembler::Fail;
131 unsigned Reg = GPR32DecoderTable[RegNo];
132 Inst.addOperand(MCOperand::createReg(Reg));
133 return MCDisassembler::Success;
136 static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
137 uint64_t Address,
138 const void *Decoder) {
139 // Enumerates registers from ranges [r0-r3],[r12-r15].
140 if (RegNo > 3)
141 RegNo += 8; // 4 for r12, etc...
143 return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
146 #include "ARCGenDisassemblerTables.inc"
148 static unsigned decodeCField(unsigned Insn) {
149 return fieldFromInstruction(Insn, 6, 6);
152 static unsigned decodeBField(unsigned Insn) {
153 return (fieldFromInstruction(Insn, 12, 3) << 3) |
154 fieldFromInstruction(Insn, 24, 3);
157 static unsigned decodeAField(unsigned Insn) {
158 return fieldFromInstruction(Insn, 0, 6);
161 static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
162 const void *Dec) {
163 // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
164 unsigned S9 = Insn & 0x1ff;
165 unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
166 DecodeGPR32RegisterClass(Inst, R, Address, Dec);
167 Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
168 return MCDisassembler::Success;
171 static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
172 uint64_t Value, const void *Decoder) {
173 static const uint64_t AtLeast = 2;
174 // TODO: Try to force emitter to use MCDisassembler* instead of void*.
175 auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
176 return (nullptr != Disassembler &&
177 Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
178 AtLeast));
181 static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
182 uint64_t Offset, const void *Decoder) {
183 uint64_t NextAddress = Address + Offset;
185 if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))
186 Inst.addOperand(MCOperand::createImm(Offset));
189 template <unsigned B>
190 static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
191 uint64_t Address, const void *Decoder) {
193 static_assert(B > 0, "field is empty");
194 DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
195 return MCDisassembler::Success;
198 template <unsigned B>
199 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
200 uint64_t /*Address*/,
201 const void * /*Decoder*/) {
203 static_assert(B > 0, "field is empty");
204 Inst.addOperand(MCOperand::createImm(
205 SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
206 return MCDisassembler::Success;
209 template <unsigned B>
210 static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
211 uint64_t /*Address*/,
212 const void * /*Decoder*/) {
214 static_assert(B > 0, "field is empty");
215 const unsigned max = (1u << B) - 1;
216 Inst.addOperand(
217 MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
218 return MCDisassembler::Success;
221 static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
222 uint64_t Address,
223 const void *Decoder) {
224 unsigned SrcC, DstB, LImm;
225 DstB = decodeBField(Insn);
226 if (DstB != 62) {
227 LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
228 return MCDisassembler::Fail;
230 SrcC = decodeCField(Insn);
231 DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
232 LImm = (Insn >> 32);
233 Inst.addOperand(MCOperand::createImm(LImm));
234 Inst.addOperand(MCOperand::createImm(0));
235 return MCDisassembler::Success;
238 static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
239 uint64_t Address,
240 const void *Decoder) {
241 unsigned DstA, SrcB, LImm;
242 LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
243 SrcB = decodeBField(Insn);
244 if (SrcB != 62) {
245 LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
246 return MCDisassembler::Fail;
248 DstA = decodeAField(Insn);
249 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
250 LImm = (Insn >> 32);
251 Inst.addOperand(MCOperand::createImm(LImm));
252 Inst.addOperand(MCOperand::createImm(0));
253 return MCDisassembler::Success;
256 static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
257 uint64_t Address,
258 const void *Decoder) {
259 unsigned DstA, SrcB;
260 LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
261 DstA = decodeAField(Insn);
262 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
263 SrcB = decodeBField(Insn);
264 DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
265 if (decodeCField(Insn) != 62) {
266 LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
267 return MCDisassembler::Fail;
269 Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
270 return MCDisassembler::Success;
273 static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
274 uint64_t Address,
275 const void *Decoder) {
276 LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
277 using Field = decltype(Insn);
278 Field H = fieldFromInstruction(Insn, 5, 3) |
279 (fieldFromInstruction(Insn, 0, 2) << 3);
280 Field G = fieldFromInstruction(Insn, 8, 3) |
281 (fieldFromInstruction(Insn, 3, 2) << 3);
283 auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
284 Field Value) {
285 if (30 == RegNum) {
286 Inst.addOperand(MCOperand::createImm(Value));
287 return MCDisassembler::Success;
290 return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
293 if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))
294 return MCDisassembler::Fail;
296 return DecodeRegisterOrImm(H, Insn >> 16u);
299 static DecodeStatus DecodeCCRU6Instruction(MCInst &Inst, uint64_t Insn,
300 uint64_t Address,
301 const void *Decoder) {
302 unsigned DstB;
303 LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");
304 DstB = decodeBField(Insn);
305 DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
306 using Field = decltype(Insn);
307 Field U6Field = fieldFromInstruction(Insn, 6, 6);
308 Inst.addOperand(MCOperand::createImm(U6Field));
309 Field CCField = fieldFromInstruction(Insn, 0, 4);
310 Inst.addOperand(MCOperand::createImm(CCField));
311 return MCDisassembler::Success;
314 DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
315 ArrayRef<uint8_t> Bytes,
316 uint64_t Address,
317 raw_ostream &cStream) const {
318 MCDisassembler::DecodeStatus Result;
319 if (Bytes.size() < 2) {
320 Size = 0;
321 return Fail;
323 uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
324 // 0x00 -> 0x07 are 32-bit instructions.
325 // 0x08 -> 0x1F are 16-bit instructions.
326 if (DecodeByte < 0x08) {
327 // 32-bit instruction.
328 if (Bytes.size() < 4) {
329 // Did we decode garbage?
330 Size = 0;
331 return Fail;
333 if (Bytes.size() >= 8) {
334 // Attempt to decode 64-bit instruction.
335 uint64_t Insn64;
336 if (!readInstruction64(Bytes, Address, Size, Insn64))
337 return Fail;
338 Result =
339 decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
340 if (Success == Result) {
341 LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
342 return Result;
344 LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
346 uint32_t Insn32;
347 if (!readInstruction32(Bytes, Address, Size, Insn32)) {
348 return Fail;
350 // Calling the auto-generated decoder function.
351 return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
352 } else {
353 if (Bytes.size() >= 6) {
354 // Attempt to treat as instr. with limm data.
355 uint64_t Insn48;
356 if (!readInstruction48(Bytes, Address, Size, Insn48))
357 return Fail;
358 Result =
359 decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
360 if (Success == Result) {
361 LLVM_DEBUG(
362 dbgs() << "Successfully decoded 16-bit instruction with limm.");
363 return Result;
365 LLVM_DEBUG(
366 dbgs() << "Not a 16-bit instruction with limm, try without it.");
369 uint32_t Insn16;
370 if (!readInstruction16(Bytes, Address, Size, Insn16))
371 return Fail;
373 // Calling the auto-generated decoder function.
374 return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
378 static MCDisassembler *createARCDisassembler(const Target &T,
379 const MCSubtargetInfo &STI,
380 MCContext &Ctx) {
381 return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
384 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler() {
385 // Register the disassembler.
386 TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
387 createARCDisassembler);