All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions
@ 2018-10-11 23:41 Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 1/7] target/ppc: Split up float_invalid_op_excp Richard Henderson
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Richard Henderson @ 2018-10-11 23:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: david, qemu-ppc

There are a few bugs here, primarily wrt usage of GETPC().
But there is opportunity to share more code between paths
that operate on different floating point types.

This is not everything that could be done, but it's a good start.
Better for this not to hang out on a branch for another release.


r~


Richard Henderson (7):
  target/ppc: Split up float_invalid_op_excp
  target/ppc: Remove float_check_status
  target/ppc: Introduce fp number classification
  target/ppc: Split out float_invalid_op_addsub
  target/ppc: Split out float_invalid_op_mul
  target/ppc: Split out float_invalid_op_div
  target/ppc: Split out float_invalid_cvt

 target/ppc/fpu_helper.c | 661 ++++++++++++++++++++--------------------
 1 file changed, 327 insertions(+), 334 deletions(-)

-- 
2.17.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 1/7] target/ppc: Split up float_invalid_op_excp
  2018-10-11 23:41 [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions Richard Henderson
@ 2018-10-11 23:41 ` Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 2/7] target/ppc: Remove float_check_status Richard Henderson
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2018-10-11 23:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: david, qemu-ppc

The always_inline trick only works if the function is always
called from the outer-most helper.  But it isn't, so pass in
the outer-most return address.  There's no need for a switch
statement whose argument is always a constant.  Unravel the
switch and goto via more helpers.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/ppc/fpu_helper.c | 344 +++++++++++++++++++++-------------------
 1 file changed, 181 insertions(+), 163 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index b9bb1b856e..6ec5227dd5 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -170,96 +170,120 @@ COMPUTE_FPRF(float64)
 COMPUTE_FPRF(float128)
 
 /* Floating-point invalid operations exception */
-static inline __attribute__((__always_inline__))
-uint64_t float_invalid_op_excp(CPUPPCState *env, int op, int set_fpcc)
+static void finish_invalid_op_excp(CPUPPCState *env, int op, uintptr_t retaddr)
 {
-    CPUState *cs = CPU(ppc_env_get_cpu(env));
-    uint64_t ret = 0;
-    int ve;
+    /* Update the floating-point invalid operation summary */
+    env->fpscr |= 1 << FPSCR_VX;
+    /* Update the floating-point exception summary */
+    env->fpscr |= FP_FX;
+    if (fpscr_ve != 0) {
+        /* Update the floating-point enabled exception summary */
+        env->fpscr |= 1 << FPSCR_FEX;
+        if (fp_exceptions_enabled(env)) {
+            raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_FP | op, retaddr);
+        }
+    }
+}
 
-    ve = fpscr_ve;
-    switch (op) {
-    case POWERPC_EXCP_FP_VXSNAN:
-        env->fpscr |= 1 << FPSCR_VXSNAN;
-        break;
-    case POWERPC_EXCP_FP_VXSOFT:
-        env->fpscr |= 1 << FPSCR_VXSOFT;
-        break;
-    case POWERPC_EXCP_FP_VXISI:
-        /* Magnitude subtraction of infinities */
-        env->fpscr |= 1 << FPSCR_VXISI;
-        goto update_arith;
-    case POWERPC_EXCP_FP_VXIDI:
-        /* Division of infinity by infinity */
-        env->fpscr |= 1 << FPSCR_VXIDI;
-        goto update_arith;
-    case POWERPC_EXCP_FP_VXZDZ:
-        /* Division of zero by zero */
-        env->fpscr |= 1 << FPSCR_VXZDZ;
-        goto update_arith;
-    case POWERPC_EXCP_FP_VXIMZ:
-        /* Multiplication of zero by infinity */
-        env->fpscr |= 1 << FPSCR_VXIMZ;
-        goto update_arith;
-    case POWERPC_EXCP_FP_VXVC:
-        /* Ordered comparison of NaN */
-        env->fpscr |= 1 << FPSCR_VXVC;
+static void finish_invalid_op_arith(CPUPPCState *env, int op,
+                                    bool set_fpcc, uintptr_t retaddr)
+{
+    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
+    if (fpscr_ve == 0) {
         if (set_fpcc) {
             env->fpscr &= ~(0xF << FPSCR_FPCC);
             env->fpscr |= 0x11 << FPSCR_FPCC;
         }
-        /* We must update the target FPR before raising the exception */
-        if (ve != 0) {
-            cs->exception_index = POWERPC_EXCP_PROGRAM;
-            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
-            /* Update the floating-point enabled exception summary */
-            env->fpscr |= 1 << FPSCR_FEX;
-            /* Exception is differed */
-            ve = 0;
-        }
-        break;
-    case POWERPC_EXCP_FP_VXSQRT:
-        /* Square root of a negative number */
-        env->fpscr |= 1 << FPSCR_VXSQRT;
-    update_arith:
-        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
-        if (ve == 0) {
-            /* Set the result to quiet NaN */
-            ret = 0x7FF8000000000000ULL;
-            if (set_fpcc) {
-                env->fpscr &= ~(0xF << FPSCR_FPCC);
-                env->fpscr |= 0x11 << FPSCR_FPCC;
-            }
-        }
-        break;
-    case POWERPC_EXCP_FP_VXCVI:
-        /* Invalid conversion */
-        env->fpscr |= 1 << FPSCR_VXCVI;
-        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
-        if (ve == 0) {
-            /* Set the result to quiet NaN */
-            ret = 0x7FF8000000000000ULL;
-            if (set_fpcc) {
-                env->fpscr &= ~(0xF << FPSCR_FPCC);
-                env->fpscr |= 0x11 << FPSCR_FPCC;
-            }
-        }
-        break;
+    }
+    finish_invalid_op_excp(env, op, retaddr);
+}
+
+/* Signalling NaN */
+static void float_invalid_op_vxsnan(CPUPPCState *env, uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXSNAN;
+    finish_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, retaddr);
+}
+
+/* Magnitude subtraction of infinities */
+static void float_invalid_op_vxisi(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXISI;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXISI, set_fpcc, retaddr);
+}
+
+/* Division of infinity by infinity */
+static void float_invalid_op_vxidi(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXIDI;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXIDI, set_fpcc, retaddr);
+}
+
+/* Division of zero by zero */
+static void float_invalid_op_vxzdz(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXZDZ;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXZDZ, set_fpcc, retaddr);
+}
+
+/* Multiplication of zero by infinity */
+static void float_invalid_op_vximz(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXIMZ;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXIMZ, set_fpcc, retaddr);
+}
+
+/* Square root of a negative number */
+static void float_invalid_op_vxsqrt(CPUPPCState *env, bool set_fpcc,
+                                    uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXSQRT;
+    finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXSQRT, set_fpcc, retaddr);
+}
+
+/* Ordered comparison of NaN */
+static void float_invalid_op_vxvc(CPUPPCState *env, bool set_fpcc,
+                                  uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXVC;
+    if (set_fpcc) {
+        env->fpscr &= ~(0xF << FPSCR_FPCC);
+        env->fpscr |= 0x11 << FPSCR_FPCC;
     }
     /* Update the floating-point invalid operation summary */
     env->fpscr |= 1 << FPSCR_VX;
     /* Update the floating-point exception summary */
     env->fpscr |= FP_FX;
-    if (ve != 0) {
+    /* We must update the target FPR before raising the exception */
+    if (fpscr_ve != 0) {
+        CPUState *cs = CPU(ppc_env_get_cpu(env));
+
+        cs->exception_index = POWERPC_EXCP_PROGRAM;
+        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
         /* Update the floating-point enabled exception summary */
         env->fpscr |= 1 << FPSCR_FEX;
-        if (fp_exceptions_enabled(env)) {
-            /* GETPC() works here because this is inline */
-            raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
-                                   POWERPC_EXCP_FP | op, GETPC());
+        /* Exception is differed */
+    }
+}
+
+/* Invalid conversion */
+static void float_invalid_op_vxcvi(CPUPPCState *env, bool set_fpcc,
+                                   uintptr_t retaddr)
+{
+    env->fpscr |= 1 << FPSCR_VXCVI;
+    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
+    if (fpscr_ve == 0) {
+        if (set_fpcc) {
+            env->fpscr &= ~(0xF << FPSCR_FPCC);
+            env->fpscr |= 0x11 << FPSCR_FPCC;
         }
     }
-    return ret;
+    finish_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, retaddr);
 }
 
 static inline void float_zero_divide_excp(CPUPPCState *env, uintptr_t raddr)
@@ -632,11 +656,11 @@ float64 helper_fadd(CPUPPCState *env, float64 arg1, float64 arg2)
     if (unlikely(status & float_flag_invalid)) {
         if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
             /* Magnitude subtraction of infinities */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+            float_invalid_op_vxisi(env, 1, GETPC());
         } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
                    float64_is_signaling_nan(arg2, &env->fp_status)) {
             /* sNaN addition */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
@@ -652,11 +676,11 @@ float64 helper_fsub(CPUPPCState *env, float64 arg1, float64 arg2)
     if (unlikely(status & float_flag_invalid)) {
         if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
             /* Magnitude subtraction of infinities */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+            float_invalid_op_vxisi(env, 1, GETPC());
         } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
                    float64_is_signaling_nan(arg2, &env->fp_status)) {
             /* sNaN addition */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
@@ -673,11 +697,11 @@ float64 helper_fmul(CPUPPCState *env, float64 arg1, float64 arg2)
         if ((float64_is_infinity(arg1) && float64_is_zero(arg2)) ||
             (float64_is_zero(arg1) && float64_is_infinity(arg2))) {
             /* Multiplication of zero by infinity */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
+            float_invalid_op_vximz(env, 1, GETPC());
         } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
                    float64_is_signaling_nan(arg2, &env->fp_status)) {
             /* sNaN multiplication */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
@@ -695,14 +719,14 @@ float64 helper_fdiv(CPUPPCState *env, float64 arg1, float64 arg2)
             /* Determine what kind of invalid operation was seen.  */
             if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
                 /* Division of infinity by infinity */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
+                float_invalid_op_vxidi(env, 1, GETPC());
             } else if (float64_is_zero(arg1) && float64_is_zero(arg2)) {
                 /* Division of zero by zero */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
+                float_invalid_op_vxzdz(env, 1, GETPC());
             } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
                        float64_is_signaling_nan(arg2, &env->fp_status)) {
                 /* sNaN division */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                float_invalid_op_vxsnan(env, GETPC());
             }
         }
         if (status & float_flag_divbyzero) {
@@ -724,14 +748,14 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)                   \
                                                                        \
     if (unlikely(env->fp_status.float_exception_flags)) {              \
         if (float64_is_any_nan(arg)) {                                 \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);      \
+            float_invalid_op_vxcvi(env, 1, GETPC());                   \
             if (float64_is_signaling_nan(arg, &env->fp_status)) {      \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); \
+                float_invalid_op_vxsnan(env, GETPC());                 \
             }                                                          \
             farg.ll = nanval;                                          \
         } else if (env->fp_status.float_exception_flags &              \
                    float_flag_invalid) {                               \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);      \
+            float_invalid_op_vxcvi(env, 1, GETPC());                   \
         }                                                              \
         float_check_status(env);                                       \
     }                                                                  \
@@ -776,7 +800,7 @@ static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
 
     if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
         /* sNaN round */
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+        float_invalid_op_vxsnan(env, GETPC());
         farg.ll = arg | 0x0008000000000000ULL;
     } else {
         int inexact = get_float_exception_flags(&env->fp_status) &
@@ -817,18 +841,18 @@ uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
 
 #define FPU_MADDSUB_UPDATE(NAME, TP)                                    \
 static void NAME(CPUPPCState *env, TP arg1, TP arg2, TP arg3,           \
-                 unsigned int madd_flags)                               \
+                 unsigned int madd_flags, uintptr_t retaddr)            \
 {                                                                       \
     if (TP##_is_signaling_nan(arg1, &env->fp_status) ||                 \
         TP##_is_signaling_nan(arg2, &env->fp_status) ||                 \
         TP##_is_signaling_nan(arg3, &env->fp_status)) {                 \
         /* sNaN operation */                                            \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);          \
+        float_invalid_op_vxsnan(env, retaddr);                          \
     }                                                                   \
     if ((TP##_is_infinity(arg1) && TP##_is_zero(arg2)) ||               \
         (TP##_is_zero(arg1) && TP##_is_infinity(arg2))) {               \
         /* Multiplication of zero by infinity */                        \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);           \
+        float_invalid_op_vximz(env, 1, retaddr);                        \
     }                                                                   \
     if ((TP##_is_infinity(arg1) || TP##_is_infinity(arg2)) &&           \
         TP##_is_infinity(arg3)) {                                       \
@@ -841,7 +865,7 @@ static void NAME(CPUPPCState *env, TP arg1, TP arg2, TP arg3,           \
             cSign ^= 1;                                                 \
         }                                                               \
         if (aSign ^ bSign ^ cSign) {                                    \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);       \
+            float_invalid_op_vxisi(env, 1, retaddr);                    \
         }                                                               \
     }                                                                   \
 }
@@ -859,7 +883,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg1,                   \
     if (flags) {                                                        \
         if (flags & float_flag_invalid) {                               \
             float64_maddsub_update_excp(env, arg1, arg2, arg3,          \
-                                        madd_flags);                    \
+                                        madd_flags, GETPC());           \
         }                                                               \
         float_check_status(env);                                        \
     }                                                                   \
@@ -885,8 +909,7 @@ uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
     farg.ll = arg;
 
     if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
-        /* sNaN square root */
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+        float_invalid_op_vxsnan(env, GETPC());
     }
     f32 = float64_to_float32(farg.d, &env->fp_status);
     farg.d = float32_to_float64(f32, &env->fp_status);
@@ -904,11 +927,11 @@ float64 helper_fsqrt(CPUPPCState *env, float64 arg)
         if (unlikely(float64_is_any_nan(arg))) {
             if (unlikely(float64_is_signaling_nan(arg, &env->fp_status))) {
                 /* sNaN square root */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                float_invalid_op_vxsnan(env, GETPC());
             }
         } else {
             /* Square root of a negative nonzero number */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
+            float_invalid_op_vxsqrt(env, 1, GETPC());
         }
     }
 
@@ -926,7 +949,7 @@ float64 helper_fre(CPUPPCState *env, float64 arg)
         if (status & float_flag_invalid) {
             if (float64_is_signaling_nan(arg, &env->fp_status)) {
                 /* sNaN reciprocal */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                float_invalid_op_vxsnan(env, GETPC());
             }
         }
         if (status & float_flag_divbyzero) {
@@ -949,7 +972,7 @@ uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
 
     if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
         /* sNaN reciprocal */
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+        float_invalid_op_vxsnan(env, GETPC());
     }
     farg.d = float64_div(float64_one, farg.d, &env->fp_status);
     f32 = float64_to_float32(farg.d, &env->fp_status);
@@ -970,10 +993,10 @@ float64 helper_frsqrte(CPUPPCState *env, float64 arg)
         if (status & float_flag_invalid) {
             if (float64_is_signaling_nan(arg, &env->fp_status)) {
                 /* sNaN reciprocal */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                float_invalid_op_vxsnan(env, GETPC());
             } else {
                 /* Square root of a negative nonzero number */
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
+                float_invalid_op_vxsqrt(env, 1, GETPC());
             }
         }
         if (status & float_flag_divbyzero) {
@@ -1095,7 +1118,7 @@ void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
                  && (float64_is_signaling_nan(farg1.d, &env->fp_status) ||
                      float64_is_signaling_nan(farg2.d, &env->fp_status)))) {
         /* sNaN comparison */
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+        float_invalid_op_vxsnan(env, GETPC());
     }
 }
 
@@ -1123,14 +1146,11 @@ void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
     env->fpscr |= ret << FPSCR_FPRF;
     env->crf[crfD] = ret;
     if (unlikely(ret == 0x01UL)) {
+        float_invalid_op_vxvc(env, 1, GETPC());
         if (float64_is_signaling_nan(farg1.d, &env->fp_status) ||
             float64_is_signaling_nan(farg2.d, &env->fp_status)) {
             /* sNaN comparison */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
-                                  POWERPC_EXCP_FP_VXVC, 1);
-        } else {
-            /* qNaN comparison */
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 }
@@ -1783,10 +1803,10 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                        \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {      \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf);    \
+                float_invalid_op_vxisi(env, sfprf, GETPC());                 \
             } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
                        tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
         }                                                                    \
                                                                              \
@@ -1832,10 +1852,10 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+            float_invalid_op_vxisi(env, 1, GETPC());
         } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
                    float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
@@ -1872,10 +1892,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if ((tp##_is_infinity(xa.fld) && tp##_is_zero(xb.fld)) ||        \
                 (tp##_is_infinity(xb.fld) && tp##_is_zero(xa.fld))) {        \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, sfprf);    \
+                float_invalid_op_vximz(env, sfprf, GETPC());                 \
             } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
                        tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
         }                                                                    \
                                                                              \
@@ -1919,10 +1939,10 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode)
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if ((float128_is_infinity(xa.f128) && float128_is_zero(xb.f128)) ||
             (float128_is_infinity(xb.f128) && float128_is_zero(xa.f128))) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
+            float_invalid_op_vximz(env, 1, GETPC());
         } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
                    float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
     helper_compute_fprf_float128(env, xt.f128);
@@ -1957,13 +1977,12 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
                                                                               \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
             if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {       \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf);     \
-            } else if (tp##_is_zero(xa.fld) &&                                \
-                tp##_is_zero(xb.fld)) {                                       \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf);     \
+                float_invalid_op_vxidi(env, sfprf, GETPC());                  \
+            } else if (tp##_is_zero(xa.fld) && tp##_is_zero(xb.fld)) {        \
+                float_invalid_op_vxzdz(env, sfprf, GETPC());                  \
             } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||               \
-                tp##_is_signaling_nan(xb.fld, &tstat)) {                      \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
+                       tp##_is_signaling_nan(xb.fld, &tstat)) {               \
+                float_invalid_op_vxsnan(env, GETPC());                        \
             }                                                                 \
         }                                                                     \
         if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {   \
@@ -2009,13 +2028,12 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
-        } else if (float128_is_zero(xa.f128) &&
-            float128_is_zero(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
+            float_invalid_op_vxidi(env, 1, GETPC());
+        } else if (float128_is_zero(xa.f128) && float128_is_zero(xb.f128)) {
+            float_invalid_op_vxzdz(env, 1, GETPC());
         } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-            float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+                   float128_is_signaling_nan(xb.f128, &tstat)) {
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
     if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {
@@ -2046,7 +2064,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
                                                                               \
     for (i = 0; i < nels; i++) {                                              \
         if (unlikely(tp##_is_signaling_nan(xb.fld, &env->fp_status))) {       \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
+            float_invalid_op_vxsnan(env, GETPC());                            \
         }                                                                     \
         xt.fld = tp##_div(tp##_one, xb.fld, &env->fp_status);                 \
                                                                               \
@@ -2093,9 +2111,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   \
+                float_invalid_op_vxsqrt(env, sfprf, GETPC());                \
             } else if (tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
         }                                                                    \
                                                                              \
@@ -2143,9 +2161,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   \
+                float_invalid_op_vxsqrt(env, sfprf, GETPC());                \
             } else if (tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
         }                                                                    \
                                                                              \
@@ -2329,7 +2347,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
         env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
                                                                               \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
-            tp##_maddsub_update_excp(env, xa.fld, b->fld, c->fld, maddflgs);  \
+            tp##_maddsub_update_excp(env, xa.fld, b->fld,                     \
+                                     c->fld, maddflgs, GETPC());              \
         }                                                                     \
                                                                               \
         if (r2sp) {                                                           \
@@ -2407,10 +2426,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
             float64_is_quiet_nan(xb.VsrD(0), &env->fp_status);                \
     }                                                                         \
     if (vxsnan_flag) {                                                        \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);                \
+        float_invalid_op_vxsnan(env, GETPC());                                \
     }                                                                         \
     if (vxvc_flag) {                                                          \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);                  \
+        float_invalid_op_vxvc(env, 0, GETPC());                               \
     }                                                                         \
     vex_flag = fpscr_ve && (vxvc_flag || vxsnan_flag);                        \
                                                                               \
@@ -2522,10 +2541,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                      \
         }                                                                \
     }                                                                    \
     if (vxsnan_flag) {                                                   \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);           \
+        float_invalid_op_vxsnan(env, GETPC());                           \
     }                                                                    \
     if (vxvc_flag) {                                                     \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);             \
+        float_invalid_op_vxvc(env, 0, GETPC());                          \
     }                                                                    \
                                                                          \
     if (float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) {           \
@@ -2572,10 +2591,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
         }                                                               \
     }                                                                   \
     if (vxsnan_flag) {                                                  \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);          \
+        float_invalid_op_vxsnan(env, GETPC());                          \
     }                                                                   \
     if (vxvc_flag) {                                                    \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);            \
+        float_invalid_op_vxvc(env, 0, GETPC());                         \
     }                                                                   \
                                                                         \
     if (float128_lt(xa.f128, xb.f128, &env->fp_status)) {               \
@@ -2617,7 +2636,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                         \
         xt.fld = tp##_##op(xa.fld, xb.fld, &env->fp_status);                  \
         if (unlikely(tp##_is_signaling_nan(xa.fld, &env->fp_status) ||        \
                      tp##_is_signaling_nan(xb.fld, &env->fp_status))) {       \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);            \
+            float_invalid_op_vxsnan(env, GETPC());                            \
         }                                                                     \
     }                                                                         \
                                                                               \
@@ -2660,7 +2679,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                         \
                                                                               \
     vex_flag = fpscr_ve & vxsnan_flag;                                        \
     if (vxsnan_flag) {                                                        \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);            \
+        float_invalid_op_vxsnan(env, GETPC());                                \
     }                                                                         \
     if (!vex_flag) {                                                          \
         putVSR(rD(opcode) + 32, &xt, env);                                    \
@@ -2715,7 +2734,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                         \
                                                                               \
     vex_flag = fpscr_ve & vxsnan_flag;                                        \
     if (vxsnan_flag) {                                                        \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);            \
+        float_invalid_op_vxsnan(env, GETPC());                                \
     }                                                                         \
     if (!vex_flag) {                                                          \
         putVSR(rD(opcode) + 32, &xt, env);                                    \
@@ -2751,10 +2770,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                       \
                      tp##_is_any_nan(xb.fld))) {                          \
             if (tp##_is_signaling_nan(xa.fld, &env->fp_status) ||         \
                 tp##_is_signaling_nan(xb.fld, &env->fp_status)) {         \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);    \
+                float_invalid_op_vxsnan(env, GETPC());                    \
             }                                                             \
             if (svxvc) {                                                  \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);      \
+                float_invalid_op_vxvc(env, 0, GETPC());                   \
             }                                                             \
             xt.fld = 0;                                                   \
             all_true = 0;                                                 \
@@ -2807,7 +2826,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                \
         xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status);        \
         if (unlikely(stp##_is_signaling_nan(xb.sfld,               \
                                             &env->fp_status))) {   \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
+            float_invalid_op_vxsnan(env, GETPC());                 \
             xt.tfld = ttp##_snan_to_qnan(xt.tfld);                 \
         }                                                          \
         if (sfprf) {                                               \
@@ -2846,7 +2865,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                       \
         xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status);             \
         if (unlikely(stp##_is_signaling_nan(xb.sfld,                    \
                                             &env->fp_status))) {        \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);      \
+            float_invalid_op_vxsnan(env, GETPC());                      \
             xt.tfld = ttp##_snan_to_qnan(xt.tfld);                      \
         }                                                               \
         if (sfprf) {                                                    \
@@ -2883,7 +2902,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                \
         xt.tfld = stp##_to_##ttp(xb.sfld, 1, &env->fp_status);     \
         if (unlikely(stp##_is_signaling_nan(xb.sfld,               \
                                             &env->fp_status))) {   \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
+            float_invalid_op_vxsnan(env, GETPC());                 \
             xt.tfld = ttp##_snan_to_qnan(xt.tfld);                 \
         }                                                          \
         if (sfprf) {                                               \
@@ -2919,9 +2938,8 @@ void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode)
 
     xt.VsrD(0) = float128_to_float64(xb.f128, &tstat);
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
-    if (unlikely(float128_is_signaling_nan(xb.f128,
-                                           &tstat))) {
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);
+    if (unlikely(float128_is_signaling_nan(xb.f128, &tstat))) {
+        float_invalid_op_vxsnan(env, GETPC());
         xt.VsrD(0) = float64_snan_to_qnan(xt.VsrD(0));
     }
     helper_compute_fprf_float64(env, xt.VsrD(0));
@@ -2967,15 +2985,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     for (i = 0; i < nels; i++) {                                             \
         if (unlikely(stp##_is_any_nan(xb.sfld))) {                           \
             if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {          \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);       \
+                float_invalid_op_vxsnan(env, GETPC());                       \
             }                                                                \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);            \
+            float_invalid_op_vxcvi(env, 0, GETPC());                         \
             xt.tfld = rnan;                                                  \
         } else {                                                             \
             xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld,                \
                           &env->fp_status);                                  \
             if (env->fp_status.float_exception_flags & float_flag_invalid) { \
-                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);        \
+                float_invalid_op_vxcvi(env, 0, GETPC());                     \
             }                                                                \
         }                                                                    \
     }                                                                        \
@@ -3020,15 +3038,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
                                                                              \
     if (unlikely(stp##_is_any_nan(xb.sfld))) {                               \
         if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {              \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);           \
+            float_invalid_op_vxsnan(env, GETPC());                           \
         }                                                                    \
-        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);                \
+        float_invalid_op_vxcvi(env, 0, GETPC());                             \
         xt.tfld = rnan;                                                      \
     } else {                                                                 \
         xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld,                    \
                       &env->fp_status);                                      \
         if (env->fp_status.float_exception_flags & float_flag_invalid) {     \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);            \
+            float_invalid_op_vxcvi(env, 0, GETPC());                         \
         }                                                                    \
     }                                                                        \
                                                                              \
@@ -3144,7 +3162,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                    \
     for (i = 0; i < nels; i++) {                                       \
         if (unlikely(tp##_is_signaling_nan(xb.fld,                     \
                                            &env->fp_status))) {        \
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);     \
+            float_invalid_op_vxsnan(env, GETPC());                     \
             xt.fld = tp##_snan_to_qnan(xb.fld);                        \
         } else {                                                       \
             xt.fld = tp##_round_to_int(xb.fld, &env->fp_status);       \
@@ -3373,7 +3391,7 @@ void helper_xsrqpi(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);
+            float_invalid_op_vxsnan(env, GETPC());
             xt.f128 = float128_snan_to_qnan(xt.f128);
         }
     }
@@ -3433,7 +3451,7 @@ void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);
+            float_invalid_op_vxsnan(env, GETPC());
             xt.f128 = float128_snan_to_qnan(xt.f128);
         }
     }
@@ -3464,12 +3482,12 @@ void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
             xt.f128 = float128_snan_to_qnan(xb.f128);
         } else if  (float128_is_quiet_nan(xb.f128, &tstat)) {
             xt.f128 = xb.f128;
         } else if (float128_is_neg(xb.f128) && !float128_is_zero(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
+            float_invalid_op_vxsqrt(env, 1, GETPC());
             xt.f128 = float128_default_nan(&env->fp_status);
         }
     }
@@ -3500,10 +3518,10 @@ void helper_xssubqp(CPUPPCState *env, uint32_t opcode)
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
         if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+            float_invalid_op_vxisi(env, 1, GETPC());
         } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
                    float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+            float_invalid_op_vxsnan(env, GETPC());
         }
     }
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 2/7] target/ppc: Remove float_check_status
  2018-10-11 23:41 [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 1/7] target/ppc: Split up float_invalid_op_excp Richard Henderson
@ 2018-10-11 23:41 ` Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 3/7] target/ppc: Introduce fp number classification Richard Henderson
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2018-10-11 23:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: david, qemu-ppc

