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.
This commit is contained in:
das 2005-03-16 19:03:46 +00:00
parent f472dda708
commit 6448887f3b
10 changed files with 166 additions and 57 deletions

View File

@ -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
__fegetmask(void)
__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
__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);

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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
fegetmask(void)
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
fegetexcept(void)
{
fenv_t __fpsr;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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
fegetmask(void)
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
fegetexcept(void)
{
fenv_t __r;