Warning: This file is not a C or C++ file. It does not have highlighting.
1 | /* Private floating point rounding and exceptions handling. AArch64 version. |
---|---|
2 | Copyright (C) 2014-2022 Free Software Foundation, Inc. |
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 |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #ifndef AARCH64_FENV_PRIVATE_H |
20 | #define AARCH64_FENV_PRIVATE_H 1 |
21 | |
22 | #include <fenv.h> |
23 | #include <fpu_control.h> |
24 | |
25 | static __always_inline void |
26 | libc_feholdexcept_aarch64 (fenv_t *envp) |
27 | { |
28 | fpu_control_t fpcr; |
29 | fpu_control_t new_fpcr; |
30 | fpu_fpsr_t fpsr; |
31 | fpu_fpsr_t new_fpsr; |
32 | |
33 | _FPU_GETCW (fpcr); |
34 | _FPU_GETFPSR (fpsr); |
35 | envp->__fpcr = fpcr; |
36 | envp->__fpsr = fpsr; |
37 | |
38 | /* Clear exception flags and set all exceptions to non-stop. */ |
39 | new_fpcr = fpcr & ~(FE_ALL_EXCEPT << FE_EXCEPT_SHIFT); |
40 | new_fpsr = fpsr & ~FE_ALL_EXCEPT; |
41 | |
42 | if (__glibc_unlikely (new_fpcr != fpcr)) |
43 | _FPU_SETCW (new_fpcr); |
44 | |
45 | if (new_fpsr != fpsr) |
46 | _FPU_SETFPSR (new_fpsr); |
47 | } |
48 | |
49 | #define libc_feholdexcept libc_feholdexcept_aarch64 |
50 | #define libc_feholdexceptf libc_feholdexcept_aarch64 |
51 | #define libc_feholdexceptl libc_feholdexcept_aarch64 |
52 | |
53 | static __always_inline void |
54 | libc_fesetround_aarch64 (int round) |
55 | { |
56 | fpu_control_t fpcr; |
57 | |
58 | _FPU_GETCW (fpcr); |
59 | |
60 | /* Check whether rounding modes are different. */ |
61 | round = (fpcr ^ round) & _FPU_FPCR_RM_MASK; |
62 | |
63 | /* Set new rounding mode if different. */ |
64 | if (__glibc_unlikely (round != 0)) |
65 | _FPU_SETCW (fpcr ^ round); |
66 | } |
67 | |
68 | #define libc_fesetround libc_fesetround_aarch64 |
69 | #define libc_fesetroundf libc_fesetround_aarch64 |
70 | #define libc_fesetroundl libc_fesetround_aarch64 |
71 | |
72 | static __always_inline void |
73 | libc_feholdexcept_setround_aarch64 (fenv_t *envp, int round) |
74 | { |
75 | fpu_control_t fpcr; |
76 | fpu_control_t new_fpcr; |
77 | fpu_fpsr_t fpsr; |
78 | fpu_fpsr_t new_fpsr; |
79 | |
80 | _FPU_GETCW (fpcr); |
81 | _FPU_GETFPSR (fpsr); |
82 | envp->__fpcr = fpcr; |
83 | envp->__fpsr = fpsr; |
84 | |
85 | /* Clear exception flags, set all exceptions to non-stop, |
86 | and set new rounding mode. */ |
87 | new_fpcr = fpcr & ~((FE_ALL_EXCEPT << FE_EXCEPT_SHIFT) | _FPU_FPCR_RM_MASK); |
88 | new_fpcr |= round; |
89 | new_fpsr = fpsr & ~FE_ALL_EXCEPT; |
90 | |
91 | if (__glibc_unlikely (new_fpcr != fpcr)) |
92 | _FPU_SETCW (new_fpcr); |
93 | |
94 | if (new_fpsr != fpsr) |
95 | _FPU_SETFPSR (new_fpsr); |
96 | } |
97 | |
98 | #define libc_feholdexcept_setround libc_feholdexcept_setround_aarch64 |
99 | #define libc_feholdexcept_setroundf libc_feholdexcept_setround_aarch64 |
100 | #define libc_feholdexcept_setroundl libc_feholdexcept_setround_aarch64 |
101 | |
102 | static __always_inline int |
103 | libc_fetestexcept_aarch64 (int ex) |
104 | { |
105 | fpu_fpsr_t fpsr; |
106 | |
107 | _FPU_GETFPSR (fpsr); |
108 | return fpsr & ex & FE_ALL_EXCEPT; |
109 | } |
110 | |
111 | #define libc_fetestexcept libc_fetestexcept_aarch64 |
112 | #define libc_fetestexceptf libc_fetestexcept_aarch64 |
113 | #define libc_fetestexceptl libc_fetestexcept_aarch64 |
114 | |
115 | static __always_inline void |
116 | libc_fesetenv_aarch64 (const fenv_t *envp) |
117 | { |
118 | fpu_control_t fpcr; |
119 | fpu_control_t new_fpcr; |
120 | |
121 | _FPU_GETCW (fpcr); |
122 | new_fpcr = envp->__fpcr; |
123 | |
124 | if (__glibc_unlikely (fpcr != new_fpcr)) |
125 | _FPU_SETCW (new_fpcr); |
126 | |
127 | _FPU_SETFPSR (envp->__fpsr); |
128 | } |
129 | |
130 | #define libc_fesetenv libc_fesetenv_aarch64 |
131 | #define libc_fesetenvf libc_fesetenv_aarch64 |
132 | #define libc_fesetenvl libc_fesetenv_aarch64 |
133 | #define libc_feresetround_noex libc_fesetenv_aarch64 |
134 | #define libc_feresetround_noexf libc_fesetenv_aarch64 |
135 | #define libc_feresetround_noexl libc_fesetenv_aarch64 |
136 | |
137 | static __always_inline int |
138 | libc_feupdateenv_test_aarch64 (const fenv_t *envp, int ex) |
139 | { |
140 | fpu_control_t fpcr; |
141 | fpu_control_t new_fpcr; |
142 | fpu_fpsr_t fpsr; |
143 | fpu_fpsr_t new_fpsr; |
144 | int excepts; |
145 | |
146 | _FPU_GETCW (fpcr); |
147 | _FPU_GETFPSR (fpsr); |
148 | |
149 | /* Merge current exception flags with the saved fenv. */ |
150 | excepts = fpsr & FE_ALL_EXCEPT; |
151 | new_fpcr = envp->__fpcr; |
152 | new_fpsr = envp->__fpsr | excepts; |
153 | |
154 | if (__glibc_unlikely (fpcr != new_fpcr)) |
155 | _FPU_SETCW (new_fpcr); |
156 | |
157 | if (fpsr != new_fpsr) |
158 | _FPU_SETFPSR (new_fpsr); |
159 | |
160 | /* Raise the exceptions if enabled in the new FP state. */ |
161 | if (__glibc_unlikely (excepts & (new_fpcr >> FE_EXCEPT_SHIFT))) |
162 | __feraiseexcept (excepts); |
163 | |
164 | return excepts & ex; |
165 | } |
166 | |
167 | #define libc_feupdateenv_test libc_feupdateenv_test_aarch64 |
168 | #define libc_feupdateenv_testf libc_feupdateenv_test_aarch64 |
169 | #define libc_feupdateenv_testl libc_feupdateenv_test_aarch64 |
170 | |
171 | static __always_inline void |
172 | libc_feupdateenv_aarch64 (const fenv_t *envp) |
173 | { |
174 | libc_feupdateenv_test_aarch64 (envp, 0); |
175 | } |
176 | |
177 | #define libc_feupdateenv libc_feupdateenv_aarch64 |
178 | #define libc_feupdateenvf libc_feupdateenv_aarch64 |
179 | #define libc_feupdateenvl libc_feupdateenv_aarch64 |
180 | |
181 | static __always_inline void |
182 | libc_feholdsetround_aarch64 (fenv_t *envp, int round) |
183 | { |
184 | fpu_control_t fpcr; |
185 | fpu_fpsr_t fpsr; |
186 | |
187 | _FPU_GETCW (fpcr); |
188 | _FPU_GETFPSR (fpsr); |
189 | envp->__fpcr = fpcr; |
190 | envp->__fpsr = fpsr; |
191 | |
192 | /* Check whether rounding modes are different. */ |
193 | round = (fpcr ^ round) & _FPU_FPCR_RM_MASK; |
194 | |
195 | /* Set new rounding mode if different. */ |
196 | if (__glibc_unlikely (round != 0)) |
197 | _FPU_SETCW (fpcr ^ round); |
198 | } |
199 | |
200 | #define libc_feholdsetround libc_feholdsetround_aarch64 |
201 | #define libc_feholdsetroundf libc_feholdsetround_aarch64 |
202 | #define libc_feholdsetroundl libc_feholdsetround_aarch64 |
203 | |
204 | static __always_inline void |
205 | libc_feresetround_aarch64 (fenv_t *envp) |
206 | { |
207 | fpu_control_t fpcr; |
208 | int round; |
209 | |
210 | _FPU_GETCW (fpcr); |
211 | |
212 | /* Check whether rounding modes are different. */ |
213 | round = (envp->__fpcr ^ fpcr) & _FPU_FPCR_RM_MASK; |
214 | |
215 | /* Restore the rounding mode if it was changed. */ |
216 | if (__glibc_unlikely (round != 0)) |
217 | _FPU_SETCW (fpcr ^ round); |
218 | } |
219 | |
220 | #define libc_feresetround libc_feresetround_aarch64 |
221 | #define libc_feresetroundf libc_feresetround_aarch64 |
222 | #define libc_feresetroundl libc_feresetround_aarch64 |
223 | |
224 | /* We have support for rounding mode context. */ |
225 | #define HAVE_RM_CTX 1 |
226 | |
227 | static __always_inline void |
228 | libc_feholdsetround_aarch64_ctx (struct rm_ctx *ctx, int r) |
229 | { |
230 | fpu_control_t fpcr; |
231 | int round; |
232 | |
233 | _FPU_GETCW (fpcr); |
234 | ctx->env.__fpcr = fpcr; |
235 | |
236 | /* Check whether rounding modes are different. */ |
237 | round = (fpcr ^ r) & _FPU_FPCR_RM_MASK; |
238 | ctx->updated_status = round != 0; |
239 | |
240 | /* Set the rounding mode if changed. */ |
241 | if (__glibc_unlikely (round != 0)) |
242 | _FPU_SETCW (fpcr ^ round); |
243 | } |
244 | |
245 | #define libc_feholdsetround_ctx libc_feholdsetround_aarch64_ctx |
246 | #define libc_feholdsetroundf_ctx libc_feholdsetround_aarch64_ctx |
247 | #define libc_feholdsetroundl_ctx libc_feholdsetround_aarch64_ctx |
248 | |
249 | static __always_inline void |
250 | libc_feresetround_aarch64_ctx (struct rm_ctx *ctx) |
251 | { |
252 | /* Restore the rounding mode if updated. */ |
253 | if (__glibc_unlikely (ctx->updated_status)) |
254 | _FPU_SETCW (ctx->env.__fpcr); |
255 | } |
256 | |
257 | #define libc_feresetround_ctx libc_feresetround_aarch64_ctx |
258 | #define libc_feresetroundf_ctx libc_feresetround_aarch64_ctx |
259 | #define libc_feresetroundl_ctx libc_feresetround_aarch64_ctx |
260 | |
261 | static __always_inline void |
262 | libc_feholdsetround_noex_aarch64_ctx (struct rm_ctx *ctx, int r) |
263 | { |
264 | fpu_control_t fpcr; |
265 | fpu_fpsr_t fpsr; |
266 | int round; |
267 | |
268 | _FPU_GETCW (fpcr); |
269 | _FPU_GETFPSR (fpsr); |
270 | ctx->env.__fpcr = fpcr; |
271 | ctx->env.__fpsr = fpsr; |
272 | |
273 | /* Check whether rounding modes are different. */ |
274 | round = (fpcr ^ r) & _FPU_FPCR_RM_MASK; |
275 | ctx->updated_status = round != 0; |
276 | |
277 | /* Set the rounding mode if changed. */ |
278 | if (__glibc_unlikely (round != 0)) |
279 | _FPU_SETCW (fpcr ^ round); |
280 | } |
281 | |
282 | #define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_aarch64_ctx |
283 | #define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_aarch64_ctx |
284 | #define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_aarch64_ctx |
285 | |
286 | static __always_inline void |
287 | libc_feresetround_noex_aarch64_ctx (struct rm_ctx *ctx) |
288 | { |
289 | /* Restore the rounding mode if updated. */ |
290 | if (__glibc_unlikely (ctx->updated_status)) |
291 | _FPU_SETCW (ctx->env.__fpcr); |
292 | |
293 | /* Write new FPSR to restore exception flags. */ |
294 | _FPU_SETFPSR (ctx->env.__fpsr); |
295 | } |
296 | |
297 | #define libc_feresetround_noex_ctx libc_feresetround_noex_aarch64_ctx |
298 | #define libc_feresetround_noexf_ctx libc_feresetround_noex_aarch64_ctx |
299 | #define libc_feresetround_noexl_ctx libc_feresetround_noex_aarch64_ctx |
300 | |
301 | #include_next <fenv_private.h> |
302 | |
303 | #endif |
304 |
Warning: This file is not a C or C++ file. It does not have highlighting.