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
25static __always_inline void
26libc_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
38static __always_inline void
39libc_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
50static __always_inline void
51libc_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
64static __always_inline void
65libc_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
77static __always_inline void
78libc_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
92static __always_inline int
93libc_fetestexcept_vfp (int ex)
94{
95 fpu_control_t fpscr;
96
97 _FPU_GETCW (fpscr);
98 return fpscr & ex & FE_ALL_EXCEPT;
99}
100
101static __always_inline void
102libc_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
114static __always_inline int
115libc_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
137static __always_inline void
138libc_feupdateenv_vfp (const fenv_t *envp)
139{
140 libc_feupdateenv_test_vfp (envp, 0);
141}
142
143static __always_inline void
144libc_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
163static __always_inline void
164libc_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
177static __always_inline void
178libc_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.

source code of glibc/sysdeps/arm/fenv_private.h