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