[RFC PATCH] SPU single precision floating point macros and functions

Patrick Mansfield patmans@us.ibm.com
Wed Apr 18 17:11:00 GMT 2007


The SPU/cell single precision floating point does not support NANs or
infinities, and is documented as such. This patch supplies SPU specific
macros and functions for various single precision floating point nan,
isfin, isfinite and fpclassify.

There is a problem with the macros in ieeefp.h, in that we can't define
them in machine ieeefp.h before the prototypes (like isnanf), this also
means those prototypes are hidden behind macros if you include ieeefp.h,
so the prototypes could be removed and the alternate macros put in
machine/ieeefp.h, but that would still leave us with name space issues
(when the machine one is included only via math.h).

Do I need to keep the namespace clean when only ieeefp.h is included (i.e.
don't supply isfinite, isinf, or isnan)? Then I need some __c99_
prefix, something like I did with __ieeefp_ prefix, or ???

Are the __ieeefp_ macro/overrides OK?

Are locations of the default macro values OK? (left in their current
files, math.h or ieeefp.h)?

Thanks ...

ChangeLog:

2007-04-17  Patrick Mansfield <patmans@us.ibm.com>

	* libc/include/ieeefp.h: use prefixed __ieeefp_ macros that can be
	overridden via machine/ieeefp.h.
	* libc/include/machine/ieeefp.h: Add SPU specific C99 and ieeefp
	macros for isnan and related macros.
	* libc/include/math.h: Allow C99 isfinite, isinf, and isnan to be
	overridden via machine/ieeefp.h.
	* libm/machine/spu/Makefile.am: Add new files.
	* libm/machine/spu/Makefile.in: Autogeneraate with new files.
	* libm/machine/spu/s_fpclassify.c: Add SPU specific __fpclassifyf,
	plus the same __fpclassifyd as in the common s_fpclassify.c.
	* libm/machine/spu/sf_finite.c: Add SPU specific finitef.
	* libm/machine/spu/sf_isinf.c: Add SPU specific isinff.
	* libm/machine/spu/sf_isinff.c: Add SPU specific __isinff.
	* libm/machine/spu/sf_isnan.c: Add SPU specific isnanf.
	* libm/machine/spu/sf_isnanf.c: Add SPU specific __isnanf.
	* libm/machine/spu/sf_nan.c: Add SPU specific nanf.

Index: my-base-quilt/newlib/libc/include/machine/ieeefp.h
===================================================================
--- my-base-quilt.orig/newlib/libc/include/machine/ieeefp.h
+++ my-base-quilt/newlib/libc/include/machine/ieeefp.h
@@ -75,8 +75,27 @@
 
 #ifdef __SPU__
 #define __IEEE_BIG_ENDIAN
-#endif
 
+#define isfinite(y) \
+          (__extension__ ({__typeof__(y) __y = (y); \
+                           (sizeof (__y) == sizeof (float))  ? (1) : \
+                           fpclassify(__y) != FP_INFINITE && fpclassify(__y) != FP_NAN;}))
+#define isinf(x) \
+          (__extension__ ({__typeof__(x) __x = (x); \
+                           (sizeof (__x) == sizeof (float))  ? (0) : __isinfd(__x);}))
+#define isnan(x) \
+          (__extension__ ({__typeof__(x) __x = (x); \
+                           (sizeof (__x) == sizeof (float))  ? (0) : __isnand(__x);}))
+
+/*
+ * Macros for use in ieeefp.h. We can't just define the real ones here
+ * (like those above) as we have name space issues when this is *not*
+ * included via generic the ieeefp.h.
+ */
+#define __ieeefp_isnanf(x)	0
+#define __ieeefp_isinff(x)	0
+#define __ieeefp_finitef(x)	1
+#endif
 
 #ifdef __sparc__
 #ifdef __LITTLE_ENDIAN_DATA__
Index: my-base-quilt/newlib/libc/include/math.h
===================================================================
--- my-base-quilt.orig/newlib/libc/include/math.h
+++ my-base-quilt/newlib/libc/include/math.h
@@ -131,21 +131,29 @@ extern int __signbitd (double x);
           (__extension__ ({__typeof__(x) __x = (x); \
                            (sizeof (__x) == sizeof (float))  ? __fpclassifyf(__x) : __fpclassifyd(__x);}))
 
+#ifndef isfinite
 #define isfinite(y) \
           (__extension__ ({__typeof__(y) __y = (y); \
                            fpclassify(__y) != FP_INFINITE && fpclassify(__y) != FP_NAN;}))
+#endif
 
 /* Note: isinf and isnan were once functions in newlib that took double
  *       arguments.  C99 specifies that these names are reserved for macros
  *       supporting multiple floating point types.  Thus, they are
  *       now defined as macros.  Implementations of the old functions
  *       taking double arguments still exist for compatibility purposes.  */
+#ifndef isinf
 #define isinf(x) \
           (__extension__ ({__typeof__(x) __x = (x); \
                            (sizeof (__x) == sizeof (float))  ? __isinff(__x) : __isinfd(__x);}))
+#endif
+
+#ifndef isnan
 #define isnan(x) \
           (__extension__ ({__typeof__(x) __x = (x); \
                            (sizeof (__x) == sizeof (float))  ? __isnanf(__x) : __isnand(__x);}))
+#endif
+
 #define isnormal(y) (fpclassify(y) == FP_NORMAL)
 #define signbit(x) \
           (__extension__ ({__typeof__(x) __x = (x); \
Index: my-base-quilt/newlib/libm/machine/spu/Makefile.am
===================================================================
--- my-base-quilt.orig/newlib/libm/machine/spu/Makefile.am
+++ my-base-quilt/newlib/libm/machine/spu/Makefile.am
@@ -8,7 +8,9 @@ INCLUDES = -I $(newlib_basedir)/../newli
 LIB_SOURCES = \
 	feclearexcept.c fe_dfl_env.c fegetenv.c fegetexceptflag.c \
 	fegetround.c feholdexcept.c feraiseexcept.c fesetenv.c \
-	fesetexceptflag.c fesetround.c fetestexcept.c feupdateenv.c
+	fesetexceptflag.c fesetround.c fetestexcept.c feupdateenv.c \
+	sf_finite.c sf_isinf.c sf_isinff.c sf_isnanf.c sf_isnan.c sf_nan.c \
+	s_fpclassify.c
 
 noinst_LIBRARIES = lib.a
 lib_a_SOURCES = $(LIB_SOURCES)
Index: my-base-quilt/newlib/libm/machine/spu/Makefile.in
===================================================================
--- my-base-quilt.orig/newlib/libm/machine/spu/Makefile.in
+++ my-base-quilt/newlib/libm/machine/spu/Makefile.in
@@ -47,7 +47,11 @@ DIST_COMMON = $(srcdir)/../../../Makefil
 	$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
 	$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
 	$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
-	$(srcdir)/../../../../compile $(srcdir)/../../../../compile
+	$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
+	$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
+	$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
+	$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
+	$(srcdir)/../../../../compile
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../../../acinclude.m4 \
@@ -68,7 +72,10 @@ am__objects_1 = lib_a-feclearexcept.$(OB
 	lib_a-feholdexcept.$(OBJEXT) lib_a-feraiseexcept.$(OBJEXT) \
 	lib_a-fesetenv.$(OBJEXT) lib_a-fesetexceptflag.$(OBJEXT) \
 	lib_a-fesetround.$(OBJEXT) lib_a-fetestexcept.$(OBJEXT) \
-	lib_a-feupdateenv.$(OBJEXT)
+	lib_a-feupdateenv.$(OBJEXT) lib_a-sf_finite.$(OBJEXT) \
+	lib_a-sf_isinf.$(OBJEXT) lib_a-sf_isinff.$(OBJEXT) \
+	lib_a-sf_isnanf.$(OBJEXT) lib_a-sf_isnan.$(OBJEXT) \
+	lib_a-sf_nan.$(OBJEXT) lib_a-s_fpclassify.$(OBJEXT)
 am_lib_a_OBJECTS = $(am__objects_1)
 lib_a_OBJECTS = $(am_lib_a_OBJECTS)
 DEFAULT_INCLUDES = -I. -I$(srcdir)
@@ -143,11 +150,6 @@ STRIP = @STRIP@
 USE_LIBTOOL_FALSE = @USE_LIBTOOL_FALSE@
 USE_LIBTOOL_TRUE = @USE_LIBTOOL_TRUE@
 VERSION = @VERSION@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_AS = @ac_ct_AS@
-ac_ct_RANLIB = @ac_ct_RANLIB@
-ac_ct_READELF = @ac_ct_READELF@
-ac_ct_STRIP = @ac_ct_STRIP@
 aext = @aext@
 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
@@ -163,18 +165,23 @@ build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@
 datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
 exec_prefix = @exec_prefix@
 host = @host@
 host_alias = @host_alias@
 host_cpu = @host_cpu@
 host_os = @host_os@
 host_vendor = @host_vendor@
+htmldir = @htmldir@
 includedir = @includedir@
 infodir = @infodir@
 install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 libm_machine_dir = @libm_machine_dir@
+localedir = @localedir@
 localstatedir = @localstatedir@
 lpfx = @lpfx@
 machine_dir = @machine_dir@
@@ -183,8 +190,10 @@ mkdir_p = @mkdir_p@
 newlib_basedir = @newlib_basedir@
 oext = @oext@
 oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
+psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 sys_dir = @sys_dir@
@@ -197,7 +206,9 @@ INCLUDES = -I $(newlib_basedir)/../newli
 LIB_SOURCES = \
 	feclearexcept.c fe_dfl_env.c fegetenv.c fegetexceptflag.c \
 	fegetround.c feholdexcept.c feraiseexcept.c fesetenv.c \
-	fesetexceptflag.c fesetround.c fetestexcept.c feupdateenv.c
+	fesetexceptflag.c fesetround.c fetestexcept.c feupdateenv.c \
+	sf_finite.c sf_isinf.c sf_isinff.c sf_isnanf.c sf_isnan.c sf_nan.c \
+	s_fpclassify.c
 
 noinst_LIBRARIES = lib.a
 lib_a_SOURCES = $(LIB_SOURCES)
@@ -334,6 +345,48 @@ lib_a-feupdateenv.o: feupdateenv.c
 
 lib_a-feupdateenv.obj: feupdateenv.c
 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-feupdateenv.obj `if test -f 'feupdateenv.c'; then $(CYGPATH_W) 'feupdateenv.c'; else $(CYGPATH_W) '$(srcdir)/feupdateenv.c'; fi`
+
+lib_a-sf_finite.o: sf_finite.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_finite.o `test -f 'sf_finite.c' || echo '$(srcdir)/'`sf_finite.c
+
+lib_a-sf_finite.obj: sf_finite.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_finite.obj `if test -f 'sf_finite.c'; then $(CYGPATH_W) 'sf_finite.c'; else $(CYGPATH_W) '$(srcdir)/sf_finite.c'; fi`
+
+lib_a-sf_isinf.o: sf_isinf.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_isinf.o `test -f 'sf_isinf.c' || echo '$(srcdir)/'`sf_isinf.c
+
+lib_a-sf_isinf.obj: sf_isinf.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_isinf.obj `if test -f 'sf_isinf.c'; then $(CYGPATH_W) 'sf_isinf.c'; else $(CYGPATH_W) '$(srcdir)/sf_isinf.c'; fi`
+
+lib_a-sf_isinff.o: sf_isinff.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_isinff.o `test -f 'sf_isinff.c' || echo '$(srcdir)/'`sf_isinff.c
+
+lib_a-sf_isinff.obj: sf_isinff.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_isinff.obj `if test -f 'sf_isinff.c'; then $(CYGPATH_W) 'sf_isinff.c'; else $(CYGPATH_W) '$(srcdir)/sf_isinff.c'; fi`
+
+lib_a-sf_isnanf.o: sf_isnanf.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_isnanf.o `test -f 'sf_isnanf.c' || echo '$(srcdir)/'`sf_isnanf.c
+
+lib_a-sf_isnanf.obj: sf_isnanf.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_isnanf.obj `if test -f 'sf_isnanf.c'; then $(CYGPATH_W) 'sf_isnanf.c'; else $(CYGPATH_W) '$(srcdir)/sf_isnanf.c'; fi`
+
+lib_a-sf_isnan.o: sf_isnan.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_isnan.o `test -f 'sf_isnan.c' || echo '$(srcdir)/'`sf_isnan.c
+
+lib_a-sf_isnan.obj: sf_isnan.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_isnan.obj `if test -f 'sf_isnan.c'; then $(CYGPATH_W) 'sf_isnan.c'; else $(CYGPATH_W) '$(srcdir)/sf_isnan.c'; fi`
+
+lib_a-sf_nan.o: sf_nan.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_nan.o `test -f 'sf_nan.c' || echo '$(srcdir)/'`sf_nan.c
+
+lib_a-sf_nan.obj: sf_nan.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_nan.obj `if test -f 'sf_nan.c'; then $(CYGPATH_W) 'sf_nan.c'; else $(CYGPATH_W) '$(srcdir)/sf_nan.c'; fi`
+
+lib_a-s_fpclassify.o: s_fpclassify.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-s_fpclassify.o `test -f 's_fpclassify.c' || echo '$(srcdir)/'`s_fpclassify.c
+
+lib_a-s_fpclassify.obj: s_fpclassify.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-s_fpclassify.obj `if test -f 's_fpclassify.c'; then $(CYGPATH_W) 's_fpclassify.c'; else $(CYGPATH_W) '$(srcdir)/s_fpclassify.c'; fi`
 uninstall-info-am:
 
 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
Index: my-base-quilt/newlib/libm/machine/spu/sf_isnan.c
===================================================================
--- /dev/null
+++ my-base-quilt/newlib/libm/machine/spu/sf_isnan.c
@@ -0,0 +1,8 @@
+/*
+ * On the SPU single precision floating does not support NAN's.
+ */
+int
+isnanf(float x)
+{
+	return 0;
+}
Index: my-base-quilt/newlib/libm/machine/spu/sf_isnanf.c
===================================================================
--- /dev/null
+++ my-base-quilt/newlib/libm/machine/spu/sf_isnanf.c
@@ -0,0 +1,8 @@
+/*
+ * On the SPU single precision floating does not support NAN's.
+ */
+int
+__isnanf(float x)
+{
+	return 0;
+}
Index: my-base-quilt/newlib/libm/machine/spu/sf_nan.c
===================================================================
--- /dev/null
+++ my-base-quilt/newlib/libm/machine/spu/sf_nan.c
@@ -0,0 +1,9 @@
+/*
+ * On the SPU single precision floating does not support NAN's, and nanf
+ * is documented as returning zero.
+ */
+float
+nanf(const char *unused)
+{
+	return 0;
+}
Index: my-base-quilt/newlib/libm/machine/spu/s_fpclassify.c
===================================================================
--- /dev/null
+++ my-base-quilt/newlib/libm/machine/spu/s_fpclassify.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 2002 by  Red Hat, Incorporated. All rights reserved.
+ * Copyright (C) 2007 IBM
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+
+#include "fdlibm.h"
+
+/*
+ * On the SPU, single precision floating point returns only FP_NORMAL and
+ * FP_ZERO, since FP_NAN, FP_INFINITE, and FP_SUBNORMAL are not
+ * supported.
+ */
+int
+__fpclassifyf (float x)
+{
+  __uint32_t w;
+
+  GET_FLOAT_WORD(w,x);
+
+  if (w == 0x00000000 || w == 0x80000000)
+    return FP_ZERO;
+  return FP_NORMAL;
+}
+
+int
+__fpclassifyd (double x)
+{
+  __uint32_t msw, lsw;
+
+  EXTRACT_WORDS(msw,lsw,x);
+
+  if ((msw == 0x00000000 && lsw == 0x00000000) ||
+      (msw == 0x80000000 && lsw == 0x00000000))
+    return FP_ZERO;
+  else if ((msw >= 0x00100000 && msw <= 0x7fefffff) ||
+           (msw >= 0x80100000 && msw <= 0xffefffff))
+    return FP_NORMAL;
+  else if ((msw >= 0x00000000 && msw <= 0x000fffff) ||
+           (msw >= 0x80000000 && msw <= 0x800fffff))
+    /* zero is already handled above */
+    return FP_SUBNORMAL;
+  else if ((msw == 0x7ff00000 && lsw == 0x00000000) ||
+           (msw == 0xfff00000 && lsw == 0x00000000))
+    return FP_INFINITE;
+  else
+    return FP_NAN;
+}
Index: my-base-quilt/newlib/libc/include/ieeefp.h
===================================================================
--- my-base-quilt.orig/newlib/libc/include/ieeefp.h
+++ my-base-quilt/newlib/libc/include/ieeefp.h
@@ -213,14 +213,22 @@ int _EXFUN(finitef, (float));
 #define __IEEE_DBL_NAN_EXP 0x7ff
 #define __IEEE_FLT_NAN_EXP 0xff
 
-
-#define isnanf(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \
-		   ((*(long *)&(x) & 0x007fffffL)!=0000000000L))
-
-#define isinff(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \
-		   ((*(long *)&(x) & 0x007fffffL)==0000000000L))
-
-#define finitef(x) (((*(long *)&(x) & 0x7f800000L)!=0x7f800000L))
+#ifndef __ieeefp_isnanf
+#define __ieeefp_isnanf(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \
+			    ((*(long *)&(x) & 0x007fffffL)!=0000000000L))
+#endif
+#define isnanf(x)	__ieeefp_isnanf(x)
+
+#ifndef __ieeefp_isinff
+#define __ieeefp_isinff(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \
+			    ((*(long *)&(x) & 0x007fffffL)==0000000000L))
+#endif
+#define isinff(x)	__ieeefp_isinff(x)
+
+#ifndef __ieeefp_finitef
+#define __ieeefp_finitef(x) (((*(long *)&(x) & 0x7f800000L)!=0x7f800000L))
+#endif
+#define finitef(x)	__ieeefp_finitef(x)
 
 #ifdef _DOUBLE_IS_32BITS
 #undef __IEEE_DBL_EXPBIAS
Index: my-base-quilt/newlib/libm/machine/spu/sf_isinf.c
===================================================================
--- /dev/null
+++ my-base-quilt/newlib/libm/machine/spu/sf_isinf.c
@@ -0,0 +1,10 @@
+/*
+ * On the SPU isinff(x) always returns 0.
+ *
+ * isinff is an extension declared in <ieeefp.h> and <math.h>.
+ */
+int
+isinff (float x)
+{
+	return 0;
+}
Index: my-base-quilt/newlib/libm/machine/spu/sf_isinff.c
===================================================================
--- /dev/null
+++ my-base-quilt/newlib/libm/machine/spu/sf_isinff.c
@@ -0,0 +1,8 @@
+/*
+ * On the SPU __isinff(x) always returns 0.
+ */
+int
+__isinff (float x)
+{
+	return 0;
+}
Index: my-base-quilt/newlib/libm/machine/spu/sf_finite.c
===================================================================
--- /dev/null
+++ my-base-quilt/newlib/libm/machine/spu/sf_finite.c
@@ -0,0 +1,8 @@
+/*
+ * On the SPU always return 1.
+ */
+int
+finitef(float x)
+{
+	return 1;
+}



More information about the Newlib mailing list