1 /* SysV FPU-related code (for systems not otherwise supported).
2 Copyright (C) 2005-2015 Free Software Foundation, Inc.
3 Contributed by Francois-Xavier Coudert <coudert@clipper.ens.fr>
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 /* FPU-related code for SysV platforms with fpsetmask(). */
28 /* BSD and Solaris systems have slightly different types and functions
29 naming. We deal with these here, to simplify the code below. */
32 # define FP_EXCEPT_TYPE fp_except
33 #elif HAVE_FP_EXCEPT_T
34 # define FP_EXCEPT_TYPE fp_except_t
40 # define FP_RND_TYPE fp_rnd
42 # define FP_RND_TYPE fp_rnd_t
48 # define FPSETSTICKY fpsetsticky
49 #elif HAVE_FPRESETSTICKY
50 # define FPSETSTICKY fpresetsticky
57 set_fpu_trap_exceptions (int trap
, int notrap
)
59 FP_EXCEPT_TYPE cw
= fpgetmask();
62 if (trap
& GFC_FPE_INVALID
)
64 if (notrap
& GFC_FPE_INVALID
)
69 if (trap
& GFC_FPE_DENORMAL
)
71 if (notrap
& GFC_FPE_DENORMAL
)
76 if (trap
& GFC_FPE_ZERO
)
78 if (notrap
& GFC_FPE_ZERO
)
83 if (trap
& GFC_FPE_OVERFLOW
)
85 if (notrap
& GFC_FPE_OVERFLOW
)
90 if (trap
& GFC_FPE_UNDERFLOW
)
92 if (notrap
& GFC_FPE_UNDERFLOW
)
97 if (trap
& GFC_FPE_INEXACT
)
99 if (notrap
& GFC_FPE_INEXACT
)
108 get_fpu_trap_exceptions (void)
111 FP_EXCEPT_TYPE cw
= fpgetmask();
114 if (cw
& FP_X_INV
) res
|= GFC_FPE_INVALID
;
118 if (cw
& FP_X_DNML
) res
|= GFC_FPE_DENORMAL
;
122 if (cw
& FP_X_DZ
) res
|= GFC_FPE_ZERO
;
126 if (cw
& FP_X_OFL
) res
|= GFC_FPE_OVERFLOW
;
130 if (cw
& FP_X_UFL
) res
|= GFC_FPE_UNDERFLOW
;
134 if (cw
& FP_X_IMP
) res
|= GFC_FPE_INEXACT
;
142 support_fpu_trap (int flag
)
144 return support_fpu_flag (flag
);
152 if (options
.fpe
& GFC_FPE_INVALID
)
153 estr_write ("Fortran runtime warning: IEEE 'invalid operation' "
154 "exception not supported.\n");
158 if (options
.fpe
& GFC_FPE_DENORMAL
)
159 estr_write ("Fortran runtime warning: Floating point 'denormal operand' "
160 "exception not supported.\n");
164 if (options
.fpe
& GFC_FPE_ZERO
)
165 estr_write ("Fortran runtime warning: IEEE 'division by zero' "
166 "exception not supported.\n");
170 if (options
.fpe
& GFC_FPE_OVERFLOW
)
171 estr_write ("Fortran runtime warning: IEEE 'overflow' "
172 "exception not supported.\n");
176 if (options
.fpe
& GFC_FPE_UNDERFLOW
)
177 estr_write ("Fortran runtime warning: IEEE 'underflow' "
178 "exception not supported.\n");
182 if (options
.fpe
& GFC_FPE_INEXACT
)
183 estr_write ("Fortran runtime warning: IEEE 'inexact' "
184 "exception not supported.\n");
187 set_fpu_trap_exceptions (options
.fpe
, 0);
192 get_fpu_except_flags (void)
195 FP_EXCEPT_TYPE set_excepts
;
198 set_excepts
= fpgetsticky ();
201 if (set_excepts
& FP_X_INV
)
202 result
|= GFC_FPE_INVALID
;
206 if (set_excepts
& FP_X_DZ
)
207 result
|= GFC_FPE_ZERO
;
211 if (set_excepts
& FP_X_OFL
)
212 result
|= GFC_FPE_OVERFLOW
;
216 if (set_excepts
& FP_X_UFL
)
217 result
|= GFC_FPE_UNDERFLOW
;
221 if (set_excepts
& FP_X_DNML
)
222 result
|= GFC_FPE_DENORMAL
;
226 if (set_excepts
& FP_X_IMP
)
227 result
|= GFC_FPE_INEXACT
;
235 set_fpu_except_flags (int set
, int clear
)
237 FP_EXCEPT_TYPE flags
;
239 flags
= fpgetsticky ();
242 if (set
& GFC_FPE_INVALID
)
244 if (clear
& GFC_FPE_INVALID
)
249 if (set
& GFC_FPE_ZERO
)
251 if (clear
& GFC_FPE_ZERO
)
256 if (set
& GFC_FPE_OVERFLOW
)
258 if (clear
& GFC_FPE_OVERFLOW
)
263 if (set
& GFC_FPE_UNDERFLOW
)
265 if (clear
& GFC_FPE_UNDERFLOW
)
270 if (set
& GFC_FPE_DENORMAL
)
272 if (clear
& GFC_FPE_DENORMAL
)
277 if (set
& GFC_FPE_INEXACT
)
279 if (clear
& GFC_FPE_INEXACT
)
288 support_fpu_flag (int flag
)
290 if (flag
& GFC_FPE_INVALID
)
296 else if (flag
& GFC_FPE_ZERO
)
302 else if (flag
& GFC_FPE_OVERFLOW
)
308 else if (flag
& GFC_FPE_UNDERFLOW
)
314 else if (flag
& GFC_FPE_DENORMAL
)
320 else if (flag
& GFC_FPE_INEXACT
)
332 get_fpu_rounding_mode (void)
334 switch (fpgetround ())
337 return GFC_FPE_TONEAREST
;
339 return GFC_FPE_UPWARD
;
341 return GFC_FPE_DOWNWARD
;
343 return GFC_FPE_TOWARDZERO
;
345 return 0; /* Should be unreachable. */
351 set_fpu_rounding_mode (int mode
)
353 FP_RND_TYPE rnd_mode
;
357 case GFC_FPE_TONEAREST
:
363 case GFC_FPE_DOWNWARD
:
366 case GFC_FPE_TOWARDZERO
:
370 return; /* Should be unreachable. */
372 fpsetround (rnd_mode
);
377 support_fpu_rounding_mode (int mode
__attribute__((unused
)))
386 FP_EXCEPT_TYPE sticky
;
391 /* Check we can actually store the FPU state in the allocated size. */
392 _Static_assert (sizeof(fpu_state_t
) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE
,
393 "GFC_FPE_STATE_BUFFER_SIZE is too small");
397 get_fpu_state (void *s
)
399 fpu_state_t
*state
= s
;
401 state
->mask
= fpgetmask ();
402 state
->sticky
= fpgetsticky ();
403 state
->round
= fpgetround ();
407 set_fpu_state (void *s
)
409 fpu_state_t
*state
= s
;
411 fpsetmask (state
->mask
);
412 FPSETSTICKY (state
->sticky
);
413 fpsetround (state
->round
);
418 support_fpu_underflow_control (int kind
__attribute__((unused
)))
425 get_fpu_underflow_mode (void)
432 set_fpu_underflow_mode (int gradual
__attribute__((unused
)))