Add support for fenv.h interface for i386 and amd64. trunk
authorjoerg <joerg@NetBSD.org>
Sat, 31 Jul 2010 21:47:52 +0000
branchtrunk
changeset 192677 74b92ed27ee1
parent 192676 ee1290585a4a
child 192678 c2fcb41e1865
Add support for fenv.h interface for i386 and amd64. Submitted by Stathis Kamperis as part of GSoC 2010 and ported from FreeBSD.
distrib/sets/lists/comp/md.amd64
distrib/sets/lists/comp/md.i386
distrib/sets/lists/comp/mi
include/Makefile
include/fenv.h
lib/libm/Makefile
lib/libm/arch/i387/fenv.c
lib/libm/arch/x86_64/fenv.c
lib/libm/man/feclearexcept.3
lib/libm/man/feenableexcept.3
lib/libm/man/fegetenv.3
lib/libm/man/fegetround.3
lib/libm/man/fenv.3
sys/arch/amd64/include/Makefile
sys/arch/amd64/include/fenv.h
sys/arch/i386/include/Makefile
sys/arch/i386/include/fenv.h
sys/arch/i386/include/npx.h
sys/arch/x86/include/ieeefp.h
--- a/distrib/sets/lists/comp/md.amd64	Sat Jul 31 21:21:17 2010 +0000
+++ b/distrib/sets/lists/comp/md.amd64	Sat Jul 31 21:47:52 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: md.amd64,v 1.71 2010/07/11 06:16:55 mrg Exp $
+# $NetBSD: md.amd64,v 1.72 2010/07/31 21:47:52 joerg Exp $
 ./usr/include/amd64				comp-c-include
 ./usr/include/amd64/ansi.h			comp-c-include
 ./usr/include/amd64/aout_machdep.h		comp-c-include
@@ -16,6 +16,7 @@
 ./usr/include/amd64/elf_machdep.h		comp-c-include
 ./usr/include/amd64/endian.h			comp-c-include
 ./usr/include/amd64/endian_machdep.h		comp-c-include
+./usr/include/amd64/fenv.h			comp-c-include
 ./usr/include/amd64/float.h			comp-c-include
 ./usr/include/amd64/fpu.h			comp-c-include
 ./usr/include/amd64/frame.h			comp-c-include
@@ -85,6 +86,7 @@
 ./usr/include/i386/elf_machdep.h		comp-c-include
 ./usr/include/i386/endian.h			comp-c-include
 ./usr/include/i386/endian_machdep.h		comp-c-include
+./usr/include/i386/fenv.h			comp-c-include
 ./usr/include/i386/float.h			comp-c-include
 ./usr/include/i386/frame.h			comp-c-include
 ./usr/include/i386/freebsd_machdep.h		comp-c-include
--- a/distrib/sets/lists/comp/md.i386	Sat Jul 31 21:21:17 2010 +0000
+++ b/distrib/sets/lists/comp/md.i386	Sat Jul 31 21:47:52 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: md.i386,v 1.113 2010/07/07 00:10:14 njoly Exp $
+# $NetBSD: md.i386,v 1.114 2010/07/31 21:47:52 joerg Exp $
 ./usr/include/emmintrin.h			comp-c-include		gcccmds
 ./usr/include/i386				comp-c-include
 ./usr/include/i386/_G_config.h			comp-obsolete		obsolete
@@ -23,6 +23,7 @@
 ./usr/include/i386/elf_machdep.h		comp-c-include
 ./usr/include/i386/endian.h			comp-c-include
 ./usr/include/i386/endian_machdep.h		comp-c-include
+./usr/include/i386/fenv.h			comp-c-include
 ./usr/include/i386/float.h			comp-c-include
 ./usr/include/i386/frame.h			comp-c-include
 ./usr/include/i386/freebsd_machdep.h		comp-c-include
--- a/distrib/sets/lists/comp/mi	Sat Jul 31 21:21:17 2010 +0000
+++ b/distrib/sets/lists/comp/mi	Sat Jul 31 21:47:52 2010 +0000
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.1488 2010/07/31 03:14:06 pgoyette Exp $
+#	$NetBSD: mi,v 1.1489 2010/07/31 21:47:52 joerg Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -632,6 +632,7 @@
 ./usr/include/evrpc.h				comp-c-include
 ./usr/include/evutil.h				comp-c-include
 ./usr/include/fcntl.h				comp-c-include
+./usr/include/fenv.h				comp-c-include
 ./usr/include/fetch.h				comp-c-include
 ./usr/include/filecorefs/filecore_mount.h	comp-c-include
 ./usr/include/float.h				comp-c-include
@@ -5783,9 +5784,24 @@
 ./usr/share/man/cat3/fdiml.0			comp-c-catman		.cat
 ./usr/share/man/cat3/fdopen.0			comp-c-catman		.cat
 ./usr/share/man/cat3/fdopendir.0		comp-c-catman		.cat
+./usr/share/man/cat3/feclearexcept.0		comp-c-catman		.cat
+./usr/share/man/cat3/fedisableexcept.0		comp-c-catman		.cat
+./usr/share/man/cat3/feenableexcept.0		comp-c-catman		.cat
+./usr/share/man/cat3/fegetenv.0			comp-c-catman		.cat
+./usr/share/man/cat3/fegetexcept.0		comp-c-catman		.cat
+./usr/share/man/cat3/fegetexceptflag.0		comp-c-catman		.cat
+./usr/share/man/cat3/fegetround.0		comp-c-catman		.cat
+./usr/share/man/cat3/feholdexcept.0		comp-c-catman		.cat
+./usr/share/man/cat3/fenv.0			comp-c-catman		.cat
 ./usr/share/man/cat3/feof.0			comp-c-catman		.cat
+./usr/share/man/cat3/feraiseexcept.0		comp-c-catman		.cat
 ./usr/share/man/cat3/ferror.0			comp-c-catman		.cat
+./usr/share/man/cat3/feseteexcpetflag.0		comp-c-catman		.cat
+./usr/share/man/cat3/fesetenv.0			comp-c-catman		.cat
+./usr/share/man/cat3/fesetround.0		comp-c-catman		.cat
 ./usr/share/man/cat3/fetch.0			comp-c-catman		.cat
+./usr/share/man/cat3/fetestexcept.0		comp-c-catman		.cat
+./usr/share/man/cat3/feupdateenv.0		comp-c-catman		.cat
 ./usr/share/man/cat3/fflush.0			comp-c-catman		.cat
 ./usr/share/man/cat3/ffs.0			comp-c-catman		.cat
 ./usr/share/man/cat3/ffs32.0			comp-c-catman		.cat
@@ -11690,9 +11706,24 @@
 ./usr/share/man/html3/fdiml.html		comp-c-htmlman		html
 ./usr/share/man/html3/fdopen.html		comp-c-htmlman		html
 ./usr/share/man/html3/fdopendir.html		comp-c-htmlman		html
+./usr/share/man/html3/feclearexcept.html	comp-c-htmlman		html
+./usr/share/man/html3/fedisableexcept.html	comp-c-htmlman		html
+./usr/share/man/html3/feenableexcept.html	comp-c-htmlman		html
+./usr/share/man/html3/fegetenv.html		comp-c-htmlman		html
+./usr/share/man/html3/fegetexcept.html		comp-c-htmlman		html
+./usr/share/man/html3/fegetexceptflag.html	comp-c-htmlman		html
+./usr/share/man/html3/fegetround.html		comp-c-htmlman		html
+./usr/share/man/html3/feholdexcept.html		comp-c-htmlman		html
+./usr/share/man/html3/fenv.html			comp-c-htmlman		html
 ./usr/share/man/html3/feof.html			comp-c-htmlman		html
+./usr/share/man/html3/feraiseexcept.html	comp-c-htmlman		html
 ./usr/share/man/html3/ferror.html		comp-c-htmlman		html
+./usr/share/man/html3/feseteexcpetflag.html	comp-c-htmlman		html
+./usr/share/man/html3/fesetenv.html		comp-c-htmlman		html
+./usr/share/man/html3/fesetround.html		comp-c-htmlman		html
 ./usr/share/man/html3/fetch.html		comp-c-htmlman		html
+./usr/share/man/html3/fetestexcept.html		comp-c-htmlman		html
+./usr/share/man/html3/feupdateenv.html		comp-c-html		html
 ./usr/share/man/html3/fflush.html		comp-c-htmlman		html
 ./usr/share/man/html3/ffs.html			comp-c-htmlman		html
 ./usr/share/man/html3/ffs32.html		comp-c-htmlman		html
@@ -17507,8 +17538,23 @@
 ./usr/share/man/man3/fdiml.3			comp-c-man		.man
 ./usr/share/man/man3/fdopen.3			comp-c-man		.man
 ./usr/share/man/man3/fdopendir.3		comp-c-man		.man
+./usr/share/man/man3/feclearexcept.3		comp-c-man		.man
+./usr/share/man/man3/fedisableexcept.3		comp-c-man		.man
+./usr/share/man/man3/feenableexcept.3		comp-c-man		.man
+./usr/share/man/man3/fegetenv.3			comp-c-man		.man
+./usr/share/man/man3/fegetexcept.3		comp-c-man		.man
+./usr/share/man/man3/fegetexceptflag.3		comp-c-man		.man
+./usr/share/man/man3/fegetround.3		comp-c-man		.man
+./usr/share/man/man3/feholdexcept.3		comp-c-man		.man
+./usr/share/man/man3/fenv.3			comp-c-man		.man
 ./usr/share/man/man3/feof.3			comp-c-man		.man
+./usr/share/man/man3/feraiseexcept.3		comp-c-man		.man
 ./usr/share/man/man3/ferror.3			comp-c-man		.man
