xref: /freebsd/lib/msun/src/fenv-softfloat.h (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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