fpu-sysv.h revision 1.1.1.4 1 1.1 mrg /* SysV FPU-related code (for systems not otherwise supported).
2 1.1.1.4 mrg Copyright (C) 2005-2024 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Francois-Xavier Coudert <coudert (at) clipper.ens.fr>
4 1.1 mrg
5 1.1 mrg This file is part of the GNU Fortran runtime library (libgfortran).
6 1.1 mrg
7 1.1 mrg Libgfortran is free software; you can redistribute it and/or
8 1.1 mrg modify it under the terms of the GNU General Public
9 1.1 mrg License as published by the Free Software Foundation; either
10 1.1 mrg version 3 of the License, or (at your option) any later version.
11 1.1 mrg
12 1.1 mrg Libgfortran is distributed in the hope that it will be useful,
13 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 mrg GNU General Public License for more details.
16 1.1 mrg
17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
18 1.1 mrg permissions described in the GCC Runtime Library Exception, version
19 1.1 mrg 3.1, as published by the Free Software Foundation.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU General Public License and
22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 1.1 mrg <http://www.gnu.org/licenses/>. */
25 1.1 mrg
26 1.1 mrg /* FPU-related code for SysV platforms with fpsetmask(). */
27 1.1 mrg
28 1.1 mrg /* BSD and Solaris systems have slightly different types and functions
29 1.1 mrg naming. We deal with these here, to simplify the code below. */
30 1.1 mrg
31 1.1 mrg #if HAVE_FP_EXCEPT
32 1.1 mrg # define FP_EXCEPT_TYPE fp_except
33 1.1 mrg #elif HAVE_FP_EXCEPT_T
34 1.1 mrg # define FP_EXCEPT_TYPE fp_except_t
35 1.1 mrg #else
36 1.1 mrg choke me
37 1.1 mrg #endif
38 1.1 mrg
39 1.1 mrg #if HAVE_FP_RND
40 1.1 mrg # define FP_RND_TYPE fp_rnd
41 1.1 mrg #elif HAVE_FP_RND_T
42 1.1 mrg # define FP_RND_TYPE fp_rnd_t
43 1.1 mrg #else
44 1.1 mrg choke me
45 1.1 mrg #endif
46 1.1 mrg
47 1.1 mrg #if HAVE_FPSETSTICKY
48 1.1 mrg # define FPSETSTICKY fpsetsticky
49 1.1 mrg #elif HAVE_FPRESETSTICKY
50 1.1 mrg # define FPSETSTICKY fpresetsticky
51 1.1 mrg #else
52 1.1 mrg choke me
53 1.1 mrg #endif
54 1.1 mrg
55 1.1 mrg
56 1.1 mrg void
57 1.1 mrg set_fpu_trap_exceptions (int trap, int notrap)
58 1.1 mrg {
59 1.1 mrg FP_EXCEPT_TYPE cw = fpgetmask();
60 1.1 mrg
61 1.1 mrg #ifdef FP_X_INV
62 1.1 mrg if (trap & GFC_FPE_INVALID)
63 1.1 mrg cw |= FP_X_INV;
64 1.1 mrg if (notrap & GFC_FPE_INVALID)
65 1.1 mrg cw &= ~FP_X_INV;
66 1.1 mrg #endif
67 1.1 mrg
68 1.1 mrg #ifdef FP_X_DNML
69 1.1 mrg if (trap & GFC_FPE_DENORMAL)
70 1.1 mrg cw |= FP_X_DNML;
71 1.1 mrg if (notrap & GFC_FPE_DENORMAL)
72 1.1 mrg cw &= ~FP_X_DNML;
73 1.1 mrg #endif
74 1.1 mrg
75 1.1 mrg #ifdef FP_X_DZ
76 1.1 mrg if (trap & GFC_FPE_ZERO)
77 1.1 mrg cw |= FP_X_DZ;
78 1.1 mrg if (notrap & GFC_FPE_ZERO)
79 1.1 mrg cw &= ~FP_X_DZ;
80 1.1 mrg #endif
81 1.1 mrg
82 1.1 mrg #ifdef FP_X_OFL
83 1.1 mrg if (trap & GFC_FPE_OVERFLOW)
84 1.1 mrg cw |= FP_X_OFL;
85 1.1 mrg if (notrap & GFC_FPE_OVERFLOW)
86 1.1 mrg cw &= ~FP_X_OFL;
87 1.1 mrg #endif
88 1.1 mrg
89 1.1 mrg #ifdef FP_X_UFL
90 1.1 mrg if (trap & GFC_FPE_UNDERFLOW)
91 1.1 mrg cw |= FP_X_UFL;
92 1.1 mrg if (notrap & GFC_FPE_UNDERFLOW)
93 1.1 mrg cw &= ~FP_X_UFL;
94 1.1 mrg #endif
95 1.1 mrg
96 1.1 mrg #ifdef FP_X_IMP
97 1.1 mrg if (trap & GFC_FPE_INEXACT)
98 1.1 mrg cw |= FP_X_IMP;
99 1.1 mrg if (notrap & GFC_FPE_INEXACT)
100 1.1 mrg cw &= ~FP_X_IMP;
101 1.1 mrg #endif
102 1.1 mrg
103 1.1 mrg fpsetmask(cw);
104 1.1 mrg }
105 1.1 mrg
106 1.1 mrg
107 1.1 mrg int
108 1.1 mrg get_fpu_trap_exceptions (void)
109 1.1 mrg {
110 1.1 mrg int res = 0;
111 1.1 mrg FP_EXCEPT_TYPE cw = fpgetmask();
112 1.1 mrg
113 1.1 mrg #ifdef FP_X_INV
114 1.1 mrg if (cw & FP_X_INV) res |= GFC_FPE_INVALID;
115 1.1 mrg #endif
116 1.1 mrg
117 1.1 mrg #ifdef FP_X_DNML
118 1.1 mrg if (cw & FP_X_DNML) res |= GFC_FPE_DENORMAL;
119 1.1 mrg #endif
120 1.1 mrg
121 1.1 mrg #ifdef FP_X_DZ
122 1.1 mrg if (cw & FP_X_DZ) res |= GFC_FPE_ZERO;
123 1.1 mrg #endif
124 1.1 mrg
125 1.1 mrg #ifdef FP_X_OFL
126 1.1 mrg if (cw & FP_X_OFL) res |= GFC_FPE_OVERFLOW;
127 1.1 mrg #endif
128 1.1 mrg
129 1.1 mrg #ifdef FP_X_UFL
130 1.1 mrg if (cw & FP_X_UFL) res |= GFC_FPE_UNDERFLOW;
131 1.1 mrg #endif
132 1.1 mrg
133 1.1 mrg #ifdef FP_X_IMP
134 1.1 mrg if (cw & FP_X_IMP) res |= GFC_FPE_INEXACT;
135 1.1 mrg #endif
136 1.1 mrg
137 1.1 mrg return res;
138 1.1 mrg }
139 1.1 mrg
140 1.1 mrg
141 1.1 mrg int
142 1.1 mrg support_fpu_trap (int flag)
143 1.1 mrg {
144 1.1 mrg return support_fpu_flag (flag);
145 1.1 mrg }
146 1.1 mrg
147 1.1 mrg
148 1.1 mrg void
149 1.1 mrg set_fpu (void)
150 1.1 mrg {
151 1.1 mrg #ifndef FP_X_INV
152 1.1 mrg if (options.fpe & GFC_FPE_INVALID)
153 1.1 mrg estr_write ("Fortran runtime warning: IEEE 'invalid operation' "
154 1.1 mrg "exception not supported.\n");
155 1.1 mrg #endif
156 1.1 mrg
157 1.1 mrg #ifndef FP_X_DNML
158 1.1 mrg if (options.fpe & GFC_FPE_DENORMAL)
159 1.1 mrg estr_write ("Fortran runtime warning: Floating point 'denormal operand' "
160 1.1 mrg "exception not supported.\n");
161 1.1 mrg #endif
162 1.1 mrg
163 1.1 mrg #ifndef FP_X_DZ
164 1.1 mrg if (options.fpe & GFC_FPE_ZERO)
165 1.1 mrg estr_write ("Fortran runtime warning: IEEE 'division by zero' "
166 1.1 mrg "exception not supported.\n");
167 1.1 mrg #endif
168 1.1 mrg
169 1.1 mrg #ifndef FP_X_OFL
170 1.1 mrg if (options.fpe & GFC_FPE_OVERFLOW)
171 1.1 mrg estr_write ("Fortran runtime warning: IEEE 'overflow' "
172 1.1 mrg "exception not supported.\n");
173 1.1 mrg #endif
174 1.1 mrg
175 1.1 mrg #ifndef FP_X_UFL
176 1.1 mrg if (options.fpe & GFC_FPE_UNDERFLOW)
177 1.1 mrg estr_write ("Fortran runtime warning: IEEE 'underflow' "
178 1.1 mrg "exception not supported.\n");
179 1.1 mrg #endif
180 1.1 mrg
181 1.1 mrg #ifndef FP_X_IMP
182 1.1 mrg if (options.fpe & GFC_FPE_INEXACT)
183 1.1 mrg estr_write ("Fortran runtime warning: IEEE 'inexact' "
184 1.1 mrg "exception not supported.\n");
185 1.1 mrg #endif
186 1.1 mrg
187 1.1 mrg set_fpu_trap_exceptions (options.fpe, 0);
188 1.1 mrg }
189 1.1 mrg
190 1.1 mrg
191 1.1 mrg int
192 1.1 mrg get_fpu_except_flags (void)
193 1.1 mrg {
194 1.1 mrg int result;
195 1.1 mrg FP_EXCEPT_TYPE set_excepts;
196 1.1 mrg
197 1.1 mrg result = 0;
198 1.1 mrg set_excepts = fpgetsticky ();
199 1.1 mrg
200 1.1 mrg #ifdef FP_X_INV
201 1.1 mrg if (set_excepts & FP_X_INV)
202 1.1 mrg result |= GFC_FPE_INVALID;
203 1.1 mrg #endif
204 1.1 mrg
205 1.1 mrg #ifdef FP_X_DZ
206 1.1 mrg if (set_excepts & FP_X_DZ)
207 1.1 mrg result |= GFC_FPE_ZERO;
208 1.1 mrg #endif
209 1.1 mrg
210 1.1 mrg #ifdef FP_X_OFL
211 1.1 mrg if (set_excepts & FP_X_OFL)
212 1.1 mrg result |= GFC_FPE_OVERFLOW;
213 1.1 mrg #endif
214 1.1 mrg
215 1.1 mrg #ifdef FP_X_UFL
216 1.1 mrg if (set_excepts & FP_X_UFL)
217 1.1 mrg result |= GFC_FPE_UNDERFLOW;
218 1.1 mrg #endif
219 1.1 mrg
220 1.1 mrg #ifdef FP_X_DNML
221 1.1 mrg if (set_excepts & FP_X_DNML)
222 1.1 mrg result |= GFC_FPE_DENORMAL;
223 1.1 mrg #endif
224 1.1 mrg
225 1.1 mrg #ifdef FP_X_IMP
226 1.1 mrg if (set_excepts & FP_X_IMP)
227 1.1 mrg result |= GFC_FPE_INEXACT;
228 1.1 mrg #endif
229 1.1 mrg
230 1.1 mrg return result;
231 1.1 mrg }
232 1.1 mrg
233 1.1 mrg
234 1.1 mrg void
235 1.1 mrg set_fpu_except_flags (int set, int clear)
236 1.1 mrg {
237 1.1 mrg FP_EXCEPT_TYPE flags;
238 1.1 mrg
239 1.1 mrg flags = fpgetsticky ();
240 1.1 mrg
241 1.1 mrg #ifdef FP_X_INV
242 1.1 mrg if (set & GFC_FPE_INVALID)
243 1.1 mrg flags |= FP_X_INV;
244 1.1 mrg if (clear & GFC_FPE_INVALID)
245 1.1 mrg flags &= ~FP_X_INV;
246 1.1 mrg #endif
247 1.1 mrg
248 1.1 mrg #ifdef FP_X_DZ
249 1.1 mrg if (set & GFC_FPE_ZERO)
250 1.1 mrg flags |= FP_X_DZ;
251 1.1 mrg if (clear & GFC_FPE_ZERO)
252 1.1 mrg flags &= ~FP_X_DZ;
253 1.1 mrg #endif
254 1.1 mrg
255 1.1 mrg #ifdef FP_X_OFL
256 1.1 mrg if (set & GFC_FPE_OVERFLOW)
257 1.1 mrg flags |= FP_X_OFL;
258 1.1 mrg if (clear & GFC_FPE_OVERFLOW)
259 1.1 mrg flags &= ~FP_X_OFL;
260 1.1 mrg #endif
261 1.1 mrg
262 1.1 mrg #ifdef FP_X_UFL
263 1.1 mrg if (set & GFC_FPE_UNDERFLOW)
264 1.1 mrg flags |= FP_X_UFL;
265 1.1 mrg if (clear & GFC_FPE_UNDERFLOW)
266 1.1 mrg flags &= ~FP_X_UFL;
267 1.1 mrg #endif
268 1.1 mrg
269 1.1 mrg #ifdef FP_X_DNML
270 1.1 mrg if (set & GFC_FPE_DENORMAL)
271 1.1 mrg flags |= FP_X_DNML;
272 1.1 mrg if (clear & GFC_FPE_DENORMAL)
273 1.1 mrg flags &= ~FP_X_DNML;
274 1.1 mrg #endif
275 1.1 mrg
276 1.1 mrg #ifdef FP_X_IMP
277 1.1 mrg if (set & GFC_FPE_INEXACT)
278 1.1 mrg flags |= FP_X_IMP;
279 1.1 mrg if (clear & GFC_FPE_INEXACT)
280 1.1 mrg flags &= ~FP_X_IMP;
281 1.1 mrg #endif
282 1.1 mrg
283 1.1 mrg FPSETSTICKY (flags);
284 1.1 mrg }
285 1.1 mrg
286 1.1 mrg
287 1.1 mrg int
288 1.1 mrg support_fpu_flag (int flag)
289 1.1 mrg {
290 1.1 mrg if (flag & GFC_FPE_INVALID)
291 1.1 mrg {
292 1.1 mrg #ifndef FP_X_INV
293 1.1 mrg return 0;
294 1.1 mrg #endif
295 1.1 mrg }
296 1.1 mrg else if (flag & GFC_FPE_ZERO)
297 1.1 mrg {
298 1.1 mrg #ifndef FP_X_DZ
299 1.1 mrg return 0;
300 1.1 mrg #endif
301 1.1 mrg }
302 1.1 mrg else if (flag & GFC_FPE_OVERFLOW)
303 1.1 mrg {
304 1.1 mrg #ifndef FP_X_OFL
305 1.1 mrg return 0;
306 1.1 mrg #endif
307 1.1 mrg }
308 1.1 mrg else if (flag & GFC_FPE_UNDERFLOW)
309 1.1 mrg {
310 1.1 mrg #ifndef FP_X_UFL
311 1.1 mrg return 0;
312 1.1 mrg #endif
313 1.1 mrg }
314 1.1 mrg else if (flag & GFC_FPE_DENORMAL)
315 1.1 mrg {
316 1.1 mrg #ifndef FP_X_DNML
317 1.1 mrg return 0;
318 1.1 mrg #endif
319 1.1 mrg }
320 1.1 mrg else if (flag & GFC_FPE_INEXACT)
321 1.1 mrg {
322 1.1 mrg #ifndef FP_X_IMP
323 1.1 mrg return 0;
324 1.1 mrg #endif
325 1.1 mrg }
326 1.1 mrg
327 1.1 mrg return 1;
328 1.1 mrg }
329 1.1 mrg
330 1.1 mrg
331 1.1 mrg int
332 1.1 mrg get_fpu_rounding_mode (void)
333 1.1 mrg {
334 1.1 mrg switch (fpgetround ())
335 1.1 mrg {
336 1.1 mrg case FP_RN:
337 1.1 mrg return GFC_FPE_TONEAREST;
338 1.1 mrg case FP_RP:
339 1.1 mrg return GFC_FPE_UPWARD;
340 1.1 mrg case FP_RM:
341 1.1 mrg return GFC_FPE_DOWNWARD;
342 1.1 mrg case FP_RZ:
343 1.1 mrg return GFC_FPE_TOWARDZERO;
344 1.1 mrg default:
345 1.1 mrg return 0; /* Should be unreachable. */
346 1.1 mrg }
347 1.1 mrg }
348 1.1 mrg
349 1.1 mrg
350 1.1 mrg void
351 1.1 mrg set_fpu_rounding_mode (int mode)
352 1.1 mrg {
353 1.1 mrg FP_RND_TYPE rnd_mode;
354 1.1 mrg
355 1.1 mrg switch (mode)
356 1.1 mrg {
357 1.1 mrg case GFC_FPE_TONEAREST:
358 1.1 mrg rnd_mode = FP_RN;
359 1.1 mrg break;
360 1.1 mrg case GFC_FPE_UPWARD:
361 1.1 mrg rnd_mode = FP_RP;
362 1.1 mrg break;
363 1.1 mrg case GFC_FPE_DOWNWARD:
364 1.1 mrg rnd_mode = FP_RM;
365 1.1 mrg break;
366 1.1 mrg case GFC_FPE_TOWARDZERO:
367 1.1 mrg rnd_mode = FP_RZ;
368 1.1 mrg break;
369 1.1 mrg default:
370 1.1 mrg return; /* Should be unreachable. */
371 1.1 mrg }
372 1.1 mrg fpsetround (rnd_mode);
373 1.1 mrg }
374 1.1 mrg
375 1.1 mrg
376 1.1 mrg int
377 1.1.1.4 mrg support_fpu_rounding_mode (int mode)
378 1.1 mrg {
379 1.1.1.4 mrg if (mode == GFC_FPE_AWAY)
380 1.1.1.4 mrg return 0;
381 1.1.1.4 mrg else
382 1.1.1.4 mrg return 1;
383 1.1 mrg }
384 1.1 mrg
385 1.1 mrg
386 1.1 mrg typedef struct
387 1.1 mrg {
388 1.1 mrg FP_EXCEPT_TYPE mask;
389 1.1 mrg FP_EXCEPT_TYPE sticky;
390 1.1 mrg FP_RND_TYPE round;
391 1.1 mrg } fpu_state_t;
392 1.1 mrg
393 1.1 mrg
394 1.1 mrg /* Check we can actually store the FPU state in the allocated size. */
395 1.1 mrg _Static_assert (sizeof(fpu_state_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE,
396 1.1 mrg "GFC_FPE_STATE_BUFFER_SIZE is too small");
397 1.1 mrg
398 1.1 mrg
399 1.1 mrg void
400 1.1 mrg get_fpu_state (void *s)
401 1.1 mrg {
402 1.1 mrg fpu_state_t *state = s;
403 1.1 mrg
404 1.1 mrg state->mask = fpgetmask ();
405 1.1 mrg state->sticky = fpgetsticky ();
406 1.1 mrg state->round = fpgetround ();
407 1.1 mrg }
408 1.1 mrg
409 1.1 mrg void
410 1.1 mrg set_fpu_state (void *s)
411 1.1 mrg {
412 1.1 mrg fpu_state_t *state = s;
413 1.1 mrg
414 1.1 mrg fpsetmask (state->mask);
415 1.1 mrg FPSETSTICKY (state->sticky);
416 1.1 mrg fpsetround (state->round);
417 1.1 mrg }
418 1.1 mrg
419 1.1 mrg
420 1.1 mrg int
421 1.1 mrg support_fpu_underflow_control (int kind __attribute__((unused)))
422 1.1 mrg {
423 1.1 mrg return 0;
424 1.1 mrg }
425 1.1 mrg
426 1.1 mrg
427 1.1 mrg int
428 1.1 mrg get_fpu_underflow_mode (void)
429 1.1 mrg {
430 1.1 mrg return 0;
431 1.1 mrg }
432 1.1 mrg
433 1.1 mrg
434 1.1 mrg void
435 1.1 mrg set_fpu_underflow_mode (int gradual __attribute__((unused)))
436 1.1 mrg {
437 1.1 mrg }
438 1.1 mrg
439