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 + * Copyright (c) 2004-2005 David Schultz * 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); 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 + * Copyright (c) 2004-2005 David Schultz * 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 + * Copyright (c) 2004-2005 David Schultz * 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 + * Copyright (c) 2004-2005 David Schultz * 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 + * Copyright (c) 2004-2005 David Schultz * 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; 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 + * Copyright (c) 2004-2005 David Schultz * 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 + * Copyright (c) 2004-2005 David Schultz * 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 + * Copyright (c) 2004-2005 David Schultz * 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 + * Copyright (c) 2004-2005 David Schultz * 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;