OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [ppc/] [dp-bit.c] - Diff between revs 24 and 157

Only display areas with differences | Details | Blame | View Log

Rev 24 Rev 157
/* This is a software floating point library which can be used instead of
/* This is a software floating point library which can be used instead of
   the floating point routines in libgcc1.c for targets without hardware
   the floating point routines in libgcc1.c for targets without hardware
   floating point.  */
   floating point.  */
 
 
/* Copyright (C) 1994, 2007, 2008 Free Software Foundation, Inc.
/* Copyright (C) 1994, 2007, 2008 Free Software Foundation, Inc.
 
 
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
/* As a special exception, if you link this library with other files,
/* As a special exception, if you link this library with other files,
   some of which are compiled with GCC, to produce an executable,
   some of which are compiled with GCC, to produce an executable,
   this library does not by itself cause the resulting executable
   this library does not by itself cause the resulting executable
   to be covered by the GNU General Public License.
   to be covered by the GNU General Public License.
   This exception does not however invalidate any other reasons why
   This exception does not however invalidate any other reasons why
   the executable file might be covered by the GNU General Public License.  */
   the executable file might be covered by the GNU General Public License.  */
 
 
/* This implements IEEE 754 format arithmetic, but does not provide a
/* This implements IEEE 754 format arithmetic, but does not provide a
   mechanism for setting the rounding mode, or for generating or handling
   mechanism for setting the rounding mode, or for generating or handling
   exceptions.
   exceptions.
 
 
   The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
   The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
   Wilson, all of Cygnus Support.  */
   Wilson, all of Cygnus Support.  */
 
 
/* The intended way to use this file is to make two copies, add `#define FLOAT'
/* The intended way to use this file is to make two copies, add `#define FLOAT'
   to one copy, then compile both copies and add them to libgcc.a.  */
   to one copy, then compile both copies and add them to libgcc.a.  */
 
 
/* The following macros can be defined to change the behaviour of this file:
/* The following macros can be defined to change the behaviour of this file:
   FLOAT: Implement a `float', aka SFmode, fp library.  If this is not
   FLOAT: Implement a `float', aka SFmode, fp library.  If this is not
     defined, then this file implements a `double', aka DFmode, fp library.
     defined, then this file implements a `double', aka DFmode, fp library.
   FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
   FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
     don't include float->double conversion which requires the double library.
     don't include float->double conversion which requires the double library.
     This is useful only for machines which can't support doubles, e.g. some
     This is useful only for machines which can't support doubles, e.g. some
     8-bit processors.
     8-bit processors.
   CMPtype: Specify the type that floating point compares should return.
   CMPtype: Specify the type that floating point compares should return.
     This defaults to SItype, aka int.
     This defaults to SItype, aka int.
   US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
   US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
     US Software goFast library.  If this is not defined, the entry points use
     US Software goFast library.  If this is not defined, the entry points use
     the same names as libgcc1.c.
     the same names as libgcc1.c.
   _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
   _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
     two integers to the FLO_union_type.
     two integers to the FLO_union_type.
   NO_NANS: Disable nan and infinity handling
   NO_NANS: Disable nan and infinity handling
   SMALL_MACHINE: Useful when operations on QIs and HIs are faster
   SMALL_MACHINE: Useful when operations on QIs and HIs are faster
     than on an SI */
     than on an SI */
 
 
