From: Dave Brolley <brolley@redhat.com>
To: Dave Brolley <brolley@redhat.com>
Cc: sid@sources.redhat.com
Subject: Re: [patch][rfc] CGEN Accurate Floating Point Support for SID
Date: Fri, 19 Aug 2005 21:31:00 -0000 [thread overview]
Message-ID: <43064F8D.40008@redhat.com> (raw)
In-Reply-To: <42EFD5AB.303@redhat.com>
I've committed this patch.
Dave
Dave Brolley wrote:
> Hi,
>
> I'm submitting this patch for approval to commit.
>
> fp.cxx and fp.h have existed in the sid/component/cgen-cpu directory
> for a while, but as far as I can tell, they have not been used. I'm
> working on an internal port which requires simulation of accurate
> floating point support, and so, I've cleaned up these files and
> created two new source files, cgen-fpu.cxx and cgen-fpu.h, in
> sid/component/cgen-cpu which add support for the semantic code which
> CGEN already generates to the cgen-cpu components.
>
> The two new sources are analogous to sim/common/cgen-accfp.c and
> implement the fpu as a virtual class defining operations on objects of
> type f as defined in fp.cxx and fp.h. Not all operations have been
> implemented (only the ones I needed), but the remaining operations
> have at least been prototyped and implementation should be straight
> forward as the need for them arises (similar to cgen-ops.h).
>
> The changes to fp.cxx and fp.h were mainly to virtualize the class in
> order to allow for implementation-defined and non-standard behaviors
> (tested by my internal port). Some clean up was also done and several
> bugs were fixed.
>
> Dave
>
>------------------------------------------------------------------------
>
>2005-08-02 Dave Brolley <brolley@redhat.com>
>
> * cgen-fpu.cxx: New file.
> * cgen-fpu.h: New file.
> * Contribute the following enhancements to floating point
> support:
>
> 2005-06-14 Dave Brolley <brolley@redhat.com>
>
> * fp.h (do_round,do_normal_round,do_normal_underflow,do_normal_overflow):
> Now virtual.
> * fp.cxx (do_normal_overflow): Round up to infinity only if
> the result is positive.
> (operator-): Don't apply 'neg' to a nan.
> (neg): Return src if it is a qnan.
>
> 2005-05-20 Dave Brolley <brolley@redhat.com>
>
> * fp.cxx (pack_any): Ensure that nan results have a positive sign.
> (operator-): Simply call operator+ with the rhs negated.
> * fp.h (is_negative): New method of fp.
>
> 2005-05-13 Dave Brolley <brolley@redhat.com>
>
> * fp.h (fp): All arithmetic operator methods are now members
> of class fp.
> * fp.cxx (fp): Likewise.
>
> 2005-04-27 Dave Brolley <brolley@redhat.com>
>
> * fp.cxx (fp::unpack): Only perform sanity check for non-nans.
>
> 2005-04-12 Dave Brolley <brolley@redhat.com>
>
> * fp.h: Move static constants and functions to top of file for
> visibility within the file.
> (get_status): New method of fp.
> (get_class): Likewise.
> (qnan_fraction): Likewise.
> (snan_fraction): Likewise.
> (qnan_exponent): Likewise.
> (snan_exponent): Likewise.
> * fp.cxx (fp_to_int): throw fp::overflow for overflow.
> (pack_any): Use [sq]nan_{exponent,fraction} to construct nans.
> (unpack): Initialize status to 'ok'. Set class and status using
> is_qnan_fraction and is_qnan respectively.
>
> 2005-03-18 Dave Brolley <brolley@redhat.com>
>
> * fp.cxx: Move static items from here.
> * fp.h: To here. Make some methods virtual. Make private members
> protected.
> (is_inexact): New method.
>
>
>
>------------------------------------------------------------------------
>
>? 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<host_int_8>(-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 <typename T> 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<signed_host_int_8> (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<host_int_8>(-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 <typename T> void unpack (const T& t);
> template <typename T> 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 <typename T> void unpack (const T& t);
> template <typename T> 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;
>
>
>------------------------------------------------------------------------
>
>// cgen-fpu.h - CPU components. -*- C++ -*-
>// CGEN fpu support for SID
>//
>// Copyright (C) 2005 Red Hat.
>// This file is part of SID and is licensed under the GPL.
>// See the file COPYING.SID for conditions for redistribution.
>
>#ifndef CGEN_FPU_H
>#define CGEN_FPU_H
>
>#include "cgen-cpu.h"
>#include "fp.h"
>
>namespace cgen
>{
>/* Floating point support is a little more complicated.
> We want to support using either host fp insns or an accurate fp library.
> We also want to support easily added variants (e.g. modified ieee).
> This is done by using a virtual helper class 'cgen_fp_ops'. */
>class cgen_fpu;
>
>/* fpu operation class */
>class cgen_fp_ops {
>public:
> // default is no error checking
> virtual void check_result (cgen_fpu*, fp &) {}
>
> /* basic SF ops */
> virtual SF addsf (cgen_fpu*, SF, SF);
> virtual SF subsf (cgen_fpu*, SF, SF);
> virtual SF mulsf (cgen_fpu*, SF, SF);
> virtual SF divsf (cgen_fpu*, SF, SF);
> virtual SF negsf (cgen_fpu*, SF);
> virtual SF abssf (cgen_fpu*, SF);
> virtual SF sqrtsf (cgen_fpu*, SF);
>#if 0
> virtual SF invsf (cgen_fpu*, SF);
> virtual SF cossf (cgen_fpu*, SF);
> virtual SF sinsf (cgen_fpu*, SF);
> virtual SF minsf (cgen_fpu*, SF, SF);
> virtual SF maxsf (cgen_fpu*, SF, SF);
>#endif
> virtual int eqsf (cgen_fpu*, SF, SF);
> virtual int nesf (cgen_fpu*, SF, SF);
> virtual int ltsf (cgen_fpu*, SF, SF);
> virtual int lesf (cgen_fpu*, SF, SF);
> virtual int gtsf (cgen_fpu*, SF, SF);
> virtual int gesf (cgen_fpu*, SF, SF);
>
>#if 0
> /* basic DF ops */
> virtual DF adddf (cgen_fpu*, DF, DF);
> virtual DF subdf (cgen_fpu*, DF, DF);
> virtual DF muldf (cgen_fpu*, DF, DF);
> virtual DF divdf (cgen_fpu*, DF, DF);
> virtual DF negdf (cgen_fpu*, DF);
> virtual DF absdf (cgen_fpu*, DF);
> virtual DF sqrtdf (cgen_fpu*, DF);
> virtual DF invdf (cgen_fpu*, DF);
> virtual DF cosdf (cgen_fpu*, DF);
> virtual DF sindf (cgen_fpu*, DF);
> virtual DF mindf (cgen_fpu*, DF, DF);
> virtual DF maxdf (cgen_fpu*, DF, DF);
>
> virtual int eqdf (cgen_fpu*, DF, DF);
> virtual int nedf (cgen_fpu*, DF, DF);
> virtual int ltdf (cgen_fpu*, DF, DF);
> virtual int ledf (cgen_fpu*, DF, DF);
> virtual int gtdf (cgen_fpu*, DF, DF);
> virtual int gedf (cgen_fpu*, DF, DF);
>
> /* SF/DF conversion ops */
> virtual DF fextsfdf (cgen_fpu*, SF);
> virtual SF ftruncdfsf (cgen_fpu*, DF);
>#endif // not implemented yet
>
> virtual SF floatsisf (cgen_fpu*, SI);
>#if 0 // not implemented yet
> virtual SF floatdisf (cgen_fpu*, DI);
> virtual SF ufloatsisf (cgen_fpu*, USI);
> virtual SF ufloatdisf (cgen_fpu*, UDI);
>#endif // not implemented yet
>
> virtual SI fixsfsi (cgen_fpu*, SF);
>#if 0 // not implemented yet
> virtual DI fixsfdi (cgen_fpu*, SF);
> virtual USI ufixsfsi (cgen_fpu*, SF);
> virtual UDI ufixsfdi (cgen_fpu*, SF);
>
> virtual DF floatsidf (cgen_fpu*, SI);
> virtual DF floatdidf (cgen_fpu*, DI);
> virtual DF ufloatsidf (cgen_fpu*, USI);
> virtual DF ufloatdidf (cgen_fpu*, UDI);
>
> virtual SI fixdfsi (cgen_fpu*, DF);
> virtual DI fixdfdi (cgen_fpu*, DF);
> virtual USI ufixdfsi (cgen_fpu*, DF);
> virtual UDI ufixdfdi (cgen_fpu*, DF);
>
> /* XF mode support (kept separate 'cus not always present) */
> virtual XF addxf (cgen_fpu*, XF, XF);
> virtual XF subxf (cgen_fpu*, XF, XF);
> virtual XF mulxf (cgen_fpu*, XF, XF);
> virtual XF divxf (cgen_fpu*, XF, XF);
> virtual XF negxf (cgen_fpu*, XF);
> virtual XF absxf (cgen_fpu*, XF);
> virtual XF sqrtxf (cgen_fpu*, XF);
> virtual XF invxf (cgen_fpu*, XF);
> virtual XF cosxf (cgen_fpu*, XF);
> virtual XF sinxf (cgen_fpu*, XF);
> virtual XF minxf (cgen_fpu*, XF, XF);
> virtual XF maxxf (cgen_fpu*, XF, XF);
>
> virtual int eqxf (cgen_fpu*, XF, XF);
> virtual int nexf (cgen_fpu*, XF, XF);
> virtual int ltxf (cgen_fpu*, XF, XF);
> virtual int lexf (cgen_fpu*, XF, XF);
> virtual int gtxf (cgen_fpu*, XF, XF);
> virtual int gexf (cgen_fpu*, XF, XF);
>
> virtual XF extsfxf (cgen_fpu*, SF);
> virtual XF extdfxf (cgen_fpu*, DF);
> virtual SF truncxfsf (cgen_fpu*, XF);
> virtual DF truncxfdf (cgen_fpu*, XF);
>
> virtual XF floatsixf (cgen_fpu*, SI);
> virtual XF floatdixf (cgen_fpu*, DI);
> virtual XF ufloatsixf (cgen_fpu*, USI);
> virtual XF ufloatdixf (cgen_fpu*, UDI);
>
> virtual SI fixxfsi (cgen_fpu*, XF);
> virtual DI fixxfdi (cgen_fpu*, XF);
> virtual USI ufixxfsi (cgen_fpu*, XF);
> virtual UDI ufixxfdi (cgen_fpu*, XF);
>
> /* TF mode support (kept separate 'cus not always present) */
> virtual TF addtf (cgen_fpu*, TF, TF);
> virtual TF subtf (cgen_fpu*, TF, TF);
> virtual TF multf (cgen_fpu*, TF, TF);
> virtual TF divtf (cgen_fpu*, TF, TF);
> virtual TF negtf (cgen_fpu*, TF);
> virtual TF abstf (cgen_fpu*, TF);
> virtual TF sqrttf (cgen_fpu*, TF);
> virtual TF invtf (cgen_fpu*, TF);
> virtual TF costf (cgen_fpu*, TF);
> virtual TF sintf (cgen_fpu*, TF);
> virtual TF mintf (cgen_fpu*, TF, TF);
> virtual TF maxtf (cgen_fpu*, TF, TF);
>
> virtual int eqtf (cgen_fpu*, TF, TF);
> virtual int netf (cgen_fpu*, TF, TF);
> virtual int lttf (cgen_fpu*, TF, TF);
> virtual int letf (cgen_fpu*, TF, TF);
> virtual int gttf (cgen_fpu*, TF, TF);
> virtual int getf (cgen_fpu*, TF, TF);
>
> virtual TF extsftf (cgen_fpu*, SF);
> virtual TF extdftf (cgen_fpu*, DF);
> virtual SF trunctfsf (cgen_fpu*, TF);
> virtual DF trunctfdf (cgen_fpu*, TF);
>
> virtual TF floatsitf (cgen_fpu*, SI);
> virtual TF floatditf (cgen_fpu*, DI);
> virtual TF ufloatsitf (cgen_fpu*, USI);
> virtual TF ufloatditf (cgen_fpu*, UDI);
>
> virtual SI fixtfsi (cgen_fpu*, TF);
> virtual DI fixtfdi (cgen_fpu*, TF);
> virtual USI ufixtfsi (cgen_fpu*, TF);
> virtual UDI ufixtfdi (cgen_fpu*, TF);
>#endif // not implemented yet
>};
>
>/* Instance of an fpu. */
>class cgen_fpu {
> public:
> cgen_fpu (cgen_bi_endian_cpu *c, cgen_fp_ops *o) : owner (c), ops (o) {}
> cgen_bi_endian_cpu* owner;
> cgen_fp_ops* ops;
>};
>
>}; // namespace cgen
>
>#endif /* CGEN_FPU_H */
>
>
>------------------------------------------------------------------------
>
>// cgen-fpu.cxx - CPU components. -*- C++ -*-
>// CGEN fpu support for SID
>//
>// Copyright (C) 2005 Red Hat.
>// This file is part of SID and is licensed under the GPL.
>// See the file COPYING.SID for conditions for redistribution.
>
>#include "cgen-fpu.h"
>#include "fp.h"
>
>using namespace sidutil;
>
>namespace cgen
>{
>/* basic SF ops */
>SF
>cgen_fp_ops::addsf (cgen_fpu* fpu, SF x, SF y)
>{
> fp r = fp (x) + fp (y);
> check_result (fpu, r);
> SF tmp;
> r.pack (tmp);
> return tmp;
>}
>
>SF cgen_fp_ops::subsf (cgen_fpu* fpu, SF x, SF y)
>{
> fp r = fp (x) - fp (y);
> check_result (fpu, r);
> SF tmp;
> r.pack (tmp);
> return tmp;
>}
>
>SF cgen_fp_ops::mulsf (cgen_fpu* fpu, SF x, SF y)
>{
> fp r = fp (x) * fp (y);
> check_result (fpu, r);
> SF tmp;
> r.pack (tmp);
> return tmp;
>}
>
>SF cgen_fp_ops::divsf (cgen_fpu* fpu, SF x, SF y)
>{
> fp r = fp (x) / fp (y);
> check_result (fpu, r);
> SF tmp;
> r.pack (tmp);
> return tmp;
>}
>
>SF cgen_fp_ops::negsf (cgen_fpu* fpu, SF x)
>{
> fp r (x);
> r = fp::neg (r);
> check_result (fpu, r);
> SF tmp;
> r.pack (tmp);
> return tmp;
>}
>
>SF cgen_fp_ops::abssf (cgen_fpu* fpu, SF x)
>{
> fp r (x);
> r = fp::abs (r);
> check_result (fpu, r);
> SF tmp;
> r.pack (tmp);
> return tmp;
>}
>
>SF cgen_fp_ops::sqrtsf (cgen_fpu* fpu, SF x)
>{
> fp r (x);
> r = fp::sqrt (r);
> check_result (fpu, r);
> SF tmp;
> r.pack (tmp);
> return tmp;
>}
>
>
>#if 0 // not implemented yet
>SF cgen_fp_ops::invsf (cgen_fpu*, SF);
>SF cgen_fp_ops::cossf (cgen_fpu*, SF);
>SF cgen_fp_ops::sinsf (cgen_fpu*, SF);
>SF cgen_fp_ops::minsf (cgen_fpu*, SF, SF);
>SF cgen_fp_ops::maxsf (cgen_fpu*, SF, SF);
>#endif
>
>int cgen_fp_ops::eqsf (cgen_fpu*, SF x, SF y)
>{
> return fp (x) == fp (y);
>}
>int cgen_fp_ops::nesf (cgen_fpu*, SF x, SF y)
>{
> return fp (x) != fp (y);
>}
>int cgen_fp_ops::ltsf (cgen_fpu*, SF x, SF y)
>{
> return fp (x) < fp (y);
>}
>int cgen_fp_ops::lesf (cgen_fpu*, SF x, SF y)
>{
> return fp (x) <= fp (y);
>}
>int cgen_fp_ops::gtsf (cgen_fpu*, SF x, SF y)
>{
> return fp (x) > fp (y);
>}
>int cgen_fp_ops::gesf (cgen_fpu*, SF x, SF y)
>{
> return fp (x) >= fp (y);
>}
>
>#if 0
>/* basic DF ops */
>DF cgen_fp_ops::adddf (cgen_fpu*, DF, DF);
>DF cgen_fp_ops::subdf (cgen_fpu*, DF, DF);
>DF cgen_fp_ops::muldf (cgen_fpu*, DF, DF);
>DF cgen_fp_ops::divdf (cgen_fpu*, DF, DF);
>DF cgen_fp_ops::negdf (cgen_fpu*, DF);
>DF cgen_fp_ops::absdf (cgen_fpu*, DF);
>DF cgen_fp_ops::sqrtdf (cgen_fpu*, DF);
>DF cgen_fp_ops::invdf (cgen_fpu*, DF);
>DF cgen_fp_ops::cosdf (cgen_fpu*, DF);
>DF cgen_fp_ops::sindf (cgen_fpu*, DF);
>DF cgen_fp_ops::mindf (cgen_fpu*, DF, DF);
>DF cgen_fp_ops::maxdf (cgen_fpu*, DF, DF);
>
>int cgen_fp_ops::eqdf (cgen_fpu*, DF, DF);
>int cgen_fp_ops::nedf (cgen_fpu*, DF, DF);
>int cgen_fp_ops::ltdf (cgen_fpu*, DF, DF);
>int cgen_fp_ops::ledf (cgen_fpu*, DF, DF);
>int cgen_fp_ops::gtdf (cgen_fpu*, DF, DF);
>int cgen_fp_ops::gedf (cgen_fpu*, DF, DF);
>
> /* SF/DF conversion ops */
>DF cgen_fp_ops::fextsfdf (cgen_fpu*, SF);
>SF cgen_fp_ops::ftruncdfsf (cgen_fpu*, DF);
>
>#endif // not implemented yet
>SF cgen_fp_ops::floatsisf (cgen_fpu* fpu, SI x)
>{
> fp r = fp::from_int (x);
> check_result (fpu, r);
> SF tmp;
> r.pack (tmp);
> return tmp;
>}
>#if 0 // not implemented yet
>SF cgen_fp_ops::floatdisf (cgen_fpu*, DI);
>SF cgen_fp_ops::ufloatsisf (cgen_fpu*, USI);
>SF cgen_fp_ops::ufloatdisf (cgen_fpu*, UDI);
>#endif // not implemented yet
>
>SI cgen_fp_ops::fixsfsi (cgen_fpu*, SF x)
>{
> fp r (x);
> unsigned int tmp;
> r.integer (tmp, fp::round_default);
> return tmp;
>}
>#if 0 // not implemented yet
>DI cgen_fp_ops::fixsfdi (cgen_fpu*, SF);
>USI cgen_fp_ops::ufixsfsi (cgen_fpu*, SF)
>UDI cgen_fp_ops::ufixsfdi (cgen_fpu*, SF);
>
>DF cgen_fp_ops::floatsidf (cgen_fpu*, SI);
>DF cgen_fp_ops::floatdidf (cgen_fpu*, DI);
>DF cgen_fp_ops::ufloatsidf (cgen_fpu*, USI);
>DF cgen_fp_ops::ufloatdidf (cgen_fpu*, UDI);
>
>SI cgen_fp_ops::fixdfsi (cgen_fpu*, DF);
>DI cgen_fp_ops::fixdfdi (cgen_fpu*, DF);
>USI cgen_fp_ops::ufixdfsi (cgen_fpu*, DF);
>UDI cgen_fp_ops::ufixdfdi (cgen_fpu*, DF);
>
>/* XF mode support (kept separate 'cus not always present) */
>XF cgen_fp_ops::addxf (cgen_fpu*, XF, XF);
>XF cgen_fp_ops::subxf (cgen_fpu*, XF, XF);
>XF cgen_fp_ops::mulxf (cgen_fpu*, XF, XF);
>XF cgen_fp_ops::divxf (cgen_fpu*, XF, XF);
>XF cgen_fp_ops::negxf (cgen_fpu*, XF);
>XF cgen_fp_ops::absxf (cgen_fpu*, XF);
>XF cgen_fp_ops::sqrtxf (cgen_fpu*, XF);
>XF cgen_fp_ops::invxf (cgen_fpu*, XF);
>XF cgen_fp_ops::cosxf (cgen_fpu*, XF);
>XF cgen_fp_ops::sinxf (cgen_fpu*, XF);
>XF cgen_fp_ops::minxf (cgen_fpu*, XF, XF);
>XF cgen_fp_ops::maxxf (cgen_fpu*, XF, XF);
>
>int cgen_fp_ops::eqxf (cgen_fpu*, XF, XF);
>int cgen_fp_ops::nexf (cgen_fpu*, XF, XF);
>int cgen_fp_ops::ltxf (cgen_fpu*, XF, XF);
>int cgen_fp_ops::lexf (cgen_fpu*, XF, XF);
>int cgen_fp_ops::gtxf (cgen_fpu*, XF, XF);
>int cgen_fp_ops::gexf (cgen_fpu*, XF, XF);
>
>XF cgen_fp_ops::extsfxf (cgen_fpu*, SF);
>XF cgen_fp_ops::extdfxf (cgen_fpu*, DF);
>SF cgen_fp_ops::truncxfsf (cgen_fpu*, XF);
>DF cgen_fp_ops::truncxfdf (cgen_fpu*, XF);
>
>XF cgen_fp_ops::floatsixf (cgen_fpu*, SI);
>XF cgen_fp_ops::floatdixf (cgen_fpu*, DI);
>XF cgen_fp_ops::ufloatsixf (cgen_fpu*, USI);
>XF cgen_fp_ops::ufloatdixf (cgen_fpu*, UDI);
>
>SI cgen_fp_ops::fixxfsi (cgen_fpu*, XF);
>DI cgen_fp_ops::fixxfdi (cgen_fpu*, XF);
>USI cgen_fp_ops::ufixxfsi (cgen_fpu*, XF);
>UDI cgen_fp_ops::ufixxfdi (cgen_fpu*, XF);
>
>/* TF mode support (kept separate 'cus not always present) */
>TF cgen_fp_ops::addtf (cgen_fpu*, TF, TF);
>TF cgen_fp_ops::subtf (cgen_fpu*, TF, TF);
>TF cgen_fp_ops::multf (cgen_fpu*, TF, TF);
>TF cgen_fp_ops::divtf (cgen_fpu*, TF, TF);
>TF cgen_fp_ops::negtf (cgen_fpu*, TF);
>TF cgen_fp_ops::abstf (cgen_fpu*, TF);
>TF cgen_fp_ops::sqrttf (cgen_fpu*, TF);
>TF cgen_fp_ops::invtf (cgen_fpu*, TF);
>TF cgen_fp_ops::costf (cgen_fpu*, TF);
>TF cgen_fp_ops::sintf (cgen_fpu*, TF);
>TF cgen_fp_ops::mintf (cgen_fpu*, TF, TF);
>TF cgen_fp_ops::maxtf (cgen_fpu*, TF, TF);
>
>int cgen_fp_ops::eqtf (cgen_fpu*, TF, TF);
>int cgen_fp_ops::netf (cgen_fpu*, TF, TF);
>int cgen_fp_ops::lttf (cgen_fpu*, TF, TF);
>int cgen_fp_ops::letf (cgen_fpu*, TF, TF);
>int cgen_fp_ops::gttf (cgen_fpu*, TF, TF);
>int cgen_fp_ops::getf (cgen_fpu*, TF, TF);
>
>TF cgen_fp_ops::extsftf (cgen_fpu*, SF);
>TF cgen_fp_ops::extdftf (cgen_fpu*, DF);
>SF cgen_fp_ops::trunctfsf (cgen_fpu*, TF);
>DF cgen_fp_ops::trunctfdf (cgen_fpu*, TF);
>
>TF cgen_fp_ops::floatsitf (cgen_fpu*, SI);
>TF cgen_fp_ops::floatditf (cgen_fpu*, DI);
>TF cgen_fp_ops::ufloatsitf (cgen_fpu*, USI);
>TF cgen_fp_ops::ufloatditf (cgen_fpu*, UDI);
>
>SI cgen_fp_ops::fixtfsi (cgen_fpu*, TF);
>DI cgen_fp_ops::fixtfdi (cgen_fpu*, TF);
>USI cgen_fp_ops::ufixtfsi (cgen_fpu*, TF);
>UDI cgen_fp_ops::ufixtfdi (cgen_fpu*, TF);
>#endif // not implemented yet
>
>}; // namespace cgen
>
>
prev parent reply other threads:[~2005-08-19 21:31 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-08-02 20:21 Dave Brolley
2005-08-02 20:29 ` Frank Ch. Eigler
2005-08-02 20:39 ` Dave Brolley
2005-08-19 21:31 ` Dave Brolley [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=43064F8D.40008@redhat.com \
--to=brolley@redhat.com \
--cc=sid@sources.redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).