This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Fix underflow reporting and tie up loose ends in sparcsoft-fp.
- From: David Miller <davem at davemloft dot net>
- To: libc-alpha at sourceware dot org
- Date: Mon, 28 May 2012 00:16:35 -0400 (EDT)
- Subject: [PATCH] Fix underflow reporting and tie up loose ends in sparcsoft-fp.
The routines sparc uses to generate exceptions would not generate
underflow without inexact properly. The dummy float operation it uses
in this situation doesn't generate any exceptions at all.
Forget all of this and directly write the exception bits into the
%fsr.
For the most part, on the 64-bit side, this is what the code was
doing. This is why the math test failures I've been working on only
failed on 64-bit, because only 64-bit could generate underflow without
inexact properly.
Also:
1) The 64-bit helper, __Qp_handle_exceptions, was erroneously given
a symbol version. This never should have happened. This is purely
an internaly helper routine, there is no declaration visible to
userspace, and nothing should refer to this.
I've thus removed the Versions entry and the abilist reference.
I double checked that there are no references to this symbol
anywhere outside of soft-fp, and that this isn't some special
symbol that either Solaris or the Sparc ELF 64-bit ABI specifies.
2) 64-bit set FP_INHIBIT_RESULTS, but 32-bit did not. There is
abolutely no reason for 32-bit and 64-bit to be different in
this regard. So I've made 32-bit define it too.
There are more sparc problems I'd like to address (on 32-bit even for
sparcv9 builds it uses SW multiplication because of the umul_ppmm
provided in longlong.h, as just one example). But I stopped here so I
can get back to fixing the underflow reporting problem in the core
soft-fp code first.
Committed to master.
* sysdeps/sparc/sparc32/soft-fp/q_util.c (___Q_numbers): Delete.
(___Q_zero): New.
(__Q_simulate_exceptions): Return void. Change to simulate
exceptions by writing into the %fsr.
* sysdeps/sparc/sparc64/soft-fp/qp_util.c
(__Qp_handle_exceptions): Likewise.
(numbers): Delete.
* sysdeps/sparc/sparc64/soft-fp/Versions: Remove entry for
__Qp_handle_exceptions.
* sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist: Remove
__Qp_handle_exceptions.
* sysdeps/sparc/sparc32/soft-fp/sfp-machine.h (_FP_DECL_EX): Mark
as unused and give dummy FP_RND_NEAREST initializer.
(FP_INHIBIT_RESULTS): Define.
(___Q_simulate_exceptions): Update declaration.
(FP_HANDLE_EXCEPTIONS): Use ___Q_zero and tidy inline asm
formatting.
* sysdeps/sparc/sparc64/soft-fp/sfp-machine.h (_FP_DECL_EX): Mark
as unused and give dummy FP_RND_NEAREST initializer.
(__Qp_handle_exceptions): Update declaration.
(FP_HANDLE_EXCEPTIONS, QP_NO_EXCEPTIONS): Tidy inline asm
formatting.
---
sysdeps/sparc/sparc32/soft-fp/q_util.c | 49 +++++++-------------
sysdeps/sparc/sparc32/soft-fp/sfp-machine.h | 16 ++++---
sysdeps/sparc/sparc64/soft-fp/Versions | 2 +-
sysdeps/sparc/sparc64/soft-fp/qp_util.c | 49 +++++++-------------
sysdeps/sparc/sparc64/soft-fp/sfp-machine.h | 16 +++----
.../sysv/linux/sparc/sparc64/nptl/libc.abilist | 1 -
6 files changed, 53 insertions(+), 80 deletions(-)
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_util.c b/sysdeps/sparc/sparc32/soft-fp/q_util.c
index 22f70ba..c4efc10 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_util.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_util.c
@@ -1,7 +1,7 @@
/* Software floating-point emulation.
Helper routine for _Q_* routines.
Simulate exceptions using double arithmetics.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek (jj@ultra.linux.cz).
@@ -21,36 +21,23 @@
#include "soft-fp.h"
-unsigned long long ___Q_numbers [] = {
-0x0000000000000000ULL, /* Zero */
-0x0010100000000000ULL, /* Very tiny number */
-0x0010000000000000ULL, /* Minimum normalized number */
-0x7fef000000000000ULL, /* A huge double number */
-};
+unsigned long long ___Q_zero = 0x0000000000000000ULL;
-double ___Q_simulate_exceptions(int exceptions)
+void ___Q_simulate_exceptions(int exceptions)
{
- double d, *p = (double *)___Q_numbers;
- if (exceptions & FP_EX_INVALID)
- d = p[0]/p[0];
- if (exceptions & FP_EX_OVERFLOW)
- {
- d = p[3] + p[3];
- exceptions &= ~FP_EX_INEXACT;
- }
- if (exceptions & FP_EX_UNDERFLOW)
- {
- if (exceptions & FP_EX_INEXACT)
- {
- d = p[2] * p[2];
- exceptions &= ~FP_EX_INEXACT;
- }
- else
- d = p[1] - p[2];
- }
- if (exceptions & FP_EX_DIVZERO)
- d = 1.0/p[0];
- if (exceptions & FP_EX_INEXACT)
- d = p[3] - p[2];
- return d;
+ fpu_control_t fcw;
+ int tem, ou;
+
+ _FPU_GETCW(fcw);
+
+ tem = (fcw >> 23) & 0x1f;
+
+ ou = exceptions & (FP_EX_OVERFLOW | FP_EX_UNDERFLOW);
+ if (ou & tem)
+ exceptions &= ~FP_EX_INVALID;
+
+ fcw &= ~0x1f;
+ fcw |= (exceptions | (exceptions << 5));
+
+ _FPU_SETCW(fcw);
}
diff --git a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
index 8cdc7c2..9037722 100644
--- a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
@@ -184,15 +184,18 @@
#define FP_EX_DIVZERO (1 << 1)
#define FP_EX_INEXACT (1 << 0)
-#define _FP_DECL_EX fpu_control_t _fcw
+#define _FP_DECL_EX \
+ fpu_control_t _fcw __attribute__ ((unused)) = (FP_RND_NEAREST << 30)
#define FP_INIT_ROUNDMODE \
do { \
_FPU_GETCW(_fcw); \
} while (0)
+#define FP_INHIBIT_RESULTS ((_fcw >> 23) & _fex)
+
/* Simulate exceptions using double arithmetics. */
-extern double ___Q_simulate_exceptions(int exc);
+extern void ___Q_simulate_exceptions(int exc);
#define FP_HANDLE_EXCEPTIONS \
do { \
@@ -201,11 +204,10 @@ do { \
/* This is the common case, so we do it inline. \
* We need to clear cexc bits if any. \
*/ \
- extern unsigned long long ___Q_numbers[]; \
- __asm__ __volatile__("\
- ldd [%0], %%f30\n\
- faddd %%f30, %%f30, %%f30\
- " : : "r" (___Q_numbers) : "f30"); \
+ extern unsigned long long ___Q_zero; \
+ __asm__ __volatile__("ldd [%0], %%f30\n\t" \
+ "faddd %%f30, %%f30, %%f30" \
+ : : "r" (&___Q_zero) : "f30"); \
} \
else \
___Q_simulate_exceptions (_fex); \
diff --git a/sysdeps/sparc/sparc64/soft-fp/Versions b/sysdeps/sparc/sparc64/soft-fp/Versions
index 4404827..9e89c3c 100644
--- a/sysdeps/sparc/sparc64/soft-fp/Versions
+++ b/sysdeps/sparc/sparc64/soft-fp/Versions
@@ -3,6 +3,6 @@ libc {
_Qp_add; _Qp_cmp; _Qp_cmpe; _Qp_div; _Qp_dtoq; _Qp_feq; _Qp_fge; _Qp_fgt;
_Qp_fle; _Qp_flt; _Qp_fne; _Qp_itoq; _Qp_mul; _Qp_neg; _Qp_qtod; _Qp_qtoi;
_Qp_qtos; _Qp_qtoui; _Qp_qtoux; _Qp_qtox; _Qp_sqrt; _Qp_stoq; _Qp_sub;
- _Qp_uitoq; _Qp_uxtoq; _Qp_xtoq; __Qp_handle_exceptions;
+ _Qp_uitoq; _Qp_uxtoq; _Qp_xtoq;
}
}
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_util.c b/sysdeps/sparc/sparc64/soft-fp/qp_util.c
index fd3043b..358d0e4 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_util.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_util.c
@@ -1,7 +1,7 @@
/* Software floating-point emulation.
Helper routine for _Qp_* routines.
Simulate exceptions using double arithmetics.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek (jj@ultra.linux.cz).
@@ -21,36 +21,21 @@
#include "soft-fp.h"
-static unsigned long numbers [] = {
-0x7fef000000000000UL, /* A huge double number */
-0x0010100000000000UL, /* Very tiny number */
-0x0010000000000000UL, /* Minimum normalized number */
-0x0000000000000000UL, /* Zero */
-};
-
-double __Qp_handle_exceptions(int exceptions)
+void __Qp_handle_exceptions(int exceptions)
{
- double d, *p = (double *)numbers;
- if (exceptions & FP_EX_INVALID)
- d = p[3]/p[3];
- if (exceptions & FP_EX_OVERFLOW)
- {
- d = p[0] + p[0];
- exceptions &= ~FP_EX_INEXACT;
- }
- if (exceptions & FP_EX_UNDERFLOW)
- {
- if (exceptions & FP_EX_INEXACT)
- {
- d = p[2] * p[2];
- exceptions &= ~FP_EX_INEXACT;
- }
- else
- d = p[1] - p[2];
- }
- if (exceptions & FP_EX_DIVZERO)
- d = 1.0/p[3];
- if (exceptions & FP_EX_INEXACT)
- d = p[0] - p[2];
- return d;
+ fpu_control_t fcw;
+ int tem, ou;
+
+ _FPU_GETCW(fcw);
+
+ tem = (fcw >> 23) & 0x1f;
+
+ ou = exceptions & (FP_EX_OVERFLOW | FP_EX_UNDERFLOW);
+ if (ou & tem)
+ exceptions &= ~FP_EX_INVALID;
+
+ fcw &= ~0x1f;
+ fcw |= (exceptions | (exceptions << 5));
+
+ _FPU_SETCW(fcw);
}
diff --git a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
index 7ec804d..36f92d6 100644
--- a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
@@ -92,7 +92,8 @@ do { \
#define FP_EX_DIVZERO (1 << 1)
#define FP_EX_INEXACT (1 << 0)
-#define _FP_DECL_EX fpu_control_t _fcw
+#define _FP_DECL_EX \
+ fpu_control_t _fcw __attribute__ ((unused)) = (FP_RND_NEAREST << 30)
#define FP_INIT_ROUNDMODE \
do { \
@@ -102,7 +103,7 @@ do { \
#define FP_INHIBIT_RESULTS ((_fcw >> 23) & _fex)
/* Simulate exceptions using double arithmetics. */
-extern double __Qp_handle_exceptions(int exc);
+extern void __Qp_handle_exceptions(int exc);
#define FP_HANDLE_EXCEPTIONS \
do { \
@@ -111,10 +112,9 @@ do { \
/* This is the common case, so we do it inline. \
* We need to clear cexc bits if any. \
*/ \
- __asm__ __volatile__("\n" \
-" fzero %%f62\n" \
-" faddd %%f62, %%f62, %%f62\n" \
-" " : : : "f62"); \
+ __asm__ __volatile__("fzero %%f62\n\t" \
+ "faddd %%f62, %%f62, %%f62" \
+ : : : "f62"); \
} \
else \
{ \
@@ -136,8 +136,8 @@ do { \
} while (0)
#define QP_NO_EXCEPTIONS \
- __asm ("fzero %%f62\n" \
-" faddd %%f62, %%f62, %%f62" : : : "f62")
+ __asm ("fzero %%f62\n\t" \
+ "faddd %%f62, %%f62, %%f62" : : : "f62")
#define QP_CLOBBER "memory", "f52", "f54", "f56", "f58", "f60", "f62"
#define QP_CLOBBER_CC QP_CLOBBER , "cc"
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist
index 2914d1c..8571fa8 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/nptl/libc.abilist
@@ -248,7 +248,6 @@ GLIBC_2.2
_Qp_uitoq F
_Qp_uxtoq F
_Qp_xtoq F
- __Qp_handle_exceptions F
__adjtimex F
__after_morecore_hook D 0x8
__align_cpy_1 F
--
1.7.10