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