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 DecodeStatus
DecodeGPRRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
62 const void *Decoder
) {
63 const FeatureBitset
&FeatureBits
=
64 static_cast<const MCDisassembler
*>(Decoder
)
67 bool IsRV32E
= FeatureBits
[RISCV::FeatureRV32E
];
69 if (RegNo
>= 32 || (IsRV32E
&& RegNo
>= 16))
70 return MCDisassembler::Fail
;
72 Register Reg
= RISCV::X0
+ RegNo
;
73 Inst
.addOperand(MCOperand::createReg(Reg
));
74 return MCDisassembler::Success
;
77 static DecodeStatus
DecodeFPR32RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
79 const void *Decoder
) {
81 return MCDisassembler::Fail
;
83 Register Reg
= RISCV::F0_F
+ RegNo
;
84 Inst
.addOperand(MCOperand::createReg(Reg
));
85 return MCDisassembler::Success
;
88 static DecodeStatus
DecodeFPR32CRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
90 const void *Decoder
) {
92 return MCDisassembler::Fail
;
94 Register Reg
= RISCV::F8_F
+ RegNo
;
95 Inst
.addOperand(MCOperand::createReg(Reg
));
96 return MCDisassembler::Success
;
99 static DecodeStatus
DecodeFPR64RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
101 const void *Decoder
) {
103 return MCDisassembler::Fail
;
105 Register Reg
= RISCV::F0_D
+ RegNo
;
106 Inst
.addOperand(MCOperand::createReg(Reg
));
107 return MCDisassembler::Success
;
110 static DecodeStatus
DecodeFPR64CRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
112 const void *Decoder
) {
114 return MCDisassembler::Fail
;
116 Register Reg
= RISCV::F8_D
+ RegNo
;
117 Inst
.addOperand(MCOperand::createReg(Reg
));
118 return MCDisassembler::Success
;
121 static DecodeStatus
DecodeGPRNoX0RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
123 const void *Decoder
) {
125 return MCDisassembler::Fail
;
128 return DecodeGPRRegisterClass(Inst
, RegNo
, Address
, Decoder
);
131 static DecodeStatus
DecodeGPRNoX0X2RegisterClass(MCInst
&Inst
, uint64_t RegNo
,
133 const void *Decoder
) {
135 return MCDisassembler::Fail
;
138 return DecodeGPRNoX0RegisterClass(Inst
, RegNo
, Address
, Decoder
);
141 static DecodeStatus
DecodeGPRCRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
143 const void *Decoder
) {
145 return MCDisassembler::Fail
;
147 Register Reg
= RISCV::X8
+ RegNo
;
148 Inst
.addOperand(MCOperand::createReg(Reg
));
149 return MCDisassembler::Success
;
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
);
164 if (Inst
.getOpcode() == RISCV::C_ADDI16SP
) {
165 DecodeGPRRegisterClass(Inst
, 2, Address
, Decoder
);
166 DecodeGPRRegisterClass(Inst
, 2, Address
, Decoder
);
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
;
179 template <unsigned N
>
180 static DecodeStatus
decodeUImmNonZeroOperand(MCInst
&Inst
, uint64_t Imm
,
182 const void *Decoder
) {
184 return MCDisassembler::Fail
;
185 return decodeUImmOperand
<N
>(Inst
, Imm
, Address
, Decoder
);
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
;
198 template <unsigned N
>
199 static DecodeStatus
decodeSImmNonZeroOperand(MCInst
&Inst
, uint64_t Imm
,
201 const void *Decoder
) {
203 return MCDisassembler::Fail
;
204 return decodeSImmOperand
<N
>(Inst
, Imm
, Address
, Decoder
);
207 template <unsigned N
>
208 static DecodeStatus
decodeSImmOperandAndLsl1(MCInst
&Inst
, uint64_t Imm
,
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
215 Inst
.addOperand(MCOperand::createImm(SignExtend64
<N
>(Imm
<< 1)));
216 return MCDisassembler::Success
;
219 static DecodeStatus
decodeCLUIImmOperand(MCInst
&Inst
, uint64_t Imm
,
221 const void *Decoder
) {
222 assert(isUInt
<6>(Imm
) && "Invalid immediate");
224 Imm
= (SignExtend64
<6>(Imm
) & 0xfffff);
226 Inst
.addOperand(MCOperand::createImm(Imm
));
227 return MCDisassembler::Success
;
230 static DecodeStatus
decodeFRMArg(MCInst
&Inst
, uint64_t Imm
,
232 const void *Decoder
) {
233 assert(isUInt
<3>(Imm
) && "Invalid immediate");
234 if (!llvm::RISCVFPRndMode::isValidRoundingMode(Imm
))
235 return MCDisassembler::Fail
;
237 Inst
.addOperand(MCOperand::createImm(Imm
));
238 return MCDisassembler::Success
;
241 static DecodeStatus
decodeRVCInstrSImm(MCInst
&Inst
, unsigned Insn
,
242 uint64_t Address
, const void *Decoder
);
244 static DecodeStatus
decodeRVCInstrRdSImm(MCInst
&Inst
, unsigned Insn
,
245 uint64_t Address
, const void *Decoder
);
247 static DecodeStatus
decodeRVCInstrRdRs1UImm(MCInst
&Inst
, unsigned Insn
,
249 const void *Decoder
);
251 static DecodeStatus
decodeRVCInstrRdRs2(MCInst
&Inst
, unsigned Insn
,
252 uint64_t Address
, const void *Decoder
);
254 static DecodeStatus
decodeRVCInstrRdRs1Rs2(MCInst
&Inst
, unsigned Insn
,
256 const void *Decoder
);
258 #include "RISCVGenDisassemblerTables.inc"
260 static DecodeStatus
decodeRVCInstrSImm(MCInst
&Inst
, unsigned Insn
,
261 uint64_t Address
, const void *Decoder
) {
263 fieldFromInstruction(Insn
, 12, 1) << 5 | fieldFromInstruction(Insn
, 2, 5);
264 DecodeStatus Result
= decodeSImmOperand
<6>(Inst
, SImm6
, Address
, Decoder
);
266 assert(Result
== MCDisassembler::Success
&& "Invalid immediate");
267 return MCDisassembler::Success
;
270 static DecodeStatus
decodeRVCInstrRdSImm(MCInst
&Inst
, unsigned Insn
,
272 const void *Decoder
) {
273 DecodeGPRRegisterClass(Inst
, 0, Address
, Decoder
);
275 fieldFromInstruction(Insn
, 12, 1) << 5 | fieldFromInstruction(Insn
, 2, 5);
276 DecodeStatus Result
= decodeSImmOperand
<6>(Inst
, SImm6
, Address
, Decoder
);
278 assert(Result
== MCDisassembler::Success
&& "Invalid immediate");
279 return MCDisassembler::Success
;
282 static DecodeStatus
decodeRVCInstrRdRs1UImm(MCInst
&Inst
, unsigned Insn
,
284 const void *Decoder
) {
285 DecodeGPRRegisterClass(Inst
, 0, Address
, Decoder
);
286 Inst
.addOperand(Inst
.getOperand(0));
288 fieldFromInstruction(Insn
, 12, 1) << 5 | fieldFromInstruction(Insn
, 2, 5);
289 DecodeStatus Result
= decodeUImmOperand
<6>(Inst
, UImm6
, Address
, Decoder
);
291 assert(Result
== MCDisassembler::Success
&& "Invalid immediate");
292 return MCDisassembler::Success
;
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
;
304 static DecodeStatus
decodeRVCInstrRdRs1Rs2(MCInst
&Inst
, unsigned Insn
,
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
;
315 DecodeStatus
RISCVDisassembler::getInstruction(MCInst
&MI
, uint64_t &Size
,
316 ArrayRef
<uint8_t> Bytes
,
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).
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) {
329 return MCDisassembler::Fail
;
331 Insn
= support::endian::read32le(Bytes
.data());
332 LLVM_DEBUG(dbgs() << "Trying RISCV32 table :\n");
333 Result
= decodeInstruction(DecoderTable32
, MI
, Insn
, Address
, this, STI
);
336 if (Bytes
.size() < 2) {
338 return MCDisassembler::Fail
;
340 Insn
= support::endian::read16le(Bytes
.data());
342 if (!STI
.getFeatureBits()[RISCV::Feature64Bit
]) {
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
,
348 if (Result
!= MCDisassembler::Fail
) {
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
);