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