1*88ebb9e2SColin LeMahieu //===-- HexagonDisassembler.cpp - Disassembler for Hexagon ISA ------------===//
2*88ebb9e2SColin LeMahieu //
3*88ebb9e2SColin LeMahieu //                     The LLVM Compiler Infrastructure
4*88ebb9e2SColin LeMahieu //
5*88ebb9e2SColin LeMahieu // This file is distributed under the University of Illinois Open Source
6*88ebb9e2SColin LeMahieu // License. See LICENSE.TXT for details.
7*88ebb9e2SColin LeMahieu //
8*88ebb9e2SColin LeMahieu //===----------------------------------------------------------------------===//
9*88ebb9e2SColin LeMahieu 
10*88ebb9e2SColin LeMahieu #include "MCTargetDesc/HexagonBaseInfo.h"
11*88ebb9e2SColin LeMahieu #include "MCTargetDesc/HexagonMCTargetDesc.h"
12*88ebb9e2SColin LeMahieu 
13*88ebb9e2SColin LeMahieu #include "llvm/MC/MCContext.h"
14*88ebb9e2SColin LeMahieu #include "llvm/MC/MCDisassembler.h"
15*88ebb9e2SColin LeMahieu #include "llvm/MC/MCExpr.h"
16*88ebb9e2SColin LeMahieu #include "llvm/MC/MCFixedLenDisassembler.h"
17*88ebb9e2SColin LeMahieu #include "llvm/MC/MCInst.h"
18*88ebb9e2SColin LeMahieu #include "llvm/MC/MCInstrDesc.h"
19*88ebb9e2SColin LeMahieu #include "llvm/MC/MCSubtargetInfo.h"
20*88ebb9e2SColin LeMahieu #include "llvm/Support/Debug.h"
21*88ebb9e2SColin LeMahieu #include "llvm/Support/ErrorHandling.h"
22*88ebb9e2SColin LeMahieu #include "llvm/Support/LEB128.h"
23*88ebb9e2SColin LeMahieu #include "llvm/Support/MemoryObject.h"
24*88ebb9e2SColin LeMahieu #include "llvm/Support/raw_ostream.h"
25*88ebb9e2SColin LeMahieu #include "llvm/Support/TargetRegistry.h"
26*88ebb9e2SColin LeMahieu #include "llvm/Support/Endian.h"
27*88ebb9e2SColin LeMahieu 
28*88ebb9e2SColin LeMahieu #include <vector>
29*88ebb9e2SColin LeMahieu #include <array>
30*88ebb9e2SColin LeMahieu 
31*88ebb9e2SColin LeMahieu using namespace llvm;
32*88ebb9e2SColin LeMahieu 
33*88ebb9e2SColin LeMahieu #define DEBUG_TYPE "hexagon-disassembler"
34*88ebb9e2SColin LeMahieu 
35*88ebb9e2SColin LeMahieu using DecodeStatus = MCDisassembler::DecodeStatus;
36*88ebb9e2SColin LeMahieu 
37*88ebb9e2SColin LeMahieu namespace {
38*88ebb9e2SColin LeMahieu /// \brief Hexagon disassembler for all Hexagon platforms.
39*88ebb9e2SColin LeMahieu class HexagonDisassembler : public MCDisassembler {
40*88ebb9e2SColin LeMahieu public:
41*88ebb9e2SColin LeMahieu   HexagonDisassembler(MCSubtargetInfo const &STI, MCContext &Ctx)
42*88ebb9e2SColin LeMahieu       : MCDisassembler(STI, Ctx) {}
43*88ebb9e2SColin LeMahieu 
44*88ebb9e2SColin LeMahieu   DecodeStatus getInstruction(MCInst &instr, uint64_t &size,
45*88ebb9e2SColin LeMahieu                               MemoryObject const &region, uint64_t address,
46*88ebb9e2SColin LeMahieu                               raw_ostream &vStream, raw_ostream &cStream) const override;
47*88ebb9e2SColin LeMahieu };
48*88ebb9e2SColin LeMahieu }
49*88ebb9e2SColin LeMahieu 
50*88ebb9e2SColin LeMahieu static const uint16_t IntRegDecoderTable[] = {
51*88ebb9e2SColin LeMahieu     Hexagon::R0,  Hexagon::R1,  Hexagon::R2,  Hexagon::R3,  Hexagon::R4,
52*88ebb9e2SColin LeMahieu     Hexagon::R5,  Hexagon::R6,  Hexagon::R7,  Hexagon::R8,  Hexagon::R9,
53*88ebb9e2SColin LeMahieu     Hexagon::R10, Hexagon::R11, Hexagon::R12, Hexagon::R13, Hexagon::R14,
54*88ebb9e2SColin LeMahieu     Hexagon::R15, Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19,
55*88ebb9e2SColin LeMahieu     Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23, Hexagon::R24,
56*88ebb9e2SColin LeMahieu     Hexagon::R25, Hexagon::R26, Hexagon::R27, Hexagon::R28, Hexagon::R29,
57*88ebb9e2SColin LeMahieu     Hexagon::R30, Hexagon::R31};
58*88ebb9e2SColin LeMahieu 
59*88ebb9e2SColin LeMahieu static const uint16_t DoubleRegDecoderTable[] = {
60*88ebb9e2SColin LeMahieu     Hexagon::D0,  Hexagon::D1,  Hexagon::D2,  Hexagon::D3,
61*88ebb9e2SColin LeMahieu     Hexagon::D4,  Hexagon::D5,  Hexagon::D6,  Hexagon::D7,
62*88ebb9e2SColin LeMahieu     Hexagon::D8,  Hexagon::D9,  Hexagon::D10, Hexagon::D11,
63*88ebb9e2SColin LeMahieu     Hexagon::D12, Hexagon::D13, Hexagon::D14, Hexagon::D15};
64*88ebb9e2SColin LeMahieu 
65*88ebb9e2SColin LeMahieu static const uint16_t PredRegDecoderTable[] = {Hexagon::P0, Hexagon::P1,
66*88ebb9e2SColin LeMahieu                                                Hexagon::P2, Hexagon::P3};
67*88ebb9e2SColin LeMahieu 
68*88ebb9e2SColin LeMahieu static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, unsigned RegNo,
69*88ebb9e2SColin LeMahieu                                                uint64_t /*Address*/,
70*88ebb9e2SColin LeMahieu                                                void const *Decoder) {
71*88ebb9e2SColin LeMahieu   if (RegNo > 31)
72*88ebb9e2SColin LeMahieu     return MCDisassembler::Fail;
73*88ebb9e2SColin LeMahieu 
74*88ebb9e2SColin LeMahieu   unsigned Register = IntRegDecoderTable[RegNo];
75*88ebb9e2SColin LeMahieu   Inst.addOperand(MCOperand::CreateReg(Register));
76*88ebb9e2SColin LeMahieu   return MCDisassembler::Success;
77*88ebb9e2SColin LeMahieu }
78*88ebb9e2SColin LeMahieu 
79*88ebb9e2SColin LeMahieu static DecodeStatus DecodeDoubleRegsRegisterClass(MCInst &Inst, unsigned RegNo,
80*88ebb9e2SColin LeMahieu                                                   uint64_t /*Address*/,
81*88ebb9e2SColin LeMahieu                                                   void const *Decoder) {
82*88ebb9e2SColin LeMahieu   if (RegNo > 15)
83*88ebb9e2SColin LeMahieu     return MCDisassembler::Fail;
84*88ebb9e2SColin LeMahieu 
85*88ebb9e2SColin LeMahieu   unsigned Register = DoubleRegDecoderTable[RegNo];
86*88ebb9e2SColin LeMahieu   Inst.addOperand(MCOperand::CreateReg(Register));
87*88ebb9e2SColin LeMahieu   return MCDisassembler::Success;
88*88ebb9e2SColin LeMahieu }
89*88ebb9e2SColin LeMahieu 
90*88ebb9e2SColin LeMahieu static DecodeStatus DecodePredRegsRegisterClass(MCInst &Inst, unsigned RegNo,
91*88ebb9e2SColin LeMahieu                                                 uint64_t /*Address*/,
92*88ebb9e2SColin LeMahieu                                                 void const *Decoder) {
93*88ebb9e2SColin LeMahieu   if (RegNo > 3)
94*88ebb9e2SColin LeMahieu     return MCDisassembler::Fail;
95*88ebb9e2SColin LeMahieu 
96*88ebb9e2SColin LeMahieu   unsigned Register = PredRegDecoderTable[RegNo];
97*88ebb9e2SColin LeMahieu   Inst.addOperand(MCOperand::CreateReg(Register));
98*88ebb9e2SColin LeMahieu   return MCDisassembler::Success;
99*88ebb9e2SColin LeMahieu }
100*88ebb9e2SColin LeMahieu 
101*88ebb9e2SColin LeMahieu #include "HexagonGenDisassemblerTables.inc"
102*88ebb9e2SColin LeMahieu 
103*88ebb9e2SColin LeMahieu static MCDisassembler *createHexagonDisassembler(Target const &T,
104*88ebb9e2SColin LeMahieu                                                  MCSubtargetInfo const &STI,
105*88ebb9e2SColin LeMahieu                                                  MCContext &Ctx) {
106*88ebb9e2SColin LeMahieu   return new HexagonDisassembler(STI, Ctx);
107*88ebb9e2SColin LeMahieu }
108*88ebb9e2SColin LeMahieu 
109*88ebb9e2SColin LeMahieu extern "C" void LLVMInitializeHexagonDisassembler() {
110*88ebb9e2SColin LeMahieu   TargetRegistry::RegisterMCDisassembler(TheHexagonTarget,
111*88ebb9e2SColin LeMahieu                                          createHexagonDisassembler);
112*88ebb9e2SColin LeMahieu }
113*88ebb9e2SColin LeMahieu 
114*88ebb9e2SColin LeMahieu DecodeStatus HexagonDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
115*88ebb9e2SColin LeMahieu                                                  MemoryObject const &Region,
116*88ebb9e2SColin LeMahieu                                                  uint64_t Address,
117*88ebb9e2SColin LeMahieu                                                  raw_ostream &os,
118*88ebb9e2SColin LeMahieu                                                  raw_ostream &cs) const {
119*88ebb9e2SColin LeMahieu   std::array<uint8_t, 4> Bytes;
120*88ebb9e2SColin LeMahieu   Size = 4;
121*88ebb9e2SColin LeMahieu   if (Region.readBytes(Address, Bytes.size(), Bytes.data()) == -1) {
122*88ebb9e2SColin LeMahieu     return MCDisassembler::Fail;
123*88ebb9e2SColin LeMahieu   }
124*88ebb9e2SColin LeMahieu   uint32_t insn =
125*88ebb9e2SColin LeMahieu       llvm::support::endian::read<uint32_t, llvm::support::little,
126*88ebb9e2SColin LeMahieu                                   llvm::support::unaligned>(Bytes.data());
127*88ebb9e2SColin LeMahieu 
128*88ebb9e2SColin LeMahieu   // Remove parse bits.
129*88ebb9e2SColin LeMahieu   insn &= ~static_cast<uint32_t>(HexagonII::InstParseBits::INST_PARSE_MASK);
130*88ebb9e2SColin LeMahieu   return decodeInstruction(DecoderTable32, MI, insn, Address, this, STI);
131*88ebb9e2SColin LeMahieu }
132