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)