#ifndef SFtype
#ifndef SFtype
typedef SFtype __attribute__ ((mode (SF)));
typedef SFtype __attribute__ ((mode (SF)));
#endif
#endif
#ifndef DFtype
#ifndef DFtype
typedef DFtype __attribute__ ((mode (DF)));
typedef DFtype __attribute__ ((mode (DF)));
#endif
#endif
 
 
#ifndef HItype
#ifndef HItype
typedef int HItype __attribute__ ((mode (HI)));
typedef int HItype __attribute__ ((mode (HI)));
#endif
#endif
#ifndef SItype
#ifndef SItype
typedef int SItype __attribute__ ((mode (SI)));
typedef int SItype __attribute__ ((mode (SI)));
#endif
#endif
#ifndef DItype
#ifndef DItype
typedef int DItype __attribute__ ((mode (DI)));
typedef int DItype __attribute__ ((mode (DI)));
#endif
#endif
 
 
/* The type of the result of a fp compare */
/* The type of the result of a fp compare */
#ifndef CMPtype
#ifndef CMPtype
#define CMPtype SItype
#define CMPtype SItype
#endif
#endif
 
 
#ifndef UHItype
#ifndef UHItype
typedef unsigned int UHItype __attribute__ ((mode (HI)));
typedef unsigned int UHItype __attribute__ ((mode (HI)));
#endif
#endif
#ifndef USItype
#ifndef USItype
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
#endif
#endif
#ifndef UDItype
#ifndef UDItype
typedef unsigned int UDItype __attribute__ ((mode (DI)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
#endif
#endif
 
 
#define MAX_SI_INT   ((SItype) ((unsigned) (~0)>>1))
#define MAX_SI_INT   ((SItype) ((unsigned) (~0)>>1))
#define MAX_USI_INT  ((USItype) ~0)
#define MAX_USI_INT  ((USItype) ~0)
 
 
 
 
#ifdef FLOAT_ONLY
#ifdef FLOAT_ONLY
#define NO_DI_MODE
#define NO_DI_MODE
#endif
#endif
 
 
#ifdef FLOAT
#ifdef FLOAT
#       define NGARDS    7L
#       define NGARDS    7L
#       define GARDROUND 0x3f
#       define GARDROUND 0x3f
#       define GARDMASK  0x7f
#       define GARDMASK  0x7f
#       define GARDMSB   0x40
#       define GARDMSB   0x40
#       define EXPBITS 8
#       define EXPBITS 8
#       define EXPBIAS 127
#       define EXPBIAS 127
#       define FRACBITS 23
#       define FRACBITS 23
#       define EXPMAX (0xff)
#       define EXPMAX (0xff)
#       define QUIET_NAN 0x100000L
#       define QUIET_NAN 0x100000L
#       define FRAC_NBITS 32
#       define FRAC_NBITS 32
#       define FRACHIGH  0x80000000L
#       define FRACHIGH  0x80000000L
#       define FRACHIGH2 0xc0000000L
#       define FRACHIGH2 0xc0000000L
        typedef USItype fractype;
        typedef USItype fractype;
        typedef UHItype halffractype;
        typedef UHItype halffractype;
        typedef SFtype FLO_type;
        typedef SFtype FLO_type;
        typedef SItype intfrac;
        typedef SItype intfrac;
 
 
#else
#else
#       define PREFIXFPDP dp
#       define PREFIXFPDP dp
#       define PREFIXSFDF df
#       define PREFIXSFDF df
#       define NGARDS 8L
#       define NGARDS 8L
#       define GARDROUND 0x7f
#       define GARDROUND 0x7f
#       define GARDMASK  0xff
#       define GARDMASK  0xff
#       define GARDMSB   0x80
#       define GARDMSB   0x80
#       define EXPBITS 11
#       define EXPBITS 11
#       define EXPBIAS 1023
#       define EXPBIAS 1023
#       define FRACBITS 52
#       define FRACBITS 52
#       define EXPMAX (0x7ff)
#       define EXPMAX (0x7ff)
#       define QUIET_NAN 0x8000000000000LL
#       define QUIET_NAN 0x8000000000000LL
#       define FRAC_NBITS 64
#       define FRAC_NBITS 64
#       define FRACHIGH  0x8000000000000000LL
#       define FRACHIGH  0x8000000000000000LL
#       define FRACHIGH2 0xc000000000000000LL
#       define FRACHIGH2 0xc000000000000000LL
        typedef UDItype fractype;
        typedef UDItype fractype;
        typedef USItype halffractype;
        typedef USItype halffractype;
        typedef DFtype FLO_type;
        typedef DFtype FLO_type;
        typedef DItype intfrac;
        typedef DItype intfrac;
#endif
#endif
 
 
#ifdef US_SOFTWARE_GOFAST
#ifdef US_SOFTWARE_GOFAST
#       ifdef FLOAT
#       ifdef FLOAT
#               define add              fpadd
#               define add              fpadd
#               define sub              fpsub
#               define sub              fpsub
#               define multiply         fpmul
#               define multiply         fpmul
#               define divide           fpdiv
#               define divide           fpdiv
#               define compare          fpcmp
#               define compare          fpcmp
#               define si_to_float      sitofp
#               define si_to_float      sitofp
#               define float_to_si      fptosi
#               define float_to_si      fptosi
#               define float_to_usi     fptoui
#               define float_to_usi     fptoui
#               define negate           __negsf2
#               define negate           __negsf2
#               define sf_to_df         fptodp
#               define sf_to_df         fptodp
#               define dptofp           dptofp
#               define dptofp           dptofp
#else
#else
#               define add              dpadd
#               define add              dpadd
#               define sub              dpsub
#               define sub              dpsub
#               define multiply         dpmul
#               define multiply         dpmul
#               define divide           dpdiv
#               define divide           dpdiv
#               define compare          dpcmp
#               define compare          dpcmp
#               define si_to_float      litodp
#               define si_to_float      litodp
#               define float_to_si      dptoli
#               define float_to_si      dptoli
#               define float_to_usi     dptoul
#               define float_to_usi     dptoul
#               define negate           __negdf2
#               define negate           __negdf2
#               define df_to_sf         dptofp
#               define df_to_sf         dptofp
#endif
#endif
#else
#else
#       ifdef FLOAT
#       ifdef FLOAT
#               define add              __addsf3
#               define add              __addsf3
#               define sub              __subsf3
#               define sub              __subsf3
#               define multiply         __mulsf3
#               define multiply         __mulsf3
#               define divide           __divsf3
#               define divide           __divsf3
#               define compare          __cmpsf2
#               define compare          __cmpsf2
#               define _eq_f2           __eqsf2
#               define _eq_f2           __eqsf2
#               define _ne_f2           __nesf2
#               define _ne_f2           __nesf2
#               define _gt_f2           __gtsf2
#               define _gt_f2           __gtsf2
#               define _ge_f2           __gesf2
#               define _ge_f2           __gesf2
#               define _lt_f2           __ltsf2
#               define _lt_f2           __ltsf2
#               define _le_f2           __lesf2
#               define _le_f2           __lesf2
#               define si_to_float      __floatsisf
#               define si_to_float      __floatsisf
#               define float_to_si      __fixsfsi
#               define float_to_si      __fixsfsi
#               define float_to_usi     __fixunssfsi
#               define float_to_usi     __fixunssfsi
#               define negate           __negsf2
#               define negate           __negsf2
#               define sf_to_df         __extendsfdf2
#               define sf_to_df         __extendsfdf2
#else
#else
#               define add              __adddf3
#               define add              __adddf3
#               define sub              __subdf3
#               define sub              __subdf3
#               define multiply         __muldf3
#               define multiply         __muldf3
#               define divide           __divdf3
#               define divide           __divdf3
#               define compare          __cmpdf2
#               define compare          __cmpdf2
#               define _eq_f2           __eqdf2
#               define _eq_f2           __eqdf2
#               define _ne_f2           __nedf2
#               define _ne_f2           __nedf2
#               define _gt_f2           __gtdf2
#               define _gt_f2           __gtdf2
#               define _ge_f2           __gedf2
#               define _ge_f2           __gedf2
#               define _lt_f2           __ltdf2
#               define _lt_f2           __ltdf2
#               define _le_f2           __ledf2
#               define _le_f2           __ledf2
#               define si_to_float      __floatsidf
#               define si_to_float      __floatsidf
#               define float_to_si      __fixdfsi
#               define float_to_si      __fixdfsi
#               define float_to_usi     __fixunsdfsi
#               define float_to_usi     __fixunsdfsi
#               define negate           __negdf2
#               define negate           __negdf2
#               define df_to_sf         __truncdfsf2
#               define df_to_sf         __truncdfsf2
#       endif
#       endif
#endif
#endif
 
 
 
 
#ifndef INLINE
#ifndef INLINE
#define INLINE __inline__
#define INLINE __inline__
#endif
#endif
 
 
/* Preserve the sticky-bit when shifting fractions to the right.  */
/* Preserve the sticky-bit when shifting fractions to the right.  */
#define LSHIFT(a) { a = (a & 1) | (a >> 1); }
#define LSHIFT(a) { a = (a & 1) | (a >> 1); }
 
 
/* numeric parameters */
/* numeric parameters */
/* F_D_BITOFF is the number of bits offset between the MSB of the mantissa
/* F_D_BITOFF is the number of bits offset between the MSB of the mantissa
   of a float and of a double. Assumes there are only two float types.
   of a float and of a double. Assumes there are only two float types.
   (double::FRAC_BITS+double::NGARGS-(float::FRAC_BITS-float::NGARDS))
   (double::FRAC_BITS+double::NGARGS-(float::FRAC_BITS-float::NGARDS))
 */
 */
#define F_D_BITOFF (52+8-(23+7))
#define F_D_BITOFF (52+8-(23+7))
 
 
 
 
#define NORMAL_EXPMIN (-(EXPBIAS)+1)
#define NORMAL_EXPMIN (-(EXPBIAS)+1)
#define IMPLICIT_1 (1LL<<(FRACBITS+NGARDS))
#define IMPLICIT_1 (1LL<<(FRACBITS+NGARDS))
#define IMPLICIT_2 (1LL<<(FRACBITS+1+NGARDS))
#define IMPLICIT_2 (1LL<<(FRACBITS+1+NGARDS))
 
 
/* common types */
/* common types */
 
 
typedef enum
typedef enum
{
{
  CLASS_SNAN,
  CLASS_SNAN,
  CLASS_QNAN,
  CLASS_QNAN,
  CLASS_ZERO,
  CLASS_ZERO,
  CLASS_NUMBER,
  CLASS_NUMBER,
  CLASS_INFINITY
  CLASS_INFINITY
} fp_class_type;
} fp_class_type;
 
 
typedef struct
typedef struct
{
{
#ifdef SMALL_MACHINE
#ifdef SMALL_MACHINE
  char class;
  char class;
  unsigned char sign;
  unsigned char sign;
  short normal_exp;
  short normal_exp;
#else
#else
  fp_class_type class;
  fp_class_type class;
  unsigned int sign;
  unsigned int sign;
  int normal_exp;
  int normal_exp;
#endif
#endif
 
 
  union
  union
    {
    {
      fractype ll;
      fractype ll;
      halffractype l[2];
      halffractype l[2];
    } fraction;
    } fraction;
} fp_number_type;
} fp_number_type;
 
 
typedef union
typedef union
{
{
  FLO_type value;
  FLO_type value;
#ifdef _DEBUG_BITFLOAT
#ifdef _DEBUG_BITFLOAT
  int l[2];
  int l[2];
#endif
#endif
  struct
  struct
    {
    {
#ifndef FLOAT_BIT_ORDER_MISMATCH
#ifndef FLOAT_BIT_ORDER_MISMATCH
      unsigned int sign:1 __attribute__ ((packed));
      unsigned int sign:1 __attribute__ ((packed));
      unsigned int exp:EXPBITS __attribute__ ((packed));
      unsigned int exp:EXPBITS __attribute__ ((packed));
      fractype fraction:FRACBITS __attribute__ ((packed));
      fractype fraction:FRACBITS __attribute__ ((packed));
#else
#else
      fractype fraction:FRACBITS __attribute__ ((packed));
      fractype fraction:FRACBITS __attribute__ ((packed));
      unsigned int exp:EXPBITS __attribute__ ((packed));
      unsigned int exp:EXPBITS __attribute__ ((packed));
      unsigned int sign:1 __attribute__ ((packed));
      unsigned int sign:1 __attribute__ ((packed));
#endif
#endif
    }
    }
  bits;
  bits;
}
}
FLO_union_type;
FLO_union_type;
 
 
 
 
/* end of header */
/* end of header */
 
 
/* IEEE "special" number predicates */
/* IEEE "special" number predicates */
 
 
#ifdef NO_NANS
#ifdef NO_NANS
 
 
#define nan() 0
#define nan() 0
#define isnan(x) 0
#define isnan(x) 0
#define isinf(x) 0
#define isinf(x) 0
#else
#else
 
 
INLINE
INLINE
static fp_number_type *
static fp_number_type *
nan ()
nan ()
{
{
  static fp_number_type thenan;
  static fp_number_type thenan;
 
 
  return &thenan;
  return &thenan;
}
}
 
 
INLINE
INLINE
static int
static int
isnan ( fp_number_type *  x)
isnan ( fp_number_type *  x)
{
{
  return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
  return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
}
}
 
 
INLINE
INLINE
static int
static int
isinf ( fp_number_type *  x)
isinf ( fp_number_type *  x)
{
{
  return x->class == CLASS_INFINITY;
  return x->class == CLASS_INFINITY;
}
}
 
 
#endif
#endif
 
 
INLINE
INLINE
static int
static int
iszero ( fp_number_type *  x)
iszero ( fp_number_type *  x)
{
{
  return x->class == CLASS_ZERO;
  return x->class == CLASS_ZERO;
}
}
 
 
INLINE
INLINE
static void
static void
flip_sign ( fp_number_type *  x)
flip_sign ( fp_number_type *  x)
{
{
  x->sign = !x->sign;
  x->sign = !x->sign;
}
}
 
 
static FLO_type
static FLO_type
pack_d ( fp_number_type *  src)
pack_d ( fp_number_type *  src)
{
{
  FLO_union_type dst;
  FLO_union_type dst;
  fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
  fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
 
 
  dst.bits.sign = src->sign;
  dst.bits.sign = src->sign;
 
 
  if (isnan (src))
  if (isnan (src))
    {
    {
      dst.bits.exp = EXPMAX;
      dst.bits.exp = EXPMAX;
      dst.bits.fraction = src->fraction.ll;
      dst.bits.fraction = src->fraction.ll;
      if (src->class == CLASS_QNAN || 1)
      if (src->class == CLASS_QNAN || 1)
        {
        {
          dst.bits.fraction |= QUIET_NAN;
          dst.bits.fraction |= QUIET_NAN;
        }
        }
    }
    }
  else if (isinf (src))
  else if (isinf (src))
    {
    {
      dst.bits.exp = EXPMAX;
      dst.bits.exp = EXPMAX;
      dst.bits.fraction = 0;
      dst.bits.fraction = 0;
    }
    }
  else if (iszero (src))
  else if (iszero (src))
    {
    {
      dst.bits.exp = 0;
      dst.bits.exp = 0;
      dst.bits.fraction = 0;
      dst.bits.fraction = 0;
    }
    }
  else if (fraction == 0)
  else if (fraction == 0)
    {
    {
      dst.value = 0;
      dst.value = 0;
    }
    }
  else
  else
    {
    {
      if (src->normal_exp < NORMAL_EXPMIN)
      if (src->normal_exp < NORMAL_EXPMIN)
        {
        {
          /* This number's exponent is too low to fit into the bits
          /* This number's exponent is too low to fit into the bits
             available in the number, so we'll store 0 in the exponent and
             available in the number, so we'll store 0 in the exponent and
             shift the fraction to the right to make up for it.  */
             shift the fraction to the right to make up for it.  */
 
 
          int shift = NORMAL_EXPMIN - src->normal_exp;
          int shift = NORMAL_EXPMIN - src->normal_exp;
 
 
          dst.bits.exp = 0;
          dst.bits.exp = 0;
 
 
          if (shift > FRAC_NBITS - NGARDS)
          if (shift > FRAC_NBITS - NGARDS)
            {
            {
              /* No point shifting, since it's more that 64 out.  */
              /* No point shifting, since it's more that 64 out.  */
              fraction = 0;
              fraction = 0;
            }
            }
          else
          else
            {
            {
              /* Shift by the value */
              /* Shift by the value */
              fraction >>= shift;
              fraction >>= shift;
            }
            }
          fraction >>= NGARDS;
          fraction >>= NGARDS;
          dst.bits.fraction = fraction;
          dst.bits.fraction = fraction;
        }
        }
      else if (src->normal_exp > EXPBIAS)
      else if (src->normal_exp > EXPBIAS)
        {
        {
          dst.bits.exp = EXPMAX;
          dst.bits.exp = EXPMAX;
          dst.bits.fraction = 0;
          dst.bits.fraction = 0;
        }
        }
      else
      else
        {
        {
          dst.bits.exp = src->normal_exp + EXPBIAS;
          dst.bits.exp = src->normal_exp + EXPBIAS;
          /* IF the gard bits are the all zero, but the first, then we're
          /* IF the gard bits are the all zero, but the first, then we're
             half way between two numbers, choose the one which makes the
             half way between two numbers, choose the one which makes the
             lsb of the answer 0.  */
             lsb of the answer 0.  */
          if ((fraction & GARDMASK) == GARDMSB)
          if ((fraction & GARDMASK) == GARDMSB)
            {
            {
              if (fraction & (1 << NGARDS))
              if (fraction & (1 << NGARDS))
                fraction += GARDROUND + 1;
                fraction += GARDROUND + 1;
            }
            }
          else
          else
            {
            {
              /* Add a one to the guards to round up */
              /* Add a one to the guards to round up */
              fraction += GARDROUND;
              fraction += GARDROUND;
            }
            }
          if (fraction >= IMPLICIT_2)
          if (fraction >= IMPLICIT_2)
            {
            {
              fraction >>= 1;
              fraction >>= 1;
              dst.bits.exp += 1;
              dst.bits.exp += 1;
            }
            }
          fraction >>= NGARDS;
          fraction >>= NGARDS;
          dst.bits.fraction = fraction;
          dst.bits.fraction = fraction;
        }
        }
    }
    }
  return dst.value;
  return dst.value;
}
}
 
 
static void
static void
unpack_d (FLO_union_type * src, fp_number_type * dst)
unpack_d (FLO_union_type * src, fp_number_type * dst)
{
{
  fractype fraction = src->bits.fraction;
  fractype fraction = src->bits.fraction;
 
 
  dst->sign = src->bits.sign;
  dst->sign = src->bits.sign;
  if (src->bits.exp == 0)
  if (src->bits.exp == 0)
    {
    {
      /* Hmm.  Looks like 0 */
      /* Hmm.  Looks like 0 */
      if (fraction == 0)
      if (fraction == 0)
        {
        {
          /* tastes like zero */
          /* tastes like zero */
          dst->class = CLASS_ZERO;
          dst->class = CLASS_ZERO;
        }
        }
      else
      else
        {
        {
          /* Zero exponent with non zero fraction - it's denormalized,
          /* Zero exponent with non zero fraction - it's denormalized,
             so there isn't a leading implicit one - we'll shift it so
             so there isn't a leading implicit one - we'll shift it so
             it gets one.  */
             it gets one.  */
          dst->normal_exp = src->bits.exp - EXPBIAS + 1;
          dst->normal_exp = src->bits.exp - EXPBIAS + 1;
          fraction <<= NGARDS;
          fraction <<= NGARDS;
 
 
          dst->class = CLASS_NUMBER;
          dst->class = CLASS_NUMBER;
#if 1
#if 1
          while (fraction < IMPLICIT_1)
          while (fraction < IMPLICIT_1)
            {
            {
              fraction <<= 1;
              fraction <<= 1;
              dst->normal_exp--;
              dst->normal_exp--;
            }
            }
#endif
#endif
          dst->fraction.ll = fraction;
          dst->fraction.ll = fraction;
        }
        }
    }
    }
  else if (src->bits.exp == EXPMAX)
  else if (src->bits.exp == EXPMAX)
    {
    {
      /* Huge exponent*/
      /* Huge exponent*/
      if (fraction == 0)
      if (fraction == 0)
        {
        {
          /* Attached to a zero fraction - means infinity */
          /* Attached to a zero fraction - means infinity */
          dst->class = CLASS_INFINITY;
          dst->class = CLASS_INFINITY;
        }
        }
      else
      else
        {
        {
          /* Non zero fraction, means nan */
          /* Non zero fraction, means nan */
          if (dst->sign)
          if (dst->sign)
            {
            {
              dst->class = CLASS_SNAN;
              dst->class = CLASS_SNAN;
            }
            }
          else
          else
            {
            {
              dst->class = CLASS_QNAN;
              dst->class = CLASS_QNAN;
            }
            }
          /* Keep the fraction part as the nan number */
          /* Keep the fraction part as the nan number */
          dst->fraction.ll = fraction;
          dst->fraction.ll = fraction;
        }
        }
    }
    }
  else
  else
    {
    {
      /* Nothing strange about this number */
      /* Nothing strange about this number */
      dst->normal_exp = src->bits.exp - EXPBIAS;
      dst->normal_exp = src->bits.exp - EXPBIAS;
      dst->class = CLASS_NUMBER;
      dst->class = CLASS_NUMBER;
      dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
      dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
    }
    }
}
}
 
 
static fp_number_type *
static fp_number_type *
_fpadd_parts (fp_number_type * a,
_fpadd_parts (fp_number_type * a,
              fp_number_type * b,
              fp_number_type * b,
              fp_number_type * tmp)
              fp_number_type * tmp)
{
{
  intfrac tfraction;
  intfrac tfraction;
 
 
  /* Put commonly used fields in local variables.  */
  /* Put commonly used fields in local variables.  */
  int a_normal_exp;
  int a_normal_exp;
  int b_normal_exp;
  int b_normal_exp;
  fractype a_fraction;
  fractype a_fraction;
  fractype b_fraction;
  fractype b_fraction;
 
 
  if (isnan (a))
  if (isnan (a))
    {
    {
      return a;
      return a;
    }
    }
  if (isnan (b))
  if (isnan (b))
    {
    {
      return b;
      return b;
    }
    }
  if (isinf (a))
  if (isinf (a))
    {
    {
      /* Adding infinities with opposite signs yields a NaN.  */
      /* Adding infinities with opposite signs yields a NaN.  */
      if (isinf (b) && a->sign != b->sign)
      if (isinf (b) && a->sign != b->sign)
        return nan ();
        return nan ();
      return a;
      return a;
    }
    }
  if (isinf (b))
  if (isinf (b))
    {
    {
      return b;
      return b;
    }
    }
  if (iszero (b))
  if (iszero (b))
    {
    {
      return a;
      return a;
    }
    }
  if (iszero (a))
  if (iszero (a))
    {
    {
      return b;
      return b;
    }
    }
 
 
  /* Got two numbers. shift the smaller and increment the exponent till
  /* Got two numbers. shift the smaller and increment the exponent till
     they're the same */
     they're the same */
  {
  {
    int diff;
    int diff;
 
 
    a_normal_exp = a->normal_exp;
    a_normal_exp = a->normal_exp;
    b_normal_exp = b->normal_exp;
    b_normal_exp = b->normal_exp;
    a_fraction = a->fraction.ll;
    a_fraction = a->fraction.ll;
    b_fraction = b->fraction.ll;
    b_fraction = b->fraction.ll;
 
 
    diff = a_normal_exp - b_normal_exp;
    diff = a_normal_exp - b_normal_exp;
 
 
    if (diff < 0)
    if (diff < 0)
      diff = -diff;
      diff = -diff;
    if (diff < FRAC_NBITS)
    if (diff < FRAC_NBITS)
      {
      {
        /* ??? This does shifts one bit at a time.  Optimize.  */
        /* ??? This does shifts one bit at a time.  Optimize.  */
        while (a_normal_exp > b_normal_exp)
        while (a_normal_exp > b_normal_exp)
          {
          {
            b_normal_exp++;
            b_normal_exp++;
            LSHIFT (b_fraction);
            LSHIFT (b_fraction);
          }
          }
        while (b_normal_exp > a_normal_exp)
        while (b_normal_exp > a_normal_exp)
          {
          {
            a_normal_exp++;
            a_normal_exp++;
            LSHIFT (a_fraction);
            LSHIFT (a_fraction);
          }
          }
      }
      }
    else
    else
      {
      {
        /* Somethings's up.. choose the biggest */
        /* Somethings's up.. choose the biggest */
        if (a_normal_exp > b_normal_exp)
        if (a_normal_exp > b_normal_exp)
          {
          {
            b_normal_exp = a_normal_exp;
            b_normal_exp = a_normal_exp;
            b_fraction = 0;
            b_fraction = 0;
          }
          }
        else
        else
          {
          {
            a_normal_exp = b_normal_exp;
            a_normal_exp = b_normal_exp;
            a_fraction = 0;
            a_fraction = 0;
          }
          }
      }
      }
  }
  }
 
 
  if (a->sign != b->sign)
  if (a->sign != b->sign)
    {
    {
      if (a->sign)
      if (a->sign)
        {
        {
          tfraction = -a_fraction + b_fraction;
          tfraction = -a_fraction + b_fraction;
        }
        }
      else
      else
        {
        {
          tfraction = a_fraction - b_fraction;
          tfraction = a_fraction - b_fraction;
        }
        }
      if (tfraction > 0)
      if (tfraction > 0)
        {
        {
          tmp->sign = 0;
          tmp->sign = 0;
          tmp->normal_exp = a_normal_exp;
          tmp->normal_exp = a_normal_exp;
          tmp->fraction.ll = tfraction;
          tmp->fraction.ll = tfraction;
        }
        }
      else
      else
        {
        {
          tmp->sign = 1;
          tmp->sign = 1;
          tmp->normal_exp = a_normal_exp;
          tmp->normal_exp = a_normal_exp;
          tmp->fraction.ll = -tfraction;
          tmp->fraction.ll = -tfraction;
        }
        }
      /* and renormalize it */
      /* and renormalize it */
 
 
      while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
      while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
        {
        {
          tmp->fraction.ll <<= 1;
          tmp->fraction.ll <<= 1;
          tmp->normal_exp--;
          tmp->normal_exp--;
        }
        }
    }
    }
  else
  else
    {
    {
      tmp->sign = a->sign;
      tmp->sign = a->sign;
      tmp->normal_exp = a_normal_exp;
      tmp->normal_exp = a_normal_exp;
      tmp->fraction.ll = a_fraction + b_fraction;
      tmp->fraction.ll = a_fraction + b_fraction;
    }
    }
  tmp->class = CLASS_NUMBER;
  tmp->class = CLASS_NUMBER;
  /* Now the fraction is added, we have to shift down to renormalize the
  /* Now the fraction is added, we have to shift down to renormalize the
     number */
     number */
 
 
  if (tmp->fraction.ll >= IMPLICIT_2)
  if (tmp->fraction.ll >= IMPLICIT_2)
    {
    {
      LSHIFT (tmp->fraction.ll);
      LSHIFT (tmp->fraction.ll);
      tmp->normal_exp++;
      tmp->normal_exp++;
    }
    }
  return tmp;
  return tmp;
 
 
}
}
 
 
FLO_type
FLO_type
add (FLO_type arg_a, FLO_type arg_b)
add (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
  fp_number_type tmp;
  fp_number_type tmp;
  fp_number_type *res;
  fp_number_type *res;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  res = _fpadd_parts (&a, &b, &tmp);
  res = _fpadd_parts (&a, &b, &tmp);
 
 
  return pack_d (res);
  return pack_d (res);
}
}
 
 
FLO_type
FLO_type
sub (FLO_type arg_a, FLO_type arg_b)
sub (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
  fp_number_type tmp;
  fp_number_type tmp;
  fp_number_type *res;
  fp_number_type *res;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  b.sign ^= 1;
  b.sign ^= 1;
 
 
  res = _fpadd_parts (&a, &b, &tmp);
  res = _fpadd_parts (&a, &b, &tmp);
 
 
  return pack_d (res);
  return pack_d (res);
}
}
 
 
static fp_number_type *
static fp_number_type *
_fpmul_parts ( fp_number_type *  a,
_fpmul_parts ( fp_number_type *  a,
               fp_number_type *  b,
               fp_number_type *  b,
               fp_number_type * tmp)
               fp_number_type * tmp)
{
{
  fractype low = 0;
  fractype low = 0;
  fractype high = 0;
  fractype high = 0;
 
 
  if (isnan (a))
  if (isnan (a))
    {
    {
      a->sign = a->sign != b->sign;
      a->sign = a->sign != b->sign;
      return a;
      return a;
    }
    }
  if (isnan (b))
  if (isnan (b))
    {
    {
      b->sign = a->sign != b->sign;
      b->sign = a->sign != b->sign;
      return b;
      return b;
    }
    }
  if (isinf (a))
  if (isinf (a))
    {
    {
      if (iszero (b))
      if (iszero (b))
        return nan ();
        return nan ();
      a->sign = a->sign != b->sign;
      a->sign = a->sign != b->sign;
      return a;
      return a;
    }
    }
  if (isinf (b))
  if (isinf (b))
    {
    {
      if (iszero (a))
      if (iszero (a))
        {
        {
          return nan ();
          return nan ();
        }
        }
      b->sign = a->sign != b->sign;
      b->sign = a->sign != b->sign;
      return b;
      return b;
    }
    }
  if (iszero (a))
  if (iszero (a))
    {
    {
      a->sign = a->sign != b->sign;
      a->sign = a->sign != b->sign;
      return a;
      return a;
    }
    }
  if (iszero (b))
  if (iszero (b))
    {
    {
      b->sign = a->sign != b->sign;
      b->sign = a->sign != b->sign;
      return b;
      return b;
    }
    }
 
 
  /* Calculate the mantissa by multiplying both 64bit numbers to get a
  /* Calculate the mantissa by multiplying both 64bit numbers to get a
     128 bit number */
     128 bit number */
  {
  {
    fractype x = a->fraction.ll;
    fractype x = a->fraction.ll;
    fractype ylow = b->fraction.ll;
    fractype ylow = b->fraction.ll;
    fractype yhigh = 0;
    fractype yhigh = 0;
    int bit;
    int bit;
 
 
#if defined(NO_DI_MODE)
#if defined(NO_DI_MODE)
    {
    {
      /* ??? This does multiplies one bit at a time.  Optimize.  */
      /* ??? This does multiplies one bit at a time.  Optimize.  */
      for (bit = 0; bit < FRAC_NBITS; bit++)
      for (bit = 0; bit < FRAC_NBITS; bit++)
        {
        {
          int carry;
          int carry;
 
 
          if (x & 1)
          if (x & 1)
            {
            {
              carry = (low += ylow) < ylow;
              carry = (low += ylow) < ylow;
              high += yhigh + carry;
              high += yhigh + carry;
            }
            }
          yhigh <<= 1;
          yhigh <<= 1;
          if (ylow & FRACHIGH)
          if (ylow & FRACHIGH)
            {
            {
              yhigh |= 1;
              yhigh |= 1;
            }
            }
          ylow <<= 1;
          ylow <<= 1;
          x >>= 1;
          x >>= 1;
        }
        }
    }
    }
#elif defined(FLOAT) 
#elif defined(FLOAT) 
    {
    {
      /* Multiplying two 32 bit numbers to get a 64 bit number  on
      /* Multiplying two 32 bit numbers to get a 64 bit number  on
        a machine with DI, so we're safe */
        a machine with DI, so we're safe */
 
 
      DItype answer = (DItype)(a->fraction.ll) * (DItype)(b->fraction.ll);
      DItype answer = (DItype)(a->fraction.ll) * (DItype)(b->fraction.ll);
 
 
      high = answer >> 32;
      high = answer >> 32;
      low = answer;
      low = answer;
    }
    }
#else
#else
    /* Doing a 64*64 to 128 */
    /* Doing a 64*64 to 128 */
    {
    {
      UDItype nl = a->fraction.ll & 0xffffffff;
      UDItype nl = a->fraction.ll & 0xffffffff;
      UDItype nh = a->fraction.ll >> 32;
      UDItype nh = a->fraction.ll >> 32;
      UDItype ml = b->fraction.ll & 0xffffffff;
      UDItype ml = b->fraction.ll & 0xffffffff;
      UDItype mh = b->fraction.ll >>32;
      UDItype mh = b->fraction.ll >>32;
      UDItype pp_ll = ml * nl;
      UDItype pp_ll = ml * nl;
      UDItype pp_hl = mh * nl;
      UDItype pp_hl = mh * nl;
      UDItype pp_lh = ml * nh;
      UDItype pp_lh = ml * nh;
      UDItype pp_hh = mh * nh;
      UDItype pp_hh = mh * nh;
      UDItype res2 = 0;
      UDItype res2 = 0;
      UDItype res0 = 0;
      UDItype res0 = 0;
      UDItype ps_hh__ = pp_hl + pp_lh;
      UDItype ps_hh__ = pp_hl + pp_lh;
      if (ps_hh__ < pp_hl)
      if (ps_hh__ < pp_hl)
        res2 += 0x100000000LL;
        res2 += 0x100000000LL;
      pp_hl = (ps_hh__ << 32) & 0xffffffff00000000LL;
      pp_hl = (ps_hh__ << 32) & 0xffffffff00000000LL;
      res0 = pp_ll + pp_hl;
      res0 = pp_ll + pp_hl;
      if (res0 < pp_ll)
      if (res0 < pp_ll)
        res2++;
        res2++;
      res2 += ((ps_hh__ >> 32) & 0xffffffffL) + pp_hh;
      res2 += ((ps_hh__ >> 32) & 0xffffffffL) + pp_hh;
      high = res2;
      high = res2;
      low = res0;
      low = res0;
    }
    }
#endif
#endif
  }
  }
 
 
  tmp->normal_exp = a->normal_exp + b->normal_exp;
  tmp->normal_exp = a->normal_exp + b->normal_exp;
  tmp->sign = a->sign != b->sign;
  tmp->sign = a->sign != b->sign;
#ifdef FLOAT
#ifdef FLOAT
  tmp->normal_exp += 2;         /* ??????????????? */
  tmp->normal_exp += 2;         /* ??????????????? */
#else
#else
  tmp->normal_exp += 4;         /* ??????????????? */
  tmp->normal_exp += 4;         /* ??????????????? */
#endif
#endif
  while (high >= IMPLICIT_2)
  while (high >= IMPLICIT_2)
    {
    {
      tmp->normal_exp++;
      tmp->normal_exp++;
      if (high & 1)
      if (high & 1)
        {
        {
          low >>= 1;
          low >>= 1;
          low |= FRACHIGH;
          low |= FRACHIGH;
        }
        }
      high >>= 1;
      high >>= 1;
    }
    }
  while (high < IMPLICIT_1)
  while (high < IMPLICIT_1)
    {
    {
      tmp->normal_exp--;
      tmp->normal_exp--;
 
 
      high <<= 1;
      high <<= 1;
      if (low & FRACHIGH)
      if (low & FRACHIGH)
        high |= 1;
        high |= 1;
      low <<= 1;
      low <<= 1;
    }
    }
  /* rounding is tricky. if we only round if it won't make us round later. */
  /* rounding is tricky. if we only round if it won't make us round later. */
#if 0
#if 0
  if (low & FRACHIGH2)
  if (low & FRACHIGH2)
    {
    {
      if (((high & GARDMASK) != GARDMSB)
      if (((high & GARDMASK) != GARDMSB)
          && (((high + 1) & GARDMASK) == GARDMSB))
          && (((high + 1) & GARDMASK) == GARDMSB))
        {
        {
          /* don't round, it gets done again later. */
          /* don't round, it gets done again later. */
        }
        }
      else
      else
        {
        {
          high++;
          high++;
        }
        }
    }
    }
#endif
#endif
  if ((high & GARDMASK) == GARDMSB)
  if ((high & GARDMASK) == GARDMSB)
    {
    {
      if (high & (1 << NGARDS))
      if (high & (1 << NGARDS))
        {
        {
          /* half way, so round to even */
          /* half way, so round to even */
          high += GARDROUND + 1;
          high += GARDROUND + 1;
        }
        }
      else if (low)
      else if (low)
        {
        {
          /* but we really weren't half way */
          /* but we really weren't half way */
          high += GARDROUND + 1;
          high += GARDROUND + 1;
        }
        }
    }
    }
  tmp->fraction.ll = high;
  tmp->fraction.ll = high;
  tmp->class = CLASS_NUMBER;
  tmp->class = CLASS_NUMBER;
  return tmp;
  return tmp;
}
}
 
 
FLO_type
FLO_type
multiply (FLO_type arg_a, FLO_type arg_b)
multiply (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
  fp_number_type tmp;
  fp_number_type tmp;
  fp_number_type *res;
  fp_number_type *res;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  res = _fpmul_parts (&a, &b, &tmp);
  res = _fpmul_parts (&a, &b, &tmp);
 
 
  return pack_d (res);
  return pack_d (res);
}
}
 
 
static fp_number_type *
static fp_number_type *
_fpdiv_parts (fp_number_type * a,
_fpdiv_parts (fp_number_type * a,
              fp_number_type * b,
              fp_number_type * b,
              fp_number_type * tmp)
              fp_number_type * tmp)
{
{
  fractype low = 0;
  fractype low = 0;
  fractype high = 0;
  fractype high = 0;
  fractype r0, r1, y0, y1, bit;
  fractype r0, r1, y0, y1, bit;
  fractype q;
  fractype q;
  fractype numerator;
  fractype numerator;
  fractype denominator;
  fractype denominator;
  fractype quotient;
  fractype quotient;
  fractype remainder;
  fractype remainder;
 
 
  if (isnan (a))
  if (isnan (a))
    {
    {
      return a;
      return a;
    }
    }
  if (isnan (b))
  if (isnan (b))
    {
    {
      return b;
      return b;
    }
    }
  if (isinf (a) || iszero (a))
  if (isinf (a) || iszero (a))
    {
    {
      if (a->class == b->class)
      if (a->class == b->class)
        return nan ();
        return nan ();
      return a;
      return a;
    }
    }
  a->sign = a->sign ^ b->sign;
  a->sign = a->sign ^ b->sign;
 
 
  if (isinf (b))
  if (isinf (b))
    {
    {
      a->fraction.ll = 0;
      a->fraction.ll = 0;
      a->normal_exp = 0;
      a->normal_exp = 0;
      return a;
      return a;
    }
    }
  if (iszero (b))
  if (iszero (b))
    {
    {
      a->class = CLASS_INFINITY;
      a->class = CLASS_INFINITY;
      return b;
      return b;
    }
    }
 
 
  /* Calculate the mantissa by multiplying both 64bit numbers to get a
  /* Calculate the mantissa by multiplying both 64bit numbers to get a
     128 bit number */
     128 bit number */
  {
  {
    int carry;
    int carry;
    intfrac d0, d1;             /* weren't unsigned before ??? */
    intfrac d0, d1;             /* weren't unsigned before ??? */
 
 
    /* quotient =
    /* quotient =
       ( numerator / denominator) * 2^(numerator exponent -  denominator exponent)
       ( numerator / denominator) * 2^(numerator exponent -  denominator exponent)
     */
     */
 
 
    a->normal_exp = a->normal_exp - b->normal_exp;
    a->normal_exp = a->normal_exp - b->normal_exp;
    numerator = a->fraction.ll;
    numerator = a->fraction.ll;
    denominator = b->fraction.ll;
    denominator = b->fraction.ll;
 
 
    if (numerator < denominator)
    if (numerator < denominator)
      {
      {
        /* Fraction will be less than 1.0 */
        /* Fraction will be less than 1.0 */
        numerator *= 2;
        numerator *= 2;
        a->normal_exp--;
        a->normal_exp--;
      }
      }
    bit = IMPLICIT_1;
    bit = IMPLICIT_1;
    quotient = 0;
    quotient = 0;
    /* ??? Does divide one bit at a time.  Optimize.  */
    /* ??? Does divide one bit at a time.  Optimize.  */
    while (bit)
    while (bit)
      {
      {
        if (numerator >= denominator)
        if (numerator >= denominator)
          {
          {
            quotient |= bit;
            quotient |= bit;
            numerator -= denominator;
            numerator -= denominator;
          }
          }
        bit >>= 1;
        bit >>= 1;
        numerator *= 2;
        numerator *= 2;
      }
      }
 
 
    if ((quotient & GARDMASK) == GARDMSB)
    if ((quotient & GARDMASK) == GARDMSB)
      {
      {
        if (quotient & (1 << NGARDS))
        if (quotient & (1 << NGARDS))
          {
          {
            /* half way, so round to even */
            /* half way, so round to even */
            quotient += GARDROUND + 1;
            quotient += GARDROUND + 1;
          }
          }
        else if (numerator)
        else if (numerator)
          {
          {
            /* but we really weren't half way, more bits exist */
            /* but we really weren't half way, more bits exist */
            quotient += GARDROUND + 1;
            quotient += GARDROUND + 1;
          }
          }
      }
      }
 
 
    a->fraction.ll = quotient;
    a->fraction.ll = quotient;
    return (a);
    return (a);
  }
  }
}
}
 
 
FLO_type
FLO_type
divide (FLO_type arg_a, FLO_type arg_b)
divide (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
  fp_number_type tmp;
  fp_number_type tmp;
  fp_number_type *res;
  fp_number_type *res;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  res = _fpdiv_parts (&a, &b, &tmp);
  res = _fpdiv_parts (&a, &b, &tmp);
 
 
  return pack_d (res);
  return pack_d (res);
}
}
 
 
/* according to the demo, fpcmp returns a comparison with 0... thus
/* according to the demo, fpcmp returns a comparison with 0... thus
   a<b -> -1
   a<b -> -1
   a==b -> 0
   a==b -> 0
   a>b -> +1
   a>b -> +1
 */
 */
 
 
