Index: lib/msun/Makefile =================================================================== RCS file: /cvs/src/lib/msun/Makefile,v retrieving revision 1.39 diff -u -r1.39 Makefile --- Makefile 7 May 2004 18:56:31 -0000 1.39 +++ Makefile 1 Jun 2004 17:45:33 -0000 @@ -42,7 +42,6 @@ # .if ${MACHINE_ARCH} == "alpha" -ARCH= alpha ARCH_SRCS = s_copysign.S s_copysignf.S # XXX Comment from NetBSD/Alpha: # XXX LINT SIGFPEs in e_exp.c's strtod(). FP underflow/denorm software @@ -59,6 +58,8 @@ # ARCH_SRCS+= s_log1p.S .endif +ARCH?= ${MACHINE_ARCH} + .PATH: ${.CURDIR}/bsdsrc .PATH: ${.CURDIR}/man .PATH: ${.CURDIR}/src @@ -75,7 +76,7 @@ e_jn.c e_jnf.c e_lgamma.c e_lgamma_r.c e_lgammaf.c e_lgammaf_r.c \ e_log.c e_log10.c e_log10f.c e_logf.c e_pow.c e_powf.c e_rem_pio2.c \ e_rem_pio2f.c e_remainder.c e_remainderf.c e_scalb.c e_scalbf.c \ - e_sinh.c e_sinhf.c e_sqrt.c e_sqrtf.c \ + e_sinh.c e_sinhf.c e_sqrt.c e_sqrtf.c fenv.c \ k_cos.c k_cosf.c k_rem_pio2.c k_rem_pio2f.c k_sin.c k_sinf.c \ k_standard.c k_tan.c k_tanf.c \ s_asinh.c s_asinhf.c s_atan.c s_atanf.c s_cbrt.c s_cbrtf.c s_ceil.c \ @@ -108,8 +109,8 @@ #COMMON_SRCS+= s_fabs.c s_frexp.c s_isnan.c s_ldexp.c s_modf.c # Exclude the generic versions of what we provide in the MD area. -.if defined(ARCH_SRCS) .PATH: ${.CURDIR}/${ARCH} +.if defined(ARCH_SRCS) .for i in ${ARCH_SRCS} COMMON_SRCS:= ${COMMON_SRCS:N${i:R}.c} .endfor @@ -117,10 +118,11 @@ SRCS= ${COMMON_SRCS} ${ARCH_SRCS} -INCS= math.h +INCS= fenv.h math.h MAN= acos.3 acosh.3 asin.3 asinh.3 atan.3 atan2.3 atanh.3 ceil.3 \ - cos.3 cosh.3 erf.3 exp.3 fabs.3 floor.3 fmod.3 hypot.3 ieee.3 \ + cos.3 cosh.3 erf.3 exp.3 fabs.3 feclearexcept.3 fegetenv.3 \ + fegetround.3 fenv.3 floor.3 fmod.3 hypot.3 ieee.3 \ ieee_test.3 j0.3 lgamma.3 math.3 rint.3 sin.3 sinh.3 sqrt.3 \ tan.3 tanh.3 @@ -140,6 +142,11 @@ exp.3 expm1f.3 exp.3 logf.3 exp.3 powf.3 \ exp.3 log10f.3 exp.3 log1pf.3 MLINKS+=fabs.3 fabsf.3 fabs.3 fabsl.3 +MLINKS+=feclearexcept.3 fegetexceptflag.3 feclearexcept.3 feraiseexcept.3 \ + feclearexcept.3 fesetexceptflag.3 feclearexcept.3 fetestexcept.3 +MLINKS+=fegetenv.3 feholdexcept.3 fegetenv.3 fesetenv.3 \ + fegetenv.3 feupdateenv.3 +MLINKS+=fegetround.3 fesetround.3 MLINKS+=floor.3 floorf.3 MLINKS+=fmod.3 fmodf.3 MLINKS+=hypot.3 cabs.3 hypot.3 cabsf.3 hypot.3 hypotf.3 Index: lib/msun/alpha/fenv.c =================================================================== RCS file: lib/msun/alpha/fenv.c diff -N lib/msun/alpha/fenv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/alpha/fenv.c 31 May 2004 08:20:17 -0000 @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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$ + */ + +#include +#include +#include + +const fenv_t __fe_dfl_env = 0x680e000000000000ULL; + +struct mask_args { + fenv_t mask; +}; + +/* + * The lower 49 bits of the FPCR are unused by the hardware, so we use + * the lower order bits to store the kernel's idea of the FP mask as + * described in the Alpha Architecture Manual. + */ +int +fegetenv(fenv_t *envp) +{ + struct mask_args p; + union __fpcr r; + + /* + * The syscall acts as an implicit exception barrier, so we + * only need to issue an excb after the mf_fpcr to ensure that + * the read is executed before any subsequent FP ops. + */ + sysarch(ALPHA_GET_FPMASK, (char *)&p); + __mf_fpcr(&r.__d); + *envp = r.__bits | p.mask; + __excb(); + return (0); +} + +int +feholdexcept(fenv_t *envp) +{ + struct mask_args p; + union __fpcr r; + + sysarch(ALPHA_GET_FPMASK, (char *)&p); + __mf_fpcr(&r.__d); + *envp = r.__bits | p.mask; + r.__bits &= ~((fenv_t)FE_ALL_EXCEPT << _FPUSW_SHIFT); + __mt_fpcr(r.__d); + if (p.mask & FE_ALL_EXCEPT) { + p.mask = 0; + sysarch(ALPHA_SET_FPMASK, &p); + } + __excb(); + return (0); +} + +int +fesetenv(const fenv_t *envp) +{ + struct mask_args p; + union __fpcr r; + + p.mask = *envp & FE_ALL_EXCEPT; + sysarch(ALPHA_SET_FPMASK, &p); + r.__bits = *envp & ~FE_ALL_EXCEPT; + __mt_fpcr(r.__d); + __excb(); + return (0); +} + +int +feupdateenv(const fenv_t *envp) +{ + struct mask_args p; + union __fpcr oldr, newr; + + p.mask = *envp & FE_ALL_EXCEPT; + sysarch(ALPHA_SET_FPMASK, &p); + __mf_fpcr(&oldr.__d); + newr.__bits = *envp & ~FE_ALL_EXCEPT; + __excb(); + __mt_fpcr(newr.__d); + feraiseexcept((oldr.__bits >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); + return (0); +} + +int +__fesetmask(int mask) +{ + struct mask_args p; + + p.mask = mask; + sysarch(ALPHA_SET_FPMASK, &p); + return (p.mask); +} + +int +__fegetmask(void) +{ + struct mask_args p; + + sysarch(ALPHA_GET_FPMASK, &p); + return (p.mask); +} + +__weak_reference(__fesetmask, fesetmask); +__weak_reference(__fegetmask, fegetmask); Index: lib/msun/alpha/fenv.h =================================================================== RCS file: lib/msun/alpha/fenv.h diff -N lib/msun/alpha/fenv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/alpha/fenv.h 31 May 2004 08:20:19 -0000 @@ -0,0 +1,184 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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_ +#define _FENV_H_ + +#include + +typedef __uint64_t fenv_t; +typedef __uint16_t fexcept_t; + +/* Exception flags */ +#define FE_INVALID 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 +#define FE_INTOVF 0x40 /* not maskable */ +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INTOVF | \ + FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +/* Rounding modes */ +#define FE_TOWARDZERO 0x00 +#define FE_DOWNWARD 0x01 +#define FE_TONEAREST 0x02 +#define FE_UPWARD 0x03 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) +#define _ROUND_SHIFT 58 + +#define _FPUSW_SHIFT 51 + +#define __excb() __asm __volatile("excb") +#define __mf_fpcr(__cw) __asm ("mf_fpcr %0" : "=f" (*(__cw))) +#define __mt_fpcr(__cw) __asm __volatile("mt_fpcr %0" : : "f" (__cw)) + +union __fpcr { + double __d; + fenv_t __bits; +}; + +__BEGIN_DECLS + +/* Default floating-point environment */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +static __inline int +feclearexcept(int __excepts) +{ + union __fpcr __r; + + __excb(); + __mf_fpcr(&__r.__d); + __r.__bits &= ~((fenv_t)__excepts << _FPUSW_SHIFT); + __mt_fpcr(__r.__d); + __excb(); + return (0); +} + +static __inline int +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + union __fpcr __r; + + __excb(); + __mf_fpcr(&__r.__d); + __excb(); + *__flagp = (__r.__bits >> _FPUSW_SHIFT) & __excepts; + return (0); +} + +static __inline int +fesetexceptflag(const fexcept_t *__flagp, int __excepts) +{ + union __fpcr __r; + fenv_t __xflag, __xexcepts; + + __xflag = (fenv_t)*__flagp << _FPUSW_SHIFT; + __xexcepts = (fenv_t)__excepts << _FPUSW_SHIFT; + __excb(); + __mf_fpcr(&__r.__d); + __r.__bits &= ~__xexcepts; + __r.__bits |= __xflag & __xexcepts; + __mt_fpcr(__r.__d); + __excb(); + return (0); +} + +static __inline int +feraiseexcept(int __excepts) +{ + + /* + * XXX Generating exceptions this way does not actually invoke + * a userland trap handler when enabled, but neither do + * arithmetic operations as far as I can tell. Perhaps there + * are more bugs in the kernel trap handler. + */ + fexcept_t __ex = __excepts; + fesetexceptflag(&__ex, __excepts); + return (0); +} + +static __inline int +fetestexcept(int __excepts) +{ + union __fpcr __r; + + __excb(); + __mf_fpcr(&__r.__d); + __excb(); + return ((__r.__bits >> _FPUSW_SHIFT) & __excepts); +} + +static __inline int +fegetround(void) +{ + union __fpcr __r; + + /* + * No exception barriers should be required here if we assume + * that only fesetround() can change the rounding mode. + */ + __mf_fpcr(&__r.__d); + return ((int)(__r.__bits >> _ROUND_SHIFT) & _ROUND_MASK); +} + +static __inline int +fesetround(int __round) +{ + union __fpcr __r; + + if (__round & ~_ROUND_MASK) + return (-1); + __excb(); + __mf_fpcr(&__r.__d); + __r.__bits &= ~((fenv_t)_ROUND_MASK << _ROUND_SHIFT); + __r.__bits |= (fenv_t)__round << _ROUND_SHIFT; + __mt_fpcr(__r.__d); + __excb(); + return (0); +} + +int fegetenv(fenv_t *__envp); +int feholdexcept(fenv_t *__envp); +int fesetenv(const fenv_t *__envp); +int feupdateenv(const fenv_t *__envp); + +#if __BSD_VISIBLE + +int fesetmask(int __mask); +int fegetmask(void); + +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* !_FENV_H_ */ Index: lib/msun/amd64/fenv.c =================================================================== RCS file: lib/msun/amd64/fenv.c diff -N lib/msun/amd64/fenv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/amd64/fenv.c 1 Jun 2004 09:10:50 -0000 @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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$ + */ + +#include +#include +#include +#include + +const fenv_t __fe_dfl_env = { + { 0xffff0000 | __INITIAL_FPUCW__, + 0xffff0000, + 0xffffffff, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff } + }, + __INITIAL_MXCSR__ +}; + +int +fesetexceptflag(const fexcept_t *flagp, int excepts) +{ + fenv_t env; + + __fnstenv(&env.__x87); + env.__x87.__status &= ~excepts; + env.__x87.__status |= *flagp & excepts; + __fldenv(env.__x87); + + __stmxcsr(&env.__mxcsr); + env.__mxcsr &= ~excepts; + env.__mxcsr |= *flagp & excepts; + __ldmxcsr(env.__mxcsr); + + return (0); +} + +int +feraiseexcept(int excepts) +{ + fexcept_t ex = excepts; + + fesetexceptflag(&ex, excepts); + __fwait(); + return (0); +} + +int +fegetenv(fenv_t *envp) +{ + int control; + + /* + * fnstenv masks all exceptions, so we need to save and + * restore the control word to avoid this side effect. + */ + __fnstcw(&control); + __fnstenv(&envp->__x87); + __stmxcsr(&envp->__mxcsr); + __fldcw(control); + return (0); +} + +int +feholdexcept(fenv_t *envp) +{ + int mxcsr; + + __stmxcsr(&mxcsr); + __fnstenv(&envp->__x87); + __fnclex(); + envp->__mxcsr = mxcsr; + mxcsr &= FE_ALL_EXCEPT; + mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT; + __ldmxcsr(mxcsr); + return (0); +} + +int +feupdateenv(const fenv_t *envp) +{ + int mxcsr, status; + + __fnstsw(&status); + __stmxcsr(&mxcsr); + fesetenv(envp); + feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT); + return (0); +} + +int +__fesetmask(int mask) +{ + int mxcsr, control, omask; + + __fnstcw(&control); + __stmxcsr(&mxcsr); + omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; + control = (control | FE_ALL_EXCEPT) & ~mask; + __fldcw(control); + mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT; + mxcsr &= ~(mask << _SSE_EMASK_SHIFT); + __ldmxcsr(mxcsr); + return (~omask); +} + +__weak_reference(__fesetmask, fesetmask); Index: lib/msun/amd64/fenv.h =================================================================== RCS file: lib/msun/amd64/fenv.h diff -N lib/msun/amd64/fenv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/amd64/fenv.h 1 Jun 2004 09:03:39 -0000 @@ -0,0 +1,202 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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_ +#define _FENV_H_ + +#include +#include + +typedef struct { + struct { + __uint32_t __control; + __uint32_t __status; + __uint32_t __tag; + char __other[16]; + } __x87; + __uint32_t __mxcsr; +} fenv_t; + +typedef __uint16_t fexcept_t; + +/* Exception flags */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ + FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +/* Rounding modes */ +#define FE_TONEAREST 0x0000 +#define FE_DOWNWARD 0x0400 +#define FE_UPWARD 0x0800 +#define FE_TOWARDZERO 0x0c00 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) + +/* + * 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 _SSE_ROUND_SHIFT 3 +#define _SSE_EMASK_SHIFT 7 + +__BEGIN_DECLS + +/* Default floating-point environment */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw)) +#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env)) +#define __fnclex() __asm __volatile("fnclex") +#define __fnstenv(__env) __asm("fnstenv %0" : "=m" (*(__env))) +#define __fnstcw(__cw) __asm("fnstcw %0" : "=m" (*(__cw))) +#define __fnstsw(__sw) __asm("fnstsw %0" : "=am" (*(__sw))) +#define __fwait() __asm __volatile("fwait") +#define __ldmxcsr(__csr) __asm __volatile("ldmxcsr %0" : : "m" (__csr)) +#define __stmxcsr(__csr) __asm("stmxcsr %0" : "=m" (*(__csr))) + +static __inline int +feclearexcept(int __excepts) +{ + fenv_t __env; + + if (__excepts == FE_ALL_EXCEPT) { + __fnclex(); + } else { + __fnstenv(&__env.__x87); + __env.__x87.__status &= ~__excepts; + __fldenv(__env.__x87); + } + __stmxcsr(&__env.__mxcsr); + __env.__mxcsr &= ~__excepts; + __ldmxcsr(__env.__mxcsr); + return (0); +} + +static __inline int +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + int __mxcsr, __status; + + __stmxcsr(&__mxcsr); + __fnstsw(&__status); + *__flagp = (__mxcsr | __status) & __excepts; + return (0); +} + +int fesetexceptflag(const fexcept_t *__flagp, int __excepts); +int feraiseexcept(int __excepts); + +static __inline int +fetestexcept(int __excepts) +{ + int __mxcsr, __status; + + __stmxcsr(&__mxcsr); + __fnstsw(&__status); + return ((__status | __mxcsr) & __excepts); +} + +static __inline int +fegetround(void) +{ + int __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 & _ROUND_MASK); +} + +static __inline int +fesetround(int __round) +{ + int __mxcsr, __control; + + if (__round & ~_ROUND_MASK) + return (-1); + + __fnstcw(&__control); + __control &= ~_ROUND_MASK; + __control |= __round; + __fldcw(__control); + + __stmxcsr(&__mxcsr); + __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT); + __mxcsr |= __round << _SSE_ROUND_SHIFT; + __ldmxcsr(__mxcsr); + + return (0); +} + +int fegetenv(fenv_t *__envp); +int feholdexcept(fenv_t *__envp); + +static __inline int +fesetenv(const fenv_t *__envp) +{ + + __fldenv(__envp->__x87); + __ldmxcsr(__envp->__mxcsr); + return (0); +} + +int feupdateenv(const fenv_t *__envp); + +#if __BSD_VISIBLE + +int fesetmask(int __mask); + +static __inline int +fegetmask(void) +{ + int __control; + + /* + * We assume that the masks for the x87 and the SSE unit are + * the same. + */ + __fnstcw(&__control); + return (~__control & FE_ALL_EXCEPT); +} + +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* !_FENV_H_ */ Index: lib/msun/arm/fenv.c =================================================================== RCS file: lib/msun/arm/fenv.c diff -N lib/msun/arm/fenv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/arm/fenv.c 1 Jun 2004 07:19:58 -0000 @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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$ + */ + +#include + +/* + * Hopefully the system ID byte is immutable, so it's valid to use + * this as a default environment. + */ +const fenv_t __fe_dfl_env = 0; Index: lib/msun/arm/fenv.h =================================================================== RCS file: lib/msun/arm/fenv.h diff -N lib/msun/arm/fenv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/arm/fenv.h 1 Jun 2004 07:17:44 -0000 @@ -0,0 +1,195 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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_ +#define _FENV_H_ + +#include + +typedef __uint32_t fenv_t; +typedef __uint32_t fexcept_t; + +/* Exception flags */ +#define FE_INVALID 0x0001 +#define FE_DIVBYZERO 0x0002 +#define FE_OVERFLOW 0x0004 +#define FE_UNDERFLOW 0x0008 +#define FE_INEXACT 0x0010 +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ + FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +__BEGIN_DECLS + +/* Default floating-point environment */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +/* We need to be able to map status flag positions to mask flag positions */ +#define _FPUSW_SHIFT 16 +#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) + +#define __rfs(__fpsr) __asm("rfs %0" : "=m" (*(__fpsr))) +#define __wfs(__fpsr) __asm __volatile("wfs %0" : : "m" (__fpsr)) + +static __inline int +feclearexcept(int __excepts) +{ + fexcept_t __fpsr; + + __rfs(&__fpsr); + __fpsr &= ~__excepts; + __wfs(__fpsr); + return (0); +} + +static __inline int +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + fexcept_t __fpsr; + + __rfs(&__fpsr); + *__flagp = __fpsr & __excepts; + return (0); +} + +static __inline int +fesetexceptflag(const fexcept_t *__flagp, int __excepts) +{ + fexcept_t __fpsr; + + __rfs(&__fpsr); + __fpsr &= ~__excepts; + __fpsr |= *__flagp & __excepts; + __wfs(__fpsr); + return (0); +} + +static __inline int +feraiseexcept(int __excepts) +{ + fexcept_t __ex = __excepts; + + fesetexceptflag(&__ex, __excepts); /* XXX */ + return (0); +} + +static __inline int +fetestexcept(int __excepts) +{ + fexcept_t __fpsr; + + __rfs(&__fpsr); + return (__fpsr & __excepts); +} + +static __inline int +fegetround(void) +{ + + /* + * Apparently, the rounding mode is specified as part of the + * instruction format on ARM, so the dynamic rounding mode is + * indeterminate. Some FPUs may differ. + */ + return (-1); +} + +static __inline int +fesetround(int __round) +{ + + return (-1); +} + +static __inline int +fegetenv(fenv_t *__envp) +{ + + __rfs(__envp); + return (0); +} + +static __inline int +feholdexcept(fenv_t *__envp) +{ + fenv_t __env; + + __rfs(&__env); + *__envp = __env; + __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); + __wfs(__env); + return (0); +} + +static __inline int +fesetenv(const fenv_t *__envp) +{ + + __wfs(*__envp); + return (0); +} + +static __inline int +feupdateenv(const fenv_t *__envp) +{ + fexcept_t __fpsr; + + __rfs(&__fpsr); + __wfs(*__envp); + feraiseexcept(__fpsr & FE_ALL_EXCEPT); + return (0); +} + +#if __BSD_VISIBLE + +static __inline int +fesetmask(int __mask) +{ + fenv_t __fpsr; + + __rfs(&__fpsr); + __fpsr &= ~_ENABLE_MASK; + __fpsr |= __mask << _FPUSW_SHIFT; + __wfs(__fpsr); + return (0); +} + +static __inline int +fegetmask(void) +{ + fenv_t __fpsr; + + __rfs(&__fpsr); + return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT); +} + +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* !_FENV_H_ */ Index: lib/msun/i387/fenv.c =================================================================== RCS file: lib/msun/i387/fenv.c diff -N lib/msun/i387/fenv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/i387/fenv.c 31 May 2004 02:30:56 -0000 @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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$ + */ + +#include +#include +#include + +const fenv_t __fe_dfl_env = { + 0xffff0000 | __INITIAL_NPXCW__, + 0xffff0000, + 0xffffffff, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff } +}; Index: lib/msun/i387/fenv.h =================================================================== RCS file: lib/msun/i387/fenv.h diff -N lib/msun/i387/fenv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/i387/fenv.h 31 May 2004 05:57:12 -0000 @@ -0,0 +1,224 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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_ +#define _FENV_H_ + +#include +#include + +typedef struct { + __uint32_t __control; + __uint32_t __status; + __uint32_t __tag; + char __other[16]; +} fenv_t; + +typedef __uint16_t fexcept_t; + +/* Exception flags */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ + FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +/* Rounding modes */ +#define FE_TONEAREST 0x0000 +#define FE_DOWNWARD 0x0400 +#define FE_UPWARD 0x0800 +#define FE_TOWARDZERO 0x0c00 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) + +__BEGIN_DECLS + +/* Default floating-point environment */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw)) +#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env)) +#define __fnclex() __asm __volatile("fnclex") +#define __fnstenv(__env) __asm("fnstenv %0" : "=m" (*(__env))) +#define __fnstcw(__cw) __asm("fnstcw %0" : "=m" (*(__cw))) +#define __fnstsw(__sw) __asm("fnstsw %0" : "=am" (*(__sw))) +#define __fwait() __asm __volatile("fwait") + +static __inline int +feclearexcept(int __excepts) +{ + fenv_t __env; + + if (__excepts == FE_ALL_EXCEPT) { + __fnclex(); + } else { + __fnstenv(&__env); + __env.__status &= ~__excepts; + __fldenv(__env); + } + return (0); +} + +static __inline int +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + int __status; + + __fnstsw(&__status); + *__flagp = __status & __excepts; + return (0); +} + +static __inline int +fesetexceptflag(const fexcept_t *__flagp, int __excepts) +{ + fenv_t __env; + + __fnstenv(&__env); + __env.__status &= ~__excepts; + __env.__status |= *__flagp & __excepts; + __fldenv(__env); + return (0); +} + +static __inline int +feraiseexcept(int __excepts) +{ + fexcept_t __ex = __excepts; + + fesetexceptflag(&__ex, __excepts); + __fwait(); + return (0); +} + +static __inline int +fetestexcept(int __excepts) +{ + int __status; + + __fnstsw(&__status); + return (__status & __excepts); +} + +static __inline int +fegetround(void) +{ + int __control; + + __fnstcw(&__control); + return (__control & _ROUND_MASK); +} + +static __inline int +fesetround(int __round) +{ + int __control; + + if (__round & ~_ROUND_MASK) + return (-1); + __fnstcw(&__control); + __control &= ~_ROUND_MASK; + __control |= __round; + __fldcw(__control); + return (0); +} + +static __inline int +fegetenv(fenv_t *__envp) +{ + int __control; + + /* + * fnstenv masks all exceptions, so we need to save and + * restore the control word to avoid this side effect. + */ + __fnstcw(&__control); + __fnstenv(__envp); + __fldcw(__control); + return (0); +} + +static __inline int +feholdexcept(fenv_t *__envp) +{ + + __fnstenv(__envp); + __fnclex(); + return (0); +} + +static __inline int +fesetenv(const fenv_t *__envp) +{ + + __fldenv(*__envp); + return (0); +} + +static __inline int +feupdateenv(const fenv_t *__envp) +{ + int __status; + + __fnstsw(&__status); + __fldenv(*__envp); + feraiseexcept(__status & FE_ALL_EXCEPT); + return (0); +} + +#if __BSD_VISIBLE + +static __inline int +fesetmask(int __mask) +{ + int __control; + + __fnstcw(&__control); + __mask = (__control | FE_ALL_EXCEPT) & ~__mask; + __fldcw(__mask); + return (~__control & FE_ALL_EXCEPT); +} + +static __inline int +fegetmask(void) +{ + int __control; + + __fnstcw(&__control); + return (~__control & FE_ALL_EXCEPT); +} + +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* !_FENV_H_ */ Index: lib/msun/ia64/fenv.c =================================================================== RCS file: lib/msun/ia64/fenv.c diff -N lib/msun/ia64/fenv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/ia64/fenv.c 1 Jun 2004 10:15:04 -0000 @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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$ + */ + +#include +#include + +const fenv_t __fe_dfl_env = 0x0009804c8a70033fULL; + +/* + * It doesn't pay to inline feupdateenv() because it includes one of + * the rare uses of feraiseexcept() where the argument is not a + * constant. Thus, no dead code elimination can occur, resulting in + * significant bloat. + */ +int +feupdateenv(const fenv_t *envp) +{ + fenv_t fpsr; + + __stfpsr(&fpsr); + __ldfpsr(*envp); + feraiseexcept(fpsr & FE_ALL_EXCEPT); + return (0); +} Index: lib/msun/ia64/fenv.h =================================================================== RCS file: lib/msun/ia64/fenv.h diff -N lib/msun/ia64/fenv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/ia64/fenv.h 1 Jun 2004 10:18:39 -0000 @@ -0,0 +1,231 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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_ +#define _FENV_H_ + +#include + +typedef __uint64_t fenv_t; +typedef __uint16_t fexcept_t; + +/* Exception flags */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ + FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +/* Rounding modes */ +#define FE_TONEAREST 0x0000 +#define FE_DOWNWARD 0x0400 +#define FE_UPWARD 0x0800 +#define FE_TOWARDZERO 0x0c00 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) + +__BEGIN_DECLS + +/* Default floating-point environment */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +#define _FPUSW_SHIFT 13 + +#define __stfpsr(__r) __asm("mov %0=ar.fpsr" : "=r" (*(__r))) +#define __ldfpsr(__r) __asm __volatile("mov ar.fpsr=%0" : : "r" (__r)) + +static __inline int +feclearexcept(int __excepts) +{ + fenv_t __fpsr; + + __stfpsr(&__fpsr); + __fpsr &= ~((fenv_t)__excepts << _FPUSW_SHIFT); + __ldfpsr(__fpsr); + return (0); +} + +static __inline int +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + fenv_t __fpsr; + + __stfpsr(&__fpsr); + *__flagp = (fexcept_t)(__fpsr >> _FPUSW_SHIFT) & __excepts; + return (0); +} + +static __inline int +fesetexceptflag(const fexcept_t *__flagp, int __excepts) +{ + fenv_t __fpsr; + + __stfpsr(&__fpsr); + __fpsr &= ~((fenv_t)__excepts << _FPUSW_SHIFT); + __fpsr |= (fenv_t)(__excepts & *__flagp) << _FPUSW_SHIFT; + __ldfpsr(__fpsr); + return (0); +} + +/* + * It is worthwhile to use the inline version of this function iff it + * is called with arguments that are compile-time constants (due to + * dead code elimination). Unfortunately, gcc isn't smart enough to + * figure this out automatically, and there's no way to tell it. + * We assume that constant arguments will be the common case. + */ +static __inline int +feraiseexcept(int __excepts) +{ + volatile double d; + + /* + * With a compiler that supports the FENV_ACCESS pragma + * properly, simple expressions like '0.0 / 0.0' should + * be sufficient to generate traps. Unfortunately, we + * need to bring a volatile variable into the equation + * to prevent incorrect optimizations. + */ + if (__excepts & FE_INVALID) { + d = 0.0; + d = 0.0 / d; + } + if (__excepts & FE_DIVBYZERO) { + d = 0.0; + d = 1.0 / d; + } + if (__excepts & FE_OVERFLOW) { + d = 0x1.ffp1023; + d *= 2.0; + } + if (__excepts & FE_UNDERFLOW) { + d = 0x1p-1022; + d /= 0x1p1023; + } + if (__excepts & FE_INEXACT) { + d = 0x1p-1022; + d += 1.0; + } + return (0); +} + +static __inline int +fetestexcept(int __excepts) +{ + fenv_t __fpsr; + + __stfpsr(&__fpsr); + return ((__fpsr >> _FPUSW_SHIFT) & __excepts); +} + + +static __inline int +fegetround(void) +{ + fenv_t __fpsr; + + __stfpsr(&__fpsr); + return (__fpsr & _ROUND_MASK); +} + +static __inline int +fesetround(int __round) +{ + fenv_t __fpsr; + + if (__round & ~_ROUND_MASK) + return (-1); + __stfpsr(&__fpsr); + __fpsr &= ~_ROUND_MASK; + __fpsr |= __round; + __ldfpsr(__fpsr); + return (0); +} + +static __inline int +fegetenv(fenv_t *__envp) +{ + + __stfpsr(__envp); + return (0); +} + +static __inline int +feholdexcept(fenv_t *__envp) +{ + fenv_t __fpsr; + + __stfpsr(&__fpsr); + *__envp = __fpsr; + __fpsr &= ~((fenv_t)FE_ALL_EXCEPT << _FPUSW_SHIFT); + __fpsr |= FE_ALL_EXCEPT; + __ldfpsr(__fpsr); + return (0); +} + +static __inline int +fesetenv(const fenv_t *__envp) +{ + + __ldfpsr(*__envp); + return (0); +} + +int feupdateenv(const fenv_t *__envp); + +#if __BSD_VISIBLE + +static __inline int +fesetmask(int __mask) +{ + fenv_t __newfpsr, __oldfpsr; + + __stfpsr(&__oldfpsr); + __newfpsr = (__oldfpsr | FE_ALL_EXCEPT) & ~__mask; + __ldfpsr(__newfpsr); + return (~__oldfpsr & FE_ALL_EXCEPT); +} + +static __inline int +fegetmask(void) +{ + fenv_t __fpsr; + + __stfpsr(&__fpsr); + return (~__fpsr & FE_ALL_EXCEPT); +} + +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* !_FENV_H_ */ Index: lib/msun/man/feclearexcept.3 =================================================================== RCS file: lib/msun/man/feclearexcept.3 diff -N lib/msun/man/feclearexcept.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/man/feclearexcept.3 7 May 2004 18:56:45 -0000 @@ -0,0 +1,137 @@ +.\" Copyright (c) 2004 David Schultz +.\" 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$ +.\" +.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 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 . Index: lib/msun/man/fegetenv.3 =================================================================== RCS file: lib/msun/man/fegetenv.3 diff -N lib/msun/man/fegetenv.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/man/fegetenv.3 7 May 2004 19:56:06 -0000 @@ -0,0 +1,113 @@ +.\" Copyright (c) 2004 David Schultz +.\" 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$ +.\" +.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 . Index: lib/msun/man/fegetround.3 =================================================================== RCS file: lib/msun/man/fegetround.3 diff -N lib/msun/man/fegetround.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/man/fegetround.3 7 May 2004 09:31:53 -0000 @@ -0,0 +1,85 @@ +.\" Copyright (c) 2004 David Schultz +.\" 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$ +.\" +.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 , +.Dv FE_DOWNWARD , +.Dv 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 . +They supersede the non-standard +.Xr fpgetround 3 +and +.Xr fpsetround 3 +functions. Index: lib/msun/man/fenv.3 =================================================================== RCS file: lib/msun/man/fenv.3 diff -N lib/msun/man/fenv.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/man/fenv.3 7 May 2004 09:32:08 -0000 @@ -0,0 +1,272 @@ +.\" Copyright (c) 2004 David Schultz +.\" 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$ +.\" +.Dd May 8, 2004 +.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 +.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" +.Sh DESCRIPTION +The fenv 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 +.Na +s, 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. +.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 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 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 cc 1 , +.Xr feclearexcept 3 , +.Xr fegetenv 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 fpgetmask 3 , +.Xr fpgetprec 3 , +.Xr fpgetsticky 3 , +.Xr fpgetround 3 , +.Xr fpresetsticky 3 , +.Xr fpsetmask 3 , +.Xr fpsetprec 3 , +.Xr fpsetround 3 +.Sh STANDARDS +Except as noted below, +.In fenv.h +conforms to +.St -isoC-99 . +.Sh HISTORY +The +.In fenv.h +header first appeared in +.Fx 5.3 . +It supersedes the non-standard routines defined in +.In ieeefp.h +and documented in +.Xr fpgetround 3 . +.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. +.Pp +On the Alpha platform, +.Xr cc 1 +must be passed the +.Fl mieee-with-inexact mfp-rounding-mode=d +options in order to generate code that has the standard +side-effects and uses the specified rounding modes. Index: lib/msun/powerpc/fenv.c =================================================================== RCS file: lib/msun/powerpc/fenv.c diff -N lib/msun/powerpc/fenv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/powerpc/fenv.c 31 May 2004 02:30:35 -0000 @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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$ + */ + +#include + +const fenv_t __fe_dfl_env = 0x00000000; Index: lib/msun/powerpc/fenv.h =================================================================== RCS file: lib/msun/powerpc/fenv.h diff -N lib/msun/powerpc/fenv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/powerpc/fenv.h 31 May 2004 05:57:31 -0000 @@ -0,0 +1,251 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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_ +#define _FENV_H_ + +#include + +typedef __uint32_t fenv_t; +typedef __uint32_t fexcept_t; + +/* Exception flags */ +#define FE_INEXACT 0x02000000 +#define FE_DIVBYZERO 0x04000000 +#define FE_UNDERFLOW 0x08000000 +#define FE_OVERFLOW 0x10000000 +#define FE_INVALID 0x20000000 /* all types of invalid FP ops */ + +/* + * The PowerPC architecture has extra invalid flags that indicate the + * specific type of invalid operation occurred. These flags may be + * tested, set, and cleared---but not masked---separately. All of + * these bits are cleared when FE_INVALID is cleared, but only + * FE_VXSOFT is set when FE_INVALID is explicitly set in software. + */ +#define FE_VXCVI 0x00000100 /* invalid integer convert */ +#define FE_VXSQRT 0x00000200 /* square root of a negative */ +#define FE_VXSOFT 0x00000400 /* software-requested exception */ +#define FE_VXVC 0x00080000 /* ordered comparison involving NaN */ +#define FE_VXIMZ 0x00100000 /* inf * 0 */ +#define FE_VXZDZ 0x00200000 /* 0 / 0 */ +#define FE_VXIDI 0x00400000 /* inf / inf */ +#define FE_VXISI 0x00800000 /* inf - inf */ +#define FE_VXSNAN 0x01000000 /* operation on a signalling NaN */ +#define FE_ALL_INVALID (FE_VXCVI | FE_VXSQRT | FE_VXSOFT | FE_VXVC | \ + FE_VXIMZ | FE_VXZDZ | FE_VXIDI | FE_VXISI | \ + FE_VXSNAN | FE_INVALID) +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ + FE_ALL_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +/* Rounding modes */ +#define FE_TONEAREST 0x0000 +#define FE_TOWARDZERO 0x0001 +#define FE_UPWARD 0x0002 +#define FE_DOWNWARD 0x0003 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) + +__BEGIN_DECLS + +/* Default floating-point environment */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +/* We need to be able to map status flag positions to mask flag positions */ +#define _FPUSW_SHIFT 22 +#define _ENABLE_MASK ((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ + FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT) + +#define __mffs(__env) __asm("mffs %0" : "=f" (*(__env))) +#define __mtfsf(__env) __asm __volatile("mtfsf 255,%0" : : "f" (__env)) + +union __fpscr { + double __d; + struct { + __uint32_t __junk; + fenv_t __reg; + } __bits; +}; + +static __inline int +feclearexcept(int __excepts) +{ + union __fpscr __r; + + if (__excepts & FE_INVALID) + __excepts |= FE_ALL_INVALID; + __mffs(&__r.__d); + __r.__bits.__reg &= ~__excepts; + __mtfsf(__r.__d); + return (0); +} + +static __inline int +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + union __fpscr __r; + + __mffs(&__r.__d); + *__flagp = __r.__bits.__reg & __excepts; + return (0); +} + +static __inline int +fesetexceptflag(const fexcept_t *__flagp, int __excepts) +{ + union __fpscr __r; + + if (__excepts & FE_INVALID) + __excepts |= FE_ALL_EXCEPT; + __mffs(&__r.__d); + __r.__bits.__reg &= ~__excepts; + __r.__bits.__reg |= *__flagp & __excepts; + __mtfsf(__r.__d); + return (0); +} + +static __inline int +feraiseexcept(int __excepts) +{ + union __fpscr __r; + + if (__excepts & FE_INVALID) + __excepts |= FE_VXSOFT; + __mffs(&__r.__d); + __r.__bits.__reg |= __excepts; + __mtfsf(__r.__d); + return (0); +} + +static __inline int +fetestexcept(int __excepts) +{ + union __fpscr __r; + + __mffs(&__r.__d); + return (__r.__bits.__reg & __excepts); +} + +static __inline int +fegetround(void) +{ + union __fpscr __r; + + __mffs(&__r.__d); + return (__r.__bits.__reg & _ROUND_MASK); +} + +static __inline int +fesetround(int __round) +{ + union __fpscr __r; + + if (__round & ~_ROUND_MASK) + return (-1); + __mffs(&__r.__d); + __r.__bits.__reg &= ~_ROUND_MASK; + __r.__bits.__reg |= __round; + __mtfsf(__r.__d); + return (0); +} + +static __inline int +fegetenv(fenv_t *__envp) +{ + union __fpscr __r; + + __mffs(&__r.__d); + *__envp = __r.__bits.__reg; + return (0); +} + +static __inline int +feholdexcept(fenv_t *__envp) +{ + union __fpscr __r; + + __mffs(&__r.__d); + *__envp = __r.__d; + __r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); + __mtfsf(__r.__d); + return (0); +} + +static __inline int +fesetenv(const fenv_t *__envp) +{ + union __fpscr __r; + + __r.__bits.__reg = *__envp; + __mtfsf(__r.__d); + return (0); +} + +static __inline int +feupdateenv(const fenv_t *__envp) +{ + union __fpscr __r; + + __mffs(&__r.__d); + __r.__bits.__reg &= FE_ALL_EXCEPT; + __r.__bits.__reg |= *__envp; + __mtfsf(__r.__d); + return (0); +} + +#if __BSD_VISIBLE + +static __inline int +fesetmask(int __mask) +{ + union __fpscr __r; + fenv_t __oldmask; + + __mffs(&__r.__d); + __oldmask = __r.__bits.__reg; + __r.__bits.__reg &= ~_ENABLE_MASK; + __r.__bits.__reg |= __mask >> _FPUSW_SHIFT; + __mtfsf(__r.__d); + return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT); +} + +static __inline int +fegetmask(void) +{ + union __fpscr __r; + + __mffs(&__r.__d); + return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT); +} + +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* !_FENV_H_ */ Index: lib/msun/sparc64/fenv.c =================================================================== RCS file: lib/msun/sparc64/fenv.c diff -N lib/msun/sparc64/fenv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/sparc64/fenv.c 1 Jun 2004 07:18:51 -0000 @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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$ + */ + +#include + +/* + * The FSR_version field may be different on different + * implementations, but it is immutable and opaque to the + * application. Thus, 0 is valid as the default environment. + */ +const fenv_t __fe_dfl_env = 0; Index: lib/msun/sparc64/fenv.h =================================================================== RCS file: lib/msun/sparc64/fenv.h diff -N lib/msun/sparc64/fenv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/msun/sparc64/fenv.h 1 Jun 2004 10:53:44 -0000 @@ -0,0 +1,244 @@ +/*- + * Copyright (c) 2004 David Schultz + * 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_ +#define _FENV_H_ + +#include + +typedef __uint64_t fenv_t; +typedef __uint64_t fexcept_t; + +/* Exception flags */ +#define FE_INVALID 0x00000200 +#define FE_DIVBYZERO 0x00000040 +#define FE_OVERFLOW 0x00000100 +#define FE_UNDERFLOW 0x00000080 +#define FE_INEXACT 0x00000020 +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ + FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +/* + * Rounding modes + * + * We can't just use the hardware bit values here, because that would + * make FE_UPWARD and FE_DOWNWARD negative, which is not allowed. + */ +#define FE_TONEAREST 0x0 +#define FE_TOWARDZERO 0x1 +#define FE_UPWARD 0x2 +#define FE_DOWNWARD 0x3 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) +#define _ROUND_SHIFT 30 + +__BEGIN_DECLS + +/* Default floating-point environment */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +/* We need to be able to map status flag positions to mask flag positions */ +#define _FPUSW_SHIFT 18 +#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) + +#define __ldxfsr(__r) __asm __volatile("ldx %0, %%fsr" : : "m" (__r)) +#define __stxfsr(__r) __asm("stx %%fsr, %0" : "=m" (*(__r))) + +static __inline int +feclearexcept(int __excepts) +{ + fexcept_t __r; + + __stxfsr(&__r); + __r &= ~__excepts; + __ldxfsr(__r); + return (0); +} + +static __inline int +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + fexcept_t __r; + + __stxfsr(&__r); + *__flagp = __r & __excepts; + return (0); +} + +static __inline int +fesetexceptflag(const fexcept_t *__flagp, int __excepts) +{ + fexcept_t __r; + + __stxfsr(&__r); + __r &= ~__excepts; + __r |= *__flagp & __excepts; + __ldxfsr(__r); + return (0); +} + +/* + * In contrast with the ia64 platform, it seems to be worthwhile to + * inline this function on sparc64 even when the arguments are not + * compile-time constants. Perhaps this depends on the register window. + */ +static __inline int +feraiseexcept(int __excepts) +{ + volatile double d; + + /* + * With a compiler that supports the FENV_ACCESS pragma + * properly, simple expressions like '0.0 / 0.0' should + * be sufficient to generate traps. Unfortunately, we + * need to bring a volatile variable into the equation + * to prevent incorrect optimizations. + */ + if (__excepts & FE_INVALID) { + d = 0.0; + d = 0.0 / d; + } + if (__excepts & FE_DIVBYZERO) { + d = 0.0; + d = 1.0 / d; + } + if (__excepts & FE_OVERFLOW) { + d = 0x1.ffp1023; + d *= 2.0; + } + if (__excepts & FE_UNDERFLOW) { + d = 0x1p-1022; + d /= 0x1p1023; + } + if (__excepts & FE_INEXACT) { + d = 0x1p-1022; + d += 1.0; + } + return (0); +} + +static __inline int +fetestexcept(int __excepts) +{ + fexcept_t __r; + + __stxfsr(&__r); + return (__r & __excepts); +} + +static __inline int +fegetround(void) +{ + fenv_t __r; + + __stxfsr(&__r); + return ((__r >> _ROUND_SHIFT) & _ROUND_MASK); +} + +static __inline int +fesetround(int __round) +{ + fenv_t __r; + + if (__round & ~_ROUND_MASK) + return (-1); + __stxfsr(&__r); + __r &= ~(_ROUND_MASK << _ROUND_SHIFT); + __r |= __round << _ROUND_SHIFT; + __ldxfsr(__r); + return (0); +} + +static __inline int +fegetenv(fenv_t *__envp) +{ + + __stxfsr(__envp); + return (0); +} + +static __inline int +feholdexcept(fenv_t *__envp) +{ + fenv_t __r; + + __stxfsr(&__r); + *__envp = __r; + __r &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); + __ldxfsr(__r); + return (0); +} + +static __inline int +fesetenv(const fenv_t *__envp) +{ + + __ldxfsr(*__envp); + return (0); +} + +static __inline int +feupdateenv(const fenv_t *__envp) +{ + fexcept_t __r; + + __stxfsr(&__r); + __ldxfsr(*__envp); + feraiseexcept(__r & FE_ALL_EXCEPT); + return (0); +} + +#if __BSD_VISIBLE + +static __inline int +fesetmask(int __mask) +{ + fenv_t __r; + + __stxfsr(&__r); + __r &= ~_ENABLE_MASK; + __r |= __mask << _FPUSW_SHIFT; + __ldxfsr(__r); + return (0); +} + +static __inline int +fegetmask(void) +{ + fenv_t __r; + + __stxfsr(&__r); + return ((__r & _ENABLE_MASK) >> _FPUSW_SHIFT); +} + +#endif /* __BSD_VISIBLE */ + +__END_DECLS + +#endif /* !_FENV_H_ */ Index: share/man/man3/fpgetround.3 =================================================================== RCS file: /cvs/src/share/man/man3/fpgetround.3,v retrieving revision 1.12 diff -u -r1.12 fpgetround.3 --- share/man/man3/fpgetround.3 5 May 2004 09:53:29 -0000 1.12 +++ share/man/man3/fpgetround.3 7 May 2004 20:15:17 -0000 @@ -93,6 +93,10 @@ .Ft fp_except_t .Fn fpresetsticky "fp_except_t sticky" .Sh DESCRIPTION +The routines described herein are deprecated. +New code should use the functionality provided by +.Xr fenv 3 . +.Pp When a floating point exception is detected, the exception sticky flag is set and the exception mask is tested. If the mask is set, then a trap @@ -162,6 +166,7 @@ functions provide functionality unavailable on many platforms. At present, they are implemented only on the i386 and amd64 platforms. .Sh SEE ALSO +.Xr fenv 3 , .Xr isnan 3 .Sh CAVEAT After a floating point exception and before a mask is set, the sticky