Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* 00037 * Common IEEE 754 normalization routines 00038 */ 00039 00040 #include "arith.internal.h" 00041 00042 00043 /* Normalization, rounding, and final processing common to all IEEE 00044 * arithmetic 00045 */ 00046 00047 int 00048 ar_i32norm (signed int expo, /* exponent */ 00049 unsigned long lbits, /* left-hand bits */ 00050 unsigned long rbits, /* right-hand rounding bits */ 00051 AR_IEEE_32 *x, /* result to package; coeff and sign */ 00052 int roundmode) { /* IEEE rounding mode */ 00053 00054 int res = AR_STAT_OK; 00055 unsigned long carry; 00056 00057 if (x->sign) 00058 res |= AR_STAT_NEGATIVE; 00059 00060 /* Zero means zero */ 00061 if (!(lbits | x->coeff0 | x->coeff1 | rbits)) { 00062 x->expo = 0; 00063 return res | AR_STAT_ZERO; 00064 } 00065 00066 /* Normalize if necessary; preserve "sticky" rounding bit */ 00067 while (expo > 1 && !lbits) { 00068 lbits = x->coeff0 >> (AR_IEEE32_C0_BITS - 1); 00069 SHLEFTIEEE32 (*x); 00070 x->coeff1 |= rbits >> (AR_IEEE32_ROUND_BITS - 1); 00071 rbits = (rbits << 1) & MASKR (AR_IEEE32_ROUND_BITS) | rbits & 1; 00072 expo--; 00073 } 00074 if (expo == 1 && !lbits) 00075 expo = 0; 00076 else if (!expo && lbits) 00077 expo = 1; 00078 00079 /* Shift right if carry; keep the sticky bit */ 00080 while (lbits > 1 || expo < 0) { 00081 rbits = (rbits >> 1) | 00082 rbits & 1 | 00083 ((x->coeff1 & 1) << (AR_IEEE32_ROUND_BITS - 1)); 00084 SHRIGHTIEEE32 (*x); 00085 x->coeff0 |= lbits << (AR_IEEE32_C0_BITS - 1); 00086 lbits >>= 1; 00087 expo++; 00088 } 00089 00090 /* Rounding decision */ 00091 switch (roundmode) { 00092 case AR_ROUND_PLUS_INFINITY: 00093 if (!rbits == !x->sign) 00094 goto noround; 00095 break; 00096 case AR_ROUND_MINUS_INFINITY: 00097 if (!rbits != !x->sign) 00098 goto noround; 00099 break; 00100 case AR_ROUND_ZERO: 00101 goto noround; 00102 default: 00103 if (!(rbits >> (AR_IEEE32_ROUND_BITS - 1))) 00104 goto noround; 00105 if (!(rbits & MASKR (AR_IEEE32_ROUND_BITS - 1)) && 00106 !(x->coeff1 & 1)) 00107 goto noround; 00108 break; 00109 } 00110 00111 /* Round up the coefficient */ 00112 carry = 1; 00113 INCIEEE32 (*x, carry); 00114 lbits += carry; 00115 00116 noround: 00117 00118 /* Shift right if necessary */ 00119 if (lbits > 1) { 00120 rbits = (rbits >> 1) | 00121 ((x->coeff1 & 1) << (AR_IEEE32_ROUND_BITS - 1)); 00122 SHRIGHTIEEE32 (*x); 00123 x->coeff0 |= lbits << (AR_IEEE32_C0_BITS - 1); 00124 lbits >>= 1; 00125 expo++; 00126 } 00127 else if (lbits) { 00128 if (!expo) 00129 expo = 1; 00130 } 00131 else 00132 expo = 0; 00133 00134 if (!(lbits | x->coeff0 | x->coeff1)) { 00135 expo = 0; 00136 res |= AR_STAT_ZERO | AR_STAT_UNDERFLOW; 00137 } 00138 00139 /* Test for out-of-range result; turn into (signed) infinity */ 00140 if (expo > AR_IEEE32_MAX_EXPO) { 00141 x->expo = AR_IEEE32_MAX_EXPO + 1; 00142 x->coeff0 = x->coeff1 = 0; 00143 return res | AR_STAT_OVERFLOW; 00144 } 00145 00146 /* Test for inexact */ 00147 if (rbits) { 00148 res |= AR_STAT_INEXACT; 00149 } 00150 00151 x->expo = expo; 00152 00153 if (!expo && 00154 ar_state_register.ar_underflow_mode != AR_UNDERFLOW_TO_DENORM) { 00155 /* don't want denorms; convert to zero */ 00156 if (x->coeff0 | x->coeff1) { 00157 /* got a denorm */ 00158 x->coeff0 = x->coeff1 = 0; 00159 if (ar_state_register.ar_underflow_mode == 00160 AR_UNDERFLOW_TO_PLUS_ZERO) 00161 x->sign = 0; 00162 else if (ar_state_register.ar_underflow_mode == 00163 AR_UNDERFLOW_TO_SIGNED_TINY) 00164 x->expo = AR_IEEE64_MIN_EXPO+1; 00165 return res | AR_STAT_ZERO | AR_STAT_UNDERFLOW; 00166 } 00167 } 00168 00169 return res; 00170 } 00171 00172 00173 int 00174 ar_i64norm (signed int expo, /* exponent */ 00175 unsigned long lbits, /* left-hand bits */ 00176 unsigned long rbits, /* right-hand rounding bits */ 00177 AR_IEEE_64 *x, /* result to package; coeff and sign */ 00178 int roundmode) { /* IEEE rounding mode */ 00179 00180 int res = AR_STAT_OK; 00181 unsigned long carry; 00182 00183 if (x->sign) 00184 res |= AR_STAT_NEGATIVE; 00185 00186 /* Zero means zero */ 00187 if (!(lbits | x->coeff0 | x->coeff1 | x->coeff2 | x->coeff3 | rbits)) { 00188 x->expo = 0; 00189 return res | AR_STAT_ZERO; 00190 } 00191 00192 /* Normalize if necessary; preserve "sticky" rounding bit */ 00193 while (expo > 1 && !lbits) { 00194 lbits = x->coeff0 >> (AR_IEEE64_C0_BITS - 1); 00195 SHLEFTIEEE64 (*x); 00196 x->coeff3 |= rbits >> (AR_IEEE64_ROUND_BITS - 1); 00197 rbits = (rbits << 1) & MASKR (AR_IEEE64_ROUND_BITS) | rbits & 1; 00198 expo--; 00199 } 00200 if (expo == 1 && !lbits) 00201 expo = 0; 00202 else if (!expo && lbits) 00203 expo = 1; 00204 00205 /* Shift right if carry; keep the sticky bit */ 00206 while (lbits > 1 || expo < 0) { 00207 rbits = (rbits >> 1) | 00208 rbits & 1 | 00209 ((x->coeff3 & 1) << (AR_IEEE64_ROUND_BITS - 1)); 00210 SHRIGHTIEEE64 (*x); 00211 x->coeff0 |= lbits << (AR_IEEE64_C0_BITS - 1); 00212 lbits >>= 1; 00213 expo++; 00214 } 00215 00216 /* Rounding decision */ 00217 switch (roundmode) { 00218 case AR_ROUND_PLUS_INFINITY: 00219 if (!rbits == !x->sign) 00220 goto noround; 00221 break; 00222 case AR_ROUND_MINUS_INFINITY: 00223 if (!rbits != !x->sign) 00224 goto noround; 00225 break; 00226 case AR_ROUND_ZERO: 00227 goto noround; 00228 default: 00229 if (!(rbits >> (AR_IEEE64_ROUND_BITS - 1))) 00230 goto noround; 00231 if (!(rbits & MASKR (AR_IEEE64_ROUND_BITS - 1)) && 00232 !(x->coeff3 & 1)) 00233 goto noround; 00234 break; 00235 } 00236 00237 /* Round up the coefficient */ 00238 carry = 1; 00239 INCIEEE64 (*x, carry); 00240 lbits += carry; 00241 00242 noround: 00243 00244 /* Shift right if necessary */ 00245 if (lbits > 1) { 00246 rbits = (rbits >> 1) | 00247 ((x->coeff3 & 1) << (AR_IEEE64_ROUND_BITS - 1)); 00248 SHRIGHTIEEE64 (*x); 00249 x->coeff0 |= lbits << (AR_IEEE64_C0_BITS - 1); 00250 lbits >>= 1; 00251 expo++; 00252 } 00253 else if (lbits) { 00254 if (!expo) 00255 expo = 1; 00256 } 00257 else 00258 expo = 0; 00259 00260 if (!(lbits | x->coeff0 | x->coeff1 | x->coeff2 | x->coeff3)) { 00261 expo = 0; 00262 res |= AR_STAT_ZERO | AR_STAT_UNDERFLOW; 00263 } 00264 00265 /* Test for out-of-range result; turn into (signed) infinity */ 00266 if (expo > AR_IEEE64_MAX_EXPO) { 00267 x->expo = AR_IEEE64_MAX_EXPO + 1; 00268 x->coeff0 = x->coeff1 = x->coeff2 = x->coeff3 = 0; 00269 return res | AR_STAT_OVERFLOW; 00270 } 00271 00272 /* Test for inexact */ 00273 if (rbits) { 00274 res |= AR_STAT_INEXACT; 00275 } 00276 00277 x->expo = expo; 00278 00279 if (!expo && 00280 ar_state_register.ar_underflow_mode != AR_UNDERFLOW_TO_DENORM) { 00281 /* don't want denorms; convert to zero */ 00282 if (x->coeff0 | x->coeff1 | x->coeff2 | x->coeff3) { 00283 /* got a denorm */ 00284 x->coeff0 = x->coeff1 = x->coeff2 = x->coeff3 = 0; 00285 if (ar_state_register.ar_underflow_mode == 00286 AR_UNDERFLOW_TO_PLUS_ZERO) 00287 x->sign = 0; 00288 else if (ar_state_register.ar_underflow_mode == 00289 AR_UNDERFLOW_TO_SIGNED_TINY) 00290 x->expo = AR_IEEE64_MIN_EXPO+1; 00291 return res | AR_STAT_ZERO | AR_STAT_UNDERFLOW; 00292 } 00293 } 00294 00295 return res; 00296 } 00297 00298 00299 int 00300 ar_i128norm(signed int expo, /* exponent */ 00301 unsigned long lbits, /* left-hand bits */ 00302 unsigned long rbits, /* right-hand rounding bits */ 00303 AR_IEEE_128 *x, /* result to package; coeff and sign */ 00304 int roundmode) { /* IEEE rounding mode */ 00305 00306 int res = AR_STAT_OK; 00307 unsigned long carry; 00308 00309 if (x->sign) 00310 res |= AR_STAT_NEGATIVE; 00311 00312 /* Zero means zero */ 00313 if (!(lbits | x->coeff0 | x->coeff1 | x->coeff2 | x->coeff3 | 00314 x->coeff4 | x->coeff5 | x->coeff6 | rbits)) { 00315 x->expo = 0; 00316 return res | AR_STAT_ZERO; 00317 } 00318 00319 /* Normalize if necessary; preserve "sticky" rounding bit */ 00320 while (expo > 1 && !lbits) { 00321 lbits = x->coeff0 >> (AR_IEEE128_C0_BITS - 1); 00322 SHLEFTIEEE128 (*x); 00323 x->coeff6 |= rbits >> (AR_IEEE128_ROUND_BITS - 1); 00324 rbits = (rbits << 1) & MASKR (AR_IEEE128_ROUND_BITS) | rbits & 1; 00325 expo--; 00326 } 00327 if (expo == 1 && !lbits) 00328 expo = 0; 00329 else if (!expo && lbits) 00330 expo = 1; 00331 00332 /* Shift right if carry; keep the sticky bit */ 00333 while (lbits > 1 || expo < 0) { 00334 rbits = (rbits >> 1) | 00335 rbits & 1 | 00336 ((x->coeff6 & 1) << (AR_IEEE128_ROUND_BITS - 1)); 00337 SHRIGHTIEEE128 (*x); 00338 x->coeff0 |= lbits << (AR_IEEE128_C0_BITS - 1); 00339 lbits >>= 1; 00340 expo++; 00341 } 00342 00343 /* Rounding decision */ 00344 switch (roundmode) { 00345 case AR_ROUND_PLUS_INFINITY: 00346 if (!rbits == !x->sign) 00347 goto noround; 00348 break; 00349 case AR_ROUND_MINUS_INFINITY: 00350 if (!rbits != !x->sign) 00351 goto noround; 00352 break; 00353 case AR_ROUND_ZERO: 00354 goto noround; 00355 default: 00356 if (!(rbits >> (AR_IEEE128_ROUND_BITS - 1))) 00357 goto noround; 00358 if (!(rbits & MASKR (AR_IEEE128_ROUND_BITS - 1)) && 00359 !(x->coeff6 & 1)) 00360 goto noround; 00361 break; 00362 } 00363 00364 /* Round up the coefficient */ 00365 carry = 1; 00366 INCIEEE128 (*x, carry); 00367 lbits += carry; 00368 00369 noround: 00370 00371 /* Shift right if necessary */ 00372 if (lbits > 1) { 00373 rbits = (rbits >> 1) | 00374 ((x->coeff6 & 1) << (AR_IEEE128_ROUND_BITS - 1)); 00375 SHRIGHTIEEE128 (*x); 00376 x->coeff0 |= lbits << (AR_IEEE128_C0_BITS - 1); 00377 lbits >>= 1; 00378 expo++; 00379 } 00380 else if (lbits) { 00381 if (!expo) 00382 expo = 1; 00383 } 00384 else 00385 expo = 0; 00386 00387 if (!(lbits | x->coeff0 | x->coeff1 | x->coeff2 | x->coeff3 | 00388 x->coeff4 | x->coeff5 | x->coeff6)) { 00389 expo = 0; 00390 res |= AR_STAT_ZERO | AR_STAT_UNDERFLOW; 00391 } 00392 00393 /* Test for out-of-range result; turn into (signed) infinity */ 00394 if (expo > AR_IEEE128_MAX_EXPO) { 00395 x->expo = AR_IEEE128_MAX_EXPO + 1; 00396 x->coeff0 = x->coeff1 = x->coeff2 = x->coeff3 = 00397 x->coeff4 = x->coeff5 = x->coeff6 = 0; 00398 return res | AR_STAT_OVERFLOW; 00399 } 00400 00401 /* Test for inexact */ 00402 if (rbits) { 00403 res |= AR_STAT_INEXACT; 00404 } 00405 00406 x->expo = expo; 00407 00408 if (!expo && 00409 ar_state_register.ar_underflow_mode != AR_UNDERFLOW_TO_DENORM) { 00410 /* don't want denorms; convert to zero */ 00411 if (x->coeff0 | x->coeff1 | x->coeff2 | x->coeff3 | 00412 x->coeff4 | x->coeff5 | x->coeff6) { 00413 /* got a denorm */ 00414 x->coeff0 = x->coeff1 = x->coeff2 = x->coeff3 = 00415 x->coeff4 = x->coeff5 = x->coeff6 = 0; 00416 if (ar_state_register.ar_underflow_mode == 00417 AR_UNDERFLOW_TO_PLUS_ZERO) 00418 x->sign = 0; 00419 else if (ar_state_register.ar_underflow_mode == 00420 AR_UNDERFLOW_TO_SIGNED_TINY) 00421 x->expo = AR_IEEE128_MIN_EXPO+1; 00422 return res | AR_STAT_ZERO | AR_STAT_UNDERFLOW; 00423 } 00424 } 00425 00426 return res; 00427 } 00428 00429 00430 static char USMID [] = "\n%Z%%M% %I% %G% %U%\n"; 00431 static char rcsid [] = "$Id: ieee_norm.c,v 1.1.1.1 2002-05-22 20:06:19 dsystem Exp $"; 00432