From: Matt Turner <[email protected]> Factor FCR→fp_status and FSR→fp_status synchronisation out of the wur_fpu{2k,}_fcr/wur_fpu_fsr helpers into cpu_set_fcr(), cpu_set_fsr(), and cpu_get_fsr(). Signal delivery code needs to restore the FP rounding mode and exception flags without duplicating the flag-mapping tables.
cpu_set_fcr() applies the union mask 0xfffff07f (superset of the wur_fpu_fcr mask 0x0000007f and the wur_fpu2k_fcr mask 0xfffff07f) so that FCR bits valid only on fpu2k configs are preserved while MBZ bits 7-11 are always cleared. Signed-off-by: Matt Turner <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Signed-off-by: Helge Deller <[email protected]> (cherry picked from commit 7e859bacea09a626c239f14ab9c01f13d5225723) Signed-off-by: Michael Tokarev <[email protected]> diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 8d70bfc0cd..03bde931e8 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -641,6 +641,10 @@ static inline void xtensa_select_static_vectors(CPUXtensaState *env, } void xtensa_runstall(CPUXtensaState *env, bool runstall); +uint32_t cpu_get_fsr(CPUXtensaState *env); +void cpu_set_fcr(CPUXtensaState *env, uint32_t v); +void cpu_set_fsr(CPUXtensaState *env, uint32_t v); + #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt)) #define XTENSA_OPTION_ALL (~(uint64_t)0) diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c index 53fc7cfd2a..89190d75c8 100644 --- a/target/xtensa/fpu_helper.c +++ b/target/xtensa/fpu_helper.c @@ -65,46 +65,39 @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first) &env->fp_status); } -void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v) +uint32_t cpu_get_fsr(CPUXtensaState *env) { - static const int rounding_mode[] = { - float_round_nearest_even, - float_round_to_zero, - float_round_up, - float_round_down, - }; + uint32_t flags = 0; + int fef = get_float_exception_flags(&env->fp_status); + unsigned i; - env->uregs[FCR] = v & 0xfffff07f; - set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status); + for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) { + if (fef & xtensa_fp_flag_map[i].softfloat_fp_flag) { + flags |= xtensa_fp_flag_map[i].xtensa_fp_flag; + } + } + return flags << XTENSA_FSR_FLAGS_SHIFT; } -void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v) +void cpu_set_fcr(CPUXtensaState *env, uint32_t v) { - static const int rounding_mode[] = { + static const FloatRoundMode rounding_mode[] = { float_round_nearest_even, float_round_to_zero, float_round_up, float_round_down, }; - if (v & 0xfffff000) { - qemu_log_mask(LOG_GUEST_ERROR, - "MBZ field of FCR is written non-zero: %08x\n", v); - } - env->uregs[FCR] = v & 0x0000007f; + env->uregs[FCR] = v & 0xfffff07f; set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status); } -void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v) +void cpu_set_fsr(CPUXtensaState *env, uint32_t v) { uint32_t flags = v >> XTENSA_FSR_FLAGS_SHIFT; int fef = 0; unsigned i; - if (v & 0xfffff000) { - qemu_log_mask(LOG_GUEST_ERROR, - "MBZ field of FSR is written non-zero: %08x\n", v); - } env->uregs[FSR] = v & 0x00000f80; for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) { if (flags & xtensa_fp_flag_map[i].xtensa_fp_flag) { @@ -114,19 +107,35 @@ void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v) set_float_exception_flags(fef, &env->fp_status); } -uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env) +void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v) { - uint32_t flags = 0; - int fef = get_float_exception_flags(&env->fp_status); - unsigned i; + cpu_set_fcr(env, v); +} - for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) { - if (fef & xtensa_fp_flag_map[i].softfloat_fp_flag) { - flags |= xtensa_fp_flag_map[i].xtensa_fp_flag; - } +void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v) +{ + if (v & 0xfffff000) { + qemu_log_mask(LOG_GUEST_ERROR, + "MBZ field of FCR is written non-zero: %08x\n", v); } - env->uregs[FSR] = flags << XTENSA_FSR_FLAGS_SHIFT; - return flags << XTENSA_FSR_FLAGS_SHIFT; + cpu_set_fcr(env, v & 0x0000007f); +} + +void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v) +{ + if (v & 0xfffff000) { + qemu_log_mask(LOG_GUEST_ERROR, + "MBZ field of FSR is written non-zero: %08x\n", v); + } + cpu_set_fsr(env, v); +} + +uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env) +{ + uint32_t fsr = cpu_get_fsr(env); + + env->uregs[FSR] = fsr; + return fsr; } float64 HELPER(abs_d)(float64 v) -- 2.47.3
