1 /* FPU-related code for systems with GNU libc.
2 Copyright (C) 2005-2014 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 systems with the GNU libc, providing the
27 feenableexcept function in fenv.h to set individual exceptions
28 (there's nothing to do that in C99). */
37 void set_fpu_trap_exceptions (int trap
, int notrap
)
40 if (trap
& GFC_FPE_INVALID
)
41 feenableexcept (FE_INVALID
);
42 if (notrap
& GFC_FPE_INVALID
)
43 fedisableexcept (FE_INVALID
);
46 /* Some glibc targets (like alpha) have FE_DENORMAL, but not many. */
48 if (trap
& GFC_FPE_DENORMAL
)
49 feenableexcept (FE_DENORMAL
);
50 if (notrap
& GFC_FPE_DENORMAL
)
51 fedisableexcept (FE_DENORMAL
);
55 if (trap
& GFC_FPE_ZERO
)
56 feenableexcept (FE_DIVBYZERO
);
57 if (notrap
& GFC_FPE_ZERO
)
58 fedisableexcept (FE_DIVBYZERO
);
62 if (trap
& GFC_FPE_OVERFLOW
)
63 feenableexcept (FE_OVERFLOW
);
64 if (notrap
& GFC_FPE_OVERFLOW
)
65 fedisableexcept (FE_OVERFLOW
);
69 if (trap
& GFC_FPE_UNDERFLOW
)
70 feenableexcept (FE_UNDERFLOW
);
71 if (notrap
& GFC_FPE_UNDERFLOW
)
72 fedisableexcept (FE_UNDERFLOW
);
76 if (trap
& GFC_FPE_INEXACT
)
77 feenableexcept (FE_INEXACT
);
78 if (notrap
& GFC_FPE_INEXACT
)
79 fedisableexcept (FE_INEXACT
);
85 get_fpu_trap_exceptions (void)
87 int exceptions
= fegetexcept ();
91 if (exceptions
& FE_INVALID
) res
|= GFC_FPE_INVALID
;
95 if (exceptions
& FE_DENORMAL
) res
|= GFC_FPE_DENORMAL
;
99 if (exceptions
& FE_DIVBYZERO
) res
|= GFC_FPE_ZERO
;
103 if (exceptions
& FE_OVERFLOW
) res
|= GFC_FPE_OVERFLOW
;
107 if (exceptions
& FE_UNDERFLOW
) res
|= GFC_FPE_UNDERFLOW
;
111 if (exceptions
& FE_INEXACT
) res
|= GFC_FPE_INEXACT
;
119 support_fpu_trap (int flag
)
121 return support_fpu_flag (flag
);
128 if (options
.fpe
& GFC_FPE_INVALID
)
129 estr_write ("Fortran runtime warning: IEEE 'invalid operation' "
130 "exception not supported.\n");
134 if (options
.fpe
& GFC_FPE_DENORMAL
)
135 estr_write ("Fortran runtime warning: Floating point 'denormal operand' "
136 "exception not supported.\n");
140 if (options
.fpe
& GFC_FPE_ZERO
)
141 estr_write ("Fortran runtime warning: IEEE 'division by zero' "
142 "exception not supported.\n");
146 if (options
.fpe
& GFC_FPE_OVERFLOW
)
147 estr_write ("Fortran runtime warning: IEEE 'overflow' "
148 "exception not supported.\n");
152 if (options
.fpe
& GFC_FPE_UNDERFLOW
)
153 estr_write ("Fortran runtime warning: IEEE 'underflow' "
154 "exception not supported.\n");
158 if (options
.fpe
& GFC_FPE_INEXACT
)
159 estr_write ("Fortran runtime warning: IEEE 'inexact' "
160 "exception not supported.\n");
163 set_fpu_trap_exceptions (options
.fpe
, 0);
168 get_fpu_except_flags (void)
170 int result
, set_excepts
;
173 set_excepts
= fetestexcept (FE_ALL_EXCEPT
);
176 if (set_excepts
& FE_INVALID
)
177 result
|= GFC_FPE_INVALID
;
181 if (set_excepts
& FE_DIVBYZERO
)
182 result
|= GFC_FPE_ZERO
;
186 if (set_excepts
& FE_OVERFLOW
)
187 result
|= GFC_FPE_OVERFLOW
;
191 if (set_excepts
& FE_UNDERFLOW
)
192 result
|= GFC_FPE_UNDERFLOW
;
196 if (set_excepts
& FE_DENORMAL
)
197 result
|= GFC_FPE_DENORMAL
;
201 if (set_excepts
& FE_INEXACT
)
202 result
|= GFC_FPE_INEXACT
;
210 set_fpu_except_flags (int set
, int clear
)
212 int exc_set
= 0, exc_clr
= 0;
215 if (set
& GFC_FPE_INVALID
)
216 exc_set
|= FE_INVALID
;
217 else if (clear
& GFC_FPE_INVALID
)
218 exc_clr
|= FE_INVALID
;
222 if (set
& GFC_FPE_ZERO
)
223 exc_set
|= FE_DIVBYZERO
;
224 else if (clear
& GFC_FPE_ZERO
)
225 exc_clr
|= FE_DIVBYZERO
;
229 if (set
& GFC_FPE_OVERFLOW
)
230 exc_set
|= FE_OVERFLOW
;
231 else if (clear
& GFC_FPE_OVERFLOW
)
232 exc_clr
|= FE_OVERFLOW
;
236 if (set
& GFC_FPE_UNDERFLOW
)
237 exc_set
|= FE_UNDERFLOW
;
238 else if (clear
& GFC_FPE_UNDERFLOW
)
239 exc_clr
|= FE_UNDERFLOW
;
243 if (set
& GFC_FPE_DENORMAL
)
244 exc_set
|= FE_DENORMAL
;
245 else if (clear
& GFC_FPE_DENORMAL
)
246 exc_clr
|= FE_DENORMAL
;
250 if (set
& GFC_FPE_INEXACT
)
251 exc_set
|= FE_INEXACT
;
252 else if (clear
& GFC_FPE_INEXACT
)
253 exc_clr
|= FE_INEXACT
;
256 feclearexcept (exc_clr
);
257 feraiseexcept (exc_set
);
262 support_fpu_flag (int flag
)
264 if (flag
& GFC_FPE_INVALID
)
270 else if (flag
& GFC_FPE_ZERO
)
276 else if (flag
& GFC_FPE_OVERFLOW
)
282 else if (flag
& GFC_FPE_UNDERFLOW
)
288 else if (flag
& GFC_FPE_DENORMAL
)
294 else if (flag
& GFC_FPE_INEXACT
)
306 get_fpu_rounding_mode (void)
310 rnd_mode
= fegetround ();
316 return GFC_FPE_TONEAREST
;
321 return GFC_FPE_UPWARD
;
326 return GFC_FPE_DOWNWARD
;
331 return GFC_FPE_TOWARDZERO
;
334 return GFC_FPE_INVALID
;
340 set_fpu_rounding_mode (int mode
)
347 case GFC_FPE_TONEAREST
:
348 rnd_mode
= FE_TONEAREST
;
354 rnd_mode
= FE_UPWARD
;
359 case GFC_FPE_DOWNWARD
:
360 rnd_mode
= FE_DOWNWARD
;
365 case GFC_FPE_TOWARDZERO
:
366 rnd_mode
= FE_TOWARDZERO
;
373 fesetround (rnd_mode
);
378 support_fpu_rounding_mode (int mode
)
382 case GFC_FPE_TONEAREST
:
396 case GFC_FPE_DOWNWARD
:
403 case GFC_FPE_TOWARDZERO
:
417 get_fpu_state (void *state
)
419 /* Check we can actually store the FPU state in the allocated size. */
420 assert (sizeof(fenv_t
) <= GFC_FPE_STATE_BUFFER_SIZE
);
427 set_fpu_state (void *state
)
429 /* Check we can actually store the FPU state in the allocated size. */
430 assert (sizeof(fenv_t
) <= GFC_FPE_STATE_BUFFER_SIZE
);