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