Home | History | Annotate | Line # | Download | only in config
fpu-sysv.h revision 1.1
      1 /* SysV FPU-related code (for systems not otherwise supported).
      2    Copyright (C) 2005-2019 Free Software Foundation, Inc.
      3    Contributed by Francois-Xavier Coudert <coudert (at) clipper.ens.fr>
      4 
      5 This file is part of the GNU Fortran runtime library (libgfortran).
      6 
      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.
     11 
     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.
     16 
     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.
     20 
     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/>.  */
     25 
     26 /* FPU-related code for SysV platforms with fpsetmask().  */
     27 
     28 /* BSD and Solaris systems have slightly different types and functions
     29    naming.  We deal with these here, to simplify the code below.  */
     30 
     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
     38 
     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
     46 
     47 #if HAVE_FPSETSTICKY
     48 # define FPSETSTICKY fpsetsticky
     49 #elif HAVE_FPRESETSTICKY
     50 # define FPSETSTICKY fpresetsticky
     51 #else
     52   choke me
     53 #endif
     54 
     55 
     56 void
     57 set_fpu_trap_exceptions (int trap, int notrap)
     58 {
     59   FP_EXCEPT_TYPE cw = fpgetmask();
     60 
     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
     67 
     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
     74 
     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
     81 
     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
     88 
     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
     95 
     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
    102 
    103   fpsetmask(cw);
    104 }
    105 
    106 
    107 int
    108 get_fpu_trap_exceptions (void)
    109 {
    110   int res = 0;
    111   FP_EXCEPT_TYPE cw = fpgetmask();
    112 
    113 #ifdef FP_X_INV
    114   if (cw & FP_X_INV) res |= GFC_FPE_INVALID;
    115 #endif
    116 
    117 #ifdef FP_X_DNML
    118   if (cw & FP_X_DNML) res |= GFC_FPE_DENORMAL;
    119 #endif
    120 
    121 #ifdef FP_X_DZ
    122   if (cw & FP_X_DZ) res |= GFC_FPE_ZERO;
    123 #endif
    124 
    125 #ifdef FP_X_OFL
    126   if (cw & FP_X_OFL) res |= GFC_FPE_OVERFLOW;
    127 #endif
    128 
    129 #ifdef FP_X_UFL
    130   if (cw & FP_X_UFL) res |= GFC_FPE_UNDERFLOW;
    131 #endif
    132 
    133 #ifdef FP_X_IMP
    134   if (cw & FP_X_IMP) res |= GFC_FPE_INEXACT;
    135 #endif
    136 
    137   return res;
    138 }
    139 
    140 
    141 int
    142 support_fpu_trap (int flag)
    143 {
    144   return support_fpu_flag (flag);
    145 }
    146 
    147 
    148 void
    149 set_fpu (void)
    150 {
    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
    156 
    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
    162 
    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
    168 
    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
    174 
    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
    180 
    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
    186 
    187   set_fpu_trap_exceptions (options.fpe, 0);
    188 }
    189 
    190 
    191 int
    192 get_fpu_except_flags (void)
    193 {
    194   int result;
    195   FP_EXCEPT_TYPE set_excepts;
    196 
    197   result = 0;
    198   set_excepts = fpgetsticky ();
    199 
    200 #ifdef FP_X_INV
    201   if (set_excepts & FP_X_INV)
    202     result |= GFC_FPE_INVALID;
    203 #endif
    204 
    205 #ifdef FP_X_DZ
    206   if (set_excepts & FP_X_DZ)
    207     result |= GFC_FPE_ZERO;
    208 #endif
    209 
    210 #ifdef FP_X_OFL
    211   if (set_excepts & FP_X_OFL)
    212     result |= GFC_FPE_OVERFLOW;
    213 #endif
    214 
    215 #ifdef FP_X_UFL
    216   if (set_excepts & FP_X_UFL)
    217     result |= GFC_FPE_UNDERFLOW;
    218 #endif
    219 
    220 #ifdef FP_X_DNML
    221   if (set_excepts & FP_X_DNML)
    222     result |= GFC_FPE_DENORMAL;
    223 #endif
    224 
    225 #ifdef FP_X_IMP
    226   if (set_excepts & FP_X_IMP)
    227     result |= GFC_FPE_INEXACT;
    228 #endif
    229 
    230   return result;
    231 }
    232 
    233 
    234 void
    235 set_fpu_except_flags (int set, int clear)
    236 {
    237   FP_EXCEPT_TYPE flags;
    238 
    239   flags = fpgetsticky ();
    240 
    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
    247 
    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
    254 
    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
    261 
    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
    268 
    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
    275 
    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
    282 
    283   FPSETSTICKY (flags);
    284 }
    285 
    286 
    287 int
    288 support_fpu_flag (int flag)
    289 {
    290   if (flag & GFC_FPE_INVALID)
    291   {
    292 #ifndef FP_X_INV
    293     return 0;
    294 #endif
    295   }
    296   else if (flag & GFC_FPE_ZERO)
    297   {
    298 #ifndef FP_X_DZ
    299     return 0;
    300 #endif
    301   }
    302   else if (flag & GFC_FPE_OVERFLOW)
    303   {
    304 #ifndef FP_X_OFL
    305     return 0;
    306 #endif
    307   }
    308   else if (flag & GFC_FPE_UNDERFLOW)
    309   {
    310 #ifndef FP_X_UFL
    311     return 0;
    312 #endif
    313   }
    314   else if (flag & GFC_FPE_DENORMAL)
    315   {
    316 #ifndef FP_X_DNML
    317     return 0;
    318 #endif
    319   }
    320   else if (flag & GFC_FPE_INEXACT)
    321   {
    322 #ifndef FP_X_IMP
    323     return 0;
    324 #endif
    325   }
    326 
    327   return 1;
    328 }
    329 
    330 
    331 int
    332 get_fpu_rounding_mode (void)
    333 {
    334   switch (fpgetround ())
    335     {
    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.  */
    346     }
    347 }
    348 
    349 
    350 void
    351 set_fpu_rounding_mode (int mode)
    352 {
    353   FP_RND_TYPE rnd_mode;
    354 
    355   switch (mode)
    356     {
    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.  */
    371     }
    372   fpsetround (rnd_mode);
    373 }
    374 
    375 
    376 int
    377 support_fpu_rounding_mode (int mode __attribute__((unused)))
    378 {
    379   return 1;
    380 }
    381 
    382 
    383 typedef struct
    384 {
    385   FP_EXCEPT_TYPE mask;
    386   FP_EXCEPT_TYPE sticky;
    387   FP_RND_TYPE round;
    388 } fpu_state_t;
    389 
    390 
    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");
    394 
    395 
    396 void
    397 get_fpu_state (void *s)
    398 {
    399   fpu_state_t *state = s;
    400 
    401   state->mask = fpgetmask ();
    402   state->sticky = fpgetsticky ();
    403   state->round = fpgetround ();
    404 }
    405 
    406 void
    407 set_fpu_state (void *s)
    408 {
    409   fpu_state_t *state = s;
    410 
    411   fpsetmask (state->mask);
    412   FPSETSTICKY (state->sticky);
    413   fpsetround (state->round);
    414 }
    415 
    416 
    417 int
    418 support_fpu_underflow_control (int kind __attribute__((unused)))
    419 {
    420   return 0;
    421 }
    422 
    423 
    424 int
    425 get_fpu_underflow_mode (void)
    426 {
    427   return 0;
    428 }
    429 
    430 
    431 void
    432 set_fpu_underflow_mode (int gradual __attribute__((unused)))
    433 {
    434 }
    435 
    436