+./usr/share/man/man3/feseteexcpetflag.3         comp-c-man              .man
+./usr/share/man/man3/fesetenv.3                 comp-c-man              .man
+./usr/share/man/man3/fesetround.3               comp-c-man              .man
+./usr/share/man/man3/fetestexcept.3		comp-c-man		.man
+./usr/share/man/man3/feupdateenv.3		comp-c-man		.man
 ./usr/share/man/man3/fetch.3			comp-c-man		.man
 ./usr/share/man/man3/fflush.3			comp-c-man		.man
 ./usr/share/man/man3/ffs.3			comp-c-man		.man
--- a/include/Makefile	Sat Jul 31 21:21:17 2010 +0000
+++ b/include/Makefile	Sat Jul 31 21:47:52 2010 +0000
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.132 2010/04/25 00:54:45 joerg Exp $
+#	$NetBSD: Makefile,v 1.133 2010/07/31 21:47:53 joerg Exp $
 #	@(#)Makefile	8.2 (Berkeley) 1/4/94
 
 # Doing a make includes builds /usr/include
@@ -9,7 +9,7 @@
 
 INCS=	a.out.h aio.h ar.h assert.h atomic.h \
 	bitstring.h bm.h cdbr.h cdbw.h complex.h cpio.h ctype.h \
-	db.h dirent.h disktab.h dlfcn.h err.h errno.h fmtmsg.h fnmatch.h \
+	db.h dirent.h disktab.h dlfcn.h err.h errno.h fenv.h fmtmsg.h fnmatch.h \
 	fstab.h fts.h ftw.h getopt.h glob.h grp.h ifaddrs.h iconv.h \
 	inttypes.h iso646.h kvm.h langinfo.h libgen.h \
 	limits.h link.h link_aout.h link_elf.h locale.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/fenv.h	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,62 @@
+/*	$NetBSD: fenv.h,v 1.1 2010/07/31 21:47:53 joerg Exp $	*/
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#if !defined(__i386__) && !defined(__amd64__)
+#error	"fenv.h is currently not supported for this architecture"
+#endif
+
+#ifndef _FENV_H_
+#define _FENV_H_
+
+#include <machine/fenv.h>
+
+__BEGIN_DECLS
+
+/* Function prototypes */
+int	feclearexcept(int);
+int	fegetexceptflag(fexcept_t *, int);
+int	feraiseexcept(int);
+int	fesetexceptflag(const fexcept_t *, int);
+int	fetestexcept(int);
+int	fegetround(void);
+int	fesetround(int);
+int	fegetenv(fenv_t *);
+int	feholdexcept(fenv_t *);
+int	fesetenv(const fenv_t *);
+int	feupdateenv(const fenv_t *);
+
+#if defined(_NETBSD_SOURCE) || (_GNU_SOURCE)
+
+int	feenableexcept(int mask);
+int	fedisableexcept(int mask);
+int	fegetexcept(void);
+
+#endif /* _NETBDS_SOURCE || _GNU_SOURCE */
+
+__END_DECLS
+
+#endif /* ! _FENV_H_ */
--- a/lib/libm/Makefile	Sat Jul 31 21:21:17 2010 +0000
+++ b/lib/libm/Makefile	Sat Jul 31 21:47:52 2010 +0000
@@ -1,4 +1,4 @@
-#  $NetBSD: Makefile,v 1.94 2010/04/23 19:17:07 drochner Exp $
+#  $NetBSD: Makefile,v 1.95 2010/07/31 21:47:53 joerg Exp $
 #
 #  @(#)Makefile 5.1beta 93/09/24
 #
@@ -51,7 +51,13 @@
 .PATH: ${.CURDIR}/arch/alpha
 ARCH_SRCS = s_copysign.S s_copysignf.S lrint.S
 .elif ((${MACHINE_ARCH} == "i386") || (${MACHINE_ARCH} == "x86_64"))
+
+.if (${MACHINE_ARCH} == "x86_64")
+.PATH: ${.CURDIR}/arch/x86_64
+.endif
 .PATH:	${.CURDIR}/arch/i387
+
+COMMON_SRCS+= fenv.c
 ARCH_SRCS = e_acos.S e_asin.S e_atan2.S e_exp.S e_expf.S e_fmod.S e_log.S \
 	    e_logf.S e_log10.S e_log10f.S e_log2.S e_log2f.S e_remainder.S \
 	    e_remainderf.S e_scalb.S e_scalbf.S e_sqrt.S e_sqrtf.S s_atan.S \
@@ -60,6 +66,7 @@
 	    s_ilogbf.S s_log1p.S s_log1pf.S s_logb.S s_logbf.S s_rint.S \
 	    s_rintf.S s_scalbn.S s_scalbnf.S s_significand.S \
 	    s_significandf.S s_sin.S s_sinf.S s_tan.S s_tanf.S lrint.S
+
 .if (${MACHINE_ARCH} == "i386")
 SUBDIR=arch/i387
 .endif
@@ -108,7 +115,7 @@
 CPPFLAGS+=-DLIBM_SCCS
 
 LIB=	m
-COMMON_SRCS = e_acos.c e_acosf.c e_acosh.c e_acoshf.c e_asin.c e_asinf.c \
+COMMON_SRCS+= e_acos.c e_acosf.c e_acosh.c e_acoshf.c e_asin.c e_asinf.c \
 	e_atan2.c e_atan2f.c e_atanh.c e_atanhf.c e_cosh.c e_coshf.c e_exp.c \
 	e_expf.c e_fmod.c e_fmodf.c e_hypot.c e_hypotf.c e_j0.c e_j0f.c \
 	e_j1.c e_j1f.c e_jn.c e_jnf.c e_lgamma_r.c e_lgammaf_r.c e_log.c \
@@ -188,6 +195,19 @@
 	math.3 modf.3 rint.3 round.3 sin.3 sinh.3 \
 	sqrt.3 tan.3 tanh.3 trunc.3 fmax.3 fdim.3
 
+# fenv.h interface
+MAN+=	feclearexcept.3 feenableexcept.3 fegetenv.3 fegetround.3 fenv.3
+MLINKS+=feclearexcept.3 fegetexceptflag.3	\
+	feclearexcept.3 feraiseexcept.3		\
+	feclearexcept.3 feseteexcpetflag.3	\
+	feclearexcept.3 fetestexcept.3
+MLINKS+=feenableexcept.3 fedisableexcept.3	\
+	feenableexcept.3 fegetexcept.3
+MLINKS+=fegetenv.3 feholdexcept.3		\
+	fegetenv.3 fesetenv.3			\
+	fegetenv.3 feupdateenv.3
+MLINKS+=fegetround.3 fesetround.3
+
 MLINKS+=acos.3 acosf.3
 MLINKS+=acosh.3 acoshf.3
 MLINKS+=asin.3 asinf.3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libm/arch/i387/fenv.c	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,516 @@
