From: Frank Chang <frank.ch...@sifive.com> Signed-off-by: Frank Chang <frank.ch...@sifive.com> --- target/riscv/helper.h | 2 +- target/riscv/insn_trans/trans_rvv.inc.c | 52 ++++++++++++------------- target/riscv/vector_helper.c | 38 ++++++++++++------ 3 files changed, 53 insertions(+), 39 deletions(-)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h index acc298219d..5939897a82 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -83,7 +83,7 @@ DEF_HELPER_1(hyp_tlb_flush, void, env) #endif /* Vector functions */ -DEF_HELPER_3(vsetvl, tl, env, tl, tl) +DEF_HELPER_5(vsetvl, tl, env, i32, i32, tl, tl) DEF_HELPER_5(vlb_v_b, void, ptr, ptr, tl, env, i32) DEF_HELPER_5(vlb_v_b_mask, void, ptr, ptr, tl, env, i32) DEF_HELPER_5(vlb_v_h, void, ptr, ptr, tl, env, i32) diff --git a/target/riscv/insn_trans/trans_rvv.inc.c b/target/riscv/insn_trans/trans_rvv.inc.c index fc1908389e..da8e7598e9 100644 --- a/target/riscv/insn_trans/trans_rvv.inc.c +++ b/target/riscv/insn_trans/trans_rvv.inc.c @@ -72,33 +72,32 @@ static inline bool is_overlapped_widen(const int astart, int asize, } } -static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl *a) +static bool trans_vsetvl(DisasContext *s, arg_vsetvl *a) { + TCGv_i32 rd, rs1; TCGv s1, s2, dst; REQUIRE_RVV; - if (!has_ext(ctx, RVV)) { + if (!has_ext(s, RVV)) { return false; } + rd = tcg_const_i32(a->rd); + rs1 = tcg_const_i32(a->rs1); + s1 = tcg_temp_new(); s2 = tcg_temp_new(); dst = tcg_temp_new(); - /* Using x0 as the rs1 register specifier, encodes an infinite AVL */ - if (a->rs1 == 0) { - /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */ - s1 = tcg_const_tl(RV_VLEN_MAX); - } else { - s1 = tcg_temp_new(); - gen_get_gpr(s1, a->rs1); - } + gen_get_gpr(s1, a->rs1); gen_get_gpr(s2, a->rs2); - gen_helper_vsetvl(dst, cpu_env, s1, s2); + gen_helper_vsetvl(dst, cpu_env, rd, rs1, s1, s2); gen_set_gpr(a->rd, dst); - tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); - lookup_and_goto_ptr(ctx); - ctx->base.is_jmp = DISAS_NORETURN; + tcg_gen_movi_tl(cpu_pc, s->pc_succ_insn); + lookup_and_goto_ptr(s); + s->base.is_jmp = DISAS_NORETURN; + tcg_temp_free_i32(rd); + tcg_temp_free_i32(rs1); tcg_temp_free(s1); tcg_temp_free(s2); tcg_temp_free(dst); @@ -106,31 +105,30 @@ static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl *a) return true; } -static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli *a) +static bool trans_vsetvli(DisasContext *s, arg_vsetvli *a) { + TCGv_i32 rd, rs1; TCGv s1, s2, dst; REQUIRE_RVV; - if (!has_ext(ctx, RVV)) { + if (!has_ext(s, RVV)) { return false; } + rd = tcg_const_i32(a->rd); + rs1 = tcg_const_i32(a->rs1); + s1 = tcg_temp_new(); s2 = tcg_const_tl(a->zimm); dst = tcg_temp_new(); - /* Using x0 as the rs1 register specifier, encodes an infinite AVL */ - if (a->rs1 == 0) { - /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */ - s1 = tcg_const_tl(RV_VLEN_MAX); - } else { - s1 = tcg_temp_new(); - gen_get_gpr(s1, a->rs1); - } - gen_helper_vsetvl(dst, cpu_env, s1, s2); + gen_get_gpr(s1, a->rs1); + gen_helper_vsetvl(dst, cpu_env, rd, rs1, s1, s2); gen_set_gpr(a->rd, dst); - gen_goto_tb(ctx, 0, ctx->pc_succ_insn); - ctx->base.is_jmp = DISAS_NORETURN; + gen_goto_tb(s, 0, s->pc_succ_insn); + s->base.is_jmp = DISAS_NORETURN; + tcg_temp_free_i32(rd); + tcg_temp_free_i32(rs1); tcg_temp_free(s1); tcg_temp_free(s2); tcg_temp_free(dst); diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index db54288c08..1279ef4fb1 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -26,33 +26,49 @@ #include "internals.h" #include <math.h> -target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1, - target_ulong s2) +target_ulong HELPER(vsetvl)(CPURISCVState *env, uint32_t rd, uint32_t rs1, + target_ulong s1, target_ulong s2) { - int vlmax, vl; + int vlmax; + int vl = 0; + RISCVCPU *cpu = env_archcpu(env); uint16_t sew = 8 << FIELD_EX64(s2, VTYPE, VSEW); uint8_t ediv = FIELD_EX64(s2, VTYPE, VEDIV); bool vill = FIELD_EX64(s2, VTYPE, VILL); + vlmax = vext_get_vlmax(cpu, s2); target_ulong reserved = FIELD_EX64(s2, VTYPE, RESERVED); - if ((sew > cpu->cfg.elen) || vill || (ediv != 0) || (reserved != 0)) { + uint64_t lmul = (FIELD_EX64(s2, VTYPE, VFLMUL) << 2) + | FIELD_EX64(s2, VTYPE, VLMUL); + float vflmul = flmul_table[lmul]; + + if ((sew > cpu->cfg.elen) + || vill + || vflmul < ((float)sew / cpu->cfg.elen) + || (ediv != 0) + || (reserved != 0)) { /* only set vill bit. */ env->vtype = FIELD_DP64(0, VTYPE, VILL, 1); - env->vl = 0; - env->vstart = 0; return 0; } - vlmax = vext_get_vlmax(cpu, s2); - if (s1 <= vlmax) { - vl = s1; - } else { + /* set vl */ + if (rd == 0 && rs1 == 0) { + /* keep existing vl */ + vl = env->vl > vlmax ? vlmax : env->vl; + } else if (rd != 0 && rs1 == 0) { + /* set vl to vlmax */ vl = vlmax; + } else if (rs1 != 0) { + /* normal stripmining */ + vl = s1 > vlmax ? vlmax : s1; } - env->vl = vl; + env->vtype = s2; env->vstart = 0; + env->vl = vl; + return vl; } -- 2.17.1