static int
static int
_fpcmp_parts (fp_number_type * a, fp_number_type * b)
_fpcmp_parts (fp_number_type * a, fp_number_type * b)
{
{
#if 0
#if 0
  /* either nan -> unordered. Must be checked outside of this routine. */
  /* either nan -> unordered. Must be checked outside of this routine. */
  if (isnan (a) && isnan (b))
  if (isnan (a) && isnan (b))
    {
    {
      return 1;                 /* still unordered! */
      return 1;                 /* still unordered! */
    }
    }
#endif
#endif
 
 
  if (isnan (a) || isnan (b))
  if (isnan (a) || isnan (b))
    {
    {
      return 1;                 /* how to indicate unordered compare? */
      return 1;                 /* how to indicate unordered compare? */
    }
    }
  if (isinf (a) && isinf (b))
  if (isinf (a) && isinf (b))
    {
    {
      /* +inf > -inf, but +inf != +inf */
      /* +inf > -inf, but +inf != +inf */
      /* b    \a| +inf(0)| -inf(1)
      /* b    \a| +inf(0)| -inf(1)
       ______\+--------+--------
       ______\+--------+--------
       +inf(0)| a==b(0)| a<b(-1)
       +inf(0)| a==b(0)| a<b(-1)
       -------+--------+--------
       -------+--------+--------
       -inf(1)| a>b(1) | a==b(0)
       -inf(1)| a>b(1) | a==b(0)
       -------+--------+--------
       -------+--------+--------
       So since unordered must be non zero, just line up the columns...
       So since unordered must be non zero, just line up the columns...
       */
       */
      return b->sign - a->sign;
      return b->sign - a->sign;
    }
    }
  /* but not both... */
  /* but not both... */
  if (isinf (a))
  if (isinf (a))
    {
    {
      return a->sign ? -1 : 1;
      return a->sign ? -1 : 1;
    }
    }
  if (isinf (b))
  if (isinf (b))
    {
    {
      return b->sign ? 1 : -1;
      return b->sign ? 1 : -1;
    }
    }
  if (iszero (a) && iszero (b))
  if (iszero (a) && iszero (b))
    {
    {
      return 0;
      return 0;
    }
    }
  if (iszero (a))
  if (iszero (a))
    {
    {
      return b->sign ? 1 : -1;
      return b->sign ? 1 : -1;
    }
    }
  if (iszero (b))
  if (iszero (b))
    {
    {
      return a->sign ? -1 : 1;
      return a->sign ? -1 : 1;
    }
    }
  /* now both are "normal". */
  /* now both are "normal". */
  if (a->sign != b->sign)
  if (a->sign != b->sign)
    {
    {
      /* opposite signs */
      /* opposite signs */
      return a->sign ? -1 : 1;
      return a->sign ? -1 : 1;
    }
    }
  /* same sign; exponents? */
  /* same sign; exponents? */
  if (a->normal_exp > b->normal_exp)
  if (a->normal_exp > b->normal_exp)
    {
    {
      return a->sign ? -1 : 1;
      return a->sign ? -1 : 1;
    }
    }
  if (a->normal_exp < b->normal_exp)
  if (a->normal_exp < b->normal_exp)
    {
    {
      return a->sign ? 1 : -1;
      return a->sign ? 1 : -1;
    }
    }
  /* same exponents; check size. */
  /* same exponents; check size. */
  if (a->fraction.ll > b->fraction.ll)
  if (a->fraction.ll > b->fraction.ll)
    {
    {
      return a->sign ? -1 : 1;
      return a->sign ? -1 : 1;
    }
    }
  if (a->fraction.ll < b->fraction.ll)
  if (a->fraction.ll < b->fraction.ll)
    {
    {
      return a->sign ? 1 : -1;
      return a->sign ? 1 : -1;
    }
    }
  /* after all that, they're equal. */
  /* after all that, they're equal. */
  return 0;
  return 0;
}
}
 
 
CMPtype
CMPtype
compare (FLO_type arg_a, FLO_type arg_b)
compare (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  return _fpcmp_parts (&a, &b);
  return _fpcmp_parts (&a, &b);
}
}
 
 
#ifndef US_SOFTWARE_GOFAST
#ifndef US_SOFTWARE_GOFAST
 
 
/* These should be optimized for their specific tasks someday.  */
/* These should be optimized for their specific tasks someday.  */
 
 
CMPtype
CMPtype
_eq_f2 (FLO_type arg_a, FLO_type arg_b)
_eq_f2 (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  if (isnan (&a) || isnan (&b))
  if (isnan (&a) || isnan (&b))
    return 1;                   /* false, truth == 0 */
    return 1;                   /* false, truth == 0 */
 
 
  return _fpcmp_parts (&a, &b) ;
  return _fpcmp_parts (&a, &b) ;
}
}
 
 
CMPtype
CMPtype
_ne_f2 (FLO_type arg_a, FLO_type arg_b)
_ne_f2 (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  if (isnan (&a) || isnan (&b))
  if (isnan (&a) || isnan (&b))
    return 1;                   /* true, truth != 0 */
    return 1;                   /* true, truth != 0 */
 
 
  return  _fpcmp_parts (&a, &b) ;
  return  _fpcmp_parts (&a, &b) ;
}
}
 
 
CMPtype
CMPtype
_gt_f2 (FLO_type arg_a, FLO_type arg_b)
_gt_f2 (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  if (isnan (&a) || isnan (&b))
  if (isnan (&a) || isnan (&b))
    return -1;                  /* false, truth > 0 */
    return -1;                  /* false, truth > 0 */
 
 
  return _fpcmp_parts (&a, &b);
  return _fpcmp_parts (&a, &b);
}
}
 
 
CMPtype
CMPtype
_ge_f2 (FLO_type arg_a, FLO_type arg_b)
_ge_f2 (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  if (isnan (&a) || isnan (&b))
  if (isnan (&a) || isnan (&b))
    return -1;                  /* false, truth >= 0 */
    return -1;                  /* false, truth >= 0 */
  return _fpcmp_parts (&a, &b) ;
  return _fpcmp_parts (&a, &b) ;
}
}
 
 
CMPtype
CMPtype
_lt_f2 (FLO_type arg_a, FLO_type arg_b)
_lt_f2 (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  if (isnan (&a) || isnan (&b))
  if (isnan (&a) || isnan (&b))
    return 1;                   /* false, truth < 0 */
    return 1;                   /* false, truth < 0 */
 
 
  return _fpcmp_parts (&a, &b);
  return _fpcmp_parts (&a, &b);
}
}
 
 
CMPtype
CMPtype
_le_f2 (FLO_type arg_a, FLO_type arg_b)
_le_f2 (FLO_type arg_a, FLO_type arg_b)
{
{
  fp_number_type a;
  fp_number_type a;
  fp_number_type b;
  fp_number_type b;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_b, &b);
  unpack_d ((FLO_union_type *) & arg_b, &b);
 
 
  if (isnan (&a) || isnan (&b))
  if (isnan (&a) || isnan (&b))
    return 1;                   /* false, truth <= 0 */
    return 1;                   /* false, truth <= 0 */
 
 
  return _fpcmp_parts (&a, &b) ;
  return _fpcmp_parts (&a, &b) ;
}
}
 
 
#endif /* ! US_SOFTWARE_GOFAST */
#endif /* ! US_SOFTWARE_GOFAST */
 
 
FLO_type
FLO_type
si_to_float (SItype arg_a)
si_to_float (SItype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
 
 
  in.class = CLASS_NUMBER;
  in.class = CLASS_NUMBER;
  in.sign = arg_a < 0;
  in.sign = arg_a < 0;
  if (!arg_a)
  if (!arg_a)
    {
    {
      in.class = CLASS_ZERO;
      in.class = CLASS_ZERO;
    }
    }
  else
  else
    {
    {
      in.normal_exp = FRACBITS + NGARDS;
      in.normal_exp = FRACBITS + NGARDS;
      if (in.sign)
      if (in.sign)
        {
        {
          /* Special case for minint, since there is no +ve integer
          /* Special case for minint, since there is no +ve integer
             representation for it */
             representation for it */
          if (arg_a == 0x80000000)
          if (arg_a == 0x80000000)
            {
            {
              return -2147483648.0;
              return -2147483648.0;
            }
            }
          in.fraction.ll = (-arg_a);
          in.fraction.ll = (-arg_a);
        }
        }
      else
      else
        in.fraction.ll = arg_a;
        in.fraction.ll = arg_a;
 
 
      while (in.fraction.ll < (1LL << (FRACBITS + NGARDS)))
      while (in.fraction.ll < (1LL << (FRACBITS + NGARDS)))
        {
        {
          in.fraction.ll <<= 1;
          in.fraction.ll <<= 1;
          in.normal_exp -= 1;
          in.normal_exp -= 1;
        }
        }
    }
    }
  return pack_d (&in);
  return pack_d (&in);
}
}
 
 
SItype
SItype
float_to_si (FLO_type arg_a)
float_to_si (FLO_type arg_a)
{
{
  fp_number_type a;
  fp_number_type a;
  SItype tmp;
  SItype tmp;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  if (iszero (&a))
  if (iszero (&a))
    return 0;
    return 0;
  if (isnan (&a))
  if (isnan (&a))
    return 0;
    return 0;
  /* get reasonable MAX_SI_INT... */
  /* get reasonable MAX_SI_INT... */
  if (isinf (&a))
  if (isinf (&a))
    return a.sign ? MAX_SI_INT : (-MAX_SI_INT)-1;
    return a.sign ? MAX_SI_INT : (-MAX_SI_INT)-1;
  /* it is a number, but a small one */
  /* it is a number, but a small one */
  if (a.normal_exp < 0)
  if (a.normal_exp < 0)
    return 0;
    return 0;
  if (a.normal_exp > 30)
  if (a.normal_exp > 30)
    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
  tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
  tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
  return a.sign ? (-tmp) : (tmp);
  return a.sign ? (-tmp) : (tmp);
}
}
 
 
#ifdef US_SOFTWARE_GOFAST
#ifdef US_SOFTWARE_GOFAST
/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
   we also define them for GOFAST because the ones in libgcc2.c have the
   we also define them for GOFAST because the ones in libgcc2.c have the
   wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
   wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
   out of libgcc2.c.  We can't define these here if not GOFAST because then
   out of libgcc2.c.  We can't define these here if not GOFAST because then
   there'd be duplicate copies.  */
   there'd be duplicate copies.  */
 
 
