2015-05-05 Yvan Roux <yvan.roux@linaro.org>
[official-gcc.git] / libgfortran / config / fpu-sysv.h
blobe7a7fac04ae9d4190a5a05f2fe8a02f0e6016dda
1 /* SysV FPU-related code (for systems not otherwise supported).
2 Copyright (C) 2005-2015 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 SysV platforms with fpsetmask(). */
28 /* BSD and Solaris systems have slightly different types and functions
29 naming. We deal with these here, to simplify the code below. */
31 #if HAVE_FP_EXCEPT
32 # define FP_EXCEPT_TYPE fp_except
33 #elif HAVE_FP_EXCEPT_T
34 # define FP_EXCEPT_TYPE fp_except_t
35 #else
36 choke me
37 #endif
39 #if HAVE_FP_RND
40 # define FP_RND_TYPE fp_rnd
41 #elif HAVE_FP_RND_T
42 # define FP_RND_TYPE fp_rnd_t
43 #else
44 choke me
45 #endif
47 #if HAVE_FPSETSTICKY
48 # define FPSETSTICKY fpsetsticky
49 #elif HAVE_FPRESETSTICKY
50 # define FPSETSTICKY fpresetsticky
51 #else
52 choke me
53 #endif
56 void
57 set_fpu_trap_exceptions (int trap, int notrap)
59 FP_EXCEPT_TYPE cw = fpgetmask();
61 #ifdef FP_X_INV
62 if (trap & GFC_FPE_INVALID)
63 cw |= FP_X_INV;
64 if (notrap & GFC_FPE_INVALID)
65 cw &= ~FP_X_INV;
66 #endif
68 #ifdef FP_X_DNML
69 if (trap & GFC_FPE_DENORMAL)
70 cw |= FP_X_DNML;
71 if (notrap & GFC_FPE_DENORMAL)
72 cw &= ~FP_X_DNML;
73 #endif
75 #ifdef FP_X_DZ
76 if (trap & GFC_FPE_ZERO)
77 cw |= FP_X_DZ;
78 if (notrap & GFC_FPE_ZERO)
79 cw &= ~FP_X_DZ;
80 #endif
82 #ifdef FP_X_OFL
83 if (trap & GFC_FPE_OVERFLOW)
84 cw |= FP_X_OFL;
85 if (notrap & GFC_FPE_OVERFLOW)
86 cw &= ~FP_X_OFL;
87 #endif
89 #ifdef FP_X_UFL
90 if (trap & GFC_FPE_UNDERFLOW)
91 cw |= FP_X_UFL;
92 if (notrap & GFC_FPE_UNDERFLOW)
93 cw &= ~FP_X_UFL;
94 #endif
96 #ifdef FP_X_IMP
97 if (trap & GFC_FPE_INEXACT)
98 cw |= FP_X_IMP;
99 if (notrap & GFC_FPE_INEXACT)
100 cw &= ~FP_X_IMP;
101 #endif
103 fpsetmask(cw);
108 get_fpu_trap_exceptions (void)
110 int res = 0;
111 FP_EXCEPT_TYPE cw = fpgetmask();
113 #ifdef FP_X_INV
114 if (cw & FP_X_INV) res |= GFC_FPE_INVALID;
115 #endif
117 #ifdef FP_X_DNML
118 if (cw & FP_X_DNML) res |= GFC_FPE_DENORMAL;
119 #endif
121 #ifdef FP_X_DZ
122 if (cw & FP_X_DZ) res |= GFC_FPE_ZERO;
123 #endif
125 #ifdef FP_X_OFL
126 if (cw & FP_X_OFL) res |= GFC_FPE_OVERFLOW;
127 #endif
129 #ifdef FP_X_UFL
130 if (cw & FP_X_UFL) res |= GFC_FPE_UNDERFLOW;
131 #endif
133 #ifdef FP_X_IMP
134 if (cw & FP_X_IMP) res |= GFC_FPE_INEXACT;
135 #endif
137 return res;
142 support_fpu_trap (int flag)
144 return support_fpu_flag (flag);
148 void
149 set_fpu (void)
151 #ifndef FP_X_INV
152 if (options.fpe & GFC_FPE_INVALID)
153 estr_write ("Fortran runtime warning: IEEE 'invalid operation' "
154 "exception not supported.\n");
155 #endif
157 #ifndef FP_X_DNML
158 if (options.fpe & GFC_FPE_DENORMAL)
159 estr_write ("Fortran runtime warning: Floating point 'denormal operand' "
160 "exception not supported.\n");
161 #endif
163 #ifndef FP_X_DZ
164 if (options.fpe & GFC_FPE_ZERO)
165 estr_write ("Fortran runtime warning: IEEE 'division by zero' "
166 "exception not supported.\n");
167 #endif
169 #ifndef FP_X_OFL
170 if (options.fpe & GFC_FPE_OVERFLOW)
171 estr_write ("Fortran runtime warning: IEEE 'overflow' "
172 "exception not supported.\n");
173 #endif
175 #ifndef FP_X_UFL
176 if (options.fpe & GFC_FPE_UNDERFLOW)
177 estr_write ("Fortran runtime warning: IEEE 'underflow' "
178 "exception not supported.\n");
179 #endif
181 #ifndef FP_X_IMP
182 if (options.fpe & GFC_FPE_INEXACT)
183 estr_write ("Fortran runtime warning: IEEE 'inexact' "
184 "exception not supported.\n");
185 #endif
187 set_fpu_trap_exceptions (options.fpe, 0);
192 get_fpu_except_flags (void)
194 int result;
195 FP_EXCEPT_TYPE set_excepts;
197 result = 0;
198 set_excepts = fpgetsticky ();
200 #ifdef FP_X_INV
201 if (set_excepts & FP_X_INV)
202 result |= GFC_FPE_INVALID;
203 #endif
205 #ifdef FP_X_DZ
206 if (set_excepts & FP_X_DZ)
207 result |= GFC_FPE_ZERO;
208 #endif
210 #ifdef FP_X_OFL
211 if (set_excepts & FP_X_OFL)
212 result |= GFC_FPE_OVERFLOW;
213 #endif
215 #ifdef FP_X_UFL
216 if (set_excepts & FP_X_UFL)
217 result |= GFC_FPE_UNDERFLOW;
218 #endif
220 #ifdef FP_X_DNML
221 if (set_excepts & FP_X_DNML)
222 result |= GFC_FPE_DENORMAL;
223 #endif
225 #ifdef FP_X_IMP
226 if (set_excepts & FP_X_IMP)
227 result |= GFC_FPE_INEXACT;
228 #endif
230 return result;
234 void
235 set_fpu_except_flags (int set, int clear)
237 FP_EXCEPT_TYPE flags;
239 flags = fpgetsticky ();
241 #ifdef FP_X_INV
242 if (set & GFC_FPE_INVALID)
243 flags |= FP_X_INV;
244 if (clear & GFC_FPE_INVALID)
245 flags &= ~FP_X_INV;
246 #endif
248 #ifdef FP_X_DZ
249 if (set & GFC_FPE_ZERO)
250 flags |= FP_X_DZ;
251 if (clear & GFC_FPE_ZERO)
252 flags &= ~FP_X_DZ;
253 #endif
255 #ifdef FP_X_OFL
256 if (set & GFC_FPE_OVERFLOW)
257 flags |= FP_X_OFL;
258 if (clear & GFC_FPE_OVERFLOW)
259 flags &= ~FP_X_OFL;
260 #endif
262 #ifdef FP_X_UFL
263 if (set & GFC_FPE_UNDERFLOW)
264 flags |= FP_X_UFL;
265 if (clear & GFC_FPE_UNDERFLOW)
266 flags &= ~FP_X_UFL;
267 #endif
269 #ifdef FP_X_DNML
270 if (set & GFC_FPE_DENORMAL)
271 flags |= FP_X_DNML;
272 if (clear & GFC_FPE_DENORMAL)
273 flags &= ~FP_X_DNML;
274 #endif
276 #ifdef FP_X_IMP
277 if (set & GFC_FPE_INEXACT)
278 flags |= FP_X_IMP;
279 if (clear & GFC_FPE_INEXACT)
280 flags &= ~FP_X_IMP;
281 #endif
283 FPSETSTICKY (flags);
288 support_fpu_flag (int flag)
290 if (flag & GFC_FPE_INVALID)
292 #ifndef FP_X_INV
293 return 0;
294 #endif
296 else if (flag & GFC_FPE_ZERO)
298 #ifndef FP_X_DZ
299 return 0;
300 #endif
302 else if (flag & GFC_FPE_OVERFLOW)
304 #ifndef FP_X_OFL
305 return 0;
306 #endif
308 else if (flag & GFC_FPE_UNDERFLOW)
310 #ifndef FP_X_UFL
311 return 0;
312 #endif
314 else if (flag & GFC_FPE_DENORMAL)
316 #ifndef FP_X_DNML
317 return 0;
318 #endif
320 else if (flag & GFC_FPE_INEXACT)
322 #ifndef FP_X_IMP
323 return 0;
324 #endif
327 return 1;
332 get_fpu_rounding_mode (void)
334 switch (fpgetround ())
336 case FP_RN:
337 return GFC_FPE_TONEAREST;
338 case FP_RP:
339 return GFC_FPE_UPWARD;
340 case FP_RM:
341 return GFC_FPE_DOWNWARD;
342 case FP_RZ:
343 return GFC_FPE_TOWARDZERO;
344 default:
345 return 0; /* Should be unreachable. */
350 void
351 set_fpu_rounding_mode (int mode)
353 FP_RND_TYPE rnd_mode;
355 switch (mode)
357 case GFC_FPE_TONEAREST:
358 rnd_mode = FP_RN;
359 break;
360 case GFC_FPE_UPWARD:
361 rnd_mode = FP_RP;
362 break;
363 case GFC_FPE_DOWNWARD:
364 rnd_mode = FP_RM;
365 break;
366 case GFC_FPE_TOWARDZERO:
367 rnd_mode = FP_RZ;
368 break;
369 default:
370 return; /* Should be unreachable. */
372 fpsetround (rnd_mode);
377 support_fpu_rounding_mode (int mode __attribute__((unused)))
379 return 1;
383 typedef struct
385 FP_EXCEPT_TYPE mask;
386 FP_EXCEPT_TYPE sticky;
387 FP_RND_TYPE round;
388 } fpu_state_t;
391 /* Check we can actually store the FPU state in the allocated size. */
392 _Static_assert (sizeof(fpu_state_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE,
393 "GFC_FPE_STATE_BUFFER_SIZE is too small");
396 void
397 get_fpu_state (void *s)
399 fpu_state_t *state = s;
401 state->mask = fpgetmask ();
402 state->sticky = fpgetsticky ();
403 state->round = fpgetround ();
406 void
407 set_fpu_state (void *s)
409 fpu_state_t *state = s;
411 fpsetmask (state->mask);
412 FPSETSTICKY (state->sticky);
413 fpsetround (state->round);
418 support_fpu_underflow_control (int kind __attribute__((unused)))
420 return 0;
425 get_fpu_underflow_mode (void)
427 return 0;
431 void
432 set_fpu_underflow_mode (int gradual __attribute__((unused)))