Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Jan 2012 13:36:05 -0500
From:      David Schultz <das@freebsd.org>
To:        freebsd-arm@freebsd.org
Subject:   fenv.h fixes for softfloat
Message-ID:  <20120108183605.GA36775@zim.MIT.EDU>

next in thread | raw e-mail | index | archive | help
The patch below should make the fenv.h functions work on ARM chips
without an FPU.  (Hardware FPU support is missing anyway, and
what's in fenv.h right now is probably wrong.)

It would be great if someone could test this, because I don't have
the hardware.  The regression tests in tools/regression/lib/msun,
particularly test-fenv.c, should provide some idea of what's
working and what isn't.

Index: msun/arm/fenv.h
===================================================================
--- msun/arm/fenv.h	(revision 229262)
+++ msun/arm/fenv.h	(working copy)
@@ -64,13 +64,25 @@
 #define _FPUSW_SHIFT	16
 #define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
 
-#ifdef	ARM_HARD_FLOAT
+#ifndef	ARM_HARD_FLOAT
+/*
+ * The following macros map between the softfloat emulator's flags and
+ * the hardware's FPSR.  The hardware this file was written for doesn't
+ * have rounding control bits, so we stick those in the system ID byte.
+ */
+#define	__set_env(env, flags, mask, rnd) env = ((flags)			\
+						| (mask)<<_FPUSW_SHIFT	\
+						| (rnd) << 24)
+#define	__env_flags(env)		((env) & FE_ALL_EXCEPT)
+#define	__env_mask(env)			(((env) >> _FPUSW_SHIFT)	\
+						& FE_ALL_EXCEPT)
+#define	__env_round(env)		(((env) >> 24) & _ROUND_MASK)
+#include <fenv-softfloat.h>
+
+#else	/* ARM_HARD_FLOAT */
+
 #define	__rfs(__fpsr)	__asm __volatile("rfs %0" : "=r" (*(__fpsr)))
 #define	__wfs(__fpsr)	__asm __volatile("wfs %0" : : "r" (__fpsr))
-#else
-#define __rfs(__fpsr)
-#define __wfs(__fpsr)
-#endif
 
 __fenv_static inline int
 feclearexcept(int __excepts)
@@ -218,6 +230,8 @@
 
 #endif /* __BSD_VISIBLE */
 
+#endif	/* ARM_HARD_FLOAT */
+
 __END_DECLS
 
 #endif	/* !_FENV_H_ */
Index: msun/arm/Makefile.inc
===================================================================
--- msun/arm/Makefile.inc	(revision 229262)
+++ msun/arm/Makefile.inc	(working copy)
@@ -1,4 +1,5 @@
 # $FreeBSD$
 
+INCS += fenv-softfloat.h
 LDBL_PREC = 53
 SYM_MAPS += ${.CURDIR}/arm/Symbol.map
