]>
Commit | Line | Data |
---|---|---|
df639d73 | 1 | /* Private floating point rounding and exceptions handling. ARM VFP version. |
04277e02 | 2 | Copyright (C) 2014-2019 Free Software Foundation, Inc. |
df639d73 WD |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library. If not, see | |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
df639d73 | 18 | |
ff6b2450 JM |
19 | #ifndef ARM_FENV_PRIVATE_H |
20 | #define ARM_FENV_PRIVATE_H 1 | |
df639d73 WD |
21 | |
22 | #include <fenv.h> | |
23 | #include <fpu_control.h> | |
24 | ||
df639d73 WD |
25 | static __always_inline void |
26 | libc_feholdexcept_vfp (fenv_t *envp) | |
27 | { | |
28 | fpu_control_t fpscr; | |
29 | ||
30 | _FPU_GETCW (fpscr); | |
31 | envp->__cw = fpscr; | |
32 | ||
33 | /* Clear exception flags and set all exceptions to non-stop. */ | |
34 | fpscr &= ~_FPU_MASK_EXCEPT; | |
35 | _FPU_SETCW (fpscr); | |
36 | } | |
37 | ||
38 | static __always_inline void | |
39 | libc_fesetround_vfp (int round) | |
40 | { | |
41 | fpu_control_t fpscr; | |
42 | ||
43 | _FPU_GETCW (fpscr); | |
44 | ||
45 | /* Set new rounding mode if different. */ | |
b5570d92 W |
46 | if (__glibc_unlikely ((fpscr & _FPU_MASK_RM) != round)) |
47 | _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round); | |
df639d73 WD |
48 | } |
49 | ||
50 | static __always_inline void | |
51 | libc_feholdexcept_setround_vfp (fenv_t *envp, int round) | |
52 | { | |
53 | fpu_control_t fpscr; | |
54 | ||
55 | _FPU_GETCW (fpscr); | |
56 | envp->__cw = fpscr; | |
57 | ||
58 | /* Clear exception flags, set all exceptions to non-stop, | |
59 | and set new rounding mode. */ | |
b5570d92 | 60 | fpscr &= ~(_FPU_MASK_EXCEPT | _FPU_MASK_RM); |
df639d73 WD |
61 | _FPU_SETCW (fpscr | round); |
62 | } | |
63 | ||
64 | static __always_inline void | |
65 | libc_feholdsetround_vfp (fenv_t *envp, int round) | |
66 | { | |
67 | fpu_control_t fpscr; | |
68 | ||
69 | _FPU_GETCW (fpscr); | |
70 | envp->__cw = fpscr; | |
71 | ||
72 | /* Set new rounding mode if different. */ | |
b5570d92 W |
73 | if (__glibc_unlikely ((fpscr & _FPU_MASK_RM) != round)) |
74 | _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round); | |
df639d73 WD |
75 | } |
76 | ||
77 | static __always_inline void | |
78 | libc_feresetround_vfp (fenv_t *envp) | |
79 | { | |
80 | fpu_control_t fpscr, round; | |
81 | ||
82 | _FPU_GETCW (fpscr); | |
83 | ||
84 | /* Check whether rounding modes are different. */ | |
b5570d92 | 85 | round = (envp->__cw ^ fpscr) & _FPU_MASK_RM; |
df639d73 WD |
86 | |
87 | /* Restore the rounding mode if it was changed. */ | |
88 | if (__glibc_unlikely (round != 0)) | |
89 | _FPU_SETCW (fpscr ^ round); | |
90 | } | |
91 | ||
92 | static __always_inline int | |
93 | libc_fetestexcept_vfp (int ex) | |
94 | { | |
95 | fpu_control_t fpscr; | |
96 | ||
97 | _FPU_GETCW (fpscr); | |
98 | return fpscr & ex & FE_ALL_EXCEPT; | |
99 | } | |
100 | ||
101 | static __always_inline void | |
102 | libc_fesetenv_vfp (const fenv_t *envp) | |
103 | { | |
104 | fpu_control_t fpscr, new_fpscr; | |
105 | ||
106 | _FPU_GETCW (fpscr); | |
107 | new_fpscr = envp->__cw; | |
108 | ||
109 | /* Write new FPSCR if different (ignoring NZCV flags). */ | |
110 | if (__glibc_unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0)) | |
111 | _FPU_SETCW (new_fpscr); | |
112 | } | |
113 | ||
114 | static __always_inline int | |
115 | libc_feupdateenv_test_vfp (const fenv_t *envp, int ex) | |
116 | { | |
117 | fpu_control_t fpscr, new_fpscr; | |
118 | int excepts; | |
119 | ||
120 | _FPU_GETCW (fpscr); | |
121 | ||
122 | /* Merge current exception flags with the saved fenv. */ | |
123 | excepts = fpscr & FE_ALL_EXCEPT; | |
124 | new_fpscr = envp->__cw | excepts; | |
125 | ||
126 | /* Write new FPSCR if different (ignoring NZCV flags). */ | |
127 | if (__glibc_unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0)) | |
128 | _FPU_SETCW (new_fpscr); | |
129 | ||
130 | /* Raise the exceptions if enabled in the new FP state. */ | |
131 | if (__glibc_unlikely (excepts & (new_fpscr >> FE_EXCEPT_SHIFT))) | |
0747f818 | 132 | __feraiseexcept (excepts); |
df639d73 WD |
133 | |
134 | return excepts & ex; | |
135 | } | |
136 | ||
137 | static __always_inline void | |
138 | libc_feupdateenv_vfp (const fenv_t *envp) | |
139 | { | |
140 | libc_feupdateenv_test_vfp (envp, 0); | |
141 | } | |
142 | ||
df639d73 WD |
143 | static __always_inline void |
144 | libc_feholdsetround_vfp_ctx (struct rm_ctx *ctx, int r) | |
145 | { | |
146 | fpu_control_t fpscr, round; | |
147 | ||
148 | _FPU_GETCW (fpscr); | |
149 | ctx->updated_status = false; | |
150 | ctx->env.__cw = fpscr; | |
151 | ||
152 | /* Check whether rounding modes are different. */ | |
b5570d92 | 153 | round = (fpscr ^ r) & _FPU_MASK_RM; |
df639d73 WD |
154 | |
155 | /* Set the rounding mode if changed. */ | |
156 | if (__glibc_unlikely (round != 0)) | |
157 | { | |
158 | ctx->updated_status = true; | |
159 | _FPU_SETCW (fpscr ^ round); | |
160 | } | |
161 | } | |
162 | ||
163 | static __always_inline void | |
164 | libc_feresetround_vfp_ctx (struct rm_ctx *ctx) | |
165 | { | |
166 | /* Restore the rounding mode if updated. */ | |
167 | if (__glibc_unlikely (ctx->updated_status)) | |
168 | { | |
169 | fpu_control_t fpscr; | |
170 | ||
171 | _FPU_GETCW (fpscr); | |
b5570d92 | 172 | fpscr = (fpscr & ~_FPU_MASK_RM) | (ctx->env.__cw & _FPU_MASK_RM); |
df639d73 WD |
173 | _FPU_SETCW (fpscr); |
174 | } | |
175 | } | |
176 | ||
177 | static __always_inline void | |
178 | libc_fesetenv_vfp_ctx (struct rm_ctx *ctx) | |
179 | { | |
180 | fpu_control_t fpscr, new_fpscr; | |
181 | ||
182 | _FPU_GETCW (fpscr); | |
183 | new_fpscr = ctx->env.__cw; | |
184 | ||
185 | /* Write new FPSCR if different (ignoring NZCV flags). */ | |
186 | if (__glibc_unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0)) | |
187 | _FPU_SETCW (new_fpscr); | |
188 | } | |
189 | ||
4841e6a6 W |
190 | #ifndef __SOFTFP__ |
191 | ||
192 | # define libc_feholdexcept libc_feholdexcept_vfp | |
193 | # define libc_feholdexceptf libc_feholdexcept_vfp | |
194 | # define libc_feholdexceptl libc_feholdexcept_vfp | |
195 | ||
196 | # define libc_fesetround libc_fesetround_vfp | |
197 | # define libc_fesetroundf libc_fesetround_vfp | |
198 | # define libc_fesetroundl libc_fesetround_vfp | |
199 | ||
200 | # define libc_feresetround libc_feresetround_vfp | |
201 | # define libc_feresetroundf libc_feresetround_vfp | |
202 | # define libc_feresetroundl libc_feresetround_vfp | |
203 | ||
204 | # define libc_feresetround_noex libc_fesetenv_vfp | |
205 | # define libc_feresetround_noexf libc_fesetenv_vfp | |
206 | # define libc_feresetround_noexl libc_fesetenv_vfp | |
207 | ||
208 | # define libc_feholdexcept_setround libc_feholdexcept_setround_vfp | |
209 | # define libc_feholdexcept_setroundf libc_feholdexcept_setround_vfp | |
210 | # define libc_feholdexcept_setroundl libc_feholdexcept_setround_vfp | |
211 | ||
212 | # define libc_feholdsetround libc_feholdsetround_vfp | |
213 | # define libc_feholdsetroundf libc_feholdsetround_vfp | |
214 | # define libc_feholdsetroundl libc_feholdsetround_vfp | |
215 | ||
216 | # define libc_fetestexcept libc_fetestexcept_vfp | |
217 | # define libc_fetestexceptf libc_fetestexcept_vfp | |
218 | # define libc_fetestexceptl libc_fetestexcept_vfp | |
219 | ||
220 | # define libc_fesetenv libc_fesetenv_vfp | |
221 | # define libc_fesetenvf libc_fesetenv_vfp | |
222 | # define libc_fesetenvl libc_fesetenv_vfp | |
223 | ||
224 | # define libc_feupdateenv libc_feupdateenv_vfp | |
225 | # define libc_feupdateenvf libc_feupdateenv_vfp | |
226 | # define libc_feupdateenvl libc_feupdateenv_vfp | |
227 | ||
228 | # define libc_feupdateenv_test libc_feupdateenv_test_vfp | |
229 | # define libc_feupdateenv_testf libc_feupdateenv_test_vfp | |
230 | # define libc_feupdateenv_testl libc_feupdateenv_test_vfp | |
231 | ||
232 | /* We have support for rounding mode context. */ | |
233 | #define HAVE_RM_CTX 1 | |
234 | ||
235 | # define libc_feholdsetround_ctx libc_feholdsetround_vfp_ctx | |
236 | # define libc_feresetround_ctx libc_feresetround_vfp_ctx | |
237 | # define libc_feresetround_noex_ctx libc_fesetenv_vfp_ctx | |
df639d73 | 238 | |
4841e6a6 W |
239 | # define libc_feholdsetroundf_ctx libc_feholdsetround_vfp_ctx |
240 | # define libc_feresetroundf_ctx libc_feresetround_vfp_ctx | |
241 | # define libc_feresetround_noexf_ctx libc_fesetenv_vfp_ctx | |
df639d73 | 242 | |
4841e6a6 W |
243 | # define libc_feholdsetroundl_ctx libc_feholdsetround_vfp_ctx |
244 | # define libc_feresetroundl_ctx libc_feresetround_vfp_ctx | |
245 | # define libc_feresetround_noexl_ctx libc_fesetenv_vfp_ctx | |
df639d73 WD |
246 | |
247 | #endif | |
248 | ||
ff6b2450 JM |
249 | #include_next <fenv_private.h> |
250 | ||
251 | #endif /* ARM_FENV_PRIVATE_H */ |