/* * RISC-V Disassembler * * Copyright (c) 2016-2017 Michael Clark * 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 /* 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_flh, rv_op_fsh, rv_op_fmadd_h, rv_op_fmsub_h, rv_op_fnmsub_h, rv_op_fnmadd_h, rv_op_fadd_h, rv_op_fsub_h, rv_op_fmul_h, rv_op_fdiv_h, rv_op_fsgnj_h, rv_op_fsgnjn_h, rv_op_fsgnjx_h, rv_op_fmin_h, rv_op_fmax_h, rv_op_fsqrt_h, rv_op_fle_h, rv_op_flt_h, rv_op_feq_h, rv_op_fcvt_w_h, rv_op_fcvt_wu_h, rv_op_fcvt_h_w, rv_op_fcvt_h_wu, rv_op_fclass_h, rv_op_fcvt_l_h, rv_op_fcvt_lu_h, rv_op_fmv_x_h, rv_op_fcvt_h_l, rv_op_fcvt_h_lu, rv_op_fmv_h_x, rv_op_fcvt_s_h, rv_op_fcvt_h_s, rv_op_fcvt_d_h, rv_op_fcvt_h_d, rv_op_fcvt_q_h, rv_op_fcvt_h_q, rv_op_fmv_h, rv_op_fabs_h, rv_op_fneg_h, 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_add_uw, rv_op_andn, rv_op_bclr, rv_op_bclri, rv_op_bext, rv_op_bexti, rv_op_binv, rv_op_binvi, rv_op_bset, rv_op_bseti, rv_op_clmul, rv_op_clmulh, rv_op_clmulr, rv_op_clz, rv_op_clzw, rv_op_cpop, rv_op_cpopw, rv_op_ctz, rv_op_ctzw, rv_op_max, rv_op_maxu, rv_op_min, rv_op_minu, rv_op_orc_b, rv_op_orn, rv_op_rev8, rv_op_rol, rv_op_rolw, rv_op_ror, rv_op_rori, rv_op_roriw, rv_op_rorw, rv_op_sext_b, rv_op_sext_h, rv_op_sh1add, rv_op_sh1add_uw, rv_op_sh2add, rv_op_sh2add_uw, rv_op_sh3add, rv_op_sh3add_uw, rv_op_slli_uw, rv_op_xnor, rv_op_zext_h, } 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 riscv_inst_length(rv_inst inst); void riscv_inst_fetch(const uint8_t *data, rv_inst *instp, size_t *length); void riscv_disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst); #endif