]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/mips/fpu/fenv_private.h
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / mips / fpu / fenv_private.h
1 /* Internal math stuff. MIPS version.
2 Copyright (C) 2013-2019 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 MIPS_FENV_PRIVATE_H
20 #define MIPS_FENV_PRIVATE_H 1
21
22 /* Inline functions to speed up the math library implementation. The
23 default versions of these routines are in generic/fenv_private.h
24 and call fesetround, feholdexcept, etc. These routines use inlined
25 code instead. */
26
27 #include <fenv.h>
28 #include <fenv_libc.h>
29 #include <fpu_control.h>
30
31 #define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \
32 |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT)
33
34 static __always_inline void
35 libc_feholdexcept_mips (fenv_t *envp)
36 {
37 fpu_control_t cw;
38
39 /* Save the current state. */
40 _FPU_GETCW (cw);
41 envp->__fp_control_register = cw;
42
43 /* Clear all exception enable bits and flags. */
44 cw &= ~(_FPU_MASK_ALL);
45 _FPU_SETCW (cw);
46 }
47 #define libc_feholdexcept libc_feholdexcept_mips
48 #define libc_feholdexceptf libc_feholdexcept_mips
49 #define libc_feholdexceptl libc_feholdexcept_mips
50
51 static __always_inline void
52 libc_fesetround_mips (int round)
53 {
54 fpu_control_t cw;
55
56 /* Get current state. */
57 _FPU_GETCW (cw);
58
59 /* Set rounding bits. */
60 cw &= ~_FPU_RC_MASK;
61 cw |= round;
62
63 /* Set new state. */
64 _FPU_SETCW (cw);
65 }
66 #define libc_fesetround libc_fesetround_mips
67 #define libc_fesetroundf libc_fesetround_mips
68 #define libc_fesetroundl libc_fesetround_mips
69
70 static __always_inline void
71 libc_feholdexcept_setround_mips (fenv_t *envp, int round)
72 {
73 fpu_control_t cw;
74
75 /* Save the current state. */
76 _FPU_GETCW (cw);
77 envp->__fp_control_register = cw;
78
79 /* Clear all exception enable bits and flags. */
80 cw &= ~(_FPU_MASK_ALL);
81
82 /* Set rounding bits. */
83 cw &= ~_FPU_RC_MASK;
84 cw |= round;
85
86 /* Set new state. */
87 _FPU_SETCW (cw);
88 }
89 #define libc_feholdexcept_setround libc_feholdexcept_setround_mips
90 #define libc_feholdexcept_setroundf libc_feholdexcept_setround_mips
91 #define libc_feholdexcept_setroundl libc_feholdexcept_setround_mips
92
93 #define libc_feholdsetround libc_feholdexcept_setround_mips
94 #define libc_feholdsetroundf libc_feholdexcept_setround_mips
95 #define libc_feholdsetroundl libc_feholdexcept_setround_mips
96
97 static __always_inline void
98 libc_fesetenv_mips (fenv_t *envp)
99 {
100 fpu_control_t cw __attribute__ ((unused));
101
102 /* Read current state to flush fpu pipeline. */
103 _FPU_GETCW (cw);
104
105 _FPU_SETCW (envp->__fp_control_register);
106 }
107 #define libc_fesetenv libc_fesetenv_mips
108 #define libc_fesetenvf libc_fesetenv_mips
109 #define libc_fesetenvl libc_fesetenv_mips
110
111 static __always_inline int
112 libc_feupdateenv_test_mips (fenv_t *envp, int excepts)
113 {
114 /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */
115 int cw, temp;
116
117 /* Get current control word. */
118 _FPU_GETCW (cw);
119
120 /* Set flag bits (which are accumulative), and *also* set the
121 cause bits. The setting of the cause bits is what actually causes
122 the hardware to generate the exception, if the corresponding enable
123 bit is set as well. */
124 temp = cw & FE_ALL_EXCEPT;
125 temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT);
126
127 /* Set new state. */
128 _FPU_SETCW (temp);
129
130 return cw & excepts & FE_ALL_EXCEPT;
131 }
132 #define libc_feupdateenv_test libc_feupdateenv_test_mips
133 #define libc_feupdateenv_testf libc_feupdateenv_test_mips
134 #define libc_feupdateenv_testl libc_feupdateenv_test_mips
135
136 static __always_inline void
137 libc_feupdateenv_mips (fenv_t *envp)
138 {
139 libc_feupdateenv_test_mips (envp, 0);
140 }
141 #define libc_feupdateenv libc_feupdateenv_mips
142 #define libc_feupdateenvf libc_feupdateenv_mips
143 #define libc_feupdateenvl libc_feupdateenv_mips
144
145 #define libc_feresetround libc_feupdateenv_mips
146 #define libc_feresetroundf libc_feupdateenv_mips
147 #define libc_feresetroundl libc_feupdateenv_mips
148
149 static __always_inline int
150 libc_fetestexcept_mips (int excepts)
151 {
152 int cw;
153
154 /* Get current control word. */
155 _FPU_GETCW (cw);
156
157 return cw & excepts & FE_ALL_EXCEPT;
158 }
159 #define libc_fetestexcept libc_fetestexcept_mips
160 #define libc_fetestexceptf libc_fetestexcept_mips
161 #define libc_fetestexceptl libc_fetestexcept_mips
162
163 /* Enable support for rounding mode context. */
164 #define HAVE_RM_CTX 1
165
166 static __always_inline void
167 libc_feholdexcept_setround_mips_ctx (struct rm_ctx *ctx, int round)
168 {
169 fpu_control_t old, new;
170
171 /* Save the current state. */
172 _FPU_GETCW (old);
173 ctx->env.__fp_control_register = old;
174
175 /* Clear all exception enable bits and flags. */
176 new = old & ~(_FPU_MASK_ALL);
177
178 /* Set rounding bits. */
179 new = (new & ~_FPU_RC_MASK) | round;
180
181 if (__glibc_unlikely (new != old))
182 {
183 _FPU_SETCW (new);
184 ctx->updated_status = true;
185 }
186 else
187 ctx->updated_status = false;
188 }
189 #define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_mips_ctx
190 #define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_mips_ctx
191 #define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_mips_ctx
192
193 static __always_inline void
194 libc_fesetenv_mips_ctx (struct rm_ctx *ctx)
195 {
196 libc_fesetenv_mips (&ctx->env);
197 }
198 #define libc_fesetenv_ctx libc_fesetenv_mips_ctx
199 #define libc_fesetenvf_ctx libc_fesetenv_mips_ctx
200 #define libc_fesetenvl_ctx libc_fesetenv_mips_ctx
201
202 static __always_inline void
203 libc_feupdateenv_mips_ctx (struct rm_ctx *ctx)
204 {
205 if (__glibc_unlikely (ctx->updated_status))
206 libc_feupdateenv_test_mips (&ctx->env, 0);
207 }
208 #define libc_feupdateenv_ctx libc_feupdateenv_mips_ctx
209 #define libc_feupdateenvf_ctx libc_feupdateenv_mips_ctx
210 #define libc_feupdateenvl_ctx libc_feupdateenv_mips_ctx
211 #define libc_feresetround_ctx libc_feupdateenv_mips_ctx
212 #define libc_feresetroundf_ctx libc_feupdateenv_mips_ctx
213 #define libc_feresetroundl_ctx libc_feupdateenv_mips_ctx
214
215 static __always_inline void
216 libc_feholdsetround_mips_ctx (struct rm_ctx *ctx, int round)
217 {
218 fpu_control_t old, new;
219
220 /* Save the current state. */
221 _FPU_GETCW (old);
222 ctx->env.__fp_control_register = old;
223
224 /* Set rounding bits. */
225 new = (old & ~_FPU_RC_MASK) | round;
226
227 if (__glibc_unlikely (new != old))
228 {
229 _FPU_SETCW (new);
230 ctx->updated_status = true;
231 }
232 else
233 ctx->updated_status = false;
234 }
235 #define libc_feholdsetround_ctx libc_feholdsetround_mips_ctx
236 #define libc_feholdsetroundf_ctx libc_feholdsetround_mips_ctx
237 #define libc_feholdsetroundl_ctx libc_feholdsetround_mips_ctx
238
239 #include_next <fenv_private.h>
240
241 #endif