Use do_float_check_status directly, so that we don't get confused
about which return address we're using.  And definitely don't use
helper_float_check_status.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/ppc/fpu_helper.c | 77 +++++++++++++++++++----------------------
 1 file changed, 35 insertions(+), 42 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 6ec5227dd5..c9198f826d 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -630,13 +630,6 @@ static void do_float_check_status(CPUPPCState *env, uintptr_t raddr)
     }
 }
 
-static inline  __attribute__((__always_inline__))
-void float_check_status(CPUPPCState *env)
-{
-    /* GETPC() works here because this is inline */
-    do_float_check_status(env, GETPC());
-}
-
 void helper_float_check_status(CPUPPCState *env)
 {
     do_float_check_status(env, GETPC());
@@ -757,7 +750,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)                   \
                    float_flag_invalid) {                               \
             float_invalid_op_vxcvi(env, 1, GETPC());                   \
         }                                                              \
-        float_check_status(env);                                       \
+        do_float_check_status(env, GETPC());                           \
     }                                                                  \
     return farg.ll;                                                    \
  }
@@ -782,7 +775,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg)       \
     } else {                                               \
         farg.d = cvtr(arg, &env->fp_status);               \
     }                                                      \
-    float_check_status(env);                               \
+    do_float_check_status(env, GETPC());                   \
     return farg.ll;                                        \
 }
 
