Duckstation/dep/riscv-disas/include/riscv-disas.h
2023-08-15 14:06:00 +10:00

521 lines
9.7 KiB
C

/*
* RISC-V Disassembler
*
* Copyright (c) 2016-2017 Michael Clark <michaeljclark@mac.com>
* Copyright (c) 2017-2018 SiFive, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef RISCV_DISASSEMBLER_H
#define RISCV_DISASSEMBLER_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
#include <string.h>
/* types */
typedef uint64_t rv_inst;
typedef uint16_t rv_opcode;
/* enums */
typedef enum {
rv32,
rv64,
rv128
} rv_isa;
typedef enum {
rv_rm_rne = 0,
rv_rm_rtz = 1,
rv_rm_rdn = 2,
rv_rm_rup = 3,
rv_rm_rmm = 4,
rv_rm_dyn = 7,
} rv_rm;
typedef enum {
rv_fence_i = 8,
rv_fence_o = 4,
rv_fence_r = 2,
rv_fence_w = 1,
} rv_fence;
typedef enum {
rv_ireg_zero,
rv_ireg_ra,
rv_ireg_sp,
rv_ireg_gp,
rv_ireg_tp,
rv_ireg_t0,
rv_ireg_t1,
rv_ireg_t2,
rv_ireg_s0,
rv_ireg_s1,
rv_ireg_a0,
rv_ireg_a1,
rv_ireg_a2,
rv_ireg_a3,
rv_ireg_a4,
rv_ireg_a5,
rv_ireg_a6,
rv_ireg_a7,
rv_ireg_s2,
rv_ireg_s3,
rv_ireg_s4,
rv_ireg_s5,
rv_ireg_s6,
rv_ireg_s7,
rv_ireg_s8,
rv_ireg_s9,
rv_ireg_s10,
rv_ireg_s11,
rv_ireg_t3,
rv_ireg_t4,
rv_ireg_t5,
rv_ireg_t6,
} rv_ireg;
typedef enum {
rvc_end,
rvc_rd_eq_ra,
rvc_rd_eq_x0,
rvc_rs1_eq_x0,
rvc_rs2_eq_x0,
rvc_rs2_eq_rs1,
rvc_rs1_eq_ra,
rvc_imm_eq_zero,
rvc_imm_eq_n1,
rvc_imm_eq_p1,
rvc_csr_eq_0x001,
rvc_csr_eq_0x002,
rvc_csr_eq_0x003,
rvc_csr_eq_0xc00,
rvc_csr_eq_0xc01,
rvc_csr_eq_0xc02,
rvc_csr_eq_0xc80,
rvc_csr_eq_0xc81,
rvc_csr_eq_0xc82,
} rvc_constraint;
typedef enum {
rv_codec_illegal,
rv_codec_none,
rv_codec_u,
rv_codec_uj,
rv_codec_i,
rv_codec_i_sh5,
rv_codec_i_sh6,
rv_codec_i_sh7,
rv_codec_i_csr,
rv_codec_s,
rv_codec_sb,
rv_codec_r,
rv_codec_r_m,
rv_codec_r4_m,
rv_codec_r_a,
rv_codec_r_l,
rv_codec_r_f,
rv_codec_cb,
rv_codec_cb_imm,
rv_codec_cb_sh5,
rv_codec_cb_sh6,
rv_codec_ci,
rv_codec_ci_sh5,
rv_codec_ci_sh6,
rv_codec_ci_16sp,
rv_codec_ci_lwsp,
rv_codec_ci_ldsp,
rv_codec_ci_lqsp,
rv_codec_ci_li,
rv_codec_ci_lui,
rv_codec_ci_none,
rv_codec_ciw_4spn,
rv_codec_cj,
rv_codec_cj_jal,
rv_codec_cl_lw,
rv_codec_cl_ld,
rv_codec_cl_lq,
rv_codec_cr,
rv_codec_cr_mv,
rv_codec_cr_jalr,
rv_codec_cr_jr,
rv_codec_cs,
rv_codec_cs_sw,
rv_codec_cs_sd,
rv_codec_cs_sq,
rv_codec_css_swsp,
rv_codec_css_sdsp,
rv_codec_css_sqsp,
} rv_codec;
typedef enum {
rv_op_illegal,
rv_op_lui,
rv_op_auipc,
rv_op_jal,
rv_op_jalr,
rv_op_beq,
rv_op_bne,
rv_op_blt,
rv_op_bge,
rv_op_bltu,
rv_op_bgeu,
rv_op_lb,
rv_op_lh,
rv_op_lw,
rv_op_lbu,
rv_op_lhu,
rv_op_sb,
rv_op_sh,
rv_op_sw,
rv_op_addi,
rv_op_slti,
rv_op_sltiu,
rv_op_xori,
rv_op_ori,
rv_op_andi,
rv_op_slli,
rv_op_srli,
rv_op_srai,
rv_op_add,
rv_op_sub,
rv_op_sll,
rv_op_slt,
rv_op_sltu,
rv_op_xor,
rv_op_srl,
rv_op_sra,
rv_op_or,
rv_op_and,
rv_op_fence,
rv_op_fence_i,
rv_op_lwu,
rv_op_ld,
rv_op_sd,
rv_op_addiw,
rv_op_slliw,
rv_op_srliw,
rv_op_sraiw,
rv_op_addw,
rv_op_subw,
rv_op_sllw,
rv_op_srlw,
rv_op_sraw,
rv_op_ldu,
rv_op_lq,
rv_op_sq,
rv_op_addid,
rv_op_sllid,
rv_op_srlid,
rv_op_sraid,
rv_op_addd,
rv_op_subd,
rv_op_slld,
rv_op_srld,
rv_op_srad,
rv_op_mul,
rv_op_mulh,
rv_op_mulhsu,
rv_op_mulhu,
rv_op_div,
rv_op_divu,
rv_op_rem,
rv_op_remu,
rv_op_mulw,
rv_op_divw,
rv_op_divuw,
rv_op_remw,
rv_op_remuw,
rv_op_muld,
rv_op_divd,
rv_op_divud,
rv_op_remd,
rv_op_remud,
rv_op_lr_w,
rv_op_sc_w,
rv_op_amoswap_w,
rv_op_amoadd_w,
rv_op_amoxor_w,
rv_op_amoor_w,
rv_op_amoand_w,
rv_op_amomin_w,
rv_op_amomax_w,
rv_op_amominu_w,
rv_op_amomaxu_w,
rv_op_lr_d,
rv_op_sc_d,
rv_op_amoswap_d,
rv_op_amoadd_d,
rv_op_amoxor_d,
rv_op_amoor_d,
rv_op_amoand_d,
rv_op_amomin_d,
rv_op_amomax_d,
rv_op_amominu_d,
rv_op_amomaxu_d,
rv_op_lr_q,
rv_op_sc_q,
rv_op_amoswap_q,
rv_op_amoadd_q,
rv_op_amoxor_q,
rv_op_amoor_q,
rv_op_amoand_q,
rv_op_amomin_q,
rv_op_amomax_q,
rv_op_amominu_q,
rv_op_amomaxu_q,
rv_op_ecall,
rv_op_ebreak,
rv_op_uret,
rv_op_sret,
rv_op_hret,
rv_op_mret,
rv_op_dret,
rv_op_sfence_vm,
rv_op_sfence_vma,
rv_op_wfi,
rv_op_csrrw,
rv_op_csrrs,
rv_op_csrrc,
rv_op_csrrwi,
rv_op_csrrsi,
rv_op_csrrci,
rv_op_flw,
rv_op_fsw,
rv_op_fmadd_s,
rv_op_fmsub_s,
rv_op_fnmsub_s,
rv_op_fnmadd_s,
rv_op_fadd_s,
rv_op_fsub_s,
rv_op_fmul_s,
rv_op_fdiv_s,
rv_op_fsgnj_s,
rv_op_fsgnjn_s,
rv_op_fsgnjx_s,
rv_op_fmin_s,
rv_op_fmax_s,
rv_op_fsqrt_s,
rv_op_fle_s,
rv_op_flt_s,
rv_op_feq_s,
rv_op_fcvt_w_s,
rv_op_fcvt_wu_s,
rv_op_fcvt_s_w,
rv_op_fcvt_s_wu,
rv_op_fmv_x_s,
rv_op_fclass_s,
rv_op_fmv_s_x,
rv_op_fcvt_l_s,
rv_op_fcvt_lu_s,
rv_op_fcvt_s_l,
rv_op_fcvt_s_lu,
rv_op_fld,
rv_op_fsd,
rv_op_fmadd_d,
rv_op_fmsub_d,
rv_op_fnmsub_d,
rv_op_fnmadd_d,
rv_op_fadd_d,
rv_op_fsub_d,
rv_op_fmul_d,
rv_op_fdiv_d,
rv_op_fsgnj_d,
rv_op_fsgnjn_d,
rv_op_fsgnjx_d,
rv_op_fmin_d,
rv_op_fmax_d,
rv_op_fcvt_s_d,
rv_op_fcvt_d_s,
rv_op_fsqrt_d,
rv_op_fle_d,
rv_op_flt_d,
rv_op_feq_d,
rv_op_fcvt_w_d,
rv_op_fcvt_wu_d,
rv_op_fcvt_d_w,
rv_op_fcvt_d_wu,
rv_op_fclass_d,
rv_op_fcvt_l_d,
rv_op_fcvt_lu_d,
rv_op_fmv_x_d,
rv_op_fcvt_d_l,
rv_op_fcvt_d_lu,
rv_op_fmv_d_x,
rv_op_flq,
rv_op_fsq,
rv_op_fmadd_q,
rv_op_fmsub_q,
rv_op_fnmsub_q,
rv_op_fnmadd_q,
rv_op_fadd_q,
rv_op_fsub_q,
rv_op_fmul_q,
rv_op_fdiv_q,
rv_op_fsgnj_q,
rv_op_fsgnjn_q,
rv_op_fsgnjx_q,
rv_op_fmin_q,
rv_op_fmax_q,
rv_op_fcvt_s_q,
rv_op_fcvt_q_s,
rv_op_fcvt_d_q,
rv_op_fcvt_q_d,
rv_op_fsqrt_q,
rv_op_fle_q,
rv_op_flt_q,
rv_op_feq_q,
rv_op_fcvt_w_q,
rv_op_fcvt_wu_q,
rv_op_fcvt_q_w,
rv_op_fcvt_q_wu,
rv_op_fclass_q,
rv_op_fcvt_l_q,
rv_op_fcvt_lu_q,
rv_op_fcvt_q_l,
rv_op_fcvt_q_lu,
rv_op_fmv_x_q,
rv_op_fmv_q_x,
rv_op_c_addi4spn,
rv_op_c_fld,
rv_op_c_lw,
rv_op_c_flw,
rv_op_c_fsd,
rv_op_c_sw,
rv_op_c_fsw,
rv_op_c_nop,
rv_op_c_addi,
rv_op_c_jal,
rv_op_c_li,
rv_op_c_addi16sp,
rv_op_c_lui,
rv_op_c_srli,
rv_op_c_srai,
rv_op_c_andi,
rv_op_c_sub,
rv_op_c_xor,
rv_op_c_or,
rv_op_c_and,
rv_op_c_subw,
rv_op_c_addw,
rv_op_c_j,
rv_op_c_beqz,
rv_op_c_bnez,
rv_op_c_slli,
rv_op_c_fldsp,
rv_op_c_lwsp,
rv_op_c_flwsp,
rv_op_c_jr,
rv_op_c_mv,
rv_op_c_ebreak,
rv_op_c_jalr,
rv_op_c_add,
rv_op_c_fsdsp,
rv_op_c_swsp,
rv_op_c_fswsp,
rv_op_c_ld,
rv_op_c_sd,
rv_op_c_addiw,
rv_op_c_ldsp,
rv_op_c_sdsp,
rv_op_c_lq,
rv_op_c_sq,
rv_op_c_lqsp,
rv_op_c_sqsp,
rv_op_nop,
rv_op_mv,
rv_op_not,
rv_op_neg,
rv_op_negw,
rv_op_sext_w,
rv_op_seqz,
rv_op_snez,
rv_op_sltz,
rv_op_sgtz,
rv_op_fmv_s,
rv_op_fabs_s,
rv_op_fneg_s,
rv_op_fmv_d,
rv_op_fabs_d,
rv_op_fneg_d,
rv_op_fmv_q,
rv_op_fabs_q,
rv_op_fneg_q,
rv_op_beqz,
rv_op_bnez,
rv_op_blez,
rv_op_bgez,
rv_op_bltz,
rv_op_bgtz,
rv_op_ble,
rv_op_bleu,
rv_op_bgt,
rv_op_bgtu,
rv_op_j,
rv_op_ret,
rv_op_jr,
rv_op_rdcycle,
rv_op_rdtime,
rv_op_rdinstret,
rv_op_rdcycleh,
rv_op_rdtimeh,
rv_op_rdinstreth,
rv_op_frcsr,
rv_op_frrm,
rv_op_frflags,
rv_op_fscsr,
rv_op_fsrm,
rv_op_fsflags,
rv_op_fsrmi,
rv_op_fsflagsi,
} rv_op;
/* structures */
typedef struct {
uint64_t pc;
uint64_t inst;
int32_t imm;
uint16_t op;
uint8_t codec;
uint8_t rd;
uint8_t rs1;
uint8_t rs2;
uint8_t rs3;
uint8_t rm;
uint8_t pred;
uint8_t succ;
uint8_t aq;
uint8_t rl;
} rv_decode;
/* functions */
size_t inst_length(rv_inst inst);
void inst_fetch(const uint8_t *data, rv_inst *instp, size_t *length);
void disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst);
#endif