qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 14/28] target/arm: Implement FPCXT_NS fp system register


From: Richard Henderson
Subject: Re: [PATCH v2 14/28] target/arm: Implement FPCXT_NS fp system register
Date: Tue, 1 Dec 2020 08:05:47 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0

On 11/19/20 3:56 PM, Peter Maydell wrote:
> Implement the v8.1M FPCXT_NS floating-point system register.  This is
> a little more complicated than FPCXT_S, because it has specific
> handling for "current FP state is inactive", and it only wants to do
> PreserveFPState(), not the full set of actions done by
> ExecuteFPCheck() which vfp_access_check() implements.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/translate-vfp.c.inc | 110 ++++++++++++++++++++++++++++++---
>  1 file changed, 103 insertions(+), 7 deletions(-)
> 
> diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
> index ebc59daf613..1c2d31f6f30 100644
> --- a/target/arm/translate-vfp.c.inc
> +++ b/target/arm/translate-vfp.c.inc
> @@ -647,8 +647,20 @@ typedef enum fp_sysreg_check_result {
>      fp_sysreg_check_continue, /* caller should continue generating code */
>  } fp_sysreg_check_result;
>  
> -static fp_sysreg_check_result fp_sysreg_checks(DisasContext *s, int regno)
> +/*
> + * Emit code to check common UNDEF cases and handle lazy state preservation
> + * including the special casing for FPCXT_NS. For reads of sysregs, caller
> + * should provide storefn and opaque; for writes to sysregs these can be 
> NULL.
> + * On return, if *insn_end_label is not NULL the caller needs to 
> gen_set_label()
> + * it at the end of the other code generated for the insn.
> + */
> +static fp_sysreg_check_result fp_sysreg_checks(DisasContext *s, int regno,
> +                                               fp_sysreg_storefn *storefn,
> +                                               void *opaque,
> +                                               TCGLabel **insn_end_label)

I think it is really ugly to bury the fpAccess check in here.

> -    if (!vfp_access_check(s)) {
> -        return fp_sysreg_check_done;

I think it would be better to do

  if (regno != ARM_VFP_FPCXT_NS && !vfp_access_check(s))

and split out

> +        /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */
> +        TCGLabel *fp_active_label = gen_new_label();
> +        TCGv_i32 aspen, fpca;
> +        aspen = load_cpu_field(v7m.fpccr[M_REG_NS]);
> +        fpca = load_cpu_field(v7m.control[M_REG_S]);
> +        tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
> +        tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
> +        tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK);
> +        tcg_gen_or_i32(fpca, fpca, aspen);
> +        tcg_gen_brcondi_i32(TCG_COND_NE, fpca, 0, fp_active_label);
> +        tcg_temp_free_i32(aspen);
> +        tcg_temp_free_i32(fpca);
> +
> +        /* fpInactive case: FPCXT_NS reads as FPDSCR_NS, write is NOP */
> +        if (storefn) {
> +            TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
> +            storefn(s, opaque, tmp);
> +        }
> +        /* jump to end of insn */
> +        *insn_end_label = gen_new_label();
> +        tcg_gen_br(*insn_end_label);
> +
> +        gen_set_label(fp_active_label);
> +        /* !fpInactive: PreserveFPState() and handle register as normal */
> +        gen_preserve_fp_state(s);

... all of this to a separate function.

Then VLDR becomes

   case ARM_VFP_FPCXT_NS:
        lab_inactive = gen_new_label();
        gen_branch_fpInactive(s, TCG_COND_NE, lab_inactive);
        ...
        gen_set_label(lab_inactive);
        gen_lookup_tb();
        break;

and VSTR becomes

   case ARM_VFP_FPCXT_NS:
       lab_end = gen_new_label();
       lab_active = gen_new_label();
       gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
       ...
       tcg_gen_br(lab_end);
       gen_set_label(lab_active);
       /* fall through */
   case ARM_VFP_FPCXT_S:
       ...
   }
   if (lab_end) {
       gen_set_label(lab_end);
   }


r~



reply via email to

[Prev in Thread] Current Thread [Next in Thread]