1//===-- RISCVInstructions.h -----------------------------------------------===// 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#ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H 10#define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H 11 12#include <cstdint> 13#include <optional> 14#include <variant> 15 16#include "llvm/ADT/APFloat.h" 17 18namespace lldb_private { 19 20class EmulateInstructionRISCV; 21 22struct Rd { 23 uint32_t rd; 24 bool Write(EmulateInstructionRISCV &emulator, uint64_t value); 25 bool WriteAPFloat(EmulateInstructionRISCV &emulator, llvm::APFloat value); 26}; 27 28struct Rs { 29 uint32_t rs; 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, 35 bool isDouble); 36}; 37 38#define DERIVE_EQ(NAME) \ 39 bool operator==(const NAME &r) const { \ 40 return std::memcmp(this, &r, sizeof(NAME)) == 0; \ 41 } 42 43#define I_TYPE_INST(NAME) \ 44 struct NAME { \ 45 Rd rd; \ 46 Rs rs1; \ 47 uint32_t imm; \ 48 DERIVE_EQ(NAME); \ 49 } 50#define S_TYPE_INST(NAME) \ 51 struct NAME { \ 52 Rs rs1; \ 53 Rs rs2; \ 54 uint32_t imm; \ 55 DERIVE_EQ(NAME); \ 56 } 57#define U_TYPE_INST(NAME) \ 58 struct NAME { \ 59 Rd rd; \ 60 uint32_t imm; \ 61 DERIVE_EQ(NAME); \ 62 } 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) \ 66 struct NAME { \ 67 Rd rd; \ 68 Rs rs1; \ 69 Rs rs2; \ 70 DERIVE_EQ(NAME); \ 71 } 72#define R_SHAMT_TYPE_INST(NAME) \ 73 struct NAME { \ 74 Rd rd; \ 75 Rs rs1; \ 76 uint32_t shamt; \ 77 DERIVE_EQ(NAME); \ 78 } 79#define R_RS1_TYPE_INST(NAME) \ 80 struct NAME { \ 81 Rd rd; \ 82 Rs rs1; \ 83 DERIVE_EQ(NAME); \ 84 } 85#define R4_TYPE_INST(NAME) \ 86 struct NAME { \ 87 Rd rd; \ 88 Rs rs1; \ 89 Rs rs2; \ 90 Rs rs3; \ 91 int32_t rm; \ 92 DERIVE_EQ(NAME); \ 93 } 94/// The `inst` fields are used for debugging. 95#define INVALID_INST(NAME) \ 96 struct NAME { \ 97 uint32_t inst; \ 98 DERIVE_EQ(NAME); \ 99 } 100 101// RV32I instructions (The base integer ISA) 102struct B { 103 Rs rs1; 104 Rs rs2; 105 uint32_t imm; 106 uint32_t funct3; 107 DERIVE_EQ(B); 108}; 109U_TYPE_INST(LUI); 110U_TYPE_INST(AUIPC); 111J_TYPE_INST(JAL); 112I_TYPE_INST(JALR); 113I_TYPE_INST(LB); 114I_TYPE_INST(LH); 115I_TYPE_INST(LW); 116I_TYPE_INST(LBU); 117I_TYPE_INST(LHU); 118S_TYPE_INST(SB); 119S_TYPE_INST(SH); 120S_TYPE_INST(SW); 121I_TYPE_INST(ADDI); 122I_TYPE_INST(SLTI); 123I_TYPE_INST(SLTIU); 124I_TYPE_INST(XORI); 125I_TYPE_INST(ORI); 126I_TYPE_INST(ANDI); 127R_TYPE_INST(ADD); 128R_TYPE_INST(SUB); 129R_TYPE_INST(SLL); 130R_TYPE_INST(SLT); 131R_TYPE_INST(SLTU); 132R_TYPE_INST(XOR); 133R_TYPE_INST(SRL); 134R_TYPE_INST(SRA); 135R_TYPE_INST(OR); 136R_TYPE_INST(AND); 137 138// RV64I inst (The base integer ISA) 139I_TYPE_INST(LWU); 140I_TYPE_INST(LD); 141S_TYPE_INST(SD); 142R_SHAMT_TYPE_INST(SLLI); 143R_SHAMT_TYPE_INST(SRLI); 144R_SHAMT_TYPE_INST(SRAI); 145I_TYPE_INST(ADDIW); 146R_SHAMT_TYPE_INST(SLLIW); 147R_SHAMT_TYPE_INST(SRLIW); 148R_SHAMT_TYPE_INST(SRAIW); 149R_TYPE_INST(ADDW); 150R_TYPE_INST(SUBW); 151R_TYPE_INST(SLLW); 152R_TYPE_INST(SRLW); 153R_TYPE_INST(SRAW); 154 155// RV32M inst (The standard integer multiplication and division extension) 156R_TYPE_INST(MUL); 157R_TYPE_INST(MULH); 158R_TYPE_INST(MULHSU); 159R_TYPE_INST(MULHU); 160R_TYPE_INST(DIV); 161R_TYPE_INST(DIVU); 162R_TYPE_INST(REM); 163R_TYPE_INST(REMU); 164 165// RV64M inst (The standard integer multiplication and division extension) 166R_TYPE_INST(MULW); 167R_TYPE_INST(DIVW); 168R_TYPE_INST(DIVUW); 169R_TYPE_INST(REMW); 170R_TYPE_INST(REMUW); 171 172// RV32A inst (The standard atomic instruction extension) 173R_RS1_TYPE_INST(LR_W); 174R_TYPE_INST(SC_W); 175R_TYPE_INST(AMOSWAP_W); 176R_TYPE_INST(AMOADD_W); 177R_TYPE_INST(AMOXOR_W); 178R_TYPE_INST(AMOAND_W); 179R_TYPE_INST(AMOOR_W); 180R_TYPE_INST(AMOMIN_W); 181R_TYPE_INST(AMOMAX_W); 182R_TYPE_INST(AMOMINU_W); 183R_TYPE_INST(AMOMAXU_W); 184 185// RV64A inst (The standard atomic instruction extension) 186R_RS1_TYPE_INST(LR_D); 187R_TYPE_INST(SC_D); 188R_TYPE_INST(AMOSWAP_D); 189R_TYPE_INST(AMOADD_D); 190R_TYPE_INST(AMOXOR_D); 191R_TYPE_INST(AMOAND_D); 192R_TYPE_INST(AMOOR_D); 193R_TYPE_INST(AMOMIN_D); 194R_TYPE_INST(AMOMAX_D); 195R_TYPE_INST(AMOMINU_D); 196R_TYPE_INST(AMOMAXU_D); 197 198// RV32F inst (The standard single-precision floating-point extension) 199I_TYPE_INST(FLW); 200S_TYPE_INST(FSW); 201R4_TYPE_INST(FMADD_S); 202R4_TYPE_INST(FMSUB_S); 203R4_TYPE_INST(FNMADD_S); 204R4_TYPE_INST(FNMSUB_S); 205R_TYPE_INST(FADD_S); 206R_TYPE_INST(FSUB_S); 207R_TYPE_INST(FMUL_S); 208R_TYPE_INST(FDIV_S); 209I_TYPE_INST(FSQRT_S); 210R_TYPE_INST(FSGNJ_S); 211R_TYPE_INST(FSGNJN_S); 212R_TYPE_INST(FSGNJX_S); 213R_TYPE_INST(FMIN_S); 214R_TYPE_INST(FMAX_S); 215I_TYPE_INST(FCVT_W_S); 216I_TYPE_INST(FCVT_WU_S); 217I_TYPE_INST(FMV_X_W); 218R_TYPE_INST(FEQ_S); 219R_TYPE_INST(FLT_S); 220R_TYPE_INST(FLE_S); 221I_TYPE_INST(FCLASS_S); 222I_TYPE_INST(FCVT_S_W); 223I_TYPE_INST(FCVT_S_WU); 224I_TYPE_INST(FMV_W_X); 225 226// RV64F inst (The standard single-precision floating-point extension) 227I_TYPE_INST(FCVT_L_S); 228I_TYPE_INST(FCVT_LU_S); 229I_TYPE_INST(FCVT_S_L); 230I_TYPE_INST(FCVT_S_LU); 231 232// RV32D inst (Extension for Double-Precision Floating-Point) 233I_TYPE_INST(FLD); 234S_TYPE_INST(FSD); 235R4_TYPE_INST(FMADD_D); 236R4_TYPE_INST(FMSUB_D); 237R4_TYPE_INST(FNMSUB_D); 238R4_TYPE_INST(FNMADD_D); 239R_TYPE_INST(FADD_D); 240R_TYPE_INST(FSUB_D); 241R_TYPE_INST(FMUL_D); 242R_TYPE_INST(FDIV_D); 243I_TYPE_INST(FSQRT_D); 244R_TYPE_INST(FSGNJ_D); 245R_TYPE_INST(FSGNJN_D); 246R_TYPE_INST(FSGNJX_D); 247R_TYPE_INST(FMIN_D); 248R_TYPE_INST(FMAX_D); 249I_TYPE_INST(FCVT_S_D); 250I_TYPE_INST(FCVT_D_S); 251R_TYPE_INST(FEQ_D); 252R_TYPE_INST(FLT_D); 253R_TYPE_INST(FLE_D); 254I_TYPE_INST(FCLASS_D); 255I_TYPE_INST(FCVT_W_D); 256I_TYPE_INST(FCVT_WU_D); 257I_TYPE_INST(FCVT_D_W); 258I_TYPE_INST(FCVT_D_WU); 259 260// RV64D inst (Extension for Double-Precision Floating-Point) 261I_TYPE_INST(FCVT_L_D); 262I_TYPE_INST(FCVT_LU_D); 263I_TYPE_INST(FMV_X_D); 264I_TYPE_INST(FCVT_D_L); 265I_TYPE_INST(FCVT_D_LU); 266I_TYPE_INST(FMV_D_X); 267 268/// Invalid and reserved instructions, the `inst` fields are used for debugging. 269INVALID_INST(INVALID); 270INVALID_INST(RESERVED); 271INVALID_INST(EBREAK); 272INVALID_INST(HINT); 273INVALID_INST(NOP); 274 275using 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>; 292 293constexpr uint8_t RV32 = 1; 294constexpr uint8_t RV64 = 2; 295constexpr uint8_t RV128 = 4; 296 297struct InstrPattern { 298 const char *name; 299 /// Bit mask to check the type of a instruction (B-Type, I-Type, J-Type, etc.) 300 uint32_t type_mask; 301 /// Characteristic value after bitwise-and with type_mask. 302 uint32_t eigen; 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; 306}; 307 308struct DecodeResult { 309 RISCVInst decoded; 310 uint32_t inst; 311 bool is_rvc; 312 InstrPattern pattern; 313}; 314 315constexpr uint32_t DecodeRD(uint32_t inst) { return (inst & 0xF80) >> 7; } 316constexpr uint32_t DecodeRS1(uint32_t inst) { return (inst & 0xF8000) >> 15; } 317constexpr uint32_t DecodeRS2(uint32_t inst) { return (inst & 0x1F00000) >> 20; } 318constexpr uint32_t DecodeRS3(uint32_t inst) { 319 return (inst & 0xF0000000) >> 27; 320} 321constexpr uint32_t DecodeFunct3(uint32_t inst) { return (inst & 0x7000) >> 12; } 322constexpr uint32_t DecodeFunct2(uint32_t inst) { 323 return (inst & 0xE000000) >> 25; 324} 325constexpr uint32_t DecodeFunct7(uint32_t inst) { 326 return (inst & 0xFE000000) >> 25; 327} 328 329constexpr int32_t DecodeRM(uint32_t inst) { return DecodeFunct3(inst); } 330 331/// RISC-V spec: The upper bits of a valid NaN-boxed value must be all 1s. 332constexpr uint64_t NanBoxing(uint64_t val) { 333 return val | 0xFFFF'FFFF'0000'0000; 334} 335constexpr uint32_t NanUnBoxing(uint64_t val) { 336 return val & (~0xFFFF'FFFF'0000'0000); 337} 338 339#undef R_TYPE_INST 340#undef R_SHAMT_TYPE_INST 341#undef R_RS1_TYPE_INST 342#undef R4_TYPE_INST 343#undef I_TYPE_INST 344#undef S_TYPE_INST 345#undef B_TYPE_INST 346#undef U_TYPE_INST 347#undef J_TYPE_INST 348#undef INVALID_INST 349#undef DERIVE_EQ 350 351} // namespace lldb_private 352#endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H 353