@@ -815,7 +808,7 @@ static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
             env->fp_status.float_exception_flags &= ~float_flag_inexact;
         }
     }
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
     return farg.ll;
 }
 
@@ -885,7 +878,7 @@ uint64_t helper_##op(CPUPPCState *env, uint64_t arg1,                   \
             float64_maddsub_update_excp(env, arg1, arg2, arg3,          \
                                         madd_flags, GETPC());           \
         }                                                               \
-        float_check_status(env);                                        \
+        do_float_check_status(env, GETPC());                            \
     }                                                                   \
     return ret;                                                         \
 }
@@ -1819,7 +1812,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                        \
         }                                                                    \
     }                                                                        \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_ADD_SUB(xsadddp, add, 1, float64, VsrD(0), 1, 0)
@@ -1862,7 +1855,7 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode)
     helper_compute_fprf_float128(env, xt.f128);
 
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 /* VSX_MUL - VSX floating point multiply
@@ -1909,7 +1902,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_MUL(xsmuldp, 1, float64, VsrD(0), 1, 0)
@@ -1948,7 +1941,7 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode)
     helper_compute_fprf_float128(env, xt.f128);
 
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 /* VSX_DIV - VSX floating point divide
@@ -1999,7 +1992,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
     }                                                                         \
                                                                               \
     putVSR(xT(opcode), &xt, env);                                             \
-    float_check_status(env);                                                  \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_DIV(xsdivdp, 1, float64, VsrD(0), 1, 0)
@@ -2042,7 +2035,7 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode)
 
     helper_compute_fprf_float128(env, xt.f128);
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 /* VSX_RE  - VSX floating point reciprocal estimate
@@ -2078,7 +2071,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
     }                                                                         \
                                                                               \
     putVSR(xT(opcode), &xt, env);                                             \
-    float_check_status(env);                                                  \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_RE(xsredp, 1, float64, VsrD(0), 1, 0)
@@ -2127,7 +2120,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_SQRT(xssqrtdp, 1, float64, VsrD(0), 1, 0)
@@ -2177,7 +2170,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_RSQRTE(xsrsqrtedp, 1, float64, VsrD(0), 1, 0)
@@ -2360,7 +2353,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
         }                                                                     \
     }                                                                         \
     putVSR(xT(opcode), &xt_out, env);                                         \
-    float_check_status(env);                                                  \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_MADD(xsmaddadp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 0)
@@ -2443,7 +2436,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
         }                                                                     \
     }                                                                         \
     putVSR(xT(opcode), &xt, env);                                             \
-    helper_float_check_status(env);                                           \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_SCALAR_CMP_DP(xscmpeqdp, eq, 1, 0)
@@ -2480,7 +2473,7 @@ void helper_xscmpexpdp(CPUPPCState *env, uint32_t opcode)
     env->fpscr |= cc << FPSCR_FPRF;
     env->crf[BF(opcode)] = cc;
 
-    helper_float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode)
@@ -2512,7 +2505,7 @@ void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode)
     env->fpscr |= cc << FPSCR_FPRF;
     env->crf[BF(opcode)] = cc;
 
-    helper_float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 #define VSX_SCALAR_CMP(op, ordered)                                      \
@@ -2559,7 +2552,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                      \
     env->fpscr |= cc << FPSCR_FPRF;                                      \
     env->crf[BF(opcode)] = cc;                                           \
                                                                          \
-    float_check_status(env);                                             \
+    do_float_check_status(env, GETPC());                                 \
 }
 
 VSX_SCALAR_CMP(xscmpodp, 1)
@@ -2609,7 +2602,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
     env->fpscr |= cc << FPSCR_FPRF;                                     \
     env->crf[BF(opcode)] = cc;                                          \
                                                                         \
-    float_check_status(env);                                            \
+    do_float_check_status(env, GETPC());                                \
 }
 
 VSX_SCALAR_CMPQ(xscmpoqp, 1)
@@ -2641,7 +2634,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                         \
     }                                                                         \
                                                                               \
     putVSR(xT(opcode), &xt, env);                                             \
-    float_check_status(env);                                                  \
+    do_float_check_status(env, GETPC());                                      \
 }
 
 VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, VsrD(0))
@@ -2792,7 +2785,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                       \
     if ((opcode >> (31-21)) & 1) {                                        \
         env->crf[6] = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0);       \
     }                                                                     \
-    float_check_status(env);                                              \
+    do_float_check_status(env, GETPC());                                  \
  }
 
 VSX_CMP(xvcmpeqdp, 2, float64, VsrD(i), eq, 0, 1)
@@ -2835,7 +2828,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                \
     }                                                              \
                                                                    \
     putVSR(xT(opcode), &xt, env);                                  \
-    float_check_status(env);                                       \
+    do_float_check_status(env, GETPC());                           \
 }
 
 VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, VsrD(0), VsrW(0), 1)
@@ -2874,7 +2867,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                       \
     }                                                                   \
                                                                         \
     putVSR(rD(opcode) + 32, &xt, env);                                  \
-    float_check_status(env);                                            \
+    do_float_check_status(env, GETPC());                                \
 }
 
 VSX_CVT_FP_TO_FP_VECTOR(xscvdpqp, 1, float64, float128, VsrD(0), f128, 1)
@@ -2911,7 +2904,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                \
     }                                                              \
                                                                    \
     putVSR(xT(opcode), &xt, env);                                  \
-    float_check_status(env);                                       \
+    do_float_check_status(env, GETPC());                           \
 }
 
 VSX_CVT_FP_TO_FP_HP(xscvdphp, 1, float64, float16, VsrD(0), VsrH(3), 1)
@@ -2945,7 +2938,7 @@ void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode)
     helper_compute_fprf_float64(env, xt.VsrD(0));
 
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
@@ -2999,7 +2992,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, VsrD(0), VsrD(0), \
@@ -3051,7 +3044,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     }                                                                        \
                                                                              \
     putVSR(rD(opcode) + 32, &xt, env);                                       \
-    float_check_status(env);                                                 \
+    do_float_check_status(env, GETPC());                                     \
 }
 
 VSX_CVT_FP_TO_INT_VECTOR(xscvqpsdz, float128, int64, f128, VsrD(0),          \
@@ -3092,7 +3085,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
     }                                                                   \
                                                                         \
     putVSR(xT(opcode), &xt, env);                                       \
-    float_check_status(env);                                            \
+    do_float_check_status(env, GETPC());                                \
 }
 
 VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, VsrD(0), VsrD(0), 1, 0)
@@ -3127,7 +3120,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
     helper_compute_fprf_##ttp(env, xt.tfld);                            \
                                                                         \
     putVSR(xT(opcode) + 32, &xt, env);                                  \
-    float_check_status(env);                                            \
+    do_float_check_status(env, GETPC());                                \
 }
 
 VSX_CVT_INT_TO_FP_VECTOR(xscvsdqp, int64, float128, VsrD(0), f128)
@@ -3181,7 +3174,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                    \
     }                                                                  \
                                                                        \
     putVSR(xT(opcode), &xt, env);                                      \
-    float_check_status(env);                                           \
+    do_float_check_status(env, GETPC());                               \
 }
 
 VSX_ROUND(xsrdpi, 1, float64, VsrD(0), float_round_ties_away, 1)
@@ -3209,7 +3202,7 @@ uint64_t helper_xsrsp(CPUPPCState *env, uint64_t xb)
     uint64_t xt = helper_frsp(env, xb);
 
     helper_compute_fprf_float64(env, xt);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
     return xt;
 }
 
@@ -3401,7 +3394,7 @@ void helper_xsrqpi(CPUPPCState *env, uint32_t opcode)
     }
 
     helper_compute_fprf_float128(env, xt.f128);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
     putVSR(rD(opcode) + 32, &xt, env);
 }
 
@@ -3458,7 +3451,7 @@ void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode)
 
     helper_compute_fprf_float128(env, xt.f128);
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode)
@@ -3494,7 +3487,7 @@ void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode)
 
     helper_compute_fprf_float128(env, xt.f128);
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
 
 void helper_xssubqp(CPUPPCState *env, uint32_t opcode)
@@ -3527,5 +3520,5 @@ void helper_xssubqp(CPUPPCState *env, uint32_t opcode)
 
     helper_compute_fprf_float128(env, xt.f128);
     putVSR(rD(opcode) + 32, &xt, env);
-    float_check_status(env);
+    do_float_check_status(env, GETPC());
 }
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 3/7] target/ppc: Introduce fp number classification
  2018-10-11 23:41 [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 1/7] target/ppc: Split up float_invalid_op_excp Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 2/7] target/ppc: Remove float_check_status Richard Henderson
@ 2018-10-11 23:41 ` Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 4/7] target/ppc: Split out float_invalid_op_addsub Richard Henderson
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2018-10-11 23:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: david, qemu-ppc

Having a separate, logical classifiation of numbers will
unify more error paths for different formats.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/ppc/fpu_helper.c | 94 ++++++++++++++++++++++-------------------
 1 file changed, 51 insertions(+), 43 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index c9198f826d..9ae55b1e93 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -114,54 +114,62 @@ static inline int ppc_float64_get_unbiased_exp(float64 f)
     return ((f >> 52) & 0x7FF) - 1023;
 }
 
-#define COMPUTE_FPRF(tp)                                       \
-void helper_compute_fprf_##tp(CPUPPCState *env, tp arg)        \
+/* Classify a floating-point number.  */
+enum {
+    is_normal   = 1,
+    is_zero     = 2,
+    is_denormal = 4,
+    is_inf      = 8,
+    is_qnan     = 16,
+    is_snan     = 32,
+    is_neg      = 64,
+};
+
+#define COMPUTE_CLASS(tp)                                      \
+static int tp##_classify(tp arg)                               \
 {                                                              \
-    int isneg;                                                 \
-    int fprf;                                                  \
-                                                               \
-    isneg = tp##_is_neg(arg);                                  \
+    int ret = tp##_is_neg(arg) * is_neg;                       \
     if (unlikely(tp##_is_any_nan(arg))) {                      \
-        if (tp##_is_signaling_nan(arg, &env->fp_status)) {     \
-            /* Signaling NaN: flags are undefined */           \
-            fprf = 0x00;                                       \
-        } else {                                               \
-            /* Quiet NaN */                                    \
-            fprf = 0x11;                                       \
-        }                                                      \
+        float_status dummy = { };  /* snan_bit_is_one = 0 */   \
+        ret |= (tp##_is_signaling_nan(arg, &dummy)             \
+                ? is_snan : is_qnan);                          \
     } else if (unlikely(tp##_is_infinity(arg))) {              \
-        /* +/- infinity */                                     \
-        if (isneg) {                                           \
-            fprf = 0x09;                                       \
-        } else {                                               \
-            fprf = 0x05;                                       \
-        }                                                      \
+        ret |= is_inf;                                         \
+    } else if (tp##_is_zero(arg)) {                            \
+        ret |= is_zero;                                        \
+    } else if (tp##_is_zero_or_denormal(arg)) {                \
+        ret |= is_denormal;                                    \
     } else {                                                   \
-        if (tp##_is_zero(arg)) {                               \
-            /* +/- zero */                                     \
-            if (isneg) {                                       \
-                fprf = 0x12;                                   \
-            } else {                                           \
-                fprf = 0x02;                                   \
-            }                                                  \
-        } else {                                               \
-            if (tp##_is_zero_or_denormal(arg)) {               \
-                /* Denormalized numbers */                     \
-                fprf = 0x10;                                   \
-            } else {                                           \
-                /* Normalized numbers */                       \
-                fprf = 0x00;                                   \
-            }                                                  \
-            if (isneg) {                                       \
-                fprf |= 0x08;                                  \
-            } else {                                           \
-                fprf |= 0x04;                                  \
-            }                                                  \
-        }                                                      \
+        ret |= is_normal;                                      \
     }                                                          \
-    /* We update FPSCR_FPRF */                                 \
-    env->fpscr &= ~(0x1F << FPSCR_FPRF);                       \
-    env->fpscr |= fprf << FPSCR_FPRF;                          \
+    return ret;                                                \
+}
+
+COMPUTE_CLASS(float16)
+COMPUTE_CLASS(float32)
+COMPUTE_CLASS(float64)
+COMPUTE_CLASS(float128)
+
+static void set_fprf_from_class(CPUPPCState *env, int class)
+{
+    static const uint8_t fprf[6][2] = {
+        { 0x04, 0x08 },  /* normalized */
+        { 0x02, 0x12 },  /* zero */
+        { 0x14, 0x18 },  /* denormalized */
+        { 0x05, 0x09 },  /* infinity */
+        { 0x11, 0x11 },  /* qnan */
+        { 0x00, 0x00 },  /* snan -- flags are undefined */
+    };
+    bool isneg = class & is_neg;
+
+    env->fpscr &= ~(0x1F << FPSCR_FPRF);
+    env->fpscr |= fprf[ctz32(class)][isneg] << FPSCR_FPRF;
+}
+
+#define COMPUTE_FPRF(tp)                                \
+void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \
+{                                                       \
+    set_fprf_from_class(env, tp##_classify(arg));       \
 }
 
 COMPUTE_FPRF(float16)
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 4/7] target/ppc: Split out float_invalid_op_addsub
  2018-10-11 23:41 [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions Richard Henderson
                   ` (2 preceding siblings ...)
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 3/7] target/ppc: Introduce fp number classification Richard Henderson
@ 2018-10-11 23:41 ` Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 5/7] target/ppc: Split out float_invalid_op_mul Richard Henderson
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2018-10-11 23:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: david, qemu-ppc

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/ppc/fpu_helper.c | 60 ++++++++++++++++++-----------------------
 1 file changed, 26 insertions(+), 34 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 9ae55b1e93..111ce12a37 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -648,6 +648,17 @@ void helper_reset_fpstatus(CPUPPCState *env)
     set_float_exception_flags(0, &env->fp_status);
 }
 
+static void float_invalid_op_addsub(CPUPPCState *env, bool set_fpcc,
+                                    uintptr_t retaddr, int classes)
+{
+    if ((classes & ~is_neg) == is_inf) {
+        /* Magnitude subtraction of infinities */
+        float_invalid_op_vxisi(env, set_fpcc, retaddr);
+    } else if (classes & is_snan) {
+        float_invalid_op_vxsnan(env, retaddr);
+    }
+}
+
 /* fadd - fadd. */
 float64 helper_fadd(CPUPPCState *env, float64 arg1, float64 arg2)
 {
@@ -655,14 +666,9 @@ float64 helper_fadd(CPUPPCState *env, float64 arg1, float64 arg2)
     int status = get_float_exception_flags(&env->fp_status);
 
     if (unlikely(status & float_flag_invalid)) {
-        if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
-            /* Magnitude subtraction of infinities */
-            float_invalid_op_vxisi(env, 1, GETPC());
-        } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
-                   float64_is_signaling_nan(arg2, &env->fp_status)) {
-            /* sNaN addition */
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_addsub(env, 1, GETPC(),
+                                float64_classify(arg1) |
+                                float64_classify(arg2));
     }
 
     return ret;
@@ -675,14 +681,9 @@ float64 helper_fsub(CPUPPCState *env, float64 arg1, float64 arg2)
     int status = get_float_exception_flags(&env->fp_status);
 
     if (unlikely(status & float_flag_invalid)) {
-        if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
-            /* Magnitude subtraction of infinities */
-            float_invalid_op_vxisi(env, 1, GETPC());
-        } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
-                   float64_is_signaling_nan(arg2, &env->fp_status)) {
-            /* sNaN addition */
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_addsub(env, 1, GETPC(),
+                                float64_classify(arg1) |
+                                float64_classify(arg2));
     }
 
     return ret;
