| /* |
| * QEMU disassembler -- RISC-V specific header. |
| * |
| * SPDX-License-Identifier: GPL-2.0-or-later |
| */ |
| |
| #ifndef DISAS_RISCV_H |
| #define DISAS_RISCV_H |
| |
| #include "qemu/osdep.h" |
| #include "target/riscv/cpu_cfg.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_k_bs, |
| rv_codec_k_rnum, |
| rv_codec_v_r, |
| rv_codec_v_ldst, |
| rv_codec_v_i, |
| rv_codec_vsetvli, |
| rv_codec_vsetivli, |
| rv_codec_zcb_ext, |
| rv_codec_zcb_mul, |
| rv_codec_zcb_lb, |
| rv_codec_zcb_lh, |
| rv_codec_zcmp_cm_pushpop, |
| rv_codec_zcmp_cm_mv, |
| rv_codec_zcmt_jt, |
| rv_codec_r2_imm5, |
| rv_codec_r2, |
| rv_codec_r2_imm6, |
| rv_codec_r_imm2, |
| rv_codec_r2_immhl, |
| rv_codec_r2_imm2_imm5, |
| } rv_codec; |
| |
| /* structures */ |
| |
| typedef struct { |
| const int op; |
| const rvc_constraint *constraints; |
| } rv_comp_data; |
| |
| typedef struct { |
| const char * const name; |
| const rv_codec codec; |
| const char * const format; |
| const rv_comp_data *pseudo; |
| const short decomp_rv32; |
| const short decomp_rv64; |
| const short decomp_rv128; |
| const short decomp_data; |
| } rv_opcode_data; |
| |
| typedef struct { |
| RISCVCPUConfig *cfg; |
| uint64_t pc; |
| uint64_t inst; |
| const rv_opcode_data *opcode_data; |
| int32_t imm; |
| int32_t imm1; |
| 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; |
| uint8_t bs; |
| uint8_t rnum; |
| uint8_t vm; |
| uint32_t vzimm; |
| uint8_t rlist; |
| } rv_decode; |
| |
| enum { |
| rv_op_illegal = 0 |
| }; |
| |
| enum { |
| rvcd_imm_nz = 0x1 |
| }; |
| |
| /* instruction formats */ |
| |
| #define rv_fmt_none "O\t" |
| #define rv_fmt_rs1 "O\t1" |
| #define rv_fmt_offset "O\to" |
| #define rv_fmt_pred_succ "O\tp,s" |
| #define rv_fmt_rs1_rs2 "O\t1,2" |
| #define rv_fmt_rd_imm "O\t0,i" |
| #define rv_fmt_rd_offset "O\t0,o" |
| #define rv_fmt_rd_rs1_rs2 "O\t0,1,2" |
| #define rv_fmt_frd_rs1 "O\t3,1" |
| #define rv_fmt_frd_frs1 "O\t3,4" |
| #define rv_fmt_rd_frs1 "O\t0,4" |
| #define rv_fmt_rd_frs1_frs2 "O\t0,4,5" |
| #define rv_fmt_frd_frs1_frs2 "O\t3,4,5" |
| #define rv_fmt_rm_frd_frs1 "O\tr,3,4" |
| #define rv_fmt_rm_frd_rs1 "O\tr,3,1" |
| #define rv_fmt_rm_rd_frs1 "O\tr,0,4" |
| #define rv_fmt_rm_frd_frs1_frs2 "O\tr,3,4,5" |
| #define rv_fmt_rm_frd_frs1_frs2_frs3 "O\tr,3,4,5,6" |
| #define rv_fmt_rd_rs1_imm "O\t0,1,i" |
| #define rv_fmt_rd_rs1_offset "O\t0,1,i" |
| #define rv_fmt_rd_offset_rs1 "O\t0,i(1)" |
| #define rv_fmt_frd_offset_rs1 "O\t3,i(1)" |
| #define rv_fmt_rd_csr_rs1 "O\t0,c,1" |
| #define rv_fmt_rd_csr_zimm "O\t0,c,7" |
| #define rv_fmt_rs2_offset_rs1 "O\t2,i(1)" |
| #define rv_fmt_frs2_offset_rs1 "O\t5,i(1)" |
| #define rv_fmt_rs1_rs2_offset "O\t1,2,o" |
| #define rv_fmt_rs2_rs1_offset "O\t2,1,o" |
| #define rv_fmt_aqrl_rd_rs2_rs1 "OAR\t0,2,(1)" |
| #define rv_fmt_aqrl_rd_rs1 "OAR\t0,(1)" |
| #define rv_fmt_rd "O\t0" |
| #define rv_fmt_rd_zimm "O\t0,7" |
| #define rv_fmt_rd_rs1 "O\t0,1" |
| #define rv_fmt_rd_rs2 "O\t0,2" |
| #define rv_fmt_rs1_offset "O\t1,o" |
| #define rv_fmt_rs2_offset "O\t2,o" |
| #define rv_fmt_rs1_rs2_bs "O\t1,2,b" |
| #define rv_fmt_rd_rs1_rnum "O\t0,1,n" |
| #define rv_fmt_ldst_vd_rs1_vm "O\tD,(1)m" |
| #define rv_fmt_ldst_vd_rs1_rs2_vm "O\tD,(1),2m" |
| #define rv_fmt_ldst_vd_rs1_vs2_vm "O\tD,(1),Fm" |
| #define rv_fmt_vd_vs2_vs1 "O\tD,F,E" |
| #define rv_fmt_vd_vs2_vs1_vl "O\tD,F,El" |
| #define rv_fmt_vd_vs2_vs1_vm "O\tD,F,Em" |
| #define rv_fmt_vd_vs2_rs1_vl "O\tD,F,1l" |
| #define rv_fmt_vd_vs2_fs1_vl "O\tD,F,4l" |
| #define rv_fmt_vd_vs2_rs1_vm "O\tD,F,1m" |
| #define rv_fmt_vd_vs2_fs1_vm "O\tD,F,4m" |
| #define rv_fmt_vd_vs2_imm_vl "O\tD,F,il" |
| #define rv_fmt_vd_vs2_imm_vm "O\tD,F,im" |
| #define rv_fmt_vd_vs2_uimm_vm "O\tD,F,um" |
| #define rv_fmt_vd_vs1_vs2_vm "O\tD,E,Fm" |
| #define rv_fmt_vd_rs1_vs2_vm "O\tD,1,Fm" |
| #define rv_fmt_vd_fs1_vs2_vm "O\tD,4,Fm" |
| #define rv_fmt_vd_vs1 "O\tD,E" |
| #define rv_fmt_vd_rs1 "O\tD,1" |
| #define rv_fmt_vd_fs1 "O\tD,4" |
| #define rv_fmt_vd_imm "O\tD,i" |
| #define rv_fmt_vd_vs2 "O\tD,F" |
| #define rv_fmt_vd_vs2_vm "O\tD,Fm" |
| #define rv_fmt_rd_vs2_vm "O\t0,Fm" |
| #define rv_fmt_rd_vs2 "O\t0,F" |
| #define rv_fmt_fd_vs2 "O\t3,F" |
| #define rv_fmt_vd_vm "O\tDm" |
| #define rv_fmt_vsetvli "O\t0,1,v" |
| #define rv_fmt_vsetivli "O\t0,u,v" |
| #define rv_fmt_rs1_rs2_zce_ldst "O\t2,i(1)" |
| #define rv_fmt_push_rlist "O\tx,-i" |
| #define rv_fmt_pop_rlist "O\tx,i" |
| #define rv_fmt_zcmt_index "O\ti" |
| #define rv_fmt_rd_rs1_rs2_imm "O\t0,1,2,i" |
| #define rv_fmt_frd_rs1_rs2_imm "O\t3,1,2,i" |
| #define rv_fmt_rd_rs1_immh_imml "O\t0,1,i,j" |
| #define rv_fmt_rd_rs1_immh_imml_addr "O\t0,(1),i,j" |
| #define rv_fmt_rd2_imm "O\t0,2,(1),i" |
| |
| #endif /* DISAS_RISCV_H */ |