PR fortran/29383
[official-gcc.git] / libgfortran / config / fpu-aix.h
blob6b44ab7c850ec7e86587193a090c0355afce3e28
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. */
28 #ifdef HAVE_FPTRAP_H
29 #include <fptrap.h>
30 #endif
32 #ifdef HAVE_FPXCP_H
33 #include <fpxcp.h>
34 #endif
36 #ifdef HAVE_FENV_H
37 #include <fenv.h>
38 #endif
41 void
42 set_fpu_trap_exceptions (int trap, int notrap)
44 fptrap_t mode_set = 0, mode_clr = 0;
46 #ifdef TRP_INVALID
47 if (trap & GFC_FPE_INVALID)
48 mode_set |= TRP_INVALID;
49 if (notrap & GFC_FPE_INVALID)
50 mode_clr |= TRP_INVALID;
51 #endif
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;
58 #endif
60 #ifdef TRP_OVERFLOW
61 if (trap & GFC_FPE_OVERFLOW)
62 mode_set |= TRP_OVERFLOW;
63 if (notrap & GFC_FPE_OVERFLOW)
64 mode_clr |= TRP_OVERFLOW;
65 #endif
67 #ifdef TRP_UNDERFLOW
68 if (trap & GFC_FPE_UNDERFLOW)
69 mode_set |= TRP_UNDERFLOW;
70 if (notrap & GFC_FPE_UNDERFLOW)
71 mode_clr |= TRP_UNDERFLOW;
72 #endif
74 #ifdef TRP_INEXACT
75 if (trap & GFC_FPE_INEXACT)
76 mode_set |= TRP_INEXACT;
77 if (notrap & GFC_FPE_INEXACT)
78 mode_clr |= TRP_INEXACT;
79 #endif
81 fp_trap (FP_TRAP_SYNC);
82 fp_enable (mode_set);
83 fp_disable (mode_clr);
87 int
88 get_fpu_trap_exceptions (void)
90 int res = 0;
92 #ifdef TRP_INVALID
93 if (fp_is_enabled (TRP_INVALID))
94 res |= GFC_FPE_INVALID;
95 #endif
97 #ifdef TRP_DIV_BY_ZERO
98 if (fp_is_enabled (TRP_DIV_BY_ZERO))
99 res |= GFC_FPE_ZERO;
100 #endif
102 #ifdef TRP_OVERFLOW
103 if (fp_is_enabled (TRP_OVERFLOW))
104 res |= GFC_FPE_OVERFLOW;
105 #endif
107 #ifdef TRP_UNDERFLOW
108 if (fp_is_enabled (TRP_UNDERFLOW))
109 res |= GFC_FPE_UNDERFLOW;
110 #endif
112 #ifdef TRP_INEXACT
113 if (fp_is_enabled (TRP_INEXACT))
114 res |= GFC_FPE_INEXACT;
115 #endif
117 return res;
122 support_fpu_trap (int flag)
124 return support_fpu_flag (flag);
128 void
129 set_fpu (void)
131 #ifndef TRP_INVALID
132 if (options.fpe & GFC_FPE_INVALID)
133 estr_write ("Fortran runtime warning: IEEE 'invalid operation' "
134 "exception not supported.\n");
135 #endif
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");
145 #endif
147 #ifndef TRP_OVERFLOW
148 if (options.fpe & GFC_FPE_OVERFLOW)
149 estr_write ("Fortran runtime warning: IEEE 'overflow' "
150 "exception not supported.\n");
151 #endif
153 #ifndef TRP_UNDERFLOW
154 if (options.fpe & GFC_FPE_UNDERFLOW)
155 estr_write ("Fortran runtime warning: IEEE 'underflow' "
156 "exception not supported.\n");
157 #endif
159 #ifndef TRP_INEXACT
160 if (options.fpe & GFC_FPE_INEXACT)
161 estr_write ("Fortran runtime warning: IEEE 'inexact' "
162 "exception not supported.\n");
163 #endif
165 set_fpu_trap_exceptions (options.fpe, 0);
169 get_fpu_except_flags (void)
171 int result, set_excepts;
173 result = 0;
175 #ifdef HAVE_FPXCP_H
176 if (!fp_any_xcp ())
177 return 0;
179 if (fp_invalid_op ())
180 result |= GFC_FPE_INVALID;
182 if (fp_divbyzero ())
183 result |= GFC_FPE_ZERO;
185 if (fp_overflow ())
186 result |= GFC_FPE_OVERFLOW;
188 if (fp_underflow ())
189 result |= GFC_FPE_UNDERFLOW;
191 if (fp_inexact ())
192 result |= GFC_FPE_INEXACT;
193 #endif
195 return result;
199 void
200 set_fpu_except_flags (int set, int clear)
202 int exc_set = 0, exc_clr = 0;
204 #ifdef FP_INVALID
205 if (set & GFC_FPE_INVALID)
206 exc_set |= FP_INVALID;
207 else if (clear & GFC_FPE_INVALID)
208 exc_clr |= FP_INVALID;
209 #endif
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;
216 #endif
218 #ifdef FP_OVERFLOW
219 if (set & GFC_FPE_OVERFLOW)
220 exc_set |= FP_OVERFLOW;
221 else if (clear & GFC_FPE_OVERFLOW)
222 exc_clr |= FP_OVERFLOW;
223 #endif
225 #ifdef FP_UNDERFLOW
226 if (set & GFC_FPE_UNDERFLOW)
227 exc_set |= FP_UNDERFLOW;
228 else if (clear & GFC_FPE_UNDERFLOW)
229 exc_clr |= FP_UNDERFLOW;
230 #endif
232 /* AIX does not have FP_DENORMAL. */
234 #ifdef FP_INEXACT
235 if (set & GFC_FPE_INEXACT)
236 exc_set |= FP_INEXACT;
237 else if (clear & GFC_FPE_INEXACT)
238 exc_clr |= FP_INEXACT;
239 #endif
241 fp_clr_flag (exc_clr);
242 fp_set_flag (exc_set);
247 support_fpu_flag (int flag)
249 if (flag & GFC_FPE_INVALID)
251 #ifndef FP_INVALID
252 return 0;
253 #endif
255 else if (flag & GFC_FPE_ZERO)
257 #ifndef FP_DIV_BY_ZERO
258 return 0;
259 #endif
261 else if (flag & GFC_FPE_OVERFLOW)
263 #ifndef FP_OVERFLOW
264 return 0;
265 #endif
267 else if (flag & GFC_FPE_UNDERFLOW)
269 #ifndef FP_UNDERFLOW
270 return 0;
271 #endif
273 else if (flag & GFC_FPE_DENORMAL)
275 /* AIX does not support denormal flag. */
276 return 0;
278 else if (flag & GFC_FPE_INEXACT)
280 #ifndef FP_INEXACT
281 return 0;
282 #endif
285 return 1;
292 get_fpu_rounding_mode (void)
294 int rnd_mode;
296 rnd_mode = fegetround ();
298 switch (rnd_mode)
300 #ifdef FE_TONEAREST
301 case FE_TONEAREST:
302 return GFC_FPE_TONEAREST;
303 #endif
305 #ifdef FE_UPWARD
306 case FE_UPWARD:
307 return GFC_FPE_UPWARD;
308 #endif
310 #ifdef FE_DOWNWARD
311 case FE_DOWNWARD:
312 return GFC_FPE_DOWNWARD;
313 #endif
315 #ifdef FE_TOWARDZERO
316 case FE_TOWARDZERO:
317 return GFC_FPE_TOWARDZERO;
318 #endif
319 default:
320 return GFC_FPE_INVALID;
325 void
326 set_fpu_rounding_mode (int mode)
328 int rnd_mode;
330 switch (mode)
332 #ifdef FE_TONEAREST
333 case GFC_FPE_TONEAREST:
334 rnd_mode = FE_TONEAREST;
335 break;
336 #endif
338 #ifdef FE_UPWARD
339 case GFC_FPE_UPWARD:
340 rnd_mode = FE_UPWARD;
341 break;
342 #endif
344 #ifdef FE_DOWNWARD
345 case GFC_FPE_DOWNWARD:
346 rnd_mode = FE_DOWNWARD;
347 break;
348 #endif
350 #ifdef FE_TOWARDZERO
351 case GFC_FPE_TOWARDZERO:
352 rnd_mode = FE_TOWARDZERO;
353 break;
354 #endif
355 default:
356 return;
359 fesetround (rnd_mode);
364 support_fpu_rounding_mode (int mode)
366 switch (mode)
368 case GFC_FPE_TONEAREST:
369 #ifdef FE_TONEAREST
370 return 1;
371 #else
372 return 0;
373 #endif
375 #ifdef FE_UPWARD
376 return 1;
377 #else
378 return 0;
379 #endif
381 #ifdef FE_DOWNWARD
382 return 1;
383 #else
384 return 0;
385 #endif
387 #ifdef FE_TOWARDZERO
388 return 1;
389 #else
390 return 0;
391 #endif
393 default:
394 return 0;
400 void
401 get_fpu_state (void *state)
403 /* Check we can actually store the FPU state in the allocated size. */
404 assert (sizeof(fenv_t) <= GFC_FPE_STATE_BUFFER_SIZE);
406 fegetenv (state);
409 void
410 set_fpu_state (void *state)
412 /* Check we can actually store the FPU state in the allocated size. */
413 assert (sizeof(fenv_t) <= GFC_FPE_STATE_BUFFER_SIZE);
415 fesetenv (state);