@@ -1803,12 +1804,9 @@ void helper_##name(CPUPPCState *env, uint32_t opcode)                        \
         env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
-            if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {      \
-                float_invalid_op_vxisi(env, sfprf, GETPC());                 \
-            } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
-                       tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_vxsnan(env, GETPC());                       \
-            }                                                                \
+            float_invalid_op_addsub(env, sfprf, GETPC(),                     \
+                                    tp##_classify(xa.fld) |                  \
+                                    tp##_classify(xb.fld));                  \
         }                                                                    \
                                                                              \
         if (r2sp) {                                                          \
@@ -1852,12 +1850,9 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode)
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
-        if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_vxisi(env, 1, GETPC());
-        } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-                   float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_addsub(env, 1, GETPC(),
+                                float128_classify(xa.f128) |
+                                float128_classify(xb.f128));
     }
 
     helper_compute_fprf_float128(env, xt.f128);
@@ -3518,12 +3513,9 @@ void helper_xssubqp(CPUPPCState *env, uint32_t opcode)
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
-        if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_vxisi(env, 1, GETPC());
-        } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-                   float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_addsub(env, 1, GETPC(),
+                                float128_classify(xa.f128) |
+                                float128_classify(xb.f128));
     }
 
     helper_compute_fprf_float128(env, xt.f128);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 5/7] target/ppc: Split out float_invalid_op_mul
  2018-10-11 23:41 [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions Richard Henderson
                   ` (3 preceding siblings ...)
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 4/7] target/ppc: Split out float_invalid_op_addsub Richard Henderson
@ 2018-10-11 23:41 ` Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 6/7] target/ppc: Split out float_invalid_op_div Richard Henderson
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2018-10-11 23:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: david, qemu-ppc

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/ppc/fpu_helper.c | 43 +++++++++++++++++++----------------------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 111ce12a37..ef251d062f 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -689,6 +689,17 @@ float64 helper_fsub(CPUPPCState *env, float64 arg1, float64 arg2)
     return ret;
 }
 
