1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31 __declare_fenv_inline(int)
feclearexcept(int excepts)32 feclearexcept(int excepts)
33 {
34 fexcept_t fcsr;
35
36 excepts &= FE_ALL_EXCEPT;
37 __cfc1(fcsr);
38 fcsr &= ~(excepts | (excepts << _FCSR_CAUSE_SHIFT));
39 __ctc1(fcsr);
40
41 return (0);
42 }
43
44 __declare_fenv_inline(int)
fegetexceptflag(fexcept_t * flagp,int excepts)45 fegetexceptflag(fexcept_t *flagp, int excepts)
46 {
47 fexcept_t fcsr;
48
49 excepts &= FE_ALL_EXCEPT;
50 __cfc1(fcsr);
51 *flagp = fcsr & excepts;
52
53 return (0);
54 }
55
56 __declare_fenv_inline(int)
fesetexceptflag(const fexcept_t * flagp,int excepts)57 fesetexceptflag(const fexcept_t *flagp, int excepts)
58 {
59 fexcept_t fcsr;
60
61 excepts &= FE_ALL_EXCEPT;
62 __cfc1(fcsr);
63 fcsr &= ~excepts;
64 fcsr |= *flagp & excepts;
65 __ctc1(fcsr);
66
67 return (0);
68 }
69
70 __declare_fenv_inline(int)
feraiseexcept(int excepts)71 feraiseexcept(int excepts)
72 {
73 fexcept_t fcsr;
74
75 excepts &= FE_ALL_EXCEPT;
76 __cfc1(fcsr);
77 fcsr |= excepts | (excepts << _FCSR_CAUSE_SHIFT);
78 __ctc1(fcsr);
79
80 return (0);
81 }
82
83 __declare_fenv_inline(int)
fesetexcept(int excepts)84 fesetexcept(int excepts)
85 {
86 fexcept_t fcsr;
87
88 excepts &= FE_ALL_EXCEPT;
89 __cfc1(fcsr);
90 fcsr |= excepts | (excepts << _FCSR_CAUSE_SHIFT);
91 __ctc1(fcsr);
92
93 return (0);
94 }
95
96 __declare_fenv_inline(int)
fetestexcept(int excepts)97 fetestexcept(int excepts)
98 {
99 fexcept_t fcsr;
100
101 excepts &= FE_ALL_EXCEPT;
102 __cfc1(fcsr);
103
104 return (fcsr & excepts);
105 }
106
107 __declare_fenv_inline(int)
fegetround(void)108 fegetround(void)
109 {
110 fexcept_t fcsr;
111
112 __cfc1(fcsr);
113
114 return (fcsr & _ROUND_MASK);
115 }
116
117 __declare_fenv_inline(int)
fesetround(int rounding_mode)118 fesetround(int rounding_mode)
119 {
120 fexcept_t fcsr;
121
122 if (rounding_mode & ~_ROUND_MASK)
123 return (-1);
124
125 __cfc1(fcsr);
126 fcsr &= ~_ROUND_MASK;
127 fcsr |= rounding_mode;
128 __ctc1(fcsr);
129
130 return (0);
131 }
132
133 __declare_fenv_inline(int)
fegetenv(fenv_t * envp)134 fegetenv(fenv_t *envp)
135 {
136
137 __cfc1(*envp);
138
139 return (0);
140 }
141
142 __declare_fenv_inline(int)
feholdexcept(fenv_t * envp)143 feholdexcept(fenv_t *envp)
144 {
145 fexcept_t fcsr;
146
147 __cfc1(fcsr);
148 *envp = fcsr;
149 fcsr &= ~(FE_ALL_EXCEPT | _FCSR_ENABLE_MASK);
150 __ctc1(fcsr);
151
152 return (0);
153 }
154
155 __declare_fenv_inline(int)
fesetenv(const fenv_t * envp)156 fesetenv(const fenv_t *envp)
157 {
158
159 __ctc1(*envp);
160
161 return (0);
162 }
163
164 __declare_fenv_inline(int)
feupdateenv(const fenv_t * envp)165 feupdateenv(const fenv_t *envp)
166 {
167 fexcept_t fcsr;
168
169 __cfc1(fcsr);
170 fesetenv(envp);
171 feraiseexcept(fcsr);
172
173 return (0);
174 }
175
176 #if __BSD_VISIBLE
177
178 /* We currently provide no external definitions of the functions below. */
179
180 __declare_fenv_inline(int)
feenableexcept(int __mask)181 feenableexcept(int __mask)
182 {
183 fenv_t __old_fcsr, __new_fcsr;
184
185 __cfc1(__old_fcsr);
186 __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _FCSR_ENABLE_SHIFT;
187 __ctc1(__new_fcsr);
188
189 return ((__old_fcsr >> _FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
190 }
191
192 __declare_fenv_inline(int)
fedisableexcept(int __mask)193 fedisableexcept(int __mask)
194 {
195 fenv_t __old_fcsr, __new_fcsr;
196
197 __cfc1(__old_fcsr);
198 __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _FCSR_ENABLE_SHIFT);
199 __ctc1(__new_fcsr);
200
201 return ((__old_fcsr >> _FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
202 }
203
204 __declare_fenv_inline(int)
fegetexcept(void)205 fegetexcept(void)
206 {
207 fexcept_t fcsr;
208
209 __cfc1(fcsr);
210
211 return ((fcsr & _FCSR_ENABLE_MASK) >> _FCSR_ENABLE_SHIFT);
212 }
213
214 #endif /* __BSD_VISIBLE */
215