@ -163,6 +163,13 @@ typedef enum {
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 ;
typedef enum {
@ -935,6 +942,26 @@ typedef enum {
rv_op_vsetvli = 766 ,
rv_op_vsetivli = 767 ,
rv_op_vsetvl = 768 ,
rv_op_c_zext_b = 769 ,
rv_op_c_sext_b = 770 ,
rv_op_c_zext_h = 771 ,
rv_op_c_sext_h = 772 ,
rv_op_c_zext_w = 773 ,
rv_op_c_not = 774 ,
rv_op_c_mul = 775 ,
rv_op_c_lbu = 776 ,
rv_op_c_lhu = 777 ,
rv_op_c_lh = 778 ,
rv_op_c_sb = 779 ,
rv_op_c_sh = 780 ,
rv_op_cm_push = 781 ,
rv_op_cm_pop = 782 ,
rv_op_cm_popret = 783 ,
rv_op_cm_popretz = 784 ,
rv_op_cm_mva01s = 785 ,
rv_op_cm_mvsa01 = 786 ,
rv_op_cm_jt = 787 ,
rv_op_cm_jalt = 788 ,
} rv_op ;
/* structures */
@ -958,6 +985,7 @@ typedef struct {
uint8_t rnum ;
uint8_t vm ;
uint32_t vzimm ;
uint8_t rlist ;
} rv_decode ;
typedef struct {
@ -1071,6 +1099,10 @@ static const char rv_vreg_name_sym[32][4] = {
# 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"
/* pseudo-instruction constraints */
@ -2066,7 +2098,27 @@ const rv_opcode_data opcode_data[] = {
{ " vsext.vf8 " , rv_codec_v_r , rv_fmt_vd_vs2_vm , NULL , rv_op_vsext_vf8 , rv_op_vsext_vf8 , 0 } ,
{ " vsetvli " , rv_codec_vsetvli , rv_fmt_vsetvli , NULL , rv_op_vsetvli , rv_op_vsetvli , 0 } ,
{ " vsetivli " , rv_codec_vsetivli , rv_fmt_vsetivli , NULL , rv_op_vsetivli , rv_op_vsetivli , 0 } ,
{ " vsetvl " , rv_codec_r , rv_fmt_rd_rs1_rs2 , NULL , rv_op_vsetvl , rv_op_vsetvl , 0 }
{ " vsetvl " , rv_codec_r , rv_fmt_rd_rs1_rs2 , NULL , rv_op_vsetvl , rv_op_vsetvl , 0 } ,
{ " c.zext.b " , rv_codec_zcb_ext , rv_fmt_rd , NULL , 0 } ,
{ " c.sext.b " , rv_codec_zcb_ext , rv_fmt_rd , NULL , 0 } ,
{ " c.zext.h " , rv_codec_zcb_ext , rv_fmt_rd , NULL , 0 } ,
{ " c.sext.h " , rv_codec_zcb_ext , rv_fmt_rd , NULL , 0 } ,
{ " c.zext.w " , rv_codec_zcb_ext , rv_fmt_rd , NULL , 0 } ,
{ " c.not " , rv_codec_zcb_ext , rv_fmt_rd , NULL , 0 } ,
{ " c.mul " , rv_codec_zcb_mul , rv_fmt_rd_rs2 , NULL , 0 , 0 } ,
{ " c.lbu " , rv_codec_zcb_lb , rv_fmt_rs1_rs2_zce_ldst , NULL , 0 , 0 , 0 } ,
{ " c.lhu " , rv_codec_zcb_lh , rv_fmt_rs1_rs2_zce_ldst , NULL , 0 , 0 , 0 } ,
{ " c.lh " , rv_codec_zcb_lh , rv_fmt_rs1_rs2_zce_ldst , NULL , 0 , 0 , 0 } ,
{ " c.sb " , rv_codec_zcb_lb , rv_fmt_rs1_rs2_zce_ldst , NULL , 0 , 0 , 0 } ,
{ " c.sh " , rv_codec_zcb_lh , rv_fmt_rs1_rs2_zce_ldst , NULL , 0 , 0 , 0 } ,
{ " cm.push " , rv_codec_zcmp_cm_pushpop , rv_fmt_push_rlist , NULL , 0 , 0 } ,
{ " cm.pop " , rv_codec_zcmp_cm_pushpop , rv_fmt_pop_rlist , NULL , 0 , 0 } ,
{ " cm.popret " , rv_codec_zcmp_cm_pushpop , rv_fmt_pop_rlist , NULL , 0 , 0 , 0 } ,
{ " cm.popretz " , rv_codec_zcmp_cm_pushpop , rv_fmt_pop_rlist , NULL , 0 , 0 } ,
{ " cm.mva01s " , rv_codec_zcmp_cm_mv , rv_fmt_rd_rs2 , NULL , 0 , 0 , 0 } ,
{ " cm.mvsa01 " , rv_codec_zcmp_cm_mv , rv_fmt_rd_rs2 , NULL , 0 , 0 , 0 } ,
{ " cm.jt " , rv_codec_zcmt_jt , rv_fmt_zcmt_index , NULL , 0 } ,
{ " cm.jalt " , rv_codec_zcmt_jt , rv_fmt_zcmt_index , NULL , 0 } ,
} ;
/* CSR names */
@ -2085,6 +2137,7 @@ static const char *csr_name(int csrno)
case 0x000a : return " vxrm " ;
case 0x000f : return " vcsr " ;
case 0x0015 : return " seed " ;
case 0x0017 : return " jvt " ;
case 0x0040 : return " uscratch " ;
case 0x0041 : return " uepc " ;
case 0x0042 : return " ucause " ;
@ -2307,6 +2360,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
op = rv_op_c_ld ;
}
break ;
case 4 :
switch ( ( inst > > 10 ) & 0 b111 ) {
case 0 : op = rv_op_c_lbu ; break ;
case 1 :
if ( ( ( inst > > 6 ) & 1 ) = = 0 ) {
op = rv_op_c_lhu ;
} else {
op = rv_op_c_lh ;
}
break ;
case 2 : op = rv_op_c_sb ; break ;
case 3 :
if ( ( ( inst > > 6 ) & 1 ) = = 0 ) {
op = rv_op_c_sh ;
}
break ;
}
break ;
case 5 :
if ( isa = = rv128 ) {
op = rv_op_c_sq ;
@ -2363,6 +2434,17 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
case 3 : op = rv_op_c_and ; break ;
case 4 : op = rv_op_c_subw ; break ;
case 5 : op = rv_op_c_addw ; break ;
case 6 : op = rv_op_c_mul ; break ;
case 7 :
switch ( ( inst > > 2 ) & 0 b111 ) {
case 0 : op = rv_op_c_zext_b ; break ;
case 1 : op = rv_op_c_sext_b ; break ;
case 2 : op = rv_op_c_zext_h ; break ;
case 3 : op = rv_op_c_sext_h ; break ;
case 4 : op = rv_op_c_zext_w ; break ;
case 5 : op = rv_op_c_not ; break ;
}
break ;
}
break ;
}
@ -2418,6 +2500,46 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
op = rv_op_c_sqsp ;
} else {
op = rv_op_c_fsdsp ;
if ( ( ( inst > > 12 ) & 0 b01 ) ) {
switch ( ( inst > > 8 ) & 0 b01111 ) {
case 8 :
if ( ( ( inst > > 4 ) & 0 b01111 ) > = 4 ) {
op = rv_op_cm_push ;
}
break ;
case 10 :
if ( ( ( inst > > 4 ) & 0 b01111 ) > = 4 ) {
op = rv_op_cm_pop ;
}
break ;
case 12 :
if ( ( ( inst > > 4 ) & 0 b01111 ) > = 4 ) {
op = rv_op_cm_popretz ;
}
break ;
case 14 :
if ( ( ( inst > > 4 ) & 0 b01111 ) > = 4 ) {
op = rv_op_cm_popret ;
}
break ;
}
} else {
switch ( ( inst > > 10 ) & 0 b011 ) {
case 0 :
if ( ( ( inst > > 2 ) & 0xFF ) > = 32 ) {
op = rv_op_cm_jalt ;
} else {
op = rv_op_cm_jt ;
}
break ;
case 3 :
switch ( ( inst > > 5 ) & 0 b011 ) {
case 1 : op = rv_op_cm_mvsa01 ; break ;
case 3 : op = rv_op_cm_mva01s ; break ;
}
break ;
}
}
}
break ;
case 6 : op = rv_op_c_swsp ; break ;
@ -3662,6 +3784,21 @@ static uint32_t operand_crs2q(rv_inst inst)
return ( inst < < 59 ) > > 61 ;
}
static uint32_t calculate_xreg ( uint32_t sreg )
{
return sreg < 2 ? sreg + 8 : sreg + 16 ;
}
static uint32_t operand_sreg1 ( rv_inst inst )
{
return calculate_xreg ( ( inst < < 54 ) > > 61 ) ;
}
static uint32_t operand_sreg2 ( rv_inst inst )
{
return calculate_xreg ( ( inst < < 59 ) > > 61 ) ;
}
static uint32_t operand_crd ( rv_inst inst )
{
return ( inst < < 52 ) > > 59 ;
@ -3884,6 +4021,46 @@ static uint32_t operand_vm(rv_inst inst)
return ( inst < < 38 ) > > 63 ;
}
static uint32_t operand_uimm_c_lb ( rv_inst inst )
{
return ( ( ( inst < < 58 ) > > 63 ) < < 1 ) |
( ( inst < < 57 ) > > 63 ) ;
}
static uint32_t operand_uimm_c_lh ( rv_inst inst )
{
return ( ( ( inst < < 58 ) > > 63 ) < < 1 ) ;
}
static uint32_t operand_zcmp_spimm ( rv_inst inst )
{
return ( ( inst < < 60 ) > > 62 ) < < 4 ;
}
static uint32_t operand_zcmp_rlist ( rv_inst inst )
{
return ( ( inst < < 56 ) > > 60 ) ;
}
static uint32_t calculate_stack_adj ( rv_isa isa , uint32_t rlist , uint32_t spimm )
{
int xlen_bytes_log2 = isa = = rv64 ? 3 : 2 ;
int regs = rlist = = 15 ? 13 : rlist - 3 ;
uint32_t stack_adj_base = ROUND_UP ( regs < < xlen_bytes_log2 , 16 ) ;
return stack_adj_base + spimm ;
}
static uint32_t operand_zcmp_stack_adj ( rv_inst inst , rv_isa isa )
{
return calculate_stack_adj ( isa , operand_zcmp_rlist ( inst ) ,
operand_zcmp_spimm ( inst ) ) ;
}
static uint32_t operand_tbl_index ( rv_inst inst )
{
return ( ( inst < < 54 ) > > 56 ) ;
}
/* decode operands */
static void decode_inst_operands ( rv_decode * dec , rv_isa isa )
@ -4200,6 +4377,34 @@ static void decode_inst_operands(rv_decode *dec, rv_isa isa)
dec - > imm = operand_vimm ( inst ) ;
dec - > vzimm = operand_vzimm10 ( inst ) ;
break ;
case rv_codec_zcb_lb :
dec - > rs1 = operand_crs1q ( inst ) + 8 ;
dec - > rs2 = operand_crs2q ( inst ) + 8 ;
dec - > imm = operand_uimm_c_lb ( inst ) ;
break ;
case rv_codec_zcb_lh :
dec - > rs1 = operand_crs1q ( inst ) + 8 ;
dec - > rs2 = operand_crs2q ( inst ) + 8 ;
dec - > imm = operand_uimm_c_lh ( inst ) ;
break ;
case rv_codec_zcb_ext :
dec - > rd = operand_crs1q ( inst ) + 8 ;
break ;
case rv_codec_zcb_mul :
dec - > rd = operand_crs1rdq ( inst ) + 8 ;
dec - > rs2 = operand_crs2q ( inst ) + 8 ;
break ;
case rv_codec_zcmp_cm_pushpop :
dec - > imm = operand_zcmp_stack_adj ( inst , isa ) ;
dec - > rlist = operand_zcmp_rlist ( inst ) ;
break ;
case rv_codec_zcmp_cm_mv :
dec - > rd = operand_sreg1 ( inst ) ;
dec - > rs2 = operand_sreg2 ( inst ) ;
break ;
case rv_codec_zcmt_jt :
dec - > imm = operand_tbl_index ( inst ) ;
break ;
} ;
}
@ -4359,6 +4564,9 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
case ' ) ' :
append ( buf , " ) " , buflen ) ;
break ;
case ' - ' :
append ( buf , " - " , buflen ) ;
break ;
case ' b ' :
snprintf ( tmp , sizeof ( tmp ) , " %d " , dec - > bs ) ;
append ( buf , tmp , buflen ) ;
@ -4542,6 +4750,24 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
append ( buf , vma , buflen ) ;
break ;
}
case ' x ' : {
switch ( dec - > rlist ) {
case 4 :
snprintf ( tmp , sizeof ( tmp ) , " {ra} " ) ;
break ;
case 5 :
snprintf ( tmp , sizeof ( tmp ) , " {ra, s0} " ) ;
break ;
case 15 :
snprintf ( tmp , sizeof ( tmp ) , " {ra, s0-s11} " ) ;
break ;
default :
snprintf ( tmp , sizeof ( tmp ) , " {ra, s0-s%d} " , dec - > rlist - 5 ) ;
break ;
}
append ( buf , tmp , buflen ) ;
break ;
}
default :
break ;
}