#ifndef _RISCV_INSN_H_
#define _RISCV_INSN_H_
union riscv_insn {
uint32_t val;
struct {
unsigned int r_opcode : 7;
unsigned int r_rd : 5;
unsigned int r_funct3 : 3;
unsigned int r_rs1 : 5;
unsigned int r_rs2 : 5;
unsigned int r_funct7 : 7;
} type_r;
struct {
unsigned int rs32_opcode : 7;
unsigned int rs32_rd : 5;
unsigned int rs32_funct3 : 3;
unsigned int rs32_rs1 : 5;
unsigned int rs32_shamt : 5;
unsigned int rs32_funct7 : 7;
} type_rs32;
struct {
unsigned int rs64_opcode : 7;
unsigned int rs64_rd : 5;
unsigned int rs64_funct3 : 3;
unsigned int rs64_rs1 : 5;
unsigned int rs64_shamt : 6;
unsigned int rs64_zero : 1;
unsigned int rs64_funct5 : 5;
} type_rs64;
struct {
unsigned int ra_opcode : 7;
unsigned int ra_rd : 5;
unsigned int ra_funct3 : 3;
unsigned int ra_rs1 : 5;
unsigned int ra_rs2 : 5;
unsigned int ra_rl : 1;
unsigned int ra_aq : 1;
unsigned int ra_funct5 : 5;
} type_ra;
struct {
unsigned int rf_opcode : 7;
unsigned int rf_rd : 5;
unsigned int rf_rm : 3;
unsigned int rf_rs1 : 5;
unsigned int rf_rs2 : 5;
unsigned int rf_size : 2;
unsigned int rf_funct5 : 5;
} type_rf;
struct {
unsigned int rf4_opcode : 7;
unsigned int rf4_rd : 5;
unsigned int rf4_rm : 3;
unsigned int rf4_rs1 : 5;
unsigned int rf4_rs2 : 5;
unsigned int rf4_size : 2;
unsigned int rf4_rs3 : 5;
} type_rf4;
struct {
unsigned int i_opcode : 7;
unsigned int i_rd : 5;
unsigned int i_funct3 : 3;
unsigned int i_rs1 : 5;
signed int i_imm11to0 : 12;
} type_i;
struct {
unsigned int s_opcode : 7;
unsigned int s_imm4_to_0 : 5;
unsigned int s_funct3 : 3;
unsigned int s_rs1 : 5;
unsigned int s_rs2 : 5;
signed int s_imm11_to_5 : 7;
} type_s;
struct {
unsigned int b_opcode : 7;
unsigned int b_imm11 : 1;
unsigned int b_imm4to1 : 4;
unsigned int b_funct3 : 3;
unsigned int b_rs1 : 5;
unsigned int b_rs2 : 5;
unsigned int b_imm10to5 : 6;
signed int b_imm12 : 1;
} type_b;
struct {
unsigned int u_opcode : 7;
unsigned int u_rd : 5;
signed int u_imm31to12 : 20;
} type_u;
struct {
unsigned int j_opcode : 7;
unsigned int j_rd : 5;
unsigned int j_imm19to12 : 9;
unsigned int j_imm11 : 1;
unsigned int j_imm10to1 : 9;
signed int j_imm20 : 1;
} type_j;
};
#define OPCODE_P(i, x) (((i) & 0b1111111) == ((OPCODE_##x<<2)|0b11))
#define INSN_SIZE_IS_16(insn) (((insn) & 0b11) != 0b11)
#define INSN_SIZE_IS_32(insn) (((insn) & 0b11100) != 0b11100)
#define INSN_SIZE_IS_48(insn) (((insn) & 0b100000) != 0b100000)
#define INSN_SIZE_IS_64(insn) (((insn) & 0b1000000) != 0b1000000)
#define INSN_HALFWORDS(insn) \
(INSN_SIZE_IS_16(insn) ? 1 : \
INSN_SIZE_IS_32(insn) ? 2 : \
INSN_SIZE_IS_48(insn) ? 3 : \
INSN_SIZE_IS_64(insn) ? 4 : \
5)
#define INSN_SIZE(insn) (INSN_HALFWORDS(insn) * sizeof(uint16_t))
#define SIGNEXT32(x, k) ( \
( ((x) & (1U << ((k)-1))) ? (0xffffffffU << (k)) : 0U) | \
((x) & (0xffffffffU >> (32 - (k)))) \
)
#define INSN_OPCODE32(insn) (((insn) & 0x0000007f) >> 2)
#define INSN_RD(insn) (((insn) & 0x00000f80) >> 7)
#define INSN_FUNCT3(insn) (((insn) & 0x00007000) >> 12)
#define INSN_RS1(insn) (((insn) & 0x000f8000) >> 15)
#define INSN_RS2(insn) (((insn) & 0x01f00000) >> 20)
#define INSN_FUNCT7(insn) (((insn) & 0xfe000000) >> 25)
#define INSN_IMM_U(insn) ((insn) & 0xfffff000)
#define INSN_IMM_I(insn) SIGNEXT32(((insn) & 0xfff00000) >> 20, 12)
#define INSN_IMM_S_raw(insn) ((INSN_FUNCT7(insn) << 5) | INSN_RD(insn))
#define INSN_IMM_S(insn) SIGNEXT32(INSN_IMM_S_raw(insn), 12)
#define INSN_IMM_B_raw(insn) \
(((insn & 0x80000000) >> (31-12)) | \
((insn & 0x00000080) << (11-7)) | \
((insn & 0x7e000000) >> (25-5)) | \
((insn & 0x00000f00) >> (8-1)))
#define INSN_IMM_B(insn) SIGNEXT32(INSN_IMM_B_raw(insn), 13)
#define INSN_IMM_J_raw(insn) \
(((insn & 0x80000000) >> (31-20)) | \
((insn & 0x000ff000) >> (12-12)) | \
((insn & 0x00100000) >> (20-11)) | \
((insn & 0x7fe00000) >> (21-1)))
#define INSN_IMM_J(insn) SIGNEXT32(INSN_IMM_J_raw(insn), 21)
#define INSN16_QUADRANT(insn) ((insn) & 0b11)
#define INSN16_FUNCT3(insn) (((insn) & 0xe000) >> 13)
#define INSN16_FUNCT2a(insn) (((insn) & 0x0c00) >> 10)
#define INSN16_FUNCT1b(insn) (((insn) & 0x1000) >> 12)
#define INSN16_FUNCT2b(insn) (((insn) & 0x0060) >> 5)
#define INSN16_FUNCT3c(insn) \
((INSN16_FUNCT1b(insn) << 2) | INSN16_FUNCT2b(insn))
#define INSN16_RS1(insn) (((insn) & 0x0f80) >> 7)
#define INSN16_RS2(insn) (((insn) & 0x007c) >> 2)
#define INSN16_RS1x(insn) ((((insn) & 0x0380) >> 7) + 8)
#define INSN16_RS2x(insn) ((((insn) & 0x001c) >> 2) + 8)
#define INSN16_IMM_CI_W(insn) \
((((insn) & 0b0001000000000000) >> (12-5)) | \
(((insn) & 0b0000000001110000) >> (4-2)) | \
(((insn) & 0b0000000000001100) << (6-2)))
#define INSN16_IMM_CI_D(insn) \
((((insn) & 0b0001000000000000) >> (12-5)) | \
(((insn) & 0b0000000001100000) >> (4-2)) | \
(((insn) & 0b0000000000011100) << (6-2)))
#define INSN16_IMM_CI_Q(insn) \
((((insn) & 0b0001000000000000) >> (12-5)) | \
(((insn) & 0b0000000001000000) >> (4-2)) | \
(((insn) & 0b0000000000111100) << (6-2)))
#define INSN16_IMM_CI_K_raw(insn) \
((((insn) & 0b0001000000000000) >> (12-5)) | \
(((insn) & 0b0000000001111100) >> (2-0)))
#define INSN16_IMM_CI_K(insn) SIGNEXT32(INSN16_IMM_CI_K_raw(insn), 6)
#define INSN16_IMM_CI_K12(insn) SIGNEXT32(INSN16_IMM_CI_K_raw(insn) << 12, 18)
#define INSN16_IMM_CI_K4_raw(insn) \
((((insn) & 0b0001000000000000) >> (12-9)) | \
(((insn) & 0b0000000001000000) >> (6-4)) | \
(((insn) & 0b0000000000100000) << (6-5)) | \
(((insn) & 0b0000000000011000) << (7-3)) | \
(((insn) & 0b0000000000000100) << (5-2)))
#define INSN16_IMM_CI_K4(insn) SIGNEXT32(INSN16_IMM_CI_K4_raw(insn), 10)
#define INSN16_IMM_CSS_W(insn) \
((((insn) & 0b0001111000000000) >> (9-2)) | \
(((insn) & 0b0000000110000000) >> (7-6)))
#define INSN16_IMM_CSS_D(insn) \
((((insn) & 0b0001110000000000) >> (9-2)) | \
(((insn) & 0b0000001110000000) >> (7-6)))
#define INSN16_IMM_CSS_Q(insn) \
((((insn) & 0b0001100000000000) >> (9-2)) | \
(((insn) & 0b0000011110000000) >> (7-6)))
#define INSN16_IMM_CL_W(insn) \
((((insn) & 0b0001110000000000) >> (10-3)) | \
(((insn) & 0b0000000001000000) >> (6-2)) | \
(((insn) & 0b0000000000100000) << (6-5)))
#define INSN16_IMM_CL_D(insn) \
((((insn) & 0b0001110000000000) >> (10-3)) | \
(((insn) & 0b0000000001100000) << (6-5)))
#define INSN16_IMM_CL_Q(insn) \
((((insn) & 0b0001100000000000) >> (11-4)) | \
(((insn) & 0b0000010000000000) >> (10-8)) | \
(((insn) & 0b0000000001100000) << (6-5)))
#define INSN16_IMM_CS_W(insn) INSN16_IMM_CL_W(insn)
#define INSN16_IMM_CS_D(insn) INSN16_IMM_CL_D(insn)
#define INSN16_IMM_CS_Q(insn) INSN16_IMM_CL_Q(insn)
#define INSN16_IMM_CJ_raw(insn) \
((((insn) & 0b0001000000000000) >> (12-11)) | \
(((insn) & 0b0000100000000000) >> (11-4)) | \
(((insn) & 0b0000011000000000) >> (9-8)) | \
(((insn) & 0b0000000100000000) << (10-8)) | \
(((insn) & 0b0000000010000000) >> (7-6)) | \
(((insn) & 0b0000000001000000) << (7-6)) | \
(((insn) & 0b0000000000111000) >> (3-1)) | \
(((insn) & 0b0000000000000100) << (5-2)))
#define INSN16_IMM_CJ(insn) SIGNEXT32(INSN16_IMM_CJ_raw(insn), 12)
#define INSN16_IMM_CB_raw(insn) \
((((insn) & 0b0001000000000000) >> (12-8)) | \
(((insn) & 0b0000110000000000) >> (10-3)) | \
(((insn) & 0b0000000001100000) << (6-5)) | \
(((insn) & 0b0000000000011000) >> (3-1)) | \
(((insn) & 0b0000000000000100) << (5-2)))
#define INSN16_IMM_CB(insn) SIGNEXT32(INSN16_IMM_CB_raw(insn), 9)
#define INSN16_IMM_CIW(insn) \
((((insn) & 0b0001100000000000) >> (11-4)) | \
(((insn) & 0b0000011110000000) >> (7-6)) | \
(((insn) & 0b0000000001000000) >> (6-2)) | \
(((insn) & 0b0000000000100000) >> (5-3)))
#define OPCODE_LOAD 0b00000
#define OPCODE_LOADFP 0b00001
#define OPCODE_CUSTOM0 0b00010
#define OPCODE_MISCMEM 0b00011
#define OPCODE_OPIMM 0b00100
#define OPCODE_AUIPC 0b00101
#define OPCODE_OPIMM32 0b00110
#define OPCODE_X48a 0b00111
#define OPCODE_STORE 0b01000
#define OPCODE_STOREFP 0b01001
#define OPCODE_CUSTOM1 0b01010
#define OPCODE_AMO 0b01011
#define OPCODE_OP 0b01100
#define OPCODE_LUI 0b01101
#define OPCODE_OP32 0b01110
#define OPCODE_X64 0b01111
#define OPCODE_MADD 0b10000
#define OPCODE_MSUB 0b10001
#define OPCODE_NMSUB 0b10010
#define OPCODE_NMADD 0b10011
#define OPCODE_OPFP 0b10100
#define OPCODE_rsvd21 0b10101
#define OPCODE_CUSTOM2 0b10110
#define OPCODE_X48b 0b10111
#define OPCODE_BRANCH 0b11000
#define OPCODE_JALR 0b11001
#define OPCODE_rsvd26 0b11010
#define OPCODE_JAL 0b11011
#define OPCODE_SYSTEM 0b11100
#define OPCODE_rsvd29 0b11101
#define OPCODE_CUSTOM3 0b11110
#define OPCODE_X80 0b11111
#define OP_ARITH 0b0000000
#define OP_MULDIV 0b0000001
#define OP_NARITH 0b0100000
#define OPFP_ADD 0b00000
#define OPFP_SUB 0b00001
#define OPFP_MUL 0b00010
#define OPFP_DIV 0b00011
#define OPFP_SGNJ 0b00100
#define OPFP_MINMAX 0b00101
#define OPFP_CVTFF 0b01000
#define OPFP_SQRT 0b01011
#define OPFP_CMP 0b10100
#define OPFP_CVTIF 0b11000
#define OPFP_CVTFI 0b11010
#define OPFP_MVFI_CLASS 0b11100
#define OPFP_MVIF 0b11110
#define OPFP_S 0b00
#define OPFP_D 0b01
#define OPFP_Q 0b11
#define OPFP_W 0b00
#define OPFP_WU 0b01
#define OPFP_L 0b10
#define OPFP_LU 0b11
#define AMO_ADD 0b00000
#define AMO_SWAP 0b00001
#define AMO_LR 0b00010
#define AMO_SC 0b00011
#define AMO_XOR 0b00100
#define AMO_OR 0b01000
#define AMO_AND 0b01100
#define AMO_MIN 0b10000
#define AMO_MAX 0b10100
#define AMO_MINU 0b11000
#define AMO_MAXU 0b11100
#define PRIV_USER 0b0000000
#define PRIV_SYSTEM 0b0001000
#define PRIV_SFENCE_VMA 0b0001001
#define PRIV_HFENCE_BVMA 0b0010001
#define PRIV_MACHINE 0b0011000
#define PRIV_HFENCE_GVMA 0b1010001
#define LOAD_LB 0b000
#define LOAD_LH 0b001
#define LOAD_LW 0b010
#define LOAD_LD 0b011
#define LOAD_LBU 0b100
#define LOAD_LHU 0b101
#define LOAD_LWU 0b110
#define LOADFP_FLW 0b010
#define LOADFP_FLD 0b011
#define LOADFP_FLQ 0b100
#define MISCMEM_FENCE 0b000
#define MISCMEM_FENCEI 0b001
#define STORE_SB 0b000
#define STORE_SH 0b001
#define STORE_SW 0b010
#define STORE_SD 0b011
#define STOREFP_FSW 0b010
#define STOREFP_FSD 0b011
#define STOREFP_FSQ 0b100
#define AMO_W 0b010
#define AMO_D 0b011
#define OP_ADDSUB 0b000
#define OP_SLL 0b001
#define OP_SLT 0b010
#define OP_SLTU 0b011
#define OP_XOR 0b100
#define OP_SRX 0b101
#define OP_OR 0b110
#define OP_AND 0b111
#define OP_MUL 0b000
#define OP_MULH 0b001
#define OP_MULHSU 0b010
#define OP_MULHU 0b011
#define OP_DIV 0b100
#define OP_DIVU 0b101
#define OP_REM 0b110
#define OP_REMU 0b111
#define ROUND_RNE 0b000
#define ROUND_RTZ 0b001
#define ROUND_RDN 0b010
#define ROUND_RUP 0b011
#define ROUND_RMM 0b100
#define ROUND_DYN 0b111
#define SGN_SGNJ 0b000
#define SGN_SGNJN 0b001
#define SGN_SGNJX 0b010
#define MINMAX_MIN 0b000
#define MINMAX_MAX 0b001
#define CMP_LE 0b000
#define CMP_LT 0b001
#define CMP_EQ 0b010
#define MVFI_CLASS_MVFI 0b000
#define MVFI_CLASS_CLASS 0b001
#define BRANCH_BEQ 0b000
#define BRANCH_BNE 0b001
#define BRANCH_BLT 0b100
#define BRANCH_BGE 0b101
#define BRANCH_BLTU 0b110
#define BRANCH_BGEU 0b111
#define SYSTEM_PRIV 0b000
#define SYSTEM_CSRRW 0b001
#define SYSTEM_CSRRS 0b010
#define SYSTEM_CSRRC 0b011
#define SYSTEM_CSRRWI 0b101
#define SYSTEM_CSRRSI 0b110
#define SYSTEM_CSRRCI 0b111
#define USER_ECALL 0b00000
#define USER_EBREAK 0b00001
#define USER_URET 0b00010
#define SYSTEM_SRET 0b00010
#define SYSTEM_WFI 0b00101
#define MACHINE_MRET 0b00010
#define CVT_W 0b00000
#define CVT_WU 0b00001
#define CVT_L 0b00010
#define CVT_LU 0b00011
#define FENCE_INPUT 0b1000
#define FENCE_OUTPUT 0b0100
#define FENCE_READ 0b0010
#define FENCE_WRITE 0b0001
#define FENCE_FM_NORMAL 0b0000
#define FENCE_FM_TSO 0b1000
#define AMO_AQ 0b0000010
#define AMO_RL 0b0000001
#define OPCODE16_Q0 0b00
#define OPCODE16_Q1 0b01
#define OPCODE16_Q2 0b10
#define Q0_ADDI4SPN 0b000
#define Q0_FLD_LQ 0b001
#define Q0_LW 0b010
#define Q0_FLW_LD 0b011
#define Q0_RESERVED 0b100
#define Q0_FSD_SQ 0b101
#define Q0_SW 0b110
#define Q0_FSW_SD 0b111
#define Q1_NOP_ADDI 0b000
#define Q1_JAL_ADDIW 0b001
#define Q1_LI 0b010
#define Q1_ADDI16SP_LUI 0b011
#define Q1_MISC 0b100
#define Q1_J 0b101
#define Q1_BEQZ 0b110
#define Q1_BNEZ 0b111
#define Q1MISC_SRLI 0b00
#define Q1MISC_SRAI 0b01
#define Q1MISC_ANDI 0b10
#define Q1MISC_MORE 0b11
#define Q1MORE_SUB 0b000
#define Q1MORE_XOR 0b001
#define Q1MORE_OR 0b010
#define Q1MORE_AND 0b011
#define Q1MORE_SUBW 0b100
#define Q1MORE_ADDW 0b101
#define Q2_SLLI 0b000
#define Q2_FLDSP_LQSP 0b001
#define Q2_LWSP 0b010
#define Q2_FLWSP_LDSP 0b011
#define Q2_MISC 0b100
#define Q2_FSDSP_SQSP 0b101
#define Q2_SWSP 0b110
#define Q2_FSWSP_SDSP 0b111
#define Q2MISC_JR_MV 0b0
#define Q2MISC_EBREAK_JALR_ADD 0b1
#define CSR_FFLAGS 0x001
#define CSR_FRM 0x002
#define CSR_FCSR 0x003
#define CSR_CYCLE 0xc00
#define CSR_TIME 0xc01
#define CSR_INSTRET 0xc02
#define CSR_HPMCOUNTER(n) (0xc00+(n))
#define CSR_CYCLEH 0xc80
#define CSR_TIMEH 0xc81
#define CSR_INSTRETH 0xc82
#define CSR_HPMCOUNTERH(n) (0xc80+(n))
#define CSR_SSTATUS 0x100
#define CSR_SIE 0x104
#define CSR_STVEC 0x105
#define CSR_SCOUNTEREN 0x106
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
#define CSR_SCAUSE 0x142
#define CSR_STVAL 0x143
#define CSR_SIP 0x144
#define CSR_SATP 0x180
#define CSR_MVENDORID 0xf11
#define CSR_MARCHID 0xf12
#define CSR_MIMPID 0xf13
#define CSR_MHARTID 0xf14
#define CSR_MSTATUS 0x300
#define CSR_MISA 0x301
#define CSR_MEDELEG 0x302
#define CSR_MIDELEG 0x303
#define CSR_MIE 0x304
#define CSR_MTVEC 0x305
#define CSR_MCOUNTEREN 0x306
#define CSR_MSCRATCH 0x340
#define CSR_MEPC 0x341
#define CSR_MCAUSE 0x342
#define CSR_MTVAL 0x343
#define CSR_MIP 0x344
#define CSR_PMPCFG(n) (0x3a0 + (n))
#define CSR_PMPADDR(n) (0x3b0 + (n))
#define CSR_MCYCLE 0xb00
#define CSR_MINSTRET 0xb02
#define CSR_MHPMCOUNTER(n) (0xb00+(n))
#define CSR_MCYCLEH 0xb80
#define CSR_MINSTRETH 0xb82
#define CSR_MHPMCOUNTERH(n) (0xb80+(n))
#define CSR_MCOUNTINHIBIT 0x320
#define CSR_MHPMEVENT(n) (0x320+(n))
#define CSR_TSELECT 0x7a0
#define CSR_TDATA1 0x7a1
#define CSR_TDATA2 0x7a2
#define CSR_TDATA3 0x7a3
#define CSR_DCSR 0x7b0
#define CSR_DPC 0x7b1
#define CSR_DSCRATCH0 0x7b2
#define CSR_DSCRATCH1 0x7b3
#endif