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