aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Schultz <das@FreeBSD.org>2005-03-16 19:03:46 +0000
committerDavid Schultz <das@FreeBSD.org>2005-03-16 19:03:46 +0000
commit10b01832c3672b9a63edd86f74f1167dbc33c7f6 (patch)
treeed1345d1aaf08f9b2af1cfc6cc10e15b82d917d1 /lib
parentc4bf1e9092058df57b90b2090eb4591d7158c521 (diff)
downloadsrc-10b01832c3672b9a63edd86f74f1167dbc33c7f6.tar.gz
src-10b01832c3672b9a63edd86f74f1167dbc33c7f6.zip
Replace fegetmask() and fesetmask() with feenableexcept(),
fedisableexcept(), and fegetexcept(). These two sets of routines provide the same functionality. I implemented the former as an undocumented internal interface to make the regression test easier to write. However, fe(enable|disable|get)except() is already part of glibc, and I would like to avoid gratuitous differences. The only major flaw in the glibc API is that there's no good way to report errors on processors that don't support all the unmasked exceptions.
Notes
Notes: svn path=/head/; revision=143708
Diffstat (limited to 'lib')
-rw-r--r--lib/msun/alpha/fenv.c25
-rw-r--r--lib/msun/alpha/fenv.h7
-rw-r--r--lib/msun/amd64/fenv.c27
-rw-r--r--lib/msun/amd64/fenv.h7
-rw-r--r--lib/msun/arm/fenv.h28
-rw-r--r--lib/msun/i387/fenv.h19
-rw-r--r--lib/msun/ia64/fenv.h19
-rw-r--r--lib/msun/man/fenv.341
-rw-r--r--lib/msun/powerpc/fenv.h22
-rw-r--r--lib/msun/sparc64/fenv.h28
10 files changed, 166 insertions, 57 deletions
diff --git a/lib/msun/alpha/fenv.c b/lib/msun/alpha/fenv.c
index 017cd7a5b3c1..5f0182c696f0 100644
--- a/lib/msun/alpha/fenv.c
+++ b/lib/msun/alpha/fenv.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -109,17 +109,29 @@ feupdateenv(const fenv_t *envp)
}
int
-__fesetmask(int mask)
+__feenableexcept(int mask)
{
struct mask_args p;
- p.mask = mask;
+ sysarch(ALPHA_GET_FPMASK, &p);
+ p.mask |= (mask & FE_ALL_EXCEPT);
+ sysarch(ALPHA_SET_FPMASK, &p);
+ return (p.mask);
+}
+
+int
+__fedisableexcept(int mask)
+{
+ struct mask_args p;
+
+ sysarch(ALPHA_GET_FPMASK, &p);
+ p.mask &= ~(mask & FE_ALL_EXCEPT);
sysarch(ALPHA_SET_FPMASK, &p);
return (p.mask);
}
int
-__fegetmask(void)
+__fegetexcept(void)
{
struct mask_args p;
@@ -127,5 +139,6 @@ __fegetmask(void)
return (p.mask);
}
-__weak_reference(__fesetmask, fesetmask);
-__weak_reference(__fegetmask, fegetmask);
+__weak_reference(__feenableexcept, feenableexcept);
+__weak_reference(__fedisableexcept, fedisableexcept);
+__weak_reference(__fegetexcept, fegetexcept);
diff --git a/lib/msun/alpha/fenv.h b/lib/msun/alpha/fenv.h
index 7b79a3fccd1c..b940a60eec34 100644
--- a/lib/msun/alpha/fenv.h
+++ b/lib/msun/alpha/fenv.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -174,8 +174,9 @@ int feupdateenv(const fenv_t *__envp);
#if __BSD_VISIBLE
-int fesetmask(int __mask);
-int fegetmask(void);
+int feenableexcept(int __mask);
+int fedisableexcept(int __mask);
+int fegetexcept(void);
#endif /* __BSD_VISIBLE */
diff --git a/lib/msun/amd64/fenv.c b/lib/msun/amd64/fenv.c
index dd21dadb168d..95c82dee6e39 100644
--- a/lib/msun/amd64/fenv.c
+++ b/lib/msun/amd64/fenv.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -113,19 +113,36 @@ feupdateenv(const fenv_t *envp)
}
int
-__fesetmask(int mask)
+__feenableexcept(int mask)
{
int mxcsr, control, omask;
+ mask &= FE_ALL_EXCEPT;
__fnstcw(&control);
__stmxcsr(&mxcsr);
omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
- control = (control | FE_ALL_EXCEPT) & ~mask;
+ control &= ~mask;
__fldcw(control);
- mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
__ldmxcsr(mxcsr);
return (~omask);
}
-__weak_reference(__fesetmask, fesetmask);
+int
+__fedisableexcept(int mask)
+{
+ int mxcsr, control, omask;
+
+ mask &= FE_ALL_EXCEPT;
+ __fnstcw(&control);
+ __stmxcsr(&mxcsr);
+ omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+ control |= mask;
+ __fldcw(control);
+ mxcsr |= mask << _SSE_EMASK_SHIFT;
+ __ldmxcsr(mxcsr);
+ return (~omask);
+}
+
+__weak_reference(__feenableexcept, feenableexcept);
+__weak_reference(__fedisableexcept, fedisableexcept);
diff --git a/lib/msun/amd64/fenv.h b/lib/msun/amd64/fenv.h
index 29efad97d7f0..cbed18e33667 100644
--- a/lib/msun/amd64/fenv.h
+++ b/lib/msun/amd64/fenv.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -180,10 +180,11 @@ int feupdateenv(const fenv_t *__envp);
#if __BSD_VISIBLE
-int fesetmask(int __mask);
+int feenableexcept(int __mask);
+int fedisableexcpt(int __mask);
static __inline int
-fegetmask(void)
+fegetexcept(void)
{
int __control;
diff --git a/lib/msun/arm/fenv.h b/lib/msun/arm/fenv.h
index 0a994329584a..d540ae2d5dbb 100644
--- a/lib/msun/arm/fenv.h
+++ b/lib/msun/arm/fenv.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -180,19 +180,29 @@ feupdateenv(const fenv_t *__envp)
#if __BSD_VISIBLE
static __inline int
-fesetmask(int __mask)
+feenableexcept(int __mask)
{
- fenv_t __fpsr;
+ fenv_t __old_fpsr, __new_fpsr;
- __rfs(&__fpsr);
- __fpsr &= ~_ENABLE_MASK;
- __fpsr |= __mask << _FPUSW_SHIFT;
- __wfs(__fpsr);
- return (0);
+ __rfs(&__old_fpsr);
+ __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
+ __wfs(__new_fpsr);
+ return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static __inline int
+fedisableexcept(int __mask)
+{
+ fenv_t __old_fpsr, __new_fpsr;
+
+ __rfs(&__old_fpsr);
+ __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
+ __wfs(__new_fpsr);
+ return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
}
static __inline int
-fegetmask(void)
+fegetexcept(void)
{
fenv_t __fpsr;
diff --git a/lib/msun/i387/fenv.h b/lib/msun/i387/fenv.h
index 27cd4164d062..2a54c70e580f 100644
--- a/lib/msun/i387/fenv.h
+++ b/lib/msun/i387/fenv.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -198,18 +198,29 @@ feupdateenv(const fenv_t *__envp)
#if __BSD_VISIBLE
static __inline int
-fesetmask(int __mask)
+feenableexcept(int __mask)
{
int __control;
__fnstcw(&__control);
- __mask = (__control | FE_ALL_EXCEPT) & ~__mask;
+ __mask = __control & ~(__mask & FE_ALL_EXCEPT);
__fldcw(__mask);
return (~__control & FE_ALL_EXCEPT);
}
static __inline int
-fegetmask(void)
+fedisableexcept(int __mask)
+{
+ int __control;
+
+ __fnstcw(&__control);
+ __mask = __control | (__mask & FE_ALL_EXCEPT);
+ __fldcw(__mask);
+ return (~__control & FE_ALL_EXCEPT);
+}
+
+static __inline int
+fegetexcept(void)
{
int __control;
diff --git a/lib/msun/ia64/fenv.h b/lib/msun/ia64/fenv.h
index 98992b189176..6f0240f7b226 100644
--- a/lib/msun/ia64/fenv.h
+++ b/lib/msun/ia64/fenv.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -205,18 +205,29 @@ int feupdateenv(const fenv_t *__envp);
#if __BSD_VISIBLE
static __inline int
-fesetmask(int __mask)
+feenableexcept(int __mask)
{
fenv_t __newfpsr, __oldfpsr;
__stfpsr(&__oldfpsr);
- __newfpsr = (__oldfpsr | FE_ALL_EXCEPT) & ~__mask;
+ __newfpsr = __oldfpsr & ~(__mask & FE_ALL_EXCEPT);
__ldfpsr(__newfpsr);
return (~__oldfpsr & FE_ALL_EXCEPT);
}
static __inline int
-fegetmask(void)
+fedisableexcept(int __mask)
+{
+ fenv_t __newfpsr, __oldfpsr;
+
+ __stfpsr(&__oldfpsr);
+ __newfpsr = __oldfpsr | (__mask & FE_ALL_EXCEPT);
+ __ldfpsr(__newfpsr);
+ return (~__oldfpsr & FE_ALL_EXCEPT);
+}
+
+static __inline int
+fegetexcept(void)
{
fenv_t __fpsr;
diff --git a/lib/msun/man/fenv.3 b/lib/msun/man/fenv.3
index 7c6de1f7f11a..1ae017788fa1 100644
--- a/lib/msun/man/fenv.3
+++ b/lib/msun/man/fenv.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 8, 2004
+.Dd March 16, 2005
.Dt FENV 3
.Os
.Sh NAME
@@ -38,7 +38,10 @@
.Nm fegetenv ,
.Nm feholdexcept ,
.Nm fesetenv ,
-.Nm feupdateenv
+.Nm feupdateenv ,
+.Nm feenableexcept ,
+.Nm fedisableexcept ,
+.Nm fegetexcept
.Nd floating-point environment control
.Sh LIBRARY
.Lb libm
@@ -67,6 +70,12 @@
.Fn fesetenv "const fenv_t *envp"
.Ft int
.Fn feupdateenv "const fenv_t *envp"
+.Ft int
+.Fn feenableexcept "int excepts"
+.Ft int
+.Fn fedisableexcept "int excepts"
+.Ft int
+.Fn fegetexcept "void"
.Sh DESCRIPTION
The
.In fenv.h
@@ -115,6 +124,17 @@ and
.Fn fetestexcept
functions to clear, save, raise, restore, and examine the
processor's floating-point exception flags, respectively.
+.Pp
+Exceptions may be
+.Em unmasked
+with
+.Fn feenableexcept
+and masked with
+.Fn fedisableexcept .
+Unmasked exceptions cause a trap when they are produced, and
+all exceptions are masked by default.
+The current mask can be tested with
+.Fn fegetexcept .
.Ss Rounding Modes
.St -ieee754
specifies four rounding modes.
@@ -219,7 +239,10 @@ double sqrt(double n) {
.Sh SEE ALSO
.Xr cc 1 ,
.Xr feclearexcept 3 ,
+.Xr fedisableexcept 3 ,
+.Xr feenableexcept 3 ,
.Xr fegetenv 3 ,
+.Xr fegetexcept 3 ,
.Xr fegetexceptflag 3 ,
.Xr fegetround 3 ,
.Xr feholdexcept 3 ,
@@ -229,19 +252,19 @@ double sqrt(double n) {
.Xr fesetround 3 ,
.Xr fetestexcept 3 ,
.Xr feupdateenv 3 ,
-.Xr fpgetmask 3 ,
.Xr fpgetprec 3 ,
-.Xr fpgetround 3 ,
-.Xr fpgetsticky 3 ,
-.Xr fpresetsticky 3 ,
-.Xr fpsetmask 3 ,
-.Xr fpsetprec 3 ,
-.Xr fpsetround 3
+.Xr fpsetprec 3
.Sh STANDARDS
Except as noted below,
.In fenv.h
conforms to
.St -isoC-99 .
+The
+.Fn feenableexcept ,
+.Fn fedisableexcept ,
+and
+.Fn fegetexcept
+routines are extensions.
.Sh HISTORY
The
.In fenv.h
diff --git a/lib/msun/powerpc/fenv.h b/lib/msun/powerpc/fenv.h
index ed9d935aa1dd..3010472e14f3 100644
--- a/lib/msun/powerpc/fenv.h
+++ b/lib/msun/powerpc/fenv.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -222,21 +222,33 @@ feupdateenv(const fenv_t *__envp)
#if __BSD_VISIBLE
static __inline int
-fesetmask(int __mask)
+feenableexcept(int __mask)
{
union __fpscr __r;
fenv_t __oldmask;
__mffs(&__r.__d);
__oldmask = __r.__bits.__reg;
- __r.__bits.__reg &= ~_ENABLE_MASK;
- __r.__bits.__reg |= __mask >> _FPUSW_SHIFT;
+ __r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT;
__mtfsf(__r.__d);
return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
}
static __inline int
-fegetmask(void)
+fedisableexcept(int __mask)
+{
+ union __fpscr __r;
+ fenv_t __oldmask;
+
+ __mffs(&__r.__d);
+ __oldmask = __r.__bits.__reg;
+ __r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT);
+ __mtfsf(__r.__d);
+ return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
+}
+
+static __inline int
+fegetexcept(void)
{
union __fpscr __r;
diff --git a/lib/msun/sparc64/fenv.h b/lib/msun/sparc64/fenv.h
index b425515c18b4..82732991349b 100644
--- a/lib/msun/sparc64/fenv.h
+++ b/lib/msun/sparc64/fenv.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -217,19 +217,29 @@ feupdateenv(const fenv_t *__envp)
#if __BSD_VISIBLE
static __inline int
-fesetmask(int __mask)
+feenableexcept(int __mask)
{
- fenv_t __r;
+ fenv_t __old_r, __new_r;
- __stxfsr(&__r);
- __r &= ~_ENABLE_MASK;
- __r |= __mask << _FPUSW_SHIFT;
- __ldxfsr(__r);
- return (0);
+ __stxfsr(&__old_r);
+ __new_r = __old_r | ((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
+ __ldxfsr(__new_r);
+ return ((__old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static __inline int
+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);
+ return ((__old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
}
static __inline int
-fegetmask(void)
+fegetexcept(void)
{
fenv_t __r;