Warning: This file is not a C or C++ file. It does not have highlighting.
1 | /* Private floating point rounding and exceptions handling. ARM VFP 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 ARM_FENV_PRIVATE_H |
20 | #define ARM_FENV_PRIVATE_H 1 |
21 | |
22 | #include <fenv.h> |
23 | #include <fpu_control.h> |
24 | |
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. */ |
46 | if (__glibc_unlikely ((fpscr & _FPU_MASK_RM) != round)) |
47 | _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round); |
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. */ |
60 | fpscr &= ~(_FPU_MASK_EXCEPT | _FPU_MASK_RM); |
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. */ |
73 | if (__glibc_unlikely ((fpscr & _FPU_MASK_RM) != round)) |
74 | _FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round); |
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. */ |
85 | round = (envp->__cw ^ fpscr) & _FPU_MASK_RM; |
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))) |
132 | __feraiseexcept (excepts); |
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 | |
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. */ |
153 | round = (fpscr ^ r) & _FPU_MASK_RM; |
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); |
172 | fpscr = (fpscr & ~_FPU_MASK_RM) | (ctx->env.__cw & _FPU_MASK_RM); |
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 | |
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 |
238 | |
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 |
242 | |
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 |
246 | |
247 | #endif |
248 | |
249 | #include_next <fenv_private.h> |
250 | |
251 | #endif /* ARM_FENV_PRIVATE_H */ |
252 |
Warning: This file is not a C or C++ file. It does not have highlighting.