+/* $NetBSD: fenv.c,v 1.1 2010/07/31 21:47:53 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2004-2005 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: fenv.c,v 1.1 2010/07/31 21:47:53 joerg Exp $");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <assert.h>
+#include <fenv.h>
+#include <stddef.h>
+#include <string.h>
+
+/* Load x87 Control Word */
+#define	__fldcw(__cw)		__asm__ __volatile__	\
+	("fldcw %0" : : "m" (__cw))
+
+/* No-Wait Store Control Word */
+#define	__fnstcw(__cw)		__asm__ __volatile__	\
+	("fnstcw %0" : "=m" (*(__cw)))
+
+/* No-Wait Store Status Word */
+#define	__fnstsw(__sw)		__asm__ __volatile__	\
+	("fnstsw %0" : "=am" (*(__sw)))
+
+/* No-Wait Clear Exception Flags */
+#define	__fnclex()		__asm__ __volatile__	\
+	("fnclex")
+
+/* Load x87 Environment */
+#define	__fldenv(__env)		__asm__ __volatile__	\
+	("fldenv %0" : : "m" (__env))
+
+/* No-Wait Store x87 environment */
+#define	__fnstenv(__env)	__asm__ __volatile__	\
+	("fnstenv %0" : "=m" (*(__env)))
+
+/* Check for and handle pending unmasked x87 pending FPU exceptions */
+#define	__fwait(__env)		__asm__	__volatile__	\
+	("fwait")
+
+/* Load the MXCSR register */
+#define	__ldmxcsr(__mxcsr)	__asm__ __volatile__	\
+	("ldmxcsr %0" : : "m" (__mxcsr))
+
+/* Store the MXCSR register state */
+#define	__stmxcsr(__mxcsr)	__asm__ __volatile__	\
+	("stmxcsr %0" : "=m" (*(__mxcsr)))
+
+/*
+ * The following constant represents the default floating-point environment
+ * (that is, the one installed at program startup) and has type pointer to
+ * const-qualified fenv_t.
+ *
+ * It can be used as an argument to the functions within the <fenv.h> header
+ * that manage the floating-point environment, namely fesetenv() and
+ * feupdateenv().
+ *
+ * x87 fpu registers are 16bit wide. The upper bits, 31-16, are marked as
+ * RESERVED. We provide a partial floating-point environment, where we
+ * define only the lower bits. The reserved bits are extracted and set by the
+ * consumers of FE_DFL_ENV, during runtime.
+ */
+fenv_t __fe_dfl_env = {
+	{
+		__NetBSD_NPXCW__,       /* Control word register */
+		0x0,			/* Unused */
+		0x0000,                 /* Status word register */
+		0x0,			/* Unused */
+		0x0000ffff,             /* Tag word register */
+		0x0,			/* Unused */
+		{
+			0x0000, 0x0000,
+			0x0000, 0xffff
+		}
+	},
+	__INITIAL_MXCSR__		/* MXCSR register */
+};
+
+/*
+ * Test for SSE support on this processor.
+ *
+ * We need to use ldmxcsr/stmxcsr to get correct results if any part
+ * of the program was compiled to use SSE floating-point, but we can't
+ * use SSE on older processors.
+ *
+ * In order to do so, we need to query the processor capabilities via the CPUID
+ * instruction. We can make it even simpler though, by querying the machdep.sse
+ * sysctl.
+ */
+static int __HAS_SSE = 0;
+
+static void __test_sse(void) __attribute__ ((constructor));
+
+static void __test_sse(void)
+{
+	char machine[64];
+	size_t oldlen;
+	int rv;
+
+	rv = sysctlbyname("machdep.sse", &__HAS_SSE, &oldlen, NULL, 0);
+	_DIAGASSERT(rv != -1);
+	if (rv == -1)
+		__HAS_SSE = 0;
+}
+
+/*
+ * The feclearexcept() function clears the supported floating-point exceptions
+ * represented by `excepts'.
+ */
+int
+feclearexcept(int excepts)
+{
+	fenv_t env;
+	uint32_t mxcsr;
+	int ex;
+
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+
+	/* It's ~3x faster to call fnclex, than store/load fp env */
+	if (ex == FE_ALL_EXCEPT) {
+		__fnclex();
+	} else {
+		__fnstenv(&env);
+		env.x87.status &= ~ex;
+		__fldenv(env);
+	}
+
+	if (__HAS_SSE) {
+		__stmxcsr(&mxcsr);
+		mxcsr &= ~ex;
+		__ldmxcsr(mxcsr);
+	}
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The fegetexceptflag() function stores an implementation-defined
+ * representation of the states of the floating-point status flags indicated by
+ * the argument excepts in the object pointed to by the argument flagp.
+ */
+int
+fegetexceptflag(fexcept_t *flagp, int excepts)
+{
+	uint32_t mxcsr;
+	uint16_t status;
+	int ex;
+
+	_DIAGASSERT(flagp != NULL);
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+
+	__fnstsw(&status);
+	if (__HAS_SSE)
+		__stmxcsr(&mxcsr);
+	else
+		mxcsr = 0;
+
+	*flagp = (mxcsr | status) & ex;
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The feraiseexcept() function raises the supported floating-point exceptions
+ * represented by the argument `excepts'.
+ *
+ * The standard explicitly allows us to execute an instruction that has the
+ * exception as a side effect, but we choose to manipulate the status register
+ * directly.
+ *
+ * The validation of input is being deferred to fesetexceptflag().
+ */
+int
+feraiseexcept(int excepts)
+{
+	fexcept_t ex;
+
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+	fesetexceptflag(&ex, excepts);
+	__fwait();
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * This function sets the floating-point status flags indicated by the argument
+ * `excepts' to the states stored in the object pointed to by `flagp'. It does
+ * NOT raise any floating-point exceptions, but only sets the state of the flags.
+ */
+int
+fesetexceptflag(const fexcept_t *flagp, int excepts)
+{
+	fenv_t env;
+	uint32_t mxcsr;
+	int ex;
+
+	_DIAGASSERT(flagp != NULL);
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+
+	__fnstenv(&env);
+	env.x87.status &= ~ex;
+	env.x87.status |= *flagp & ex;
+	__fldenv(env);
+
+	if (__HAS_SSE) {
+		__stmxcsr(&mxcsr);
+		mxcsr &= ~ex;
+		mxcsr |= *flagp & ex;
+		__ldmxcsr(mxcsr);
+	}
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The fetestexcept() function determines which of a specified subset of the
+ * floating-point exception flags are currently set. The `excepts' argument
+ * specifies the floating-point status flags to be queried.
+ */
+int
+fetestexcept(int excepts)
+{
+	uint32_t mxcsr;
+	uint16_t status;
+	int ex;
+
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+
+	__fnstsw(&status);
+	if (__HAS_SSE)
+		__stmxcsr(&mxcsr);
+	else
+		mxcsr = 0;
+
+	return ((status | mxcsr) & ex);
+}
+
+int
+fegetround(void)
+{
+	uint16_t control;
+
+	/*
+	 * We assume that the x87 and the SSE unit agree on the
+	 * rounding mode.  Reading the control word on the x87 turns
+	 * out to be about 5 times faster than reading it on the SSE
+	 * unit on an Opteron 244.
+	 */
+	__fnstcw(&control);
+
+	return (control & __X87_ROUND_MASK);
+}
+
+/*
+ * The fesetround() function shall establish the rounding direction represented
+ * by its argument round. If the argument is not equal to the value of a
+ * rounding direction macro, the rounding direction is not changed.
+ */
+int
+fesetround(int round)
+{
+	uint32_t mxcsr;
+	uint16_t control;
+
+	if (round & ~__X87_ROUND_MASK) {
+		/* Failure */
+		return (-1);
+	}
+
+	__fnstcw(&control);
+	control &= ~__X87_ROUND_MASK;
+	control |= round;
+	__fldcw(control);
+
+	if (__HAS_SSE) {
+		__stmxcsr(&mxcsr);
+		mxcsr &= ~(__X87_ROUND_MASK << __SSE_ROUND_SHIFT);
+		mxcsr |= round << __SSE_ROUND_SHIFT;
+		__ldmxcsr(mxcsr);
+	}
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The fegetenv() function attempts to store the current floating-point
+ * environment in the object pointed to by envp.
+ */
+int
+fegetenv(fenv_t *envp)
+{
+	uint32_t mxcsr;
+
+	_DIAGASSERT(flagp != NULL);
+
+	/*
+	 * fnstenv masks all exceptions, so we need to restore the old control
+	 * word to avoid this side effect.
+	 */
+	__fnstenv(envp);
+	__fldcw(envp->x87.control);
+	if (__HAS_SSE) {
+		__stmxcsr(&mxcsr);
+		envp->mxcsr = mxcsr;
+	}
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The feholdexcept() function saves the current floating-point environment in
+ * the object pointed to by envp, clears the floating-point status flags, and
+ * then installs a non-stop (continue on floating-point exceptions) mode, if
+ * available, for all floating-point exceptions.
+ */
+int
+feholdexcept(fenv_t *envp)
+{
+	uint32_t mxcsr;
+
+	_DIAGASSERT(envp != NULL);
+
+	__fnstenv(envp);
+	__fnclex();
+	if (__HAS_SSE) {
+		__stmxcsr(&mxcsr);
+		envp->mxcsr = mxcsr;
+		mxcsr &= ~FE_ALL_EXCEPT;
+		mxcsr |= FE_ALL_EXCEPT << __SSE_EMASK_SHIFT;
+		__ldmxcsr(mxcsr);
+	}
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The fesetenv() function attempts to establish the floating-point environment
+ * represented by the object pointed to by envp. The argument `envp' points
+ * to an object set by a call to fegetenv() or feholdexcept(), or equal a
+ * floating-point environment macro. The fesetenv() function does not raise
+ * floating-point exceptions, but only installs the state of the floating-point
+ * status flags represented through its argument.
+ */
+int
+fesetenv(const fenv_t *envp)
+{
+	fenv_t env;
+
+	_DIAGASSERT(envp != NULL);
+
+	/* Store the x87 floating-point environment */
+	memset(&env, 0, sizeof(env));
+	__fnstenv(&env);
+
+	__fe_dfl_env.x87.unused1 = env.x87.unused1;
+	__fe_dfl_env.x87.unused2 = env.x87.unused2;
+	__fe_dfl_env.x87.unused3 = env.x87.unused3;
+	memcpy(__fe_dfl_env.x87.others,
+	       env.x87.others,
+	       sizeof(__fe_dfl_env.x87.others) / sizeof(uint32_t));
+
+	__fldenv(envp->x87);
+	if (__HAS_SSE)
+		__ldmxcsr(envp->mxcsr);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The feupdateenv() function saves the currently raised floating-point
+ * exceptions in its automatic storage, installs the floating-point environment
+ * represented by the object pointed to by `envp', and then raises the saved
+ * floating-point exceptions. The argument `envp' shall point to an object set
+ * by a call to feholdexcept() or fegetenv(), or equal a floating-point
+ * environment macro.
+ */
+int
+feupdateenv(const fenv_t *envp)
+{
+	fenv_t env;
+	uint32_t mxcsr;
+	uint16_t status;
+
+	_DIAGASSERT(envp != NULL);
+
+	/* Store the x87 floating-point environment */
+	memset(&env, 0, sizeof(env));
+	__fnstenv(&env);
+
+	__fe_dfl_env.x87.unused1 = env.x87.unused1;
+	__fe_dfl_env.x87.unused2 = env.x87.unused2;
+	__fe_dfl_env.x87.unused3 = env.x87.unused3;
+	memcpy(__fe_dfl_env.x87.others,
+	       env.x87.others,
+	       sizeof(__fe_dfl_env.x87.others) / sizeof(uint32_t));
+
+	__fnstsw(&status);
+	if (__HAS_SSE)
+		__stmxcsr(&mxcsr);
+	else
+		mxcsr = 0;
+	fesetenv(envp);
+	feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The following functions are extentions to the standard
+ */
+int
+feenableexcept(int mask)
+{
+	uint32_t mxcsr, omask;
+	uint16_t control;
+
+	mask &= FE_ALL_EXCEPT;
+	__fnstcw(&control);
+	if (__HAS_SSE)
+		__stmxcsr(&mxcsr);
+	else
+		mxcsr = 0;
+
+	omask = (control | mxcsr >> __SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+	control &= ~mask;
+	__fldcw(control);
+	if (__HAS_SSE) {
+		mxcsr &= ~(mask << __SSE_EMASK_SHIFT);
+		__ldmxcsr(mxcsr);
+	}
+
+	return (~omask);
+}
+
+int
+fedisableexcept(int mask)
+{
+	uint32_t mxcsr, omask;
+	uint16_t control;
+
+	mask &= FE_ALL_EXCEPT;
+	__fnstcw(&control);
+	if (__HAS_SSE)
+		__stmxcsr(&mxcsr);
+	else
+		mxcsr = 0;
+
+	omask = (control | mxcsr >> __SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+	control |= mask;
+	__fldcw(control);
+	if (__HAS_SSE) {
+		mxcsr |= mask << __SSE_EMASK_SHIFT;
+		__ldmxcsr(mxcsr);
+	}
+
+	return (~omask);
+}
+
+int
+fegetexcept(void)
+{
+	uint16_t control;
+
+	/*
+	 * We assume that the masks for the x87 and the SSE unit are
+	 * the same.
+	 */
+	__fnstcw(&control);
+
+	return (control & FE_ALL_EXCEPT);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libm/arch/x86_64/fenv.c	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,524 @@
+/* $NetBSD: fenv.c,v 1.1 2010/07/31 21:47:53 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das (at) 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: fenv.c,v 1.1 2010/07/31 21:47:53 joerg Exp $");
+
+#include <assert.h>
+#include <fenv.h>
+#include <stddef.h>
+#include <string.h>
+
+/* Load x87 Control Word */
+#define	__fldcw(__cw)		__asm__ __volatile__ \
+	("fldcw %0" : : "m" (__cw))
+
+/* No-Wait Store Control Word */
+#define	__fnstcw(__cw)		__asm__ __volatile__ \
+	("fnstcw %0" : "=m" (*(__cw)))
+
+/* No-Wait Store Status Word */
+#define	__fnstsw(__sw)		__asm__ __volatile__ \
+	("fnstsw %0" : "=am" (*(__sw)))
+
+/* No-Wait Clear Exception Flags */
+#define	__fnclex()		__asm__ __volatile__ \
+	("fnclex")
+
+/* Load x87 Environment */
+#define	__fldenv(__env)		__asm__ __volatile__ \
+	("fldenv %0" : : "m" (__env))
+
+/* No-Wait Store x87 environment */
+#define	__fnstenv(__env)	__asm__ __volatile__ \
+	("fnstenv %0" : "=m" (*(__env)))
+
+/* Load the MXCSR register */
+#define	__ldmxcsr(__mxcsr)	__asm__ __volatile__ \
+	("ldmxcsr %0" : : "m" (__mxcsr))
+
+/* Store the MXCSR register state */
+#define	__stmxcsr(__mxcsr)	__asm__ __volatile__ \
+	("stmxcsr %0" : "=m" (*(__mxcsr)))
+
+/*
+ * The following constant represents the default floating-point environment
+ * (that is, the one installed at program startup) and has type pointer to
+ * const-qualified fenv_t.
+ *
+ * It can be used as an argument to the functions within the <fenv.h> header
+ * that manage the floating-point environment, namely fesetenv() and
+ * feupdateenv().
+ *
+ * x87 fpu registers are 16bit wide. The upper bits, 31-16, are marked as
+ * RESERVED. We provide a partial floating-point environment, where we
+ * define only the lower bits. The reserved bits are extracted and set by
+ * the consumers of FE_DFL_ENV, during runtime.
+ */
+fenv_t __fe_dfl_env = {
+	{
+		__NetBSD_NPXCW__,	/* Control word register */
+		0x00000000,		/* Status word register */
+		0x0000ffff,		/* Tag word register */
+		{
+			0x00000000,
+			0x00000000,
+			0x00000000,
+			0x00000000,
+		},
+	},
+	__INITIAL_MXCSR__       /* MXCSR register */
+};
+#define FE_DFL_ENV      ((const fenv_t *) &__fe_dfl_env)
+
+
+/*
+ * The feclearexcept() function clears the supported floating-point exceptions
+ * represented by `excepts'.
+ */
+int
+feclearexcept(int excepts)
+{
+	fenv_t fenv;
+	int ex;
+
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+
+	/* Store the current x87 floating-point environment */
+	__fnstenv(&fenv);
+
+	/* Clear the requested floating-point exceptions */
+	fenv.x87.status &= ~ex;
+
+	/* Load the x87 floating-point environent */
+	__fldenv(fenv);
+
+	/* Same for SSE environment */
+	__stmxcsr(&fenv.mxcsr);
+	fenv.mxcsr &= ~ex;
+	__ldmxcsr(fenv.mxcsr);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The fegetexceptflag() function stores an implementation-defined
+ * representation of the states of the floating-point status flags indicated by
+ * the argument excepts in the object pointed to by the argument flagp.
+ */
+int
+fegetexceptflag(fexcept_t *flagp, int excepts)
+{
+	uint32_t mxcsr;
+	uint16_t x87_status;
+	int ex;
+
+	_DIAGASSERT(flagp != NULL);
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+
+	/* Store the current x87 status register */
+	__fnstsw(&x87_status);
+
+	/* Store the MXCSR register */
+	__stmxcsr(&mxcsr);
+
+	/* Store the results in flagp */
+	*flagp = (x87_status | mxcsr) & ex;
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The feraiseexcept() function raises the supported floating-point exceptions
+ * represented by the argument `excepts'.
+ *
+ * The standard explicitly allows us to execute an instruction that has the
+ * exception as a side effect, but we choose to manipulate the status register
+ * directly.
+ *
+ * The validation of input is being deferred to fesetexceptflag().
+ */
+int
+feraiseexcept(int excepts)
+{
+	int ex;
+
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+	fesetexceptflag((unsigned int *)&excepts, excepts);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * This function sets the floating-point status flags indicated by the argument
+ * `excepts' to the states stored in the object pointed to by `flagp'. It does
+ * NOT raise any floating-point exceptions, but only sets the state of the flags.
+ */
+int
+fesetexceptflag(const fexcept_t *flagp, int excepts)
+{
+	fenv_t fenv;
+	int ex;
+
+	_DIAGASSERT(flagp != NULL);
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+
+	/* Store the current x87 floating-point environment */
+	__fnstenv(&fenv);
+
+	/* Set the requested status flags */
+	fenv.x87.status |= *flagp & ex;
+
+	/* Load the x87 floating-point environent */
+	__fldenv(fenv);
+
+	/* Same for SSE environment */
+	__stmxcsr(&fenv.mxcsr);
+	fenv.mxcsr |= *flagp & ex;
+	__ldmxcsr(fenv.mxcsr);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The fetestexcept() function determines which of a specified subset of the
+ * floating-point exception flags are currently set. The `excepts' argument
+ * specifies the floating-point status flags to be queried.
+ */
+int
+fetestexcept(int excepts)
+{
+	fenv_t fenv;
+	uint32_t mxcsr;
+	uint16_t status;
+	int ex;
+
+	_DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0);
+
+	ex = excepts & FE_ALL_EXCEPT;
+
+	/* Store the current x87 floating-point environment */
+	memset(&fenv, 0, sizeof(fenv));
+
+	__fnstenv(&fenv);
+	__fnstsw(&status);
+
+	/* Store the MXCSR register state */
+	__stmxcsr(&fenv.mxcsr);
+	__stmxcsr(&mxcsr);
+
+	return ((fenv.x87.status | fenv.mxcsr) & ex);
+}
+
+/*
+ * The fegetround() function gets the current rounding direction.
+ */
+int
+fegetround(void)
+{
+	uint32_t mxcsr;
+	uint16_t control;
+
+	/*
+	 * We check both the x87 floating-point unit _and_ the SSE unit.
+	 * Normally, those two must agree with respect to each other. If they
+	 * don't, it's not our fault and the result is non-determinable, in
+	 * which case POSIX says that a negative value should be returned.
+	 */
+	__fnstcw(&control);
+	__stmxcsr(&mxcsr);
+
+	if ((control & _X87_ROUNDING_MASK)
+	    != ((mxcsr & _SSE_ROUNDING_MASK) >> 3)) {
+		return (-1);
+	}
+
+	return (control & _X87_ROUNDING_MASK);
+}
+
+/*
+ * The fesetround() function establishes the rounding direction represented by
+ * its argument `round'. If the argument is not equal to the value of a rounding
+ * direction macro, the rounding direction is not changed.
+ */
+int
+fesetround(int round)
+{
+	uint32_t  mxcsr;
+	uint16_t control;
+
+	/* Check whether requested rounding direction is supported */
+	if (round & (~_X87_ROUNDING_MASK))
+		return (-1);
+
+	/* Store the current x87 control word register  */
+	__fnstcw(&control);
+
+	/*
+	 * Set the rounding direction
+	 * Rounding Control is bits 10-11, so shift appropriately
+	 */
+	control &= ~_X87_ROUNDING_MASK;
+	control |= round;
+
+	/* Load the x87 control word register */
+	__fldcw(control);
+
+	/*
+	 * Same for the SSE environment
+	 * Rounding Control is bits 13-14, so shift appropriately
+	 */
+	__stmxcsr(&mxcsr);
+	mxcsr &= ~_SSE_ROUNDING_MASK;
+	mxcsr |= (round << _SSE_ROUND_SHIFT);
+	__ldmxcsr(mxcsr);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The fegetenv() function attempts to store the current floating-point
+ * environment in the object pointed to by envp.
+ */
+int
+fegetenv(fenv_t *envp)
+{
+	_DIAGASSERT(envp != NULL);
+
+	/* Store the current x87 floating-point environment */
+	__fnstenv(envp);
+
+	/* Store the MXCSR register state */
+	__stmxcsr(&envp->mxcsr);
+
+     /*
+      * When an FNSTENV instruction is executed, all pending exceptions are
+      * essentially lost (either the x87 FPU status register is cleared or all
+      * exceptions are masked).
+      *
+      * 8.6 X87 FPU EXCEPTION SYNCHRONIZATION -
+      * Intel(R) 64 and IA-32 Architectures Softare Developer's Manual - Vol 1
+      *
+      */
+	__fldcw(envp->x87.control);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The feholdexcept() function saves the current floating-point environment
+ * in the object pointed to by envp, clears the floating-point status flags, and
+ * then installs a non-stop (continue on floating-point exceptions) mode, if
+ * available, for all floating-point exceptions.
+ */
+int
+feholdexcept(fenv_t *envp)
+{
+	uint32_t mxcsr;
+
+	_DIAGASSERT(envp != NULL);
+
+	/* Store the current x87 floating-point environment */
+	__fnstenv(envp);
+
+	/* Clear all exception flags in FPU */
+	__fnclex();
+
+	/* Store the MXCSR register state */
+	__stmxcsr(&envp->mxcsr);
+
+	/* Clear exception flags in MXCSR XXX */
+	mxcsr = envp->mxcsr;
+	mxcsr &= ~FE_ALL_EXCEPT;
+
+	/* Mask all exceptions */
+	mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
+
+	__ldmxcsr(mxcsr);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The fesetenv() function attempts to establish the floating-point environment
+ * represented by the object pointed to by envp. The argument `envp' points
+ * to an object set by a call to fegetenv() or feholdexcept(), or equal a
+ * floating-point environment macro. The fesetenv() function does not raise
+ * floating-point exceptions, but only installs the state of the floating-point
+ * status flags represented through its argument.
+ */
+int
+fesetenv(const fenv_t *envp)
+{
+	fenv_t fenv;
+
+	_DIAGASSERT(envp != NULL);
+
+	/* Store the x87 floating-point environment */
+	memset(&fenv, 0, sizeof fenv);
+	__fnstenv(&fenv);
+
+	__fe_dfl_env.x87.control = (fenv.x87.control & 0xffff0000)
+	    | (__fe_dfl_env.x87.control & 0x0000ffff);
+	__fe_dfl_env.x87.status = (fenv.x87.status & 0xffff0000)
+	    | (__fe_dfl_env.x87.status & 0x0000ffff);
+	__fe_dfl_env.x87.tag = (fenv.x87.tag & 0xffff0000)
+	    | (__fe_dfl_env.x87.tag & 0x0000ffff);
+	__fe_dfl_env.x87.others[3] = (fenv.x87.others[3] & 0xffff0000)
+	    | (__fe_dfl_env.x87.others[3] & 0x0000ffff);
+	__fldenv(*envp);
+
+	/* Store the MXCSR register */
+	__ldmxcsr(envp->mxcsr);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The feupdateenv() function saves the currently raised floating-point
+ * exceptions in its automatic storage, installs the floating-point environment
+ * represented by the object pointed to by `envp', and then raises the saved
+ * floating-point exceptions. The argument `envp' shall point to an object set
+ * by a call to feholdexcept() or fegetenv(), or equal a floating-point
+ * environment macro.
+ */
+int
+feupdateenv(const fenv_t *envp)
+{
+	fenv_t fenv;
+	uint32_t mxcsr;
+	uint16_t sw;
+
+	_DIAGASSERT(envp != NULL);
+
+	/* Store the x87 floating-point environment */
+	memset(&fenv, 0, sizeof(fenv));
+	__fnstenv(&fenv);
+
+	__fe_dfl_env.x87.control = (fenv.x87.control & 0xffff0000)
+	    | (__fe_dfl_env.x87.control & 0x0000ffff);
+	__fe_dfl_env.x87.status = (fenv.x87.status & 0xffff0000)
+	    | (__fe_dfl_env.x87.status & 0x0000ffff);
+	__fe_dfl_env.x87.tag = (fenv.x87.tag & 0xffff0000)
+	    | (__fe_dfl_env.x87.tag & 0x0000ffff);
+	__fe_dfl_env.x87.others[3] = (fenv.x87.others[3] & 0xffff0000)
+	    | (__fe_dfl_env.x87.others[3] & 0x0000ffff);
+
+	/* Store the x87 status register */
+	__fnstsw(&sw);
+
+	/* Store the MXCSR register */
+	__stmxcsr(&mxcsr);
+
+	/* Install new floating-point environment */
+	fesetenv(envp);
+
+	/* Raise any previously accumulated exceptions */
+	feraiseexcept((sw | mxcsr) & FE_ALL_EXCEPT);
+
+	/* Success */
+	return (0);
+}
+
+/*
+ * The following functions are extentions to the standard
+ */
+int
+feenableexcept(int mask)
+{
+	uint32_t mxcsr, omask;
+	uint16_t control;
+
+	_DIAGASSERT((mask & ~FE_ALL_EXCEPT) == 0);
+	mask &= FE_ALL_EXCEPT;
+
+	__fnstcw(&control);
+	__stmxcsr(&mxcsr);
+
+	omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+	control &= ~mask;
+	__fldcw(control);
+
+	mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
+	__ldmxcsr(mxcsr);
+
+	return (~omask);
+
+}
+
+int
+fedisableexcept(int mask)
+{
+	uint32_t mxcsr, omask;
+	uint16_t control;
+
+	_DIAGASSERT((mask & ~FE_ALL_EXCEPT) == 0);
+
+	__fnstcw(&control);
+	__stmxcsr(&mxcsr);
+
+	omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+	control |= mask;
+	__fldcw(control);
+
+	mxcsr |= mask << _SSE_EMASK_SHIFT;
+	__ldmxcsr(mxcsr);
+
+	return (~omask);
+}
+
+int
+fegetexcept(void)
+{
+	uint16_t control;
+
+	/*
+	 * We assume that the masks for the x87 and the SSE unit are
+	 * the same.
+	 */
+	__fnstcw(&control);
+
+	return (control & FE_ALL_EXCEPT);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libm/man/feclearexcept.3	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,140 @@
+.\"	$NetBSD: feclearexcept.3,v 1.1 2010/07/31 21:47:53 joerg Exp $
+.\" Copyright (c) 2004 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.
+.\"
+.Dd May 8, 2004
+.Dt FECLEAREXCEPT 3
+.Os
+.Sh NAME
+.Nm feclearexcept ,
+.Nm fegetexceptflag ,
+.Nm feraiseexcept ,
+.Nm fesetexceptflag ,
+.Nm fetestexcept
+.Nd floating-point exception flag manipulation
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In fenv.h
+.Fd "#pragma STDC FENV_ACCESS ON"
+.Ft int
+.Fn feclearexcept "int excepts"
+.Ft int
+.Fn fegetexceptflag "fexcept_t *flagp" "int excepts"
+.Ft int
+.Fn feraiseexcept "int excepts"
+.Ft int
+.Fn fesetexceptflag "const fexcept_t *flagp" "int excepts"
+.Ft int
+.Fn fetestexcept "int excepts"
+.Sh DESCRIPTION
+The
+.Fn feclearexcept
+routine clears the floating-point exception flags specified by
+.Fa excepts ,
+whereas
+.Fn feraiseexcept
+raises the specified exceptions.
+Raising an exception causes the corresponding flag to be set,
+and a
+.Dv SIGFPE
+is delivered to the process if the exception is unmasked.
+.Pp
+The
+.Fn fetestexcept
+function determines which flags are currently set, of those specified by
+.Fa excepts .
+.Pp
+The
+.Fn fegetexceptflag
+function stores the state of the exception flags specified in
+.Fa excepts
+in the opaque object pointed to by
+.Fa flagp .
+Similarly,
+.Fn fesetexceptflag
+changes the specified exception flags to reflect the state stored in
+the object pointed to by
+.Fa flagp .
+Note that the flags restored with
+.Fn fesetexceptflag
+must be a (not necessarily proper) subset of the flags recorded by
+a prior call to
+.Fn fegetexceptflag .
+.Pp
+For all of these functions, the possible types of exceptions
+include those described in
+.Xr fenv 3 .
+Some architectures may define other types of floating-point exceptions.
+.Sh IMPLEMENTATION NOTES
+On some architectures, raising an overflow or underflow exception
+also causes an inexact exception to be raised.
+In these cases, the overflow or underflow will be raised first.
+.Pp
+The
+.Fn fegetexceptflag
+and
+.Fn fesetexceptflag
+routines are preferred to
+.Fn fetestexcept
+and
+.Fn feraiseexcept ,
+respectively, for saving and restoring exception flags.
+The latter do not re-raise exceptions and may preserve
+architecture-specific information such as addresses where
+exceptions occurred.
+.Sh RETURN VALUES
+The
+.Fn feclearexcept ,
+.Fn fegetexceptflag ,
+.Fn feraiseexcept ,
+and
+.Fn fesetexceptflag
+functions return 0 upon success, and non-zero otherwise.
+The
+.Fn fetestexcept
+function returns the bitwise OR of the values of the current exception
+flags that were requested.
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr feholdexcept 3 ,
+.Xr fenv 3 ,
+.Xr feupdateenv 3 ,
+.Xr fpgetsticky 3 ,
+.Xr fpresetsticky 3
+.Sh STANDARDS
+The
+.Fn feclearexcept ,
+.Fn fegetexceptflag ,
+.Fn feraiseexcept ,
+.Fn fesetexceptflag ,
+and
+.Fn fetestexcept
+routines conform to
+.St -isoC-99 .
+.Sh HISTORY
+These functions first appeared in
+.Fx 5.3
+and
+.Nx 6.0 .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libm/man/feenableexcept.3	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,97 @@
+.\"	$NetBSD: feenableexcept.3,v 1.1 2010/07/31 21:47:53 joerg Exp $
+.\" Copyright (c) 2004 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.
+.\"
+.Dd March 16, 2005
+.Dt FEENABLEEXCEPT 3
+.Os
+.Sh NAME
+.Nm feenableexcept ,
+.Nm fedisableexcept ,
+.Nm fegetexcept
+.Nd floating-point exception masking
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In fenv.h
+.Fd "#pragma STDC FENV_ACCESS ON"
+.Ft int
+.Fn feenableexcept "int excepts"
+.Ft int
+.Fn fedisableexcept "int excepts"
+.Ft int
+.Fn fegetexcept "void"
+.Sh DESCRIPTION
+The
+.Fn feenableexcept
+and
+.Fn fedisableexcept
+functions
+unmask and mask (respectively) exceptions specified in
+.Fa excepts .
+The
+.Fn fegetexcept
+function
+returns the current exception mask.
+All exceptions are masked by default.
+.Pp
+Floating-point operations that produce unmasked exceptions will trap, and a
+.Dv SIGFPE
+will be delivered to the process.
+By installing a signal handler for
+.Dv SIGFPE ,
+applications can take appropriate action immediately without
+testing the exception flags after every operation.
+Note that the trap may not be immediate, but it should occur
+before the next floating-point instruction is executed.
+.Pp
+For all of these functions, the possible types of exceptions
+include those described in
+.Xr fenv 3 .
+Some architectures may define other types of floating-point exceptions.
+.Sh RETURN VALUES
+The
+.Fn feenableexcept ,
+.Fn fedisableexcept ,
+and
+.Fn fegetexcept
+functions return a bitmap of the exceptions that were unmasked
+prior to the call.
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr feclearexcept 3 ,
+.Xr feholdexcept 3 ,
+.Xr fenv 3 ,
+.Xr feupdateenv 3
+.Sh BUGS
+Functions in the standard library may trigger exceptions multiple
+times as a result of intermediate computations;
+however, they generally do not trigger spurious exceptions.
+.Pp
+No interface is provided to permit exceptions to be handled in
+nontrivial ways.
+There is no uniform way for an exception handler to access
+information about the exception-causing instruction, or
+to determine whether that instruction should be reexecuted
+after returning from the handler.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libm/man/fegetenv.3	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,114 @@
+.\"	$NetBSD: fegetenv.3,v 1.1 2010/07/31 21:47:53 joerg Exp $
+.\" Copyright (c) 2004 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.
+.\"
+.Dd May 8, 2004
+.Dt FEGETENV 3
+.Os
+.Sh NAME
+.Nm fegetenv ,
+.Nm feholdexcept ,
+.Nm fesetenv ,
+.Nm feupdateenv
+.Nd floating-point environment save and restore
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In fenv.h
+.Fd "#pragma STDC FENV_ACCESS ON"
+.Ft int
+.Fn fegetenv "fenv_t *envp"
+.Ft int
+.Fn feholdexcept "fenv_t *envp"
+.Ft int
+.Fn fesetenv "const fenv_t *envp"
+.Ft int
+.Fn feupdateenv "const fenv_t *envp"
+.Sh DESCRIPTION
+The floating-point environment includes exception flags and masks, the
+current rounding mode, and other architecture-specific settings.
+However, it does not include the floating-point register file.
+.Pp
+The
+.Fn fegetenv
+function stores the current floating-point environment in the object
+pointed to by
+.Fa envp ,
+whereas
+.Fn feholdexcept
+saves the current environment, then clears all exception flags
+and masks all floating-point exceptions.
+.Pp
+The
+.Fn fesetenv
+function restores a previously saved environment.
+The
+.Fn feupdateenv
+function restores a saved environment as well, but it also
+raises any exceptions that were set in the environment it
+replaces.
+.Pp
+The
+.Fn feholdexcept
+function is often used with
+.Fn feupdateenv
+or
+.Fn fesetenv
+to suppress spurious exceptions that occur as a result of
+intermediate computations.
+An example in
+.Xr fenv 3
+demonstrates how to do this.
+.Sh RETURN VALUES
+The
+.Fn fegetenv ,
+.Fn feholdexcept ,
+.Fn fesetenv ,
+and
+.Fn feupdateenv
+functions return 0 if they succeed, and non-zero otherwise.
+.Sh SEE ALSO
+.Xr feclearexcept 3 ,
+.Xr fenv 3 ,
+.Xr feraiseexcept 3 ,
+.Xr fesetenv 3 ,
+.Xr fetestexcept 3 ,
+.Xr fpgetmask 3 ,
+.\"Xr fpgetprec 3 ,
+.Xr fpsetmask 3 ,
+.\"Xr fpsetprec 3
+.Sh STANDARDS
+The
+.Fn fegetenv ,
+.Fn feholdexcept ,
+.Fn fesetenv ,
+and
+.Fn feupdateenv
+functions conform to
+.St -isoC-99 .
+.Sh HISTORY
+These routines first appeared in
+.Fx 5.3
+and
+.Nx 6.0 .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libm/man/fegetround.3	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,84 @@
+.\"	$NetBSD: fegetround.3,v 1.1 2010/07/31 21:47:53 joerg Exp $
+.\" Copyright (c) 2004 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.
+.\"
+.Dd May 8, 2004
+.Dt FEGETROUND 3
+.Os
+.Sh NAME
+.Nm fegetround ,
+.Nm fesetround
+.Nd floating-point rounding control
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In fenv.h
+.Fd "#pragma STDC FENV_ACCESS ON"
+.Ft int
+.Fn fegetround void
+.Ft int
+.Fn fesetround "int round"
+.Sh DESCRIPTION
+The
+.Fn fegetround
+function determines the current floating-point rounding mode,
+and the
+.Fn fesetround
+function sets the current rounding mode to
+.Fa round .
+The rounding mode is one of
+.Dv FE_TONEAREST , FE_DOWNWARD , FE_UPWARD ,
+or
+.Dv FE_TOWARDZERO ,
+as described in
+.Xr fenv 3 .
+.Sh RETURN VALUES
+The
+.Fn fegetround
+routine returns the current rounding mode.
+The
+.Fn fesetround
+function returns 0 on success and non-zero otherwise;
+however, the present implementation always succeeds.
+.Sh SEE ALSO
+.Xr fenv 3 ,
+.Xr fpgetround 3 ,
+.Xr fpsetround 3
+.Sh STANDARDS
+The
+.Fn fegetround
+and
+.Fn fesetround
+functions conform to
+.St -isoC-99 .
+.Sh HISTORY
+These routines first appeared in
+.Fx 5.3
+and
+.Nx 6.0 .
+They supersede the non-standard
+.Xr fpgetround 3
+and
+.Xr fpsetround 3
+functions.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libm/man/fenv.3	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,283 @@
+.\"	$NetBSD: fenv.3,v 1.1 2010/07/31 21:47:53 joerg Exp $
+.\" Copyright (c) 2004 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.
+.\"
+.Dd March 16, 2005
+.Dt FENV 3
+.Os
+.Sh NAME
+.Nm feclearexcept ,
+.Nm fegetexceptflag ,
+.Nm feraiseexcept ,
+.Nm fesetexceptflag ,
+.Nm fetestexcept ,
+.Nm fegetround ,
+.Nm fesetround ,
+.Nm fegetenv ,
+.Nm feholdexcept ,
+.Nm fesetenv ,
+.Nm feupdateenv ,
+.Nm feenableexcept ,
+.Nm fedisableexcept ,
+.Nm fegetexcept
+.Nd floating-point environment control
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In fenv.h
+.Fd "#pragma STDC FENV_ACCESS ON"
+.Ft int
+.Fn feclearexcept "int excepts"
+.Ft int
+.Fn fegetexceptflag "fexcept_t *flagp" "int excepts"
+.Ft int
+.Fn feraiseexcept "int excepts"
+.Ft int
+.Fn fesetexceptflag "const fexcept_t *flagp" "int excepts"
+.Ft int
+.Fn fetestexcept "int excepts"
+.Ft int
+.Fn fegetround void
+.Ft int
+.Fn fesetround "int round"
+.Ft int
+.Fn fegetenv "fenv_t *envp"
+.Ft int
+.Fn feholdexcept "fenv_t *envp"
+.Ft int
+.Fn fesetenv "const fenv_t *envp"
+.Ft int
+.Fn feupdateenv "const fenv_t *envp"
+.Ft int
+.Fn feenableexcept "int excepts"
+.Ft int
+.Fn fedisableexcept "int excepts"
+.Ft int
+.Fn fegetexcept void
+.Sh DESCRIPTION
+The
+.In fenv.h
+routines manipulate the floating-point environment,
+which includes the exception flags and rounding modes defined in
+.St -ieee754 .
+.Ss Exceptions
+Exception flags are set as side-effects of floating-point arithmetic
+operations and math library routines, and they remain set until
+explicitly cleared.
+The following macros expand to bit flags of type
+.Vt int
+representing the five standard floating-point exceptions.
+.Bl -tag -width ".Dv FE_DIVBYZERO"
+.It Dv FE_DIVBYZERO
+A divide-by-zero exception occurs when the program attempts to
+divide a finite non-zero number by zero.
+.It Dv FE_INEXACT
+An inexact exception is raised whenever there is a loss of precision
+due to rounding.
+.It Dv FE_INVALID
+Invalid operation exceptions occur when a program attempts to
+perform calculations for which there is no reasonable representable
+answer.
+For instance, subtraction of infinities, division of zero by zero,
+ordered comparison involving \*(Nas, and taking the square root of a
+negative number are all invalid operations.
+.It Dv FE_OVERFLOW
+An overflow exception occurs when the magnitude of the result of a
+computation is too large to fit in the destination type.
+.It Dv FE_UNDERFLOW
+Underflow occurs when the result of a computation is too close to zero
+to be represented as a non-zero value in the destination type.
+.El
+.Pp
+Additionally, the
+.Dv FE_ALL_EXCEPT
+macro expands to the bitwise OR of the above flags and any
+architecture-specific flags.
+Combinations of these flags are passed to the
+.Fn feclearexcept ,
+.Fn fegetexceptflag ,
+.Fn feraiseexcept ,
+.Fn fesetexceptflag ,
+and
+.Fn fetestexcept
+functions to clear, save, raise, restore, and examine the
+processor's floating-point exception flags, respectively.
+.Pp
+Exceptions may be
+.Em unmasked
+with
+.Fn feenableexcept
+and masked with
+.Fn fedisableexcept .
+Unmasked exceptions cause a trap when they are produced, and
+all exceptions are masked by default.
+The current mask can be tested with
+.Fn fegetexcept .
+.Ss Rounding Modes
+.St -ieee754
+specifies four rounding modes.
+These modes control the direction in which results are rounded
+from their exact values in order to fit them into binary
+floating-point variables.
+The four modes correspond with the following symbolic constants.
+.Bl -tag -width ".Dv FE_TOWARDZERO"
+.It Dv FE_TONEAREST
+Results are rounded to the closest representable value.
+If the exact result is exactly half way between two representable
+values, the value whose last binary digit is even (zero) is chosen.
+This is the default mode.
+.It Dv FE_DOWNWARD
+Results are rounded towards negative \*[If].
+.It Dv FE_UPWARD
+Results are rounded towards positive \*[If].
+.It Dv FE_TOWARDZERO
+Results are rounded towards zero.
+.El
+.Pp
+The
+.Fn fegetround
+and
+.Fn fesetround
+functions query and set the rounding mode.
+.Ss Environment Control
+The
+.Fn fegetenv
+and
+.Fn fesetenv
+functions save and restore the floating-point environment,
+which includes exception flags, the current exception mask,
+the rounding mode, and possibly other implementation-specific
+state.
+The
+.Fn feholdexcept
+function behaves like
+.Fn fegetenv ,
+but with the additional effect of clearing the exception flags and
+installing a
+.Em non-stop
+mode.
+In non-stop mode, floating-point operations will set exception flags
+as usual, but no
+.Dv SIGFPE
+signals will be generated as a result.
+Non-stop mode is the default, but it may be altered by
+non-standard mechanisms.
+.\" XXX Mention fe[gs]etmask() here after the interface is finalized
+.\" XXX and ready to be officially documented.
+The
+.Fn feupdateenv
+function restores a saved environment similarly to
+.Fn fesetenv ,
+but it also re-raises any floating-point exceptions from the old
+environment.
+.Pp
+The macro
+.Dv FE_DFL_ENV
+expands to a pointer to the default environment.
+.Sh EXAMPLES
+The following routine computes the square root function.
+It explicitly raises an invalid exception on appropriate inputs using
+.Fn feraiseexcept .
+It also defers inexact exceptions while it computes intermediate
+values, and then it allows an inexact exception to be raised only if
+the final answer is inexact.
+.Bd -literal -offset indent
+#pragma STDC FENV_ACCESS ON
+double sqrt(double n) {
+	double x = 1.0;
+	fenv_t env;
+
+	if (isnan(n) || n < 0.0) {
+		feraiseexcept(FE_INVALID);
+		return (NAN);
+	}
+	if (isinf(n) || n == 0.0)
+		return (n);
+	feholdexcept(&env);
+	while (fabs((x * x) - n) > DBL_EPSILON * 2 * x)
+		x = (x / 2) + (n / (2 * x));
+	if (x * x == n)
+		feclearexcept(FE_INEXACT);
+	feupdateenv(&env);
+	return (x);
+}
+.Ed
+.Sh SEE ALSO
+.Xr c99 1 ,
+.Xr feclearexcept 3 ,
+.Xr fedisableexcept 3 ,
+.Xr feenableexcept 3 ,
+.Xr fegetenv 3 ,
+.Xr fegetexcept 3 ,
+.Xr fegetexceptflag 3 ,
+.Xr fegetround 3 ,
+.Xr feholdexcept 3 ,
+.Xr feraiseexcept 3 ,
+.Xr fesetenv 3 ,
+.Xr fesetexceptflag 3 ,
+.Xr fesetround 3 ,
+.Xr fetestexcept 3 ,
+.Xr feupdateenv 3 ,
+.\"Xr fpgetprec 3 ,
+.\"Xr fpsetprec 3
+.Sh STANDARDS
+Except as noted below,
+.In fenv.h
+conforms to
+.St -isoC-99 .
+The
+.Fn feenableexcept ,
+.Fn fedisableexcept ,
+and
+.Fn fegetexcept
+routines are extensions.
+.Sh HISTORY
+The
+.In fenv.h
+header first appeared in
+.Fx 5.3
+and
+.Nx 6.0 .
+It supersedes the non-standard routines defined in
+.In ieeefp.h
+and documented in
+.Xr fpgetround 3 .
+.Sh CAVEATS
+The FENV_ACCESS pragma can be enabled with
+.Dl "#pragma STDC FENV_ACCESS ON"
+and disabled with the
+.Dl "#pragma STDC FENV_ACCESS OFF"
+directive.
+This lexically-scoped annotation tells the compiler that the program
+may access the floating-point environment, so optimizations that would
+violate strict IEEE-754 semantics are disabled.
+If execution reaches a block of code for which
+.Dv FENV_ACCESS
+is off, the floating-point environment will become undefined.
+.Sh BUGS
+The
+.Dv FENV_ACCESS
+pragma is unimplemented in the system compiler.
+However, non-constant expressions generally produce the correct
+side-effects at low optimization levels.
--- a/sys/arch/amd64/include/Makefile	Sat Jul 31 21:21:17 2010 +0000
+++ b/sys/arch/amd64/include/Makefile	Sat Jul 31 21:47:52 2010 +0000
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.10 2008/01/04 23:04:53 dsl Exp $
+#	$NetBSD: Makefile,v 1.11 2010/07/31 21:47:53 joerg Exp $
 
 INCSDIR= /usr/include/amd64
 
@@ -9,7 +9,7 @@
 	elf_machdep.h endian.h endian_machdep.h \
 	float.h fpu.h frame.h frame_regs.h \
 	gdt.h \
-	ieee.h ieeefp.h \
+	ieee.h ieeefp.h fenv.h \
 	int_const.h int_fmtio.h int_limits.h int_mwgwtypes.h int_types.h \
 	intr.h intrdefs.h \
 	joystick.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/amd64/include/fenv.h	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,107 @@
+/*	$NetBSD: fenv.h,v 1.1 2010/07/31 21:47:54 joerg Exp $	*/
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das (at) 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.
+ */
+
+#ifndef _AMD64_FENV_H_
+#define _AMD64_FENV_H_
+
+#include <sys/stdint.h>
+#include <machine/fpu.h>
+
+/*
+ * Each symbol representing a floating point exception expands to an integer
+ * constant expression with values, such that bitwise-inclusive ORs of _all
+ * combinations_ of the constants result in distinct values.
+ *
+ * We use such values that allow direct bitwise operations on FPU/SSE registers.
+ */
+#define	FE_INVALID	0x01	/* 000000000001 */
+#define	FE_DENORMAL	0x02	/* 000000000010 */
+#define	FE_DIVBYZERO	0x04	/* 000000000100 */
+#define	FE_OVERFLOW	0x08	/* 000000001000 */
+#define	FE_UNDERFLOW	0x10	/* 000000010000 */
+#define	FE_INEXACT	0x20	/* 000000100000 */
+
+/*
+ * The following symbol is simply the bitwise-inclusive OR of all floating-point
+ * exception constants defined above
+ */
+#define FE_ALL_EXCEPT   \
+  (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+/*
+ * Each symbol representing the rounding direction, expands to an integer
+ * constant expression whose value is distinct non-negative value.
+ *
+ * We use such values that allow direct bitwise operations on FPU/SSE registers.
+ */
+#define	FE_TONEAREST	0x000	/* 000000000000 */
+#define	FE_DOWNWARD	0x400	/* 010000000000 */
+#define	FE_UPWARD	0x800	/* 100000000000 */
+#define	FE_TOWARDZERO	0xC00	/* 110000000000 */
+
+/*
+ * As compared to the x87 control word, the SSE unit's control word
+ * has the rounding control bits offset by 3 and the exception mask
+ * bits offset by 7.
+ */
+#define	_X87_ROUNDING_MASK	0xC00		/* 110000000000 */
+#define	_SSE_ROUNDING_MASK	(0xC00 << 3)
+#define	_SSE_ROUND_SHIFT	3
+#define	_SSE_EMASK_SHIFT	7
+
+/*
+ * fenv_t represents the entire floating-point environment
+ */
+typedef struct {
+	struct {
+		uint32_t control;	/* Control word register */
+		uint32_t status;	/* Status word register */
+		uint32_t tag;		/* Tag word register */
+		uint32_t others[4];	/* EIP, Pointer Selector, etc */
+	} x87;
+
+	uint32_t mxcsr;			/* Control and status register */
+} fenv_t;
+
+extern fenv_t		__fe_dfl_env;
+#define FE_DFL_ENV      ((const fenv_t *) &__fe_dfl_env)
+
+/*
+ * fexcept_t represents the floating-point status flags collectively, including
+ * any status the implementation associates with the flags.
+ *
+ * A floating-point status flag is a system variable whose value is set (but
+ * never cleared) when a floating-point exception is raised, which occurs as a
+ * side effect of exceptional floating-point arithmetic to provide auxiliary
+ * information.
+ *
+ * A floating-point control mode is a system variable whose value may be set by
+ * the user to affect the subsequent behavior of floating-point arithmetic.
+ */
+typedef uint32_t fexcept_t;
+
+#endif /* ! _AMD64_FENV_H_ */
--- a/sys/arch/i386/include/Makefile	Sat Jul 31 21:21:17 2010 +0000
+++ b/sys/arch/i386/include/Makefile	Sat Jul 31 21:47:52 2010 +0000
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.36 2007/12/20 23:46:12 ad Exp $
+#	$NetBSD: Makefile,v 1.37 2010/07/31 21:47:54 joerg Exp $
 
 INCSDIR= /usr/include/i386
 
@@ -7,7 +7,7 @@
 	cdefs.h cpu.h cpufunc.h cputypes.h \
 	disklabel.h \
 	elf_machdep.h endian.h endian_machdep.h \
-	float.h frame.h freebsd_machdep.h \
+	fenv.h float.h frame.h freebsd_machdep.h \
 	gdt.h \
 	ibcs2_machdep.h ieee.h ieeefp.h \
 	int_const.h int_fmtio.h int_limits.h int_mwgwtypes.h int_types.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/i386/include/fenv.h	Sat Jul 31 21:47:52 2010 +0000
@@ -0,0 +1,116 @@
+/*	$NetBSD: fenv.h,v 1.1 2010/07/31 21:47:54 joerg Exp $	*/
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das (at) 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.
+ */
+
+#ifndef	_X86_FENV_H_
+#define	_X86_FENV_H_
+
+#include <sys/stdint.h>
+#include <i386/npx.h>
+
+/*
+ * Each symbol representing a floating point exception expands to an integer
+ * constant expression with values, such that bitwise-inclusive ORs of _all
+ * combinations_ of the constants result in distinct values.
+ *
+ * We use such values that allow direct bitwise operations on FPU/SSE registers.
+ */
+#define	FE_INVALID	0x01	/* 000000000001 */
+#define	FE_DENORMAL	0x02	/* 000000000010 */
+#define	FE_DIVBYZERO	0x04	/* 000000000100 */
+#define	FE_OVERFLOW	0x08	/* 000000001000 */
+#define	FE_UNDERFLOW	0x10	/* 000000010000 */
+#define	FE_INEXACT	0x20	/* 000000100000 */
+
+/*
+ * The following symbol is simply the bitwise-inclusive OR of all floating-point
+ * exception constants defined above.
+ */
+#define FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \
+			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+/*
+ * Each symbol representing the rounding direction, expands to an integer
+ * constant expression whose value is distinct non-negative value.
+ *
+ * We use such values that allow direct bitwise operations on FPU/SSE registers.
+ */
+#define	FE_TONEAREST	0x000	/* 000000000000 */
+#define	FE_DOWNWARD	0x400	/* 010000000000 */
+#define	FE_UPWARD	0x800	/* 100000000000 */
+#define	FE_TOWARDZERO	0xC00	/* 110000000000 */
+
+/*
+ * As compared to the x87 control word, the SSE unit's control has the rounding
+ * control bits offset by 3 and the exception mask bits offset by 7
+ */
+#define	__X87_ROUND_MASK	0xC00		/* 110000000000 */
+#define	__SSE_ROUND_SHIFT	3
+#define	__SSE_EMASK_SHIFT	7
+
+/*
+ * fenv_t represents the entire floating-point environment
+ */
+typedef struct {
+	struct {
+		uint16_t control;	/* Control word register */
+		uint16_t unused1;
+		uint16_t status;	/* Status word register */
+		uint16_t unused2;
+		uint16_t tag;		/* Tag word register */
+		uint16_t unused3;
+		uint32_t others[4];	/* EIP, Pointer Selector, etc */
+	} x87;
+		
+	uint32_t mxcsr;			/* Control and status register */
+} fenv_t;
+
+/*
+ * The following constant represents the default floating-point environment
+ * (that is, the one installed at program startup) and has type pointer to
+ * const-qualified fenv_t.
+ *
+ * It can be used as an argument to the functions within the <fenv.h> header
+ * that manage the floating-point environment.
+ */
+extern  fenv_t		__fe_dfl_env;
+#define FE_DFL_ENV      ((const fenv_t *) &__fe_dfl_env)
+
+/*
+ * fexcept_t represents the floating-point status flags collectively, including
+ * any status the implementation associates with the flags.
+ *
+ * A floating-point status flag is a system variable whose value is set (but
+ * never cleared) when a floating-point exception is raised, which occurs as a
+ * side effect of exceptional floating-point arithmetic to provide auxiliary
+ * information.
+ *
+ * A floating-point control mode is a system variable whose value may be set by
+ * the user to affect the subsequent behavior of floating-point arithmetic.
+ */
+typedef uint32_t fexcept_t;
+
+#endif	/* ! _X86_FENV_H_ */
--- a/sys/arch/i386/include/npx.h	Sat Jul 31 21:21:17 2010 +0000
+++ b/sys/arch/i386/include/npx.h	Sat Jul 31 21:47:52 2010 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npx.h,v 1.24 2010/07/25 19:19:57 christos Exp $	*/
+/*	$NetBSD: npx.h,v 1.25 2010/07/31 21:47:54 joerg Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -44,25 +44,25 @@
 
 /* Environment information of floating point unit */
 struct env87 {
-	long	en_cw;		/* control word (16bits) */
-	long	en_sw;		/* status word (16bits) */
-	long	en_tw;		/* tag word (16bits) */
-	long	en_fip;		/* floating point instruction pointer */
-	u_short	en_fcs;		/* floating code segment selector */
-	u_short	en_opcode;	/* opcode last executed (11 bits ) */
-	long	en_foo;		/* floating operand offset */
-	long	en_fos;		/* floating operand segment selector */
+	long	 en_cw;		/* control word (16bits) */
+	long	 en_sw;		/* status word (16bits) */
+	long	 en_tw;		/* tag word (16bits) */
+	long	 en_fip;	/* floating point instruction pointer */
+	uint16_t en_fcs;	/* floating code segment selector */
+	uint16_t en_opcode;	/* opcode last executed (11 bits ) */
+	long	 en_foo;	/* floating operand offset */
+	long	 en_fos;	/* floating operand segment selector */
 };
 
 /* Contents of each floating point accumulator */
 struct fpacc87 {
 #ifdef dontdef	/* too unportable */
-	u_long	fp_mantlo;	/* mantissa low (31:0) */
-	u_long	fp_manthi;	/* mantissa high (63:32) */
-	int	fp_exp:15;	/* exponent */
-	int	fp_sgn:1;	/* mantissa sign */
+	uint32_t fp_mantlo;	/* mantissa low (31:0) */
+	uint32_t fp_manthi;	/* mantissa high (63:32) */
+	int	 fp_exp:15;	/* exponent */
+	int	 fp_sgn:1;	/* mantissa sign */
 #else
-	u_char	fp_bytes[10];
+	uint8_t	 fp_bytes[10];
 #endif
 };
 
@@ -71,9 +71,9 @@
 	struct	env87 sv_env;		/* floating point control/status */
 	struct	fpacc87	sv_ac[8];	/* accumulator contents, 0-7 */
 #ifndef dontdef
-	u_long	sv_ex_sw;	/* status word for last exception (was pad) */
-	u_long	sv_ex_tw;	/* tag word for last exception (was pad) */
-	u_char	sv_pad[8 * 2 - 2 * 4];	/* bogus historical padding */
+	uint32_t sv_ex_sw;	/* status word for last exception (was pad) */
+	uint32_t sv_ex_tw;	/* tag word for last exception (was pad) */
+	uint8_t	 sv_pad[8 * 2 - 2 * 4];	/* bogus historical padding */
 #endif
 };
 
--- a/sys/arch/x86/include/ieeefp.h	Sat Jul 31 21:21:17 2010 +0000
+++ b/sys/arch/x86/include/ieeefp.h	Sat Jul 31 21:47:52 2010 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: ieeefp.h,v 1.2 2008/08/05 16:47:42 matt Exp $	*/
+/*	$NetBSD: ieeefp.h,v 1.3 2010/07/31 21:47:54 joerg Exp $	*/
 
 /* 
  * Written by J.T. Conklin, Apr 6, 1995
@@ -9,27 +9,7 @@
 #define _X86_IEEEFP_H_
 
 #include <sys/featuretest.h>
-
-#if defined(_NETBSD_SOURCE) || defined(_ISOC99_SOURCE)
-
-typedef int fenv_t;
-typedef int fexcept_t;
-
-#define	FE_INVALID	0x01	/* invalid operation exception */
-#define	FE_DENORMAL	0x02	/* denormalization exception */
-#define	FE_DIVBYZERO	0x04	/* divide-by-zero exception */
-#define	FE_OVERFLOW	0x08	/* underflow exception */
-#define	FE_UNDERFLOW	0x10	/* overflow exception */
-#define	FE_INEXACT	0x20	/* imprecise (loss of precision) */
-
-#define	FE_ALL_EXCEPT	0x3f
-
-#define	FE_TONEAREST	0	/* round to nearest representable number */
-#define	FE_DOWNWARD	1	/* round toward negative infinity */
-#define	FE_UPWARD	2	/* round toward positive infinity */
-#define	FE_TOWARDZERO	3	/* round to zero (truncate) */
-
-#if !defined(_ISOC99_SOURCE)
+#include <machine/fenv.h>
 
 typedef int fp_except;
 #define FP_X_INV	FE_INVALID	/* invalid operation exception */
@@ -46,8 +26,4 @@
     FP_RZ=FE_TOWARDZERO		/* round to zero (truncate) */
 } fp_rnd;
 
-#endif /* !_ISOC99_SOURCE */
-
-#endif /* _NETBSD_SOURCE || _ISOC99_SOURCE */
-
 #endif /* _X86_IEEEFP_H_ */