Index: msun/src/fenv-softfloat.h
===================================================================
--- msun/src/fenv-softfloat.h	(revision 0)
+++ msun/src/fenv-softfloat.h	(revision 0)
@@ -0,0 +1,182 @@
+/*-
+ * Copyright (c) 2004-2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef	_FENV_H_
+#error "This file is meant to be included only by <fenv.h>."
+#endif
+
+/*
+ * This file implements the functionality of <fenv.h> on platforms that
+ * lack an FPU and use softfloat in libc for floating point.  To use it,
+ * you must write an <fenv.h> that provides the following:
+ *
+ *   - a typedef for fenv_t, which may be an integer or struct type
+ *   - a typedef for fexcept_t (XXX This file assumes fexcept_t is a
+ *     simple integer type containing the exception mask.)
+ *   - definitions of FE_* constants for the five exceptions and four
+ *     rounding modes in IEEE 754, as described in fenv(3)
+ *   - a definition, and the corresponding external symbol, for FE_DFL_ENV
+ *   - a macro __set_env(env, flags, mask, rnd), which sets the given fenv_t
+ *     from the exception flags, mask, and rounding mode
+ *   - macros __env_flags(env), __env_mask(env), and __env_round(env), which
+ *     extract fields from an fenv_t
+ *   - a definition of __fenv_static
+ *
+ * If the architecture supports an optional FPU, it's recommended that you
+ * define fenv_t and fexcept_t to match the hardware ABI.  Otherwise, it
+ * doesn't matter how you define them.
+ */
+
+extern int __softfloat_float_exception_flags;
+extern int __softfloat_float_exception_mask;
+extern int __softfloat_float_rounding_mode;
+void __softfloat_float_raise(int);
+
+__fenv_static inline int
+feclearexcept(int __excepts)
+{
+
+	__softfloat_float_exception_flags &= ~__excepts;
+	return (0);
+}
+
+__fenv_static inline int
+fegetexceptflag(fexcept_t *__flagp, int __excepts)
+{
+
+	*__flagp = __softfloat_float_exception_flags & __excepts;
+	return (0);
+}
+
+__fenv_static inline int
+fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+{
+
+	__softfloat_float_exception_flags |= *__flagp & __excepts;
+	return (0);
+}
+
+__fenv_static inline int
+feraiseexcept(int __excepts)
+{
+
+	__softfloat_float_raise(__excepts);
+	return (0);
+}
+
+__fenv_static inline int
+fetestexcept(int __excepts)
+{
+
+	return (__softfloat_float_exception_flags & __excepts);
+}
+
+__fenv_static inline int
+fegetround(void)
+{
+
+	return (__softfloat_float_rounding_mode);
+}
+
+__fenv_static inline int
+fesetround(int __round)
+{
+
+	__softfloat_float_rounding_mode = __round;
+	return (0);
+}
+
+__fenv_static inline int
+fegetenv(fenv_t *__envp)
+{
+
+	__set_env(*__envp, __softfloat_float_exception_flags,
+	    __softfloat_float_exception_mask, __softfloat_float_rounding_mode);
+	return (0);
+}
+
+__fenv_static inline int
+feholdexcept(fenv_t *__envp)
+{
+	fenv_t __env;
+
+	fegetenv(__envp);
+	__softfloat_float_exception_mask = 0;
+	return (0);
+}
+
+__fenv_static inline int
+fesetenv(const fenv_t *__envp)
+{
+
+	__softfloat_float_exception_flags = __env_flags(*__envp);
+	__softfloat_float_exception_mask = __env_mask(*__envp);
+	__softfloat_float_rounding_mode = __env_round(*__envp);
+	return (0);
+}
+
+__fenv_static inline int
+feupdateenv(const fenv_t *__envp)
+{
+	int __oflags = __softfloat_float_exception_flags;
+
+	fesetenv(__envp);
+	feraiseexcept(__oflags);
+	return (0);
+}
+
+#if __BSD_VISIBLE
+
+/* We currently provide no external definitions of the functions below. */
+
+static inline int
+feenableexcept(int __mask)
+{
+	int __omask = __softfloat_float_exception_mask;
+
+	__softfloat_float_exception_mask |= __mask;
+	return (__omask);
+}
+
+static inline int
+fedisableexcept(int __mask)
+{
+	int __omask = __softfloat_float_exception_mask;
+
+	__softfloat_float_exception_mask &= ~__mask;
+	return (__omask);
+}
+
+static inline int
+fegetexcept(void)
+{
+
+	return (__softfloat_float_exception_mask);
+}
+
+#endif /* __BSD_VISIBLE */

Property changes on: msun/src/fenv-softfloat.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + FreeBSD=%H
Added: svn:eol-style
   + native

Index: msun/Makefile
===================================================================
--- msun/Makefile	(revision 229262)
+++ msun/Makefile	(working copy)
@@ -125,7 +125,7 @@
 
 SRCS=	${COMMON_SRCS} ${ARCH_SRCS}
 
-INCS=	fenv.h math.h
+INCS+=	fenv.h math.h
 
 MAN=	acos.3 acosh.3 asin.3 asinh.3 atan.3 atan2.3 atanh.3 \
 	ceil.3 ccos.3 ccosh.3 cexp.3 \
Index: libc/arm/softfloat/softfloat.h
===================================================================
--- libc/arm/softfloat/softfloat.h	(revision 229262)
+++ libc/arm/softfloat/softfloat.h	(working copy)
@@ -45,7 +45,7 @@
 /* #define FLOATX80 */
 /* #define FLOAT128 */
 
