17bde21b1SDavid Schultz /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro 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
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
feclearexcept(int __excepts)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
fegetexceptflag(fexcept_t * __flagp,int __excepts)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
fesetexceptflag(const fexcept_t * __flagp,int __excepts)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
feraiseexcept(int __excepts)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
fetestexcept(int __excepts)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
fegetround(void)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
fesetround(int __round)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
fegetenv(fenv_t * __envp)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
feholdexcept(fenv_t * __envp)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
fesetenv(const fenv_t * __envp)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
feupdateenv(const fenv_t * __envp)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
159cd827392SAndrew Turner __fenv_static inline int
feenableexcept(int __mask)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
168cd827392SAndrew Turner __fenv_static inline int
fedisableexcept(int __mask)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
177cd827392SAndrew Turner __fenv_static inline int
fegetexcept(void)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