1 /* Internal math stuff. MIPS version.
2 Copyright (C) 2013-2023 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 MIPS_FENV_PRIVATE_H
20 #define MIPS_FENV_PRIVATE_H 1
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
28 #include <fenv_libc.h>
29 #include <fpu_control.h>
31 #define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \
32 |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT)
34 static __always_inline
void
35 libc_feholdexcept_mips (fenv_t
*envp
)
39 /* Save the current state. */
41 envp
->__fp_control_register
= cw
;
43 /* Clear all exception enable bits and flags. */
44 cw
&= ~(_FPU_MASK_ALL
);
47 #define libc_feholdexcept libc_feholdexcept_mips
48 #define libc_feholdexceptf libc_feholdexcept_mips
49 #define libc_feholdexceptl libc_feholdexcept_mips
51 static __always_inline
void
52 libc_fesetround_mips (int round
)
56 /* Get current state. */
59 /* Set rounding bits. */
66 #define libc_fesetround libc_fesetround_mips
67 #define libc_fesetroundf libc_fesetround_mips
68 #define libc_fesetroundl libc_fesetround_mips
70 static __always_inline
void
71 libc_feholdexcept_setround_mips (fenv_t
*envp
, int round
)
75 /* Save the current state. */
77 envp
->__fp_control_register
= cw
;
79 /* Clear all exception enable bits and flags. */
80 cw
&= ~(_FPU_MASK_ALL
);
82 /* Set rounding bits. */
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
93 #define libc_feholdsetround libc_feholdexcept_setround_mips
94 #define libc_feholdsetroundf libc_feholdexcept_setround_mips
95 #define libc_feholdsetroundl libc_feholdexcept_setround_mips
97 static __always_inline
void
98 libc_fesetenv_mips (fenv_t
*envp
)
100 fpu_control_t cw
__attribute__ ((unused
));
102 /* Read current state to flush fpu pipeline. */
105 _FPU_SETCW (envp
->__fp_control_register
);
107 #define libc_fesetenv libc_fesetenv_mips
108 #define libc_fesetenvf libc_fesetenv_mips
109 #define libc_fesetenvl libc_fesetenv_mips
111 static __always_inline
int
112 libc_feupdateenv_test_mips (fenv_t
*envp
, int excepts
)
114 /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */
117 /* Get current control word. */
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
);
130 return cw
& excepts
& FE_ALL_EXCEPT
;
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
136 static __always_inline
void
137 libc_feupdateenv_mips (fenv_t
*envp
)
139 libc_feupdateenv_test_mips (envp
, 0);
141 #define libc_feupdateenv libc_feupdateenv_mips
142 #define libc_feupdateenvf libc_feupdateenv_mips
143 #define libc_feupdateenvl libc_feupdateenv_mips
145 #define libc_feresetround libc_feupdateenv_mips
146 #define libc_feresetroundf libc_feupdateenv_mips
147 #define libc_feresetroundl libc_feupdateenv_mips
149 static __always_inline
int
150 libc_fetestexcept_mips (int excepts
)
154 /* Get current control word. */
157 return cw
& excepts
& FE_ALL_EXCEPT
;
159 #define libc_fetestexcept libc_fetestexcept_mips
160 #define libc_fetestexceptf libc_fetestexcept_mips
161 #define libc_fetestexceptl libc_fetestexcept_mips
163 /* Enable support for rounding mode context. */
164 #define HAVE_RM_CTX 1
166 static __always_inline
void
167 libc_feholdexcept_setround_mips_ctx (struct rm_ctx
*ctx
, int round
)
169 fpu_control_t old
, new;
171 /* Save the current state. */
173 ctx
->env
.__fp_control_register
= old
;
175 /* Clear all exception enable bits and flags. */
176 new = old
& ~(_FPU_MASK_ALL
);
178 /* Set rounding bits. */
179 new = (new & ~_FPU_RC_MASK
) | round
;
181 if (__glibc_unlikely (new != old
))
184 ctx
->updated_status
= true;
187 ctx
->updated_status
= false;
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
193 static __always_inline
void
194 libc_fesetenv_mips_ctx (struct rm_ctx
*ctx
)
196 libc_fesetenv_mips (&ctx
->env
);
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
202 static __always_inline
void
203 libc_feupdateenv_mips_ctx (struct rm_ctx
*ctx
)
205 if (__glibc_unlikely (ctx
->updated_status
))
206 libc_feupdateenv_test_mips (&ctx
->env
, 0);
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
215 static __always_inline
void
216 libc_feholdsetround_mips_ctx (struct rm_ctx
*ctx
, int round
)
218 fpu_control_t old
, new;
220 /* Save the current state. */
222 ctx
->env
.__fp_control_register
= old
;
224 /* Set rounding bits. */
225 new = (old
& ~_FPU_RC_MASK
) | round
;
227 if (__glibc_unlikely (new != old
))
230 ctx
->updated_status
= true;
233 ctx
->updated_status
= false;
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
239 #include_next <fenv_private.h>