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