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 * ======================================================================= 00038 * 00039 * 00040 * ======================================================================= 00041 * ======================================================================= 00042 */ 00043 00044 00045 00046 #include "quad.h" 00047 #include "stdio.h" 00048 #include "stdlib.h" 00049 #include "math.h" 00050 #include <fp_class.h> 00051 #include "defs.h" 00052 #include "quadsim.h" 00053 00054 /* For fp_class */ 00055 00056 #define DMANTWIDTH 52 00057 #define DEXPWIDTH 11 00058 #define DSIGNMASK 0x7fffffffffffffffll 00059 #define DEXPMASK 0x800fffffffffffffll 00060 #define DQNANBITMASK 0xfff7ffffffffffffll 00061 00062 #define MANTWIDTH 23 00063 #define EXPWIDTH 8 00064 #define SIGNMASK 0x7fffffff 00065 #define EXPMASK 0x807fffff 00066 #define QNANBITMASK 0xffbfffff 00067 00068 typedef union 00069 { 00070 struct 00071 { 00072 UINT32 hi; 00073 UINT32 lo; 00074 } word; 00075 00076 double d; 00077 } du; 00078 00079 static const du m_twop31 = 00080 {0xc1e00000, 0x00000000}; 00081 00082 static const du twop31m1 = 00083 {0x41dfffff, 0xffc00000}; 00084 00085 static const du twop32m1 = 00086 {0x41efffff, 0xffe00000}; 00087 00088 static const du twop52 = 00089 {0x43300000, 0x00000000}; 00090 00091 static const du twop62 = 00092 {0x43d00000, 0x00000000}; 00093 00094 static const du m_twop63 = 00095 {0xc3e00000, 0x00000000}; 00096 00097 static const du twop63 = 00098 {0x43e00000, 0x00000000}; 00099 00100 static const du twop64 = 00101 {0x43f00000, 0x00000000}; 00102 00103 static const du twopm916 = 00104 {0x06b00000, 0x00000000}; 00105 00106 /* Note: the name 'infinity' may conflict with <math.h> */ 00107 static const du myinfinity = 00108 {0x7ff00000, 0x00000000}; 00109 00110 extern INT c_q_le(QUAD x, QUAD y, INT *p_err ); 00111 extern INT c_q_ge(QUAD x, QUAD y, INT *p_err ); 00112 extern INT32 c_ji_qint(QUAD x, INT *p_err ); 00113 extern INT32 c_fp_class_q(QUAD x); 00114 extern UINT32 c_ji_quint(QUAD x, INT *p_err ); 00115 extern INT64 c_ki_qint(QUAD x, INT *p_err ); 00116 extern UINT64 c_ki_quint(QUAD x, INT *p_err ); 00117 extern float c_sngl_q(QUAD x, INT *p_err ); 00118 extern double c_dble_q(QUAD x, INT *p_err ); 00119 extern QUAD c_q_flotj(INT32 n, INT *p_err ); 00120 extern QUAD c_q_flotju(UINT32 n, INT *p_err ); 00121 extern QUAD c_q_flotk(INT64 n, INT *p_err ); 00122 extern QUAD c_q_flotku(UINT64 n, INT *p_err ); 00123 extern QUAD c_q_ext( float x, INT *p_err ); 00124 extern QUAD c_q_extd(double x, INT *p_err ); 00125 extern QUAD c_q_trunc(QUAD x, INT *p_err ); 00126 extern double trunc(double x); 00127 00128 #if defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__) 00129 00130 #define c_q_trunc __c_q_trunc 00131 #define c_q_ge __c_q_ge 00132 #define c_ki_qint __c_ki_qint 00133 #define c_q_le __c_q_le 00134 00135 #endif 00136 00137 /* quad to INT32 */ 00138 00139 #pragma weak c_ji_qint = __c_ji_qint 00140 #define c_ji_qint __c_ji_qint 00141 00142 INT32 00143 c_ji_qint(QUAD x, INT *p_err ) 00144 { 00145 QUAD xi; 00146 INT32 result; 00147 00148 *p_err = 0; 00149 00150 if ( x.hi != x.hi ) 00151 { 00152 *p_err = 1; 00153 00154 return ( (INT32)x.hi ); 00155 } 00156 00157 if ( fabs(x.hi) == myinfinity.d ) 00158 { 00159 *p_err = 1; 00160 00161 return ( (INT32)x.hi ); 00162 } 00163 00164 xi = c_q_trunc(x, p_err); 00165 00166 if ( xi.hi > twop31m1.d ) 00167 *p_err = 1; 00168 00169 if ( xi.hi < m_twop31.d ) 00170 *p_err = 1; 00171 00172 result = (INT32)xi.hi; 00173 00174 return ( result ); 00175 } 00176 00177 /* quad to UINT32 */ 00178 00179 #pragma weak c_ji_quint = __c_ji_quint 00180 #define c_ji_quint __c_ji_quint 00181 00182 UINT32 00183 c_ji_quint(QUAD x, INT *p_err ) 00184 { 00185 QUAD xi; 00186 INT64 n; 00187 UINT32 result; 00188 00189 *p_err = 0; 00190 00191 if ( x.hi != x.hi ) 00192 { 00193 *p_err = 1; 00194 00195 return ( (UINT32)x.hi ); 00196 } 00197 00198 if ( fabs(x.hi) == myinfinity.d ) 00199 { 00200 *p_err = 1; 00201 00202 return ( (UINT32)x.hi ); 00203 } 00204 00205 xi = c_q_trunc(x, p_err); 00206 00207 if ( xi.hi > twop32m1.d ) 00208 { 00209 *p_err = 1; 00210 00211 return ( (UINT32)x.hi ); 00212 } 00213 00214 if ( xi.hi < 0.0 ) 00215 { 00216 *p_err = 1; 00217 00218 return ( (UINT32)x.hi ); 00219 } 00220 00221 n = c_ki_qint(xi, p_err); 00222 00223 result = n & 0xffffffff; 00224 00225 return ( result ); 00226 } 00227 00228 /* quad to INT64 */ 00229 00230 #pragma weak c_ki_qint = __c_ki_qint 00231 #define c_ki_qint __c_ki_qint 00232 00233 INT64 00234 c_ki_qint(QUAD x, INT *p_err ) 00235 { 00236 QUAD xi; 00237 INT64 t; 00238 00239 *p_err = 0; 00240 00241 if ( x.hi != x.hi ) 00242 { 00243 *p_err = 1; 00244 00245 return ( (INT64)x.hi ); 00246 } 00247 00248 if ( fabs(x.hi) == myinfinity.d ) 00249 { 00250 *p_err = 1; 00251 00252 return ( (INT64)x.hi ); 00253 } 00254 00255 xi = c_q_trunc(x, p_err); 00256 00257 if ( (xi.hi > twop63.d) || 00258 ((xi.hi == twop63.d) && (xi.lo >= 0.0)) 00259 ) 00260 { 00261 /* we get overflow here, so just let the hardware do it */ 00262 00263 *p_err = 1; 00264 00265 return ( (INT64)xi.hi ); 00266 } 00267 00268 if ( (xi.hi < m_twop63.d) || 00269 ((xi.hi == m_twop63.d) && (xi.lo < 0.0)) 00270 ) 00271 { 00272 /* we get overflow here, so just let the hardware do it */ 00273 00274 if ( xi.hi == m_twop63.d ) 00275 { 00276 xi.hi *= 2.0; 00277 } 00278 00279 *p_err = 1; 00280 00281 return ( (INT64)xi.hi ); 00282 } 00283 00284 if ( fabs(xi.hi) > twop62.d ) 00285 { 00286 /* add things up very carefully to avoid overflow */ 00287 00288 t = 0.5*xi.hi; 00289 return ( ((INT64)xi.lo) + t + t ); 00290 } 00291 00292 /* just do it */ 00293 00294 return ( (INT64)xi.hi + (INT64)xi.lo ); 00295 } 00296 00297 /* quad to UINT64 */ 00298 00299 #pragma weak c_ki_quint = __c_ki_quint 00300 #define c_ki_quint __c_ki_quint 00301 00302 UINT64 00303 c_ki_quint(QUAD x, INT *p_err ) 00304 { 00305 QUAD xi; 00306 double z; 00307 UINT64 t; 00308 00309 *p_err = 0; 00310 00311 if ( x.hi != x.hi ) 00312 { 00313 *p_err = 1; 00314 00315 return ( (UINT64)x.hi ); 00316 } 00317 00318 if ( fabs(x.hi) == myinfinity.d ) 00319 { 00320 *p_err = 1; 00321 00322 return ( (UINT64)x.hi ); 00323 } 00324 00325 xi = c_q_trunc(x, p_err); 00326 00327 if ( (xi.hi > twop64.d) || 00328 ((xi.hi == twop64.d) && (xi.lo > -1.0)) 00329 ) 00330 { 00331 *p_err = 1; 00332 00333 return ( (UINT64)x.hi ); 00334 } 00335 00336 if ( xi.hi < 0.0 ) 00337 { 00338 *p_err = 1; 00339 00340 return ( (UINT64)x.hi ); 00341 } 00342 00343 if ( (xi.hi > twop63.d) || 00344 (xi.hi == twop63.d) && (xi.lo >= 0.0) 00345 ) 00346 { 00347 /* subtract 2**64 */ 00348 00349 z = xi.hi - twop64.d; 00350 00351 /* normalize result */ 00352 00353 xi.hi = z + xi.lo; 00354 xi.lo = z - xi.hi + xi.lo; 00355 } 00356 00357 if ( fabs(xi.hi) > twop62.d ) 00358 { 00359 /* add things up very carefully to avoid overflow */ 00360 00361 t = 0.5*xi.hi; 00362 return ( ((UINT64)xi.lo) + t + t ); 00363 } 00364 00365 /* just do it */ 00366 00367 return ( (UINT64)xi.hi + (UINT64)xi.lo ); 00368 } 00369 00370 /* quad to float */ 00371 00372 #pragma weak c_sngl_q = __c_sngl_q 00373 #define c_sngl_q __c_sngl_q 00374 00375 float 00376 c_sngl_q(QUAD x, INT *p_err ) 00377 { 00378 *p_err = 0; 00379 00380 return ( (float)x.hi ); 00381 } 00382 00383 /* quad to double */ 00384 00385 #pragma weak c_dble_q = __c_dble_q 00386 #define c_dble_q __c_dble_q 00387 00388 double 00389 c_dble_q(QUAD x, INT *p_err ) 00390 { 00391 *p_err = 0; 00392 00393 return ( x.hi ); 00394 } 00395 00396 /* INT32 to quad */ 00397 00398 #pragma weak c_q_flotj = __c_q_flotj 00399 #define c_q_flotj __c_q_flotj 00400 00401 QUAD 00402 c_q_flotj(INT32 n, INT *p_err ) 00403 { 00404 QUAD result; 00405 00406 *p_err = 0; 00407 00408 result.hi = n; 00409 result.lo = 0.0; 00410 return ( result ); 00411 } 00412 00413 /* UINT32 to quad */ 00414 00415 #pragma weak c_q_flotju = __c_q_flotju 00416 #define c_q_flotju __c_q_flotju 00417 00418 QUAD 00419 c_q_flotju(UINT32 n, INT *p_err ) 00420 { 00421 QUAD result; 00422 00423 *p_err = 0; 00424 00425 result.hi = n; 00426 result.lo = 0.0; 00427 return ( result ); 00428 } 00429 00430 /* INT64 to quad */ 00431 00432 #pragma weak c_q_flotk = __c_q_flotk 00433 #define c_q_flotk __c_q_flotk 00434 00435 QUAD 00436 c_q_flotk(INT64 n, INT *p_err ) 00437 { 00438 INT64 m; 00439 double w, ww; 00440 QUAD result; 00441 00442 *p_err = 0; 00443 00444 m = (n >> 11); 00445 m <<= 11; 00446 00447 w = m; 00448 00449 ww = n - m; 00450 00451 /* normalize result */ 00452 00453 result.hi = w + ww; 00454 result.lo = w - result.hi + ww; 00455 00456 return ( result ); 00457 } 00458 00459 /* UINT64 to QUAD */ 00460 00461 #pragma weak c_q_flotku = __c_q_flotku 00462 #define c_q_flotku __c_q_flotku 00463 00464 QUAD 00465 c_q_flotku(UINT64 n, INT *p_err ) 00466 { 00467 UINT64 m; 00468 double w, ww; 00469 QUAD result; 00470 00471 *p_err = 0; 00472 00473 m = (n >> 11); 00474 m <<= 11; 00475 00476 w = m; 00477 00478 ww = n - m; 00479 00480 /* normalize result */ 00481 00482 result.hi = w + ww; 00483 result.lo = w - result.hi + ww; 00484 00485 return ( result ); 00486 } 00487 00488 /* float to quad */ 00489 00490 #pragma weak c_q_ext = __c_q_ext 00491 #define c_q_ext __c_q_ext 00492 00493 QUAD 00494 c_q_ext( float x, INT *p_err ) 00495 { 00496 QUAD result; 00497 00498 *p_err = 0; 00499 00500 result.hi = x; 00501 result.lo = 0.0; 00502 return ( result ); 00503 } 00504 00505 /* double to quad */ 00506 00507 #pragma weak c_q_extd = __c_q_extd 00508 #define c_q_extd __c_q_extd 00509 00510 QUAD 00511 c_q_extd(double x, INT *p_err ) 00512 { 00513 QUAD result; 00514 00515 *p_err = 0; 00516 00517 result.hi = x; 00518 result.lo = 0.0; 00519 return ( result ); 00520 } 00521 00522 /* truncates a long double, i.e. computes the integral part of 00523 a long double 00524 */ 00525 00526 #pragma weak c_q_trunc = __c_q_trunc 00527 #define c_q_trunc __c_q_trunc 00528 00529 QUAD 00530 c_q_trunc(QUAD x, INT *p_err ) 00531 { 00532 double uhi, ulo; 00533 QUAD result; 00534 00535 uhi = x.hi; 00536 ulo = x.lo; 00537 00538 *p_err = 0; 00539 00540 if ( uhi != uhi ) 00541 { 00542 result.hi = uhi; 00543 result.lo = ulo; 00544 00545 return ( result ); 00546 } 00547 00548 if ( uhi >= 0.0 ) 00549 { 00550 if ( uhi < twop52.d ) 00551 { 00552 /* binary point occurs in uhi; truncate uhi to an integer 00553 */ 00554 00555 result.hi = trunc(uhi); 00556 00557 result.lo = 0.0; 00558 00559 if ( result.hi < uhi ) 00560 return ( result ); 00561 00562 /* must adjust result by one if ulo < 0.0 */ 00563 00564 if ( ulo < 0.0 ) 00565 { 00566 result.hi -= 1.0; 00567 00568 return ( result ); 00569 } 00570 00571 return ( result ); 00572 } 00573 else if ( fabs(ulo) < twop52.d ) 00574 { 00575 /* binary point occurs in ulo; truncate ulo to an integer 00576 */ 00577 00578 result.hi = uhi; 00579 00580 result.lo = trunc(ulo); 00581 00582 if ( result.lo > ulo ) 00583 { 00584 result.lo -= 1.0; 00585 } 00586 00587 return ( result ); 00588 } 00589 00590 /* arg is an integer */ 00591 00592 result.hi = uhi; 00593 result.lo = ulo; 00594 00595 return ( result ); 00596 } 00597 else 00598 { 00599 if ( fabs(uhi) < twop52.d ) 00600 { 00601 /* binary point occurs in uhi; truncate uhi to an integer 00602 */ 00603 00604 result.hi = trunc(uhi); 00605 00606 result.lo = 0.0; 00607 00608 if ( result.hi > uhi ) 00609 return ( result ); 00610 00611 /* must adjust result by one if ulo > 0.0 */ 00612 00613 if ( ulo > 0.0 ) 00614 { 00615 result.hi += 1.0; 00616 00617 return ( result ); 00618 } 00619 00620 return ( result ); 00621 } 00622 else if ( fabs(ulo) < twop52.d ) 00623 { 00624 /* binary point occurs in ulo; truncate ulo to an integer 00625 */ 00626 00627 result.hi = uhi; 00628 00629 result.lo = trunc(ulo); 00630 00631 if ( result.lo < ulo ) 00632 { 00633 result.lo += 1.0; 00634 } 00635 00636 return ( result ); 00637 } 00638 00639 /* arg is an integer */ 00640 00641 result.hi = uhi; 00642 result.lo = ulo; 00643 00644 return ( result ); 00645 } 00646 } 00647 00648 /* ==================================================================== 00649 * 00650 * FunctionName: c_fp_class_q 00651 * 00652 * Description: c_fp_class_q(u) returns the floating point class 00653 * to which u belongs, and should work equivalently to the 00654 * functions declared in <fp_class.h>. 00655 * 00656 * ==================================================================== 00657 */ 00658 00659 00660 #pragma weak c_fp_class_q = __c_fp_class_q 00661 #define c_fp_class_q __c_fp_class_q 00662 00663 INT 00664 fp_class_d( double x ) 00665 { 00666 UINT64 ll, exp, mantissa; 00667 INT32 sign; 00668 00669 ll = *(UINT64*)&x; 00670 exp = (ll >> DMANTWIDTH); 00671 sign = (exp >> DEXPWIDTH); 00672 exp &= 0x7ff; 00673 mantissa = (ll & (DSIGNMASK & DEXPMASK)); 00674 if ( exp == 0x7ff ) { 00675 /* result is an infinity, or a NaN */ 00676 if ( mantissa == 0 ) 00677 return ( (sign == 0) ? FP_POS_INF : FP_NEG_INF ); 00678 else if ( mantissa & ~DQNANBITMASK ) 00679 return ( FP_QNAN ); 00680 else 00681 return ( FP_SNAN ); 00682 } 00683 00684 if ( exp == 0 ) { 00685 if ( mantissa == 0 ) 00686 return ( (sign == 0) ? FP_POS_ZERO : FP_NEG_ZERO ); 00687 else 00688 return ( (sign == 0) ? FP_POS_DENORM : FP_NEG_DENORM ); 00689 } 00690 else 00691 return ( (sign == 0) ? FP_POS_NORM : FP_NEG_NORM ); 00692 } 00693 00694 INT32 00695 c_fp_class_q(QUAD x) 00696 { 00697 QUAD y; 00698 INT err; 00699 INT32 class; 00700 00701 /* Notice that the definition of denormal for quad precision is 00702 * chosen so that normal quads have a full 107 bits precision 00703 * in their mantissas. 00704 */ 00705 00706 class = fp_class_d(x.hi); 00707 00708 if ( (class != FP_POS_NORM) && (class != FP_NEG_NORM) ) 00709 return ( class ); 00710 00711 class = fp_class_d(x.lo); 00712 00713 if ( (class == FP_POS_DENORM) && (class == FP_NEG_DENORM) ) 00714 return ( class ); 00715 00716 y.hi = twopm916.d; 00717 y.lo = 0.0; 00718 00719 if ( c_q_ge(x, y, &err) ) 00720 return ( FP_POS_NORM ); 00721 00722 y.hi = -y.hi; 00723 00724 if ( c_q_le(x, y, &err) ) 00725 return ( FP_POS_NORM ); 00726 00727 if ( x.hi > 0.0 ) 00728 return ( FP_POS_DENORM ); 00729 00730 return ( FP_NEG_DENORM ); 00731 } 00732