blob: 3a71b80b2ba7a9377eeb1acaad7a6b0ec97098bf [file] [log] [blame]
Jacques Pienaarfcef3e42016-03-28 13:09:54 +00001//===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- 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// This file is part of the Lanai Disassembler.
11//
12//===----------------------------------------------------------------------===//
13
14#include "LanaiDisassembler.h"
15
16#include "Lanai.h"
17#include "LanaiSubtarget.h"
18#include "llvm/MC/MCFixedLenDisassembler.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCSubtargetInfo.h"
21#include "llvm/Support/MathExtras.h"
22#include "llvm/Support/MemoryObject.h"
23#include "llvm/Support/TargetRegistry.h"
24
25using namespace llvm;
26
27typedef MCDisassembler::DecodeStatus DecodeStatus;
28
29namespace llvm {
30extern Target TheLanaiTarget;
31}
32
33static MCDisassembler *createLanaiDisassembler(const Target &T,
34 const MCSubtargetInfo &STI,
35 MCContext &Ctx) {
36 return new LanaiDisassembler(STI, Ctx);
37}
38
39extern "C" void LLVMInitializeLanaiDisassembler() {
40 // Register the disassembler
41 TargetRegistry::RegisterMCDisassembler(TheLanaiTarget,
42 createLanaiDisassembler);
43}
44
45LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
46 : MCDisassembler(STI, Ctx) {}
47
48// Forward declare because the autogenerated code will reference this.
49// Definition is further down.
50DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
51 uint64_t Address, const void *Decoder);
52
53static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
54 uint64_t Address, const void *Decoder);
55
56static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
57 uint64_t Address, const void *Decoder);
58
59static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
60 uint64_t Address, const void *Decoder);
61
62static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
63 const void *Decoder);
64
65static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
66 uint64_t Address, const void *Decoder);
67
68#include "LanaiGenDisassemblerTables.inc"
69
70static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
71 uint64_t &Size, uint32_t &Insn) {
72 // We want to read exactly 4 bytes of data.
73 if (Bytes.size() < 4) {
74 Size = 0;
75 return MCDisassembler::Fail;
76 }
77
78 // Encoded as big-endian 32-bit word in the stream.
79 Insn =
80 (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);
81
82 return MCDisassembler::Success;
83}
84
85static void PostOperandDecodeAdjust(MCInst &Instr, uint32_t Insn) {
86 unsigned AluOp = LPAC::ADD;
87 // Fix up for pre and post operations.
88 int PqShift = -1;
89 if (isRMOpcode(Instr.getOpcode()))
90 PqShift = 16;
91 else if (isSPLSOpcode(Instr.getOpcode()))
92 PqShift = 10;
93 else if (isRRMOpcode(Instr.getOpcode())) {
94 PqShift = 16;
95 // Determine RRM ALU op.
96 AluOp = (Insn >> 8) & 0x7;
97 if (AluOp == 7)
98 // Handle JJJJJ
99 // 0b10000 or 0b11000
100 AluOp |= 0x20 | (((Insn >> 3) & 0xf) << 1);
101 }
102
103 if (PqShift != -1) {
104 unsigned PQ = (Insn >> PqShift) & 0x3;
105 switch (PQ) {
106 case 0x0:
107 if (Instr.getOperand(2).isReg()) {
108 Instr.getOperand(2).setReg(Lanai::R0);
109 }
110 if (Instr.getOperand(2).isImm())
111 Instr.getOperand(2).setImm(0);
112 break;
113 case 0x1:
114 AluOp = LPAC::makePostOp(AluOp);
115 break;
116 case 0x2:
117 break;
118 case 0x3:
119 AluOp = LPAC::makePreOp(AluOp);
120 break;
121 }
122 Instr.addOperand(MCOperand::createImm(AluOp));
123 }
124}
125
126DecodeStatus LanaiDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
127 ArrayRef<uint8_t> Bytes,
128 uint64_t Address,
129 raw_ostream &VStream,
130 raw_ostream &CStream) const {
131 uint32_t Insn;
132
133 DecodeStatus Result = readInstruction32(Bytes, Address, Size, Insn);
134
135 if (Result == MCDisassembler::Fail)
136 return MCDisassembler::Fail;
137
138 // Call auto-generated decoder function
139 Result =
140 decodeInstruction(DecoderTableLanai32, Instr, Insn, Address, this, STI);
141
142 if (Result != MCDisassembler::Fail) {
143 PostOperandDecodeAdjust(Instr, Insn);
144 Size = 4;
145 return Result;
146 }
147
148 return MCDisassembler::Fail;
149}
150
151static const unsigned GPRDecoderTable[] = {
152 Lanai::R0, Lanai::R1, Lanai::PC, Lanai::R3, Lanai::SP, Lanai::FP,
153 Lanai::R6, Lanai::R7, Lanai::RV, Lanai::R9, Lanai::RR1, Lanai::RR2,
154 Lanai::R12, Lanai::R13, Lanai::R14, Lanai::RCA, Lanai::R16, Lanai::R17,
155 Lanai::R18, Lanai::R19, Lanai::R20, Lanai::R21, Lanai::R22, Lanai::R23,
156 Lanai::R24, Lanai::R25, Lanai::R26, Lanai::R27, Lanai::R28, Lanai::R29,
157 Lanai::R30, Lanai::R31};
158
159DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
160 uint64_t Address, const void *Decoder) {
161 if (RegNo > 31)
162 return MCDisassembler::Fail;
163
164 unsigned Reg = GPRDecoderTable[RegNo];
165 Inst.addOperand(MCOperand::createReg(Reg));
166 return MCDisassembler::Success;
167}
168
169static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
170 uint64_t Address, const void *Decoder) {
171 // RI memory values encoded using 23 bits:
172 // 5 bit register, 16 bit constant
173 unsigned Register = (Insn >> 18) & 0x1f;
174 Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
175 unsigned Offset = (Insn & 0xffff);
176 Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
177
178 return MCDisassembler::Success;
179}
180
181static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
182 uint64_t Address, const void *Decoder) {
183 // RR memory values encoded using 20 bits:
184 // 5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
185 unsigned Register = (Insn >> 15) & 0x1f;
186 Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
187 Register = (Insn >> 10) & 0x1f;
188 Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
189
190 return MCDisassembler::Success;
191}
192
193static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
194 uint64_t Address, const void *Decoder) {
195 // RI memory values encoded using 17 bits:
196 // 5 bit register, 10 bit constant
197 unsigned Register = (Insn >> 12) & 0x1f;
198 Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
199 unsigned Offset = (Insn & 0x3ff);
200 Inst.addOperand(MCOperand::createImm(SignExtend32<10>(Offset)));
201
202 return MCDisassembler::Success;
203}
204
205static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
206 uint64_t Address, uint64_t Offset,
207 uint64_t Width, MCInst &MI,
208 const void *Decoder) {
209 const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
210 return Dis->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
211 Width);
212}
213
214static DecodeStatus decodeBranch(MCInst &MI, unsigned Insn, uint64_t Address,
215 const void *Decoder) {
216 if (!tryAddingSymbolicOperand(Insn + Address, false, Address, 2, 23, MI,
217 Decoder))
218 MI.addOperand(MCOperand::createImm(Insn));
219 return MCDisassembler::Success;
220}
221
222static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
223 uint64_t Address, const void *Decoder) {
224 unsigned Offset = (Insn & 0xffff);
225 Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
226
227 return MCDisassembler::Success;
228}