This is the mail archive of the sid@sourceware.org mailing list for the SID project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch][rfc] CGEN Accurate Floating Point Support for SID


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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]