Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h
39653 views
//===-- RISCVInstructions.h -----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H9#define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H1011#include <cstdint>12#include <optional>13#include <variant>1415#include "llvm/ADT/APFloat.h"1617namespace lldb_private {1819class EmulateInstructionRISCV;2021struct Rd {22uint32_t rd;23bool Write(EmulateInstructionRISCV &emulator, uint64_t value);24bool WriteAPFloat(EmulateInstructionRISCV &emulator, llvm::APFloat value);25};2627struct Rs {28uint32_t rs;29std::optional<uint64_t> Read(EmulateInstructionRISCV &emulator);30std::optional<int32_t> ReadI32(EmulateInstructionRISCV &emulator);31std::optional<int64_t> ReadI64(EmulateInstructionRISCV &emulator);32std::optional<uint32_t> ReadU32(EmulateInstructionRISCV &emulator);33std::optional<llvm::APFloat> ReadAPFloat(EmulateInstructionRISCV &emulator,34bool isDouble);35};3637#define DERIVE_EQ(NAME) \38bool operator==(const NAME &r) const { \39return std::memcmp(this, &r, sizeof(NAME)) == 0; \40}4142#define I_TYPE_INST(NAME) \43struct NAME { \44Rd rd; \45Rs rs1; \46uint32_t imm; \47DERIVE_EQ(NAME); \48}49#define S_TYPE_INST(NAME) \50struct NAME { \51Rs rs1; \52Rs rs2; \53uint32_t imm; \54DERIVE_EQ(NAME); \55}56#define U_TYPE_INST(NAME) \57struct NAME { \58Rd rd; \59uint32_t imm; \60DERIVE_EQ(NAME); \61}62/// The memory layout are the same in our code.63#define J_TYPE_INST(NAME) U_TYPE_INST(NAME)64#define R_TYPE_INST(NAME) \65struct NAME { \66Rd rd; \67Rs rs1; \68Rs rs2; \69DERIVE_EQ(NAME); \70}71#define R_SHAMT_TYPE_INST(NAME) \72struct NAME { \73Rd rd; \74Rs rs1; \75uint32_t shamt; \76DERIVE_EQ(NAME); \77}78#define R_RS1_TYPE_INST(NAME) \79struct NAME { \80Rd rd; \81Rs rs1; \82DERIVE_EQ(NAME); \83}84#define R4_TYPE_INST(NAME) \85struct NAME { \86Rd rd; \87Rs rs1; \88Rs rs2; \89Rs rs3; \90int32_t rm; \91DERIVE_EQ(NAME); \92}93/// The `inst` fields are used for debugging.94#define INVALID_INST(NAME) \95struct NAME { \96uint32_t inst; \97DERIVE_EQ(NAME); \98}99100// RV32I instructions (The base integer ISA)101struct B {102Rs rs1;103Rs rs2;104uint32_t imm;105uint32_t funct3;106DERIVE_EQ(B);107};108U_TYPE_INST(LUI);109U_TYPE_INST(AUIPC);110J_TYPE_INST(JAL);111I_TYPE_INST(JALR);112I_TYPE_INST(LB);113I_TYPE_INST(LH);114I_TYPE_INST(LW);115I_TYPE_INST(LBU);116I_TYPE_INST(LHU);117S_TYPE_INST(SB);118S_TYPE_INST(SH);119S_TYPE_INST(SW);120I_TYPE_INST(ADDI);121I_TYPE_INST(SLTI);122I_TYPE_INST(SLTIU);123I_TYPE_INST(XORI);124I_TYPE_INST(ORI);125I_TYPE_INST(ANDI);126R_TYPE_INST(ADD);127R_TYPE_INST(SUB);128R_TYPE_INST(SLL);129R_TYPE_INST(SLT);130R_TYPE_INST(SLTU);131R_TYPE_INST(XOR);132R_TYPE_INST(SRL);133R_TYPE_INST(SRA);134R_TYPE_INST(OR);135R_TYPE_INST(AND);136137// RV64I inst (The base integer ISA)138I_TYPE_INST(LWU);139I_TYPE_INST(LD);140S_TYPE_INST(SD);141R_SHAMT_TYPE_INST(SLLI);142R_SHAMT_TYPE_INST(SRLI);143R_SHAMT_TYPE_INST(SRAI);144I_TYPE_INST(ADDIW);145R_SHAMT_TYPE_INST(SLLIW);146R_SHAMT_TYPE_INST(SRLIW);147R_SHAMT_TYPE_INST(SRAIW);148R_TYPE_INST(ADDW);149R_TYPE_INST(SUBW);150R_TYPE_INST(SLLW);151R_TYPE_INST(SRLW);152R_TYPE_INST(SRAW);153154// RV32M inst (The standard integer multiplication and division extension)155R_TYPE_INST(MUL);156R_TYPE_INST(MULH);157R_TYPE_INST(MULHSU);158R_TYPE_INST(MULHU);159R_TYPE_INST(DIV);160R_TYPE_INST(DIVU);161R_TYPE_INST(REM);162R_TYPE_INST(REMU);163164// RV64M inst (The standard integer multiplication and division extension)165R_TYPE_INST(MULW);166R_TYPE_INST(DIVW);167R_TYPE_INST(DIVUW);168R_TYPE_INST(REMW);169R_TYPE_INST(REMUW);170171// RV32A inst (The standard atomic instruction extension)172R_RS1_TYPE_INST(LR_W);173R_TYPE_INST(SC_W);174R_TYPE_INST(AMOSWAP_W);175R_TYPE_INST(AMOADD_W);176R_TYPE_INST(AMOXOR_W);177R_TYPE_INST(AMOAND_W);178R_TYPE_INST(AMOOR_W);179R_TYPE_INST(AMOMIN_W);180R_TYPE_INST(AMOMAX_W);181R_TYPE_INST(AMOMINU_W);182R_TYPE_INST(AMOMAXU_W);183184// RV64A inst (The standard atomic instruction extension)185R_RS1_TYPE_INST(LR_D);186R_TYPE_INST(SC_D);187R_TYPE_INST(AMOSWAP_D);188R_TYPE_INST(AMOADD_D);189R_TYPE_INST(AMOXOR_D);190R_TYPE_INST(AMOAND_D);191R_TYPE_INST(AMOOR_D);192R_TYPE_INST(AMOMIN_D);193R_TYPE_INST(AMOMAX_D);194R_TYPE_INST(AMOMINU_D);195R_TYPE_INST(AMOMAXU_D);196197// RV32F inst (The standard single-precision floating-point extension)198I_TYPE_INST(FLW);199S_TYPE_INST(FSW);200R4_TYPE_INST(FMADD_S);201R4_TYPE_INST(FMSUB_S);202R4_TYPE_INST(FNMADD_S);203R4_TYPE_INST(FNMSUB_S);204R_TYPE_INST(FADD_S);205R_TYPE_INST(FSUB_S);206R_TYPE_INST(FMUL_S);207R_TYPE_INST(FDIV_S);208I_TYPE_INST(FSQRT_S);209R_TYPE_INST(FSGNJ_S);210R_TYPE_INST(FSGNJN_S);211R_TYPE_INST(FSGNJX_S);212R_TYPE_INST(FMIN_S);213R_TYPE_INST(FMAX_S);214I_TYPE_INST(FCVT_W_S);215I_TYPE_INST(FCVT_WU_S);216I_TYPE_INST(FMV_X_W);217R_TYPE_INST(FEQ_S);218R_TYPE_INST(FLT_S);219R_TYPE_INST(FLE_S);220I_TYPE_INST(FCLASS_S);221I_TYPE_INST(FCVT_S_W);222I_TYPE_INST(FCVT_S_WU);223I_TYPE_INST(FMV_W_X);224225// RV64F inst (The standard single-precision floating-point extension)226I_TYPE_INST(FCVT_L_S);227I_TYPE_INST(FCVT_LU_S);228I_TYPE_INST(FCVT_S_L);229I_TYPE_INST(FCVT_S_LU);230231// RV32D inst (Extension for Double-Precision Floating-Point)232I_TYPE_INST(FLD);233S_TYPE_INST(FSD);234R4_TYPE_INST(FMADD_D);235R4_TYPE_INST(FMSUB_D);236R4_TYPE_INST(FNMSUB_D);237R4_TYPE_INST(FNMADD_D);238R_TYPE_INST(FADD_D);239R_TYPE_INST(FSUB_D);240R_TYPE_INST(FMUL_D);241R_TYPE_INST(FDIV_D);242I_TYPE_INST(FSQRT_D);243R_TYPE_INST(FSGNJ_D);244R_TYPE_INST(FSGNJN_D);245R_TYPE_INST(FSGNJX_D);246R_TYPE_INST(FMIN_D);247R_TYPE_INST(FMAX_D);248I_TYPE_INST(FCVT_S_D);249I_TYPE_INST(FCVT_D_S);250R_TYPE_INST(FEQ_D);251R_TYPE_INST(FLT_D);252R_TYPE_INST(FLE_D);253I_TYPE_INST(FCLASS_D);254I_TYPE_INST(FCVT_W_D);255I_TYPE_INST(FCVT_WU_D);256I_TYPE_INST(FCVT_D_W);257I_TYPE_INST(FCVT_D_WU);258259// RV64D inst (Extension for Double-Precision Floating-Point)260I_TYPE_INST(FCVT_L_D);261I_TYPE_INST(FCVT_LU_D);262I_TYPE_INST(FMV_X_D);263I_TYPE_INST(FCVT_D_L);264I_TYPE_INST(FCVT_D_LU);265I_TYPE_INST(FMV_D_X);266267/// Invalid and reserved instructions, the `inst` fields are used for debugging.268INVALID_INST(INVALID);269INVALID_INST(RESERVED);270INVALID_INST(EBREAK);271INVALID_INST(HINT);272INVALID_INST(NOP);273274using RISCVInst = std::variant<275LUI, AUIPC, JAL, JALR, B, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI,276SLTIU, XORI, ORI, ANDI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND,277LWU, LD, SD, SLLI, SRLI, SRAI, ADDIW, SLLIW, SRLIW, SRAIW, ADDW, SUBW, SLLW,278SRLW, SRAW, MUL, MULH, MULHSU, MULHU, DIV, DIVU, REM, REMU, MULW, DIVW,279DIVUW, REMW, REMUW, LR_W, SC_W, AMOSWAP_W, AMOADD_W, AMOXOR_W, AMOAND_W,280AMOOR_W, AMOMIN_W, AMOMAX_W, AMOMINU_W, AMOMAXU_W, LR_D, SC_D, AMOSWAP_D,281AMOADD_D, AMOXOR_D, AMOAND_D, AMOOR_D, AMOMIN_D, AMOMAX_D, AMOMINU_D,282AMOMAXU_D, FLW, FSW, FMADD_S, FMSUB_S, FNMADD_S, FNMSUB_S, FADD_S, FSUB_S,283FMUL_S, FDIV_S, FSQRT_S, FSGNJ_S, FSGNJN_S, FSGNJX_S, FMIN_S, FMAX_S,284FCVT_W_S, FCVT_WU_S, FMV_X_W, FEQ_S, FLT_S, FLE_S, FCLASS_S, FCVT_S_W,285FCVT_S_WU, FMV_W_X, FCVT_L_S, FCVT_LU_S, FCVT_S_L, FCVT_S_LU, FLD, FSD,286FMADD_D, FMSUB_D, FNMSUB_D, FNMADD_D, FADD_D, FSUB_D, FMUL_D, FDIV_D,287FSQRT_D, FSGNJ_D, FSGNJN_D, FSGNJX_D, FMIN_D, FMAX_D, FCVT_S_D, FCVT_D_S,288FEQ_D, FLT_D, FLE_D, FCLASS_D, FCVT_W_D, FCVT_WU_D, FCVT_D_W, FCVT_D_WU,289FCVT_L_D, FCVT_LU_D, FMV_X_D, FCVT_D_L, FCVT_D_LU, FMV_D_X, INVALID, EBREAK,290RESERVED, HINT, NOP>;291292constexpr uint8_t RV32 = 1;293constexpr uint8_t RV64 = 2;294constexpr uint8_t RV128 = 4;295296struct InstrPattern {297const char *name;298/// Bit mask to check the type of a instruction (B-Type, I-Type, J-Type, etc.)299uint32_t type_mask;300/// Characteristic value after bitwise-and with type_mask.301uint32_t eigen;302RISCVInst (*decode)(uint32_t inst);303/// If not specified, the inst will be supported by all RV versions.304uint8_t inst_type = RV32 | RV64 | RV128;305};306307struct DecodeResult {308RISCVInst decoded;309uint32_t inst;310bool is_rvc;311InstrPattern pattern;312};313314constexpr uint32_t DecodeRD(uint32_t inst) { return (inst & 0xF80) >> 7; }315constexpr uint32_t DecodeRS1(uint32_t inst) { return (inst & 0xF8000) >> 15; }316constexpr uint32_t DecodeRS2(uint32_t inst) { return (inst & 0x1F00000) >> 20; }317constexpr uint32_t DecodeRS3(uint32_t inst) {318return (inst & 0xF0000000) >> 27;319}320constexpr uint32_t DecodeFunct3(uint32_t inst) { return (inst & 0x7000) >> 12; }321constexpr uint32_t DecodeFunct2(uint32_t inst) {322return (inst & 0xE000000) >> 25;323}324constexpr uint32_t DecodeFunct7(uint32_t inst) {325return (inst & 0xFE000000) >> 25;326}327328constexpr int32_t DecodeRM(uint32_t inst) { return DecodeFunct3(inst); }329330/// RISC-V spec: The upper bits of a valid NaN-boxed value must be all 1s.331constexpr uint64_t NanBoxing(uint64_t val) {332return val | 0xFFFF'FFFF'0000'0000;333}334constexpr uint32_t NanUnBoxing(uint64_t val) {335return val & (~0xFFFF'FFFF'0000'0000);336}337338#undef R_TYPE_INST339#undef R_SHAMT_TYPE_INST340#undef R_RS1_TYPE_INST341#undef R4_TYPE_INST342#undef I_TYPE_INST343#undef S_TYPE_INST344#undef B_TYPE_INST345#undef U_TYPE_INST346#undef J_TYPE_INST347#undef INVALID_INST348#undef DERIVE_EQ349350} // namespace lldb_private351#endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H352353354