In this patch, we implement the th.vetvl{i} instructions. In the th_vsetvl
function, some work has been done according to the difference between RVV1.0
and XTheadVector.

th.vsetvl{i} differs from vsetvl{i} in the following points:
1. th.vsetvl{i} does not have the option to maintain the existing vl.
2. XTheadVector has different vtype encoding from RVV1.0.

Signed-off-by: Huang Tao <eric.hu...@linux.alibaba.com>
---
 .../riscv/insn_trans/trans_xtheadvector.c.inc | 93 ++++++++++++++++++-
 1 file changed, 91 insertions(+), 2 deletions(-)

diff --git a/target/riscv/insn_trans/trans_xtheadvector.c.inc 
b/target/riscv/insn_trans/trans_xtheadvector.c.inc
index 2dd77d74ab..0461b53893 100644
--- a/target/riscv/insn_trans/trans_xtheadvector.c.inc
+++ b/target/riscv/insn_trans/trans_xtheadvector.c.inc
@@ -25,14 +25,103 @@ static bool require_xtheadvector(DisasContext *s)
            s->mstatus_vs != EXT_STATUS_DISABLED;
 }
 
+/*
+ * XTheadVector has different vtype encoding from RVV1.0.
+ * We recode the value in RVV1.0 vtype format to reuse the RVV1.0 functions.
+ * In RVV1.0:
+ *   vtype[7] -> vma
+ *   vtype[6] -> vta
+ *   vtype[5:3] -> vsew
+ *   vtype[2:0] -> vlmul
+ * In XTheadVector:
+ *   vtype[6:5] -> vediv (reserved)
+ *   vtype[4:2] -> vsew
+ *   vtype[1:0] -> vlmul
+ *
+ * Also th_vsetvl does not have feature of keeping existing vl when
+ * (rd == 0 && rs1 == 0)
+ */
+static bool th_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2)
+{
+    TCGv temp = tcg_temp_new();
+    TCGv dst_s2 = tcg_temp_new();
+    /* illegal value check*/
+    TCGLabel *legal = gen_new_label();
+    tcg_gen_shri_tl(temp, s2, 5);
+    tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, legal);
+    /*
+     * if illegal, set unsupported value
+     * s2[8:5] == 0b111, which is reserved field in XTheadVector
+     */
+    tcg_gen_movi_tl(s2, 0xff);
+    gen_set_label(legal);
+    /* get vlmul, s2[1:0] -> dst_s2[2:0] */
+    tcg_gen_andi_tl(dst_s2, s2, 0x3);
+    /* get vsew, s2[4:2] -> dst_s2[5:3] */
+    tcg_gen_andi_tl(temp, s2, 0x1c);
+    tcg_gen_shli_tl(temp, temp, 1);
+    tcg_gen_or_tl(dst_s2, dst_s2, temp);
+    /*
+     * get reserved field when illegal, s2[7:5] -> dst_s2[10:8]
+     * avoid dst_s2[7:6], because dst_s2[7:6] are vma and vta.
+     *
+     * Make the dst_s2 an illegal value for RVV1.0, leads to the illegal
+     * operation processing flow.
+     */
+    tcg_gen_andi_tl(temp, s2, 0xe0);
+    tcg_gen_shli_tl(temp, temp, 3);
+    tcg_gen_or_tl(dst_s2, dst_s2, temp);
+
+    /*
+     * We can't reuse do_vsetvl for we don't have ext_zve32f
+     * The code below is almost copied from rvv do_vsetvl
+     * delete zve32f check and the situation when rd = rs1 = 0
+     */
+    TCGv s1, dst;
+    dst = dest_gpr(s, rd);
+    if (rs1 == 0) {
+        /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */
+        s1 = tcg_constant_tl(RV_VLEN_MAX);
+    } else {
+        s1 = get_gpr(s, rs1, EXT_ZERO);
+    }
+
+    gen_helper_vsetvl(dst, tcg_env, s1, dst_s2);
+    gen_set_gpr(s, rd, dst);
+    mark_vs_dirty(s);
+
+    gen_update_pc(s, s->cur_insn_len);
+    lookup_and_goto_ptr(s);
+    s->base.is_jmp = DISAS_NORETURN;
+    return true;
+}
+
+static bool trans_th_vsetvl(DisasContext *s, arg_th_vsetvl *a)
+{
+    if (!require_xtheadvector(s)) {
+        return false;
+    }
+
+    TCGv s2 = get_gpr(s, a->rs2, EXT_ZERO);
+    return th_vsetvl(s, a->rd, a->rs1, s2);
+}
+
+static bool trans_th_vsetvli(DisasContext *s, arg_th_vsetvli *a)
+{
+    if (!require_xtheadvector(s)) {
+        return false;
+    }
+
+    TCGv s2 = tcg_constant_tl(a->zimm);
+    return th_vsetvl(s, a->rd, a->rs1, s2);
+}
+
 #define TH_TRANS_STUB(NAME)                                \
 static bool trans_##NAME(DisasContext *s, arg_##NAME *a)   \
 {                                                          \
     return require_xtheadvector(s);                        \
 }
 
-TH_TRANS_STUB(th_vsetvli)
-TH_TRANS_STUB(th_vsetvl)
 TH_TRANS_STUB(th_vlb_v)
 TH_TRANS_STUB(th_vlh_v)
 TH_TRANS_STUB(th_vlw_v)
-- 
2.44.0


Reply via email to