1 //===-- RISCVDisassembler.cpp - Disassembler for RISCV --------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the RISCVDisassembler class.
11 //===----------------------------------------------------------------------===//
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"
28 #define DEBUG_TYPE "riscv-disassembler"
30 typedef MCDisassembler::DecodeStatus DecodeStatus
;
33 class RISCVDisassembler
: public MCDisassembler
{
36 RISCVDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
37 : MCDisassembler(STI
, Ctx
) {}
39 DecodeStatus
getInstruction(MCInst
&Instr
, uint64_t &Size
,
40 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
42 raw_ostream
&CStream
) const override
;
44 } // end anonymous namespace
46 static MCDisassembler
*createRISCVDisassembler(const Target
&T
,
47 const MCSubtargetInfo
&STI
,
49 return new RISCVDisassembler(STI
, Ctx
);
52 extern "C" void LLVMInitializeRISCVDisassembler() {
53 // Register the disassembler for each target.
54 TargetRegistry::RegisterMCDisassembler(getTheRISCV32Target(),
55 createRISCVDisassembler
);
56 TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
57 createRISCVDisassembler
);
60 static const Register GPRDecoderTable
[] = {
61 RISCV::X0
, RISCV::X1
, RISCV::X2
, RISCV::X3
,
62 RISCV::X4
, RISCV::X5
, RISCV::X6
, RISCV::X7
,
63 RISCV::X8
, RISCV::X9
, RISCV::X10
, RISCV::X11
,
64 RISCV::X12
, RISCV::X13
, RISCV::X14
, RISCV::X15
,
65 RISCV::X16
, RISCV::X17
, RISCV::X18
, RISCV::X19
,
66 RISCV::X20
, RISCV::X21
, RISCV::X22
, RISCV::X23
,
67 RISCV::X24
, RISCV::X25
, RISCV::X26
, RISCV::X27
,
68 RISCV::X28
, RISCV::X29
, RISCV::X30
, RISCV::X31
71 static DecodeStatus
DecodeGPRRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
73 const void *Decoder
) {
74 const FeatureBitset
&FeatureBits
=
75 static_cast<const MCDisassembler
*>(Decoder
)
78 bool IsRV32E
= FeatureBits
[RISCV::FeatureRV32E
];
80 if (RegNo
> array_lengthof(GPRDecoderTable
) || (IsRV32E
&& RegNo
> 15))
81 return MCDisassembler::Fail
;
83 // We must define our own mapping from RegNo to register identifier.
84 // Accessing index RegNo in the register class will work in the case that
85 // registers were added in ascending order, but not in general.
86 Register Reg
= GPRDecoderTable
[RegNo
];
87 Inst
.addOperand(MCOperand::createReg(Reg
));
88 return MCDisassembler::Success
;
91 static const Register FPR32DecoderTable
[] = {
92 RISCV::F0_32
, RISCV::F1_32
, RISCV::F2_32
, RISCV::F3_32
,
93 RISCV::F4_32
, RISCV::F5_32
, RISCV::F6_32
, RISCV::F7_32
,
94 RISCV::F8_32
, RISCV::F9_32
, RISCV::F10_32
, RISCV::F11_32
,
95 RISCV::F12_32
, RISCV::F13_32
, RISCV::F14_32
, RISCV::F15_32
,
96 RISCV::F16_32
, RISCV::F17_32
, RISCV::F18_32
, RISCV::F19_32
,
97 RISCV::F20_32
, RISCV::F21_32
, RISCV::F22_32
, RISCV::F23_32
,
98 RISCV::F24_32
, RISCV::F25_32
, RISCV::F26_32
, RISCV::F27_32
,
99 RISCV::F28_32
, RISCV::F29_32
, RISCV::F30_32
, RISCV::F31_32
102 static DecodeStatus
DecodeFPR32RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
104 const void *Decoder
) {
105 if (RegNo
> array_lengthof(FPR32DecoderTable
))
106 return MCDisassembler::Fail
;
108 // We must define our own mapping from RegNo to register identifier.
109 // Accessing index RegNo in the register class will work in the case that
110 // registers were added in ascending order, but not in general.
111 Register Reg
= FPR32DecoderTable
[RegNo
];
112 Inst
.addOperand(MCOperand::createReg(Reg
));
113 return MCDisassembler::Success
;
116 static DecodeStatus
DecodeFPR32CRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
118 const void *Decoder
) {
120 return MCDisassembler::Fail
;
122 Register Reg
= FPR32DecoderTable
[RegNo
+ 8];
123 Inst
.addOperand(MCOperand::createReg(Reg
));
124 return MCDisassembler::Success
;
127 static const Register FPR64DecoderTable
[] = {
128 RISCV::F0_64
, RISCV::F1_64
, RISCV::F2_64
, RISCV::F3_64
,
129 RISCV::F4_64
, RISCV::F5_64
, RISCV::F6_64
, RISCV::F7_64
,
130 RISCV::F8_64
, RISCV::F9_64
, RISCV::F10_64
, RISCV::F11_64
,
131 RISCV::F12_64
, RISCV::F13_64
, RISCV::F14_64
, RISCV::F15_64
,
132 RISCV::F16_64
, RISCV::F17_64
, RISCV::F18_64
, RISCV::F19_64
,
133 RISCV::F20_64
, RISCV::F21_64
, RISCV::F22_64
, RISCV::F23_64
,
134 RISCV::F24_64
, RISCV::F25_64
, RISCV::F26_64
, RISCV::F27_64
,
135 RISCV::F28_64
, RISCV::F29_64
, RISCV::F30_64
, RISCV::F31_64
138 static DecodeStatus
DecodeFPR64RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
140 const void *Decoder
) {
141 if (RegNo
> array_lengthof(FPR64DecoderTable
))
142 return MCDisassembler::Fail
;
144 // We must define our own mapping from RegNo to register identifier.
145 // Accessing index RegNo in the register class will work in the case that
146 // registers were added in ascending order, but not in general.
147 Register Reg
= FPR64DecoderTable
[RegNo
];
148 Inst
.addOperand(MCOperand::createReg(Reg
));
149 return MCDisassembler::Success
;
152 static DecodeStatus
DecodeFPR64CRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
154 const void *Decoder
) {
156 return MCDisassembler::Fail
;
158 Register Reg
= FPR64DecoderTable
[RegNo
+ 8];
159 Inst
.addOperand(MCOperand::createReg(Reg
));
160 return MCDisassembler::Success
;
163 static DecodeStatus
DecodeGPRNoX0RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
165 const void *Decoder
) {
167 return MCDisassembler::Fail
;
170 return DecodeGPRRegisterClass(Inst
, RegNo
, Address
, Decoder
);
173 static DecodeStatus
DecodeGPRNoX0X2RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
175 const void *Decoder
) {
177 return MCDisassembler::Fail
;
180 return DecodeGPRNoX0RegisterClass(Inst
, RegNo
, Address
, Decoder
);
183 static DecodeStatus
DecodeGPRCRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
185 const void *Decoder
) {
187 return MCDisassembler::Fail
;
189 Register Reg
= GPRDecoderTable
[RegNo
+ 8];
190 Inst
.addOperand(MCOperand::createReg(Reg
));
191 return MCDisassembler::Success
;
194 // Add implied SP operand for instructions *SP compressed instructions. The SP
195 // operand isn't explicitly encoded in the instruction.
196 static void addImplySP(MCInst
&Inst
, int64_t Address
, const void *Decoder
) {
197 if (Inst
.getOpcode() == RISCV::C_LWSP
|| Inst
.getOpcode() == RISCV::C_SWSP
||
198 Inst
.getOpcode() == RISCV::C_LDSP
|| Inst
.getOpcode() == RISCV::C_SDSP
||
199 Inst
.getOpcode() == RISCV::C_FLWSP
||
200 Inst
.getOpcode() == RISCV::C_FSWSP
||
201 Inst
.getOpcode() == RISCV::C_FLDSP
||
202 Inst
.getOpcode() == RISCV::C_FSDSP
||
203 Inst
.getOpcode() == RISCV::C_ADDI4SPN
) {
204 DecodeGPRRegisterClass(Inst
, 2, Address
, Decoder
);
206 if (Inst
.getOpcode() == RISCV::C_ADDI16SP
) {
207 DecodeGPRRegisterClass(Inst
, 2, Address
, Decoder
);
208 DecodeGPRRegisterClass(Inst
, 2, Address
, Decoder
);
212 template <unsigned N
>
213 static DecodeStatus
decodeUImmOperand(MCInst
&Inst
, uint64_t Imm
,
214 int64_t Address
, const void *Decoder
) {
215 assert(isUInt
<N
>(Imm
) && "Invalid immediate");
216 addImplySP(Inst
, Address
, Decoder
);
217 Inst
.addOperand(MCOperand::createImm(Imm
));
218 return MCDisassembler::Success
;
221 template <unsigned N
>
222 static DecodeStatus
decodeUImmNonZeroOperand(MCInst
&Inst
, uint64_t Imm
,
224 const void *Decoder
) {
226 return MCDisassembler::Fail
;
227 return decodeUImmOperand
<N
>(Inst
, Imm
, Address
, Decoder
);
230 template <unsigned N
>
231 static DecodeStatus
decodeSImmOperand(MCInst
&Inst
, uint64_t Imm
,
232 int64_t Address
, const void *Decoder
) {
233 assert(isUInt
<N
>(Imm
) && "Invalid immediate");
234 addImplySP(Inst
, Address
, Decoder
);
235 // Sign-extend the number in the bottom N bits of Imm
236 Inst
.addOperand(MCOperand::createImm(SignExtend64
<N
>(Imm
)));
237 return MCDisassembler::Success
;
240 template <unsigned N
>
241 static DecodeStatus
decodeSImmNonZeroOperand(MCInst
&Inst
, uint64_t Imm
,
243 const void *Decoder
) {
245 return MCDisassembler::Fail
;
246 return decodeSImmOperand
<N
>(Inst
, Imm
, Address
, Decoder
);
249 template <unsigned N
>
250 static DecodeStatus
decodeSImmOperandAndLsl1(MCInst
&Inst
, uint64_t Imm
,
252 const void *Decoder
) {
253 assert(isUInt
<N
>(Imm
) && "Invalid immediate");
254 // Sign-extend the number in the bottom N bits of Imm after accounting for
255 // the fact that the N bit immediate is stored in N-1 bits (the LSB is
257 Inst
.addOperand(MCOperand::createImm(SignExtend64
<N
>(Imm
<< 1)));
258 return MCDisassembler::Success
;
261 static DecodeStatus
decodeCLUIImmOperand(MCInst
&Inst
, uint64_t Imm
,
263 const void *Decoder
) {
264 assert(isUInt
<6>(Imm
) && "Invalid immediate");
266 Imm
= (SignExtend64
<6>(Imm
) & 0xfffff);
268 Inst
.addOperand(MCOperand::createImm(Imm
));
269 return MCDisassembler::Success
;
272 static DecodeStatus
decodeFRMArg(MCInst
&Inst
, uint64_t Imm
,
274 const void *Decoder
) {
275 assert(isUInt
<3>(Imm
) && "Invalid immediate");
276 if (!llvm::RISCVFPRndMode::isValidRoundingMode(Imm
))
277 return MCDisassembler::Fail
;
279 Inst
.addOperand(MCOperand::createImm(Imm
));
280 return MCDisassembler::Success
;
283 static DecodeStatus
decodeRVCInstrSImm(MCInst
&Inst
, unsigned Insn
,
284 uint64_t Address
, const void *Decoder
);
286 static DecodeStatus
decodeRVCInstrRdSImm(MCInst
&Inst
, unsigned Insn
,
287 uint64_t Address
, const void *Decoder
);
289 static DecodeStatus
decodeRVCInstrRdRs1UImm(MCInst
&Inst
, unsigned Insn
,
291 const void *Decoder
);
293 static DecodeStatus
decodeRVCInstrRdRs2(MCInst
&Inst
, unsigned Insn
,
294 uint64_t Address
, const void *Decoder
);
296 static DecodeStatus
decodeRVCInstrRdRs1Rs2(MCInst
&Inst
, unsigned Insn
,
298 const void *Decoder
);
300 #include "RISCVGenDisassemblerTables.inc"
302 static DecodeStatus
decodeRVCInstrSImm(MCInst
&Inst
, unsigned Insn
,
303 uint64_t Address
, const void *Decoder
) {
305 fieldFromInstruction(Insn
, 12, 1) << 5 | fieldFromInstruction(Insn
, 2, 5);
306 DecodeStatus Result
= decodeSImmOperand
<6>(Inst
, SImm6
, Address
, Decoder
);
308 assert(Result
== MCDisassembler::Success
&& "Invalid immediate");
309 return MCDisassembler::Success
;
312 static DecodeStatus
decodeRVCInstrRdSImm(MCInst
&Inst
, unsigned Insn
,
314 const void *Decoder
) {
315 DecodeGPRRegisterClass(Inst
, 0, Address
, Decoder
);
317 fieldFromInstruction(Insn
, 12, 1) << 5 | fieldFromInstruction(Insn
, 2, 5);
318 DecodeStatus Result
= decodeSImmOperand
<6>(Inst
, SImm6
, Address
, Decoder
);
320 assert(Result
== MCDisassembler::Success
&& "Invalid immediate");
321 return MCDisassembler::Success
;
324 static DecodeStatus
decodeRVCInstrRdRs1UImm(MCInst
&Inst
, unsigned Insn
,
326 const void *Decoder
) {
327 DecodeGPRRegisterClass(Inst
, 0, Address
, Decoder
);
328 Inst
.addOperand(Inst
.getOperand(0));
330 fieldFromInstruction(Insn
, 12, 1) << 5 | fieldFromInstruction(Insn
, 2, 5);
331 DecodeStatus Result
= decodeUImmOperand
<6>(Inst
, UImm6
, Address
, Decoder
);
333 assert(Result
== MCDisassembler::Success
&& "Invalid immediate");
334 return MCDisassembler::Success
;
337 static DecodeStatus
decodeRVCInstrRdRs2(MCInst
&Inst
, unsigned Insn
,
338 uint64_t Address
, const void *Decoder
) {
339 unsigned Rd
= fieldFromInstruction(Insn
, 7, 5);
340 unsigned Rs2
= fieldFromInstruction(Insn
, 2, 5);
341 DecodeGPRRegisterClass(Inst
, Rd
, Address
, Decoder
);
342 DecodeGPRRegisterClass(Inst
, Rs2
, Address
, Decoder
);
343 return MCDisassembler::Success
;
346 static DecodeStatus
decodeRVCInstrRdRs1Rs2(MCInst
&Inst
, unsigned Insn
,
348 const void *Decoder
) {
349 unsigned Rd
= fieldFromInstruction(Insn
, 7, 5);
350 unsigned Rs2
= fieldFromInstruction(Insn
, 2, 5);
351 DecodeGPRRegisterClass(Inst
, Rd
, Address
, Decoder
);
352 Inst
.addOperand(Inst
.getOperand(0));
353 DecodeGPRRegisterClass(Inst
, Rs2
, Address
, Decoder
);
354 return MCDisassembler::Success
;
357 DecodeStatus
RISCVDisassembler::getInstruction(MCInst
&MI
, uint64_t &Size
,
358 ArrayRef
<uint8_t> Bytes
,
361 raw_ostream
&CS
) const {
362 // TODO: This will need modification when supporting instruction set
363 // extensions with instructions > 32-bits (up to 176 bits wide).
367 // It's a 32 bit instruction if bit 0 and 1 are 1.
368 if ((Bytes
[0] & 0x3) == 0x3) {
369 if (Bytes
.size() < 4) {
371 return MCDisassembler::Fail
;
373 Insn
= support::endian::read32le(Bytes
.data());
374 LLVM_DEBUG(dbgs() << "Trying RISCV32 table :\n");
375 Result
= decodeInstruction(DecoderTable32
, MI
, Insn
, Address
, this, STI
);
378 if (Bytes
.size() < 2) {
380 return MCDisassembler::Fail
;
382 Insn
= support::endian::read16le(Bytes
.data());
384 if (!STI
.getFeatureBits()[RISCV::Feature64Bit
]) {
386 dbgs() << "Trying RISCV32Only_16 table (16-bit Instruction):\n");
387 // Calling the auto-generated decoder function.
388 Result
= decodeInstruction(DecoderTableRISCV32Only_16
, MI
, Insn
, Address
,
390 if (Result
!= MCDisassembler::Fail
) {
396 LLVM_DEBUG(dbgs() << "Trying RISCV_C table (16-bit Instruction):\n");
397 // Calling the auto-generated decoder function.
398 Result
= decodeInstruction(DecoderTable16
, MI
, Insn
, Address
, this, STI
);