Message ID | 20221129024343.20384-10-liweiwei@iscas.ac.cn (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | support subsets of code size reduction extension | expand |
At 2022-11-29 10:43:43, "Weiwei Li" <liweiwei@iscas.ac.cn> wrote: >Zcmp/Zcmt instructions will override disasm for c.fld*/c.fsd* >instructions currently > >Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn> >Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn> >Acked-by: Alistair Francis <alistair.francis@wdc.com> >--- > disas/riscv.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 286 insertions(+), 1 deletion(-) > >diff --git a/disas/riscv.c b/disas/riscv.c >index d216b9c39b..81369063b5 100644 >--- a/disas/riscv.c >+++ b/disas/riscv.c >@@ -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 { >@@ -1070,6 +1098,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 */ > >@@ -2065,7 +2097,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 */ >@@ -2084,6 +2136,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"; >@@ -2306,6 +2359,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) > op = rv_op_c_ld; > } > break; >+ case 4: >+ switch ((inst >> 10) & 0b111) { >+ 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; >@@ -2362,6 +2433,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) & 0b111) { >+ 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; > } >@@ -2417,6 +2499,30 @@ 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) & 0b01)) { >+ switch ((inst >> 8) & 0b01111) { >+ case 8: op = rv_op_cm_push; break; >+ case 10: op = rv_op_cm_pop; break; >+ case 12: op = rv_op_cm_popretz; break; >+ case 14: op = rv_op_cm_popret; break; >+ } >+ } else { >+ switch ((inst >> 10) & 0b011) { >+ case 0: >+ if (((inst >> 2) & 0xFF) >= 32) { >+ op = rv_op_cm_jalt; >+ } else { >+ op = rv_op_cm_jt; >+ } >+ break; >+ case 3: >+ switch ((inst >> 5) & 0b011) { >+ 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; >@@ -3661,6 +3767,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; >@@ -3883,6 +4004,97 @@ 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) >+{ >+ uint32_t stack_adj_base = 0; >+ if (isa == rv64) { >+ switch (rlist) { >+ case 15: >+ stack_adj_base = 112; >+ break; >+ case 14: >+ stack_adj_base = 96; >+ break; >+ case 13: >+ case 12: >+ stack_adj_base = 80; >+ break; >+ case 11: >+ case 10: >+ stack_adj_base = 64; >+ break; >+ case 9: >+ case 8: >+ stack_adj_base = 48; >+ break; >+ case 7: >+ case 6: >+ stack_adj_base = 32; >+ break; >+ case 5: >+ case 4: >+ stack_adj_base = 16; >+ break; >+ } >+ } else { >+ switch (rlist) { >+ case 15: >+ stack_adj_base = 64; >+ break; >+ case 14: >+ case 13: >+ case 12: >+ stack_adj_base = 48; >+ break; >+ case 11: >+ case 10: >+ case 9: >+ case 8: >+ stack_adj_base = 32; >+ break; >+ case 7: >+ case 6: >+ case 5: >+ case 4: >+ stack_adj_base = 16; >+ break; >+ } >+ } I think you can be simply: int target_long_bytes_log2 = isa == rv64 ? 3 : 2; int regs = rlist == 15 ? 13 : rlist - 3; stack_adj_base = ROUND_UP(regs << target_long_bytes_log2, 16); may get closer to the description of spec. Shabo Song >+ 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) >@@ -4199,6 +4411,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; > }; > } > >@@ -4358,6 +4598,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); >@@ -4541,6 +4784,48 @@ 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 6: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s1}"); >+ break; >+ case 7: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s2}"); >+ break; >+ case 8: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s3}"); >+ break; >+ case 9: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s4}"); >+ break; >+ case 10: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s5}"); >+ break; >+ case 11: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s6}"); >+ break; >+ case 12: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s7}"); >+ break; >+ case 13: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s8}"); >+ break; >+ case 14: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s9}"); >+ break; >+ case 15: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s11}"); >+ break; >+ } >+ append(buf, tmp, buflen); >+ break; >+ } > default: > break; > } >-- >2.25.1 >
At 2022-11-29 10:43:43, "Weiwei Li" <liweiwei@iscas.ac.cn> wrote: >Zcmp/Zcmt instructions will override disasm for c.fld*/c.fsd* >instructions currently we might make a encode using top 16 bits of flags in struct disassemble_info, to describe enable status of zc-subsets. Then we can pass it to disasm_inst in print_insn_riscv. But I don't know if flags have any others. > >Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn> >Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn> >Acked-by: Alistair Francis <alistair.francis@wdc.com> >--- > disas/riscv.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 286 insertions(+), 1 deletion(-) > >diff --git a/disas/riscv.c b/disas/riscv.c >index d216b9c39b..81369063b5 100644 >--- a/disas/riscv.c >+++ b/disas/riscv.c >@@ -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 { >@@ -1070,6 +1098,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 */ > >@@ -2065,7 +2097,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 */ >@@ -2084,6 +2136,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"; >@@ -2306,6 +2359,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) > op = rv_op_c_ld; > } > break; >+ case 4: >+ switch ((inst >> 10) & 0b111) { >+ 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; >@@ -2362,6 +2433,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) & 0b111) { >+ 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; > } >@@ -2417,6 +2499,30 @@ 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) & 0b01)) { >+ switch ((inst >> 8) & 0b01111) { >+ case 8: op = rv_op_cm_push; break; >+ case 10: op = rv_op_cm_pop; break; >+ case 12: op = rv_op_cm_popretz; break; >+ case 14: op = rv_op_cm_popret; break; >+ } >+ } else { >+ switch ((inst >> 10) & 0b011) { >+ case 0: >+ if (((inst >> 2) & 0xFF) >= 32) { >+ op = rv_op_cm_jalt; >+ } else { >+ op = rv_op_cm_jt; >+ } >+ break; >+ case 3: >+ switch ((inst >> 5) & 0b011) { >+ 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; >@@ -3661,6 +3767,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; >@@ -3883,6 +4004,97 @@ 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) >+{ >+ uint32_t stack_adj_base = 0; >+ if (isa == rv64) { >+ switch (rlist) { >+ case 15: >+ stack_adj_base = 112; >+ break; >+ case 14: >+ stack_adj_base = 96; >+ break; >+ case 13: >+ case 12: >+ stack_adj_base = 80; >+ break; >+ case 11: >+ case 10: >+ stack_adj_base = 64; >+ break; >+ case 9: >+ case 8: >+ stack_adj_base = 48; >+ break; >+ case 7: >+ case 6: >+ stack_adj_base = 32; >+ break; >+ case 5: >+ case 4: >+ stack_adj_base = 16; >+ break; >+ } >+ } else { >+ switch (rlist) { >+ case 15: >+ stack_adj_base = 64; >+ break; >+ case 14: >+ case 13: >+ case 12: >+ stack_adj_base = 48; >+ break; >+ case 11: >+ case 10: >+ case 9: >+ case 8: >+ stack_adj_base = 32; >+ break; >+ case 7: >+ case 6: >+ case 5: >+ case 4: >+ stack_adj_base = 16; >+ break; >+ } >+ } >+ 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) >@@ -4199,6 +4411,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; > }; > } > >@@ -4358,6 +4598,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); >@@ -4541,6 +4784,48 @@ 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 6: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s1}"); >+ break; >+ case 7: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s2}"); >+ break; >+ case 8: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s3}"); >+ break; >+ case 9: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s4}"); >+ break; >+ case 10: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s5}"); >+ break; >+ case 11: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s6}"); >+ break; >+ case 12: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s7}"); >+ break; >+ case 13: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s8}"); >+ break; >+ case 14: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s9}"); >+ break; >+ case 15: >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s11}"); >+ break; >+ } >+ append(buf, tmp, buflen); >+ break; >+ } > default: > break; > } >-- >2.25.1 >
On 2022/11/30 11:04, Shaobo Song wrote: > > At 2022-11-29 10:43:43, "Weiwei Li" <liweiwei@iscas.ac.cn> wrote: > > >Zcmp/Zcmt instructions will override disasm for c.fld*/c.fsd* > >instructions currently > > > >Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn> > >Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn> > >Acked-by: Alistair Francis <alistair.francis@wdc.com> > >--- > > disas/riscv.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++- > > 1 file changed, 286 insertions(+), 1 deletion(-) > > > >diff --git a/disas/riscv.c b/disas/riscv.c > >index d216b9c39b..81369063b5 100644 > >--- a/disas/riscv.c > >+++ b/disas/riscv.c > >@@ -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 { > >@@ -1070,6 +1098,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 */ > > > >@@ -2065,7 +2097,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 */ > >@@ -2084,6 +2136,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"; > >@@ -2306,6 +2359,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) > > op = rv_op_c_ld; > > } > > break; > >+ case 4: > >+ switch ((inst >> 10) & 0b111) { > >+ 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; > >@@ -2362,6 +2433,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) & 0b111) { > >+ 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; > > } > >@@ -2417,6 +2499,30 @@ 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) & 0b01)) { > >+ switch ((inst >> 8) & 0b01111) { > >+ case 8: op = rv_op_cm_push; break; > >+ case 10: op = rv_op_cm_pop; break; > >+ case 12: op = rv_op_cm_popretz; break; > >+ case 14: op = rv_op_cm_popret; break; > >+ } > >+ } else { > >+ switch ((inst >> 10) & 0b011) { > >+ case 0: > >+ if (((inst >> 2) & 0xFF) >= 32) { > >+ op = rv_op_cm_jalt; > >+ } else { > >+ op = rv_op_cm_jt; > >+ } > >+ break; > >+ case 3: > >+ switch ((inst >> 5) & 0b011) { > >+ 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; > >@@ -3661,6 +3767,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; > >@@ -3883,6 +4004,97 @@ 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) > >+{ > >+ uint32_t stack_adj_base = 0; > >+ if (isa == rv64) { > >+ switch (rlist) { > >+ case 15: > >+ stack_adj_base = 112; > >+ break; > >+ case 14: > >+ stack_adj_base = 96; > >+ break; > >+ case 13: > >+ case 12: > >+ stack_adj_base = 80; > >+ break; > >+ case 11: > >+ case 10: > >+ stack_adj_base = 64; > >+ break; > >+ case 9: > >+ case 8: > >+ stack_adj_base = 48; > >+ break; > >+ case 7: > >+ case 6: > >+ stack_adj_base = 32; > >+ break; > >+ case 5: > >+ case 4: > >+ stack_adj_base = 16; > >+ break; > >+ } > >+ } else { > >+ switch (rlist) { > >+ case 15: > >+ stack_adj_base = 64; > >+ break; > >+ case 14: > >+ case 13: > >+ case 12: > >+ stack_adj_base = 48; > >+ break; > >+ case 11: > >+ case 10: > >+ case 9: > >+ case 8: > >+ stack_adj_base = 32; > >+ break; > >+ case 7: > >+ case 6: > >+ case 5: > >+ case 4: > >+ stack_adj_base = 16; > >+ break; > >+ } > >+ } > I think you can be simply: > int target_long_bytes_log2 = isa == rv64 ? 3 : 2; > int regs = rlist == 15 ? 13 : rlist - 3; > stack_adj_base = ROUND_UP(regs << target_long_bytes_log2, 16); > may get closer to the description of spec. > Shabo Song Yeah, this is similar to the calculation in trans function for Zcmp. I'll update this in next version. Regards, Weiwei Li > >+ 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) > >@@ -4199,6 +4411,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; > > }; > > } > > > >@@ -4358,6 +4598,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); > >@@ -4541,6 +4784,48 @@ 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 6: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s1}"); > >+ break; > >+ case 7: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s2}"); > >+ break; > >+ case 8: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s3}"); > >+ break; > >+ case 9: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s4}"); > >+ break; > >+ case 10: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s5}"); > >+ break; > >+ case 11: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s6}"); > >+ break; > >+ case 12: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s7}"); > >+ break; > >+ case 13: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s8}"); > >+ break; > >+ case 14: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s9}"); > >+ break; > >+ case 15: > >+ snprintf(tmp, sizeof(tmp), "{ra, s0-s11}"); > >+ break; > >+ } > >+ append(buf, tmp, buflen); > >+ break; > >+ } > > default: > > break; > > } > >-- > >2.25.1 > >
diff --git a/disas/riscv.c b/disas/riscv.c index d216b9c39b..81369063b5 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -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 { @@ -1070,6 +1098,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 */ @@ -2065,7 +2097,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 */ @@ -2084,6 +2136,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"; @@ -2306,6 +2359,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) op = rv_op_c_ld; } break; + case 4: + switch ((inst >> 10) & 0b111) { + 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; @@ -2362,6 +2433,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) & 0b111) { + 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; } @@ -2417,6 +2499,30 @@ 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) & 0b01)) { + switch ((inst >> 8) & 0b01111) { + case 8: op = rv_op_cm_push; break; + case 10: op = rv_op_cm_pop; break; + case 12: op = rv_op_cm_popretz; break; + case 14: op = rv_op_cm_popret; break; + } + } else { + switch ((inst >> 10) & 0b011) { + case 0: + if (((inst >> 2) & 0xFF) >= 32) { + op = rv_op_cm_jalt; + } else { + op = rv_op_cm_jt; + } + break; + case 3: + switch ((inst >> 5) & 0b011) { + 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; @@ -3661,6 +3767,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; @@ -3883,6 +4004,97 @@ 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) +{ + uint32_t stack_adj_base = 0; + if (isa == rv64) { + switch (rlist) { + case 15: + stack_adj_base = 112; + break; + case 14: + stack_adj_base = 96; + break; + case 13: + case 12: + stack_adj_base = 80; + break; + case 11: + case 10: + stack_adj_base = 64; + break; + case 9: + case 8: + stack_adj_base = 48; + break; + case 7: + case 6: + stack_adj_base = 32; + break; + case 5: + case 4: + stack_adj_base = 16; + break; + } + } else { + switch (rlist) { + case 15: + stack_adj_base = 64; + break; + case 14: + case 13: + case 12: + stack_adj_base = 48; + break; + case 11: + case 10: + case 9: + case 8: + stack_adj_base = 32; + break; + case 7: + case 6: + case 5: + case 4: + stack_adj_base = 16; + break; + } + } + 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) @@ -4199,6 +4411,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; }; } @@ -4358,6 +4598,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); @@ -4541,6 +4784,48 @@ 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 6: + snprintf(tmp, sizeof(tmp), "{ra, s0-s1}"); + break; + case 7: + snprintf(tmp, sizeof(tmp), "{ra, s0-s2}"); + break; + case 8: + snprintf(tmp, sizeof(tmp), "{ra, s0-s3}"); + break; + case 9: + snprintf(tmp, sizeof(tmp), "{ra, s0-s4}"); + break; + case 10: + snprintf(tmp, sizeof(tmp), "{ra, s0-s5}"); + break; + case 11: + snprintf(tmp, sizeof(tmp), "{ra, s0-s6}"); + break; + case 12: + snprintf(tmp, sizeof(tmp), "{ra, s0-s7}"); + break; + case 13: + snprintf(tmp, sizeof(tmp), "{ra, s0-s8}"); + break; + case 14: + snprintf(tmp, sizeof(tmp), "{ra, s0-s9}"); + break; + case 15: + snprintf(tmp, sizeof(tmp), "{ra, s0-s11}"); + break; + } + append(buf, tmp, buflen); + break; + } default: break; }