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