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