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


Reply via email to