1 /* Private floating point rounding and exceptions handling. ARM VFP version.
2 Copyright (C) 2014-2017 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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 <http://www.gnu.org/licenses/>. */
19 #ifndef FENV_PRIVATE_H
20 #define FENV_PRIVATE_H 1
23 #include <fpu_control.h>
25 static __always_inline
void
26 libc_feholdexcept_vfp (fenv_t
*envp
)
33 /* Clear exception flags and set all exceptions to non-stop. */
34 fpscr
&= ~_FPU_MASK_EXCEPT
;
38 static __always_inline
void
39 libc_fesetround_vfp (int round
)
45 /* Set new rounding mode if different. */
46 if (__glibc_unlikely ((fpscr
& _FPU_MASK_RM
) != round
))
47 _FPU_SETCW ((fpscr
& ~_FPU_MASK_RM
) | round
);
50 static __always_inline
void
51 libc_feholdexcept_setround_vfp (fenv_t
*envp
, int round
)
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
);
64 static __always_inline
void
65 libc_feholdsetround_vfp (fenv_t
*envp
, int round
)
72 /* Set new rounding mode if different. */
73 if (__glibc_unlikely ((fpscr
& _FPU_MASK_RM
) != round
))
74 _FPU_SETCW ((fpscr
& ~_FPU_MASK_RM
) | round
);
77 static __always_inline
void
78 libc_feresetround_vfp (fenv_t
*envp
)
80 fpu_control_t fpscr
, round
;
84 /* Check whether rounding modes are different. */
85 round
= (envp
->__cw
^ fpscr
) & _FPU_MASK_RM
;
87 /* Restore the rounding mode if it was changed. */
88 if (__glibc_unlikely (round
!= 0))
89 _FPU_SETCW (fpscr
^ round
);
92 static __always_inline
int
93 libc_fetestexcept_vfp (int ex
)
98 return fpscr
& ex
& FE_ALL_EXCEPT
;
101 static __always_inline
void
102 libc_fesetenv_vfp (const fenv_t
*envp
)
104 fpu_control_t fpscr
, new_fpscr
;
107 new_fpscr
= envp
->__cw
;
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
);
114 static __always_inline
int
115 libc_feupdateenv_test_vfp (const fenv_t
*envp
, int ex
)
117 fpu_control_t fpscr
, new_fpscr
;
122 /* Merge current exception flags with the saved fenv. */
123 excepts
= fpscr
& FE_ALL_EXCEPT
;
124 new_fpscr
= envp
->__cw
| excepts
;
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
);
130 /* Raise the exceptions if enabled in the new FP state. */
131 if (__glibc_unlikely (excepts
& (new_fpscr
>> FE_EXCEPT_SHIFT
)))
132 __feraiseexcept (excepts
);
137 static __always_inline
void
138 libc_feupdateenv_vfp (const fenv_t
*envp
)
140 libc_feupdateenv_test_vfp (envp
, 0);
143 static __always_inline
void
144 libc_feholdsetround_vfp_ctx (struct rm_ctx
*ctx
, int r
)
146 fpu_control_t fpscr
, round
;
149 ctx
->updated_status
= false;
150 ctx
->env
.__cw
= fpscr
;
152 /* Check whether rounding modes are different. */
153 round
= (fpscr
^ r
) & _FPU_MASK_RM
;
155 /* Set the rounding mode if changed. */
156 if (__glibc_unlikely (round
!= 0))
158 ctx
->updated_status
= true;
159 _FPU_SETCW (fpscr
^ round
);
163 static __always_inline
void
164 libc_feresetround_vfp_ctx (struct rm_ctx
*ctx
)
166 /* Restore the rounding mode if updated. */
167 if (__glibc_unlikely (ctx
->updated_status
))
172 fpscr
= (fpscr
& ~_FPU_MASK_RM
) | (ctx
->env
.__cw
& _FPU_MASK_RM
);
177 static __always_inline
void
178 libc_fesetenv_vfp_ctx (struct rm_ctx
*ctx
)
180 fpu_control_t fpscr
, new_fpscr
;
183 new_fpscr
= ctx
->env
.__cw
;
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
);
192 # define libc_feholdexcept libc_feholdexcept_vfp
193 # define libc_feholdexceptf libc_feholdexcept_vfp
194 # define libc_feholdexceptl libc_feholdexcept_vfp
196 # define libc_fesetround libc_fesetround_vfp
197 # define libc_fesetroundf libc_fesetround_vfp
198 # define libc_fesetroundl libc_fesetround_vfp
200 # define libc_feresetround libc_feresetround_vfp
201 # define libc_feresetroundf libc_feresetround_vfp
202 # define libc_feresetroundl libc_feresetround_vfp
204 # define libc_feresetround_noex libc_fesetenv_vfp
205 # define libc_feresetround_noexf libc_fesetenv_vfp
206 # define libc_feresetround_noexl libc_fesetenv_vfp
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
212 # define libc_feholdsetround libc_feholdsetround_vfp
213 # define libc_feholdsetroundf libc_feholdsetround_vfp
214 # define libc_feholdsetroundl libc_feholdsetround_vfp
216 # define libc_fetestexcept libc_fetestexcept_vfp
217 # define libc_fetestexceptf libc_fetestexcept_vfp
218 # define libc_fetestexceptl libc_fetestexcept_vfp
220 # define libc_fesetenv libc_fesetenv_vfp
221 # define libc_fesetenvf libc_fesetenv_vfp
222 # define libc_fesetenvl libc_fesetenv_vfp
224 # define libc_feupdateenv libc_feupdateenv_vfp
225 # define libc_feupdateenvf libc_feupdateenv_vfp
226 # define libc_feupdateenvl libc_feupdateenv_vfp
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
232 /* We have support for rounding mode context. */
233 #define HAVE_RM_CTX 1
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
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
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
249 #endif /* FENV_PRIVATE_H */