Blame 0004-target-sparc-fix-fcmp-s-d-q-instructions-wrt-excepti.patch

5544c1
From 5e955b895d4a92cdc49c7b4e76284483d49aa4b8 Mon Sep 17 00:00:00 2001
5544c1
From: Aurelien Jarno <aurelien@aurel32.net>
5544c1
Date: Fri, 7 Sep 2012 17:13:28 +0200
5544c1
Subject: [PATCH] target-sparc: fix fcmp{s,d,q} instructions wrt exception
5544c1
5544c1
fcmp{s,d,q} instructions are supposed to ignore quiet NaN (contrary to
5544c1
the fcmpe{s,d,q} instructions), but the current code is wrongly setting
5544c1
the NV exception in that case. Moreover the current code is duplicated:
5544c1
first the arguments are checked for NaN to generate an exception, and
5544c1
later in case the comparison is unordered (which can only happens if one
5544c1
of the argument is a NaN), the same check is done to generate an
5544c1
exception.
5544c1
5544c1
Fix that by calling clear_float_exceptions() followed by
5544c1
check_ieee_exceptions() as for the other floating point instructions.
5544c1
Use the _compare_quiet functions for fcmp{s,d,q} and the _compare ones
5544c1
for fcmpe{s,d,q}. Simplify the flag setting by not clearing a flag that
5544c1
is set the line just below.
5544c1
5544c1
This fix allows the math glibc testsuite to pass.
5544c1
5544c1
Cc: Blue Swirl <blauwirbel@gmail.com>
5544c1
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
5544c1
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
5544c1
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
5544c1
---
5544c1
 target-sparc/fop_helper.c | 67 +++++++++++++++++++----------------------------
5544c1
 1 file changed, 27 insertions(+), 40 deletions(-)
5544c1
5544c1
diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c
5544c1
index 9c64ef8..f4b62a5 100644
5544c1
--- a/target-sparc/fop_helper.c
5544c1
+++ b/target-sparc/fop_helper.c
5544c1
@@ -334,34 +334,28 @@ void helper_fsqrtq(CPUSPARCState *env)
5544c1
 }
5544c1
 
5544c1
 #define GEN_FCMP(name, size, reg1, reg2, FS, E)                         \
5544c1
-    void glue(helper_, name) (CPUSPARCState *env)                            \
5544c1
+    void glue(helper_, name) (CPUSPARCState *env)                       \
5544c1
     {                                                                   \
5544c1
-        env->fsr &= FSR_FTT_NMASK;                                      \
5544c1
-        if (E && (glue(size, _is_any_nan)(reg1) ||                      \
5544c1
-                  glue(size, _is_any_nan)(reg2)) &&                     \
5544c1
-            (env->fsr & FSR_NVM)) {                                     \
5544c1
-            env->fsr |= FSR_NVC;                                        \
5544c1
-            env->fsr |= FSR_FTT_IEEE_EXCP;                              \
5544c1
-            helper_raise_exception(env, TT_FP_EXCP);                    \
5544c1
+        int ret;                                                        \
5544c1
+        clear_float_exceptions(env);                                    \
5544c1
+        if (E) {                                                        \
5544c1
+            ret = glue(size, _compare)(reg1, reg2, &env->fp_status);    \
5544c1
+        } else {                                                        \
5544c1
+            ret = glue(size, _compare_quiet)(reg1, reg2,                \
5544c1
+                                             &env->fp_status);          \
5544c1
         }                                                               \
5544c1
-        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
5544c1
+        check_ieee_exceptions(env);                                     \
5544c1
+        switch (ret) {                                                  \
5544c1
         case float_relation_unordered:                                  \
5544c1
-            if ((env->fsr & FSR_NVM)) {                                 \
5544c1
-                env->fsr |= FSR_NVC;                                    \
5544c1
-                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
5544c1
-                helper_raise_exception(env, TT_FP_EXCP);                \
5544c1
-            } else {                                                    \
5544c1
-                env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
5544c1
-                env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
5544c1
-                env->fsr |= FSR_NVA;                                    \
5544c1
-            }                                                           \
5544c1
+            env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                    \
5544c1
+            env->fsr |= FSR_NVA;                                        \
5544c1
             break;                                                      \
5544c1
         case float_relation_less:                                       \
5544c1
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
5544c1
+            env->fsr &= ~(FSR_FCC1) << FS;                              \
5544c1
             env->fsr |= FSR_FCC0 << FS;                                 \
5544c1
             break;                                                      \
5544c1
         case float_relation_greater:                                    \
5544c1
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
5544c1
+            env->fsr &= ~(FSR_FCC0) << FS;                              \
5544c1
             env->fsr |= FSR_FCC1 << FS;                                 \
5544c1
             break;                                                      \
5544c1
         default:                                                        \
5544c1
@@ -370,34 +364,27 @@ void helper_fsqrtq(CPUSPARCState *env)
5544c1
         }                                                               \
5544c1
     }
5544c1
 #define GEN_FCMP_T(name, size, FS, E)                                   \
5544c1
-    void glue(helper_, name)(CPUSPARCState *env, size src1, size src2)       \
5544c1
+    void glue(helper_, name)(CPUSPARCState *env, size src1, size src2)  \
5544c1
     {                                                                   \
5544c1
-        env->fsr &= FSR_FTT_NMASK;                                      \
5544c1
-        if (E && (glue(size, _is_any_nan)(src1) ||                      \
5544c1
-                  glue(size, _is_any_nan)(src2)) &&                     \
5544c1
-            (env->fsr & FSR_NVM)) {                                     \
5544c1
-            env->fsr |= FSR_NVC;                                        \
5544c1
-            env->fsr |= FSR_FTT_IEEE_EXCP;                              \
5544c1
-            helper_raise_exception(env, TT_FP_EXCP);                    \
5544c1
+        int ret;                                                        \
5544c1
+        clear_float_exceptions(env);                                    \
5544c1
+        if (E) {                                                        \
5544c1
+            ret = glue(size, _compare)(src1, src2, &env->fp_status);    \
5544c1
+        } else {                                                        \
5544c1
+            ret = glue(size, _compare_quiet)(src1, src2,                \
5544c1
+                                             &env->fp_status);          \
5544c1
         }                                                               \
5544c1
-        switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
5544c1
+        check_ieee_exceptions(env);                                     \
5544c1
+        switch (ret) {                                                  \
5544c1
         case float_relation_unordered:                                  \
5544c1
-            if ((env->fsr & FSR_NVM)) {                                 \
5544c1
-                env->fsr |= FSR_NVC;                                    \
5544c1
-                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
5544c1
-                helper_raise_exception(env, TT_FP_EXCP);                \
5544c1
-            } else {                                                    \
5544c1
-                env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
5544c1
-                env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
5544c1
-                env->fsr |= FSR_NVA;                                    \
5544c1
-            }                                                           \
5544c1
+            env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                    \
5544c1
             break;                                                      \
5544c1
         case float_relation_less:                                       \
5544c1
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
5544c1
+            env->fsr &= ~(FSR_FCC1 << FS);                              \
5544c1
             env->fsr |= FSR_FCC0 << FS;                                 \
5544c1
             break;                                                      \
5544c1
         case float_relation_greater:                                    \
5544c1
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
5544c1
+            env->fsr &= ~(FSR_FCC0 << FS);                              \
5544c1
             env->fsr |= FSR_FCC1 << FS;                                 \
5544c1
             break;                                                      \
5544c1
         default:                                                        \
5544c1
-- 
5544c1
1.7.12.1
5544c1