? sid/component/cgen-cpu/cgen-fpu.cxx ? sid/component/cgen-cpu/cgen-fpu.h Index: sid/component/cgen-cpu/Makefile.am =================================================================== RCS file: /cvs/src/src/sid/component/cgen-cpu/Makefile.am,v retrieving revision 1.12 diff -c -p -r1.12 Makefile.am *** sid/component/cgen-cpu/Makefile.am 4 Jun 2005 03:23:02 -0000 1.12 --- sid/component/cgen-cpu/Makefile.am 2 Aug 2005 19:19:22 -0000 *************** MAKEOVERRIDES= *** 20,26 **** LIBIBERTY = -L../../../libiberty/pic -liberty ! libcgencpu_la_SOURCES = compCGEN.cxx tracedis.cxx libcgencpu_la_LDFLAGS = -module -no-undefined libcgencpu_la_LIBADD = @cpu_libs@ $(INTLLIBS) $(LIBIBERTY) cgen-asm.lo cgen-dis.lo cgen-opc.lo dis-buf.lo dis-init.lo libcgencpu_la_DEPENDENCIES = @cpu_libs@ cgen-asm.lo cgen-dis.lo cgen-opc.lo dis-buf.lo dis-init.lo --- 20,26 ---- LIBIBERTY = -L../../../libiberty/pic -liberty ! libcgencpu_la_SOURCES = compCGEN.cxx cgen-fpu.cxx fp.cxx tracedis.cxx libcgencpu_la_LDFLAGS = -module -no-undefined libcgencpu_la_LIBADD = @cpu_libs@ $(INTLLIBS) $(LIBIBERTY) cgen-asm.lo cgen-dis.lo cgen-opc.lo dis-buf.lo dis-init.lo libcgencpu_la_DEPENDENCIES = @cpu_libs@ cgen-asm.lo cgen-dis.lo cgen-opc.lo dis-buf.lo dis-init.lo Index: sid/component/cgen-cpu/fp.cxx =================================================================== RCS file: /cvs/src/src/sid/component/cgen-cpu/fp.cxx,v retrieving revision 1.2 diff -c -p -r1.2 fp.cxx *** sid/component/cgen-cpu/fp.cxx 8 Jan 2003 10:36:49 -0000 1.2 --- sid/component/cgen-cpu/fp.cxx 2 Aug 2005 19:19:22 -0000 *************** *** 1,6 **** // fp.cxx - Floating point number class implementation. -*- C++ -*- ! // Copyright 1997, 1998, 2002 Free Software Foundation, Inc. // Copyright 2002 Red Hat, Inc. // This file is part of SID. --- 1,6 ---- // fp.cxx - Floating point number class implementation. -*- C++ -*- ! // Copyright 1997, 1998, 2002, 2005 Free Software Foundation, Inc. // Copyright 2002 Red Hat, Inc. // This file is part of SID. *************** *** 23,172 **** #include "fp.h" - using sid::host_int_4; - using sid::host_int_8; - using sid::signed_host_int_8; - - // XXX: more of this cruft should be C++-ed. - - #define FRAC32MASK LSMASK64 (63, NR_FRAC_GUARD - 32 + 1) - #define MAX_UINT32 LSMASK64 (31, 0) - #define MAX_UINT64 LSMASK64 (63, 0) - #define MAX_INT (is_64bit ? MAX_INT64 () : MAX_INT32 ()) - #define MIN_INT (is_64bit ? MIN_INT64 () : MIN_INT32 ()) - #define MAX_UINT (is_64bit ? MAX_UINT64 () : MAX_UINT32 ()) - #define QUIET_NAN LSBIT64 (NR_FRACBITS (double_p) - 1) - #define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD) - #define IMPLICIT_2 LSBIT64 (NR_FRAC_GUARD + 1) - #define IMPLICIT_4 LSBIT64 (NR_FRAC_GUARD + 2) - #define NORMAL_EXPMIN (-(EXPBIAS (double_p) )+1) - #define NORMAL_EXPMAX (EXPBIAS (double_p)) - - #if (WITH_TARGET_WORD_MSB == 0) - #define _LSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) - #else - #define _LSB_SHIFT(WIDTH, POS) (POS) - #endif - - #if (WITH_TARGET_WORD_MSB == 0) - #define _MSB_SHIFT(WIDTH, POS) (POS) - #else - #define _MSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) - #endif - - #define _MASK64(WIDTH, START, STOP) (((static_cast(-1)) \ - >> (_MSB_SHIFT (WIDTH, START) \ - + _LSB_SHIFT (WIDTH, STOP))) \ - << _LSB_SHIFT (WIDTH, STOP)) - - #if (WITH_TARGET_WORD_MSB == 0) - #define _LSB_POS(WIDTH, SHIFT) (WIDTH - 1 - SHIFT) - #else - #define _LSB_POS(WIDTH, SHIFT) (SHIFT) - #endif - - #define _LSMASK64(WIDTH, FIRST, LAST) _MASK64 (WIDTH, \ - _LSB_POS (WIDTH, FIRST), \ - _LSB_POS (WIDTH, LAST)) - - #define LSMASK64(FIRST, LAST) _LSMASK64 (64, (FIRST), (LAST)) - - #define GUARDMSB LSBIT64 (NR_GUARDS (double_p) - 1) - #define GUARDLSB LSBIT64 (NR_PAD) - #define GUARDMASK LSMASK64 (NR_GUARDS (double_p) - 1, 0) - #define GUARDROUND LSMASK64 (NR_GUARDS (double_p) - 2, 0) - - static const int NR_SPARE = 2; - static const int EXPMAX32 = 255; - static const int EXPMAX64 = 2047; - static const int NR_FRAC_GUARD = 60; - static const int EXPBIAS32 = 127; - static const int EXPBIAS64 = 1023; - static const int NR_PAD32 = 30; - static const int NR_PAD64 = 0; - static const int NR_GUARDS32 = 7 + NR_PAD32; - static const int NR_GUARDS64 = 8 + NR_PAD64; - static const int NORMAL_EXPMAX32 = EXPBIAS32; - static const int NORMAL_EXPMAX64 = EXPBIAS64; - - static inline - signed_host_int_8 MAX_INT32 () - { - return LSMASK64 (30, 0); - } - - static inline - signed_host_int_8 MIN_INT32 () - { - return LSMASK64 (63, 31); - } - - static inline - signed_host_int_8 MAX_INT64 () - { - return LSMASK64 (62, 0); - } - - static inline - signed_host_int_8 MIN_INT64 () - { - return LSMASK64 (63, 63); - } - - static inline - unsigned EXPMAX (bool double_p) - { - return double_p ? EXPMAX64 : EXPMAX32; - } - - static inline - int EXPBIAS (bool double_p) - { - return double_p ? EXPBIAS64 : EXPBIAS32; - } - - static inline - int NR_GUARDS (bool double_p) - { - return double_p ? NR_GUARDS64 : NR_GUARDS32; - } - - static inline - int NR_EXPBITS (bool double_p) - { - return double_p ? 11 : 8; - } - - static inline - int NR_FRACBITS (bool double_p) - { - return double_p ? 52 : 23; - } - - static inline - int NR_INTBITS (bool is_64bit) - { - return is_64bit ? 64 : 32; - } - - static inline - host_int_8 LSBIT64 (int pos) - { - return host_int_8 (1) << pos; - } - - static inline - host_int_8 MSBIT64 (int pos) - { - return host_int_8 (1) << (64 - 1 - pos); - } - - static inline - host_int_8 SIGNBIT (bool double_p) - { - return double_p ? MSBIT64 (0) : MSBIT64 (32); - } - static void print_bits (std::ostream& out, host_int_8 x, int msbit, int digits) { --- 23,28 ---- *************** namespace sidutil *** 264,270 **** if (fraction == IMPLICIT_1) return; // exact if (is_64bit) // can't round ! throw fp::error (fp::invalid_cvi); // must be overflow // For a 32bit with MAX_INT, rounding is possible. switch (round) --- 120,126 ---- if (fraction == IMPLICIT_1) return; // exact if (is_64bit) // can't round ! throw fp::error (fp::overflow); // must be overflow // For a 32bit with MAX_INT, rounding is possible. switch (round) *************** namespace sidutil *** 302,308 **** if (normal_exp > (NR_INTBITS (is_64bit) - 2)) { i = sign ? MIN_INT : MAX_INT; ! throw fp::error (fp::invalid_cvi); } // Normal number shift it into place. tmp = fraction; --- 158,164 ---- if (normal_exp > (NR_INTBITS (is_64bit) - 2)) { i = sign ? MIN_INT : MAX_INT; ! throw fp::error (fp::overflow); } // Normal number shift it into place. tmp = fraction; *************** namespace sidutil *** 329,334 **** --- 185,192 ---- { host_int_8 tmp; int shift; + int is_64bit = (sizeof u == 8); + bool double_p = (sizeof u == 8); if (is_zero ()) { *************** namespace sidutil *** 475,497 **** host_int_8 exp; host_int_8 frac; host_int_8 packed; switch (fp_class) { // Create a NaN. case fp::class_qnan: ! exp = EXPMAX (double_p); ! // Force fraction to correct class. ! frac = fraction; ! frac >>= NR_GUARDS (double_p); ! frac |= QUIET_NAN; break; case fp::class_snan: ! exp = EXPMAX (double_p); ! // Force fraction to correct class. ! frac = fraction; ! frac >>= NR_GUARDS (double_p); ! frac &= ~QUIET_NAN; break; case fp::class_infinity: exp = EXPMAX (double_p); --- 333,352 ---- host_int_8 exp; host_int_8 frac; host_int_8 packed; + int sign_bit = sign; switch (fp_class) { // Create a NaN. case fp::class_qnan: ! sign_bit = 0; ! exp = qnan_exponent (double_p); ! frac = qnan_fraction (double_p); break; case fp::class_snan: ! sign_bit = 0; ! exp = snan_exponent (double_p); ! frac = snan_fraction (double_p); break; case fp::class_infinity: exp = EXPMAX (double_p); *************** namespace sidutil *** 570,576 **** abort (); } ! packed = ((sign ? SIGNBIT (double_p) : 0) | (exp << NR_FRACBITS (double_p)) | LSMASKED64 (frac, NR_FRACBITS (double_p) - 1, 0)); t = packed; } --- 425,431 ---- abort (); } ! packed = ((sign_bit ? SIGNBIT (double_p) : 0) | (exp << NR_FRACBITS (double_p)) | LSMASKED64 (frac, NR_FRACBITS (double_p) - 1, 0)); t = packed; } *************** namespace sidutil *** 578,583 **** --- 433,439 ---- template void fp::unpack (const T& packed) { + status = ok; // Unpack a 32/64 bit integer into an fp object. bool double_p = (sizeof packed == 8); *************** namespace sidutil *** 627,633 **** // Non zero fraction, means NaN. sign = signbit; fraction = (frac << NR_GUARDS (double_p)); ! fp_class = (frac >= QUIET_NAN) ? fp::class_qnan : fp::class_snan; } } else --- 483,490 ---- // Non zero fraction, means NaN. sign = signbit; fraction = (frac << NR_GUARDS (double_p)); ! fp_class = is_qnan_fraction (frac, double_p) ? fp::class_qnan : fp::class_snan; ! status = is_qnan () ? invalid_qnan : invalid_snan; } } else *************** namespace sidutil *** 640,651 **** } // Sanity checks. { - map_t val; - pack (val.i); - if (double_p) ! assert (val.i == packed); else { host_int_4 val; --- 497,510 ---- } // Sanity checks. + if (! is_nan ()) { if (double_p) ! { ! map_t val; ! pack (val.i); ! assert (val.i == packed); ! } else { host_int_4 val; *************** namespace sidutil *** 811,817 **** fp_class = fp::class_infinity; break; case fp::round_up: ! if (sign) fp_class = fp::class_infinity; break; case fp::round_down: --- 670,676 ---- fp_class = fp::class_infinity; break; case fp::round_up: ! if (! sign) fp_class = fp::class_infinity; break; case fp::round_down: *************** namespace sidutil *** 942,989 **** } bool ! operator< (const fp& l, const fp& r) { ! if (!l.is_nan () && !r.is_nan ()) { map_t lval, rval; ! l.pack (lval.i); r.pack (rval.i); return (lval.d < rval.d); } ! else if (l.is_snan () || r.is_snan ()) throw fp::error (fp::invalid_snan); else throw fp::error (fp::invalid_qnan); } bool ! operator<= (const fp& l, const fp& r) { ! if (!l.is_nan () && !r.is_nan ()) { map_t lval, rval; ! l.pack (lval.i); r.pack (rval.i); return (lval.d <= rval.d); } ! else if (l.is_snan () || r.is_snan ()) throw fp::error (fp::invalid_snan); else throw fp::error (fp::invalid_qnan); } bool ! operator== (const fp& l, const fp& r) { ! if (!l.is_nan () && !r.is_nan ()) { map_t lval, rval; ! l.pack (lval.i); r.pack (rval.i); return (lval.d == rval.d); } ! else if (l.is_snan () || r.is_snan ()) throw fp::error (fp::invalid_snan); else throw fp::error (fp::invalid_qnan); --- 801,848 ---- } bool ! fp::operator< (const fp& r) const { ! if (!this->is_nan () && !r.is_nan ()) { map_t lval, rval; ! this->pack (lval.i); r.pack (rval.i); return (lval.d < rval.d); } ! else if (this->is_snan () || r.is_snan ()) throw fp::error (fp::invalid_snan); else throw fp::error (fp::invalid_qnan); } bool ! fp::operator<= (const fp& r) const { ! if (!this->is_nan () && !r.is_nan ()) { map_t lval, rval; ! this->pack (lval.i); r.pack (rval.i); return (lval.d <= rval.d); } ! else if (this->is_snan () || r.is_snan ()) throw fp::error (fp::invalid_snan); else throw fp::error (fp::invalid_qnan); } bool ! fp::operator== (const fp& r) const { ! if (!this->is_nan () && !r.is_nan ()) { map_t lval, rval; ! this->pack (lval.i); r.pack (rval.i); return (lval.d == rval.d); } ! else if (this->is_snan () || r.is_snan ()) throw fp::error (fp::invalid_snan); else throw fp::error (fp::invalid_qnan); *************** namespace sidutil *** 991,1031 **** bool ! operator!= (const fp& l, const fp& r) { ! if (!l.is_nan () && !r.is_nan ()) ! { ! map_t lval, rval; ! l.pack (lval.i); ! r.pack (rval.i); ! return (lval.d != rval.d); ! } ! else if (l.is_snan () || r.is_snan ()) ! throw fp::error (fp::invalid_snan); ! else ! throw fp::error (fp::invalid_qnan); } bool ! operator>= (const fp& l, const fp& r) { ! return r <= l; } bool ! operator> (const fp& l, const fp& r) { ! return r < l; } fp ! operator+ (const fp& l, const fp& r) { fp f; ! if (l.is_snan ()) { ! f = l; f.fp_class = fp::class_qnan; f.status = fp::invalid_snan; return f; --- 850,880 ---- bool ! fp::operator!= (const fp& r) const { ! return !(*this == r); } bool ! fp::operator>= (const fp& r) const { ! return r <= *this; } bool ! fp::operator> (const fp& r) const { ! return r < *this; } fp ! fp::operator+ (const fp& r) const { fp f; ! if (this->is_snan ()) { ! f = *this; f.fp_class = fp::class_qnan; f.status = fp::invalid_snan; return f; *************** namespace sidutil *** 1039,1047 **** return f; } ! if (l.is_qnan ()) { ! f = l; f.status = fp::ok; return f; } --- 888,896 ---- return f; } ! if (this->is_qnan ()) { ! f = *this; f.status = fp::ok; return f; } *************** namespace sidutil *** 1053,1067 **** return f; } ! if (l.is_infinity ()) { ! if (r.is_infinity () && l.sign != r.sign) { f = constant_qnan; f.status = fp::invalid_isi; return f; } ! f = l; f.status = fp::ok; return f; } --- 902,916 ---- return f; } ! if (this->is_infinity ()) { ! if (r.is_infinity () && this->sign != r.sign) { f = constant_qnan; f.status = fp::invalid_isi; return f; } ! f = *this; f.status = fp::ok; return f; } *************** namespace sidutil *** 1073,1084 **** return f; } ! if (l.is_zero ()) { if (r.is_zero ()) { f = constant_zero; ! f.sign = l.sign & r.sign; } else f = r; --- 922,933 ---- return f; } ! if (this->is_zero ()) { if (r.is_zero ()) { f = constant_zero; ! f.sign = this->sign & r.sign; } else f = r; *************** namespace sidutil *** 1088,1122 **** if (r.is_zero ()) { ! f = l; f.status = fp::ok; return f; } fp::status_t status = fp::ok; ! int shift = l.normal_exp - r.normal_exp; host_int_8 lfraction; host_int_8 rfraction; // Use exp of larger. if (shift >= NR_FRAC_GUARD) { // Left has much bigger magnitude. ! f = l; f.status = fp::inexact; return f; } if (shift <= - NR_FRAC_GUARD) { ! // Right has much bigger magnitute. f = r; f.status = fp::inexact; return f; } ! lfraction = l.fraction; rfraction = r.fraction; if (shift > 0) { ! f.normal_exp = l.normal_exp; if (rfraction & LSMASK64 (shift - 1, 0)) { status |= fp::inexact; --- 937,971 ---- if (r.is_zero ()) { ! f = *this; f.status = fp::ok; return f; } fp::status_t status = fp::ok; ! int shift = this->normal_exp - r.normal_exp; host_int_8 lfraction; host_int_8 rfraction; // Use exp of larger. if (shift >= NR_FRAC_GUARD) { // Left has much bigger magnitude. ! f = *this; f.status = fp::inexact; return f; } if (shift <= - NR_FRAC_GUARD) { ! // Right has much bigger magnitude. f = r; f.status = fp::inexact; return f; } ! lfraction = this->fraction; rfraction = r.fraction; if (shift > 0) { ! f.normal_exp = this->normal_exp; if (rfraction & LSMASK64 (shift - 1, 0)) { status |= fp::inexact; *************** namespace sidutil *** 1138,1144 **** f.normal_exp = r.normal_exp; // Perform the addition. ! if (l.sign) lfraction = - lfraction; if (r.sign) rfraction = - rfraction; --- 987,993 ---- f.normal_exp = r.normal_exp; // Perform the addition. ! if (this->sign) lfraction = - lfraction; if (r.sign) rfraction = - rfraction; *************** namespace sidutil *** 1183,1350 **** } fp ! operator- (const fp& l, const fp& r) { ! fp f; ! ! if (l.is_snan ()) ! { ! f = l; ! f.fp_class = fp::class_qnan; ! f.status = fp::invalid_snan; ! return f; ! } ! ! if (r.is_snan ()) ! { ! f = r; ! f.fp_class = fp::class_qnan; ! f.status = fp::invalid_snan; ! return f; ! } ! ! if (l.is_infinity ()) ! { ! if (r.is_infinity () && l.sign == r.sign) ! { ! f = constant_qnan; ! f.status = fp::invalid_isi; ! return f; ! } ! f = l; ! f.status = fp::ok; ! return f; ! } ! ! if (r.is_infinity ()) ! { ! f = r; ! f.sign = !r.sign; ! f.status = fp::ok; ! return f; ! } ! ! if (l.is_zero ()) ! { ! if (r.is_zero ()) ! { ! f = constant_zero; ! f.sign = l.sign & !r.sign; ! } ! else ! { ! f = r; ! f.sign = !r.sign; ! } ! f.status = fp::ok; ! return f; ! } ! if (r.is_zero ()) ! { ! f = l; ! f.status = fp::ok; ! return f; ! } ! ! fp::status_t status = fp::ok; ! int shift = l.normal_exp - r.normal_exp; ! host_int_8 lfraction; ! host_int_8 rfraction; ! // Use exp of larger. ! if (shift >= NR_FRAC_GUARD) ! { ! // Left has much bigger magnitude. ! f = l; ! f.status = fp::inexact; ! return f; ! } ! if (shift <= - NR_FRAC_GUARD) ! { ! // Right has much bigger magnitute. ! f = r; ! f.sign = !r.sign; ! f.status = fp::inexact; ! return f; ! } ! lfraction = l.fraction; ! rfraction = r.fraction; ! if (shift > 0) ! { ! f.normal_exp = l.normal_exp; ! if (rfraction & LSMASK64 (shift - 1, 0)) ! { ! status |= fp::inexact; ! rfraction |= LSBIT64 (shift); // Stick LSBit. ! } ! rfraction >>= shift; ! } ! else if (shift < 0) ! { ! f.normal_exp = r.normal_exp; ! if (lfraction & LSMASK64 (- shift - 1, 0)) ! { ! status |= fp::inexact; ! lfraction |= LSBIT64 (- shift); // Stick LSBit. ! } ! lfraction >>= -shift; ! } ! else ! { ! f.normal_exp = r.normal_exp; ! } ! ! // Perform the subtraction. ! if (l.sign) ! lfraction = - lfraction; ! if (!r.sign) ! rfraction = - rfraction; ! f.fraction = lfraction + rfraction; ! ! // Zero? ! if (f.fraction == 0) ! { ! f = constant_zero; ! return f; ! } ! ! // Sign? ! f.fp_class = fp::class_number; ! if (static_cast (f.fraction) >= 0) ! f.sign = 0; ! else ! { ! f.sign = 1; ! f.fraction = - f.fraction; ! } ! ! // Normalize it. ! if ((f.fraction & IMPLICIT_2)) ! { ! f.fraction = (f.fraction >> 1) | (f.fraction & 1); ! f.normal_exp ++; ! } ! else if (f.fraction < IMPLICIT_1) ! { ! do ! { ! f.fraction <<= 1; ! f.normal_exp --; ! } ! while (f.fraction < IMPLICIT_1); ! } ! ! assert (f.fraction >= IMPLICIT_1 && f.fraction < IMPLICIT_2); ! return f; } fp ! operator* (const fp& l, const fp& r) { fp f; ! if (l.is_snan ()) { ! f = l; f.fp_class = fp::class_qnan; f.status = fp::invalid_snan; return f; --- 1032,1052 ---- } fp ! fp::operator- (const fp& r) const { ! if (! r.is_nan ()) ! return *this + neg (r); ! return *this + r; } fp ! fp::operator* (const fp& r) const { fp f; ! if (this->is_snan ()) { ! f = *this; f.fp_class = fp::class_qnan; f.status = fp::invalid_snan; return f; *************** namespace sidutil *** 1356,1364 **** f.status = fp::invalid_snan; return f; } ! if (l.is_qnan ()) { ! f = l; f.status = fp::ok; return f; } --- 1058,1066 ---- f.status = fp::invalid_snan; return f; } ! if (this->is_qnan ()) { ! f = *this; f.status = fp::ok; return f; } *************** namespace sidutil *** 1368,1374 **** f.status = fp::ok; return f; } ! if (l.is_infinity ()) { if (r.is_zero ()) { --- 1070,1076 ---- f.status = fp::ok; return f; } ! if (this->is_infinity ()) { if (r.is_zero ()) { *************** namespace sidutil *** 1376,1401 **** f.status = fp::invalid_imz; return f; } ! f = l; ! f.sign = l.sign ^ r.sign; return f; } if (r.is_infinity ()) { ! if (l.is_zero ()) { f = constant_qnan; f.status = fp::invalid_imz; return f; } f = r; ! f.sign = l.sign ^ r.sign; return f; } ! if (l.is_zero () || r.is_zero ()) { f = constant_zero; ! f.sign = l.sign ^ r.sign; return f; } --- 1078,1103 ---- f.status = fp::invalid_imz; return f; } ! f = *this; ! f.sign = this->sign ^ r.sign; return f; } if (r.is_infinity ()) { ! if (this->is_zero ()) { f = constant_qnan; f.status = fp::invalid_imz; return f; } f = r; ! f.sign = this->sign ^ r.sign; return f; } ! if (this->is_zero () || r.is_zero ()) { f = constant_zero; ! f.sign = this->sign ^ r.sign; return f; } *************** namespace sidutil *** 1404,1411 **** host_int_8 low; host_int_8 high; ! host_int_8 nl = l.fraction & 0xffffffff; ! host_int_8 nh = l.fraction >> 32; host_int_8 ml = r.fraction & 0xffffffff; host_int_8 mh = r.fraction >>32; host_int_8 pp_ll = ml * nl; --- 1106,1113 ---- host_int_8 low; host_int_8 high; ! host_int_8 nl = this->fraction & 0xffffffff; ! host_int_8 nh = this->fraction >> 32; host_int_8 ml = r.fraction & 0xffffffff; host_int_8 mh = r.fraction >>32; host_int_8 pp_ll = ml * nl; *************** namespace sidutil *** 1425,1432 **** high = res2; low = res0; ! f.normal_exp = l.normal_exp + r.normal_exp; ! f.sign = l.sign ^ r.sign; f.fp_class = fp::class_number; // Input is bounded by [1,2) ; [2^60,2^61) --- 1127,1134 ---- high = res2; low = res0; ! f.normal_exp = this->normal_exp + r.normal_exp; ! f.sign = this->sign ^ r.sign; f.fp_class = fp::class_number; // Input is bounded by [1,2) ; [2^60,2^61) *************** namespace sidutil *** 1469,1481 **** } fp ! operator/ (const fp& l, const fp& r) { fp f; ! if (l.is_snan ()) { ! f = l; f.fp_class = fp::class_qnan; f.status = fp::invalid_snan; return f; --- 1171,1183 ---- } fp ! fp::operator/ (const fp& r) const { fp f; ! if (this->is_snan ()) { ! f = *this; f.fp_class = fp::class_qnan; f.status = fp::invalid_snan; return f; *************** namespace sidutil *** 1487,1495 **** f.status = fp::invalid_snan; return f; } ! if (l.is_qnan ()) { ! f = l; f.fp_class = fp::class_qnan; return f; } --- 1189,1197 ---- f.status = fp::invalid_snan; return f; } ! if (this->is_qnan ()) { ! f = *this; f.fp_class = fp::class_qnan; return f; } *************** namespace sidutil *** 1499,1505 **** f.fp_class = fp::class_qnan; return f; } ! if (l.is_infinity ()) { if (r.is_infinity ()) { --- 1201,1207 ---- f.fp_class = fp::class_qnan; return f; } ! if (this->is_infinity ()) { if (r.is_infinity ()) { *************** namespace sidutil *** 1508,1520 **** } else { ! f = l; ! f.sign = l.sign ^ r.sign; } return f; } ! if (l.is_zero ()) { if (r.is_zero ()) { --- 1210,1222 ---- } else { ! f = *this; ! f.sign = this->sign ^ r.sign; } return f; } ! if (this->is_zero ()) { if (r.is_zero ()) { *************** namespace sidutil *** 1523,1530 **** } else { ! f = l; ! f.sign = l.sign ^ r.sign; } return f; } --- 1225,1232 ---- } else { ! f = *this; ! f.sign = this->sign ^ r.sign; } return f; } *************** namespace sidutil *** 1532,1545 **** if (r.is_infinity ()) { f = constant_zero; ! f.sign = l.sign ^ r.sign; return f; } if (r.is_zero ()) { f.fp_class = fp::class_infinity; ! f.sign = l.sign ^ r.sign; f.status = fp::invalid_div0; return f; } --- 1234,1247 ---- if (r.is_infinity ()) { f = constant_zero; ! f.sign = this->sign ^ r.sign; return f; } if (r.is_zero ()) { f.fp_class = fp::class_infinity; ! f.sign = this->sign ^ r.sign; f.status = fp::invalid_div0; return f; } *************** namespace sidutil *** 1556,1565 **** host_int_8 bit; f.fp_class = fp::class_number; ! f.sign = l.sign ^ r.sign; ! f.normal_exp = l.normal_exp - r.normal_exp; ! numerator = l.fraction; denominator = r.fraction; // Fraction will be less than 1.0. --- 1258,1267 ---- host_int_8 bit; f.fp_class = fp::class_number; ! f.sign = this->sign ^ r.sign; ! f.normal_exp = this->normal_exp - r.normal_exp; ! numerator = this->fraction; denominator = r.fraction; // Fraction will be less than 1.0. *************** namespace sidutil *** 1813,1819 **** } if (src.is_qnan()) { ! return dest; } dest = src; dest.sign = !src.sign; --- 1515,1521 ---- } if (src.is_qnan()) { ! return src; } dest = src; dest.sign = !src.sign; Index: sid/component/cgen-cpu/fp.h =================================================================== RCS file: /cvs/src/src/sid/component/cgen-cpu/fp.h,v retrieving revision 1.2 diff -c -p -r1.2 fp.h *** sid/component/cgen-cpu/fp.h 8 Jan 2003 10:36:49 -0000 1.2 --- sid/component/cgen-cpu/fp.h 2 Aug 2005 19:19:22 -0000 *************** *** 1,6 **** // fp.h - Floating point number class using host integer ops. -*- C++ -*- ! // Copyright 1997, 1998, 2002 Free Software Foundation, Inc. // Copyright 2002 Red Hat, Inc. // This file is part of SID. --- 1,6 ---- // fp.h - Floating point number class using host integer ops. -*- C++ -*- ! // Copyright 1997, 1998, 2002, 2005 Free Software Foundation, Inc. // Copyright 2002 Red Hat, Inc. // This file is part of SID. *************** *** 28,33 **** --- 28,185 ---- #include "sidtypes.h" #include "cgen-types.h" + using sid::host_int_4; + using sid::host_int_8; + using sid::signed_host_int_8; + + // XXX: more of this cruft should be C++-ed. + + #define FRAC32MASK LSMASK64 (63, NR_FRAC_GUARD - 32 + 1) + #define MAX_UINT32() LSMASK64 (31, 0) + #define MAX_UINT64() LSMASK64 (63, 0) + #define MAX_INT (is_64bit ? MAX_INT64 () : MAX_INT32 ()) + #define MIN_INT (is_64bit ? MIN_INT64 () : MIN_INT32 ()) + #define MAX_UINT (is_64bit ? MAX_UINT64 () : MAX_UINT32 ()) + #define QUIET_NAN LSBIT64 (NR_FRACBITS (double_p) - 1) + #define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD) + #define IMPLICIT_2 LSBIT64 (NR_FRAC_GUARD + 1) + #define IMPLICIT_4 LSBIT64 (NR_FRAC_GUARD + 2) + #define NORMAL_EXPMIN (-(EXPBIAS (double_p) )+1) + #define NORMAL_EXPMAX (EXPBIAS (double_p)) + + #if (WITH_TARGET_WORD_MSB == 0) + #define _LSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) + #else + #define _LSB_SHIFT(WIDTH, POS) (POS) + #endif + + #if (WITH_TARGET_WORD_MSB == 0) + #define _MSB_SHIFT(WIDTH, POS) (POS) + #else + #define _MSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) + #endif + + #define _MASK64(WIDTH, START, STOP) (((static_cast(-1)) \ + >> (_MSB_SHIFT (WIDTH, START) \ + + _LSB_SHIFT (WIDTH, STOP))) \ + << _LSB_SHIFT (WIDTH, STOP)) + + #if (WITH_TARGET_WORD_MSB == 0) + #define _LSB_POS(WIDTH, SHIFT) (WIDTH - 1 - SHIFT) + #else + #define _LSB_POS(WIDTH, SHIFT) (SHIFT) + #endif + + #define _LSMASK64(WIDTH, FIRST, LAST) _MASK64 (WIDTH, \ + _LSB_POS (WIDTH, FIRST), \ + _LSB_POS (WIDTH, LAST)) + + #define LSMASK64(FIRST, LAST) _LSMASK64 (64, (FIRST), (LAST)) + + #define GUARDMSB LSBIT64 (NR_GUARDS (double_p) - 1) + #define GUARDLSB LSBIT64 (NR_PADS (double_p)) + #define GUARDMASK LSMASK64 (NR_GUARDS (double_p) - 1, 0) + #define GUARDROUND LSMASK64 (NR_GUARDS (double_p) - 2, 0) + + #define PADMASK LSMASK64 (NR_PADS (double_p) - 1, 0) + + static const int NR_SPARE = 2; + static const int EXPMAX32 = 255; + static const int EXPMAX64 = 2047; + static const int NR_FRAC_GUARD = 60; + static const int EXPBIAS32 = 127; + static const int EXPBIAS64 = 1023; + static const int NR_PAD32 = 30; + static const int NR_PAD64 = 0; + static const int NR_GUARDS32 = 7 + NR_PAD32; + static const int NR_GUARDS64 = 8 + NR_PAD64; + static const int NORMAL_EXPMAX32 = EXPBIAS32; + static const int NORMAL_EXPMAX64 = EXPBIAS64; + + static inline + signed_host_int_8 MAX_INT32 () + { + return LSMASK64 (30, 0); + } + + static inline + signed_host_int_8 MIN_INT32 () + { + return LSMASK64 (63, 31); + } + + static inline + signed_host_int_8 MAX_INT64 () + { + return LSMASK64 (62, 0); + } + + static inline + signed_host_int_8 MIN_INT64 () + { + return LSMASK64 (63, 63); + } + + static inline + unsigned EXPMAX (bool double_p) + { + return double_p ? EXPMAX64 : EXPMAX32; + } + + static inline + int EXPBIAS (bool double_p) + { + return double_p ? EXPBIAS64 : EXPBIAS32; + } + + static inline + int NR_GUARDS (bool double_p) + { + return double_p ? NR_GUARDS64 : NR_GUARDS32; + } + + static inline + int NR_PADS (bool double_p) + { + return double_p ? NR_PAD64 : NR_PAD32; + } + + static inline + int NR_EXPBITS (bool double_p) + { + return double_p ? 11 : 8; + } + + static inline + int NR_FRACBITS (bool double_p) + { + return double_p ? 52 : 23; + } + + static inline + int NR_INTBITS (bool is_64bit) + { + return is_64bit ? 64 : 32; + } + + static inline + host_int_8 LSBIT64 (int pos) + { + return host_int_8 (1) << pos; + } + + static inline + host_int_8 MSBIT64 (int pos) + { + return host_int_8 (1) << (64 - 1 - pos); + } + + static inline + host_int_8 SIGNBIT (bool double_p) + { + return double_p ? MSBIT64 (0) : MSBIT64 (32); + } + namespace sidutil { class fp *************** namespace sidutil *** 98,115 **** bool is_zero () const; bool is_infinity () const; bool is_number () const; // Conversions to integers. ! void integer (int&, round_mode_t = round_default); ! void integer (long&, round_mode_t = round_default); ! void integer (unsigned int&, round_mode_t = round_default); ! void integer (unsigned long&, round_mode_t = round_default); // Pack an fp into registers of various sizes. void pack (cgen::SF&) const; void pack (cgen::DF&) const; void pack (cgen::SF& upper, cgen::SF& lower) const; // Round an fp suitable for packing. void round_32 (round_mode_t = round_default, enum denorm_t = denorm_default); void round_64 (round_mode_t = round_default, enum denorm_t = denorm_default); --- 250,302 ---- bool is_zero () const; bool is_infinity () const; bool is_number () const; + bool is_inexact () const; + bool is_negative () const; + + status_t get_status () const { return status; } + class_t get_class () const { return fp_class; } // Conversions to integers. ! virtual void integer (int&, round_mode_t = round_default); ! virtual void integer (long&, round_mode_t = round_default); ! virtual void integer (unsigned int&, round_mode_t = round_default); ! virtual void integer (unsigned long&, round_mode_t = round_default); // Pack an fp into registers of various sizes. void pack (cgen::SF&) const; void pack (cgen::DF&) const; void pack (cgen::SF& upper, cgen::SF& lower) const; + virtual host_int_8 qnan_exponent (bool double_p) const + { + return EXPMAX (double_p); + } + + virtual host_int_8 qnan_fraction (bool double_p) const + { + // Force fraction to correct class. + host_int_8 frac = fraction; + frac >>= NR_GUARDS (double_p); + frac |= QUIET_NAN; + return frac; + } + + virtual host_int_8 snan_exponent (bool double_p) const + { + return EXPMAX (double_p); + } + + virtual host_int_8 snan_fraction (bool double_p) const + { + // Force fraction to correct class. + host_int_8 frac = fraction; + frac >>= NR_GUARDS (double_p); + frac &= ~QUIET_NAN; + return frac; + } + + virtual bool is_qnan_fraction (host_int_8 frac, bool double_p) const { return frac >= QUIET_NAN; } + // Round an fp suitable for packing. void round_32 (round_mode_t = round_default, enum denorm_t = denorm_default); void round_64 (round_mode_t = round_default, enum denorm_t = denorm_default); *************** namespace sidutil *** 145,161 **** denorm = 0x4000 }; ! private: status_t status; enum class_t fp_class; int sign; fraction_t fraction; exp_t normal_exp; ! void do_round (bool double_p, round_mode_t round, enum denorm_t denorm); ! status_t do_normal_round (int nr_guards, enum round_mode_t round); ! status_t do_normal_overflow (bool double_p, enum round_mode_t round); ! status_t do_normal_underflow (bool double_p, enum round_mode_t round); void int_to_fp (cgen::SI i); void uint_to_fp (cgen::USI i); --- 332,348 ---- denorm = 0x4000 }; ! protected: status_t status; enum class_t fp_class; int sign; fraction_t fraction; exp_t normal_exp; ! virtual void do_round (bool double_p, round_mode_t round, enum denorm_t denorm); ! virtual status_t do_normal_round (int nr_guards, enum round_mode_t round); ! virtual status_t do_normal_overflow (bool double_p, enum round_mode_t round); ! virtual status_t do_normal_underflow (bool double_p, enum round_mode_t round); void int_to_fp (cgen::SI i); void uint_to_fp (cgen::USI i); *************** namespace sidutil *** 164,188 **** template void unpack (const T& t); template void pack_any (T& t) const; friend std::ostream& operator<< (std::ostream& out, const fp& f); - friend fp operator+ (const fp& l, const fp& r); - friend fp operator- (const fp& l, const fp& r); - friend fp operator* (const fp& l, const fp& r); - friend fp operator/ (const fp& l, const fp& r); }; - fp operator+ (const fp& l, const fp& r); - fp operator- (const fp& l, const fp& r); - fp operator* (const fp& l, const fp& r); - fp operator/ (const fp& l, const fp& r); - - bool operator< (const fp& l, const fp& r); - bool operator<= (const fp& l, const fp& r); - bool operator== (const fp& l, const fp& r); - bool operator!= (const fp& l, const fp& r); - bool operator>= (const fp& l, const fp& r); - bool operator> (const fp& l, const fp& r); - std::ostream& operator<< (std::ostream& op, const fp& f); // A number of useful constants. --- 351,372 ---- template void unpack (const T& t); template void pack_any (T& t) const; + public: + fp operator+ (const fp& r) const; + fp operator- (const fp& r) const; + fp operator* (const fp& r) const; + fp operator/ (const fp& r) const; + + bool operator< (const fp& r) const; + bool operator<= (const fp& r) const; + bool operator== (const fp& r) const; + bool operator!= (const fp& r) const; + bool operator>= (const fp& r) const; + bool operator> (const fp& r) const; + friend std::ostream& operator<< (std::ostream& out, const fp& f); }; std::ostream& operator<< (std::ostream& op, const fp& f); // A number of useful constants. *************** namespace sidutil *** 230,235 **** --- 414,431 ---- } inline bool + fp::is_negative () const + { + return (is_number () || is_zero ()) && sign; + } + + inline bool + fp::is_inexact () const + { + return status == inexact; + } + + inline bool fp::is_denorm () const { return fp_class == class_denorm;