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