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