USItype
USItype
float_to_usi (FLO_type arg_a)
float_to_usi (FLO_type arg_a)
{
{
  fp_number_type a;
  fp_number_type a;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  if (iszero (&a))
  if (iszero (&a))
    return 0;
    return 0;
  if (isnan (&a))
  if (isnan (&a))
    return 0;
    return 0;
  /* get reasonable MAX_USI_INT... */
  /* get reasonable MAX_USI_INT... */
  if (isinf (&a))
  if (isinf (&a))
    return a.sign ? MAX_USI_INT : 0;
    return a.sign ? MAX_USI_INT : 0;
  /* it is a negative number */
  /* it is a negative number */
  if (a.sign)
  if (a.sign)
    return 0;
    return 0;
  /* it is a number, but a small one */
  /* it is a number, but a small one */
  if (a.normal_exp < 0)
  if (a.normal_exp < 0)
    return 0;
    return 0;
  if (a.normal_exp > 31)
  if (a.normal_exp > 31)
    return MAX_USI_INT;
    return MAX_USI_INT;
  else if (a.normal_exp > (FRACBITS + NGARDS))
  else if (a.normal_exp > (FRACBITS + NGARDS))
    return a.fraction.ll << ((FRACBITS + NGARDS) - a.normal_exp);
    return a.fraction.ll << ((FRACBITS + NGARDS) - a.normal_exp);
  else
  else
    return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
    return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
}
}
#endif
#endif
 
 
FLO_type
FLO_type
negate (FLO_type arg_a)
negate (FLO_type arg_a)
{
{
  fp_number_type a;
  fp_number_type a;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &a);
  unpack_d ((FLO_union_type *) & arg_a, &a);
  flip_sign (&a);
  flip_sign (&a);
  return pack_d (&a);
  return pack_d (&a);
}
}
 
 
#ifdef FLOAT
#ifdef FLOAT
 
 
SFtype
SFtype
__make_fp(fp_class_type class,
__make_fp(fp_class_type class,
             unsigned int sign,
             unsigned int sign,
             int exp,
             int exp,
             USItype frac)
             USItype frac)
{
{
  fp_number_type in;
  fp_number_type in;
 
 
  in.class = class;
  in.class = class;
  in.sign = sign;
  in.sign = sign;
  in.normal_exp = exp;
  in.normal_exp = exp;
  in.fraction.ll = frac;
  in.fraction.ll = frac;
  return pack_d (&in);
  return pack_d (&in);
}
}
 
 
#ifndef FLOAT_ONLY
#ifndef FLOAT_ONLY
 
 
/* This enables one to build an fp library that supports float but not double.
/* This enables one to build an fp library that supports float but not double.
   Otherwise, we would get an undefined reference to __make_dp.
   Otherwise, we would get an undefined reference to __make_dp.
   This is needed for some 8-bit ports that can't handle well values that
   This is needed for some 8-bit ports that can't handle well values that
   are 8-bytes in size, so we just don't support double for them at all.  */
   are 8-bytes in size, so we just don't support double for them at all.  */
 
 
extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype frac);
extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype frac);
 
 
DFtype
DFtype
sf_to_df (SFtype arg_a)
sf_to_df (SFtype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &in);
  unpack_d ((FLO_union_type *) & arg_a, &in);
  return __make_dp (in.class, in.sign, in.normal_exp,
  return __make_dp (in.class, in.sign, in.normal_exp,
                    ((UDItype) in.fraction.ll) << F_D_BITOFF);
                    ((UDItype) in.fraction.ll) << F_D_BITOFF);
}
}
 
 
#endif
#endif
#endif
#endif
 
 
#ifndef FLOAT
#ifndef FLOAT
 
 
extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
 
 
DFtype
DFtype
__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
{
{
  fp_number_type in;
  fp_number_type in;
 
 
  in.class = class;
  in.class = class;
  in.sign = sign;
  in.sign = sign;
  in.normal_exp = exp;
  in.normal_exp = exp;
  in.fraction.ll = frac;
  in.fraction.ll = frac;
  return pack_d (&in);
  return pack_d (&in);
}
}
 
 
SFtype
SFtype
df_to_sf (DFtype arg_a)
df_to_sf (DFtype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
 
 
  unpack_d ((FLO_union_type *) & arg_a, &in);
  unpack_d ((FLO_union_type *) & arg_a, &in);
  return __make_fp (in.class, in.sign, in.normal_exp,
  return __make_fp (in.class, in.sign, in.normal_exp,
                    in.fraction.ll >> F_D_BITOFF);
                    in.fraction.ll >> F_D_BITOFF);
}
}
 
 
#endif
#endif
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.