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