-#include <machine/ieeefp.h>
+#include <fenv.h>
 
 /*
 -------------------------------------------------------------------------------
@@ -84,12 +84,12 @@
 Software IEC/IEEE floating-point rounding mode.
 -------------------------------------------------------------------------------
 */
-extern fp_rnd_t float_rounding_mode;
+extern int float_rounding_mode;
 enum {
-    float_round_nearest_even = FP_RN,
-    float_round_to_zero      = FP_RZ,
-    float_round_down         = FP_RM,
-    float_round_up           = FP_RP
+    float_round_nearest_even = FE_TONEAREST,
+    float_round_to_zero      = FE_TOWARDZERO,
+    float_round_down         = FE_DOWNWARD,
+    float_round_up           = FE_UPWARD
 };
 
 /*
@@ -97,14 +97,14 @@
 Software IEC/IEEE floating-point exception flags.
 -------------------------------------------------------------------------------
 */
-extern fp_except float_exception_flags;
-extern fp_except float_exception_mask;
+extern int float_exception_flags;
+extern int float_exception_mask;
 enum {
-    float_flag_inexact   = FP_X_IMP,
-    float_flag_underflow = FP_X_UFL,
-    float_flag_overflow  = FP_X_OFL,
-    float_flag_divbyzero = FP_X_DZ,
-    float_flag_invalid   = FP_X_INV
+    float_flag_inexact   = FE_INEXACT,
+    float_flag_underflow = FE_UNDERFLOW,
+    float_flag_overflow  = FE_OVERFLOW,
+    float_flag_divbyzero = FE_DIVBYZERO,
+    float_flag_invalid   = FE_INVALID
 };
 
 /*
@@ -113,7 +113,7 @@
 exception flags.
 -------------------------------------------------------------------------------
 */
-void float_raise( fp_except );
+void float_raise( int );
 
 /*
 -------------------------------------------------------------------------------
Index: libc/softfloat/softfloat-specialize
===================================================================
--- libc/softfloat/softfloat-specialize	(revision 229262)
+++ libc/softfloat/softfloat-specialize	(working copy)
@@ -58,8 +58,8 @@
 should be simply `float_exception_flags |= flags;'.
 -------------------------------------------------------------------------------
 */
