17bde21b1SDavid Schultz /*- 27bde21b1SDavid Schultz * Copyright (c) 2004-2011 David Schultz <das@FreeBSD.ORG> 37bde21b1SDavid Schultz * All rights reserved. 47bde21b1SDavid Schultz * 57bde21b1SDavid Schultz * Redistribution and use in source and binary forms, with or without 67bde21b1SDavid Schultz * modification, are permitted provided that the following conditions 77bde21b1SDavid Schultz * are met: 87bde21b1SDavid Schultz * 1. Redistributions of source code must retain the above copyright 97bde21b1SDavid Schultz * notice, this list of conditions and the following disclaimer. 107bde21b1SDavid Schultz * 2. Redistributions in binary form must reproduce the above copyright 117bde21b1SDavid Schultz * notice, this list of conditions and the following disclaimer in the 127bde21b1SDavid Schultz * documentation and/or other materials provided with the distribution. 137bde21b1SDavid Schultz * 147bde21b1SDavid Schultz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 157bde21b1SDavid Schultz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 167bde21b1SDavid Schultz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 177bde21b1SDavid Schultz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 187bde21b1SDavid Schultz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 197bde21b1SDavid Schultz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 207bde21b1SDavid Schultz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 217bde21b1SDavid Schultz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 227bde21b1SDavid Schultz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 237bde21b1SDavid Schultz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 247bde21b1SDavid Schultz * SUCH DAMAGE. 257bde21b1SDavid Schultz * 267bde21b1SDavid Schultz * $FreeBSD$ 277bde21b1SDavid Schultz */ 287bde21b1SDavid Schultz 297bde21b1SDavid Schultz #ifndef _FENV_H_ 307bde21b1SDavid Schultz #error "This file is meant to be included only by <fenv.h>." 317bde21b1SDavid Schultz #endif 327bde21b1SDavid Schultz 337bde21b1SDavid Schultz /* 347bde21b1SDavid Schultz * This file implements the functionality of <fenv.h> on platforms that 357bde21b1SDavid Schultz * lack an FPU and use softfloat in libc for floating point. To use it, 367bde21b1SDavid Schultz * you must write an <fenv.h> that provides the following: 377bde21b1SDavid Schultz * 387bde21b1SDavid Schultz * - a typedef for fenv_t, which may be an integer or struct type 397bde21b1SDavid Schultz * - a typedef for fexcept_t (XXX This file assumes fexcept_t is a 407bde21b1SDavid Schultz * simple integer type containing the exception mask.) 417bde21b1SDavid Schultz * - definitions of FE_* constants for the five exceptions and four 427bde21b1SDavid Schultz * rounding modes in IEEE 754, as described in fenv(3) 437bde21b1SDavid Schultz * - a definition, and the corresponding external symbol, for FE_DFL_ENV 447bde21b1SDavid Schultz * - a macro __set_env(env, flags, mask, rnd), which sets the given fenv_t 457bde21b1SDavid Schultz * from the exception flags, mask, and rounding mode 467bde21b1SDavid Schultz * - macros __env_flags(env), __env_mask(env), and __env_round(env), which 477bde21b1SDavid Schultz * extract fields from an fenv_t 487bde21b1SDavid Schultz * - a definition of __fenv_static 497bde21b1SDavid Schultz * 507bde21b1SDavid Schultz * If the architecture supports an optional FPU, it's recommended that you 517bde21b1SDavid Schultz * define fenv_t and fexcept_t to match the hardware ABI. Otherwise, it 527bde21b1SDavid Schultz * doesn't matter how you define them. 537bde21b1SDavid Schultz */ 547bde21b1SDavid Schultz 557bde21b1SDavid Schultz extern int __softfloat_float_exception_flags; 567bde21b1SDavid Schultz extern int __softfloat_float_exception_mask; 577bde21b1SDavid Schultz extern int __softfloat_float_rounding_mode; 587bde21b1SDavid Schultz void __softfloat_float_raise(int); 597bde21b1SDavid Schultz 607bde21b1SDavid Schultz __fenv_static inline int 617bde21b1SDavid Schultz feclearexcept(int __excepts) 627bde21b1SDavid Schultz { 637bde21b1SDavid Schultz 647bde21b1SDavid Schultz __softfloat_float_exception_flags &= ~__excepts; 657bde21b1SDavid Schultz return (0); 667bde21b1SDavid Schultz } 677bde21b1SDavid Schultz 687bde21b1SDavid Schultz __fenv_static inline int 697bde21b1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts) 707bde21b1SDavid Schultz { 717bde21b1SDavid Schultz 727bde21b1SDavid Schultz *__flagp = __softfloat_float_exception_flags & __excepts; 737bde21b1SDavid Schultz return (0); 747bde21b1SDavid Schultz } 757bde21b1SDavid Schultz 767bde21b1SDavid Schultz __fenv_static inline int 777bde21b1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts) 787bde21b1SDavid Schultz { 797bde21b1SDavid Schultz 807bde21b1SDavid Schultz __softfloat_float_exception_flags &= ~__excepts; 817bde21b1SDavid Schultz __softfloat_float_exception_flags |= *__flagp & __excepts; 827bde21b1SDavid Schultz return (0); 837bde21b1SDavid Schultz } 847bde21b1SDavid Schultz 857bde21b1SDavid Schultz __fenv_static inline int 867bde21b1SDavid Schultz feraiseexcept(int __excepts) 877bde21b1SDavid Schultz { 887bde21b1SDavid Schultz 897bde21b1SDavid Schultz __softfloat_float_raise(__excepts); 907bde21b1SDavid Schultz return (0); 917bde21b1SDavid Schultz } 927bde21b1SDavid Schultz 937bde21b1SDavid Schultz __fenv_static inline int 947bde21b1SDavid Schultz fetestexcept(int __excepts) 957bde21b1SDavid Schultz { 967bde21b1SDavid Schultz 977bde21b1SDavid Schultz return (__softfloat_float_exception_flags & __excepts); 987bde21b1SDavid Schultz } 997bde21b1SDavid Schultz 1007bde21b1SDavid Schultz __fenv_static inline int 1017bde21b1SDavid Schultz fegetround(void) 1027bde21b1SDavid Schultz { 1037bde21b1SDavid Schultz 1047bde21b1SDavid Schultz return (__softfloat_float_rounding_mode); 1057bde21b1SDavid Schultz } 1067bde21b1SDavid Schultz 1077bde21b1SDavid Schultz __fenv_static inline int 1087bde21b1SDavid Schultz fesetround(int __round) 1097bde21b1SDavid Schultz { 1107bde21b1SDavid Schultz 1117bde21b1SDavid Schultz __softfloat_float_rounding_mode = __round; 1127bde21b1SDavid Schultz return (0); 1137bde21b1SDavid Schultz } 1147bde21b1SDavid Schultz 1157bde21b1SDavid Schultz __fenv_static inline int 1167bde21b1SDavid Schultz fegetenv(fenv_t *__envp) 1177bde21b1SDavid Schultz { 1187bde21b1SDavid Schultz 1197bde21b1SDavid Schultz __set_env(*__envp, __softfloat_float_exception_flags, 1207bde21b1SDavid Schultz __softfloat_float_exception_mask, __softfloat_float_rounding_mode); 1217bde21b1SDavid Schultz return (0); 1227bde21b1SDavid Schultz } 1237bde21b1SDavid Schultz 1247bde21b1SDavid Schultz __fenv_static inline int 1257bde21b1SDavid Schultz feholdexcept(fenv_t *__envp) 1267bde21b1SDavid Schultz { 1277bde21b1SDavid Schultz fenv_t __env; 1287bde21b1SDavid Schultz 1297bde21b1SDavid Schultz fegetenv(__envp); 1307bde21b1SDavid Schultz __softfloat_float_exception_flags = 0; 1317bde21b1SDavid Schultz __softfloat_float_exception_mask = 0; 1327bde21b1SDavid Schultz return (0); 1337bde21b1SDavid Schultz } 1347bde21b1SDavid Schultz 1357bde21b1SDavid Schultz __fenv_static inline int 1367bde21b1SDavid Schultz fesetenv(const fenv_t *__envp) 1377bde21b1SDavid Schultz { 1387bde21b1SDavid Schultz 1397bde21b1SDavid Schultz __softfloat_float_exception_flags = __env_flags(*__envp); 1407bde21b1SDavid Schultz __softfloat_float_exception_mask = __env_mask(*__envp); 1417bde21b1SDavid Schultz __softfloat_float_rounding_mode = __env_round(*__envp); 1427bde21b1SDavid Schultz return (0); 1437bde21b1SDavid Schultz } 1447bde21b1SDavid Schultz 1457bde21b1SDavid Schultz __fenv_static inline int 1467bde21b1SDavid Schultz feupdateenv(const fenv_t *__envp) 1477bde21b1SDavid Schultz { 1487bde21b1SDavid Schultz int __oflags = __softfloat_float_exception_flags; 1497bde21b1SDavid Schultz 1507bde21b1SDavid Schultz fesetenv(__envp); 1517bde21b1SDavid Schultz feraiseexcept(__oflags); 1527bde21b1SDavid Schultz return (0); 1537bde21b1SDavid Schultz } 1547bde21b1SDavid Schultz 1557bde21b1SDavid Schultz #if __BSD_VISIBLE 1567bde21b1SDavid Schultz 1577bde21b1SDavid Schultz /* We currently provide no external definitions of the functions below. */ 1587bde21b1SDavid Schultz 159*cd827392SAndrew Turner __fenv_static inline int 1607bde21b1SDavid Schultz feenableexcept(int __mask) 1617bde21b1SDavid Schultz { 1627bde21b1SDavid Schultz int __omask = __softfloat_float_exception_mask; 1637bde21b1SDavid Schultz 1647bde21b1SDavid Schultz __softfloat_float_exception_mask |= __mask; 1657bde21b1SDavid Schultz return (__omask); 1667bde21b1SDavid Schultz } 1677bde21b1SDavid Schultz 168*cd827392SAndrew Turner __fenv_static inline int 1697bde21b1SDavid Schultz fedisableexcept(int __mask) 1707bde21b1SDavid Schultz { 1717bde21b1SDavid Schultz int __omask = __softfloat_float_exception_mask; 1727bde21b1SDavid Schultz 1737bde21b1SDavid Schultz __softfloat_float_exception_mask &= ~__mask; 1747bde21b1SDavid Schultz return (__omask); 1757bde21b1SDavid Schultz } 1767bde21b1SDavid Schultz 177*cd827392SAndrew Turner __fenv_static inline int 1787bde21b1SDavid Schultz fegetexcept(void) 1797bde21b1SDavid Schultz { 1807bde21b1SDavid Schultz 1817bde21b1SDavid Schultz return (__softfloat_float_exception_mask); 1827bde21b1SDavid Schultz } 1837bde21b1SDavid Schultz 1847bde21b1SDavid Schultz #endif /* __BSD_VISIBLE */ 185