diff options
Diffstat (limited to 'lib/libm/arch')
-rw-r--r-- | lib/libm/arch/alpha/fenv.c | 19 | ||||
-rw-r--r-- | lib/libm/arch/amd64/fenv.c | 71 | ||||
-rw-r--r-- | lib/libm/arch/arm/fenv.c | 10 | ||||
-rw-r--r-- | lib/libm/arch/hppa/fenv.c | 135 | ||||
-rw-r--r-- | lib/libm/arch/hppa64/fenv.c | 372 | ||||
-rw-r--r-- | lib/libm/arch/i387/fenv.c | 381 | ||||
-rw-r--r-- | lib/libm/arch/m88k/fenv.c | 358 | ||||
-rw-r--r-- | lib/libm/arch/mc68881/fenv.c | 29 | ||||
-rw-r--r-- | lib/libm/arch/mips64/fenv.c | 143 | ||||
-rw-r--r-- | lib/libm/arch/powerpc/fenv.c | 183 | ||||
-rw-r--r-- | lib/libm/arch/sh/fenv.c | 85 | ||||
-rw-r--r-- | lib/libm/arch/sparc/fenv.c | 157 | ||||
-rw-r--r-- | lib/libm/arch/sparc64/fenv.c | 157 |
13 files changed, 1366 insertions, 734 deletions
diff --git a/lib/libm/arch/alpha/fenv.c b/lib/libm/arch/alpha/fenv.c index f0db3a3dbee..fa1758104d9 100644 --- a/lib/libm/arch/alpha/fenv.c +++ b/lib/libm/arch/alpha/fenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/23 22:39:14 martynas Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ /* * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org> @@ -176,9 +176,7 @@ fesetround(int round) __asm__ __volatile__ ("mf_fpcr %0" : "=f" (fpcr)); __asm__ __volatile__ ("trapb"); - /* - * Set the rounding direction - */ + /* Set the rounding direction */ fpcr &= ~((unsigned long)_ROUND_MASK << _ROUND_SHIFT); fpcr |= (unsigned long)round << _ROUND_SHIFT; @@ -200,10 +198,10 @@ fegetenv(fenv_t *envp) unsigned long fpcr; /* Store the current floating-point sticky flags */ - envp->__excepts = sysarch(ALPHA_FPGETSTICKY, 0L); + envp->__sticky = sysarch(ALPHA_FPGETSTICKY, 0L) & FE_ALL_EXCEPT; /* Store the current floating-point masks */ - envp->__mask = sysarch(ALPHA_FPGETMASK, 0L); + envp->__mask = sysarch(ALPHA_FPGETMASK, 0L) & FE_ALL_EXCEPT; /* Store the current floating-point control register */ __asm__ __volatile__ ("trapb"); @@ -229,13 +227,11 @@ feholdexcept(fenv_t *envp) fegetenv(envp); /* Clear exception flags */ - a.mask = envp->__excepts; - a.mask &= ~FE_ALL_EXCEPT; + a.mask = 0; sysarch(ALPHA_FPSETSTICKY, &a); /* Mask all exceptions */ - a.mask = envp->__excepts; - a.mask &= ~FE_ALL_EXCEPT; + a.mask = 0; sysarch(ALPHA_FPSETMASK, &a); return (0); @@ -256,7 +252,7 @@ fesetenv(const fenv_t *envp) struct alpha_fp_except_args a; /* Load the floating-point sticky flags */ - a.mask = envp->__excepts & FE_ALL_EXCEPT; + a.mask = envp->__sticky & FE_ALL_EXCEPT; sysarch(ALPHA_FPSETSTICKY, &a); /* Load the floating-point masks */ @@ -268,6 +264,7 @@ fesetenv(const fenv_t *envp) __asm__ __volatile__ ("mf_fpcr %0" : "=f" (fpcr)); __asm__ __volatile__ ("trapb"); + /* Set the requested flags */ fpcr &= ~((unsigned long)_ROUND_MASK << _ROUND_SHIFT); fpcr |= ((unsigned long)envp->__round & _ROUND_MASK) << _ROUND_SHIFT; diff --git a/lib/libm/arch/amd64/fenv.c b/lib/libm/arch/amd64/fenv.c index 781d8a39d92..245ca0af695 100644 --- a/lib/libm/arch/amd64/fenv.c +++ b/lib/libm/arch/amd64/fenv.c @@ -1,5 +1,5 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/21 21:12:55 martynas Exp $ */ -/* $NetBSD: fenv.c,v 1.1 2010/07/31 21:47:53 joerg Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ +/* $NetBSD: fenv.c,v 1.1 2010/07/31 21:47:53 joerg Exp $ */ /*- * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG> @@ -53,8 +53,8 @@ fenv_t __fe_dfl_env = { 0x00000000, 0x00000000, 0x00000000, - 0xffff0000, - }, + 0xffff0000 + } }, __INITIAL_MXCSR__ /* MXCSR register */ }; @@ -97,19 +97,19 @@ feclearexcept(int excepts) int fegetexceptflag(fexcept_t *flagp, int excepts) { - unsigned short x87_status; + unsigned short status; unsigned int mxcsr; excepts &= FE_ALL_EXCEPT; /* Store the current x87 status register */ - __asm__ __volatile__ ("fnstsw %0" : "=am" (x87_status)); + __asm__ __volatile__ ("fnstsw %0" : "=am" (status)); /* Store the MXCSR register */ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); /* Store the results in flagp */ - *flagp = (x87_status | mxcsr) & excepts; + *flagp = (status | mxcsr) & excepts; return (0); } @@ -175,18 +175,18 @@ fesetexceptflag(const fexcept_t *flagp, int excepts) int fetestexcept(int excepts) { - unsigned short x87_status; + unsigned short status; unsigned int mxcsr; excepts &= FE_ALL_EXCEPT; /* Store the current x87 status register */ - __asm__ __volatile__ ("fnstsw %0" : "=am" (x87_status)); + __asm__ __volatile__ ("fnstsw %0" : "=am" (status)); /* Store the MXCSR register state */ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); - return ((x87_status | mxcsr) & excepts); + return ((status | mxcsr) & excepts); } /* @@ -196,21 +196,14 @@ int fegetround(void) { unsigned short control; - unsigned int mxcsr; /* - * 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. + * 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. */ __asm__ __volatile__ ("fnstcw %0" : "=m" (control)); - __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); - - if ((control & _X87_ROUND_MASK) - != ((mxcsr & _SSE_ROUND_MASK) >> 3)) { - return (-1); - } return (control & _X87_ROUND_MASK); } @@ -230,26 +223,20 @@ fesetround(int round) if (round & ~_X87_ROUND_MASK) return (-1); - /* Store the current x87 control word register */ + /* Store the current x87 control word register */ __asm__ __volatile__ ("fnstcw %0" : "=m" (control)); - /* - * Set the rounding direction - * Rounding Control is bits 10-11, so shift appropriately - */ + /* Set the rounding direction */ control &= ~_X87_ROUND_MASK; control |= round; /* Load the x87 control word register */ __asm__ __volatile__ ("fldcw %0" : : "m" (control)); - /* - * Same for the SSE environment - * Rounding Control is bits 13-14, so shift appropriately - */ + /* Same for the SSE environment */ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); - mxcsr &= ~_SSE_ROUND_MASK; - mxcsr |= (round << _SSE_ROUND_SHIFT); + mxcsr &= ~(_X87_ROUND_MASK << _SSE_ROUND_SHIFT); + mxcsr |= round << _SSE_ROUND_SHIFT; __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); return (0); @@ -301,13 +288,14 @@ feholdexcept(fenv_t *envp) /* Store the MXCSR register state */ __asm__ __volatile__ ("stmxcsr %0" : "=m" (envp->__mxcsr)); - /* Clear exception flags in MXCSR XXX */ + /* Clear exception flags in MXCSR */ mxcsr = envp->__mxcsr; mxcsr &= ~FE_ALL_EXCEPT; /* Mask all exceptions */ - mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT; + mxcsr |= FE_ALL_EXCEPT << _SSE_MASK_SHIFT; + /* Store the MXCSR register */ __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); return (0); @@ -344,11 +332,11 @@ fesetenv(const fenv_t *envp) int feupdateenv(const fenv_t *envp) { - unsigned short x87_status; + unsigned short status; unsigned int mxcsr; /* Store the x87 status register */ - __asm__ __volatile__ ("fnstsw %0" : "=am" (x87_status)); + __asm__ __volatile__ ("fnstsw %0" : "=am" (status)); /* Store the MXCSR register */ __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); @@ -357,7 +345,7 @@ feupdateenv(const fenv_t *envp) fesetenv(envp); /* Raise any previously accumulated exceptions */ - feraiseexcept(x87_status | mxcsr); + feraiseexcept(status | mxcsr); return (0); } @@ -376,15 +364,14 @@ feenableexcept(int mask) __asm__ __volatile__ ("fnstcw %0" : "=m" (control)); __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); - omask = ~(control | (mxcsr >> _SSE_EMASK_SHIFT)) & FE_ALL_EXCEPT; + omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT; control &= ~mask; __asm__ __volatile__ ("fldcw %0" : : "m" (control)); - mxcsr &= ~(mask << _SSE_EMASK_SHIFT); + mxcsr &= ~(mask << _SSE_MASK_SHIFT); __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); return (omask); - } int @@ -398,11 +385,11 @@ fedisableexcept(int mask) __asm__ __volatile__ ("fnstcw %0" : "=m" (control)); __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); - omask = ~(control | (mxcsr >> _SSE_EMASK_SHIFT)) & FE_ALL_EXCEPT; + omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT; control |= mask; __asm__ __volatile__ ("fldcw %0" : : "m" (control)); - mxcsr |= mask << _SSE_EMASK_SHIFT; + mxcsr |= mask << _SSE_MASK_SHIFT; __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); return (omask); diff --git a/lib/libm/arch/arm/fenv.c b/lib/libm/arch/arm/fenv.c index 0230ca0ac53..66bc3bc2b75 100644 --- a/lib/libm/arch/arm/fenv.c +++ b/lib/libm/arch/arm/fenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/24 00:20:27 martynas Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ /* * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org> @@ -138,9 +138,7 @@ fesetround(int round) if (round & ~_ROUND_MASK) return (-1); - /* - * Set the rounding direction - */ + /* Set the rounding direction */ _softfloat_float_rounding_mode &= ~_ROUND_MASK; _softfloat_float_rounding_mode |= round; @@ -155,7 +153,7 @@ int fegetenv(fenv_t *envp) { /* Store the current floating-point sticky flags */ - envp->__excepts = _softfloat_float_exception_flags; + envp->__sticky = _softfloat_float_exception_flags; /* Store the current floating-point masks */ envp->__mask = _softfloat_float_exception_mask; @@ -199,7 +197,7 @@ int fesetenv(const fenv_t *envp) { /* Load the floating-point sticky flags */ - _softfloat_float_exception_flags = envp->__excepts & FE_ALL_EXCEPT; + _softfloat_float_exception_flags = envp->__sticky & FE_ALL_EXCEPT; /* Load the floating-point masks */ _softfloat_float_exception_mask = envp->__mask & FE_ALL_EXCEPT; diff --git a/lib/libm/arch/hppa/fenv.c b/lib/libm/arch/hppa/fenv.c index 73a93935dbd..74deb254db7 100644 --- a/lib/libm/arch/hppa/fenv.c +++ b/lib/libm/arch/hppa/fenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/21 20:40:54 martynas Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ /* * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org> @@ -20,6 +20,11 @@ #include <fenv.h> +union u { + unsigned long long fpsr; + unsigned int bits[2]; +}; + /* * The following constant represents the default floating-point environment * (that is, the one installed at program startup) and has type pointer to @@ -38,18 +43,19 @@ fenv_t __fe_dfl_env = 0; int feclearexcept(int excepts) { - volatile unsigned int fpsr[2]; + volatile union u u; excepts &= FE_ALL_EXCEPT; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); /* Clear the requested floating-point exceptions */ - fpsr[0] &= ~excepts; + u.bits[0] &= ~(excepts << _MASK_SHIFT); /* Load the floating-point status register */ - __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&fpsr)); + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); return (0); } @@ -62,15 +68,16 @@ feclearexcept(int excepts) int fegetexceptflag(fexcept_t *flagp, int excepts) { - volatile unsigned int fpsr[2]; + volatile union u u; excepts &= FE_ALL_EXCEPT; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); /* Store the results in flagp */ - *flagp = fpsr[0] & excepts; + *flagp = (u.bits[0] >> _MASK_SHIFT) & excepts; return (0); } @@ -126,19 +133,20 @@ feraiseexcept(int excepts) int fesetexceptflag(const fexcept_t *flagp, int excepts) { - volatile unsigned int fpsr[2]; + volatile union u u; excepts &= FE_ALL_EXCEPT; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); /* Set the requested status flags */ - fpsr[0] &= ~excepts; - fpsr[0] |= *flagp & excepts; + u.bits[0] &= ~(excepts << _MASK_SHIFT); + u.bits[0] |= (*flagp & excepts) << _MASK_SHIFT; /* Load the floating-point status register */ - __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&fpsr)); + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); return (0); } @@ -151,14 +159,15 @@ fesetexceptflag(const fexcept_t *flagp, int excepts) int fetestexcept(int excepts) { - volatile unsigned int fpsr[2]; + volatile union u u; excepts &= FE_ALL_EXCEPT; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); - return (fpsr[0] & excepts); + return ((u.bits[0] >> _MASK_SHIFT) & excepts); } /* @@ -167,11 +176,13 @@ fetestexcept(int excepts) int fegetround(void) { - volatile unsigned int fpsr[2]; + volatile union u u; - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); - return (fpsr[0] & _ROUND_MASK); + return (u.bits[0] & _ROUND_MASK); } /* @@ -182,23 +193,22 @@ fegetround(void) int fesetround(int round) { - volatile unsigned int fpsr[2]; + volatile union u u; /* Check whether requested rounding direction is supported */ if (round & ~_ROUND_MASK) return (-1); /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); - /* - * Set the rounding direction - */ - fpsr[0] &= ~_ROUND_MASK; - fpsr[0] |= round; + /* Set the rounding direction */ + u.bits[0] &= ~_ROUND_MASK; + u.bits[0] |= round; /* Load the floating-point status register */ - __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&fpsr)); + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); return (0); } @@ -210,12 +220,13 @@ fesetround(int round) int fegetenv(fenv_t *envp) { - volatile unsigned int fpsr[2]; + volatile union u u; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); - *envp = fpsr[0]; + *envp = u.bits[0]; return (0); } @@ -229,19 +240,20 @@ fegetenv(fenv_t *envp) int feholdexcept(fenv_t *envp) { - volatile unsigned int fpsr[2]; + volatile union u u; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); - *envp = fpsr[0]; + *envp = u.bits[0]; /* Clear exception flags in FPSR */ - fpsr[0] &= ~FE_ALL_EXCEPT; + u.bits[0] &= ~(FE_ALL_EXCEPT << _MASK_SHIFT); /* Mask all exceptions */ - fpsr[0] &= ~((unsigned int)FE_ALL_EXCEPT >> _EMASK_SHIFT); - __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&fpsr)); + u.bits[0] &= ~FE_ALL_EXCEPT; + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); return (0); } @@ -257,19 +269,20 @@ feholdexcept(fenv_t *envp) int fesetenv(const fenv_t *envp) { - volatile unsigned int fpsr[2]; + volatile union u u; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); /* Set the requested flags */ - fpsr[0] &= ~(((unsigned int)FE_ALL_EXCEPT >> _EMASK_SHIFT) | - _ROUND_MASK | FE_ALL_EXCEPT); - fpsr[0] |= *envp & (((unsigned int)FE_ALL_EXCEPT >> _EMASK_SHIFT) | - _ROUND_MASK | FE_ALL_EXCEPT); + u.bits[0] &= ~(FE_ALL_EXCEPT | _ROUND_MASK | + (FE_ALL_EXCEPT << _MASK_SHIFT)); + u.bits[0] |= *envp & (FE_ALL_EXCEPT | _ROUND_MASK | + (FE_ALL_EXCEPT << _MASK_SHIFT)); /* Load the floating-point status register */ - __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&fpsr)); + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); return (0); } @@ -285,16 +298,17 @@ fesetenv(const fenv_t *envp) int feupdateenv(const fenv_t *envp) { - volatile unsigned int fpsr[2]; + volatile union u u; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); /* Install new floating-point environment */ fesetenv(envp); /* Raise any previously accumulated exceptions */ - feraiseexcept(fpsr[0]); + feraiseexcept(u.bits[0] >> _MASK_SHIFT); return (0); } @@ -305,19 +319,20 @@ feupdateenv(const fenv_t *envp) int feenableexcept(int mask) { - volatile unsigned int fpsr[2]; + volatile union u u; unsigned int omask; mask &= FE_ALL_EXCEPT; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); - omask = (fpsr[0] << _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpsr[0] |= (unsigned int)mask >> _EMASK_SHIFT; + omask = u.bits[0] & FE_ALL_EXCEPT; + u.bits[0] |= mask; /* Load the floating-point status register */ - __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&fpsr)); + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); return (omask); @@ -326,19 +341,20 @@ feenableexcept(int mask) int fedisableexcept(int mask) { - volatile unsigned int fpsr[2]; + volatile union u u; unsigned int omask; mask &= FE_ALL_EXCEPT; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); - omask = (fpsr[0] << _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpsr[0] &= ~((unsigned int)mask >> _EMASK_SHIFT); + omask = u.bits[0] & FE_ALL_EXCEPT; + u.bits[0] &= ~mask; /* Load the floating-point status register */ - __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&fpsr)); + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); return (omask); } @@ -346,10 +362,11 @@ fedisableexcept(int mask) int fegetexcept(void) { - volatile unsigned int fpsr[2]; + volatile union u u; /* Store the current floating-point status register */ - __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (fpsr) : "r" (&fpsr)); + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); - return ((fpsr[0] << _EMASK_SHIFT) & FE_ALL_EXCEPT); + return (u.bits[0] & FE_ALL_EXCEPT); } diff --git a/lib/libm/arch/hppa64/fenv.c b/lib/libm/arch/hppa64/fenv.c new file mode 100644 index 00000000000..1452f51f1c7 --- /dev/null +++ b/lib/libm/arch/hppa64/fenv.c @@ -0,0 +1,372 @@ +/* $OpenBSD: fenv.c,v 1.1 2011/04/28 17:34:23 martynas Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/cdefs.h> + +#include <fenv.h> + +union u { + unsigned long long fpsr; + unsigned int bits[2]; +}; + +/* + * 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(). + */ +fenv_t __fe_dfl_env = 0; + +/* + * The feclearexcept() function clears the supported floating-point exceptions + * represented by `excepts'. + */ +int +feclearexcept(int excepts) +{ + volatile union u u; + + excepts &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + /* Clear the requested floating-point exceptions */ + u.bits[0] &= ~(excepts << _MASK_SHIFT); + + /* Load the floating-point status register */ + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); + + 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) +{ + volatile union u u; + + excepts &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + /* Store the results in flagp */ + *flagp = (u.bits[0] >> _MASK_SHIFT) & excepts; + + return (0); +} + +/* + * The feraiseexcept() function raises the supported floating-point exceptions + * represented by the argument `excepts'. + */ +int +feraiseexcept(int excepts) +{ + volatile double d; + + excepts &= FE_ALL_EXCEPT; + + /* + * 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; + } + __asm__ __volatile__ ("fldd 0(%%sr0,%%sp), %0" : "=f" (d)); + + 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) +{ + volatile union u u; + + excepts &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + /* Set the requested status flags */ + u.bits[0] &= ~(excepts << _MASK_SHIFT); + u.bits[0] |= (*flagp & excepts) << _MASK_SHIFT; + + /* Load the floating-point status register */ + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); + + 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) +{ + volatile union u u; + + excepts &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + return ((u.bits[0] >> _MASK_SHIFT) & excepts); +} + +/* + * The fegetround() function gets the current rounding direction. + */ +int +fegetround(void) +{ + volatile union u u; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + return (u.bits[0] & _ROUND_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) +{ + volatile union u u; + + /* Check whether requested rounding direction is supported */ + if (round & ~_ROUND_MASK) + return (-1); + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + /* Set the rounding direction */ + u.bits[0] &= ~_ROUND_MASK; + u.bits[0] |= round; + + /* Load the floating-point status register */ + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); + + 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) +{ + volatile union u u; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + *envp = u.bits[0]; + + 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) +{ + volatile union u u; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + *envp = u.bits[0]; + + /* Clear exception flags in FPSR */ + u.bits[0] &= ~(FE_ALL_EXCEPT << _MASK_SHIFT); + + /* Mask all exceptions */ + u.bits[0] &= ~FE_ALL_EXCEPT; + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); + + 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) +{ + volatile union u u; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + /* Set the requested flags */ + u.bits[0] &= ~(FE_ALL_EXCEPT | _ROUND_MASK | + (FE_ALL_EXCEPT << _MASK_SHIFT)); + u.bits[0] |= *envp & (FE_ALL_EXCEPT | _ROUND_MASK | + (FE_ALL_EXCEPT << _MASK_SHIFT)); + + /* Load the floating-point status register */ + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); + + 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) +{ + volatile union u u; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + /* Install new floating-point environment */ + fesetenv(envp); + + /* Raise any previously accumulated exceptions */ + feraiseexcept(u.bits[0] >> _MASK_SHIFT); + + return (0); +} + +/* + * The following functions are extentions to the standard + */ +int +feenableexcept(int mask) +{ + volatile union u u; + unsigned int omask; + + mask &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + omask = u.bits[0] & FE_ALL_EXCEPT; + u.bits[0] |= mask; + + /* Load the floating-point status register */ + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); + + return (omask); + +} + +int +fedisableexcept(int mask) +{ + volatile union u u; + unsigned int omask; + + mask &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + omask = u.bits[0] & FE_ALL_EXCEPT; + u.bits[0] &= ~mask; + + /* Load the floating-point status register */ + __asm__ __volatile__ ("fldd 0(%0), %%fr0" : : "r" (&u.fpsr)); + + return (omask); +} + +int +fegetexcept(void) +{ + volatile union u u; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fstd %%fr0, 0(%1)" : "=m" (u.fpsr) : + "r" (&u.fpsr)); + + return (u.bits[0] & FE_ALL_EXCEPT); +} diff --git a/lib/libm/arch/i387/fenv.c b/lib/libm/arch/i387/fenv.c index 639a4d5c633..9f79a807e8b 100644 --- a/lib/libm/arch/i387/fenv.c +++ b/lib/libm/arch/i387/fenv.c @@ -1,5 +1,5 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/24 00:35:22 martynas Exp $ */ -/* $NetBSD: fenv.c,v 1.3 2010/08/01 06:34:38 taca Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ +/* $NetBSD: fenv.c,v 1.3 2010/08/01 06:34:38 taca Exp $ */ /*- * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> @@ -28,52 +28,12 @@ */ #include <sys/cdefs.h> - +#include <machine/cpu.h> +#include <machine/npx.h> #include <sys/param.h> #include <sys/sysctl.h> -#include <machine/cpu.h> -#include <assert.h> -#include <fenv.h> -#include <stddef.h> -#include <string.h> - -#define _DIAGASSERT(x) ((void) 0) /* XXX */ - -/* 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))) +#include <fenv.h> /* * The following constant represents the default floating-point environment @@ -85,21 +45,18 @@ * 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. + * RESERVED. */ fenv_t __fe_dfl_env = { { - __INITIAL_NPXCW__, /* Control word register */ - 0x0, /* Unused */ - 0x0000, /* Status word register */ - 0x0, /* Unused */ - 0x0000ffff, /* Tag word register */ - 0x0, /* Unused */ + 0xffff0000 | __INITIAL_NPXCW__, /* Control word register */ + 0xffff0000, /* Status word register */ + 0xffffffff, /* Tag word register */ { - 0x0000, 0x0000, - 0x0000, 0xffff + 0x00000000, + 0x00000000, + 0x00000000, + 0xffff0000 } }, __INITIAL_MXCSR__ /* MXCSR register */ @@ -138,30 +95,27 @@ static void __test_sse(void) int feclearexcept(int excepts) { - fenv_t env; - uint32_t mxcsr; - int ex; + fenv_t fenv; + unsigned int mxcsr; - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; - ex = excepts & FE_ALL_EXCEPT; + /* Store the current x87 floating-point environment */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (fenv)); - /* 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); - } + /* Clear the requested floating-point exceptions */ + fenv.__x87.__status &= ~excepts; + + /* Load the x87 floating-point environent */ + __asm__ __volatile__ ("fldenv %0" : : "m" (fenv)); + /* Same for SSE environment */ if (__HAS_SSE) { - __stmxcsr(&mxcsr); - mxcsr &= ~ex; - __ldmxcsr(mxcsr); + __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); + mxcsr &= ~excepts; + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); } - /* Success */ return (0); } @@ -173,24 +127,21 @@ feclearexcept(int excepts) int fegetexceptflag(fexcept_t *flagp, int excepts) { - uint32_t mxcsr; - uint16_t status; - int ex; + unsigned short status; + unsigned int mxcsr = 0; - _DIAGASSERT(flagp != NULL); - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; - ex = excepts & FE_ALL_EXCEPT; + /* Store the current x87 status register */ + __asm__ __volatile__ ("fnstsw %0" : "=am" (status)); - __fnstsw(&status); + /* Store the MXCSR register */ if (__HAS_SSE) - __stmxcsr(&mxcsr); - else - mxcsr = 0; + __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); - *flagp = (mxcsr | status) & ex; + /* Store the results in flagp */ + *flagp = (status | mxcsr) & excepts; - /* Success */ return (0); } @@ -207,15 +158,11 @@ fegetexceptflag(fexcept_t *flagp, int excepts) int feraiseexcept(int excepts) { - fexcept_t ex; + excepts &= FE_ALL_EXCEPT; - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + fesetexceptflag((fexcept_t *)&excepts, excepts); + __asm__ __volatile__ ("fwait"); - ex = excepts & FE_ALL_EXCEPT; - fesetexceptflag(&ex, excepts); - __fwait(); - - /* Success */ return (0); } @@ -227,28 +174,29 @@ feraiseexcept(int excepts) int fesetexceptflag(const fexcept_t *flagp, int excepts) { - fenv_t env; - uint32_t mxcsr; - int ex; + fenv_t fenv; + unsigned int mxcsr; + + excepts &= FE_ALL_EXCEPT; - _DIAGASSERT(flagp != NULL); - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + /* Store the current x87 floating-point environment */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (fenv)); - ex = excepts & FE_ALL_EXCEPT; + /* Set the requested status flags */ + fenv.__x87.__status &= ~excepts; + fenv.__x87.__status |= *flagp & excepts; - __fnstenv(&env); - env.x87.status &= ~ex; - env.x87.status |= *flagp & ex; - __fldenv(env); + /* Load the x87 floating-point environent */ + __asm__ __volatile__ ("fldenv %0" : : "m" (fenv)); + /* Same for SSE environment */ if (__HAS_SSE) { - __stmxcsr(&mxcsr); - mxcsr &= ~ex; - mxcsr |= *flagp & ex; - __ldmxcsr(mxcsr); + __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); + mxcsr &= ~excepts; + mxcsr |= *flagp & excepts; + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); } - /* Success */ return (0); } @@ -260,27 +208,28 @@ fesetexceptflag(const fexcept_t *flagp, int excepts) int fetestexcept(int excepts) { - uint32_t mxcsr; - uint16_t status; - int ex; + unsigned short status; + unsigned int mxcsr = 0; - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; - ex = excepts & FE_ALL_EXCEPT; + /* Store the current x87 status register */ + __asm__ __volatile__ ("fnstsw %0" : "=am" (status)); - __fnstsw(&status); + /* Store the MXCSR register state */ if (__HAS_SSE) - __stmxcsr(&mxcsr); - else - mxcsr = 0; + __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); - return ((status | mxcsr) & ex); + return ((status | mxcsr) & excepts); } +/* + * The fegetround() function gets the current rounding direction. + */ int fegetround(void) { - uint16_t control; + unsigned short control; /* * We assume that the x87 and the SSE unit agree on the @@ -288,40 +237,44 @@ fegetround(void) * out to be about 5 times faster than reading it on the SSE * unit on an Opteron 244. */ - __fnstcw(&control); + __asm__ __volatile__ ("fnstcw %0" : "=m" (control)); - return (control & __X87_ROUND_MASK); + 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. + * 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; + unsigned short control; + unsigned int mxcsr; - if (round & ~__X87_ROUND_MASK) { - /* Failure */ + /* Check whether requested rounding direction is supported */ + if (round & ~_X87_ROUND_MASK) return (-1); - } - __fnstcw(&control); - control &= ~__X87_ROUND_MASK; + /* Store the current x87 control word register */ + __asm__ __volatile__ ("fnstcw %0" : "=m" (control)); + + /* Set the rounding direction */ + control &= ~_X87_ROUND_MASK; control |= round; - __fldcw(control); + /* Load the x87 control word register */ + __asm__ __volatile__ ("fldcw %0" : : "m" (control)); + + /* Same for the SSE environment */ if (__HAS_SSE) { - __stmxcsr(&mxcsr); - mxcsr &= ~(__X87_ROUND_MASK << __SSE_ROUND_SHIFT); - mxcsr |= round << __SSE_ROUND_SHIFT; - __ldmxcsr(mxcsr); + __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); + mxcsr &= ~(_X87_ROUND_MASK << _SSE_ROUND_SHIFT); + mxcsr |= round << _SSE_ROUND_SHIFT; + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); } - /* Success */ return (0); } @@ -332,49 +285,58 @@ fesetround(int round) int fegetenv(fenv_t *envp) { - uint32_t mxcsr; + /* Store the current x87 floating-point environment */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*envp)); - _DIAGASSERT(flagp != NULL); + /* Store the MXCSR register state */ + if (__HAS_SSE) + __asm__ __volatile__ ("stmxcsr %0" : "=m" (envp->__mxcsr)); /* - * fnstenv masks all exceptions, so we need to restore the old control - * word to avoid this side effect. + * 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 - Vol1 */ - __fnstenv(envp); - __fldcw(envp->x87.control); - if (__HAS_SSE) { - __stmxcsr(&mxcsr); - envp->mxcsr = mxcsr; - } + __asm__ __volatile__ ("fldcw %0" : : "m" (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 + * 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; + unsigned int mxcsr; - _DIAGASSERT(envp != NULL); + /* Store the current x87 floating-point environment */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*envp)); + + /* Clear all exception flags in FPU */ + __asm__ __volatile__ ("fnclex"); - __fnstenv(envp); - __fnclex(); if (__HAS_SSE) { - __stmxcsr(&mxcsr); - envp->mxcsr = mxcsr; + /* Store the MXCSR register state */ + __asm__ __volatile__ ("stmxcsr %0" : "=m" (envp->__mxcsr)); + + /* Clear exception flags in MXCSR */ + mxcsr = envp->__mxcsr; mxcsr &= ~FE_ALL_EXCEPT; - mxcsr |= FE_ALL_EXCEPT << __SSE_EMASK_SHIFT; - __ldmxcsr(mxcsr); + + /* Mask all exceptions */ + mxcsr |= FE_ALL_EXCEPT << _SSE_MASK_SHIFT; + + /* Store the MXCSR register */ + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); } - /* Success */ return (0); } @@ -389,26 +351,13 @@ feholdexcept(fenv_t *envp) int fesetenv(const fenv_t *envp) { - fenv_t env; - - _DIAGASSERT(envp != NULL); + /* Load the x87 floating-point environent */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*envp)); - /* 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); + /* Store the MXCSR register */ if (__HAS_SSE) - __ldmxcsr(envp->mxcsr); + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (envp->__mxcsr)); - /* Success */ return (0); } @@ -423,32 +372,22 @@ fesetenv(const fenv_t *envp) int feupdateenv(const fenv_t *envp) { - fenv_t env; - uint32_t mxcsr; - uint16_t status; - - _DIAGASSERT(envp != NULL); + unsigned short status; + unsigned int mxcsr = 0; - /* Store the x87 floating-point environment */ - memset(&env, 0, sizeof(env)); - __fnstenv(&env); + /* Store the x87 status register */ + __asm__ __volatile__ ("fnstsw %0" : "=am" (status)); - __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); + /* Store the MXCSR register */ if (__HAS_SSE) - __stmxcsr(&mxcsr); - else - mxcsr = 0; + __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); + + /* Install new floating-point environment */ fesetenv(envp); - feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT); - /* Success */ + /* Raise any previously accumulated exceptions */ + feraiseexcept(status | mxcsr); + return (0); } @@ -458,61 +397,61 @@ feupdateenv(const fenv_t *envp) int feenableexcept(int mask) { - uint32_t mxcsr, omask; - uint16_t control; + unsigned int mxcsr = 0, omask; + unsigned short control; mask &= FE_ALL_EXCEPT; - __fnstcw(&control); + + __asm__ __volatile__ ("fnstcw %0" : "=m" (control)); if (__HAS_SSE) - __stmxcsr(&mxcsr); - else - mxcsr = 0; + __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); - omask = (control | mxcsr >> __SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; + omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT; control &= ~mask; - __fldcw(control); + __asm__ __volatile__ ("fldcw %0" : : "m" (control)); + if (__HAS_SSE) { - mxcsr &= ~(mask << __SSE_EMASK_SHIFT); - __ldmxcsr(mxcsr); + mxcsr &= ~(mask << _SSE_MASK_SHIFT); + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); } - return (~omask); + return (omask); } int fedisableexcept(int mask) { - uint32_t mxcsr, omask; - uint16_t control; + unsigned int mxcsr = 0, omask; + unsigned short control; mask &= FE_ALL_EXCEPT; - __fnstcw(&control); + + __asm__ __volatile__ ("fnstcw %0" : "=m" (control)); if (__HAS_SSE) - __stmxcsr(&mxcsr); - else - mxcsr = 0; + __asm__ __volatile__ ("stmxcsr %0" : "=m" (mxcsr)); - omask = (control | mxcsr >> __SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; + omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT; control |= mask; - __fldcw(control); + __asm__ __volatile__ ("fldcw %0" : : "m" (control)); + if (__HAS_SSE) { - mxcsr |= mask << __SSE_EMASK_SHIFT; - __ldmxcsr(mxcsr); + mxcsr |= mask << _SSE_MASK_SHIFT; + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (mxcsr)); } - return (~omask); + return (omask); } int fegetexcept(void) { - uint16_t control; + unsigned short control; /* * We assume that the masks for the x87 and the SSE unit are * the same. */ - __fnstcw(&control); + __asm__ __volatile__ ("fnstcw %0" : "=m" (control)); - return (control & FE_ALL_EXCEPT); + return (~control & FE_ALL_EXCEPT); } diff --git a/lib/libm/arch/m88k/fenv.c b/lib/libm/arch/m88k/fenv.c new file mode 100644 index 00000000000..c0a34508188 --- /dev/null +++ b/lib/libm/arch/m88k/fenv.c @@ -0,0 +1,358 @@ +/* $OpenBSD: fenv.c,v 1.1 2011/04/28 17:34:23 martynas Exp $ */ + +/* + * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/cdefs.h> + +#include <fenv.h> + +/* + * 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(). + */ +fenv_t __fe_dfl_env = { + 0x00000000, /* Control register */ + 0x00000000 /* Status register */ +}; + +/* + * The feclearexcept() function clears the supported floating-point exceptions + * represented by `excepts'. + */ +int +feclearexcept(int excepts) +{ + unsigned int fpsr; + + excepts &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fldcr %0, fcr62" : "=r" (fpsr)); + + /* Clear the requested floating-point exceptions */ + fpsr &= ~excepts; + + /* Load the floating-point status register */ + __asm__ __volatile__ ("fstcr %0, fcr62" : : "r" (fpsr)); + + 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) +{ + unsigned int fpsr; + + excepts &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fldcr %0, fcr62" : "=r" (fpsr)); + + /* Store the results in flagp */ + *flagp = fpsr & excepts; + + return (0); +} + +/* + * The feraiseexcept() function raises the supported floating-point exceptions + * represented by the argument `excepts'. + */ +int +feraiseexcept(int excepts) +{ + volatile double d; + + excepts &= FE_ALL_EXCEPT; + + /* + * 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; + } + __asm__ __volatile__ ("fnop"); + + 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) +{ + unsigned int fpsr; + + excepts &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fldcr %0, fcr62" : "=r" (fpsr)); + + /* Set the requested status flags */ + fpsr &= ~excepts; + fpsr |= *flagp & excepts; + + /* Load the floating-point status register */ + __asm__ __volatile__ ("fstcr %0, fcr62" : : "r" (fpsr)); + + 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) +{ + unsigned int fpsr; + + excepts &= FE_ALL_EXCEPT; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fldcr %0, fcr62" : "=r" (fpsr)); + + return (fpsr & excepts); +} + +/* + * The fegetround() function gets the current rounding direction. + */ +int +fegetround(void) +{ + unsigned int fpcr; + + /* Store the current floating-point control register */ + __asm__ __volatile__ ("fldcr %0, fcr63" : "=r" (fpcr)); + + return (fpcr & _ROUND_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) +{ + unsigned int fpcr; + + /* Check whether requested rounding direction is supported */ + if (round & ~_ROUND_MASK) + return (-1); + + /* Store the current floating-point control register */ + __asm__ __volatile__ ("fldcr %0, fcr63" : "=r" (fpcr)); + + /* Set the rounding direction */ + fpcr &= ~_ROUND_MASK; + fpcr |= round; + + /* Load the floating-point control register */ + __asm__ __volatile__ ("fstcr %0, fcr63" : : "r" (fpcr)); + + 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) +{ + /* Store the current floating-point control and status registers */ + __asm__ __volatile__ ("fldcr %0, fcr63" : "=r" (envp->__control)); + __asm__ __volatile__ ("fldcr %0, fcr62" : "=r" (envp->__status)); + + 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) +{ + unsigned int fpsr, fpcr; + + /* Store the current floating-point control and status registers */ + __asm__ __volatile__ ("fldcr %0, fcr63" : "=r" (envp->__control)); + __asm__ __volatile__ ("fldcr %0, fcr62" : "=r" (envp->__status)); + + /* Clear exception flags in FPSR */ + fpsr = envp->__status; + fpsr &= ~FE_ALL_EXCEPT; + __asm__ __volatile__ ("fstcr %0, fcr62" : : "r" (fpsr)); + + /* Mask all exceptions */ + fpcr = envp->__control; + fpcr &= ~FE_ALL_EXCEPT; + __asm__ __volatile__ ("fstcr %0, fcr63" : : "r" (fpcr)); + + 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; + + /* Store the current floating-point control and status registers */ + __asm__ __volatile__ ("fldcr %0, fcr63" : "=r" (fenv.__control)); + __asm__ __volatile__ ("fldcr %0, fcr62" : "=r" (fenv.__status)); + + /* Set the requested control flags */ + fenv.__control &= ~(FE_ALL_EXCEPT | _ROUND_MASK); + fenv.__control |= envp->__control & (FE_ALL_EXCEPT | _ROUND_MASK); + + /* Set the requested status flags */ + fenv.__status &= ~FE_ALL_EXCEPT; + fenv.__status |= envp->__status & FE_ALL_EXCEPT; + + /* Load the floating-point control and status registers */ + __asm__ __volatile__ ("fstcr %0, fcr63" : : "r" (fenv.__control)); + __asm__ __volatile__ ("fstcr %0, fcr62" : : "r" (fenv.__status)); + + 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) +{ + unsigned int fpsr; + + /* Store the current floating-point status register */ + __asm__ __volatile__ ("fldcr %0, fcr62" : "=r" (fpsr)); + + /* Install new floating-point environment */ + fesetenv(envp); + + /* Raise any previously accumulated exceptions */ + feraiseexcept(fpsr); + + return (0); +} + +/* + * The following functions are extentions to the standard + */ +int +feenableexcept(int mask) +{ + unsigned int fpcr, omask; + + mask &= FE_ALL_EXCEPT; + + /* Store the current floating-point control register */ + __asm__ __volatile__ ("fldcr %0, fcr63" : "=r" (fpcr)); + + omask = fpcr & FE_ALL_EXCEPT; + fpcr |= mask; + + /* Load the floating-point control register */ + __asm__ __volatile__ ("fstcr %0, fcr63" : : "r" (fpcr)); + + return (omask); + +} + +int +fedisableexcept(int mask) +{ + unsigned int fpcr, omask; + + mask &= FE_ALL_EXCEPT; + + /* Store the current floating-point control register */ + __asm__ __volatile__ ("fldcr %0, fcr63" : "=r" (fpcr)); + + omask = fpcr & FE_ALL_EXCEPT; + fpcr &= ~mask; + + /* Load the floating-point control register */ + __asm__ __volatile__ ("fstcr %0, fcr63" : : "r" (fpcr)); + + return (omask); +} + +int +fegetexcept(void) +{ + unsigned int fpcr; + + /* Store the current floating-point control register */ + __asm__ __volatile__ ("fldcr %0, fcr63" : "=r" (fpcr)); + + return (fpcr & FE_ALL_EXCEPT); +} diff --git a/lib/libm/arch/mc68881/fenv.c b/lib/libm/arch/mc68881/fenv.c index ec2419f93ab..4d65045df0c 100644 --- a/lib/libm/arch/mc68881/fenv.c +++ b/lib/libm/arch/mc68881/fenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/20 22:27:59 martynas Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ /* * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org> @@ -30,8 +30,8 @@ * feupdateenv(). */ fenv_t __fe_dfl_env = { - 0x00000000, /* Control register */ - 0x00000000 /* Status register */ + 0x00000000, /* Control register */ + 0x00000000 /* Status register */ }; /* @@ -172,6 +172,7 @@ fegetround(void) { unsigned int fpcr; + /* Store the current floating-point control register */ __asm__ __volatile__ ("fmovel fpcr, %0" : "=dm" (fpcr)); return (fpcr & _ROUND_MASK); @@ -194,9 +195,7 @@ fesetround(int round) /* Store the current floating-point control register */ __asm__ __volatile__ ("fmovel fpcr, %0" : "=dm" (fpcr)); - /* - * Set the rounding direction - */ + /* Set the rounding direction */ fpcr &= ~_ROUND_MASK; fpcr |= round; @@ -242,7 +241,7 @@ feholdexcept(fenv_t *envp) /* Mask all exceptions */ fpcr = envp->__control; - fpcr &= ~(FE_ALL_EXCEPT << _EMASK_SHIFT); + fpcr &= ~(FE_ALL_EXCEPT << _MASK_SHIFT); __asm__ __volatile__ ("fmovel %0, fpcr" : : "dm" (fpcr)); return (0); @@ -266,15 +265,15 @@ fesetenv(const fenv_t *envp) __asm__ __volatile__ ("fmovel fpsr, %0" : "=dm" (fenv.__status)); /* Set the requested control flags */ - fenv.__control &= ~((FE_ALL_EXCEPT << _EMASK_SHIFT) | _ROUND_MASK); - fenv.__control |= envp->__control & ((FE_ALL_EXCEPT << _EMASK_SHIFT) | + fenv.__control &= ~((FE_ALL_EXCEPT << _MASK_SHIFT) | _ROUND_MASK); + fenv.__control |= envp->__control & ((FE_ALL_EXCEPT << _MASK_SHIFT) | _ROUND_MASK); /* Set the requested status flags */ fenv.__status &= ~FE_ALL_EXCEPT; fenv.__status |= envp->__status & FE_ALL_EXCEPT; - /* Load the current floating-point control and status registers */ + /* Load the floating-point control and status registers */ __asm__ __volatile__ ("fmovel %0, fpcr" : : "dm" (fenv.__control)); __asm__ __volatile__ ("fmovel %0, fpsr" : : "dm" (fenv.__status)); @@ -319,8 +318,8 @@ feenableexcept(int mask) /* Store the current floating-point control register */ __asm__ __volatile__ ("fmovel fpcr, %0" : "=dm" (fpcr)); - omask = (fpcr >> _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpcr |= mask << _EMASK_SHIFT; + omask = (fpcr >> _MASK_SHIFT) & FE_ALL_EXCEPT; + fpcr |= mask << _MASK_SHIFT; /* Load the floating-point control register */ __asm__ __volatile__ ("fmovel %0, fpcr" : : "dm" (fpcr)); @@ -339,8 +338,8 @@ fedisableexcept(int mask) /* Store the current floating-point control register */ __asm__ __volatile__ ("fmovel fpcr, %0" : "=dm" (fpcr)); - omask = (fpcr >> _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpcr &= ~(mask << _EMASK_SHIFT); + omask = (fpcr >> _MASK_SHIFT) & FE_ALL_EXCEPT; + fpcr &= ~(mask << _MASK_SHIFT); /* Load the floating-point control register */ __asm__ __volatile__ ("fmovel %0, fpcr" : : "dm" (fpcr)); @@ -356,5 +355,5 @@ fegetexcept(void) /* Store the current floating-point control register */ __asm__ __volatile__ ("fmovel fpcr, %0" : "=dm" (fpcr)); - return ((fpcr >> _EMASK_SHIFT) & FE_ALL_EXCEPT); + return ((fpcr >> _MASK_SHIFT) & FE_ALL_EXCEPT); } diff --git a/lib/libm/arch/mips64/fenv.c b/lib/libm/arch/mips64/fenv.c index 3f8bdfc8c3c..72f9bd6dc54 100644 --- a/lib/libm/arch/mips64/fenv.c +++ b/lib/libm/arch/mips64/fenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/26 21:14:07 martynas Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ /* * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org> @@ -38,18 +38,18 @@ fenv_t __fe_dfl_env = 0; int feclearexcept(int excepts) { - unsigned int fpscr; + unsigned int fcsr; excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); /* Clear the requested floating-point exceptions */ - fpscr &= ~excepts; + fcsr &= ~excepts; - /* Load the floating-point status register */ - __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fpscr)); + /* Load the floating-point control and status register */ + __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fcsr)); return (0); } @@ -62,15 +62,15 @@ feclearexcept(int excepts) int fegetexceptflag(fexcept_t *flagp, int excepts) { - unsigned int fpscr; + unsigned int fcsr; excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); /* Store the results in flagp */ - *flagp = fpscr & excepts; + *flagp = fcsr & excepts; return (0); } @@ -82,17 +82,17 @@ fegetexceptflag(fexcept_t *flagp, int excepts) int feraiseexcept(int excepts) { - unsigned int fpscr; + unsigned int fcsr; excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); - fpscr |= excepts | (excepts << 10); + fcsr |= excepts | (excepts << 10); - /* Load the floating-point status register */ - __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fpscr)); + /* Load the floating-point control and status register */ + __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fcsr)); return (0); } @@ -105,19 +105,19 @@ feraiseexcept(int excepts) int fesetexceptflag(const fexcept_t *flagp, int excepts) { - unsigned int fpscr; + unsigned int fcsr; excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); /* Set the requested status flags */ - fpscr &= ~excepts; - fpscr |= *flagp & excepts; + fcsr &= ~excepts; + fcsr |= *flagp & excepts; - /* Load the floating-point status register */ - __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fpscr)); + /* Load the floating-point control and status register */ + __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fcsr)); return (0); } @@ -130,14 +130,14 @@ fesetexceptflag(const fexcept_t *flagp, int excepts) int fetestexcept(int excepts) { - unsigned int fpscr; + unsigned int fcsr; excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); - return (fpscr & excepts); + return (fcsr & excepts); } /* @@ -146,11 +146,12 @@ fetestexcept(int excepts) int fegetround(void) { - unsigned int fpscr; + unsigned int fcsr; - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); - return (fpscr & _ROUND_MASK); + return (fcsr & _ROUND_MASK); } /* @@ -161,23 +162,21 @@ fegetround(void) int fesetround(int round) { - unsigned int fpscr; + unsigned int fcsr; /* Check whether requested rounding direction is supported */ if (round & ~_ROUND_MASK) return (-1); - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); - /* - * Set the rounding direction - */ - fpscr &= ~_ROUND_MASK; - fpscr |= round; + /* Set the rounding direction */ + fcsr &= ~_ROUND_MASK; + fcsr |= round; - /* Load the floating-point status register */ - __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fpscr)); + /* Load the floating-point control and status register */ + __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fcsr)); return (0); } @@ -189,7 +188,7 @@ fesetround(int round) int fegetenv(fenv_t *envp) { - /* Store the current floating-point status register */ + /* Store the current floating-point control and status register */ __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (*envp)); return (0); @@ -204,18 +203,18 @@ fegetenv(fenv_t *envp) int feholdexcept(fenv_t *envp) { - unsigned int fpscr; + unsigned int fcsr; - /* Store the current floating-point status register */ + /* Store the current floating-point control and status register */ __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (*envp)); - /* Clear exception flags in FPSR */ - fpscr = *envp; - fpscr &= ~FE_ALL_EXCEPT; + /* Clear exception flags in FCSR */ + fcsr = *envp; + fcsr &= ~FE_ALL_EXCEPT; /* Mask all exceptions */ - fpscr &= ~(FE_ALL_EXCEPT << _EMASK_SHIFT); - __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fpscr)); + fcsr &= ~(FE_ALL_EXCEPT << _MASK_SHIFT); + __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fcsr)); return (0); } @@ -231,7 +230,7 @@ feholdexcept(fenv_t *envp) int fesetenv(const fenv_t *envp) { - /* Load the floating-point status register */ + /* Load the floating-point control and status register */ __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (*envp)); return (0); @@ -248,16 +247,16 @@ fesetenv(const fenv_t *envp) int feupdateenv(const fenv_t *envp) { - unsigned int fpscr; + unsigned int fcsr; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); /* Install new floating-point environment */ fesetenv(envp); /* Raise any previously accumulated exceptions */ - feraiseexcept(fpscr); + feraiseexcept(fcsr); return (0); } @@ -268,18 +267,18 @@ feupdateenv(const fenv_t *envp) int feenableexcept(int mask) { - unsigned int fpscr, omask; + unsigned int fcsr, omask; mask &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); - omask = (fpscr >> _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpscr |= mask << _EMASK_SHIFT; + omask = (fcsr >> _MASK_SHIFT) & FE_ALL_EXCEPT; + fcsr |= mask << _MASK_SHIFT; - /* Load the floating-point status register */ - __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fpscr)); + /* Load the floating-point control and status register */ + __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fcsr)); return (omask); @@ -288,18 +287,18 @@ feenableexcept(int mask) int fedisableexcept(int mask) { - unsigned int fpscr, omask; + unsigned int fcsr, omask; mask &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); - omask = (fpscr >> _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpscr &= ~(mask << _EMASK_SHIFT); + omask = (fcsr >> _MASK_SHIFT) & FE_ALL_EXCEPT; + fcsr &= ~(mask << _MASK_SHIFT); - /* Load the floating-point status register */ - __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fpscr)); + /* Load the floating-point control and status register */ + __asm__ __volatile__ ("ctc1 %0, $31" : : "r" (fcsr)); return (omask); } @@ -307,10 +306,10 @@ fedisableexcept(int mask) int fegetexcept(void) { - unsigned int fpscr; + unsigned int fcsr; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fpscr)); + /* Store the current floating-point control and status register */ + __asm__ __volatile__ ("cfc1 %0, $31" : "=r" (fcsr)); - return ((fpscr >> _EMASK_SHIFT) & FE_ALL_EXCEPT); + return ((fcsr >> _MASK_SHIFT) & FE_ALL_EXCEPT); } diff --git a/lib/libm/arch/powerpc/fenv.c b/lib/libm/arch/powerpc/fenv.c index 633fe3e7061..7f31179f177 100644 --- a/lib/libm/arch/powerpc/fenv.c +++ b/lib/libm/arch/powerpc/fenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/25 20:34:09 martynas Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ /* * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org> @@ -20,6 +20,11 @@ #include <fenv.h> +union u { + unsigned long long fpscr; + unsigned int bits[2]; +}; + /* * The following constant represents the default floating-point environment * (that is, the one installed at program startup) and has type pointer to @@ -38,22 +43,19 @@ fenv_t __fe_dfl_env = 0; int feclearexcept(int excepts) { - struct { - unsigned int bits[2]; - } fpscr; - + union u u; excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); /* Clear the requested floating-point exceptions */ - fpscr.bits[1] &= ~excepts; + u.bits[1] &= ~excepts; if (excepts & FE_INVALID) - fpscr.bits[1] &= ~_FE_INVALID_ALL; + u.bits[1] &= ~_FE_INVALID_ALL; - /* Load the floating-point status register */ - __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (fpscr)); + /* Load the floating-point status and control register */ + __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (u.fpscr)); return (0); } @@ -66,17 +68,15 @@ feclearexcept(int excepts) int fegetexceptflag(fexcept_t *flagp, int excepts) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr.bits)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); /* Store the results in flagp */ - *flagp = fpscr.bits[1] & excepts; + *flagp = u.bits[1] & excepts; return (0); } @@ -103,27 +103,25 @@ feraiseexcept(int excepts) int fesetexceptflag(const fexcept_t *flagp, int excepts) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); /* Set the requested status flags */ - fpscr.bits[1] &= ~excepts; - fpscr.bits[1] |= *flagp & excepts; + u.bits[1] &= ~excepts; + u.bits[1] |= *flagp & excepts; if (excepts & FE_INVALID) { if (*flagp & FE_INVALID) - fpscr.bits[1] |= _FE_INVALID_SOFT; + u.bits[1] |= _FE_INVALID_SOFT; else - fpscr.bits[1] &= ~_FE_INVALID_ALL; + u.bits[1] &= ~_FE_INVALID_ALL; } - /* Load the floating-point status register */ - __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (fpscr)); + /* Load the floating-point status and control register */ + __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (u.fpscr)); return (0); } @@ -136,16 +134,14 @@ fesetexceptflag(const fexcept_t *flagp, int excepts) int fetestexcept(int excepts) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr.bits)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); - return (fpscr.bits[1] & excepts); + return (u.bits[1] & excepts); } /* @@ -154,13 +150,12 @@ fetestexcept(int excepts) int fegetround(void) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); - return (fpscr.bits[1] & _ROUND_MASK); + return (u.bits[1] & _ROUND_MASK); } /* @@ -171,25 +166,21 @@ fegetround(void) int fesetround(int round) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; /* Check whether requested rounding direction is supported */ if (round & ~_ROUND_MASK) return (-1); - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); - /* - * Set the rounding direction - */ - fpscr.bits[1] &= ~_ROUND_MASK; - fpscr.bits[1] |= round; + /* Set the rounding direction */ + u.bits[1] &= ~_ROUND_MASK; + u.bits[1] |= round; - /* Load the floating-point status register */ - __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (fpscr)); + /* Load the floating-point status and control register */ + __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (u.fpscr)); return (0); } @@ -201,14 +192,12 @@ fesetround(int round) int fegetenv(fenv_t *envp) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); - *envp = fpscr.bits[1]; + *envp = u.bits[1]; return (0); } @@ -222,21 +211,19 @@ fegetenv(fenv_t *envp) int feholdexcept(fenv_t *envp) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); - *envp = fpscr.bits[1]; + *envp = u.bits[1]; /* Clear exception flags in FPSCR */ - fpscr.bits[1] &= ~(FE_ALL_EXCEPT | _FE_INVALID_ALL); + u.bits[1] &= ~(FE_ALL_EXCEPT | _FE_INVALID_ALL); /* Mask all exceptions */ - fpscr.bits[1] &= ~(FE_ALL_EXCEPT >> _EMASK_SHIFT); - __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (fpscr)); + u.bits[1] &= ~(FE_ALL_EXCEPT >> _MASK_SHIFT); + __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (u.fpscr)); return (0); } @@ -252,15 +239,13 @@ feholdexcept(fenv_t *envp) int fesetenv(const fenv_t *envp) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; - fpscr.bits[0] = 0; - fpscr.bits[1] = *envp; + u.bits[0] = 0; + u.bits[1] = *envp; - /* Load the floating-point status register */ - __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (fpscr)); + /* Load the floating-point status and control register */ + __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (u.fpscr)); return (0); } @@ -276,18 +261,16 @@ fesetenv(const fenv_t *envp) int feupdateenv(const fenv_t *envp) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr.bits)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); /* Install new floating-point environment */ fesetenv(envp); /* Raise any previously accumulated exceptions */ - feraiseexcept(fpscr.bits[1]); + feraiseexcept(u.bits[1]); return (0); } @@ -298,21 +281,19 @@ feupdateenv(const fenv_t *envp) int feenableexcept(int mask) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; unsigned int omask; mask &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); - omask = (fpscr.bits[1] << _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpscr.bits[1] |= mask >> _EMASK_SHIFT; + omask = (u.bits[1] << _MASK_SHIFT) & FE_ALL_EXCEPT; + u.bits[1] |= mask >> _MASK_SHIFT; - /* Load the floating-point status register */ - __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (fpscr)); + /* Load the floating-point status and control register */ + __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (u.fpscr)); return (omask); @@ -321,21 +302,19 @@ feenableexcept(int mask) int fedisableexcept(int mask) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; unsigned int omask; mask &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); - omask = (fpscr.bits[1] << _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpscr.bits[1] &= ~(mask >> _EMASK_SHIFT); + omask = (u.bits[1] << _MASK_SHIFT) & FE_ALL_EXCEPT; + u.bits[1] &= ~(mask >> _MASK_SHIFT); - /* Load the floating-point status register */ - __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (fpscr)); + /* Load the floating-point status and control register */ + __asm__ __volatile__ ("mtfsf 0xff,%0" :: "f" (u.fpscr)); return (omask); } @@ -343,12 +322,10 @@ fedisableexcept(int mask) int fegetexcept(void) { - struct { - unsigned int bits[2]; - } fpscr; + union u u; - /* Store the current floating-point status register */ - __asm__ __volatile__ ("mffs %0" : "=f" (fpscr)); + /* Store the current floating-point status and control register */ + __asm__ __volatile__ ("mffs %0" : "=f" (u.fpscr)); - return ((fpscr.bits[1] << _EMASK_SHIFT) & FE_ALL_EXCEPT); + return ((u.bits[1] << _MASK_SHIFT) & FE_ALL_EXCEPT); } diff --git a/lib/libm/arch/sh/fenv.c b/lib/libm/arch/sh/fenv.c index 02eb84e7a80..32de203a0dc 100644 --- a/lib/libm/arch/sh/fenv.c +++ b/lib/libm/arch/sh/fenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/24 15:05:12 martynas Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ /* * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org> @@ -20,7 +20,7 @@ #include <fenv.h> -extern unsigned int __fpscr_values[2]; +extern unsigned int __fpscr_values[2]; /* * The following constant represents the default floating-point environment @@ -44,7 +44,7 @@ feclearexcept(int excepts) excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); /* Clear the requested floating-point exceptions */ @@ -52,7 +52,7 @@ feclearexcept(int excepts) __fpscr_values[0] &= ~excepts; __fpscr_values[1] &= ~excepts; - /* Load the floating-point status register */ + /* Load the floating-point status and control register */ __asm__ __volatile__ ("lds %0, fpscr" : : "r" (fpscr)); return (0); @@ -70,7 +70,7 @@ fegetexceptflag(fexcept_t *flagp, int excepts) excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); /* Store the results in flagp */ @@ -133,7 +133,7 @@ fesetexceptflag(const fexcept_t *flagp, int excepts) excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); /* Set the requested status flags */ @@ -145,7 +145,7 @@ fesetexceptflag(const fexcept_t *flagp, int excepts) __fpscr_values[0] |= *flagp & excepts; __fpscr_values[1] |= *flagp & excepts; - /* Load the floating-point status register */ + /* Load the floating-point status and control register */ __asm__ __volatile__ ("lds %0, fpscr" : : "r" (fpscr)); return (0); @@ -163,7 +163,7 @@ fetestexcept(int excepts) excepts &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); return (fpscr & excepts); @@ -177,6 +177,7 @@ fegetround(void) { unsigned int fpscr; + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); return (fpscr & _ROUND_MASK); @@ -196,12 +197,10 @@ fesetround(int round) if (round & ~_ROUND_MASK) return (-1); - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); - /* - * Set the rounding direction - */ + /* Set the rounding direction */ fpscr &= ~_ROUND_MASK; __fpscr_values[0] &= ~_ROUND_MASK; __fpscr_values[1] &= ~_ROUND_MASK; @@ -210,7 +209,7 @@ fesetround(int round) __fpscr_values[0] |= round; __fpscr_values[1] |= round; - /* Load the floating-point status register */ + /* Load the floating-point status and control register */ __asm__ __volatile__ ("lds %0, fpscr" : : "r" (fpscr)); return (0); @@ -223,7 +222,7 @@ fesetround(int round) int fegetenv(fenv_t *envp) { - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (*envp)); return (0); @@ -240,22 +239,22 @@ feholdexcept(fenv_t *envp) { unsigned int fpscr; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); *envp = fpscr; - /* Clear exception flags in FPSR */ + /* Clear exception flags in FPSCR */ fpscr &= ~FE_ALL_EXCEPT; __fpscr_values[0] &= ~FE_ALL_EXCEPT; __fpscr_values[1] &= ~FE_ALL_EXCEPT; /* Mask all exceptions */ - fpscr &= ~(FE_ALL_EXCEPT << _EMASK_SHIFT); - __fpscr_values[0] &= ~(FE_ALL_EXCEPT << _EMASK_SHIFT); - __fpscr_values[1] &= ~(FE_ALL_EXCEPT << _EMASK_SHIFT); + fpscr &= ~(FE_ALL_EXCEPT << _MASK_SHIFT); + __fpscr_values[0] &= ~(FE_ALL_EXCEPT << _MASK_SHIFT); + __fpscr_values[1] &= ~(FE_ALL_EXCEPT << _MASK_SHIFT); - /* Load the floating-point status register */ + /* Load the floating-point status and control register */ __asm__ __volatile__ ("lds %0, fpscr" : : "r" (fpscr)); return (0); @@ -274,25 +273,25 @@ fesetenv(const fenv_t *envp) { unsigned int fpscr; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); /* Set the requested flags */ - fpscr &= ~((FE_ALL_EXCEPT << _EMASK_SHIFT) | _ROUND_MASK | + fpscr &= ~((FE_ALL_EXCEPT << _MASK_SHIFT) | _ROUND_MASK | FE_ALL_EXCEPT); - __fpscr_values[0] &= ~((FE_ALL_EXCEPT << _EMASK_SHIFT) | _ROUND_MASK | + __fpscr_values[0] &= ~((FE_ALL_EXCEPT << _MASK_SHIFT) | _ROUND_MASK | FE_ALL_EXCEPT); - __fpscr_values[1] &= ~((FE_ALL_EXCEPT << _EMASK_SHIFT) | _ROUND_MASK | + __fpscr_values[1] &= ~((FE_ALL_EXCEPT << _MASK_SHIFT) | _ROUND_MASK | FE_ALL_EXCEPT); - fpscr |= *envp & ((FE_ALL_EXCEPT << _EMASK_SHIFT) | _ROUND_MASK | + fpscr |= *envp & ((FE_ALL_EXCEPT << _MASK_SHIFT) | _ROUND_MASK | FE_ALL_EXCEPT); - __fpscr_values[0] |= *envp & ((FE_ALL_EXCEPT << _EMASK_SHIFT) | + __fpscr_values[0] |= *envp & ((FE_ALL_EXCEPT << _MASK_SHIFT) | _ROUND_MASK | FE_ALL_EXCEPT); - __fpscr_values[1] |= *envp & ((FE_ALL_EXCEPT << _EMASK_SHIFT) | + __fpscr_values[1] |= *envp & ((FE_ALL_EXCEPT << _MASK_SHIFT) | _ROUND_MASK | FE_ALL_EXCEPT); - /* Load the floating-point status register */ + /* Load the floating-point status and control register */ __asm__ __volatile__ ("lds %0, fpscr" : : "r" (fpscr)); return (0); @@ -311,7 +310,7 @@ feupdateenv(const fenv_t *envp) { unsigned int fpscr; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); /* Install new floating-point environment */ @@ -333,15 +332,15 @@ feenableexcept(int mask) mask &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); - omask = (fpscr >> _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpscr |= mask << _EMASK_SHIFT; - __fpscr_values[0] |= mask << _EMASK_SHIFT; - __fpscr_values[1] |= mask << _EMASK_SHIFT; + omask = (fpscr >> _MASK_SHIFT) & FE_ALL_EXCEPT; + fpscr |= mask << _MASK_SHIFT; + __fpscr_values[0] |= mask << _MASK_SHIFT; + __fpscr_values[1] |= mask << _MASK_SHIFT; - /* Load the floating-point status register */ + /* Load the floating-point status and control register */ __asm__ __volatile__ ("lds %0, fpscr" : : "r" (fpscr)); return (omask); @@ -355,15 +354,15 @@ fedisableexcept(int mask) mask &= FE_ALL_EXCEPT; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); - omask = (fpscr >> _EMASK_SHIFT) & FE_ALL_EXCEPT; - fpscr &= ~(mask << _EMASK_SHIFT); - __fpscr_values[0] &= ~(mask << _EMASK_SHIFT); - __fpscr_values[1] &= ~(mask << _EMASK_SHIFT); + omask = (fpscr >> _MASK_SHIFT) & FE_ALL_EXCEPT; + fpscr &= ~(mask << _MASK_SHIFT); + __fpscr_values[0] &= ~(mask << _MASK_SHIFT); + __fpscr_values[1] &= ~(mask << _MASK_SHIFT); - /* Load the floating-point status register */ + /* Load the floating-point status and control register */ __asm__ __volatile__ ("lds %0, fpscr" : : "r" (fpscr)); return (omask); @@ -374,8 +373,8 @@ fegetexcept(void) { unsigned int fpscr; - /* Store the current floating-point status register */ + /* Store the current floating-point status and control register */ __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr)); - return ((fpscr >> _EMASK_SHIFT) & FE_ALL_EXCEPT); + return ((fpscr >> _MASK_SHIFT) & FE_ALL_EXCEPT); } diff --git a/lib/libm/arch/sparc/fenv.c b/lib/libm/arch/sparc/fenv.c index 7f9544654ae..722973f6f92 100644 --- a/lib/libm/arch/sparc/fenv.c +++ b/lib/libm/arch/sparc/fenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fenv.c,v 1.1 2011/04/25 21:04:29 martynas Exp $ */ +/* $OpenBSD: fenv.c,v 1.2 2011/04/28 17:34:23 martynas Exp $ */ /* $NetBSD: fenv.c,v 1.1 2011/01/31 00:19:33 christos Exp $ */ /*- @@ -26,19 +26,8 @@ */ #include <sys/cdefs.h> -#include <assert.h> #include <fenv.h> -#define _DIAGASSERT(x) ((void) 0) - -/* Load floating-point state register (all 64bits) */ -#define __ldxfsr(__r) __asm__ __volatile__ \ - ("ld %0, %%fsr" : : "m" (__r)) - -/* Save floating-point state register (all 64bits) */ -#define __stxfsr(__r) __asm__ __volatile__ \ - ("st %%fsr, %0" : "=m" (*(__r))) - /* * The following constant represents the default floating-point environment * (that is, the one installed at program startup) and has type pointer to @@ -58,17 +47,17 @@ int feclearexcept(int excepts) { fexcept_t r; - int ex; - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; - ex = excepts & FE_ALL_EXCEPT; + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (r)); - __stxfsr(&r); - r &= ~ex; - __ldxfsr(r); + r &= ~excepts; + + /* Load floating-point state register */ + __asm__ __volatile__ ("ld %0, %%fsr" : : "m" (r)); - /* Success */ return 0; } @@ -81,17 +70,14 @@ int fegetexceptflag(fexcept_t *flagp, int excepts) { fexcept_t r; - int ex; - _DIAGASSERT(flagp != NULL); - _DIAGASSERT((excepts & ~_FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; - ex = excepts & FE_ALL_EXCEPT; + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (r)); - __stxfsr(&r); - *flagp = r & ex; + *flagp = r & excepts; - /* Success */ return 0; } @@ -105,19 +91,18 @@ int fesetexceptflag(const fexcept_t *flagp, int excepts) { fexcept_t r; - int ex; - _DIAGASSERT(flagp != NULL); - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; + + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (r)); - ex = excepts & FE_ALL_EXCEPT; + r &= ~excepts; + r |= *flagp & excepts; - __stxfsr(&r); - r &= ~ex; - r |= *flagp & ex; - __ldxfsr(r); + /* Load floating-point state register */ + __asm__ __volatile__ ("ld %0, %%fsr" : : "m" (r)); - /* Success */ return 0; } @@ -132,11 +117,8 @@ int feraiseexcept(int excepts) { volatile double d; - int ex; - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); - - ex = excepts & FE_ALL_EXCEPT; + excepts &= FE_ALL_EXCEPT; /* * With a compiler that supports the FENV_ACCESS pragma properly, simple @@ -144,28 +126,27 @@ feraiseexcept(int excepts) * Unfortunately, we need to bring a volatile variable into the equation * to prevent incorrect optimizations. */ - if (ex & FE_INVALID) { + if (excepts & FE_INVALID) { d = 0.0; d = 0.0 / d; } - if (ex & FE_DIVBYZERO) { + if (excepts & FE_DIVBYZERO) { d = 0.0; d = 1.0 / d; } - if (ex & FE_OVERFLOW) { + if (excepts & FE_OVERFLOW) { d = 0x1.ffp1023; d *= 2.0; } - if (ex & FE_UNDERFLOW) { + if (excepts & FE_UNDERFLOW) { d = 0x1p-1022; d /= 0x1p1023; } - if (ex & FE_INEXACT) { + if (excepts & FE_INEXACT) { d = 0x1p-1022; d += 1.0; } - /* Success */ return 0; } @@ -179,11 +160,12 @@ fetestexcept(int excepts) { fexcept_t r; - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; - __stxfsr(&r); + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (r)); - return r & (excepts & FE_ALL_EXCEPT); + return r & excepts; } /* @@ -194,7 +176,8 @@ fegetround(void) { fenv_t r; - __stxfsr(&r); + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (r)); return (r >> _ROUND_SHIFT) & _ROUND_MASK; } @@ -209,16 +192,18 @@ fesetround(int round) { fenv_t r; - _DIAGASSERT((round & ~_ROUND_MASK) == 0); if (round & ~_ROUND_MASK) return -1; - __stxfsr(&r); + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (r)); + r &= ~(_ROUND_MASK << _ROUND_SHIFT); r |= round << _ROUND_SHIFT; - __ldxfsr(r); - /* Success */ + /* Load floating-point state register */ + __asm__ __volatile__ ("ld %0, %%fsr" : : "m" (r)); + return 0; } @@ -229,11 +214,9 @@ fesetround(int round) int fegetenv(fenv_t *envp) { - _DIAGASSERT(envp != NULL); - - __stxfsr(envp); + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (*envp)); - /* Success */ return 0; } @@ -249,14 +232,15 @@ feholdexcept(fenv_t *envp) { fenv_t r; - _DIAGASSERT(envp != NULL); + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (r)); - __stxfsr(&r); *envp = r; - r &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); - __ldxfsr(r); + r &= ~(FE_ALL_EXCEPT | (FE_ALL_EXCEPT << _MASK_SHIFT)); + + /* Load floating-point state register */ + __asm__ __volatile__ ("ld %0, %%fsr" : : "m" (r)); - /* Success */ return 0; } @@ -271,11 +255,9 @@ feholdexcept(fenv_t *envp) int fesetenv(const fenv_t *envp) { - _DIAGASSERT(envp != NULL); - - __ldxfsr(*envp); + /* Load floating-point state register */ + __asm__ __volatile__ ("ld %0, %%fsr" : : "m" (*envp)); - /* Success */ return 0; } @@ -293,15 +275,14 @@ feupdateenv(const fenv_t *envp) { fexcept_t r; - _DIAGASSERT(envp != NULL); + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (r)); - __stxfsr(&r); - __ldxfsr(*envp); + /* Load floating-point state register */ + __asm__ __volatile__ ("ld %0, %%fsr" : : "m" (*envp)); - _DIAGASSERT((r & ~FE_ALL_EXCEPT) == 0); feraiseexcept(r & FE_ALL_EXCEPT); - /* Success */ return 0; } @@ -313,11 +294,17 @@ feenableexcept(int mask) { fenv_t old_r, new_r; - __stxfsr(&old_r); - new_r = old_r | ((mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); - __ldxfsr(new_r); + mask &= FE_ALL_EXCEPT; + + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (old_r)); + + new_r = old_r | (mask << _MASK_SHIFT); + + /* Load floating-point state register */ + __asm__ __volatile__ ("ld %0, %%fsr" : : "m" (new_r)); - return (old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT; + return (old_r >> _MASK_SHIFT) & FE_ALL_EXCEPT; } int @@ -325,11 +312,17 @@ fedisableexcept(int mask) { fenv_t old_r, new_r; - __stxfsr(&old_r); - new_r = old_r & ~((mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); - __ldxfsr(new_r); + mask &= FE_ALL_EXCEPT; - return (old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT; + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (old_r)); + + new_r = old_r & ~(mask << _MASK_SHIFT); + + /* Load floating-point state register */ + __asm__ __volatile__ ("ld %0, %%fsr" : : "m" (new_r)); + + return (old_r >> _MASK_SHIFT) & FE_ALL_EXCEPT; } int @@ -337,6 +330,8 @@ fegetexcept(void) { fenv_t r; - __stxfsr(&r); - return (r & _ENABLE_MASK) >> _FPUSW_SHIFT; + /* Save floating-point state register */ + __asm__ __volatile__ ("st %%fsr, %0" : "=m" (r)); + + return (r & (FE_ALL_EXCEPT << _MASK_SHIFT)) >> _MASK_SHIFT; } diff --git a/lib/libm/arch/sparc64/fenv.c b/lib/libm/arch/sparc64/fenv.c index 75fb354c6d4..b865c7ec388 100644 --- a/lib/libm/arch/sparc64/fenv.c +++ b/lib/libm/arch/sparc64/fenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fenv.c,v 1.2 2011/04/25 21:04:29 martynas Exp $ */ +/* $OpenBSD: fenv.c,v 1.3 2011/04/28 17:34:23 martynas Exp $ */ /* $NetBSD: fenv.c,v 1.1 2011/01/31 00:19:33 christos Exp $ */ /*- @@ -26,19 +26,8 @@ */ #include <sys/cdefs.h> -#include <assert.h> #include <fenv.h> -#define _DIAGASSERT(x) ((void) 0) - -/* Load floating-point state register (all 64bits) */ -#define __ldxfsr(__r) __asm__ __volatile__ \ - ("ldx %0, %%fsr" : : "m" (__r)) - -/* Save floating-point state register (all 64bits) */ -#define __stxfsr(__r) __asm__ __volatile__ \ - ("stx %%fsr, %0" : "=m" (*(__r))) - /* * The following constant represents the default floating-point environment * (that is, the one installed at program startup) and has type pointer to @@ -58,17 +47,17 @@ int feclearexcept(int excepts) { fexcept_t r; - int ex; - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; - ex = excepts & FE_ALL_EXCEPT; + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (r)); - __stxfsr(&r); - r &= ~ex; - __ldxfsr(r); + r &= ~excepts; + + /* Load floating-point state register */ + __asm__ __volatile__ ("ldx %0, %%fsr" : : "m" (r)); - /* Success */ return 0; } @@ -81,17 +70,14 @@ int fegetexceptflag(fexcept_t *flagp, int excepts) { fexcept_t r; - int ex; - _DIAGASSERT(flagp != NULL); - _DIAGASSERT((excepts & ~_FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; - ex = excepts & FE_ALL_EXCEPT; + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (r)); - __stxfsr(&r); - *flagp = r & ex; + *flagp = r & excepts; - /* Success */ return 0; } @@ -105,19 +91,18 @@ int fesetexceptflag(const fexcept_t *flagp, int excepts) { fexcept_t r; - int ex; - _DIAGASSERT(flagp != NULL); - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; + + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (r)); - ex = excepts & FE_ALL_EXCEPT; + r &= ~excepts; + r |= *flagp & excepts; - __stxfsr(&r); - r &= ~ex; - r |= *flagp & ex; - __ldxfsr(r); + /* Load floating-point state register */ + __asm__ __volatile__ ("ldx %0, %%fsr" : : "m" (r)); - /* Success */ return 0; } @@ -132,11 +117,8 @@ int feraiseexcept(int excepts) { volatile double d; - int ex; - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); - - ex = excepts & FE_ALL_EXCEPT; + excepts &= FE_ALL_EXCEPT; /* * With a compiler that supports the FENV_ACCESS pragma properly, simple @@ -144,28 +126,27 @@ feraiseexcept(int excepts) * Unfortunately, we need to bring a volatile variable into the equation * to prevent incorrect optimizations. */ - if (ex & FE_INVALID) { + if (excepts & FE_INVALID) { d = 0.0; d = 0.0 / d; } - if (ex & FE_DIVBYZERO) { + if (excepts & FE_DIVBYZERO) { d = 0.0; d = 1.0 / d; } - if (ex & FE_OVERFLOW) { + if (excepts & FE_OVERFLOW) { d = 0x1.ffp1023; d *= 2.0; } - if (ex & FE_UNDERFLOW) { + if (excepts & FE_UNDERFLOW) { d = 0x1p-1022; d /= 0x1p1023; } - if (ex & FE_INEXACT) { + if (excepts & FE_INEXACT) { d = 0x1p-1022; d += 1.0; } - /* Success */ return 0; } @@ -179,11 +160,12 @@ fetestexcept(int excepts) { fexcept_t r; - _DIAGASSERT((excepts & ~FE_ALL_EXCEPT) == 0); + excepts &= FE_ALL_EXCEPT; - __stxfsr(&r); + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (r)); - return r & (excepts & FE_ALL_EXCEPT); + return r & excepts; } /* @@ -194,7 +176,8 @@ fegetround(void) { fenv_t r; - __stxfsr(&r); + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (r)); return (r >> _ROUND_SHIFT) & _ROUND_MASK; } @@ -209,16 +192,18 @@ fesetround(int round) { fenv_t r; - _DIAGASSERT((round & ~_ROUND_MASK) == 0); if (round & ~_ROUND_MASK) return -1; - __stxfsr(&r); + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (r)); + r &= ~(_ROUND_MASK << _ROUND_SHIFT); r |= round << _ROUND_SHIFT; - __ldxfsr(r); - /* Success */ + /* Load floating-point state register */ + __asm__ __volatile__ ("ldx %0, %%fsr" : : "m" (r)); + return 0; } @@ -229,11 +214,9 @@ fesetround(int round) int fegetenv(fenv_t *envp) { - _DIAGASSERT(envp != NULL); - - __stxfsr(envp); + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (*envp)); - /* Success */ return 0; } @@ -249,14 +232,15 @@ feholdexcept(fenv_t *envp) { fenv_t r; - _DIAGASSERT(envp != NULL); + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (r)); - __stxfsr(&r); *envp = r; - r &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); - __ldxfsr(r); + r &= ~(FE_ALL_EXCEPT | (FE_ALL_EXCEPT << _MASK_SHIFT)); + + /* Load floating-point state register */ + __asm__ __volatile__ ("ldx %0, %%fsr" : : "m" (r)); - /* Success */ return 0; } @@ -271,11 +255,9 @@ feholdexcept(fenv_t *envp) int fesetenv(const fenv_t *envp) { - _DIAGASSERT(envp != NULL); - - __ldxfsr(*envp); + /* Load floating-point state register */ + __asm__ __volatile__ ("ldx %0, %%fsr" : : "m" (*envp)); - /* Success */ return 0; } @@ -293,15 +275,14 @@ feupdateenv(const fenv_t *envp) { fexcept_t r; - _DIAGASSERT(envp != NULL); + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (r)); - __stxfsr(&r); - __ldxfsr(*envp); + /* Load floating-point state register */ + __asm__ __volatile__ ("ldx %0, %%fsr" : : "m" (*envp)); - _DIAGASSERT((r & ~FE_ALL_EXCEPT) == 0); feraiseexcept(r & FE_ALL_EXCEPT); - /* Success */ return 0; } @@ -313,11 +294,17 @@ feenableexcept(int mask) { fenv_t old_r, new_r; - __stxfsr(&old_r); - new_r = old_r | ((mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); - __ldxfsr(new_r); + mask &= FE_ALL_EXCEPT; + + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (old_r)); + + new_r = old_r | (mask << _MASK_SHIFT); + + /* Load floating-point state register */ + __asm__ __volatile__ ("ldx %0, %%fsr" : : "m" (new_r)); - return (old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT; + return (old_r >> _MASK_SHIFT) & FE_ALL_EXCEPT; } int @@ -325,11 +312,17 @@ fedisableexcept(int mask) { fenv_t old_r, new_r; - __stxfsr(&old_r); - new_r = old_r & ~((mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); - __ldxfsr(new_r); + mask &= FE_ALL_EXCEPT; - return (old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT; + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (old_r)); + + new_r = old_r & ~(mask << _MASK_SHIFT); + + /* Load floating-point state register */ + __asm__ __volatile__ ("ldx %0, %%fsr" : : "m" (new_r)); + + return (old_r >> _MASK_SHIFT) & FE_ALL_EXCEPT; } int @@ -337,6 +330,8 @@ fegetexcept(void) { fenv_t r; - __stxfsr(&r); - return (r & _ENABLE_MASK) >> _FPUSW_SHIFT; + /* Save floating-point state register */ + __asm__ __volatile__ ("stx %%fsr, %0" : "=m" (r)); + + return (r & (FE_ALL_EXCEPT << _MASK_SHIFT)) >> _MASK_SHIFT; } |