diff options
author | Martynas Venckus <martynas@cvs.openbsd.org> | 2011-04-28 17:34:24 +0000 |
---|---|---|
committer | Martynas Venckus <martynas@cvs.openbsd.org> | 2011-04-28 17:34:24 +0000 |
commit | f70eacf51aa926a56332357f2fd9556df8f52acb (patch) | |
tree | 8f92efc601af164ae9d2320e5eeae77bc248a633 /lib/libm/arch/sparc/fenv.c | |
parent | 8fbde66430aa8b0773d3387e5e56968cd07a3156 (diff) |
fenv improvements and cleanups
Diffstat (limited to 'lib/libm/arch/sparc/fenv.c')
-rw-r--r-- | lib/libm/arch/sparc/fenv.c | 157 |
1 files changed, 76 insertions, 81 deletions
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; } |