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