fenv-softfloat.h revision 302408
123660Speter/*-
250476Speter * Copyright (c) 2004-2011 David Schultz <das@FreeBSD.ORG>
31573Srgrimes * All rights reserved.
41573Srgrimes *
5262722Smarcel * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
734386Sjb * are met:
834386Sjb * 1. Redistributions of source code must retain the above copyright
9262722Smarcel *    notice, this list of conditions and the following disclaimer.
1030448Sbde * 2. Redistributions in binary form must reproduce the above copyright
1134386Sjb *    notice, this list of conditions and the following disclaimer in the
1234386Sjb *    documentation and/or other materials provided with the distribution.
1334386Sjb *
1434386Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1534386Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16262722Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18237434Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19237434Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20237434Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21237434Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2234386Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23276630Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24276630Skib * SUCH DAMAGE.
25276630Skib *
26276630Skib * $FreeBSD: stable/11/lib/msun/src/fenv-softfloat.h 261161 2014-01-25 16:03:08Z andrew $
27277610Sjilles */
28277610Sjilles
29277610Sjilles#ifndef	_FENV_H_
30277610Sjilles#error "This file is meant to be included only by <fenv.h>."
31302092Sbrooks#endif
32302092Sbrooks
33276630Skib/*
34276630Skib * This file implements the functionality of <fenv.h> on platforms that
35276630Skib * lack an FPU and use softfloat in libc for floating point.  To use it,
36276630Skib * you must write an <fenv.h> that provides the following:
37276630Skib *
38276630Skib *   - a typedef for fenv_t, which may be an integer or struct type
39276630Skib *   - a typedef for fexcept_t (XXX This file assumes fexcept_t is a
40276630Skib *     simple integer type containing the exception mask.)
41276630Skib *   - definitions of FE_* constants for the five exceptions and four
42280818Skib *     rounding modes in IEEE 754, as described in fenv(3)
43276630Skib *   - a definition, and the corresponding external symbol, for FE_DFL_ENV
44276630Skib *   - a macro __set_env(env, flags, mask, rnd), which sets the given fenv_t
45276630Skib *     from the exception flags, mask, and rounding mode
46276630Skib *   - macros __env_flags(env), __env_mask(env), and __env_round(env), which
47276630Skib *     extract fields from an fenv_t
48281712Skib *   - a definition of __fenv_static
49276630Skib *
50276630Skib * If the architecture supports an optional FPU, it's recommended that you
51276630Skib * define fenv_t and fexcept_t to match the hardware ABI.  Otherwise, it
52276630Skib * doesn't matter how you define them.
53276630Skib */
54276630Skib
55276630Skibextern int __softfloat_float_exception_flags;
56276630Skibextern int __softfloat_float_exception_mask;
57276630Skibextern int __softfloat_float_rounding_mode;
58276630Skibvoid __softfloat_float_raise(int);
59276630Skib
60276630Skib__fenv_static inline int
61276630Skibfeclearexcept(int __excepts)
62276630Skib{
63276630Skib
64276630Skib	__softfloat_float_exception_flags &= ~__excepts;
65281712Skib	return (0);
66276630Skib}
67276630Skib
68276630Skib__fenv_static inline int
69278870Smariusfegetexceptflag(fexcept_t *__flagp, int __excepts)
70278870Smarius{
71278870Smarius
72278870Smarius	*__flagp = __softfloat_float_exception_flags & __excepts;
73278870Smarius	return (0);
74278870Smarius}
75278870Smarius
76276630Skib__fenv_static inline int
77276630Skibfesetexceptflag(const fexcept_t *__flagp, int __excepts)
78276630Skib{
79276630Skib
8034386Sjb	__softfloat_float_exception_flags &= ~__excepts;
8134386Sjb	__softfloat_float_exception_flags |= *__flagp & __excepts;
821573Srgrimes	return (0);
8334386Sjb}
8434386Sjb
8571770Sdeischen__fenv_static inline int
8671770Sdeischenferaiseexcept(int __excepts)
8764106Speter{
8834386Sjb
8934386Sjb	__softfloat_float_raise(__excepts);
9034386Sjb	return (0);
9134386Sjb}
9234386Sjb
9334386Sjb__fenv_static inline int
941573Srgrimesfetestexcept(int __excepts)
9525105Sbde{
962366Sbde
9725105Sbde	return (__softfloat_float_exception_flags & __excepts);
982366Sbde}
9971770Sdeischen
1001573Srgrimes__fenv_static inline int
101262722Smarcelfegetround(void)
102156613Sdeischen{
10325736Speter
10471770Sdeischen	return (__softfloat_float_rounding_mode);
10525736Speter}
106217850Skib
107288373Skib__fenv_static inline int
108217850Skibfesetround(int __round)
109217850Skib{
110217850Skib
111217850Skib	__softfloat_float_rounding_mode = __round;
112217850Skib	return (0);
11325105Sbde}
114194910Sjhb
115194910Sjhb__fenv_static inline int
116217850Skibfegetenv(fenv_t *__envp)
1172366Sbde{
11825105Sbde
119194910Sjhb	__set_env(*__envp, __softfloat_float_exception_flags,
12071770Sdeischen	    __softfloat_float_exception_mask, __softfloat_float_rounding_mode);
121194910Sjhb	return (0);
122217850Skib}
1232366Sbde
124246884Spjd__fenv_static inline int
125246884Spjdfeholdexcept(fenv_t *__envp)
126246884Spjd{
127246884Spjd	fenv_t __env;
128246884Spjd
129246884Spjd	fegetenv(__envp);
130246884Spjd	__softfloat_float_exception_flags = 0;
131259921Spluknet	__softfloat_float_exception_mask = 0;
132251526Sglebius	return (0);
133246884Spjd}
134246884Spjd
135246884Spjd__fenv_static inline int
136246884Spjdfesetenv(const fenv_t *__envp)
137246884Spjd{
138246884Spjd
139247667Spjd	__softfloat_float_exception_flags = __env_flags(*__envp);
140246884Spjd	__softfloat_float_exception_mask = __env_mask(*__envp);
141246884Spjd	__softfloat_float_rounding_mode = __env_round(*__envp);
142247602Spjd	return (0);
143247602Spjd}
144247602Spjd
145246884Spjd__fenv_static inline int
146246884Spjdfeupdateenv(const fenv_t *__envp)
147246884Spjd{
148246884Spjd	int __oflags = __softfloat_float_exception_flags;
149246884Spjd
150246884Spjd	fesetenv(__envp);
151246884Spjd	feraiseexcept(__oflags);
152246884Spjd	return (0);
153246884Spjd}
154247667Spjd
155246884Spjd#if __BSD_VISIBLE
156246884Spjd
157246884Spjd/* We currently provide no external definitions of the functions below. */
158246884Spjd
159246884Spjd__fenv_static inline int
160246884Spjdfeenableexcept(int __mask)
161246884Spjd{
162246884Spjd	int __omask = __softfloat_float_exception_mask;
163246884Spjd
164246884Spjd	__softfloat_float_exception_mask |= __mask;
165246884Spjd	return (__omask);
166246884Spjd}
167246884Spjd
168246884Spjd__fenv_static inline int
169246884Spjdfedisableexcept(int __mask)
170246884Spjd{
171246884Spjd	int __omask = __softfloat_float_exception_mask;
172246884Spjd
173246884Spjd	__softfloat_float_exception_mask &= ~__mask;
174246884Spjd	return (__omask);
175246884Spjd}
176246884Spjd
177246884Spjd__fenv_static inline int
178246884Spjdfegetexcept(void)
179246884Spjd{
180246884Spjd
181246884Spjd	return (__softfloat_float_exception_mask);
182246884Spjd}
183246884Spjd
184246884Spjd#endif /* __BSD_VISIBLE */
185246884Spjd