+static void float_invalid_op_mul(CPUPPCState *env, bool set_fprc,
+                                 uintptr_t retaddr, int classes)
+{
+    if ((classes & (is_zero | is_inf)) == (is_zero | is_inf)) {
+        /* Multiplication of zero by infinity */
+        float_invalid_op_vximz(env, set_fprc, retaddr);
+    } else if (classes & is_snan) {
+        float_invalid_op_vxsnan(env, retaddr);
+    }
+}
+
 /* fmul - fmul. */
 float64 helper_fmul(CPUPPCState *env, float64 arg1, float64 arg2)
 {
@@ -696,15 +707,9 @@ float64 helper_fmul(CPUPPCState *env, float64 arg1, float64 arg2)
     int status = get_float_exception_flags(&env->fp_status);
 
     if (unlikely(status & float_flag_invalid)) {
-        if ((float64_is_infinity(arg1) && float64_is_zero(arg2)) ||
-            (float64_is_zero(arg1) && float64_is_infinity(arg2))) {
-            /* Multiplication of zero by infinity */
-            float_invalid_op_vximz(env, 1, GETPC());
-        } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
-                   float64_is_signaling_nan(arg2, &env->fp_status)) {
-            /* sNaN multiplication */
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_mul(env, 1, GETPC(),
+                             float64_classify(arg1) |
+                             float64_classify(arg2));
     }
 
     return ret;
@@ -1886,13 +1891,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
         env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
                                                                              \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
-            if ((tp##_is_infinity(xa.fld) && tp##_is_zero(xb.fld)) ||        \
-                (tp##_is_infinity(xb.fld) && tp##_is_zero(xa.fld))) {        \
-                float_invalid_op_vximz(env, sfprf, GETPC());                 \
-            } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
-                       tp##_is_signaling_nan(xb.fld, &tstat)) {              \
-                float_invalid_op_vxsnan(env, GETPC());                       \
-            }                                                                \
+            float_invalid_op_mul(env, sfprf, GETPC(),                        \
+                                 tp##_classify(xa.fld) |                     \
+                                 tp##_classify(xb.fld));                     \
         }                                                                    \
                                                                              \
         if (r2sp) {                                                          \
@@ -1933,13 +1934,9 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode)
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
-        if ((float128_is_infinity(xa.f128) && float128_is_zero(xb.f128)) ||
-            (float128_is_infinity(xb.f128) && float128_is_zero(xa.f128))) {
-            float_invalid_op_vximz(env, 1, GETPC());
-        } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-                   float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_mul(env, 1, GETPC(),
+                             float128_classify(xa.f128) |
+                             float128_classify(xb.f128));
     }
     helper_compute_fprf_float128(env, xt.f128);
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 6/7] target/ppc: Split out float_invalid_op_div
  2018-10-11 23:41 [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions Richard Henderson
                   ` (4 preceding siblings ...)
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 5/7] target/ppc: Split out float_invalid_op_mul Richard Henderson
@ 2018-10-11 23:41 ` Richard Henderson
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 7/7] target/ppc: Split out float_invalid_cvt Richard Henderson
  2018-10-12  1:14 ` [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions David Gibson
  7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2018-10-11 23:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: david, qemu-ppc

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/ppc/fpu_helper.c | 52 +++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 28 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index ef251d062f..127c08bcec 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -715,6 +715,21 @@ float64 helper_fmul(CPUPPCState *env, float64 arg1, float64 arg2)
     return ret;
 }
 
+static void float_invalid_op_div(CPUPPCState *env, bool set_fprc,
+                                 uintptr_t retaddr, int classes)
+{
+    classes &= ~is_neg;
+    if (classes == is_inf) {
+        /* Division of infinity by infinity */
+        float_invalid_op_vxidi(env, set_fprc, retaddr);
+    } else if (classes == is_zero) {
+        /* Division of zero by zero */
+        float_invalid_op_vxzdz(env, set_fprc, retaddr);
+    } else if (classes & is_snan) {
+        float_invalid_op_vxsnan(env, retaddr);
+    }
+}
+
 /* fdiv - fdiv. */
 float64 helper_fdiv(CPUPPCState *env, float64 arg1, float64 arg2)
 {
@@ -723,18 +738,9 @@ float64 helper_fdiv(CPUPPCState *env, float64 arg1, float64 arg2)
 
     if (unlikely(status)) {
         if (status & float_flag_invalid) {
-            /* Determine what kind of invalid operation was seen.  */
-            if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
-                /* Division of infinity by infinity */
-                float_invalid_op_vxidi(env, 1, GETPC());
-            } else if (float64_is_zero(arg1) && float64_is_zero(arg2)) {
-                /* Division of zero by zero */
-                float_invalid_op_vxzdz(env, 1, GETPC());
-            } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
-                       float64_is_signaling_nan(arg2, &env->fp_status)) {
-                /* sNaN division */
-                float_invalid_op_vxsnan(env, GETPC());
-            }
+            float_invalid_op_div(env, 1, GETPC(),
+                                 float64_classify(arg1) |
+                                 float64_classify(arg2));
         }
         if (status & float_flag_divbyzero) {
             float_zero_divide_excp(env, GETPC());
@@ -1969,14 +1975,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
         env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
                                                                               \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
-            if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {       \
-                float_invalid_op_vxidi(env, sfprf, GETPC());                  \
-            } else if (tp##_is_zero(xa.fld) && tp##_is_zero(xb.fld)) {        \
-                float_invalid_op_vxzdz(env, sfprf, GETPC());                  \
-            } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||               \
-                       tp##_is_signaling_nan(xb.fld, &tstat)) {               \
-                float_invalid_op_vxsnan(env, GETPC());                        \
-            }                                                                 \
+            float_invalid_op_div(env, sfprf, GETPC(),                         \
+                                 tp##_classify(xa.fld) |                      \
+                                 tp##_classify(xb.fld));                      \
         }                                                                     \
         if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {   \
             float_zero_divide_excp(env, GETPC());                             \
@@ -2020,14 +2021,9 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode)
     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
 
     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
-        if (float128_is_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
-            float_invalid_op_vxidi(env, 1, GETPC());
-        } else if (float128_is_zero(xa.f128) && float128_is_zero(xb.f128)) {
-            float_invalid_op_vxzdz(env, 1, GETPC());
-        } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
-                   float128_is_signaling_nan(xb.f128, &tstat)) {
-            float_invalid_op_vxsnan(env, GETPC());
-        }
+        float_invalid_op_div(env, 1, GETPC(),
+                             float128_classify(xa.f128) |
+                             float128_classify(xb.f128));
     }
     if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {
         float_zero_divide_excp(env, GETPC());
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 7/7] target/ppc: Split out float_invalid_cvt
  2018-10-11 23:41 [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions Richard Henderson
                   ` (5 preceding siblings ...)
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 6/7] target/ppc: Split out float_invalid_op_div Richard Henderson
@ 2018-10-11 23:41 ` Richard Henderson
  2018-10-12  1:14 ` [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions David Gibson
  7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2018-10-11 23:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: david, qemu-ppc

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/ppc/fpu_helper.c | 67 +++++++++++++++++------------------------
 1 file changed, 28 insertions(+), 39 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 127c08bcec..2ed4f42275 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -750,30 +750,30 @@ float64 helper_fdiv(CPUPPCState *env, float64 arg1, float64 arg2)
     return ret;
 }
 
