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]> --- target/xtensa/cpu.h | 4 ++ target/xtensa/fpu_helper.c | 111 ++++++++++++++++++++----------------- 2 files changed, 64 insertions(+), 51 deletions(-) diff --git ./target/xtensa/cpu.h ./target/xtensa/cpu.h index 75cfeee6e3..442e98bd1b 100644 --- ./target/xtensa/cpu.h +++ ./target/xtensa/cpu.h @@ -642,6 +642,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 ./target/xtensa/fpu_helper.c ./target/xtensa/fpu_helper.c index 5358060c50..2e51cabe3f 100644 --- ./target/xtensa/fpu_helper.c +++ ./target/xtensa/fpu_helper.c @@ -64,56 +64,7 @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first) &env->fp_status); } -void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v) -{ - static const int rounding_mode[] = { - float_round_nearest_even, - float_round_to_zero, - float_round_up, - float_round_down, - }; - - env->uregs[FCR] = v & 0xfffff07f; - set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status); -} - -void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v) -{ - static const int 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; - set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status); -} - -void HELPER(wur_fpu_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) { - fef |= xtensa_fp_flag_map[i].softfloat_fp_flag; - } - } - set_float_exception_flags(fef, &env->fp_status); -} - -uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env) +uint32_t cpu_get_fsr(CPUXtensaState *env) { uint32_t flags = 0; int fef = get_float_exception_flags(&env->fp_status); @@ -124,10 +75,68 @@ uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env) flags |= xtensa_fp_flag_map[i].xtensa_fp_flag; } } - env->uregs[FSR] = flags << XTENSA_FSR_FLAGS_SHIFT; return flags << XTENSA_FSR_FLAGS_SHIFT; } +void cpu_set_fcr(CPUXtensaState *env, uint32_t v) +{ + static const FloatRoundMode rounding_mode[] = { + float_round_nearest_even, + float_round_to_zero, + float_round_up, + float_round_down, + }; + + env->uregs[FCR] = v & 0xfffff07f; + set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status); +} + +void cpu_set_fsr(CPUXtensaState *env, uint32_t v) +{ + uint32_t flags = v >> XTENSA_FSR_FLAGS_SHIFT; + int fef = 0; + unsigned i; + + 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) { + fef |= xtensa_fp_flag_map[i].softfloat_fp_flag; + } + } + set_float_exception_flags(fef, &env->fp_status); +} + +void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v) +{ + cpu_set_fcr(env, v); +} + +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); + } + 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) { return float64_abs(v); -- 2.53.0
