@samitouri / QOSamiQemu / commits / 7e859bacea

target/xtensa: add cpu_set_fcr/fsr helpers to sync fp_status

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 <mattst88@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Helge Deller <deller@gmx.de>

Matt Turner committed Jun 10, 2026 at 11:25 UTC 7e859bacea09a626c239f14ab9c01f13d5225723
2 files changed +44 -31
target/xtensa/cpu.h
+4
@@ -642,6 +642,10 @@ static inline void xtensa_select_static_vectors(CPUXtensaState *env,
642 }
643 void xtensa_runstall(CPUXtensaState *env, bool runstall);
644
645 +uint32_t cpu_get_fsr(CPUXtensaState *env);
646 +void cpu_set_fcr(CPUXtensaState *env, uint32_t v);
647 +void cpu_set_fsr(CPUXtensaState *env, uint32_t v);
648 +
649 #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
650 #define XTENSA_OPTION_ALL (~(uint64_t)0)
651
target/xtensa/fpu_helper.c
+40 -31
@@ -64,46 +64,39 @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
64 &env->fp_status);
65 }
66
67 -void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
67 +uint32_t cpu_get_fsr(CPUXtensaState *env)
68 {
69 - static const int rounding_mode[] = {
70 - float_round_nearest_even,
71 - float_round_to_zero,
72 - float_round_up,
73 - float_round_down,
74 - };
69 + uint32_t flags = 0;
70 + int fef = get_float_exception_flags(&env->fp_status);
71 + unsigned i;
72
76 - env->uregs[FCR] = v & 0xfffff07f;
77 - set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status);
73 + for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) {
74 + if (fef & xtensa_fp_flag_map[i].softfloat_fp_flag) {
75 + flags |= xtensa_fp_flag_map[i].xtensa_fp_flag;
76 + }
77 + }
78 + return flags << XTENSA_FSR_FLAGS_SHIFT;
79 }
80
80 -void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v)
81 +void cpu_set_fcr(CPUXtensaState *env, uint32_t v)
82 {
82 - static const int rounding_mode[] = {
83 + static const FloatRoundMode rounding_mode[] = {
84 float_round_nearest_even,
85 float_round_to_zero,
86 float_round_up,
87 float_round_down,
88 };
89
89 - if (v & 0xfffff000) {
90 - qemu_log_mask(LOG_GUEST_ERROR,
91 - "MBZ field of FCR is written non-zero: %08x\n", v);
92 - }
93 - env->uregs[FCR] = v & 0x0000007f;
90 + env->uregs[FCR] = v & 0xfffff07f;
91 set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status);
92 }
93
97 -void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v)
94 +void cpu_set_fsr(CPUXtensaState *env, uint32_t v)
95 {
96 uint32_t flags = v >> XTENSA_FSR_FLAGS_SHIFT;
97 int fef = 0;
98 unsigned i;
99
103 - if (v & 0xfffff000) {
104 - qemu_log_mask(LOG_GUEST_ERROR,
105 - "MBZ field of FSR is written non-zero: %08x\n", v);
106 - }
100 env->uregs[FSR] = v & 0x00000f80;
101 for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) {
102 if (flags & xtensa_fp_flag_map[i].xtensa_fp_flag) {
@@ -113,19 +106,35 @@ void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v)
106 set_float_exception_flags(fef, &env->fp_status);
107 }
108
116 -uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env)
109 +void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
110 {
118 - uint32_t flags = 0;
119 - int fef = get_float_exception_flags(&env->fp_status);
120 - unsigned i;
111 + cpu_set_fcr(env, v);
112 +}
113
122 - for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) {
123 - if (fef & xtensa_fp_flag_map[i].softfloat_fp_flag) {
124 - flags |= xtensa_fp_flag_map[i].xtensa_fp_flag;
125 - }
114 +void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v)
115 +{
116 + if (v & 0xfffff000) {
117 + qemu_log_mask(LOG_GUEST_ERROR,
118 + "MBZ field of FCR is written non-zero: %08x\n", v);
119 }
127 - env->uregs[FSR] = flags << XTENSA_FSR_FLAGS_SHIFT;
128 - return flags << XTENSA_FSR_FLAGS_SHIFT;
120 + cpu_set_fcr(env, v & 0x0000007f);
121 +}
122 +
123 +void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v)
124 +{
125 + if (v & 0xfffff000) {
126 + qemu_log_mask(LOG_GUEST_ERROR,
127 + "MBZ field of FSR is written non-zero: %08x\n", v);
128 + }
129 + cpu_set_fsr(env, v);
130 +}
131 +
132 +uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env)
133 +{
134 + uint32_t fsr = cpu_get_fsr(env);
135 +
136 + env->uregs[FSR] = fsr;
137 + return fsr;
138 }
139
140 float64 HELPER(abs_d)(float64 v)