xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
1 //===-- RISCVDisassembler.cpp - Disassembler for RISCV --------------------===//
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 implements the RISCVDisassembler class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "MCTargetDesc/RISCVMCTargetDesc.h"
14 #include "TargetInfo/RISCVTargetInfo.h"
15 #include "Utils/RISCVBaseInfo.h"
16 #include "llvm/CodeGen/Register.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
19 #include "llvm/MC/MCFixedLenDisassembler.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/TargetRegistry.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "riscv-disassembler"
29 
30 typedef MCDisassembler::DecodeStatus DecodeStatus;
31 
32 namespace {
33 class RISCVDisassembler : public MCDisassembler {
34 
35 public:
36   RISCVDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
37       : MCDisassembler(STI, Ctx) {}
38 
39   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
40                               ArrayRef<uint8_t> Bytes, uint64_t Address,
41                               raw_ostream &VStream,
42                               raw_ostream &CStream) const override;
43 };
44 } // end anonymous namespace
45 
46 static MCDisassembler *createRISCVDisassembler(const Target &T,
47                                                const MCSubtargetInfo &STI,
48                                                MCContext &Ctx) {
49   return new RISCVDisassembler(STI, Ctx);
50 }
51 
52 extern "C" void LLVMInitializeRISCVDisassembler() {
53   // Register the disassembler for each target.
54   TargetRegistry::RegisterMCDisassembler(getTheRISCV32Target(),
55                                          createRISCVDisassembler);
56   TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
57                                          createRISCVDisassembler);
58 }
59 
60 static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
61                                            uint64_t Address,
62                                            const void *Decoder) {
63   const FeatureBitset &FeatureBits =
64       static_cast<const MCDisassembler *>(Decoder)
65           ->getSubtargetInfo()
66           .getFeatureBits();
67   bool IsRV32E = FeatureBits[RISCV::FeatureRV32E];
68 
69   if (RegNo >= 32 || (IsRV32E && RegNo >= 16))
70     return MCDisassembler::Fail;
71 
72   Register Reg = RISCV::X0 + RegNo;
73   Inst.addOperand(MCOperand::createReg(Reg));
74   return MCDisassembler::Success;
75 }
76 
77 static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
78                                              uint64_t Address,
79                                              const void *Decoder) {
80   if (RegNo >= 32)
81     return MCDisassembler::Fail;
82 
83   Register Reg = RISCV::F0_F + RegNo;
84   Inst.addOperand(MCOperand::createReg(Reg));
85   return MCDisassembler::Success;
86 }
87 
88 static DecodeStatus DecodeFPR32CRegisterClass(MCInst &Inst, uint64_t RegNo,
89                                               uint64_t Address,
90                                               const void *Decoder) {
91   if (RegNo >= 8) {
92     return MCDisassembler::Fail;
93   }
94   Register Reg = RISCV::F8_F + RegNo;
95   Inst.addOperand(MCOperand::createReg(Reg));
96   return MCDisassembler::Success;
97 }
98 
99 static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,
100                                              uint64_t Address,
101                                              const void *Decoder) {
102   if (RegNo >= 32)
103     return MCDisassembler::Fail;
104 
105   Register Reg = RISCV::F0_D + RegNo;
106   Inst.addOperand(MCOperand::createReg(Reg));
107   return MCDisassembler::Success;
108 }
109 
110 static DecodeStatus DecodeFPR64CRegisterClass(MCInst &Inst, uint64_t RegNo,
111                                               uint64_t Address,
112                                               const void *Decoder) {
113   if (RegNo >= 8) {
114     return MCDisassembler::Fail;
115   }
116   Register Reg = RISCV::F8_D + RegNo;
117   Inst.addOperand(MCOperand::createReg(Reg));
118   return MCDisassembler::Success;
119 }
120 
121 static DecodeStatus DecodeGPRNoX0RegisterClass(MCInst &Inst, uint64_t RegNo,
122                                                uint64_t Address,
123                                                const void *Decoder) {
124   if (RegNo == 0) {
125     return MCDisassembler::Fail;
126   }
127 
128   return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
129 }
130 
131 static DecodeStatus DecodeGPRNoX0X2RegisterClass(MCInst &Inst, uint64_t RegNo,
132                                                  uint64_t Address,
133                                                  const void *Decoder) {
134   if (RegNo == 2) {
135     return MCDisassembler::Fail;
136   }
137 
138   return DecodeGPRNoX0RegisterClass(Inst, RegNo, Address, Decoder);
139 }
140 
141 static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
142                                             uint64_t Address,
143                                             const void *Decoder) {
144   if (RegNo >= 8)
145     return MCDisassembler::Fail;
146 
147   Register Reg = RISCV::X8 + RegNo;
148   Inst.addOperand(MCOperand::createReg(Reg));
149   return MCDisassembler::Success;
150 }
151 
152 // Add implied SP operand for instructions *SP compressed instructions. The SP
153 // operand isn't explicitly encoded in the instruction.
154 static void addImplySP(MCInst &Inst, int64_t Address, const void *Decoder) {
155   if (Inst.getOpcode() == RISCV::C_LWSP || Inst.getOpcode() == RISCV::C_SWSP ||
156       Inst.getOpcode() == RISCV::C_LDSP || Inst.getOpcode() == RISCV::C_SDSP ||
157       Inst.getOpcode() == RISCV::C_FLWSP ||
158       Inst.getOpcode() == RISCV::C_FSWSP ||
159       Inst.getOpcode() == RISCV::C_FLDSP ||
160       Inst.getOpcode() == RISCV::C_FSDSP ||
161       Inst.getOpcode() == RISCV::C_ADDI4SPN) {
162     DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
163   }
164   if (Inst.getOpcode() == RISCV::C_ADDI16SP) {
165     DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
166     DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
167   }
168 }
169 
170 template <unsigned N>
171 static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
172                                       int64_t Address, const void *Decoder) {
173   assert(isUInt<N>(Imm) && "Invalid immediate");
174   addImplySP(Inst, Address, Decoder);
175   Inst.addOperand(MCOperand::createImm(Imm));
176   return MCDisassembler::Success;
177 }
178 
179 template <unsigned N>
180 static DecodeStatus decodeUImmNonZeroOperand(MCInst &Inst, uint64_t Imm,
181                                              int64_t Address,
182                                              const void *Decoder) {
183   if (Imm == 0)
184     return MCDisassembler::Fail;
185   return decodeUImmOperand<N>(Inst, Imm, Address, Decoder);
186 }
187 
188 template <unsigned N>
189 static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
190                                       int64_t Address, const void *Decoder) {
191   assert(isUInt<N>(Imm) && "Invalid immediate");
192   addImplySP(Inst, Address, Decoder);
193   // Sign-extend the number in the bottom N bits of Imm
194   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
195   return MCDisassembler::Success;
196 }
197 
198 template <unsigned N>
199 static DecodeStatus decodeSImmNonZeroOperand(MCInst &Inst, uint64_t Imm,
200                                              int64_t Address,
201                                              const void *Decoder) {
202   if (Imm == 0)
203     return MCDisassembler::Fail;
204   return decodeSImmOperand<N>(Inst, Imm, Address, Decoder);
205 }
206 
207 template <unsigned N>
208 static DecodeStatus decodeSImmOperandAndLsl1(MCInst &Inst, uint64_t Imm,
209                                              int64_t Address,
210                                              const void *Decoder) {
211   assert(isUInt<N>(Imm) && "Invalid immediate");
212   // Sign-extend the number in the bottom N bits of Imm after accounting for
213   // the fact that the N bit immediate is stored in N-1 bits (the LSB is
214   // always zero)
215   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm << 1)));
216   return MCDisassembler::Success;
217 }
218 
219 static DecodeStatus decodeCLUIImmOperand(MCInst &Inst, uint64_t Imm,
220                                          int64_t Address,
221                                          const void *Decoder) {
222   assert(isUInt<6>(Imm) && "Invalid immediate");
223   if (Imm > 31) {
224     Imm = (SignExtend64<6>(Imm) & 0xfffff);
225   }
226   Inst.addOperand(MCOperand::createImm(Imm));
227   return MCDisassembler::Success;
228 }
229 
230 static DecodeStatus decodeFRMArg(MCInst &Inst, uint64_t Imm,
231                                  int64_t Address,
232                                  const void *Decoder) {
233   assert(isUInt<3>(Imm) && "Invalid immediate");
234   if (!llvm::RISCVFPRndMode::isValidRoundingMode(Imm))
235     return MCDisassembler::Fail;
236 
237   Inst.addOperand(MCOperand::createImm(Imm));
238   return MCDisassembler::Success;
239 }
240 
241 static DecodeStatus decodeRVCInstrSImm(MCInst &Inst, unsigned Insn,
242                                        uint64_t Address, const void *Decoder);
243 
244 static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, unsigned Insn,
245                                          uint64_t Address, const void *Decoder);
246 
247 static DecodeStatus decodeRVCInstrRdRs1UImm(MCInst &Inst, unsigned Insn,
248                                             uint64_t Address,
249                                             const void *Decoder);
250 
251 static DecodeStatus decodeRVCInstrRdRs2(MCInst &Inst, unsigned Insn,
252                                         uint64_t Address, const void *Decoder);
253 
254 static DecodeStatus decodeRVCInstrRdRs1Rs2(MCInst &Inst, unsigned Insn,
255                                            uint64_t Address,
256                                            const void *Decoder);
257 
258 #include "RISCVGenDisassemblerTables.inc"
259 
260 static DecodeStatus decodeRVCInstrSImm(MCInst &Inst, unsigned Insn,
261                                        uint64_t Address, const void *Decoder) {
262   uint64_t SImm6 =
263       fieldFromInstruction(Insn, 12, 1) << 5 | fieldFromInstruction(Insn, 2, 5);
264   DecodeStatus Result = decodeSImmOperand<6>(Inst, SImm6, Address, Decoder);
265   (void)Result;
266   assert(Result == MCDisassembler::Success && "Invalid immediate");
267   return MCDisassembler::Success;
268 }
269 
270 static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, unsigned Insn,
271                                          uint64_t Address,
272                                          const void *Decoder) {
273   DecodeGPRRegisterClass(Inst, 0, Address, Decoder);
274   uint64_t SImm6 =
275       fieldFromInstruction(Insn, 12, 1) << 5 | fieldFromInstruction(Insn, 2, 5);
276   DecodeStatus Result = decodeSImmOperand<6>(Inst, SImm6, Address, Decoder);
277   (void)Result;
278   assert(Result == MCDisassembler::Success && "Invalid immediate");
279   return MCDisassembler::Success;
280 }
281 
282 static DecodeStatus decodeRVCInstrRdRs1UImm(MCInst &Inst, unsigned Insn,
283                                             uint64_t Address,
284                                             const void *Decoder) {
285   DecodeGPRRegisterClass(Inst, 0, Address, Decoder);
286   Inst.addOperand(Inst.getOperand(0));
287   uint64_t UImm6 =
288       fieldFromInstruction(Insn, 12, 1) << 5 | fieldFromInstruction(Insn, 2, 5);
289   DecodeStatus Result = decodeUImmOperand<6>(Inst, UImm6, Address, Decoder);
290   (void)Result;
291   assert(Result == MCDisassembler::Success && "Invalid immediate");
292   return MCDisassembler::Success;
293 }
294 
295 static DecodeStatus decodeRVCInstrRdRs2(MCInst &Inst, unsigned Insn,
296                                         uint64_t Address, const void *Decoder) {
297   unsigned Rd = fieldFromInstruction(Insn, 7, 5);
298   unsigned Rs2 = fieldFromInstruction(Insn, 2, 5);
299   DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
300   DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
301   return MCDisassembler::Success;
302 }
303 
304 static DecodeStatus decodeRVCInstrRdRs1Rs2(MCInst &Inst, unsigned Insn,
305                                            uint64_t Address,
306                                            const void *Decoder) {
307   unsigned Rd = fieldFromInstruction(Insn, 7, 5);
308   unsigned Rs2 = fieldFromInstruction(Insn, 2, 5);
309   DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
310   Inst.addOperand(Inst.getOperand(0));
311   DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
312   return MCDisassembler::Success;
313 }
314 
315 DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
316                                                ArrayRef<uint8_t> Bytes,
317                                                uint64_t Address,
318                                                raw_ostream &OS,
319                                                raw_ostream &CS) const {
320   // TODO: This will need modification when supporting instruction set
321   // extensions with instructions > 32-bits (up to 176 bits wide).
322   uint32_t Insn;
323   DecodeStatus Result;
324 
325   // It's a 32 bit instruction if bit 0 and 1 are 1.
326   if ((Bytes[0] & 0x3) == 0x3) {
327     if (Bytes.size() < 4) {
328       Size = 0;
329       return MCDisassembler::Fail;
330     }
331     Insn = support::endian::read32le(Bytes.data());
332     LLVM_DEBUG(dbgs() << "Trying RISCV32 table :\n");
333     Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI);
334     Size = 4;
335   } else {
336     if (Bytes.size() < 2) {
337       Size = 0;
338       return MCDisassembler::Fail;
339     }
340     Insn = support::endian::read16le(Bytes.data());
341 
342     if (!STI.getFeatureBits()[RISCV::Feature64Bit]) {
343       LLVM_DEBUG(
344           dbgs() << "Trying RISCV32Only_16 table (16-bit Instruction):\n");
345       // Calling the auto-generated decoder function.
346       Result = decodeInstruction(DecoderTableRISCV32Only_16, MI, Insn, Address,
347                                  this, STI);
348       if (Result != MCDisassembler::Fail) {
349         Size = 2;
350         return Result;
351       }
352     }
353 
354     LLVM_DEBUG(dbgs() << "Trying RISCV_C table (16-bit Instruction):\n");
355     // Calling the auto-generated decoder function.
356     Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
357     Size = 2;
358   }
359 
360   return Result;
361 }
362