mirror of
				https://github.com/RetroDECK/Duckstation.git
				synced 2025-04-10 19:15:14 +00:00 
			
		
		
		
	
		
			
	
	
		
			521 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			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
 |