1 //===-- RISCVInstructions.h -----------------------------------------------===//
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 #ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H
10 #define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H
16 #include "llvm/ADT/APFloat.h"
18 namespace lldb_private
{
20 class EmulateInstructionRISCV
;
24 bool Write(EmulateInstructionRISCV
&emulator
, uint64_t value
);
25 bool WriteAPFloat(EmulateInstructionRISCV
&emulator
, llvm::APFloat value
);
30 std::optional
<uint64_t> Read(EmulateInstructionRISCV
&emulator
);
31 std::optional
<int32_t> ReadI32(EmulateInstructionRISCV
&emulator
);
32 std::optional
<int64_t> ReadI64(EmulateInstructionRISCV
&emulator
);
33 std::optional
<uint32_t> ReadU32(EmulateInstructionRISCV
&emulator
);
34 std::optional
<llvm::APFloat
> ReadAPFloat(EmulateInstructionRISCV
&emulator
,
38 #define DERIVE_EQ(NAME) \
39 bool operator==(const NAME &r) const { \
40 return std::memcmp(this, &r, sizeof(NAME)) == 0; \
43 #define I_TYPE_INST(NAME) \
50 #define S_TYPE_INST(NAME) \
57 #define U_TYPE_INST(NAME) \
63 /// The memory layout are the same in our code.
64 #define J_TYPE_INST(NAME) U_TYPE_INST(NAME)
65 #define R_TYPE_INST(NAME) \
72 #define R_SHAMT_TYPE_INST(NAME) \
79 #define R_RS1_TYPE_INST(NAME) \
85 #define R4_TYPE_INST(NAME) \
94 /// The `inst` fields are used for debugging.
95 #define INVALID_INST(NAME) \
101 // RV32I instructions (The base integer ISA)
138 // RV64I inst (The base integer ISA)
142 R_SHAMT_TYPE_INST(SLLI
);
143 R_SHAMT_TYPE_INST(SRLI
);
144 R_SHAMT_TYPE_INST(SRAI
);
146 R_SHAMT_TYPE_INST(SLLIW
);
147 R_SHAMT_TYPE_INST(SRLIW
);
148 R_SHAMT_TYPE_INST(SRAIW
);
155 // RV32M inst (The standard integer multiplication and division extension)
165 // RV64M inst (The standard integer multiplication and division extension)
172 // RV32A inst (The standard atomic instruction extension)
173 R_RS1_TYPE_INST(LR_W
);
175 R_TYPE_INST(AMOSWAP_W
);
176 R_TYPE_INST(AMOADD_W
);
177 R_TYPE_INST(AMOXOR_W
);
178 R_TYPE_INST(AMOAND_W
);
179 R_TYPE_INST(AMOOR_W
);
180 R_TYPE_INST(AMOMIN_W
);
181 R_TYPE_INST(AMOMAX_W
);
182 R_TYPE_INST(AMOMINU_W
);
183 R_TYPE_INST(AMOMAXU_W
);
185 // RV64A inst (The standard atomic instruction extension)
186 R_RS1_TYPE_INST(LR_D
);
188 R_TYPE_INST(AMOSWAP_D
);
189 R_TYPE_INST(AMOADD_D
);
190 R_TYPE_INST(AMOXOR_D
);
191 R_TYPE_INST(AMOAND_D
);
192 R_TYPE_INST(AMOOR_D
);
193 R_TYPE_INST(AMOMIN_D
);
194 R_TYPE_INST(AMOMAX_D
);
195 R_TYPE_INST(AMOMINU_D
);
196 R_TYPE_INST(AMOMAXU_D
);
198 // RV32F inst (The standard single-precision floating-point extension)
201 R4_TYPE_INST(FMADD_S
);
202 R4_TYPE_INST(FMSUB_S
);
203 R4_TYPE_INST(FNMADD_S
);
204 R4_TYPE_INST(FNMSUB_S
);
209 I_TYPE_INST(FSQRT_S
);
210 R_TYPE_INST(FSGNJ_S
);
211 R_TYPE_INST(FSGNJN_S
);
212 R_TYPE_INST(FSGNJX_S
);
215 I_TYPE_INST(FCVT_W_S
);
216 I_TYPE_INST(FCVT_WU_S
);
217 I_TYPE_INST(FMV_X_W
);
221 I_TYPE_INST(FCLASS_S
);
222 I_TYPE_INST(FCVT_S_W
);
223 I_TYPE_INST(FCVT_S_WU
);
224 I_TYPE_INST(FMV_W_X
);
226 // RV64F inst (The standard single-precision floating-point extension)
227 I_TYPE_INST(FCVT_L_S
);
228 I_TYPE_INST(FCVT_LU_S
);
229 I_TYPE_INST(FCVT_S_L
);
230 I_TYPE_INST(FCVT_S_LU
);
232 // RV32D inst (Extension for Double-Precision Floating-Point)
235 R4_TYPE_INST(FMADD_D
);
236 R4_TYPE_INST(FMSUB_D
);
237 R4_TYPE_INST(FNMSUB_D
);
238 R4_TYPE_INST(FNMADD_D
);
243 I_TYPE_INST(FSQRT_D
);
244 R_TYPE_INST(FSGNJ_D
);
245 R_TYPE_INST(FSGNJN_D
);
246 R_TYPE_INST(FSGNJX_D
);
249 I_TYPE_INST(FCVT_S_D
);
250 I_TYPE_INST(FCVT_D_S
);
254 I_TYPE_INST(FCLASS_D
);
255 I_TYPE_INST(FCVT_W_D
);
256 I_TYPE_INST(FCVT_WU_D
);
257 I_TYPE_INST(FCVT_D_W
);
258 I_TYPE_INST(FCVT_D_WU
);
260 // RV64D inst (Extension for Double-Precision Floating-Point)
261 I_TYPE_INST(FCVT_L_D
);
262 I_TYPE_INST(FCVT_LU_D
);
263 I_TYPE_INST(FMV_X_D
);
264 I_TYPE_INST(FCVT_D_L
);
265 I_TYPE_INST(FCVT_D_LU
);
266 I_TYPE_INST(FMV_D_X
);
268 /// Invalid and reserved instructions, the `inst` fields are used for debugging.
269 INVALID_INST(INVALID
);
270 INVALID_INST(RESERVED
);
271 INVALID_INST(EBREAK
);
275 using RISCVInst
= std::variant
<
276 LUI
, AUIPC
, JAL
, JALR
, B
, LB
, LH
, LW
, LBU
, LHU
, SB
, SH
, SW
, ADDI
, SLTI
,
277 SLTIU
, XORI
, ORI
, ANDI
, ADD
, SUB
, SLL
, SLT
, SLTU
, XOR
, SRL
, SRA
, OR
, AND
,
278 LWU
, LD
, SD
, SLLI
, SRLI
, SRAI
, ADDIW
, SLLIW
, SRLIW
, SRAIW
, ADDW
, SUBW
, SLLW
,
279 SRLW
, SRAW
, MUL
, MULH
, MULHSU
, MULHU
, DIV
, DIVU
, REM
, REMU
, MULW
, DIVW
,
280 DIVUW
, REMW
, REMUW
, LR_W
, SC_W
, AMOSWAP_W
, AMOADD_W
, AMOXOR_W
, AMOAND_W
,
281 AMOOR_W
, AMOMIN_W
, AMOMAX_W
, AMOMINU_W
, AMOMAXU_W
, LR_D
, SC_D
, AMOSWAP_D
,
282 AMOADD_D
, AMOXOR_D
, AMOAND_D
, AMOOR_D
, AMOMIN_D
, AMOMAX_D
, AMOMINU_D
,
283 AMOMAXU_D
, FLW
, FSW
, FMADD_S
, FMSUB_S
, FNMADD_S
, FNMSUB_S
, FADD_S
, FSUB_S
,
284 FMUL_S
, FDIV_S
, FSQRT_S
, FSGNJ_S
, FSGNJN_S
, FSGNJX_S
, FMIN_S
, FMAX_S
,
285 FCVT_W_S
, FCVT_WU_S
, FMV_X_W
, FEQ_S
, FLT_S
, FLE_S
, FCLASS_S
, FCVT_S_W
,
286 FCVT_S_WU
, FMV_W_X
, FCVT_L_S
, FCVT_LU_S
, FCVT_S_L
, FCVT_S_LU
, FLD
, FSD
,
287 FMADD_D
, FMSUB_D
, FNMSUB_D
, FNMADD_D
, FADD_D
, FSUB_D
, FMUL_D
, FDIV_D
,
288 FSQRT_D
, FSGNJ_D
, FSGNJN_D
, FSGNJX_D
, FMIN_D
, FMAX_D
, FCVT_S_D
, FCVT_D_S
,
289 FEQ_D
, FLT_D
, FLE_D
, FCLASS_D
, FCVT_W_D
, FCVT_WU_D
, FCVT_D_W
, FCVT_D_WU
,
290 FCVT_L_D
, FCVT_LU_D
, FMV_X_D
, FCVT_D_L
, FCVT_D_LU
, FMV_D_X
, INVALID
, EBREAK
,
291 RESERVED
, HINT
, NOP
>;
293 constexpr uint8_t RV32
= 1;
294 constexpr uint8_t RV64
= 2;
295 constexpr uint8_t RV128
= 4;
297 struct InstrPattern
{
299 /// Bit mask to check the type of a instruction (B-Type, I-Type, J-Type, etc.)
301 /// Characteristic value after bitwise-and with type_mask.
303 RISCVInst (*decode
)(uint32_t inst
);
304 /// If not specified, the inst will be supported by all RV versions.
305 uint8_t inst_type
= RV32
| RV64
| RV128
;
308 struct DecodeResult
{
312 InstrPattern pattern
;
315 constexpr uint32_t DecodeRD(uint32_t inst
) { return (inst
& 0xF80) >> 7; }
316 constexpr uint32_t DecodeRS1(uint32_t inst
) { return (inst
& 0xF8000) >> 15; }
317 constexpr uint32_t DecodeRS2(uint32_t inst
) { return (inst
& 0x1F00000) >> 20; }
318 constexpr uint32_t DecodeRS3(uint32_t inst
) {
319 return (inst
& 0xF0000000) >> 27;
321 constexpr uint32_t DecodeFunct3(uint32_t inst
) { return (inst
& 0x7000) >> 12; }
322 constexpr uint32_t DecodeFunct2(uint32_t inst
) {
323 return (inst
& 0xE000000) >> 25;
325 constexpr uint32_t DecodeFunct7(uint32_t inst
) {
326 return (inst
& 0xFE000000) >> 25;
329 constexpr int32_t DecodeRM(uint32_t inst
) { return DecodeFunct3(inst
); }
331 /// RISC-V spec: The upper bits of a valid NaN-boxed value must be all 1s.
332 constexpr uint64_t NanBoxing(uint64_t val
) {
333 return val
| 0xFFFF'FFFF'0000'0000;
335 constexpr uint32_t NanUnBoxing(uint64_t val
) {
336 return val
& (~0xFFFF'FFFF'0000'0000);
340 #undef R_SHAMT_TYPE_INST
341 #undef R_RS1_TYPE_INST
351 } // namespace lldb_private
352 #endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H