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");
133 /* glibc does never have a FE_DENORMAL. */
135 if (options
.fpe
& GFC_FPE_DENORMAL
)
136 estr_write ("Fortran runtime warning: Floating point 'denormal operand' "
137 "exception not supported.\n");
141 if (options
.fpe
& GFC_FPE_ZERO
)
142 estr_write ("Fortran runtime warning: IEEE 'division by zero' "
143 "exception not supported.\n");
147 if (options
.fpe
& GFC_FPE_OVERFLOW
)
148 estr_write ("Fortran runtime warning: IEEE 'overflow' "
149 "exception not supported.\n");
153 if (options
.fpe
& GFC_FPE_UNDERFLOW
)
154 estr_write ("Fortran runtime warning: IEEE 'underflow' "
155 "exception not supported.\n");
159 if (options
.fpe
& GFC_FPE_INEXACT
)
160 estr_write ("Fortran runtime warning: IEEE 'inexact' "
161 "exception not supported.\n");
164 set_fpu_trap_exceptions (options
.fpe
, 0);
169 get_fpu_except_flags (void)
171 int result
, set_excepts
;
174 set_excepts
= fetestexcept (FE_ALL_EXCEPT
);
177 if (set_excepts
& FE_INVALID
)
178 result
|= GFC_FPE_INVALID
;
182 if (set_excepts
& FE_DIVBYZERO
)
183 result
|= GFC_FPE_ZERO
;
187 if (set_excepts
& FE_OVERFLOW
)
188 result
|= GFC_FPE_OVERFLOW
;
192 if (set_excepts
& FE_UNDERFLOW
)
193 result
|= GFC_FPE_UNDERFLOW
;
197 if (set_excepts
& FE_DENORMAL
)
198 result
|= GFC_FPE_DENORMAL
;
202 if (set_excepts
& FE_INEXACT
)
203 result
|= GFC_FPE_INEXACT
;
211 set_fpu_except_flags (int set
, int clear
)
213 int exc_set
= 0, exc_clr
= 0;
216 if (set
& GFC_FPE_INVALID
)
217 exc_set
|= FE_INVALID
;
218 else if (clear
& GFC_FPE_INVALID
)
219 exc_clr
|= FE_INVALID
;
223 if (set
& GFC_FPE_ZERO
)
224 exc_set
|= FE_DIVBYZERO
;
225 else if (clear
& GFC_FPE_ZERO
)
226 exc_clr
|= FE_DIVBYZERO
;
230 if (set
& GFC_FPE_OVERFLOW
)
231 exc_set
|= FE_OVERFLOW
;
232 else if (clear
& GFC_FPE_OVERFLOW
)
233 exc_clr
|= FE_OVERFLOW
;
237 if (set
& GFC_FPE_UNDERFLOW
)
238 exc_set
|= FE_UNDERFLOW
;
239 else if (clear
& GFC_FPE_UNDERFLOW
)
240 exc_clr
|= FE_UNDERFLOW
;
244 if (set
& GFC_FPE_DENORMAL
)
245 exc_set
|= FE_DENORMAL
;
246 else if (clear
& GFC_FPE_DENORMAL
)
247 exc_clr
|= FE_DENORMAL
;
251 if (set
& GFC_FPE_INEXACT
)
252 exc_set
|= FE_INEXACT
;
253 else if (clear
& GFC_FPE_INEXACT
)
254 exc_clr
|= FE_INEXACT
;
257 feclearexcept (exc_clr
);
258 feraiseexcept (exc_set
);
263 support_fpu_flag (int flag
)
265 if (flag
& GFC_FPE_INVALID
)
271 else if (flag
& GFC_FPE_ZERO
)
277 else if (flag
& GFC_FPE_OVERFLOW
)
283 else if (flag
& GFC_FPE_UNDERFLOW
)
289 else if (flag
& GFC_FPE_DENORMAL
)
295 else if (flag
& GFC_FPE_INEXACT
)
307 get_fpu_rounding_mode (void)
311 rnd_mode
= fegetround ();
317 return GFC_FPE_TONEAREST
;
322 return GFC_FPE_UPWARD
;
327 return GFC_FPE_DOWNWARD
;
332 return GFC_FPE_TOWARDZERO
;
335 return GFC_FPE_INVALID
;
341 set_fpu_rounding_mode (int mode
)
348 case GFC_FPE_TONEAREST
:
349 rnd_mode
= FE_TONEAREST
;
355 rnd_mode
= FE_UPWARD
;
360 case GFC_FPE_DOWNWARD
:
361 rnd_mode
= FE_DOWNWARD
;
366 case GFC_FPE_TOWARDZERO
:
367 rnd_mode
= FE_TOWARDZERO
;
374 fesetround (rnd_mode
);
379 support_fpu_rounding_mode (int mode
)
383 case GFC_FPE_TONEAREST
:
397 case GFC_FPE_DOWNWARD
:
404 case GFC_FPE_TOWARDZERO
:
418 get_fpu_state (void *state
)
420 /* Check we can actually store the FPU state in the allocated size. */
421 assert (sizeof(fenv_t
) <= GFC_FPE_STATE_BUFFER_SIZE
);
428 set_fpu_state (void *state
)
430 /* Check we can actually store the FPU state in the allocated size. */
431 assert (sizeof(fenv_t
) <= GFC_FPE_STATE_BUFFER_SIZE
);