diff mbox series

[v3,2/4] target/riscv: Reuse tb->flags.FS

Message ID 20230428165212.2800669-3-mchitale@ventanamicro.com
State New
Headers show
Series Smstateen FCSR | expand

Commit Message

Mayuresh Chitale April 28, 2023, 4:52 p.m. UTC
When misa.F is 0 tb->flags.FS field is unused and can be used to save
the current state of smstateen0.FCSR check which is needed by the
floating point translation routines.

Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
---
 target/riscv/cpu_helper.c |  9 +++++++++
 target/riscv/translate.c  | 12 +++++++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)

Comments

Weiwei Li April 29, 2023, 1:17 a.m. UTC | #1
On 2023/4/29 00:52, Mayuresh Chitale wrote:
> When misa.F is 0 tb->flags.FS field is unused and can be used to save
> the current state of smstateen0.FCSR check which is needed by the
> floating point translation routines.
>
> Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
> ---

Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>

Weiwei Li

>   target/riscv/cpu_helper.c |  9 +++++++++
>   target/riscv/translate.c  | 12 +++++++++++-
>   2 files changed, 20 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index b68dcfe7b6..126ac221a0 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -119,6 +119,15 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>           vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
>       }
>   
> +    /*
> +     * If misa.F is 0 then the FS field of the tb->flags can be used to pass
> +     * the current state of the smstateen.FCSR bit which must be checked for
> +     * in the floating point translation routines.
> +     */
> +    if (!riscv_has_ext(env, RVF)) {
> +        fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE);
> +    }
> +
>       if (cpu->cfg.debug && !icount_enabled()) {
>           flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
>       }
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 928da0d3f0..74f624aa62 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -78,6 +78,7 @@ typedef struct DisasContext {
>       int frm;
>       RISCVMXL ol;
>       bool virt_inst_excp;
> +    bool smstateen_fcsr_ok;
>       bool virt_enabled;
>       const RISCVCPUConfig *cfg_ptr;
>       /* vector extension */
> @@ -1155,7 +1156,11 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>       ctx->pc_succ_insn = ctx->base.pc_first;
>       ctx->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV);
>       ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
> -    ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
> +    if (has_ext(ctx, RVF)) {
> +        ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
> +    } else {
> +        ctx->mstatus_fs = 0;
> +    }
>       ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
>       ctx->priv_ver = env->priv_ver;
>       ctx->virt_enabled = FIELD_EX32(tb_flags, TB_FLAGS, VIRT_ENABLED);
> @@ -1178,6 +1183,11 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>       ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
>       ctx->zero = tcg_constant_tl(0);
>       ctx->virt_inst_excp = false;
> +    if (has_ext(ctx, RVF) || !cpu->cfg.ext_smstateen) {
> +        ctx->smstateen_fcsr_ok = 1;
> +    } else {
> +        ctx->smstateen_fcsr_ok = FIELD_EX32(tb_flags, TB_FLAGS, FS);
> +    }
>   }
>   
>   static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
Richard Henderson April 29, 2023, 8:54 a.m. UTC | #2
On 4/28/23 17:52, Mayuresh Chitale wrote:
> When misa.F is 0 tb->flags.FS field is unused and can be used to save
> the current state of smstateen0.FCSR check which is needed by the
> floating point translation routines.
> 
> Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
> ---
>   target/riscv/cpu_helper.c |  9 +++++++++
>   target/riscv/translate.c  | 12 +++++++++++-
>   2 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index b68dcfe7b6..126ac221a0 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -119,6 +119,15 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
>           vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
>       }
>   
> +    /*
> +     * If misa.F is 0 then the FS field of the tb->flags can be used to pass
> +     * the current state of the smstateen.FCSR bit which must be checked for
> +     * in the floating point translation routines.
> +     */
> +    if (!riscv_has_ext(env, RVF)) {
> +        fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE);
> +    }

You have misunderstood my suggestion:

     /* With Zfinx, floating point is enabled/disabled by Smstateen. */
     if (!riscv_has_ext(env, RVF)) {
         fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR)
               ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED);
     }

> +    bool smstateen_fcsr_ok;

Not needed.

> -    ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
> +    if (has_ext(ctx, RVF)) {
> +        ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
> +    } else {
> +        ctx->mstatus_fs = 0;
> +    }

Not needed.

In patch 3, which should be merged with this, there are no changes to REQUIRE_ZFINX_OR_F, 
no additional smstateen_fcsr_check, and REQUIRE_FPU reduces to

#define REQUIRE_FPU do {                          \
     if (ctx->mstatus_fs == EXT_STATUS_DISABLED) { \
         return false;                             \
     }                                             \
} while (0)

This makes the DisasContext version of fs be the single gate for floating point.
No extra checks required.


