summaryrefslogtreecommitdiff
path: root/lib/libm/arch
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libm/arch')
-rw-r--r--lib/libm/arch/alpha/fenv.c19
-rw-r--r--lib/libm/arch/amd64/fenv.c71
-rw-r--r--lib/libm/arch/arm/fenv.c10
-rw-r--r--lib/libm/arch/hppa/fenv.c135
-rw-r--r--lib/libm/arch/hppa64/fenv.c372
-rw-r--r--lib/libm/arch/i387/fenv.c381
-rw-r--r--lib/libm/arch/m88k/fenv.c358
-rw-r--r--lib/libm/arch/mc68881/fenv.c29
-rw-r--r--lib/libm/arch/mips64/fenv.c143
-rw-r--r--lib/libm/arch/powerpc/fenv.c183
-rw-r--r--lib/libm/arch/sh/fenv.c85
-rw-r--r--lib/libm/arch/sparc/fenv.c157
-rw-r--r--lib/libm/arch/sparc64/fenv.c157
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;
}