Home | History | Annotate | Line # | Download | only in libbid
      1 /* Copyright (C) 2007-2024 Free Software Foundation, Inc.
      2 
      3 This file is part of GCC.
      4 
      5 GCC is free software; you can redistribute it and/or modify it under
      6 the terms of the GNU General Public License as published by the Free
      7 Software Foundation; either version 3, or (at your option) any later
      8 version.
      9 
     10 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     12 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     13 for more details.
     14 
     15 Under Section 7 of GPL version 3, you are granted additional
     16 permissions described in the GCC Runtime Library Exception, version
     17 3.1, as published by the Free Software Foundation.
     18 
     19 You should have received a copy of the GNU General Public License and
     20 a copy of the GCC Runtime Library Exception along with this program;
     21 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     22 <http://www.gnu.org/licenses/>.  */
     23 
     24 /*****************************************************************************
     25  *    Non-computational Operations on Flags:
     26  ****************************************************************************/
     27 
     28 #include "bid_internal.h"
     29 
     30 // Note the following definitions from bid_conf.h: if the status flags are
     31 // global, they have a fixed name recognized by the library functions:
     32 // _IDEC_glbflags; pfpsf, defined as &_IDEC_glbflags, can be used instead; no
     33 // argument is passed for the status flags to the library functions; if the
     34 // status flags are local then they are passed as an arument, always by
     35 // reference, to the library functions
     36 //
     37 // #if !DECIMAL_GLOBAL_EXCEPTION_FLAGS
     38 //   #define _EXC_FLAGS_PARAM , _IDEC_flags *pfpsf
     39 // #else
     40 //   extern _IDEC_flags _IDEC_glbflags;
     41 //   #define _EXC_FLAGS_PARAM
     42 //   #define pfpsf &_IDEC_glbflags
     43 // #endif
     44 
     45 #if DECIMAL_CALL_BY_REFERENCE
     46 void
     47 signalException (_IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
     48   // *pflagsmask is the logical OR of the flags to be set, e.g.
     49   // *pflagsmask =INVALID_EXCEPTION | ZERO_DIVIDE_EXCEPTION | OVERFLOW_EXCEPTION
     50   // UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION to set all five IEEE 754R
     51   // exception flags
     52   *pfpsf = *pfpsf | (*pflagsmask & BID_IEEE_FLAGS);
     53 }
     54 #else
     55 void
     56 signalException (_IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
     57   // flagsmask is the logical OR of the flags to be set, e.g.
     58   // flagsmask = INVALID_EXCEPTION | ZERO_DIVIDE_EXCEPTION | OVERFLOW_EXCEPTION
     59   // UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION to set all five IEEE 754R
     60   // exception flags
     61   *pfpsf = *pfpsf | (flagsmask & BID_IEEE_FLAGS);
     62 }
     63 #endif
     64 
     65 #if DECIMAL_CALL_BY_REFERENCE
     66 void
     67 lowerFlags (_IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
     68   // *pflagsmask is the logical OR of the flags to be cleared, e.g.
     69   // *pflagsmask =INVALID_EXCEPTION | ZERO_DIVIDE_EXCEPTION | OVERFLOW_EXCEPTION
     70   // UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION to clear all five IEEE 754R
     71   // exception flags
     72   *pfpsf = *pfpsf & ~(*pflagsmask & BID_IEEE_FLAGS);
     73 }
     74 #else
     75 void
     76 lowerFlags (_IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
     77   // flagsmask is the logical OR of the flags to be cleared, e.g.
     78   // flagsmask = INVALID_EXCEPTION | ZERO_DIVIDE_EXCEPTION | OVERFLOW_EXCEPTION
     79   // UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION to clear all five IEEE 754R
     80   // exception flags
     81   *pfpsf = *pfpsf & ~(flagsmask & BID_IEEE_FLAGS);
     82 }
     83 #endif
     84 
     85 #if DECIMAL_CALL_BY_REFERENCE
     86 void
     87 testFlags (_IDEC_flags * praised,
     88 	   _IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
     89   // *praised is a pointer to the result, i.e. the logical OR of the flags
     90   // selected by *pflagsmask that are set; e.g. if
     91   // *pflagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
     92   // and only the invalid and inexact flags are raised (set) then upon return
     93   // *praised = INVALID_EXCEPTION | INEXACT_EXCEPTION
     94   *praised = *pfpsf & (*pflagsmask & BID_IEEE_FLAGS);
     95 }
     96 #else
     97 _IDEC_flags
     98 testFlags (_IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
     99   _IDEC_flags raised;
    100   // the raturn value raised is the logical OR of the flags
    101   // selected by flagsmask, that are set; e.g. if
    102   // flagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION and
    103   // only the invalid and inexact flags are raised (set) then the return value
    104   // is raised = INVALID_EXCEPTION | INEXACT_EXCEPTION
    105   raised = *pfpsf & (flagsmask & BID_IEEE_FLAGS);
    106   return (raised);
    107 }
    108 #endif
    109 
    110 #if DECIMAL_CALL_BY_REFERENCE
    111 void
    112 testSavedFlags (_IDEC_flags * praised, _IDEC_flags * psavedflags,
    113 		_IDEC_flags * pflagsmask) {
    114   // *praised is a pointer to the result, i.e. the logical OR of the flags
    115   // selected by *pflagsmask that are set in *psavedflags; e.g. if
    116   // *pflagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
    117   // and only the invalid and inexact flags are raised (set) in *psavedflags
    118   // then upon return *praised = INVALID_EXCEPTION | INEXACT_EXCEPTION
    119   // Note that the flags could be saved in a global variable, but this function
    120   // would still expect that value as an argument passed by reference
    121   *praised = *psavedflags & (*pflagsmask & BID_IEEE_FLAGS);
    122 }
    123 #else
    124 _IDEC_flags
    125 testSavedFlags (_IDEC_flags savedflags, _IDEC_flags flagsmask) {
    126   _IDEC_flags raised;
    127   // the raturn value raised is the logical OR of the flags
    128   // selected by flagsmask, that are set in savedflags; e.g. if
    129   // flagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION and
    130   // only the invalid and inexact flags are raised (set) in savedflags
    131   // then the return value is raised = INVALID_EXCEPTION | INEXACT_EXCEPTION
    132   // Note that the flags could be saved in a global variable, but this function
    133   // would still expect that value as an argument passed by value
    134   raised = savedflags & (flagsmask & BID_IEEE_FLAGS);
    135   return (raised);
    136 }
    137 #endif
    138 
    139 #if DECIMAL_CALL_BY_REFERENCE
    140 void
    141 restoreFlags (_IDEC_flags * pflagsvalues,
    142 	      _IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
    143   // restore the status flags selected by *pflagsmask to the values speciafied
    144   // (as a logical OR) in *pflagsvalues; e.g. if
    145   // *pflagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
    146   // and only the invalid and inexact flags are raised (set) in *pflagsvalues
    147   // then upon return the invalid status flag will be set, the underflow status
    148   // flag will be clear, and the inexact status flag will be set
    149   *pfpsf = *pfpsf & ~(*pflagsmask & BID_IEEE_FLAGS);
    150   // clear flags that have to be restored
    151   *pfpsf = *pfpsf | (*pflagsvalues & (*pflagsmask & BID_IEEE_FLAGS));
    152   // restore flags
    153 }
    154 #else
    155 void
    156 restoreFlags (_IDEC_flags flagsvalues,
    157 	      _IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
    158   // restore the status flags selected by flagsmask to the values speciafied
    159   // (as a logical OR) in flagsvalues; e.g. if
    160   // flagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
    161   // and only the invalid and inexact flags are raised (set) in flagsvalues
    162   // then upon return the invalid status flag will be set, the underflow status
    163   // flag will be clear, and the inexact status flag will be set
    164   *pfpsf = *pfpsf & ~(flagsmask & BID_IEEE_FLAGS);
    165   // clear flags that have to be restored
    166   *pfpsf = *pfpsf | (flagsvalues & (flagsmask & BID_IEEE_FLAGS));
    167   // restore flags
    168 }
    169 #endif
    170 
    171 #if DECIMAL_CALL_BY_REFERENCE
    172 void
    173 saveFlags (_IDEC_flags * pflagsvalues,
    174 	   _IDEC_flags * pflagsmask _EXC_FLAGS_PARAM) {
    175   // return in *pflagsvalues the status flags specified (as a logical OR) in
    176   // *pflagsmask; e.g. if
    177   // *pflagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
    178   // and only the invalid and inexact flags are raised (set) in the status word,
    179   // then upon return the value in *pflagsvalues will have the invalid status
    180   // flag set, the underflow status flag clear, and the inexact status flag set
    181   *pflagsvalues = *pfpsf & (*pflagsmask & BID_IEEE_FLAGS);
    182 }
    183 #else
    184 _IDEC_flags
    185 saveFlags (_IDEC_flags flagsmask _EXC_FLAGS_PARAM) {
    186   _IDEC_flags flagsvalues;
    187   // return the status flags specified (as a logical OR) in flagsmask; e.g. if
    188   // flagsmask = INVALID_EXCEPTION | UNDERFLOW_EXCEPTION | INEXACT_EXCEPTION
    189   // and only the invalid and inexact flags are raised (set) in the status word,
    190   // then the return value will have the invalid status  flag set, the
    191   // underflow status flag clear, and the inexact status flag set
    192   flagsvalues = *pfpsf & (flagsmask & BID_IEEE_FLAGS);
    193   return (flagsvalues);
    194 }
    195 #endif
    196 
    197 // Note the following definitions from bid_conf.h (rearranged): if the rounding
    198 // mode is global, it has a fixed name recognized by the library functions:
    199 // _IDEC_glbround; rnd_mode, defined as &_IDEC_glbround, can be used instead; no
    200 // argument is passed for the rounding mode to the library functions; if the
    201 // rounding mode is local then it is passed as an arument, by reference or by
    202 // value, to the library functions
    203 //
    204 // #if DECIMAL_CALL_BY_REFERENCE
    205 //   #if !DECIMAL_GLOBAL_ROUNDING
    206 //     #define _RND_MODE_PARAM , _IDEC_round *prnd_mode
    207 //   #else
    208 //     #define _RND_MODE_PARAM
    209 //     #define rnd_mode _IDEC_glbround
    210 //   #endif
    211 // #else
    212 //   #if !DECIMAL_GLOBAL_ROUNDING
    213 //     #define _RND_MODE_PARAM , _IDEC_round rnd_mode
    214 //   #else
    215 //     #define _RND_MODE_PARAM
    216 //     #define rnd_mode _IDEC_glbround
    217 //   #endif
    218 // #endif
    219 
    220 #if DECIMAL_CALL_BY_REFERENCE
    221 #if !DECIMAL_GLOBAL_ROUNDING
    222     // #define _RND_MODE_PARAM , _IDEC_round *prnd_mode
    223 void
    224 getDecimalRoundingDirection (_IDEC_round * rounding_mode
    225 			     _RND_MODE_PARAM) {
    226   // returns the current rounding mode
    227   *rounding_mode = *prnd_mode;
    228 }
    229 #else
    230     // #define _RND_MODE_PARAM
    231     // #define rnd_mode _IDEC_glbround
    232 void
    233 getDecimalRoundingDirection (_IDEC_round * rounding_mode
    234 			     _RND_MODE_PARAM) {
    235   // returns the current rounding mode
    236   *rounding_mode = rnd_mode;
    237 }
    238 #endif
    239 #else
    240 #if !DECIMAL_GLOBAL_ROUNDING
    241     // #define _RND_MODE_PARAM , _IDEC_round rnd_mode
    242 _IDEC_round
    243 getDecimalRoundingDirection (_IDEC_round rnd_mode) {
    244   // returns the current rounding mode
    245   return (rnd_mode);
    246 }
    247 #else
    248     // #define _RND_MODE_PARAM
    249     // #define rnd_mode _IDEC_glbround
    250 _IDEC_round
    251 getDecimalRoundingDirection (void) {
    252   // returns the current rounding mode
    253   return (rnd_mode);
    254 }
    255 #endif
    256 #endif
    257 
    258 #if DECIMAL_CALL_BY_REFERENCE
    259 #if !DECIMAL_GLOBAL_ROUNDING
    260     // #define _RND_MODE_PARAM , _IDEC_round *prnd_mode
    261 void
    262 setDecimalRoundingDirection (_IDEC_round * rounding_mode
    263 			     _RND_MODE_PARAM) {
    264   // sets the current rounding mode to the value in *rounding_mode, if valid
    265   if (*rounding_mode == ROUNDING_TO_NEAREST ||
    266       *rounding_mode == ROUNDING_DOWN ||
    267       *rounding_mode == ROUNDING_UP ||
    268       *rounding_mode == ROUNDING_TO_ZERO ||
    269       *rounding_mode == ROUNDING_TIES_AWAY) {
    270     *prnd_mode = *rounding_mode;
    271   }
    272 }
    273 #else
    274     // #define _RND_MODE_PARAM
    275     // #define rnd_mode _IDEC_glbround
    276 void
    277 setDecimalRoundingDirection (_IDEC_round * rounding_mode
    278 			     ) {
    279   // sets the global rounding mode to the value in *rounding_mode, if valid
    280   if (*rounding_mode == ROUNDING_TO_NEAREST ||
    281       *rounding_mode == ROUNDING_DOWN ||
    282       *rounding_mode == ROUNDING_UP ||
    283       *rounding_mode == ROUNDING_TO_ZERO ||
    284       *rounding_mode == ROUNDING_TIES_AWAY) {
    285     rnd_mode = *rounding_mode;
    286   }
    287 }
    288 #endif
    289 #else
    290 #if !DECIMAL_GLOBAL_ROUNDING
    291     // #define _RND_MODE_PARAM , _IDEC_round rnd_mode
    292 _IDEC_round
    293 setDecimalRoundingDirection (_IDEC_round rounding_mode _RND_MODE_PARAM) {
    294   // sets the current rounding mode to the value in rounding_mode;
    295   // however, when arguments are passed by value and the rounding mode
    296   // is a local variable, this is not of any use
    297   if (rounding_mode == ROUNDING_TO_NEAREST ||
    298       rounding_mode == ROUNDING_DOWN ||
    299       rounding_mode == ROUNDING_UP ||
    300       rounding_mode == ROUNDING_TO_ZERO ||
    301       rounding_mode == ROUNDING_TIES_AWAY) {
    302     return (rounding_mode);
    303   }
    304   return (rnd_mode);
    305 }
    306 #else
    307     // #define _RND_MODE_PARAM
    308     // #define rnd_mode _IDEC_glbround
    309 void
    310 setDecimalRoundingDirection (_IDEC_round rounding_mode) {
    311   // sets the current rounding mode to the value in rounding_mode, if valid;
    312   if (rounding_mode == ROUNDING_TO_NEAREST ||
    313       rounding_mode == ROUNDING_DOWN ||
    314       rounding_mode == ROUNDING_UP ||
    315       rounding_mode == ROUNDING_TO_ZERO ||
    316       rounding_mode == ROUNDING_TIES_AWAY) {
    317     rnd_mode = rounding_mode;
    318   }
    319 }
    320 #endif
    321 #endif
    322 
    323 #if DECIMAL_CALL_BY_REFERENCE
    324 void
    325 is754 (int *retval) {
    326   *retval = 0;
    327 }
    328 #else
    329 int
    330 is754 (void) {
    331   return 0;
    332 }
    333 #endif
    334 
    335 #if DECIMAL_CALL_BY_REFERENCE
    336 void
    337 is754R (int *retval) {
    338   *retval = 1;
    339 }
    340 #else
    341 int
    342 is754R (void) {
    343   return 1;
    344 }
    345 #endif
    346