]>
Commit | Line | Data |
---|---|---|
57267616 | 1 | /* Internal math stuff. MIPS version. |
688903eb | 2 | Copyright (C) 2013-2018 Free Software Foundation, Inc. |
57267616 TS |
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 | ||
ff6b2450 JM |
19 | #ifndef MIPS_FENV_PRIVATE_H |
20 | #define MIPS_FENV_PRIVATE_H 1 | |
57267616 | 21 | |
c79fb0ed | 22 | /* Inline functions to speed up the math library implementation. The |
ff6b2450 | 23 | default versions of these routines are in generic/fenv_private.h |
c79fb0ed SE |
24 | and call fesetround, feholdexcept, etc. These routines use inlined |
25 | code instead. */ | |
26 | ||
ff6b2450 JM |
27 | #include <fenv.h> |
28 | #include <fenv_libc.h> | |
29 | #include <fpu_control.h> | |
c79fb0ed | 30 | |
ff6b2450 JM |
31 | #define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \ |
32 | |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT) | |
5b456e9d | 33 | |
c79fb0ed SE |
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. */ | |
5b456e9d | 44 | cw &= ~(_FPU_MASK_ALL); |
c79fb0ed SE |
45 | _FPU_SETCW (cw); |
46 | } | |
ff6b2450 JM |
47 | #define libc_feholdexcept libc_feholdexcept_mips |
48 | #define libc_feholdexceptf libc_feholdexcept_mips | |
49 | #define libc_feholdexceptl libc_feholdexcept_mips | |
c79fb0ed SE |
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 | } | |
ff6b2450 JM |
66 | #define libc_fesetround libc_fesetround_mips |
67 | #define libc_fesetroundf libc_fesetround_mips | |
68 | #define libc_fesetroundl libc_fesetround_mips | |
c79fb0ed SE |
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. */ | |
5b456e9d | 80 | cw &= ~(_FPU_MASK_ALL); |
c79fb0ed SE |
81 | |
82 | /* Set rounding bits. */ | |
83 | cw &= ~_FPU_RC_MASK; | |
84 | cw |= round; | |
85 | ||
86 | /* Set new state. */ | |
87 | _FPU_SETCW (cw); | |
88 | } | |
ff6b2450 JM |
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 | |
c79fb0ed | 92 | |
ff6b2450 JM |
93 | #define libc_feholdsetround libc_feholdexcept_setround_mips |
94 | #define libc_feholdsetroundf libc_feholdexcept_setround_mips | |
95 | #define libc_feholdsetroundl libc_feholdexcept_setround_mips | |
5b456e9d | 96 | |
c79fb0ed SE |
97 | static __always_inline void |
98 | libc_fesetenv_mips (fenv_t *envp) | |
99 | { | |
35e977b0 | 100 | fpu_control_t cw __attribute__ ((unused)); |
c79fb0ed SE |
101 | |
102 | /* Read current state to flush fpu pipeline. */ | |
103 | _FPU_GETCW (cw); | |
104 | ||
105 | _FPU_SETCW (envp->__fp_control_register); | |
106 | } | |
ff6b2450 JM |
107 | #define libc_fesetenv libc_fesetenv_mips |
108 | #define libc_fesetenvf libc_fesetenv_mips | |
109 | #define libc_fesetenvl libc_fesetenv_mips | |
c79fb0ed | 110 | |
5b456e9d SE |
111 | static __always_inline int |
112 | libc_feupdateenv_test_mips (fenv_t *envp, int excepts) | |
c79fb0ed | 113 | { |
5b456e9d SE |
114 | /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */ |
115 | int cw, temp; | |
c79fb0ed | 116 | |
5b456e9d SE |
117 | /* Get current control word. */ |
118 | _FPU_GETCW (cw); | |
c79fb0ed SE |
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. */ | |
5b456e9d | 124 | temp = cw & FE_ALL_EXCEPT; |
c79fb0ed SE |
125 | temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT); |
126 | ||
127 | /* Set new state. */ | |
128 | _FPU_SETCW (temp); | |
5b456e9d SE |
129 | |
130 | return cw & excepts & FE_ALL_EXCEPT; | |
131 | } | |
ff6b2450 JM |
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 | |
5b456e9d SE |
135 | |
136 | static __always_inline void | |
137 | libc_feupdateenv_mips (fenv_t *envp) | |
138 | { | |
139 | libc_feupdateenv_test_mips (envp, 0); | |
c79fb0ed | 140 | } |
ff6b2450 JM |
141 | #define libc_feupdateenv libc_feupdateenv_mips |
142 | #define libc_feupdateenvf libc_feupdateenv_mips | |
143 | #define libc_feupdateenvl libc_feupdateenv_mips | |
c79fb0ed | 144 | |
ff6b2450 JM |
145 | #define libc_feresetround libc_feupdateenv_mips |
146 | #define libc_feresetroundf libc_feupdateenv_mips | |
147 | #define libc_feresetroundl libc_feupdateenv_mips | |
5b456e9d SE |
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 | } | |
ff6b2450 JM |
159 | #define libc_fetestexcept libc_fetestexcept_mips |
160 | #define libc_fetestexceptf libc_fetestexcept_mips | |
161 | #define libc_fetestexceptl libc_fetestexcept_mips | |
5b456e9d SE |
162 | |
163 | /* Enable support for rounding mode context. */ | |
ff6b2450 | 164 | #define HAVE_RM_CTX 1 |
5b456e9d SE |
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 | } | |
ff6b2450 JM |
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 | |
5b456e9d SE |
192 | |
193 | static __always_inline void | |
194 | libc_fesetenv_mips_ctx (struct rm_ctx *ctx) | |
195 | { | |
196 | libc_fesetenv_mips (&ctx->env); | |
197 | } | |
ff6b2450 JM |
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 | |
5b456e9d SE |
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 | } | |
ff6b2450 JM |
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 | |
5b456e9d SE |
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 | } | |
ff6b2450 JM |
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 | |
c79fb0ed | 238 | |
ff6b2450 | 239 | #include_next <fenv_private.h> |
57267616 TS |
240 | |
241 | #endif |