]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - lib/msun/arm/fenv.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / lib / msun / arm / fenv.c
1 /*-
2  * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
3  * Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 #define __fenv_static
31 #include "fenv.h"
32
33 #include <machine/acle-compat.h>
34
35 #if __ARM_ARCH >= 6
36 #define FENV_ARMv6
37 #endif
38
39 /* When SOFTFP_ABI is defined we are using the softfp ABI. */
40 #if defined(__VFP_FP__) && !defined(__ARM_PCS_VFP)
41 #define SOFTFP_ABI
42 #endif
43
44
45 #ifndef FENV_MANGLE
46 /*
47  * Hopefully the system ID byte is immutable, so it's valid to use
48  * this as a default environment.
49  */
50 const fenv_t __fe_dfl_env = 0;
51 #endif
52
53
54 /* If this is a non-mangled softfp version special processing is required */
55 #if defined(FENV_MANGLE) || !defined(SOFTFP_ABI) || !defined(FENV_ARMv6)
56
57 /*
58  * The following macros map between the softfloat emulator's flags and
59  * the hardware's FPSR.  The hardware this file was written for doesn't
60  * have rounding control bits, so we stick those in the system ID byte.
61  */
62 #ifndef __ARM_PCS_VFP
63 #define __set_env(env, flags, mask, rnd) env = ((flags)                 \
64                                                 | (mask)<<_FPUSW_SHIFT  \
65                                                 | (rnd) << 24)
66 #define __env_flags(env)                ((env) & FE_ALL_EXCEPT)
67 #define __env_mask(env)                 (((env) >> _FPUSW_SHIFT)        \
68                                                 & FE_ALL_EXCEPT)
69 #define __env_round(env)                (((env) >> 24) & _ROUND_MASK)
70 #include "fenv-softfloat.h"
71 #endif
72
73 #ifdef __GNUC_GNU_INLINE__
74 #error "This file must be compiled with C99 'inline' semantics"
75 #endif
76
77 extern inline int feclearexcept(int __excepts);
78 extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
79 extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
80 extern inline int feraiseexcept(int __excepts);
81 extern inline int fetestexcept(int __excepts);
82 extern inline int fegetround(void);
83 extern inline int fesetround(int __round);
84 extern inline int fegetenv(fenv_t *__envp);
85 extern inline int feholdexcept(fenv_t *__envp);
86 extern inline int fesetenv(const fenv_t *__envp);
87 extern inline int feupdateenv(const fenv_t *__envp);
88 extern inline int feenableexcept(int __mask);
89 extern inline int fedisableexcept(int __mask);
90 extern inline int fegetexcept(void);
91
92 #else /* !FENV_MANGLE && SOFTFP_ABI */
93 /* Set by libc when the VFP unit is enabled */
94 extern int _libc_arm_fpu_present;
95
96 int __softfp_feclearexcept(int __excepts);
97 int __softfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
98 int __softfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
99 int __softfp_feraiseexcept(int __excepts);
100 int __softfp_fetestexcept(int __excepts);
101 int __softfp_fegetround(void);
102 int __softfp_fesetround(int __round);
103 int __softfp_fegetenv(fenv_t *__envp);
104 int __softfp_feholdexcept(fenv_t *__envp);
105 int __softfp_fesetenv(const fenv_t *__envp);
106 int __softfp_feupdateenv(const fenv_t *__envp);
107 int __softfp_feenableexcept(int __mask);
108 int __softfp_fedisableexcept(int __mask);
109 int __softfp_fegetexcept(void);
110
111 int __vfp_feclearexcept(int __excepts);
112 int __vfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
113 int __vfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
114 int __vfp_feraiseexcept(int __excepts);
115 int __vfp_fetestexcept(int __excepts);
116 int __vfp_fegetround(void);
117 int __vfp_fesetround(int __round);
118 int __vfp_fegetenv(fenv_t *__envp);
119 int __vfp_feholdexcept(fenv_t *__envp);
120 int __vfp_fesetenv(const fenv_t *__envp);
121 int __vfp_feupdateenv(const fenv_t *__envp);
122 int __vfp_feenableexcept(int __mask);
123 int __vfp_fedisableexcept(int __mask);
124 int __vfp_fegetexcept(void);
125
126 static int
127 __softfp_round_to_vfp(int round)
128 {
129
130         switch (round) {
131         case FE_TONEAREST:
132         default:
133                 return VFP_FE_TONEAREST;
134         case FE_TOWARDZERO:
135                 return VFP_FE_TOWARDZERO;
136         case FE_UPWARD:
137                 return VFP_FE_UPWARD;
138         case FE_DOWNWARD:
139                 return VFP_FE_DOWNWARD;
140         }
141 }
142
143 static int
144 __softfp_round_from_vfp(int round)
145 {
146
147         switch (round) {
148         case VFP_FE_TONEAREST:
149         default:
150                 return FE_TONEAREST;
151         case VFP_FE_TOWARDZERO:
152                 return FE_TOWARDZERO;
153         case VFP_FE_UPWARD:
154                 return FE_UPWARD;
155         case VFP_FE_DOWNWARD:
156                 return FE_DOWNWARD;
157         }
158 }
159
160 int feclearexcept(int __excepts)
161 {
162
163         if (_libc_arm_fpu_present)
164                 __vfp_feclearexcept(__excepts);
165         __softfp_feclearexcept(__excepts);
166
167         return (0);
168 }
169
170 int fegetexceptflag(fexcept_t *__flagp, int __excepts)
171 {
172         fexcept_t __vfp_flagp;
173
174         __vfp_flagp = 0;
175         if (_libc_arm_fpu_present)
176                 __vfp_fegetexceptflag(&__vfp_flagp, __excepts);
177         __softfp_fegetexceptflag(__flagp, __excepts);
178
179         *__flagp |= __vfp_flagp;
180
181         return (0);
182 }
183
184 int fesetexceptflag(const fexcept_t *__flagp, int __excepts)
185 {
186
187         if (_libc_arm_fpu_present)
188                 __vfp_fesetexceptflag(__flagp, __excepts);
189         __softfp_fesetexceptflag(__flagp, __excepts);
190
191         return (0);
192 }
193
194 int feraiseexcept(int __excepts)
195 {
196
197         if (_libc_arm_fpu_present)
198                 __vfp_feraiseexcept(__excepts);
199         __softfp_feraiseexcept(__excepts);
200
201         return (0);
202 }
203
204 int fetestexcept(int __excepts)
205 {
206         int __got_excepts;
207
208         __got_excepts = 0;
209         if (_libc_arm_fpu_present)
210                 __got_excepts = __vfp_fetestexcept(__excepts);
211         __got_excepts |= __softfp_fetestexcept(__excepts);
212
213         return (__got_excepts);
214 }
215
216 int fegetround(void)
217 {
218
219         if (_libc_arm_fpu_present)
220                 return __softfp_round_from_vfp(__vfp_fegetround());
221         return __softfp_fegetround();
222 }
223
224 int fesetround(int __round)
225 {
226
227         if (_libc_arm_fpu_present)
228                 __vfp_fesetround(__softfp_round_to_vfp(__round));
229         __softfp_fesetround(__round);
230
231         return (0);
232 }
233
234 int fegetenv(fenv_t *__envp)
235 {
236         fenv_t __vfp_envp;
237
238         __vfp_envp = 0;
239         if (_libc_arm_fpu_present)
240                 __vfp_fegetenv(&__vfp_envp);
241         __softfp_fegetenv(__envp);
242         *__envp |= __vfp_envp;
243
244         return (0);
245 }
246
247 int feholdexcept(fenv_t *__envp)
248 {
249         fenv_t __vfp_envp;
250
251         __vfp_envp = 0;
252         if (_libc_arm_fpu_present)
253                 __vfp_feholdexcept(&__vfp_envp);
254         __softfp_feholdexcept(__envp);
255         *__envp |= __vfp_envp;
256
257         return (0);
258 }
259
260 int fesetenv(const fenv_t *__envp)
261 {
262
263         if (_libc_arm_fpu_present)
264                 __vfp_fesetenv(__envp);
265         __softfp_fesetenv(__envp);
266
267         return (0);
268 }
269
270 int feupdateenv(const fenv_t *__envp)
271 {
272
273         if (_libc_arm_fpu_present)
274                 __vfp_feupdateenv(__envp);
275         __softfp_feupdateenv(__envp);
276
277         return (0);
278 }
279
280 int feenableexcept(int __mask)
281 {
282         int __unmasked;
283
284         __unmasked = 0;
285         if (_libc_arm_fpu_present)
286                 __unmasked = __vfp_feenableexcept(__mask);
287         __unmasked |= __softfp_feenableexcept(__mask);
288
289         return (__unmasked);
290 }
291
292 int fedisableexcept(int __mask)
293 {
294         int __unmasked;
295
296         __unmasked = 0;
297         if (_libc_arm_fpu_present)
298                 __unmasked = __vfp_fedisableexcept(__mask);
299         __unmasked |= __softfp_fedisableexcept(__mask);
300
301         return (__unmasked);
302 }
303
304 int fegetexcept(void)
305 {
306         int __unmasked;
307
308         __unmasked = 0;
309         if (_libc_arm_fpu_present)
310                 __unmasked = __vfp_fegetexcept();
311         __unmasked |= __softfp_fegetexcept();
312
313         return (__unmasked);
314 }
315
316 #endif
317