diff options
Diffstat (limited to 'target/riscv/cpu_helper.c')
| -rw-r--r-- | target/riscv/cpu_helper.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 9eeed38c7e..10f3baba53 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -75,12 +75,22 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, *cs_base = 0; if (riscv_has_ext(env, RVV)) { + /* + * If env->vl equals to VLMAX, we can use generic vector operation + * expanders (GVEC) to accerlate the vector operations. + * However, as LMUL could be a fractional number. The maximum + * vector size can be operated might be less than 8 bytes, + * which is not supported by GVEC. So we set vl_eq_vlmax flag to true + * only when maxsz >= 8 bytes. + */ uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype); - bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl); + uint32_t sew = FIELD_EX64(env->vtype, VTYPE, VSEW); + uint32_t maxsz = vlmax << sew; + bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) && + (maxsz >= 8); flags = FIELD_DP32(flags, TB_FLAGS, VILL, FIELD_EX64(env->vtype, VTYPE, VILL)); - flags = FIELD_DP32(flags, TB_FLAGS, SEW, - FIELD_EX64(env->vtype, VTYPE, VSEW)); + flags = FIELD_DP32(flags, TB_FLAGS, SEW, sew); flags = FIELD_DP32(flags, TB_FLAGS, LMUL, FIELD_EX64(env->vtype, VTYPE, VLMUL)); flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax); @@ -90,12 +100,17 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, #ifdef CONFIG_USER_ONLY flags |= TB_FLAGS_MSTATUS_FS; + flags |= TB_FLAGS_MSTATUS_VS; #else flags |= cpu_mmu_index(env, 0); if (riscv_cpu_fp_enabled(env)) { flags |= env->mstatus & MSTATUS_FS; } + if (riscv_cpu_vector_enabled(env)) { + flags |= env->mstatus & MSTATUS_VS; + } + if (riscv_has_ext(env, RVH)) { if (env->priv == PRV_M || (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || @@ -106,6 +121,9 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS, get_field(env->mstatus_hs, MSTATUS_FS)); + + flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS, + get_field(env->mstatus_hs, MSTATUS_VS)); } if (riscv_has_ext(env, RVJ)) { int priv = flags & TB_FLAGS_PRIV_MMU_MASK; @@ -189,11 +207,24 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env) return false; } +/* Return true is vector support is currently enabled */ +bool riscv_cpu_vector_enabled(CPURISCVState *env) +{ + if (env->mstatus & MSTATUS_VS) { + if (riscv_cpu_virt_enabled(env) && !(env->mstatus_hs & MSTATUS_VS)) { + return false; + } + return true; + } + + return false; +} + void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env) { uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS | MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE | - MSTATUS64_UXL; + MSTATUS64_UXL | MSTATUS_VS; bool current_virt = riscv_cpu_virt_enabled(env); g_assert(riscv_has_ext(env, RVH)); |