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
29 using namespace llvm;
30
31 typedef MCDisassembler::DecodeStatus DecodeStatus;
32
createLanaiDisassembler(const Target &,const MCSubtargetInfo & STI,MCContext & Ctx)33 static MCDisassembler *createLanaiDisassembler(const Target & /*T*/,
34 const MCSubtargetInfo &STI,
35 MCContext &Ctx) {
36 return new LanaiDisassembler(STI, Ctx);
37 }
38
39 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeLanaiDisassembler()40 LLVMInitializeLanaiDisassembler() {
41 // Register the disassembler
42 TargetRegistry::RegisterMCDisassembler(getTheLanaiTarget(),
43 createLanaiDisassembler);
44 }
45
LanaiDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)46 LanaiDisassembler::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.
51 static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
52 uint64_t Address,
53 const MCDisassembler *Decoder);
54
55 static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
56 uint64_t Address,
57 const MCDisassembler *Decoder);
58
59 static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
60 uint64_t Address,
61 const MCDisassembler *Decoder);
62
63 static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
64 uint64_t Address,
65 const MCDisassembler *Decoder);
66
67 static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
68 const MCDisassembler *Decoder);
69
70 static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
71 uint64_t Address,
72 const MCDisassembler *Decoder);
73
74 static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
75 uint64_t Address,
76 const MCDisassembler *Decoder);
77
78 #include "LanaiGenDisassemblerTables.inc"
79
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t & Size,uint32_t & Insn)80 static 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
PostOperandDecodeAdjust(MCInst & Instr,uint32_t Insn)95 static 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(Instr.getOpcode()))
100 PqShift = 16;
101 else if (isSPLSOpcode(Instr.getOpcode()))
102 PqShift = 10;
103 else if (isRRMOpcode(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(2).isReg()) {
118 Instr.getOperand(2).setReg(Lanai::R0);
119 }
120 if (Instr.getOperand(2).isImm())
121 Instr.getOperand(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(MCOperand::createImm(AluOp));
133 }
134 }
135
136 DecodeStatus
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream &) const137 LanaiDisassembler::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(DecoderTableLanai32, Instr, Insn, Address, 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
160 static 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
DecodeGPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t,const MCDisassembler *)168 DecodeStatus 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(MCOperand::createReg(Reg));
176 return MCDisassembler::Success;
177 }
178
decodeRiMemoryValue(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)179 static 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(MCOperand::createReg(GPRDecoderTable[Register]));
186 unsigned Offset = (Insn & 0xffff);
187 Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
188
189 return MCDisassembler::Success;
190 }
191
decodeRrMemoryValue(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)192 static 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(MCOperand::createReg(GPRDecoderTable[Register]));
199 Register = (Insn >> 10) & 0x1f;
200 Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
201
202 return MCDisassembler::Success;
203 }
204
decodeSplsValue(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)205 static 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(MCOperand::createReg(GPRDecoderTable[Register]));
212 unsigned Offset = (Insn & 0x3ff);
213 Inst.addOperand(MCOperand::createImm(SignExtend32<10>(Offset)));
214
215 return MCDisassembler::Success;
216 }
217
tryAddingSymbolicOperand(int64_t Value,bool IsBranch,uint64_t Address,uint64_t Offset,uint64_t Width,MCInst & MI,const MCDisassembler * Decoder)218 static 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(MI, Value, Address, IsBranch, Offset,
223 Width, /*InstSize=*/0);
224 }
225
decodeBranch(MCInst & MI,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)226 static DecodeStatus decodeBranch(MCInst &MI, unsigned Insn, uint64_t Address,
227 const MCDisassembler *Decoder) {
228 if (!tryAddingSymbolicOperand(Insn + Address, false, Address, 2, 23, MI,
229 Decoder))
230 MI.addOperand(MCOperand::createImm(Insn));
231 return MCDisassembler::Success;
232 }
233
decodeShiftImm(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)234 static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
235 uint64_t Address,
236 const MCDisassembler *Decoder) {
237 unsigned Offset = (Insn & 0xffff);
238 Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
239
240 return MCDisassembler::Success;
241 }
242
decodePredicateOperand(MCInst & Inst,unsigned Val,uint64_t Address,const MCDisassembler * Decoder)243 static 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(MCOperand::createImm(Val));
249 return MCDisassembler::Success;
250 }
251