1 /* AIX FPU-related code.
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/>. */
27 /* FPU-related code for AIX. */
42 set_fpu_trap_exceptions (int trap
, int notrap
)
44 fptrap_t mode_set
= 0, mode_clr
= 0;
47 if (trap
& GFC_FPE_INVALID
)
48 mode_set
|= TRP_INVALID
;
49 if (notrap
& GFC_FPE_INVALID
)
50 mode_clr
|= TRP_INVALID
;
53 #ifdef TRP_DIV_BY_ZERO
54 if (trap
& GFC_FPE_ZERO
)
55 mode_set
|= TRP_DIV_BY_ZERO
;
56 if (notrap
& GFC_FPE_ZERO
)
57 mode_clr
|= TRP_DIV_BY_ZERO
;
61 if (trap
& GFC_FPE_OVERFLOW
)
62 mode_set
|= TRP_OVERFLOW
;
63 if (notrap
& GFC_FPE_OVERFLOW
)
64 mode_clr
|= TRP_OVERFLOW
;
68 if (trap
& GFC_FPE_UNDERFLOW
)
69 mode_set
|= TRP_UNDERFLOW
;
70 if (notrap
& GFC_FPE_UNDERFLOW
)
71 mode_clr
|= TRP_UNDERFLOW
;
75 if (trap
& GFC_FPE_INEXACT
)
76 mode_set
|= TRP_INEXACT
;
77 if (notrap
& GFC_FPE_INEXACT
)
78 mode_clr
|= TRP_INEXACT
;
81 fp_trap (FP_TRAP_SYNC
);
83 fp_disable (mode_clr
);
88 get_fpu_trap_exceptions (void)
93 if (fp_is_enabled (TRP_INVALID
))
94 res
|= GFC_FPE_INVALID
;
97 #ifdef TRP_DIV_BY_ZERO
98 if (fp_is_enabled (TRP_DIV_BY_ZERO
))
103 if (fp_is_enabled (TRP_OVERFLOW
))
104 res
|= GFC_FPE_OVERFLOW
;
108 if (fp_is_enabled (TRP_UNDERFLOW
))
109 res
|= GFC_FPE_UNDERFLOW
;
113 if (fp_is_enabled (TRP_INEXACT
))
114 res
|= GFC_FPE_INEXACT
;
122 support_fpu_trap (int flag
)
124 return support_fpu_flag (flag
);
132 if (options
.fpe
& GFC_FPE_INVALID
)
133 estr_write ("Fortran runtime warning: IEEE 'invalid operation' "
134 "exception not supported.\n");
137 if (options
.fpe
& GFC_FPE_DENORMAL
)
138 estr_write ("Fortran runtime warning: Floating point 'denormal operand' "
139 "exception not supported.\n");
141 #ifndef TRP_DIV_BY_ZERO
142 if (options
.fpe
& GFC_FPE_ZERO
)
143 estr_write ("Fortran runtime warning: IEEE 'division by zero' "
144 "exception not supported.\n");
148 if (options
.fpe
& GFC_FPE_OVERFLOW
)
149 estr_write ("Fortran runtime warning: IEEE 'overflow' "
150 "exception not supported.\n");
153 #ifndef TRP_UNDERFLOW
154 if (options
.fpe
& GFC_FPE_UNDERFLOW
)
155 estr_write ("Fortran runtime warning: IEEE 'underflow' "
156 "exception not supported.\n");
160 if (options
.fpe
& GFC_FPE_INEXACT
)
161 estr_write ("Fortran runtime warning: IEEE 'inexact' "
162 "exception not supported.\n");
165 set_fpu_trap_exceptions (options
.fpe
, 0);
169 get_fpu_except_flags (void)
171 int result
, set_excepts
;
179 if (fp_invalid_op ())
180 result
|= GFC_FPE_INVALID
;
183 result
|= GFC_FPE_ZERO
;
186 result
|= GFC_FPE_OVERFLOW
;
189 result
|= GFC_FPE_UNDERFLOW
;
192 result
|= GFC_FPE_INEXACT
;
200 set_fpu_except_flags (int set
, int clear
)
202 int exc_set
= 0, exc_clr
= 0;
205 if (set
& GFC_FPE_INVALID
)
206 exc_set
|= FP_INVALID
;
207 else if (clear
& GFC_FPE_INVALID
)
208 exc_clr
|= FP_INVALID
;
211 #ifdef FP_DIV_BY_ZERO
212 if (set
& GFC_FPE_ZERO
)
213 exc_set
|= FP_DIV_BY_ZERO
;
214 else if (clear
& GFC_FPE_ZERO
)
215 exc_clr
|= FP_DIV_BY_ZERO
;
219 if (set
& GFC_FPE_OVERFLOW
)
220 exc_set
|= FP_OVERFLOW
;
221 else if (clear
& GFC_FPE_OVERFLOW
)
222 exc_clr
|= FP_OVERFLOW
;
226 if (set
& GFC_FPE_UNDERFLOW
)
227 exc_set
|= FP_UNDERFLOW
;
228 else if (clear
& GFC_FPE_UNDERFLOW
)
229 exc_clr
|= FP_UNDERFLOW
;
232 /* AIX does not have FP_DENORMAL. */
235 if (set
& GFC_FPE_INEXACT
)
236 exc_set
|= FP_INEXACT
;
237 else if (clear
& GFC_FPE_INEXACT
)
238 exc_clr
|= FP_INEXACT
;
241 fp_clr_flag (exc_clr
);
242 fp_set_flag (exc_set
);
247 support_fpu_flag (int flag
)
249 if (flag
& GFC_FPE_INVALID
)
255 else if (flag
& GFC_FPE_ZERO
)
257 #ifndef FP_DIV_BY_ZERO
261 else if (flag
& GFC_FPE_OVERFLOW
)
267 else if (flag
& GFC_FPE_UNDERFLOW
)
273 else if (flag
& GFC_FPE_DENORMAL
)
275 /* AIX does not support denormal flag. */
278 else if (flag
& GFC_FPE_INEXACT
)
292 get_fpu_rounding_mode (void)
296 rnd_mode
= fegetround ();
302 return GFC_FPE_TONEAREST
;
307 return GFC_FPE_UPWARD
;
312 return GFC_FPE_DOWNWARD
;
317 return GFC_FPE_TOWARDZERO
;
320 return GFC_FPE_INVALID
;
326 set_fpu_rounding_mode (int mode
)
333 case GFC_FPE_TONEAREST
:
334 rnd_mode
= FE_TONEAREST
;
340 rnd_mode
= FE_UPWARD
;
345 case GFC_FPE_DOWNWARD
:
346 rnd_mode
= FE_DOWNWARD
;
351 case GFC_FPE_TOWARDZERO
:
352 rnd_mode
= FE_TOWARDZERO
;
359 fesetround (rnd_mode
);
364 support_fpu_rounding_mode (int mode
)
368 case GFC_FPE_TONEAREST
:
382 case GFC_FPE_DOWNWARD
:
389 case GFC_FPE_TOWARDZERO
:
404 get_fpu_state (void *state
)
406 /* Check we can actually store the FPU state in the allocated size. */
407 assert (sizeof(fenv_t
) <= GFC_FPE_STATE_BUFFER_SIZE
);
413 set_fpu_state (void *state
)
415 /* Check we can actually store the FPU state in the allocated size. */
416 assert (sizeof(fenv_t
) <= GFC_FPE_STATE_BUFFER_SIZE
);