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. */
41 /* Check we can actually store the FPU state in the allocated size. */
42 _Static_assert (sizeof(fenv_t
) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE
,
43 "GFC_FPE_STATE_BUFFER_SIZE is too small");
47 set_fpu_trap_exceptions (int trap
, int notrap
)
49 fptrap_t mode_set
= 0, mode_clr
= 0;
52 if (trap
& GFC_FPE_INVALID
)
53 mode_set
|= TRP_INVALID
;
54 if (notrap
& GFC_FPE_INVALID
)
55 mode_clr
|= TRP_INVALID
;
58 #ifdef TRP_DIV_BY_ZERO
59 if (trap
& GFC_FPE_ZERO
)
60 mode_set
|= TRP_DIV_BY_ZERO
;
61 if (notrap
& GFC_FPE_ZERO
)
62 mode_clr
|= TRP_DIV_BY_ZERO
;
66 if (trap
& GFC_FPE_OVERFLOW
)
67 mode_set
|= TRP_OVERFLOW
;
68 if (notrap
& GFC_FPE_OVERFLOW
)
69 mode_clr
|= TRP_OVERFLOW
;
73 if (trap
& GFC_FPE_UNDERFLOW
)
74 mode_set
|= TRP_UNDERFLOW
;
75 if (notrap
& GFC_FPE_UNDERFLOW
)
76 mode_clr
|= TRP_UNDERFLOW
;
80 if (trap
& GFC_FPE_INEXACT
)
81 mode_set
|= TRP_INEXACT
;
82 if (notrap
& GFC_FPE_INEXACT
)
83 mode_clr
|= TRP_INEXACT
;
86 fp_trap (FP_TRAP_SYNC
);
88 fp_disable (mode_clr
);
93 get_fpu_trap_exceptions (void)
98 if (fp_is_enabled (TRP_INVALID
))
99 res
|= GFC_FPE_INVALID
;
102 #ifdef TRP_DIV_BY_ZERO
103 if (fp_is_enabled (TRP_DIV_BY_ZERO
))
108 if (fp_is_enabled (TRP_OVERFLOW
))
109 res
|= GFC_FPE_OVERFLOW
;
113 if (fp_is_enabled (TRP_UNDERFLOW
))
114 res
|= GFC_FPE_UNDERFLOW
;
118 if (fp_is_enabled (TRP_INEXACT
))
119 res
|= GFC_FPE_INEXACT
;
127 support_fpu_trap (int flag
)
129 return support_fpu_flag (flag
);
137 if (options
.fpe
& GFC_FPE_INVALID
)
138 estr_write ("Fortran runtime warning: IEEE 'invalid operation' "
139 "exception not supported.\n");
142 if (options
.fpe
& GFC_FPE_DENORMAL
)
143 estr_write ("Fortran runtime warning: Floating point 'denormal operand' "
144 "exception not supported.\n");
146 #ifndef TRP_DIV_BY_ZERO
147 if (options
.fpe
& GFC_FPE_ZERO
)
148 estr_write ("Fortran runtime warning: IEEE 'division by zero' "
149 "exception not supported.\n");
153 if (options
.fpe
& GFC_FPE_OVERFLOW
)
154 estr_write ("Fortran runtime warning: IEEE 'overflow' "
155 "exception not supported.\n");
158 #ifndef TRP_UNDERFLOW
159 if (options
.fpe
& GFC_FPE_UNDERFLOW
)
160 estr_write ("Fortran runtime warning: IEEE 'underflow' "
161 "exception not supported.\n");
165 if (options
.fpe
& GFC_FPE_INEXACT
)
166 estr_write ("Fortran runtime warning: IEEE 'inexact' "
167 "exception not supported.\n");
170 set_fpu_trap_exceptions (options
.fpe
, 0);
174 get_fpu_except_flags (void)
176 int result
, set_excepts
;
184 if (fp_invalid_op ())
185 result
|= GFC_FPE_INVALID
;
188 result
|= GFC_FPE_ZERO
;
191 result
|= GFC_FPE_OVERFLOW
;
194 result
|= GFC_FPE_UNDERFLOW
;
197 result
|= GFC_FPE_INEXACT
;
205 set_fpu_except_flags (int set
, int clear
)
207 int exc_set
= 0, exc_clr
= 0;
210 if (set
& GFC_FPE_INVALID
)
211 exc_set
|= FP_INVALID
;
212 else if (clear
& GFC_FPE_INVALID
)
213 exc_clr
|= FP_INVALID
;
216 #ifdef FP_DIV_BY_ZERO
217 if (set
& GFC_FPE_ZERO
)
218 exc_set
|= FP_DIV_BY_ZERO
;
219 else if (clear
& GFC_FPE_ZERO
)
220 exc_clr
|= FP_DIV_BY_ZERO
;
224 if (set
& GFC_FPE_OVERFLOW
)
225 exc_set
|= FP_OVERFLOW
;
226 else if (clear
& GFC_FPE_OVERFLOW
)
227 exc_clr
|= FP_OVERFLOW
;
231 if (set
& GFC_FPE_UNDERFLOW
)
232 exc_set
|= FP_UNDERFLOW
;
233 else if (clear
& GFC_FPE_UNDERFLOW
)
234 exc_clr
|= FP_UNDERFLOW
;
237 /* AIX does not have FP_DENORMAL. */
240 if (set
& GFC_FPE_INEXACT
)
241 exc_set
|= FP_INEXACT
;
242 else if (clear
& GFC_FPE_INEXACT
)
243 exc_clr
|= FP_INEXACT
;
246 fp_clr_flag (exc_clr
);
247 fp_set_flag (exc_set
);
252 support_fpu_flag (int flag
)
254 if (flag
& GFC_FPE_INVALID
)
260 else if (flag
& GFC_FPE_ZERO
)
262 #ifndef FP_DIV_BY_ZERO
266 else if (flag
& GFC_FPE_OVERFLOW
)
272 else if (flag
& GFC_FPE_UNDERFLOW
)
278 else if (flag
& GFC_FPE_DENORMAL
)
280 /* AIX does not support denormal flag. */
283 else if (flag
& GFC_FPE_INEXACT
)
297 get_fpu_rounding_mode (void)
301 rnd_mode
= fegetround ();
307 return GFC_FPE_TONEAREST
;
312 return GFC_FPE_UPWARD
;
317 return GFC_FPE_DOWNWARD
;
322 return GFC_FPE_TOWARDZERO
;
325 return GFC_FPE_INVALID
;
331 set_fpu_rounding_mode (int mode
)
338 case GFC_FPE_TONEAREST
:
339 rnd_mode
= FE_TONEAREST
;
345 rnd_mode
= FE_UPWARD
;
350 case GFC_FPE_DOWNWARD
:
351 rnd_mode
= FE_DOWNWARD
;
356 case GFC_FPE_TOWARDZERO
:
357 rnd_mode
= FE_TOWARDZERO
;
364 fesetround (rnd_mode
);
369 support_fpu_rounding_mode (int mode
)
373 case GFC_FPE_TONEAREST
:
387 case GFC_FPE_DOWNWARD
:
394 case GFC_FPE_TOWARDZERO
:
409 get_fpu_state (void *state
)
415 set_fpu_state (void *state
)