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 * Portable Cray floating-point addition/subtraction emulation 00038 */ 00039 00040 #include "arith.internal.h" 00041 00042 00043 int 00044 ar_cfadd64 (AR_CRAY_64 *x, 00045 const AR_CRAY_64 *a, 00046 const AR_CRAY_64 *b) { 00047 00048 int res = AR_STAT_OK, a_expo = a->expo, b_expo = b->expo; 00049 unsigned int carry, shift, inexact; 00050 AR_CRAY_64 y; 00051 00052 /* Ensure that the first argument has the largest exponent */ 00053 if (b_expo > a_expo) 00054 y = *a, *x = *b; 00055 else 00056 y = *b, *x = *a; 00057 00058 /* Test for underflow */ 00059 if (x->expo < AR_CRAY_MIN_EXPO) { 00060 ZEROCRAY64 (*x); 00061 return AR_STAT_UNDERFLOW | AR_STAT_ZERO; 00062 } 00063 00064 /* Shift the coefficient of the second argument down (right). We 00065 * do this in parts so as not to overflow registers. 00066 */ 00067 inexact = 0; 00068 shift = x->expo - y.expo; 00069 if (shift > AR_CRAY64_COEFF_BITS) 00070 ZEROCRAY64 (y); 00071 else { 00072 for (; shift; shift--) { 00073 inexact |= y.coeff2 & 1; 00074 SHRIGHTCRAY64 (y); 00075 y.expo++; 00076 } 00077 } 00078 00079 /* If signs differ, complement the first argument; this is equivalent 00080 * to negating and then subtracting one, in a two's complement sense. 00081 */ 00082 if (x->sign != y.sign) 00083 NOTCRAY64 (*x); 00084 00085 /* Compute sum of coefficients */ 00086 carry = 0; 00087 ADDCRAY64 (*x, carry, *x, y); 00088 00089 /* Check if the sign changed, and add 1 if so; otherwise, undo 00090 * the complement. 00091 */ 00092 if (x->sign != y.sign) 00093 if (carry) { 00094 x->sign ^= 1; 00095 carry = 1; 00096 INCCRAY64 (*x, carry); 00097 carry = 0; 00098 } else 00099 NOTCRAY64 (*x); 00100 00101 if (carry) { 00102 SHRIGHTCRAY64 (*x); 00103 x->coeff0 |= 1 << (AR_CRAY_C0_BITS - 1); 00104 x->expo++; 00105 } 00106 00107 /* Check for a zero result, as a special case */ 00108 if (!(x->coeff0 | x->coeff1 | x->coeff2)) { 00109 x->sign = x->expo = 0; 00110 return AR_STAT_ZERO; 00111 } 00112 00113 /* Shift the result coefficient left until normalized */ 00114 while (!(x->coeff0 >> (AR_CRAY_C0_BITS - 1))) { 00115 x->expo--; 00116 SHLEFTCRAY64 (*x); 00117 } 00118 00119 /* Test for out-of-range result or operand */ 00120 if (x->expo > AR_CRAY_MAX_EXPO || 00121 a_expo > AR_CRAY_MAX_EXPO || 00122 b_expo > AR_CRAY_MAX_EXPO) { 00123 x->sign = 0; 00124 x->expo = AR_CRAY_MAX_EXPO + 1; 00125 res |= AR_STAT_OVERFLOW; 00126 } 00127 00128 if (inexact) 00129 res |= AR_STAT_INEXACT; 00130 if (x->sign) 00131 res |= AR_STAT_NEGATIVE; 00132 00133 return res; 00134 } 00135 00136 00137 int 00138 ar_cfsub64 (AR_CRAY_64 *x, 00139 const AR_CRAY_64 *a, 00140 const AR_CRAY_64 *b) { 00141 00142 AR_CRAY_64 nb = *b; 00143 00144 nb.sign ^= 1; 00145 return ar_cfadd64 (x, a, &nb); 00146 } 00147 00148 00149 int 00150 ar_cfadd128 (AR_CRAY_128 *x, 00151 const AR_CRAY_128 *a, 00152 const AR_CRAY_128 *b) { 00153 00154 int res = AR_STAT_OK, x_expo; 00155 long carry, shift, inexact; 00156 AR_CRAY_128 y; 00157 00158 x->zero = 0; 00159 00160 /* Ensure that the first argument has the largest absolute value 00161 * (assuming normalized inputs) 00162 */ 00163 if (b->expo > a->expo || 00164 b->expo == a->expo && 00165 (b->coeff0 > a->coeff0 || 00166 b->coeff0 == a->coeff0 && 00167 (b->coeff1 > a->coeff1 || 00168 b->coeff1 == a->coeff1 && 00169 (b->coeff2 > a->coeff2 || 00170 b->coeff2 == a->coeff2 && 00171 (b->coeff3 > a->coeff3 || 00172 b->coeff3 == a->coeff3 && 00173 (b->coeff4 > a->coeff4 || 00174 b->coeff4 == a->coeff4 && 00175 b->coeff5 > a->coeff5)))))) 00176 y = *a, *x = *b; 00177 else 00178 y = *b, *x = *a; 00179 00180 if ((x_expo = x->expo) > AR_CRAY_MAX_EXPO) { 00181 ZEROCRAY128 (*x); 00182 x->expo = AR_CRAY_MAX_EXPO + 1; 00183 x->coeff0 = 1 << (AR_CRAY_C0_BITS - 1); 00184 return AR_STAT_OVERFLOW; 00185 } 00186 00187 /* Shift the coefficient of the second argument down (right) */ 00188 inexact = 0; 00189 shift = x_expo - y.expo; 00190 if (shift > AR_CRAY128_COEFF_BITS) 00191 ZEROCRAY128 (y); 00192 else 00193 for (; shift; shift--) { 00194 inexact |= y.coeff5 & 1; 00195 SHRIGHTCRAY128 (y); 00196 y.expo++; 00197 } 00198 00199 /* If signs differ, negate the second argument in two's complement. */ 00200 if (x->sign != y.sign) { 00201 NOTCRAY128 (y); 00202 carry = 1; 00203 } else 00204 carry = 0; 00205 00206 /* Compute sum of coefficients */ 00207 ADDCRAY128 (*x, carry, *x, y); 00208 00209 /* Handle a carry out of the upper bit */ 00210 if (x->sign != y.sign) 00211 carry--; 00212 00213 if (carry < 0) { 00214 00215 /* Bug reproduction from a negative shift count resulting 00216 * from an unnormalized argument in a subtraction. 00217 */ 00218 x_expo += 16; 00219 x->coeff0 = x->coeff1 = x->coeff2 = 00220 x->coeff3 = x->coeff4 = x->coeff5 = 0; 00221 00222 } else if (carry > 0) { 00223 00224 /* Handle carry out of coefficient */ 00225 if (carry > 0) { 00226 SHRIGHTCRAY128 (*x); 00227 x->coeff0 |= 1 << (AR_CRAY_C0_BITS - 1); 00228 x_expo++; 00229 } 00230 00231 } else if (x->coeff0 | x->coeff1 | x->coeff2 | 00232 x->coeff3 | x->coeff4 | x->coeff5) { 00233 00234 /* Shift the nonzero result coefficient left until normalized */ 00235 while (!(x->coeff0 >> (AR_CRAY_C0_BITS - 1))) { 00236 x_expo--; 00237 SHLEFTCRAY128 (*x); 00238 } 00239 00240 } else if (x_expo >= AR_CRAY_MIN_EXPO && x_expo <= AR_CRAY_MAX_EXPO) { 00241 00242 /* Zero result */ 00243 x->sign = 0; 00244 x_expo = 0; 00245 res |= AR_STAT_ZERO; 00246 } 00247 00248 /* Test for out-of-range result or operand, as well as an 00249 * underflowed result. 00250 */ 00251 if (x_expo > AR_CRAY_MAX_EXPO) { 00252 ZEROCRAY128 (*x); 00253 x->expo = AR_CRAY_MAX_EXPO + 1; 00254 x->coeff0 = 1 << (AR_CRAY_C0_BITS - 1); 00255 res |= AR_STAT_OVERFLOW; 00256 } else if (x_expo < AR_CRAY_MIN_EXPO) { 00257 ZEROCRAY128 (*x); 00258 res |= AR_STAT_UNDERFLOW | AR_STAT_ZERO; 00259 } else 00260 x->expo = x_expo; 00261 00262 if (inexact) 00263 res |= AR_STAT_INEXACT; 00264 if (x->sign) 00265 res |= AR_STAT_NEGATIVE; 00266 00267 return res; 00268 } 00269 00270 00271 int 00272 ar_cfsub128 (AR_CRAY_128 *x, 00273 const AR_CRAY_128 *a, 00274 const AR_CRAY_128 *b) { 00275 00276 AR_CRAY_128 nb = *b; 00277 00278 nb.sign ^= 1; 00279 return ar_cfadd128 (x, a, &nb); 00280 } 00281 00282 00283 static char USMID [] = "\n%Z%%M% %I% %G% %U%\n"; 00284 static char rcsid [] = "$Id: cray_fadd.c,v 1.1.1.1 2002-05-22 20:06:18 dsystem Exp $";