[PATCH 2/6] target/microblaze: Extract FPU helpers to fpu_helper.c

Philippe Mathieu-Daudé posted 6 patches 4 years, 8 months ago
[PATCH 2/6] target/microblaze: Extract FPU helpers to fpu_helper.c
Posted by Philippe Mathieu-Daudé 4 years, 8 months ago
Extract FPU helpers to their own file: fpu_helper.c,
so it is easier to focus on the generic helpers in
op_helper.c.

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 target/microblaze/fpu_helper.c | 308 +++++++++++++++++++++++++++++++++
 target/microblaze/op_helper.c  | 287 +-----------------------------
 target/microblaze/meson.build  |   1 +
 3 files changed, 310 insertions(+), 286 deletions(-)
 create mode 100644 target/microblaze/fpu_helper.c

diff --git a/target/microblaze/fpu_helper.c b/target/microblaze/fpu_helper.c
new file mode 100644
index 00000000000..ce729947079
--- /dev/null
+++ b/target/microblaze/fpu_helper.c
@@ -0,0 +1,308 @@
+/*
+ *  Microblaze FPU helper routines.
+ *
+ *  Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>.
+ *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "fpu/softfloat.h"
+
+static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
+{
+    if (unlikely(b == 0)) {
+        env->msr |= MSR_DZ;
+
+        if ((env->msr & MSR_EE) &&
+            env_archcpu(env)->cfg.div_zero_exception) {
+            CPUState *cs = env_cpu(env);
+
+            env->esr = ESR_EC_DIVZERO;
+            cs->exception_index = EXCP_HW_EXCP;
+            cpu_loop_exit_restore(cs, ra);
+        }
+        return false;
+    }
+    return true;
+}
+
+uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    if (!check_divz(env, a, b, GETPC())) {
+        return 0;
+    }
+    return (int32_t)a / (int32_t)b;
+}
+
+uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    if (!check_divz(env, a, b, GETPC())) {
+        return 0;
+    }
+    return a / b;
+}
+
+/* raise FPU exception.  */
+static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
+{
+    CPUState *cs = env_cpu(env);
+
+    env->esr = ESR_EC_FPU;
+    cs->exception_index = EXCP_HW_EXCP;
+    cpu_loop_exit_restore(cs, ra);
+}
+
+static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
+{
+    int raise = 0;
+
+    if (flags & float_flag_invalid) {
+        env->fsr |= FSR_IO;
+        raise = 1;
+    }
+    if (flags & float_flag_divbyzero) {
+        env->fsr |= FSR_DZ;
+        raise = 1;
+    }
+    if (flags & float_flag_overflow) {
+        env->fsr |= FSR_OF;
+        raise = 1;
+    }
+    if (flags & float_flag_underflow) {
+        env->fsr |= FSR_UF;
+        raise = 1;
+    }
+    if (raise
+        && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK)
+        && (env->msr & MSR_EE)) {
+        raise_fpu_exception(env, ra);
+    }
+}
+
+uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fd, fa, fb;
+    int flags;
+
+    set_float_exception_flags(0, &env->fp_status);
+    fa.l = a;
+    fb.l = b;
+    fd.f = float32_add(fa.f, fb.f, &env->fp_status);
+
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags, GETPC());
+    return fd.l;
+}
+
+uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fd, fa, fb;
+    int flags;
+
+    set_float_exception_flags(0, &env->fp_status);
+    fa.l = a;
+    fb.l = b;
+    fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags, GETPC());
+    return fd.l;
+}
+
+uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fd, fa, fb;
+    int flags;
+
+    set_float_exception_flags(0, &env->fp_status);
+    fa.l = a;
+    fb.l = b;
+    fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags, GETPC());
+
+    return fd.l;
+}
+
+uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fd, fa, fb;
+    int flags;
+
+    set_float_exception_flags(0, &env->fp_status);
+    fa.l = a;
+    fb.l = b;
+    fd.f = float32_div(fb.f, fa.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags, GETPC());
+
+    return fd.l;
+}
+
+uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fa, fb;
+    uint32_t r = 0;
+
+    fa.l = a;
+    fb.l = b;
+
+    if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
+        float32_is_signaling_nan(fb.f, &env->fp_status)) {
+        update_fpu_flags(env, float_flag_invalid, GETPC());
+        r = 1;
+    }
+
+    if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
+        float32_is_quiet_nan(fb.f, &env->fp_status)) {
+        r = 1;
+    }
+
+    return r;
+}
+
+uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fa, fb;
+    int r;
+    int flags;
+
+    set_float_exception_flags(0, &env->fp_status);
+    fa.l = a;
+    fb.l = b;
+    r = float32_lt(fb.f, fa.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
+
+    return r;
+}
+
+uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fa, fb;
+    int flags;
+    int r;
+
+    set_float_exception_flags(0, &env->fp_status);
+    fa.l = a;
+    fb.l = b;
+    r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
+
+    return r;
+}
+
+uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fa, fb;
+    int flags;
+    int r;
+
+    fa.l = a;
+    fb.l = b;
+    set_float_exception_flags(0, &env->fp_status);
+    r = float32_le(fa.f, fb.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
+
+
+    return r;
+}
+
+uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fa, fb;
+    int flags, r;
+
+    fa.l = a;
+    fb.l = b;
+    set_float_exception_flags(0, &env->fp_status);
+    r = float32_lt(fa.f, fb.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
+    return r;
+}
+
+uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fa, fb;
+    int flags, r;
+
+    fa.l = a;
+    fb.l = b;
+    set_float_exception_flags(0, &env->fp_status);
+    r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
+
+    return r;
+}
+
+uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
+{
+    CPU_FloatU fa, fb;
+    int flags, r;
+
+    fa.l = a;
+    fb.l = b;
+    set_float_exception_flags(0, &env->fp_status);
+    r = !float32_lt(fa.f, fb.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
+
+    return r;
+}
+
+uint32_t helper_flt(CPUMBState *env, uint32_t a)
+{
+    CPU_FloatU fd, fa;
+
+    fa.l = a;
+    fd.f = int32_to_float32(fa.l, &env->fp_status);
+    return fd.l;
+}
+
+uint32_t helper_fint(CPUMBState *env, uint32_t a)
+{
+    CPU_FloatU fa;
+    uint32_t r;
+    int flags;
+
+    set_float_exception_flags(0, &env->fp_status);
+    fa.l = a;
+    r = float32_to_int32(fa.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags, GETPC());
+
+    return r;
+}
+
+uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
+{
+    CPU_FloatU fd, fa;
+    int flags;
+
+    set_float_exception_flags(0, &env->fp_status);
+    fa.l = a;
+    fd.l = float32_sqrt(fa.f, &env->fp_status);
+    flags = get_float_exception_flags(&env->fp_status);
+    update_fpu_flags(env, flags, GETPC());
+
+    return fd.l;
+}
diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c
index 58d633584d3..8d20522ee88 100644
--- a/target/microblaze/op_helper.c
+++ b/target/microblaze/op_helper.c
@@ -21,10 +21,8 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "exec/helper-proto.h"
-#include "qemu/host-utils.h"
+#include "qemu/log.h"
 #include "exec/exec-all.h"
-#include "exec/cpu_ldst.h"
-#include "fpu/softfloat.h"
 
 void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
 {
@@ -69,289 +67,6 @@ void helper_raise_exception(CPUMBState *env, uint32_t index)
     cpu_loop_exit(cs);
 }
 
-static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
-{
-    if (unlikely(b == 0)) {
-        env->msr |= MSR_DZ;
-
-        if ((env->msr & MSR_EE) &&
-            env_archcpu(env)->cfg.div_zero_exception) {
-            CPUState *cs = env_cpu(env);
-
-            env->esr = ESR_EC_DIVZERO;
-            cs->exception_index = EXCP_HW_EXCP;
-            cpu_loop_exit_restore(cs, ra);
-        }
-        return false;
-    }
-    return true;
-}
-
-uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    if (!check_divz(env, a, b, GETPC())) {
-        return 0;
-    }
-    return (int32_t)a / (int32_t)b;
-}
-
-uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    if (!check_divz(env, a, b, GETPC())) {
-        return 0;
-    }
-    return a / b;
-}
-
-/* raise FPU exception.  */
-static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
-{
-    CPUState *cs = env_cpu(env);
-
-    env->esr = ESR_EC_FPU;
-    cs->exception_index = EXCP_HW_EXCP;
-    cpu_loop_exit_restore(cs, ra);
-}
-
-static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
-{
-    int raise = 0;
-
-    if (flags & float_flag_invalid) {
-        env->fsr |= FSR_IO;
-        raise = 1;
-    }
-    if (flags & float_flag_divbyzero) {
-        env->fsr |= FSR_DZ;
-        raise = 1;
-    }
-    if (flags & float_flag_overflow) {
-        env->fsr |= FSR_OF;
-        raise = 1;
-    }
-    if (flags & float_flag_underflow) {
-        env->fsr |= FSR_UF;
-        raise = 1;
-    }
-    if (raise
-        && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK)
-        && (env->msr & MSR_EE)) {
-        raise_fpu_exception(env, ra);
-    }
-}
-
-uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fd, fa, fb;
-    int flags;
-
-    set_float_exception_flags(0, &env->fp_status);
-    fa.l = a;
-    fb.l = b;
-    fd.f = float32_add(fa.f, fb.f, &env->fp_status);
-
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags, GETPC());
-    return fd.l;
-}
-
-uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fd, fa, fb;
-    int flags;
-
-    set_float_exception_flags(0, &env->fp_status);
-    fa.l = a;
-    fb.l = b;
-    fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags, GETPC());
-    return fd.l;
-}
-
-uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fd, fa, fb;
-    int flags;
-
-    set_float_exception_flags(0, &env->fp_status);
-    fa.l = a;
-    fb.l = b;
-    fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags, GETPC());
-
-    return fd.l;
-}
-
-uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fd, fa, fb;
-    int flags;
-
-    set_float_exception_flags(0, &env->fp_status);
-    fa.l = a;
-    fb.l = b;
-    fd.f = float32_div(fb.f, fa.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags, GETPC());
-
-    return fd.l;
-}
-
-uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fa, fb;
-    uint32_t r = 0;
-
-    fa.l = a;
-    fb.l = b;
-
-    if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
-        float32_is_signaling_nan(fb.f, &env->fp_status)) {
-        update_fpu_flags(env, float_flag_invalid, GETPC());
-        r = 1;
-    }
-
-    if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
-        float32_is_quiet_nan(fb.f, &env->fp_status)) {
-        r = 1;
-    }
-
-    return r;
-}
-
-uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fa, fb;
-    int r;
-    int flags;
-
-    set_float_exception_flags(0, &env->fp_status);
-    fa.l = a;
-    fb.l = b;
-    r = float32_lt(fb.f, fa.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
-
-    return r;
-}
-
-uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fa, fb;
-    int flags;
-    int r;
-
-    set_float_exception_flags(0, &env->fp_status);
-    fa.l = a;
-    fb.l = b;
-    r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
-
-    return r;
-}
-
-uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fa, fb;
-    int flags;
-    int r;
-
-    fa.l = a;
-    fb.l = b;
-    set_float_exception_flags(0, &env->fp_status);
-    r = float32_le(fa.f, fb.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
-
-
-    return r;
-}
-
-uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fa, fb;
-    int flags, r;
-
-    fa.l = a;
-    fb.l = b;
-    set_float_exception_flags(0, &env->fp_status);
-    r = float32_lt(fa.f, fb.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
-    return r;
-}
-
-uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fa, fb;
-    int flags, r;
-
-    fa.l = a;
-    fb.l = b;
-    set_float_exception_flags(0, &env->fp_status);
-    r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
-
-    return r;
-}
-
-uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
-{
-    CPU_FloatU fa, fb;
-    int flags, r;
-
-    fa.l = a;
-    fb.l = b;
-    set_float_exception_flags(0, &env->fp_status);
-    r = !float32_lt(fa.f, fb.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
-
-    return r;
-}
-
-uint32_t helper_flt(CPUMBState *env, uint32_t a)
-{
-    CPU_FloatU fd, fa;
-
-    fa.l = a;
-    fd.f = int32_to_float32(fa.l, &env->fp_status);
-    return fd.l;
-}
-
-uint32_t helper_fint(CPUMBState *env, uint32_t a)
-{
-    CPU_FloatU fa;
-    uint32_t r;
-    int flags;
-
-    set_float_exception_flags(0, &env->fp_status);
-    fa.l = a;
-    r = float32_to_int32(fa.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags, GETPC());
-
-    return r;
-}
-
-uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
-{
-    CPU_FloatU fd, fa;
-    int flags;
-
-    set_float_exception_flags(0, &env->fp_status);
-    fa.l = a;
-    fd.l = float32_sqrt(fa.f, &env->fp_status);
-    flags = get_float_exception_flags(&env->fp_status);
-    update_fpu_flags(env, flags, GETPC());
-
-    return fd.l;
-}
-
 uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
 {
     unsigned int i;
diff --git a/target/microblaze/meson.build b/target/microblaze/meson.build
index 05ee0ec1635..0a5e46027af 100644
--- a/target/microblaze/meson.build
+++ b/target/microblaze/meson.build
@@ -4,6 +4,7 @@
 microblaze_ss.add(gen)
 microblaze_ss.add(files(
   'cpu.c',
+  'fpu_helper.c',
   'gdbstub.c',
   'helper.c',
   'op_helper.c',
-- 
2.26.3

Re: [PATCH 2/6] target/microblaze: Extract FPU helpers to fpu_helper.c
Posted by Edgar E. Iglesias 4 years, 8 months ago
On Thu, Jun 03, 2021 at 11:03:06AM +0200, Philippe Mathieu-Daudé wrote:
> Extract FPU helpers to their own file: fpu_helper.c,
> so it is easier to focus on the generic helpers in
> op_helper.c.
> 
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  target/microblaze/fpu_helper.c | 308 +++++++++++++++++++++++++++++++++
>  target/microblaze/op_helper.c  | 287 +-----------------------------
>  target/microblaze/meson.build  |   1 +
>  3 files changed, 310 insertions(+), 286 deletions(-)
>  create mode 100644 target/microblaze/fpu_helper.c
> 
> diff --git a/target/microblaze/fpu_helper.c b/target/microblaze/fpu_helper.c
> new file mode 100644
> index 00000000000..ce729947079
> --- /dev/null
> +++ b/target/microblaze/fpu_helper.c
> @@ -0,0 +1,308 @@
> +/*
> + *  Microblaze FPU helper routines.
> + *
> + *  Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>.
> + *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "exec/helper-proto.h"
> +#include "exec/exec-all.h"
> +#include "fpu/softfloat.h"
> +
> +static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
> +{
> +    if (unlikely(b == 0)) {
> +        env->msr |= MSR_DZ;
> +
> +        if ((env->msr & MSR_EE) &&
> +            env_archcpu(env)->cfg.div_zero_exception) {
> +            CPUState *cs = env_cpu(env);
> +
> +            env->esr = ESR_EC_DIVZERO;
> +            cs->exception_index = EXCP_HW_EXCP;
> +            cpu_loop_exit_restore(cs, ra);
> +        }
> +        return false;
> +    }
> +    return true;
> +}
> +
> +uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    if (!check_divz(env, a, b, GETPC())) {
> +        return 0;
> +    }
> +    return (int32_t)a / (int32_t)b;
> +}
> +
> +uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    if (!check_divz(env, a, b, GETPC())) {
> +        return 0;
> +    }
> +    return a / b;
> +}
> +
> +/* raise FPU exception.  */
> +static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
> +{
> +    CPUState *cs = env_cpu(env);
> +
> +    env->esr = ESR_EC_FPU;
> +    cs->exception_index = EXCP_HW_EXCP;
> +    cpu_loop_exit_restore(cs, ra);
> +}
> +
> +static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
> +{
> +    int raise = 0;
> +
> +    if (flags & float_flag_invalid) {
> +        env->fsr |= FSR_IO;
> +        raise = 1;
> +    }
> +    if (flags & float_flag_divbyzero) {
> +        env->fsr |= FSR_DZ;
> +        raise = 1;
> +    }
> +    if (flags & float_flag_overflow) {
> +        env->fsr |= FSR_OF;
> +        raise = 1;
> +    }
> +    if (flags & float_flag_underflow) {
> +        env->fsr |= FSR_UF;
> +        raise = 1;
> +    }
> +    if (raise
> +        && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK)
> +        && (env->msr & MSR_EE)) {
> +        raise_fpu_exception(env, ra);
> +    }
> +}
> +
> +uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fd, fa, fb;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    fd.f = float32_add(fa.f, fb.f, &env->fp_status);
> +
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +    return fd.l;
> +}
> +
> +uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fd, fa, fb;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +    return fd.l;
> +}
> +
> +uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fd, fa, fb;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +
> +    return fd.l;
> +}
> +
> +uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fd, fa, fb;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    fd.f = float32_div(fb.f, fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +
> +    return fd.l;
> +}
> +
> +uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    uint32_t r = 0;
> +
> +    fa.l = a;
> +    fb.l = b;
> +
> +    if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
> +        float32_is_signaling_nan(fb.f, &env->fp_status)) {
> +        update_fpu_flags(env, float_flag_invalid, GETPC());
> +        r = 1;
> +    }
> +
> +    if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
> +        float32_is_quiet_nan(fb.f, &env->fp_status)) {
> +        r = 1;
> +    }
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int r;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    r = float32_lt(fb.f, fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags;
> +    int r;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags;
> +    int r;
> +
> +    fa.l = a;
> +    fb.l = b;
> +    set_float_exception_flags(0, &env->fp_status);
> +    r = float32_le(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags, r;
> +
> +    fa.l = a;
> +    fb.l = b;
> +    set_float_exception_flags(0, &env->fp_status);
> +    r = float32_lt(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags, r;
> +
> +    fa.l = a;
> +    fb.l = b;
> +    set_float_exception_flags(0, &env->fp_status);
> +    r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags, r;
> +
> +    fa.l = a;
> +    fb.l = b;
> +    set_float_exception_flags(0, &env->fp_status);
> +    r = !float32_lt(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_flt(CPUMBState *env, uint32_t a)
> +{
> +    CPU_FloatU fd, fa;
> +
> +    fa.l = a;
> +    fd.f = int32_to_float32(fa.l, &env->fp_status);
> +    return fd.l;
> +}
> +
> +uint32_t helper_fint(CPUMBState *env, uint32_t a)
> +{
> +    CPU_FloatU fa;
> +    uint32_t r;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    r = float32_to_int32(fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
> +{
> +    CPU_FloatU fd, fa;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fd.l = float32_sqrt(fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +
> +    return fd.l;
> +}
> diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c
> index 58d633584d3..8d20522ee88 100644
> --- a/target/microblaze/op_helper.c
> +++ b/target/microblaze/op_helper.c
> @@ -21,10 +21,8 @@
>  #include "qemu/osdep.h"
>  #include "cpu.h"
>  #include "exec/helper-proto.h"
> -#include "qemu/host-utils.h"
> +#include "qemu/log.h"
>  #include "exec/exec-all.h"
> -#include "exec/cpu_ldst.h"
> -#include "fpu/softfloat.h"
>  
>  void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
>  {
> @@ -69,289 +67,6 @@ void helper_raise_exception(CPUMBState *env, uint32_t index)
>      cpu_loop_exit(cs);
>  }
>  
> -static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
> -{
> -    if (unlikely(b == 0)) {
> -        env->msr |= MSR_DZ;
> -
> -        if ((env->msr & MSR_EE) &&
> -            env_archcpu(env)->cfg.div_zero_exception) {
> -            CPUState *cs = env_cpu(env);
> -
> -            env->esr = ESR_EC_DIVZERO;
> -            cs->exception_index = EXCP_HW_EXCP;
> -            cpu_loop_exit_restore(cs, ra);
> -        }
> -        return false;
> -    }
> -    return true;
> -}
> -
> -uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    if (!check_divz(env, a, b, GETPC())) {
> -        return 0;
> -    }
> -    return (int32_t)a / (int32_t)b;
> -}
> -
> -uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    if (!check_divz(env, a, b, GETPC())) {
> -        return 0;
> -    }
> -    return a / b;
> -}
> -
> -/* raise FPU exception.  */
> -static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
> -{
> -    CPUState *cs = env_cpu(env);
> -
> -    env->esr = ESR_EC_FPU;
> -    cs->exception_index = EXCP_HW_EXCP;
> -    cpu_loop_exit_restore(cs, ra);
> -}
> -
> -static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
> -{
> -    int raise = 0;
> -
> -    if (flags & float_flag_invalid) {
> -        env->fsr |= FSR_IO;
> -        raise = 1;
> -    }
> -    if (flags & float_flag_divbyzero) {
> -        env->fsr |= FSR_DZ;
> -        raise = 1;
> -    }
> -    if (flags & float_flag_overflow) {
> -        env->fsr |= FSR_OF;
> -        raise = 1;
> -    }
> -    if (flags & float_flag_underflow) {
> -        env->fsr |= FSR_UF;
> -        raise = 1;
> -    }
> -    if (raise
> -        && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK)
> -        && (env->msr & MSR_EE)) {
> -        raise_fpu_exception(env, ra);
> -    }
> -}
> -
> -uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fd, fa, fb;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    fd.f = float32_add(fa.f, fb.f, &env->fp_status);
> -
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -    return fd.l;
> -}
> -
> -uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fd, fa, fb;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -    return fd.l;
> -}
> -
> -uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fd, fa, fb;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -
> -    return fd.l;
> -}
> -
> -uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fd, fa, fb;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    fd.f = float32_div(fb.f, fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -
> -    return fd.l;
> -}
> -
> -uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    uint32_t r = 0;
> -
> -    fa.l = a;
> -    fb.l = b;
> -
> -    if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
> -        float32_is_signaling_nan(fb.f, &env->fp_status)) {
> -        update_fpu_flags(env, float_flag_invalid, GETPC());
> -        r = 1;
> -    }
> -
> -    if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
> -        float32_is_quiet_nan(fb.f, &env->fp_status)) {
> -        r = 1;
> -    }
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int r;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    r = float32_lt(fb.f, fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags;
> -    int r;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags;
> -    int r;
> -
> -    fa.l = a;
> -    fb.l = b;
> -    set_float_exception_flags(0, &env->fp_status);
> -    r = float32_le(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags, r;
> -
> -    fa.l = a;
> -    fb.l = b;
> -    set_float_exception_flags(0, &env->fp_status);
> -    r = float32_lt(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags, r;
> -
> -    fa.l = a;
> -    fb.l = b;
> -    set_float_exception_flags(0, &env->fp_status);
> -    r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags, r;
> -
> -    fa.l = a;
> -    fb.l = b;
> -    set_float_exception_flags(0, &env->fp_status);
> -    r = !float32_lt(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_flt(CPUMBState *env, uint32_t a)
> -{
> -    CPU_FloatU fd, fa;
> -
> -    fa.l = a;
> -    fd.f = int32_to_float32(fa.l, &env->fp_status);
> -    return fd.l;
> -}
> -
> -uint32_t helper_fint(CPUMBState *env, uint32_t a)
> -{
> -    CPU_FloatU fa;
> -    uint32_t r;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    r = float32_to_int32(fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
> -{
> -    CPU_FloatU fd, fa;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fd.l = float32_sqrt(fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -
> -    return fd.l;
> -}
> -
>  uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
>  {
>      unsigned int i;
> diff --git a/target/microblaze/meson.build b/target/microblaze/meson.build
> index 05ee0ec1635..0a5e46027af 100644
> --- a/target/microblaze/meson.build
> +++ b/target/microblaze/meson.build
> @@ -4,6 +4,7 @@
>  microblaze_ss.add(gen)
>  microblaze_ss.add(files(
>    'cpu.c',
> +  'fpu_helper.c',
>    'gdbstub.c',
>    'helper.c',
>    'op_helper.c',
> -- 
> 2.26.3
> 

Re: [PATCH 2/6] target/microblaze: Extract FPU helpers to fpu_helper.c
Posted by Alistair Francis 4 years, 8 months ago
On Thu, Jun 3, 2021 at 7:05 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> Extract FPU helpers to their own file: fpu_helper.c,
> so it is easier to focus on the generic helpers in
> op_helper.c.
>
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/microblaze/fpu_helper.c | 308 +++++++++++++++++++++++++++++++++
>  target/microblaze/op_helper.c  | 287 +-----------------------------
>  target/microblaze/meson.build  |   1 +
>  3 files changed, 310 insertions(+), 286 deletions(-)
>  create mode 100644 target/microblaze/fpu_helper.c
>
> diff --git a/target/microblaze/fpu_helper.c b/target/microblaze/fpu_helper.c
> new file mode 100644
> index 00000000000..ce729947079
> --- /dev/null
> +++ b/target/microblaze/fpu_helper.c
> @@ -0,0 +1,308 @@
> +/*
> + *  Microblaze FPU helper routines.
> + *
> + *  Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>.
> + *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "exec/helper-proto.h"
> +#include "exec/exec-all.h"
> +#include "fpu/softfloat.h"
> +
> +static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
> +{
> +    if (unlikely(b == 0)) {
> +        env->msr |= MSR_DZ;
> +
> +        if ((env->msr & MSR_EE) &&
> +            env_archcpu(env)->cfg.div_zero_exception) {
> +            CPUState *cs = env_cpu(env);
> +
> +            env->esr = ESR_EC_DIVZERO;
> +            cs->exception_index = EXCP_HW_EXCP;
> +            cpu_loop_exit_restore(cs, ra);
> +        }
> +        return false;
> +    }
> +    return true;
> +}
> +
> +uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    if (!check_divz(env, a, b, GETPC())) {
> +        return 0;
> +    }
> +    return (int32_t)a / (int32_t)b;
> +}
> +
> +uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    if (!check_divz(env, a, b, GETPC())) {
> +        return 0;
> +    }
> +    return a / b;
> +}
> +
> +/* raise FPU exception.  */
> +static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
> +{
> +    CPUState *cs = env_cpu(env);
> +
> +    env->esr = ESR_EC_FPU;
> +    cs->exception_index = EXCP_HW_EXCP;
> +    cpu_loop_exit_restore(cs, ra);
> +}
> +
> +static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
> +{
> +    int raise = 0;
> +
> +    if (flags & float_flag_invalid) {
> +        env->fsr |= FSR_IO;
> +        raise = 1;
> +    }
> +    if (flags & float_flag_divbyzero) {
> +        env->fsr |= FSR_DZ;
> +        raise = 1;
> +    }
> +    if (flags & float_flag_overflow) {
> +        env->fsr |= FSR_OF;
> +        raise = 1;
> +    }
> +    if (flags & float_flag_underflow) {
> +        env->fsr |= FSR_UF;
> +        raise = 1;
> +    }
> +    if (raise
> +        && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK)
> +        && (env->msr & MSR_EE)) {
> +        raise_fpu_exception(env, ra);
> +    }
> +}
> +
> +uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fd, fa, fb;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    fd.f = float32_add(fa.f, fb.f, &env->fp_status);
> +
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +    return fd.l;
> +}
> +
> +uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fd, fa, fb;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +    return fd.l;
> +}
> +
> +uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fd, fa, fb;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +
> +    return fd.l;
> +}
> +
> +uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fd, fa, fb;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    fd.f = float32_div(fb.f, fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +
> +    return fd.l;
> +}
> +
> +uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    uint32_t r = 0;
> +
> +    fa.l = a;
> +    fb.l = b;
> +
> +    if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
> +        float32_is_signaling_nan(fb.f, &env->fp_status)) {
> +        update_fpu_flags(env, float_flag_invalid, GETPC());
> +        r = 1;
> +    }
> +
> +    if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
> +        float32_is_quiet_nan(fb.f, &env->fp_status)) {
> +        r = 1;
> +    }
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int r;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    r = float32_lt(fb.f, fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags;
> +    int r;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fb.l = b;
> +    r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags;
> +    int r;
> +
> +    fa.l = a;
> +    fb.l = b;
> +    set_float_exception_flags(0, &env->fp_status);
> +    r = float32_le(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags, r;
> +
> +    fa.l = a;
> +    fb.l = b;
> +    set_float_exception_flags(0, &env->fp_status);
> +    r = float32_lt(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags, r;
> +
> +    fa.l = a;
> +    fb.l = b;
> +    set_float_exception_flags(0, &env->fp_status);
> +    r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
> +{
> +    CPU_FloatU fa, fb;
> +    int flags, r;
> +
> +    fa.l = a;
> +    fb.l = b;
> +    set_float_exception_flags(0, &env->fp_status);
> +    r = !float32_lt(fa.f, fb.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_flt(CPUMBState *env, uint32_t a)
> +{
> +    CPU_FloatU fd, fa;
> +
> +    fa.l = a;
> +    fd.f = int32_to_float32(fa.l, &env->fp_status);
> +    return fd.l;
> +}
> +
> +uint32_t helper_fint(CPUMBState *env, uint32_t a)
> +{
> +    CPU_FloatU fa;
> +    uint32_t r;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    r = float32_to_int32(fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +
> +    return r;
> +}
> +
> +uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
> +{
> +    CPU_FloatU fd, fa;
> +    int flags;
> +
> +    set_float_exception_flags(0, &env->fp_status);
> +    fa.l = a;
> +    fd.l = float32_sqrt(fa.f, &env->fp_status);
> +    flags = get_float_exception_flags(&env->fp_status);
> +    update_fpu_flags(env, flags, GETPC());
> +
> +    return fd.l;
> +}
> diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c
> index 58d633584d3..8d20522ee88 100644
> --- a/target/microblaze/op_helper.c
> +++ b/target/microblaze/op_helper.c
> @@ -21,10 +21,8 @@
>  #include "qemu/osdep.h"
>  #include "cpu.h"
>  #include "exec/helper-proto.h"
> -#include "qemu/host-utils.h"
> +#include "qemu/log.h"
>  #include "exec/exec-all.h"
> -#include "exec/cpu_ldst.h"
> -#include "fpu/softfloat.h"
>
>  void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
>  {
> @@ -69,289 +67,6 @@ void helper_raise_exception(CPUMBState *env, uint32_t index)
>      cpu_loop_exit(cs);
>  }
>
> -static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
> -{
> -    if (unlikely(b == 0)) {
> -        env->msr |= MSR_DZ;
> -
> -        if ((env->msr & MSR_EE) &&
> -            env_archcpu(env)->cfg.div_zero_exception) {
> -            CPUState *cs = env_cpu(env);
> -
> -            env->esr = ESR_EC_DIVZERO;
> -            cs->exception_index = EXCP_HW_EXCP;
> -            cpu_loop_exit_restore(cs, ra);
> -        }
> -        return false;
> -    }
> -    return true;
> -}
> -
> -uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    if (!check_divz(env, a, b, GETPC())) {
> -        return 0;
> -    }
> -    return (int32_t)a / (int32_t)b;
> -}
> -
> -uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    if (!check_divz(env, a, b, GETPC())) {
> -        return 0;
> -    }
> -    return a / b;
> -}
> -
> -/* raise FPU exception.  */
> -static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
> -{
> -    CPUState *cs = env_cpu(env);
> -
> -    env->esr = ESR_EC_FPU;
> -    cs->exception_index = EXCP_HW_EXCP;
> -    cpu_loop_exit_restore(cs, ra);
> -}
> -
> -static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
> -{
> -    int raise = 0;
> -
> -    if (flags & float_flag_invalid) {
> -        env->fsr |= FSR_IO;
> -        raise = 1;
> -    }
> -    if (flags & float_flag_divbyzero) {
> -        env->fsr |= FSR_DZ;
> -        raise = 1;
> -    }
> -    if (flags & float_flag_overflow) {
> -        env->fsr |= FSR_OF;
> -        raise = 1;
> -    }
> -    if (flags & float_flag_underflow) {
> -        env->fsr |= FSR_UF;
> -        raise = 1;
> -    }
> -    if (raise
> -        && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK)
> -        && (env->msr & MSR_EE)) {
> -        raise_fpu_exception(env, ra);
> -    }
> -}
> -
> -uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fd, fa, fb;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    fd.f = float32_add(fa.f, fb.f, &env->fp_status);
> -
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -    return fd.l;
> -}
> -
> -uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fd, fa, fb;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -    return fd.l;
> -}
> -
> -uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fd, fa, fb;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -
> -    return fd.l;
> -}
> -
> -uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fd, fa, fb;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    fd.f = float32_div(fb.f, fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -
> -    return fd.l;
> -}
> -
> -uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    uint32_t r = 0;
> -
> -    fa.l = a;
> -    fb.l = b;
> -
> -    if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
> -        float32_is_signaling_nan(fb.f, &env->fp_status)) {
> -        update_fpu_flags(env, float_flag_invalid, GETPC());
> -        r = 1;
> -    }
> -
> -    if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
> -        float32_is_quiet_nan(fb.f, &env->fp_status)) {
> -        r = 1;
> -    }
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int r;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    r = float32_lt(fb.f, fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags;
> -    int r;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fb.l = b;
> -    r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags;
> -    int r;
> -
> -    fa.l = a;
> -    fb.l = b;
> -    set_float_exception_flags(0, &env->fp_status);
> -    r = float32_le(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags, r;
> -
> -    fa.l = a;
> -    fb.l = b;
> -    set_float_exception_flags(0, &env->fp_status);
> -    r = float32_lt(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags, r;
> -
> -    fa.l = a;
> -    fb.l = b;
> -    set_float_exception_flags(0, &env->fp_status);
> -    r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
> -{
> -    CPU_FloatU fa, fb;
> -    int flags, r;
> -
> -    fa.l = a;
> -    fb.l = b;
> -    set_float_exception_flags(0, &env->fp_status);
> -    r = !float32_lt(fa.f, fb.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags & float_flag_invalid, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_flt(CPUMBState *env, uint32_t a)
> -{
> -    CPU_FloatU fd, fa;
> -
> -    fa.l = a;
> -    fd.f = int32_to_float32(fa.l, &env->fp_status);
> -    return fd.l;
> -}
> -
> -uint32_t helper_fint(CPUMBState *env, uint32_t a)
> -{
> -    CPU_FloatU fa;
> -    uint32_t r;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    r = float32_to_int32(fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -
> -    return r;
> -}
> -
> -uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
> -{
> -    CPU_FloatU fd, fa;
> -    int flags;
> -
> -    set_float_exception_flags(0, &env->fp_status);
> -    fa.l = a;
> -    fd.l = float32_sqrt(fa.f, &env->fp_status);
> -    flags = get_float_exception_flags(&env->fp_status);
> -    update_fpu_flags(env, flags, GETPC());
> -
> -    return fd.l;
> -}
> -
>  uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
>  {
>      unsigned int i;
> diff --git a/target/microblaze/meson.build b/target/microblaze/meson.build
> index 05ee0ec1635..0a5e46027af 100644
> --- a/target/microblaze/meson.build
> +++ b/target/microblaze/meson.build
> @@ -4,6 +4,7 @@
>  microblaze_ss.add(gen)
>  microblaze_ss.add(files(
>    'cpu.c',
> +  'fpu_helper.c',
>    'gdbstub.c',
>    'helper.c',
>    'op_helper.c',
> --
> 2.26.3
>
>