Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / arm / fenv_private.h
blob9d21d0f4f1415f1addae9cb65f334c898c35750b
1 /* Private floating point rounding and exceptions handling. ARM VFP version.
2 Copyright (C) 2014-2015 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
22 #include <fenv.h>
23 #include <fpu_control.h>
25 static __always_inline void
26 libc_feholdexcept_vfp (fenv_t *envp)
28 fpu_control_t fpscr;
30 _FPU_GETCW (fpscr);
31 envp->__cw = fpscr;
33 /* Clear exception flags and set all exceptions to non-stop. */
34 fpscr &= ~_FPU_MASK_EXCEPT;
35 _FPU_SETCW (fpscr);
38 static __always_inline void
39 libc_fesetround_vfp (int round)
41 fpu_control_t fpscr;
43 _FPU_GETCW (fpscr);
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)
53 fpu_control_t fpscr;
55 _FPU_GETCW (fpscr);
56 envp->__cw = fpscr;
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)
67 fpu_control_t fpscr;
69 _FPU_GETCW (fpscr);
70 envp->__cw = fpscr;
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;
82 _FPU_GETCW (fpscr);
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)
95 fpu_control_t fpscr;
97 _FPU_GETCW (fpscr);
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;
106 _FPU_GETCW (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;
118 int excepts;
120 _FPU_GETCW (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);
134 return excepts & ex;
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;
148 _FPU_GETCW (fpscr);
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))
169 fpu_control_t fpscr;
171 _FPU_GETCW (fpscr);
172 fpscr = (fpscr & ~_FPU_MASK_RM) | (ctx->env.__cw & _FPU_MASK_RM);
173 _FPU_SETCW (fpscr);
177 static __always_inline void
178 libc_fesetenv_vfp_ctx (struct rm_ctx *ctx)
180 fpu_control_t fpscr, new_fpscr;
182 _FPU_GETCW (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);
190 #ifndef __SOFTFP__
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
247 #endif
249 #endif /* FENV_PRIVATE_H */