]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/csky/fpu/fenv_private.h
81ca6ef8323e057b5f44db99742769180d0c18d4
1 /* Private floating point rounding and exceptions handling. C-SKY version.
2 Copyright (C) 2018-2021 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 <https://www.gnu.org/licenses/>. */
19 #ifndef CSKY_FENV_PRIVATE_H
20 #define CSKY_FENV_PRIVATE_H 1
23 #include <fpu_control.h>
24 #include <fenv_libc.h>
26 static __always_inline
void
27 libc_feholdexcept_vfp (fenv_t
*envp
)
29 fpu_control_t fpsr
, fpcr
;
37 /* Now set all exceptions to non-stop. */
38 fpcr
&= ~FE_ALL_EXCEPT
;
40 /* And clear all exception flags. */
41 fpsr
&= ~(FE_ALL_EXCEPT
<< CAUSE_SHIFT
);
48 static __always_inline
void
49 libc_fesetround_vfp (int round
)
55 /* Set new rounding mode if different. */
56 if (__glibc_unlikely ((fpcr
& FE_DOWNWARD
) != round
))
57 _FPU_SETCW ((fpcr
& ~FE_DOWNWARD
) | round
);
60 static __always_inline
void
61 libc_feholdexcept_setround_vfp (fenv_t
*envp
, int round
)
63 fpu_control_t fpsr
, fpcr
;
71 /* Clear exception flags, set all exceptions to non-stop,
72 and set new rounding mode. */
73 fpsr
&= ~(FE_ALL_EXCEPT
<< CAUSE_SHIFT
);
76 fpcr
&= ~(FE_ALL_EXCEPT
| FE_DOWNWARD
);
77 _FPU_SETCW (fpcr
| round
);
80 static __always_inline
void
81 libc_feholdsetround_vfp (fenv_t
*envp
, int round
)
88 /* Set new rounding mode if different. */
89 if (__glibc_unlikely ((fpcr
& FE_DOWNWARD
) != round
))
90 _FPU_SETCW ((fpcr
& ~FE_DOWNWARD
) | round
);
93 static __always_inline
void
94 libc_feresetround_vfp (fenv_t
*envp
)
96 fpu_control_t fpcr
, round
;
100 /* Check whether rounding modes are different. */
101 round
= (envp
->__fpcr
^ fpcr
) & FE_DOWNWARD
;
103 /* Restore the rounding mode if it was changed. */
104 if (__glibc_unlikely (round
!= 0))
105 _FPU_SETCW (fpcr
^ round
);
108 static __always_inline
int
109 libc_fetestexcept_vfp (int ex
)
114 fpsr
= fpsr
>> CAUSE_SHIFT
;
115 return fpsr
& ex
& FE_ALL_EXCEPT
;
118 static __always_inline
void
119 libc_fesetenv_vfp (const fenv_t
*envp
)
121 fpu_control_t fpcr
, fpsr
, new_fpcr
, new_fpsr
;
126 new_fpcr
= envp
->__fpcr
;
127 new_fpsr
= envp
->__fpsr
;
129 if (__glibc_unlikely (fpsr
^ new_fpsr
) != 0)
130 _FPU_SETFPSR (new_fpsr
);
132 if (__glibc_unlikely (fpcr
^ new_fpcr
) != 0)
133 _FPU_SETCW (new_fpcr
);
136 static __always_inline
int
137 libc_feupdateenv_test_vfp (const fenv_t
*envp
, int ex
)
139 fpu_control_t fpcr
, fpsr
, new_fpcr
, new_fpsr
, excepts
;
144 /* Merge current exception flags with the saved fenv. */
145 excepts
= (fpsr
>> CAUSE_SHIFT
) & FE_ALL_EXCEPT
;
146 new_fpcr
= envp
->__fpcr
;
147 new_fpsr
= envp
->__fpsr
| (excepts
<< CAUSE_SHIFT
);
149 /* Write FCR and FESR if different. */
150 if (__glibc_unlikely (fpsr
^ new_fpsr
) != 0)
151 _FPU_SETFPSR (new_fpsr
);
153 if (__glibc_unlikely (fpcr
^ new_fpcr
) != 0)
154 _FPU_SETCW (new_fpcr
);
156 /* Raise the exceptions if enabled in the new FP state. */
157 if (__glibc_unlikely (excepts
& new_fpcr
))
158 __feraiseexcept (excepts
);
163 static __always_inline
void
164 libc_feupdateenv_vfp (const fenv_t
*envp
)
166 libc_feupdateenv_test_vfp (envp
, 0);
169 static __always_inline
void
170 libc_feholdsetround_vfp_ctx (struct rm_ctx
*ctx
, int r
)
172 fpu_control_t fpcr
, fpsr
, round
;
176 ctx
->updated_status
= false;
177 ctx
->env
.__fpcr
= fpcr
;
178 ctx
->env
.__fpsr
= fpsr
;
180 /* Check whether rounding modes are different. */
181 round
= (fpcr
^ r
) & FE_DOWNWARD
;
183 /* Set the rounding mode if changed. */
184 if (__glibc_unlikely (round
!= 0))
186 ctx
->updated_status
= true;
187 _FPU_SETCW (fpcr
^ round
);
191 static __always_inline
void
192 libc_feresetround_vfp_ctx (struct rm_ctx
*ctx
)
194 /* Restore the rounding mode if updated. */
195 if (__glibc_unlikely (ctx
->updated_status
))
200 fpcr
= (fpcr
& ~FE_DOWNWARD
) | (ctx
->env
.__fpcr
& FE_DOWNWARD
);
205 static __always_inline
void
206 libc_fesetenv_vfp_ctx (struct rm_ctx
*ctx
)
208 fpu_control_t fpcr
, fpsr
, new_fpcr
, new_fpsr
;
213 new_fpcr
= ctx
->env
.__fpcr
;
214 new_fpsr
= ctx
->env
.__fpsr
;
216 if (__glibc_unlikely (fpsr
^ new_fpsr
) != 0)
217 _FPU_SETFPSR (new_fpsr
);
219 if (__glibc_unlikely (fpcr
^ new_fpcr
) != 0)
220 _FPU_SETCW (new_fpcr
);
223 #define libc_feholdexcept libc_feholdexcept_vfp
224 #define libc_feholdexceptf libc_feholdexcept_vfp
225 #define libc_feholdexceptl libc_feholdexcept_vfp
227 #define libc_fesetround libc_fesetround_vfp
228 #define libc_fesetroundf libc_fesetround_vfp
229 #define libc_fesetroundl libc_fesetround_vfp
231 #define libc_feresetround libc_feresetround_vfp
232 #define libc_feresetroundf libc_feresetround_vfp
233 #define libc_feresetroundl libc_feresetround_vfp
235 #define libc_feresetround_noex libc_fesetenv_vfp
236 #define libc_feresetround_noexf libc_fesetenv_vfp
237 #define libc_feresetround_noexl libc_fesetenv_vfp
239 #define libc_feholdexcept_setround libc_feholdexcept_setround_vfp
240 #define libc_feholdexcept_setroundf libc_feholdexcept_setround_vfp
241 #define libc_feholdexcept_setroundl libc_feholdexcept_setround_vfp
243 #define libc_feholdsetround libc_feholdsetround_vfp
244 #define libc_feholdsetroundf libc_feholdsetround_vfp
245 #define libc_feholdsetroundl libc_feholdsetround_vfp
247 #define libc_fetestexcept libc_fetestexcept_vfp
248 #define libc_fetestexceptf libc_fetestexcept_vfp
249 #define libc_fetestexceptl libc_fetestexcept_vfp
251 #define libc_fesetenv libc_fesetenv_vfp
252 #define libc_fesetenvf libc_fesetenv_vfp
253 #define libc_fesetenvl libc_fesetenv_vfp
255 #define libc_feupdateenv libc_feupdateenv_vfp
256 #define libc_feupdateenvf libc_feupdateenv_vfp
257 #define libc_feupdateenvl libc_feupdateenv_vfp
259 #define libc_feupdateenv_test libc_feupdateenv_test_vfp
260 #define libc_feupdateenv_testf libc_feupdateenv_test_vfp
261 #define libc_feupdateenv_testl libc_feupdateenv_test_vfp
263 /* We have support for rounding mode context. */
264 #define HAVE_RM_CTX 1
266 #define libc_feholdsetround_ctx libc_feholdsetround_vfp_ctx
267 #define libc_feresetround_ctx libc_feresetround_vfp_ctx
268 #define libc_feresetround_noex_ctx libc_fesetenv_vfp_ctx
270 #define libc_feholdsetroundf_ctx libc_feholdsetround_vfp_ctx
271 #define libc_feresetroundf_ctx libc_feresetround_vfp_ctx
272 #define libc_feresetround_noexf_ctx libc_fesetenv_vfp_ctx
274 #define libc_feholdsetroundl_ctx libc_feholdsetround_vfp_ctx
275 #define libc_feresetroundl_ctx libc_feresetround_vfp_ctx
276 #define libc_feresetround_noexl_ctx libc_fesetenv_vfp_ctx
278 #include_next <fenv_private.h>
280 #endif /* CSKY_FENV_PRIVATE_H */