MIPS: math-emu: Reinstate sNaN quieting handlers
authorMaciej W. Rozycki <macro@linux-mips.org>
Fri, 3 Apr 2015 22:25:34 +0000 (23:25 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Tue, 7 Apr 2015 23:09:31 +0000 (01:09 +0200)
Revert the changes made by commit fdffbafb [Lots of FPU bug fixes from
Kjeld Borch Egevang.] to `ieee754sp_nanxcpt' and `ieee754dp_nanxcpt'
sNaN quieting handlers and their callers so that sNaN processing is done
within the handlers againg.  Pass the sNaN causing an IEEE 754 invalid
operation exception down to the relevant handler.  Pass the sNaN in `fs'
where two sNaNs are supplied to a binary operation.

Set the Invalid Operation FCSR exception bits in the quieting handlers
rather than at their call sites throughout.  Make the handlers exclusive
for sNaN processing.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9688/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
14 files changed:
arch/mips/math-emu/dp_add.c
arch/mips/math-emu/dp_div.c
arch/mips/math-emu/dp_fsp.c
arch/mips/math-emu/dp_mul.c
arch/mips/math-emu/dp_sqrt.c
arch/mips/math-emu/dp_sub.c
arch/mips/math-emu/ieee754dp.c
arch/mips/math-emu/ieee754sp.c
arch/mips/math-emu/sp_add.c
arch/mips/math-emu/sp_div.c
arch/mips/math-emu/sp_fdp.c
arch/mips/math-emu/sp_mul.c
arch/mips/math-emu/sp_sqrt.c
arch/mips/math-emu/sp_sub.c

index 58b27959a6c460e03d7e4acdec4f1e7df56e6b31..8954ef031f843fe41b3feca15852985c2b1251d9 100644 (file)
@@ -37,19 +37,20 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y)
        FLUSHYDP;
 
        switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754dp_nanxcpt(ieee754dp_indef());
+               return ieee754dp_nanxcpt(x);
 
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
index bef0e55e59381e2b5c5d03b4970a0f8132a3b6b1..f4746f7c5f63b1f686d51b5a59fd6d5dcd85d0be 100644 (file)
@@ -39,19 +39,20 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y)
        FLUSHYDP;
 
        switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754dp_nanxcpt(ieee754dp_indef());
+               return ieee754dp_nanxcpt(x);
 
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
index af48d2a277a4d402e55cfab3011c1a8466d11678..57d09ca5403a4824333861f64472b342098abfd6 100644 (file)
@@ -40,8 +40,7 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x)
 
        switch (xc) {
        case IEEE754_CLASS_SNAN:
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754dp_nanxcpt(ieee754dp_indef());
+               return ieee754dp_nanxcpt(ieee754dp_nan_fsp(xs, xm));
 
        case IEEE754_CLASS_QNAN:
                return ieee754dp_nan_fsp(xs, xm);
index d3acdedb5b9dd33053d7688af197a4d0e1f2d5de..d0901f03fa197c30a979ec3b560ba5bfa0244902 100644 (file)
@@ -47,19 +47,20 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y)
        FLUSHYDP;
 
        switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754dp_nanxcpt(ieee754dp_indef());
+               return ieee754dp_nanxcpt(x);
 
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
index 0d8e7ffdba5ee6762ec7948c1b0671c730c63a0c..cd5bc083001e81e697717b0bb0ba8ebf80bef4d7 100644 (file)
@@ -42,14 +42,13 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x)
 
        /* x == INF or NAN? */
        switch (xc) {
+       case IEEE754_CLASS_SNAN:
+               return ieee754dp_nanxcpt(x);
+
        case IEEE754_CLASS_QNAN:
                /* sqrt(Nan) = Nan */
                return x;
 
-       case IEEE754_CLASS_SNAN:
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754dp_nanxcpt(ieee754dp_indef());
-
        case IEEE754_CLASS_ZERO:
                /* sqrt(0) = 0 */
                return x;
index 2eb87cd23ba800902cc723d0b5dc239acdf94fc6..fc17a781b9ae868890303f57b08eb6f7b7d72cd3 100644 (file)
@@ -37,19 +37,20 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y)
        FLUSHYDP;
 
        switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754dp_nanxcpt(ieee754dp_indef());
+               return ieee754dp_nanxcpt(x);
 
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
index 9723a518e5ade80ccf6e61bf3194d67321d34815..49c811a920b532d82910ac9732e0643fa25eb4e7 100644 (file)
@@ -42,18 +42,16 @@ static inline int ieee754dp_issnan(union ieee754dp x)
 }
 
 
+/*
+ * Raise the Invalid Operation IEEE 754 exception
+ * and convert the signaling NaN supplied to a quiet NaN.
+ */
 union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r)
 {
-       assert(ieee754dp_isnan(r));
-
-       if (!ieee754dp_issnan(r))       /* QNAN does not cause invalid op !! */
-               return r;
-
-       /* If not enabled convert to a quiet NaN.  */
-       if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
-               return ieee754dp_indef();
+       assert(ieee754dp_issnan(r));
 
-       return r;
+       ieee754_setcx(IEEE754_INVALID_OPERATION);
+       return ieee754dp_indef();
 }
 
 static u64 ieee754dp_get_rounding(int sn, u64 xm)
index 7bde3c204d02d30a8886f334c1d9a03629245ce0..21899ce05171e2bf291a2ff89320556eb8e1673f 100644 (file)
@@ -42,18 +42,16 @@ static inline int ieee754sp_issnan(union ieee754sp x)
 }
 
 
+/*
+ * Raise the Invalid Operation IEEE 754 exception
+ * and convert the signaling NaN supplied to a quiet NaN.
+ */
 union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)
 {
-       assert(ieee754sp_isnan(r));
-
-       if (!ieee754sp_issnan(r))       /* QNAN does not cause invalid op !! */
-               return r;
-
-       /* If not enabled convert to a quiet NaN.  */
-       if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
-               return ieee754sp_indef();
+       assert(ieee754sp_issnan(r));
 
-       return r;
+       ieee754_setcx(IEEE754_INVALID_OPERATION);
+       return ieee754sp_indef();
 }
 
 static unsigned ieee754sp_get_rounding(int sn, unsigned xm)
index 7a33af4b4b59cbb45675fbdf1e6939ec66c507f1..f1c87b07d3b4758167628bb087fc21124c8c5f51 100644 (file)
@@ -37,19 +37,20 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y)
        FLUSHYSP;
 
        switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754sp_nanxcpt(ieee754sp_indef());
+               return ieee754sp_nanxcpt(x);
 
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
index 721f317aa8778bc8a0a71c6c76252ebe269a72b4..27f6db3a0a4c5b1a16c9767b16fb2aa5faf8a84c 100644 (file)
@@ -39,19 +39,20 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y)
        FLUSHYSP;
 
        switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754sp_nanxcpt(ieee754sp_indef());
+               return ieee754sp_nanxcpt(x);
 
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
index 18a3f8c37136947d4a1ec39b1607f1c57e00e9b3..152637093854fd645d72db786ef6ea3c6c259a15 100644 (file)
@@ -43,8 +43,7 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x)
 
        switch (xc) {
        case IEEE754_CLASS_SNAN:
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754sp_nanxcpt(ieee754sp_indef());
+               return ieee754sp_nanxcpt(ieee754sp_nan_fdp(xs, xm));
 
        case IEEE754_CLASS_QNAN:
                nan = ieee754sp_nan_fdp(xs, xm);
index 890c13a2965e78ffb5aca93eb3105e74b0e8ee58..d910c43a6f309a83cb680b66b19841cb7655e597 100644 (file)
@@ -47,19 +47,20 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y)
        FLUSHYSP;
 
        switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754sp_nanxcpt(ieee754sp_indef());
+               return ieee754sp_nanxcpt(x);
 
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
index 9cc53effee62c7ca702d97bae3943c0a9a30bcf0..67059c33a250a9e45bcdb4c18e84ad295fb9de6a 100644 (file)
@@ -35,14 +35,13 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x)
 
        /* x == INF or NAN? */
        switch (xc) {
+       case IEEE754_CLASS_SNAN:
+               return ieee754sp_nanxcpt(x);
+
        case IEEE754_CLASS_QNAN:
                /* sqrt(Nan) = Nan */
                return x;
 
-       case IEEE754_CLASS_SNAN:
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754sp_nanxcpt(ieee754sp_indef());
-
        case IEEE754_CLASS_ZERO:
                /* sqrt(0) = 0 */
                return x;
index 1189bc5ca1fd24cec588c3bc8799fb984f5e08fd..ec5f937a8b3eeb7ae1e6369bdfdb4c7f42323fd7 100644 (file)
@@ -37,19 +37,20 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y)
        FLUSHYSP;
 
        switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
        case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
        case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754sp_nanxcpt(ieee754sp_indef());
+               return ieee754sp_nanxcpt(x);
 
        case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):