1 /* Copyright (C) 2007, 2009 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