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