]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/csky/fpu/fenv_private.h
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / csky / fpu / fenv_private.h
CommitLineData
5f72b005 1/* Private floating point rounding and exceptions handling. C-SKY version.
04277e02 2 Copyright (C) 2018-2019 Free Software Foundation, Inc.
5f72b005
MH
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
5a82c748 17 <https://www.gnu.org/licenses/>. */
5f72b005
MH
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
26static __always_inline void
27libc_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
48static __always_inline void
49libc_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
60static __always_inline void
61libc_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
80static __always_inline void
81libc_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
93static __always_inline void
94libc_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
108static __always_inline int
109libc_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
118static __always_inline void
119libc_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
136static __always_inline int
137libc_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
163static __always_inline void
164libc_feupdateenv_vfp (const fenv_t *envp)
165{
166 libc_feupdateenv_test_vfp (envp, 0);
167}
168
169static __always_inline void
170libc_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
191static __always_inline void
192libc_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
205static __always_inline void
206libc_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 */