r~
Weiwei Li April 29, 2023, 9:20 a.m. UTC | #3
On 2023/4/29 16:54, Richard Henderson wrote:
> On 4/28/23 17:52, Mayuresh Chitale wrote:
>> When misa.F is 0 tb->flags.FS field is unused and can be used to save
>> the current state of smstateen0.FCSR check which is needed by the
>> floating point translation routines.
>>
>> Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
>> ---
>>   target/riscv/cpu_helper.c |  9 +++++++++
>>   target/riscv/translate.c  | 12 +++++++++++-
>>   2 files changed, 20 insertions(+), 1 deletion(-)
>>
>> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
>> index b68dcfe7b6..126ac221a0 100644
>> --- a/target/riscv/cpu_helper.c
>> +++ b/target/riscv/cpu_helper.c
>> @@ -119,6 +119,15 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, 
>> target_ulong *pc,
>>           vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
>>       }
>>   +    /*
>> +     * If misa.F is 0 then the FS field of the tb->flags can be used 
>> to pass
>> +     * the current state of the smstateen.FCSR bit which must be 
>> checked for
>> +     * in the floating point translation routines.
>> +     */
>> +    if (!riscv_has_ext(env, RVF)) {
>> +        fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == 
>> RISCV_EXCP_NONE);
>> +    }
>
> You have misunderstood my suggestion:
>
>     /* With Zfinx, floating point is enabled/disabled by Smstateen. */
>     if (!riscv_has_ext(env, RVF)) {
>         fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR)
>               ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED);
>     }
>
>> +    bool smstateen_fcsr_ok;
>
> Not needed.
>
>> -    ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
>> +    if (has_ext(ctx, RVF)) {
>> +        ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
>> +    } else {
>> +        ctx->mstatus_fs = 0;
>> +    }
>
> Not needed.
>
> In patch 3, which should be merged with this, there are no changes to 
> REQUIRE_ZFINX_OR_F, no additional smstateen_fcsr_check, and 
> REQUIRE_FPU reduces to
>
> #define REQUIRE_FPU do {                          \
>     if (ctx->mstatus_fs == EXT_STATUS_DISABLED) { \
>         return false;                             \
>     }                                             \
> } while (0)
>
> This makes the DisasContext version of fs be the single gate for 
> floating point.
> No extra checks required.

Yeah. It's better to merge with REQUIRE_FPU.

However,  virtual instruction exception will be triggered in VS/VU mode 
if smstateen check fails, which is different from normal REQUIRE_FPU.

So, we may need to modify REQUIRE_FPU to distinguish them:

#define REQUIRE_FPU do {                          \
     if (ctx->mstatus_fs == EXT_STATUS_DISABLED) { \
           ctx->virt_inst_excp = ctx->virt_enabled && 
ctx->cfg_ptr->ext_zfinx;  \
           return false;                             \
     }                                             \
} while (0)

Regards,

Weiwei Li

>
>
> r~
diff mbox series

Patch

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b68dcfe7b6..126ac221a0 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -119,6 +119,15 @@  void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
         vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS));
     }
 
+    /*
+     * If misa.F is 0 then the FS field of the tb->flags can be used to pass
+     * the current state of the smstateen.FCSR bit which must be checked for
+     * in the floating point translation routines.
+     */
+    if (!riscv_has_ext(env, RVF)) {
+        fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE);
+    }
+
     if (cpu->cfg.debug && !icount_enabled()) {
         flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
     }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 928da0d3f0..74f624aa62 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -78,6 +78,7 @@  typedef struct DisasContext {
     int frm;
     RISCVMXL ol;
     bool virt_inst_excp;
+    bool smstateen_fcsr_ok;
     bool virt_enabled;
     const RISCVCPUConfig *cfg_ptr;
     /* vector extension */
@@ -1155,7 +1156,11 @@  static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->pc_succ_insn = ctx->base.pc_first;
     ctx->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV);
     ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
-    ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
+    if (has_ext(ctx, RVF)) {
+        ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
+    } else {
+        ctx->mstatus_fs = 0;
+    }
     ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
     ctx->priv_ver = env->priv_ver;
     ctx->virt_enabled = FIELD_EX32(tb_flags, TB_FLAGS, VIRT_ENABLED);
@@ -1178,6 +1183,11 @@  static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
     ctx->zero = tcg_constant_tl(0);
     ctx->virt_inst_excp = false;
+    if (has_ext(ctx, RVF) || !cpu->cfg.ext_smstateen) {
+        ctx->smstateen_fcsr_ok = 1;
+    } else {
+        ctx->smstateen_fcsr_ok = FIELD_EX32(tb_flags, TB_FLAGS, FS);
+    }
 }
 
 static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)