(root)/
gcc-13.2.0/
libgcc/
config/
libbid/
bid_flag_operations.c
       1  /* Copyright (C) 2007-2023 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