@@ -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)
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.huang@linux.alibaba.com> --- .../riscv/insn_trans/trans_xtheadvector.c.inc | 93 ++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-)