diff options
Diffstat (limited to 'target/arm')
-rw-r--r-- | target/arm/cpu.c | 3 | ||||
-rw-r--r-- | target/arm/cpu.h | 9 | ||||
-rw-r--r-- | target/arm/translate.h | 3 | ||||
-rw-r--r-- | target/arm/vfp_helper.c | 5 |
4 files changed, 18 insertions, 2 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 111579554f..6b382fcd60 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -391,12 +391,15 @@ static void arm_cpu_reset(DeviceState *dev) set_flush_to_zero(1, &env->vfp.standard_fp_status); set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status); set_default_nan_mode(1, &env->vfp.standard_fp_status); + set_default_nan_mode(1, &env->vfp.standard_fp_status_f16); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.fp_status); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.standard_fp_status); set_float_detect_tininess(float_tininess_before_rounding, &env->vfp.fp_status_f16); + set_float_detect_tininess(float_tininess_before_rounding, + &env->vfp.standard_fp_status_f16); #ifndef CONFIG_USER_ONLY if (kvm_enabled()) { kvm_arm_reset_vcpu(cpu); diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 9d2845c179..ac857bdc2c 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -609,6 +609,8 @@ typedef struct CPUARMState { * fp_status: is the "normal" fp status. * fp_status_fp16: used for half-precision calculations * standard_fp_status : the ARM "Standard FPSCR Value" + * standard_fp_status_fp16 : used for half-precision + * calculations with the ARM "Standard FPSCR Value" * * Half-precision operations are governed by a separate * flush-to-zero control bit in FPSCR:FZ16. We pass a separate @@ -619,15 +621,20 @@ typedef struct CPUARMState { * Neon) which the architecture defines as controlled by the * standard FPSCR value rather than the FPSCR. * + * The "standard FPSCR but for fp16 ops" is needed because + * the "standard FPSCR" tracks the FPSCR.FZ16 bit rather than + * using a fixed value for it. + * * To avoid having to transfer exception bits around, we simply * say that the FPSCR cumulative exception flags are the logical - * OR of the flags in the three fp statuses. This relies on the + * OR of the flags in the four fp statuses. This relies on the * only thing which needs to read the exception flags being * an explicit FPSCR read. */ float_status fp_status; float_status fp_status_f16; float_status standard_fp_status; + float_status standard_fp_status_f16; /* ZCR_EL[1-3] */ uint64_t zcr_el[4]; diff --git a/target/arm/translate.h b/target/arm/translate.h index e3680e6547..6d6d4c0f42 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -436,7 +436,8 @@ static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour) offset = offsetof(CPUARMState, vfp.standard_fp_status); break; case FPST_STD_F16: - /* Not yet used or implemented: fall through to assert */ + offset = offsetof(CPUARMState, vfp.standard_fp_status_f16); + break; default: g_assert_not_reached(); } diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c index 60dcd4bf14..64266ece62 100644 --- a/target/arm/vfp_helper.c +++ b/target/arm/vfp_helper.c @@ -93,6 +93,8 @@ static uint32_t vfp_get_fpscr_from_host(CPUARMState *env) /* FZ16 does not generate an input denormal exception. */ i |= (get_float_exception_flags(&env->vfp.fp_status_f16) & ~float_flag_input_denormal); + i |= (get_float_exception_flags(&env->vfp.standard_fp_status_f16) + & ~float_flag_input_denormal); return vfp_exceptbits_from_host(i); } @@ -124,7 +126,9 @@ static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val) if (changed & FPCR_FZ16) { bool ftz_enabled = val & FPCR_FZ16; set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16); + set_flush_to_zero(ftz_enabled, &env->vfp.standard_fp_status_f16); set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16); + set_flush_inputs_to_zero(ftz_enabled, &env->vfp.standard_fp_status_f16); } if (changed & FPCR_FZ) { bool ftz_enabled = val & FPCR_FZ; @@ -146,6 +150,7 @@ static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val) set_float_exception_flags(i, &env->vfp.fp_status); set_float_exception_flags(0, &env->vfp.fp_status_f16); set_float_exception_flags(0, &env->vfp.standard_fp_status); + set_float_exception_flags(0, &env->vfp.standard_fp_status_f16); } #else |