1 /* AIX FPU-related code.
2 Copyright (C) 2005-2018 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
)
295 get_fpu_rounding_mode (void)
299 rnd_mode
= fegetround ();
305 return GFC_FPE_TONEAREST
;
310 return GFC_FPE_UPWARD
;
315 return GFC_FPE_DOWNWARD
;
320 return GFC_FPE_TOWARDZERO
;
324 return 0; /* Should be unreachable. */
330 set_fpu_rounding_mode (int mode
)
337 case GFC_FPE_TONEAREST
:
338 rnd_mode
= FE_TONEAREST
;
344 rnd_mode
= FE_UPWARD
;
349 case GFC_FPE_DOWNWARD
:
350 rnd_mode
= FE_DOWNWARD
;
355 case GFC_FPE_TOWARDZERO
:
356 rnd_mode
= FE_TOWARDZERO
;
361 return; /* Should be unreachable. */
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
:
402 return 0; /* Should be unreachable. */
409 get_fpu_state (void *state
)
415 set_fpu_state (void *state
)
422 support_fpu_underflow_control (int kind
__attribute__((unused
)))
429 get_fpu_underflow_mode (void)
436 set_fpu_underflow_mode (int gradual
__attribute__((unused
)))