+static void float_invalid_cvt(CPUPPCState *env, bool set_fprc,
+                              uintptr_t retaddr, int class1)
+{
+    float_invalid_op_vxcvi(env, set_fprc, retaddr);
+    if (class1 & is_snan) {
+        float_invalid_op_vxsnan(env, retaddr);
+    }
+}
 
 #define FPU_FCTI(op, cvt, nanval)                                      \
-uint64_t helper_##op(CPUPPCState *env, uint64_t arg)                   \
+uint64_t helper_##op(CPUPPCState *env, float64 arg)                    \
 {                                                                      \
-    CPU_DoubleU farg;                                                  \
+    uint64_t ret = float64_to_##cvt(arg, &env->fp_status);             \
+    int status = get_float_exception_flags(&env->fp_status);           \
                                                                        \
-    farg.ll = arg;                                                     \
-    farg.ll = float64_to_##cvt(farg.d, &env->fp_status);               \
-                                                                       \
-    if (unlikely(env->fp_status.float_exception_flags)) {              \
-        if (float64_is_any_nan(arg)) {                                 \
-            float_invalid_op_vxcvi(env, 1, GETPC());                   \
-            if (float64_is_signaling_nan(arg, &env->fp_status)) {      \
-                float_invalid_op_vxsnan(env, GETPC());                 \
-            }                                                          \
-            farg.ll = nanval;                                          \
-        } else if (env->fp_status.float_exception_flags &              \
-                   float_flag_invalid) {                               \
-            float_invalid_op_vxcvi(env, 1, GETPC());                   \
+    if (unlikely(status)) {                                            \
+        if (status & float_flag_invalid) {                             \
+            float_invalid_cvt(env, 1, GETPC(), float64_classify(arg)); \
+            ret = nanval;                                              \
         }                                                              \
         do_float_check_status(env, GETPC());                           \
     }                                                                  \
-    return farg.ll;                                                    \
- }
+    return ret;                                                        \
+}
 
 FPU_FCTI(fctiw, int32, 0x80000000U)
 FPU_FCTI(fctiwz, int32_round_to_zero, 0x80000000U)
@@ -2965,6 +2965,7 @@ uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
 #define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, rnan)              \
 void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
 {                                                                            \
+    int all_flags = env->fp_status.float_exception_flags, flags;             \
     ppc_vsr_t xt, xb;                                                        \
     int i;                                                                   \
                                                                              \
@@ -2972,22 +2973,18 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     getVSR(xT(opcode), &xt, env);                                            \
                                                                              \
     for (i = 0; i < nels; i++) {                                             \
-        if (unlikely(stp##_is_any_nan(xb.sfld))) {                           \
-            if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {          \
-                float_invalid_op_vxsnan(env, GETPC());                       \
-            }                                                                \
-            float_invalid_op_vxcvi(env, 0, GETPC());                         \
+        env->fp_status.float_exception_flags = 0;                            \
+        xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, &env->fp_status);  \
+        flags = env->fp_status.float_exception_flags;                        \
+        if (unlikely(flags & float_flag_invalid)) {                          \
+            float_invalid_cvt(env, 0, GETPC(), stp##_classify(xb.sfld));     \
             xt.tfld = rnan;                                                  \
-        } else {                                                             \
-            xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld,                \
-                          &env->fp_status);                                  \
-            if (env->fp_status.float_exception_flags & float_flag_invalid) { \
-                float_invalid_op_vxcvi(env, 0, GETPC());                     \
-            }                                                                \
         }                                                                    \
+        all_flags |= flags;                                                  \
     }                                                                        \
                                                                              \
     putVSR(xT(opcode), &xt, env);                                            \
+    env->fp_status.float_exception_flags = all_flags;                        \
     do_float_check_status(env, GETPC());                                     \
 }
 
@@ -3025,18 +3022,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
     getVSR(rB(opcode) + 32, &xb, env);                                       \
     memset(&xt, 0, sizeof(xt));                                              \
                                                                              \
-    if (unlikely(stp##_is_any_nan(xb.sfld))) {                               \
-        if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {              \
-            float_invalid_op_vxsnan(env, GETPC());                           \
-        }                                                                    \
-        float_invalid_op_vxcvi(env, 0, GETPC());                             \
+    xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, &env->fp_status);      \
+    if (env->fp_status.float_exception_flags & float_flag_invalid) {         \
+        float_invalid_cvt(env, 0, GETPC(), stp##_classify(xb.sfld));         \
         xt.tfld = rnan;                                                      \
-    } else {                                                                 \
-        xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld,                    \
-                      &env->fp_status);                                      \
-        if (env->fp_status.float_exception_flags & float_flag_invalid) {     \
-            float_invalid_op_vxcvi(env, 0, GETPC());                         \
-        }                                                                    \
     }                                                                        \
                                                                              \
     putVSR(rD(opcode) + 32, &xt, env);                                       \
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions
  2018-10-11 23:41 [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions Richard Henderson
                   ` (6 preceding siblings ...)
  2018-10-11 23:41 ` [Qemu-devel] [PATCH 7/7] target/ppc: Split out float_invalid_cvt Richard Henderson
@ 2018-10-12  1:14 ` David Gibson
  7 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2018-10-12  1:14 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel, qemu-ppc

[-- Attachment #1: Type: text/plain, Size: 1147 bytes --]

On Thu, Oct 11, 2018 at 04:41:52PM -0700, Richard Henderson wrote:
1;5202;0c> There are a few bugs here, primarily wrt usage of GETPC().
> But there is opportunity to share more code between paths
> that operate on different floating point types.
> 
> This is not everything that could be done, but it's a good start.
> Better for this not to hang out on a branch for another release.

Applied to ppc-for-3.1, thanks.

> 
> 
> r~
> 
> 
> Richard Henderson (7):
>   target/ppc: Split up float_invalid_op_excp
>   target/ppc: Remove float_check_status
>   target/ppc: Introduce fp number classification
>   target/ppc: Split out float_invalid_op_addsub
>   target/ppc: Split out float_invalid_op_mul
>   target/ppc: Split out float_invalid_op_div
>   target/ppc: Split out float_invalid_cvt
> 
>  target/ppc/fpu_helper.c | 661 ++++++++++++++++++++--------------------
>  1 file changed, 327 insertions(+), 334 deletions(-)
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-10-12  1:44 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-11 23:41 [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions Richard Henderson
2018-10-11 23:41 ` [Qemu-devel] [PATCH 1/7] target/ppc: Split up float_invalid_op_excp Richard Henderson
2018-10-11 23:41 ` [Qemu-devel] [PATCH 2/7] target/ppc: Remove float_check_status Richard Henderson
2018-10-11 23:41 ` [Qemu-devel] [PATCH 3/7] target/ppc: Introduce fp number classification Richard Henderson
2018-10-11 23:41 ` [Qemu-devel] [PATCH 4/7] target/ppc: Split out float_invalid_op_addsub Richard Henderson
2018-10-11 23:41 ` [Qemu-devel] [PATCH 5/7] target/ppc: Split out float_invalid_op_mul Richard Henderson
2018-10-11 23:41 ` [Qemu-devel] [PATCH 6/7] target/ppc: Split out float_invalid_op_div Richard Henderson
2018-10-11 23:41 ` [Qemu-devel] [PATCH 7/7] target/ppc: Split out float_invalid_cvt Richard Henderson
2018-10-12  1:14 ` [Qemu-devel] [PATCH 0/7] target/ppc: Some cleanups to fp exceptions David Gibson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.