-fp_except float_exception_mask = 0;
-void float_raise( fp_except flags )
+int float_exception_mask = 0;
+void float_raise( int flags )
 {
 
     float_exception_flags |= flags;
Index: libc/softfloat/bits64/softfloat.c
===================================================================
--- libc/softfloat/bits64/softfloat.c	(revision 229262)
+++ libc/softfloat/bits64/softfloat.c	(working copy)
@@ -71,8 +71,8 @@
 and exception flags.
 -------------------------------------------------------------------------------
 */
-fp_rnd_t float_rounding_mode = float_round_nearest_even;
-fp_except float_exception_flags = 0;
+int float_rounding_mode = float_round_nearest_even;
+int float_exception_flags = 0;
 #ifdef FLOATX80
 int8 floatx80_rounding_precision = 80;
 #endif
Index: libc/softfloat/Symbol.map
===================================================================
--- libc/softfloat/Symbol.map	(revision 229262)
+++ libc/softfloat/Symbol.map	(working copy)
@@ -18,16 +18,10 @@
 };
 
 FBSDprivate_1.0 {
-	_softfloat_float_exception_flags;
-	_softfloat_float_exception_mask;
-	_softfloat_float_rounding_mode;
-	_softfloat_float_raise;
-	_softfloat_float32_eq;
-	_softfloat_float32_le;
-	_softfloat_float32_lt;
-	_softfloat_float64_eq;
-	_softfloat_float64_le;
-	_softfloat_float64_lt;
+	__softfloat_float_exception_flags;
+	__softfloat_float_exception_mask;
+	__softfloat_float_rounding_mode;
+	__softfloat_float_raise;
 	__eqdf2;
 	__eqsf2;
 	__gedf2;
Index: libc/softfloat/softfloat-for-gcc.h
===================================================================
--- libc/softfloat/softfloat-for-gcc.h	(revision 229262)
+++ libc/softfloat/softfloat-for-gcc.h	(working copy)
@@ -5,17 +5,17 @@
  * Move private identifiers with external linkage into implementation
  * namespace.  -- Klaus Klein <kleink@NetBSD.org>, May 5, 1999
  */
-#define float_exception_flags	_softfloat_float_exception_flags
-#define float_exception_mask	_softfloat_float_exception_mask
-#define float_rounding_mode	_softfloat_float_rounding_mode
-#define float_raise		_softfloat_float_raise
+#define float_exception_flags	__softfloat_float_exception_flags
+#define float_exception_mask	__softfloat_float_exception_mask
+#define float_rounding_mode	__softfloat_float_rounding_mode
+#define float_raise		__softfloat_float_raise
 /* The following batch are called by GCC through wrappers */
-#define float32_eq		_softfloat_float32_eq
-#define float32_le		_softfloat_float32_le
-#define float32_lt		_softfloat_float32_lt
-#define float64_eq		_softfloat_float64_eq
-#define float64_le		_softfloat_float64_le
-#define float64_lt		_softfloat_float64_lt
+#define float32_eq		__softfloat_float32_eq
+#define float32_le		__softfloat_float32_le
+#define float32_lt		__softfloat_float32_lt
+#define float64_eq		__softfloat_float64_eq
+#define float64_le		__softfloat_float64_le
+#define float64_lt		__softfloat_float64_lt
 
 /*
  * Macros to define functions with the GCC expected names
Index: libc/softfloat/bits32/softfloat.c
===================================================================
--- libc/softfloat/bits32/softfloat.c	(revision 229262)
+++ libc/softfloat/bits32/softfloat.c	(working copy)
@@ -77,8 +77,8 @@
 Floating-point rounding mode and exception flags.
 -------------------------------------------------------------------------------
 */
-fp_rnd_t float_rounding_mode = float_round_nearest_even;
-fp_except float_exception_flags = 0;
+int float_rounding_mode = float_round_nearest_even;
+int float_exception_flags = 0;
 
 /*
 -------------------------------------------------------------------------------
Index: libc/mips/softfloat/softfloat.h
===================================================================
--- libc/mips/softfloat/softfloat.h	(revision 229262)
+++ libc/mips/softfloat/softfloat.h	(working copy)
@@ -45,7 +45,7 @@
 /* #define FLOATX80 */
 /* #define FLOAT128 */
 
-#include <machine/ieeefp.h>
+#include <fenv.h>
 
 /*
 -------------------------------------------------------------------------------
@@ -84,12 +84,12 @@
 Software IEC/IEEE floating-point rounding mode.
 -------------------------------------------------------------------------------
 */
-extern fp_rnd_t float_rounding_mode;
+extern int float_rounding_mode;
 enum {
-    float_round_nearest_even = FP_RN,
-    float_round_to_zero      = FP_RZ,
-    float_round_down         = FP_RM,
-    float_round_up           = FP_RP
+    float_round_nearest_even = FE_TONEAREST,
+    float_round_to_zero      = FE_TOWARDZERO,
+    float_round_down         = FE_DOWNWARD,
+    float_round_up           = FE_UPWARD
 };
 
 /*
@@ -97,14 +97,14 @@
 Software IEC/IEEE floating-point exception flags.
 -------------------------------------------------------------------------------
 */
-extern fp_except float_exception_flags;
-extern fp_except float_exception_mask;
+extern int float_exception_flags;
+extern int float_exception_mask;
 enum {
-    float_flag_inexact   = FP_X_IMP,
-    float_flag_underflow = FP_X_UFL,
-    float_flag_overflow  = FP_X_OFL,
-    float_flag_divbyzero = FP_X_DZ,
-    float_flag_invalid   = FP_X_INV
+    float_flag_inexact   = FE_INEXACT,
+    float_flag_underflow = FE_UNDERFLOW,
+    float_flag_overflow  = FE_OVERFLOW,
+    float_flag_divbyzero = FE_DIVBYZERO,
+    float_flag_invalid   = FE_INVALID
 };
 
 /*
@@ -113,7 +113,7 @@
 exception flags.
 -------------------------------------------------------------------------------
 */
-void float_raise( fp_except );
+void float_raise( int );
 
 /*
 -------------------------------------------------------------------------------



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120108183605.GA36775>