diff mbox series

[v7,9/9] disas/riscv.c: add disasm support for Zc*

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

Commit Message

Weiwei Li Nov. 29, 2022, 2:43 a.m. UTC
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(-)

Comments

Shaobo Song Nov. 30, 2022, 3:04 a.m. UTC | #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
>
>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

>
Shaobo Song Nov. 30, 2022, 5:38 a.m. UTC | #2
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
>
Weiwei Li Nov. 30, 2022, 7:08 a.m. UTC | #3
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 mbox series

Patch

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;
         }