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