]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/csky/fpu/fenv_private.h
d086cfcfbbb87bd2911948ed7daf708629881d2c
[thirdparty/glibc.git] / sysdeps / csky / fpu / fenv_private.h
1 /* Private floating point rounding and exceptions handling. C-SKY version.
2 Copyright (C) 2018 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 <http://www.gnu.org/licenses/>. */
18
19 #ifndef CSKY_FENV_PRIVATE_H
20 #define CSKY_FENV_PRIVATE_H 1
21
22 #include <fenv.h>
23 #include <fpu_control.h>
24 #include <fenv_libc.h>
25
26 static __always_inline void
27 libc_feholdexcept_vfp (fenv_t *envp)
28 {
29 fpu_control_t fpsr, fpcr;
30
31 _FPU_GETCW (fpcr);
32 envp->__fpcr = fpcr;
33
34 _FPU_GETFPSR (fpsr);
35 envp->__fpsr = fpsr;
36
37 /* Now set all exceptions to non-stop. */
38 fpcr &= ~FE_ALL_EXCEPT;
39
40 /* And clear all exception flags. */
41 fpsr &= ~(FE_ALL_EXCEPT << CAUSE_SHIFT);
42
43 _FPU_SETFPSR (fpsr);
44
45 _FPU_SETCW (fpcr);
46 }
47
48 static __always_inline void
49 libc_fesetround_vfp (int round)
50 {
51 fpu_control_t fpcr;
52
53 _FPU_GETCW (fpcr);
54
55 /* Set new rounding mode if different. */
56 if (__glibc_unlikely ((fpcr & FE_DOWNWARD) != round))
57 _FPU_SETCW ((fpcr & ~FE_DOWNWARD) | round);
58 }
59
60 static __always_inline void
61 libc_feholdexcept_setround_vfp (fenv_t *envp, int round)
62 {
63 fpu_control_t fpsr, fpcr;
64
65 _FPU_GETCW (fpcr);
66 envp->__fpcr = fpcr;
67
68 _FPU_GETFPSR (fpsr);
69 envp->__fpsr = fpsr;
70
71 /* Clear exception flags, set all exceptions to non-stop,
72 and set new rounding mode. */
73 fpsr &= ~(FE_ALL_EXCEPT << CAUSE_SHIFT);
74 _FPU_SETFPSR (fpsr);
75
76 fpcr &= ~(FE_ALL_EXCEPT | FE_DOWNWARD);
77 _FPU_SETCW (fpcr | round);
78 }
79
80 static __always_inline void
81 libc_feholdsetround_vfp (fenv_t *envp, int round)
82 {
83 fpu_control_t fpcr;
84
85 _FPU_GETCW (fpcr);
86 envp->__fpcr = fpcr;
87
88 /* Set new rounding mode if different. */
89 if (__glibc_unlikely ((fpcr & FE_DOWNWARD) != round))
90 _FPU_SETCW ((fpcr & ~FE_DOWNWARD) | round);
91 }
92
93 static __always_inline void
94 libc_feresetround_vfp (fenv_t *envp)
95 {
96 fpu_control_t fpcr, round;
97
98 _FPU_GETCW (fpcr);
99
100 /* Check whether rounding modes are different. */
101 round = (envp->__fpcr ^ fpcr) & FE_DOWNWARD;
102
103 /* Restore the rounding mode if it was changed. */
104 if (__glibc_unlikely (round != 0))
105 _FPU_SETCW (fpcr ^ round);
106 }
107
108 static __always_inline int
109 libc_fetestexcept_vfp (int ex)
110 {
111 fpu_control_t fpsr;
112
113 _FPU_GETFPSR (fpsr);
114 fpsr = fpsr >> CAUSE_SHIFT;
115 return fpsr & ex & FE_ALL_EXCEPT;
116 }
117
118 static __always_inline void
119 libc_fesetenv_vfp (const fenv_t *envp)
120 {
121 fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr;
122
123 _FPU_GETCW (fpcr);
124 _FPU_GETFPSR (fpsr);
125
126 new_fpcr = envp->__fpcr;
127 new_fpsr = envp->__fpsr;
128
129 if (__glibc_unlikely (fpsr ^ new_fpsr) != 0)
130 _FPU_SETFPSR (new_fpsr);
131
132 if (__glibc_unlikely (fpcr ^ new_fpcr) != 0)
133 _FPU_SETCW (new_fpcr);
134 }
135
136 static __always_inline int
137 libc_feupdateenv_test_vfp (const fenv_t *envp, int ex)
138 {
139 fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr, excepts;
140
141 _FPU_GETCW (fpcr);
142 _FPU_GETFPSR (fpsr);
143
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);
148
149 /* Write FCR and FESR if different. */
150 if (__glibc_unlikely (fpsr ^ new_fpsr) != 0)
151 _FPU_SETFPSR (new_fpsr);
152
153 if (__glibc_unlikely (fpcr ^ new_fpcr) != 0)
154 _FPU_SETCW (new_fpcr);
155
156 /* Raise the exceptions if enabled in the new FP state. */
157 if (__glibc_unlikely (excepts & new_fpcr))
158 __feraiseexcept (excepts);
159
160 return excepts & ex;
161 }
162
163 static __always_inline void
164 libc_feupdateenv_vfp (const fenv_t *envp)
165 {
166 libc_feupdateenv_test_vfp (envp, 0);
167 }
168
169 static __always_inline void
170 libc_feholdsetround_vfp_ctx (struct rm_ctx *ctx, int r)
171 {
172 fpu_control_t fpcr, fpsr, round;
173
174 _FPU_GETCW (fpcr);
175 _FPU_GETFPSR (fpsr);
176 ctx->updated_status = false;
177 ctx->env.__fpcr = fpcr;
178 ctx->env.__fpsr = fpsr;
179
180 /* Check whether rounding modes are different. */
181 round = (fpcr ^ r) & FE_DOWNWARD;
182
183 /* Set the rounding mode if changed. */
184 if (__glibc_unlikely (round != 0))
185 {
186 ctx->updated_status = true;
187 _FPU_SETCW (fpcr ^ round);
188 }
189 }
190
191 static __always_inline void
192 libc_feresetround_vfp_ctx (struct rm_ctx *ctx)
193 {
194 /* Restore the rounding mode if updated. */
195 if (__glibc_unlikely (ctx->updated_status))
196 {
197 fpu_control_t fpcr;
198
199 _FPU_GETCW (fpcr);
200 fpcr = (fpcr & ~FE_DOWNWARD) | (ctx->env.__fpcr & FE_DOWNWARD);
201 _FPU_SETCW (fpcr);
202 }
203 }
204
205 static __always_inline void
206 libc_fesetenv_vfp_ctx (struct rm_ctx *ctx)
207 {
208 fpu_control_t fpcr, fpsr, new_fpcr, new_fpsr;
209
210 _FPU_GETCW (fpcr);
211 _FPU_GETFPSR (fpsr);
212
213 new_fpcr = ctx->env.__fpcr;
214 new_fpsr = ctx->env.__fpsr;
215
216 if (__glibc_unlikely (fpsr ^ new_fpsr) != 0)
217 _FPU_SETFPSR (new_fpsr);
218
219 if (__glibc_unlikely (fpcr ^ new_fpcr) != 0)
220 _FPU_SETCW (new_fpcr);
221 }
222
223 #define libc_feholdexcept libc_feholdexcept_vfp
224 #define libc_feholdexceptf libc_feholdexcept_vfp
225 #define libc_feholdexceptl libc_feholdexcept_vfp
226
227 #define libc_fesetround libc_fesetround_vfp
228 #define libc_fesetroundf libc_fesetround_vfp
229 #define libc_fesetroundl libc_fesetround_vfp
230
231 #define libc_feresetround libc_feresetround_vfp
232 #define libc_feresetroundf libc_feresetround_vfp
233 #define libc_feresetroundl libc_feresetround_vfp
234
235 #define libc_feresetround_noex libc_fesetenv_vfp
236 #define libc_feresetround_noexf libc_fesetenv_vfp
237 #define libc_feresetround_noexl libc_fesetenv_vfp
238
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
242
243 #define libc_feholdsetround libc_feholdsetround_vfp
244 #define libc_feholdsetroundf libc_feholdsetround_vfp
245 #define libc_feholdsetroundl libc_feholdsetround_vfp
246
247 #define libc_fetestexcept libc_fetestexcept_vfp
248 #define libc_fetestexceptf libc_fetestexcept_vfp
249 #define libc_fetestexceptl libc_fetestexcept_vfp
250
251 #define libc_fesetenv libc_fesetenv_vfp
252 #define libc_fesetenvf libc_fesetenv_vfp
253 #define libc_fesetenvl libc_fesetenv_vfp
254
255 #define libc_feupdateenv libc_feupdateenv_vfp
256 #define libc_feupdateenvf libc_feupdateenv_vfp
257 #define libc_feupdateenvl libc_feupdateenv_vfp
258
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
262
263 /* We have support for rounding mode context. */
264 #define HAVE_RM_CTX 1
265
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
269
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
273
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
277
278 #include_next <fenv_private.h>
279
280 #endif /* CSKY_FENV_PRIVATE_H */