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

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

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

Dave Brolley-2
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  <[hidden email]>

        * cgen-fpu.cxx: New file.
        * cgen-fpu.h: New file.
        * Contribute the following enhancements to floating point
        support:
       
        2005-06-14  Dave Brolley  <[hidden email]>

        * 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  <[hidden email]>

        * 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  <[hidden email]>

        * fp.h (fp): All arithmetic operator methods are now members
        of class fp.
        * fp.cxx (fp): Likewise.

        2005-04-27  Dave Brolley  <[hidden email]>

        * fp.cxx (fp::unpack): Only perform sanity check for non-nans.

        2005-04-12  Dave Brolley  <[hidden email]>

        * 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  <[hidden email]>

        * 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
Reply | Threaded
Open this post in threaded view
|

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

Frank Ch. Eigler
Hi -

> [...]  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. [...]

Great.  It will be nice to see the demise of those odd and
occasionally uncompilable macro-function LSMASK32 widgets.

- FChE

attachment0 (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

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

Dave Brolley-2
Frank Ch. Eigler wrote:

>Hi -
>
>  
>
>>[...]  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. [...]
>>    
>>
[typo] The above should read "objects of type fp"

>
>Great.  It will be nice to see the demise of those odd and
>occasionally uncompilable macro-function LSMASK32 widgets.
>
>  
>
Would be nice, but I didn't do it.....

Reply | Threaded
Open this post in threaded view
|

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

Dave Brolley-2
In reply to this post by Dave Brolley-2
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  <[hidden email]>
>
> * cgen-fpu.cxx: New file.
> * cgen-fpu.h: New file.
> * Contribute the following enhancements to floating point
> support:
>
> 2005-06-14  Dave Brolley  <[hidden email]>
>
> * 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  <[hidden email]>
>
> * 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  <[hidden email]>
>
> * fp.h (fp): All arithmetic operator methods are now members
> of class fp.
> * fp.cxx (fp): Likewise.
>
> 2005-04-27  Dave Brolley  <[hidden email]>
>
> * fp.cxx (fp::unpack): Only perform sanity check for non-nans.
>
> 2005-04-12  Dave Brolley  <[hidden email]>
>
> * 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  <[hidden email]>
>
> * 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
>  
>