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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [fp-bit.c] - Diff between revs 154 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 154 Rev 816
/* This is a software floating point library which can be used
/* This is a software floating point library which can be used
   for targets without hardware floating point.
   for targets without hardware floating point.
   Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003,
   Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003,
   2004, 2005 Free Software Foundation, Inc.
   2004, 2005 Free Software Foundation, Inc.
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify it under
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
Software Foundation; either version 2, or (at your option) any later
version.
version.
 
 
In addition to the permissions in the GNU General Public License, the
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
and to distribute those combinations without any restriction coming
from the use of this file.  (The General Public License restrictions
from the use of this file.  (The General Public License restrictions
do apply in other respects; for example, they cover modification of
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
the file, and distribution when not linked into a combine
executable.)
executable.)
 
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
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 GCC; see the file COPYING.  If not, write to the Free
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.  */
02110-1301, USA.  */
 
 
/* 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.  */
 
 
#include "tconfig.h"
#include "tconfig.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tm.h"
#include "tm.h"
#include "config/fp-bit.h"
#include "config/fp-bit.h"
 
 
/* The following macros can be defined to change the behavior of this file:
/* The following macros can be defined to change the behavior 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.
     US Software goFast library.
   _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_DENORMALS: Disable handling of denormals.
   NO_DENORMALS: Disable handling of denormals.
   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 */
 
 
/* We don't currently support extended floats (long doubles) on machines
/* We don't currently support extended floats (long doubles) on machines
   without hardware to deal with them.
   without hardware to deal with them.
 
 
   These stubs are just to keep the linker from complaining about unresolved
   These stubs are just to keep the linker from complaining about unresolved
   references which can be pulled in from libio & libstdc++, even if the
   references which can be pulled in from libio & libstdc++, even if the
   user isn't using long doubles.  However, they may generate an unresolved
   user isn't using long doubles.  However, they may generate an unresolved
   external to abort if abort is not used by the function, and the stubs
   external to abort if abort is not used by the function, and the stubs
   are referenced from within libc, since libgcc goes before and after the
   are referenced from within libc, since libgcc goes before and after the
   system library.  */
   system library.  */
 
 
#ifdef DECLARE_LIBRARY_RENAMES
#ifdef DECLARE_LIBRARY_RENAMES
  DECLARE_LIBRARY_RENAMES
  DECLARE_LIBRARY_RENAMES
#endif
#endif
 
 
#ifdef EXTENDED_FLOAT_STUBS
#ifdef EXTENDED_FLOAT_STUBS
extern void abort (void);
extern void abort (void);
void __extendsfxf2 (void) { abort(); }
void __extendsfxf2 (void) { abort(); }
void __extenddfxf2 (void) { abort(); }
void __extenddfxf2 (void) { abort(); }
void __truncxfdf2 (void) { abort(); }
void __truncxfdf2 (void) { abort(); }
void __truncxfsf2 (void) { abort(); }
void __truncxfsf2 (void) { abort(); }
void __fixxfsi (void) { abort(); }
void __fixxfsi (void) { abort(); }
void __floatsixf (void) { abort(); }
void __floatsixf (void) { abort(); }
void __addxf3 (void) { abort(); }
void __addxf3 (void) { abort(); }
void __subxf3 (void) { abort(); }
void __subxf3 (void) { abort(); }
void __mulxf3 (void) { abort(); }
void __mulxf3 (void) { abort(); }
void __divxf3 (void) { abort(); }
void __divxf3 (void) { abort(); }
void __negxf2 (void) { abort(); }
void __negxf2 (void) { abort(); }
void __eqxf2 (void) { abort(); }
void __eqxf2 (void) { abort(); }
void __nexf2 (void) { abort(); }
void __nexf2 (void) { abort(); }
void __gtxf2 (void) { abort(); }
void __gtxf2 (void) { abort(); }
void __gexf2 (void) { abort(); }
void __gexf2 (void) { abort(); }
void __lexf2 (void) { abort(); }
void __lexf2 (void) { abort(); }
void __ltxf2 (void) { abort(); }
void __ltxf2 (void) { abort(); }
 
 
void __extendsftf2 (void) { abort(); }
void __extendsftf2 (void) { abort(); }
void __extenddftf2 (void) { abort(); }
void __extenddftf2 (void) { abort(); }
void __trunctfdf2 (void) { abort(); }
void __trunctfdf2 (void) { abort(); }
void __trunctfsf2 (void) { abort(); }
void __trunctfsf2 (void) { abort(); }
void __fixtfsi (void) { abort(); }
void __fixtfsi (void) { abort(); }
void __floatsitf (void) { abort(); }
void __floatsitf (void) { abort(); }
void __addtf3 (void) { abort(); }
void __addtf3 (void) { abort(); }
void __subtf3 (void) { abort(); }
void __subtf3 (void) { abort(); }
void __multf3 (void) { abort(); }
void __multf3 (void) { abort(); }
void __divtf3 (void) { abort(); }
void __divtf3 (void) { abort(); }
void __negtf2 (void) { abort(); }
void __negtf2 (void) { abort(); }
void __eqtf2 (void) { abort(); }
void __eqtf2 (void) { abort(); }
void __netf2 (void) { abort(); }
void __netf2 (void) { abort(); }
void __gttf2 (void) { abort(); }
void __gttf2 (void) { abort(); }
void __getf2 (void) { abort(); }
void __getf2 (void) { abort(); }
void __letf2 (void) { abort(); }
void __letf2 (void) { abort(); }
void __lttf2 (void) { abort(); }
void __lttf2 (void) { abort(); }
#else   /* !EXTENDED_FLOAT_STUBS, rest of file */
#else   /* !EXTENDED_FLOAT_STUBS, rest of file */
 
 
/* 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
 
 
#if   defined L_thenan_sf
#if   defined L_thenan_sf
const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
#elif defined L_thenan_df
#elif defined L_thenan_df
const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
#elif defined L_thenan_tf
#elif defined L_thenan_tf
const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
#elif defined TFLOAT
#elif defined TFLOAT
extern const fp_number_type __thenan_tf;
extern const fp_number_type __thenan_tf;
#elif defined FLOAT
#elif defined FLOAT
extern const fp_number_type __thenan_sf;
extern const fp_number_type __thenan_sf;
#else
#else
extern const fp_number_type __thenan_df;
extern const fp_number_type __thenan_df;
#endif
#endif
 
 
INLINE
INLINE
static fp_number_type *
static fp_number_type *
nan (void)
nan (void)
{
{
  /* Discard the const qualifier...  */
  /* Discard the const qualifier...  */
#ifdef TFLOAT
#ifdef TFLOAT
  return (fp_number_type *) (& __thenan_tf);
  return (fp_number_type *) (& __thenan_tf);
#elif defined FLOAT  
#elif defined FLOAT  
  return (fp_number_type *) (& __thenan_sf);
  return (fp_number_type *) (& __thenan_sf);
#else
#else
  return (fp_number_type *) (& __thenan_df);
  return (fp_number_type *) (& __thenan_df);
#endif
#endif
}
}
 
 
INLINE
INLINE
static int
static int
isnan ( fp_number_type *  x)
isnan ( fp_number_type *  x)
{
{
  return __builtin_expect (x->class == CLASS_SNAN || x->class == CLASS_QNAN,
  return __builtin_expect (x->class == CLASS_SNAN || x->class == CLASS_QNAN,
                           0);
                           0);
}
}
 
 
INLINE
INLINE
static int
static int
isinf ( fp_number_type *  x)
isinf ( fp_number_type *  x)
{
{
  return __builtin_expect (x->class == CLASS_INFINITY, 0);
  return __builtin_expect (x->class == CLASS_INFINITY, 0);
}
}
 
 
#endif /* NO_NANS */
#endif /* NO_NANS */
 
 
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;
}
}
 
 
/* Count leading zeroes in N.  */
/* Count leading zeroes in N.  */
INLINE
INLINE
static int
static int
clzusi (USItype n)
clzusi (USItype n)
{
{
  extern int __clzsi2 (USItype);
  extern int __clzsi2 (USItype);
  if (sizeof (USItype) == sizeof (unsigned int))
  if (sizeof (USItype) == sizeof (unsigned int))
    return __builtin_clz (n);
    return __builtin_clz (n);
  else if (sizeof (USItype) == sizeof (unsigned long))
  else if (sizeof (USItype) == sizeof (unsigned long))
    return __builtin_clzl (n);
    return __builtin_clzl (n);
  else if (sizeof (USItype) == sizeof (unsigned long long))
  else if (sizeof (USItype) == sizeof (unsigned long long))
    return __builtin_clzll (n);
    return __builtin_clzll (n);
  else
  else
    return __clzsi2 (n);
    return __clzsi2 (n);
}
}
 
 
extern FLO_type pack_d ( fp_number_type * );
extern FLO_type pack_d ( fp_number_type * );
 
 
#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
FLO_type
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? */
  int sign = src->sign;
  int sign = src->sign;
  int exp = 0;
  int exp = 0;
 
 
  if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
  if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
    {
    {
      /* We can't represent these values accurately.  By using the
      /* We can't represent these values accurately.  By using the
         largest possible magnitude, we guarantee that the conversion
         largest possible magnitude, we guarantee that the conversion
         of infinity is at least as big as any finite number.  */
         of infinity is at least as big as any finite number.  */
      exp = EXPMAX;
      exp = EXPMAX;
      fraction = ((fractype) 1 << FRACBITS) - 1;
      fraction = ((fractype) 1 << FRACBITS) - 1;
    }
    }
  else if (isnan (src))
  else if (isnan (src))
    {
    {
      exp = EXPMAX;
      exp = EXPMAX;
      if (src->class == CLASS_QNAN || 1)
      if (src->class == CLASS_QNAN || 1)
        {
        {
#ifdef QUIET_NAN_NEGATED
#ifdef QUIET_NAN_NEGATED
          fraction |= QUIET_NAN - 1;
          fraction |= QUIET_NAN - 1;
#else
#else
          fraction |= QUIET_NAN;
          fraction |= QUIET_NAN;
#endif
#endif
        }
        }
    }
    }
  else if (isinf (src))
  else if (isinf (src))
    {
    {
      exp = EXPMAX;
      exp = EXPMAX;
      fraction = 0;
      fraction = 0;
    }
    }
  else if (iszero (src))
  else if (iszero (src))
    {
    {
      exp = 0;
      exp = 0;
      fraction = 0;
      fraction = 0;
    }
    }
  else if (fraction == 0)
  else if (fraction == 0)
    {
    {
      exp = 0;
      exp = 0;
    }
    }
  else
  else
    {
    {
      if (__builtin_expect (src->normal_exp < NORMAL_EXPMIN, 0))
      if (__builtin_expect (src->normal_exp < NORMAL_EXPMIN, 0))
        {
        {
#ifdef NO_DENORMALS
#ifdef NO_DENORMALS
          /* Go straight to a zero representation if denormals are not
          /* Go straight to a zero representation if denormals are not
             supported.  The denormal handling would be harmless but
             supported.  The denormal handling would be harmless but
             isn't unnecessary.  */
             isn't unnecessary.  */
          exp = 0;
          exp = 0;
          fraction = 0;
          fraction = 0;
#else /* NO_DENORMALS */
#else /* NO_DENORMALS */
          /* 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;
 
 
          exp = 0;
          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
            {
            {
              int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
              int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
              fraction = (fraction >> shift) | lowbit;
              fraction = (fraction >> shift) | lowbit;
            }
            }
          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 to the guards to round up.  */
              /* Add to the guards to round up.  */
              fraction += GARDROUND;
              fraction += GARDROUND;
            }
            }
          /* Perhaps the rounding means we now need to change the
          /* Perhaps the rounding means we now need to change the
             exponent, because the fraction is no longer denormal.  */
             exponent, because the fraction is no longer denormal.  */
          if (fraction >= IMPLICIT_1)
          if (fraction >= IMPLICIT_1)
            {
            {
              exp += 1;
              exp += 1;
            }
            }
          fraction >>= NGARDS;
          fraction >>= NGARDS;
#endif /* NO_DENORMALS */
#endif /* NO_DENORMALS */
        }
        }
      else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
      else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
               && __builtin_expect (src->normal_exp > EXPBIAS, 0))
               && __builtin_expect (src->normal_exp > EXPBIAS, 0))
        {
        {
          exp = EXPMAX;
          exp = EXPMAX;
          fraction = 0;
          fraction = 0;
        }
        }
      else
      else
        {
        {
          exp = src->normal_exp + EXPBIAS;
          exp = src->normal_exp + EXPBIAS;
          if (!ROUND_TOWARDS_ZERO)
          if (!ROUND_TOWARDS_ZERO)
            {
            {
              /* 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;
                  exp += 1;
                  exp += 1;
                }
                }
            }
            }
          fraction >>= NGARDS;
          fraction >>= NGARDS;
 
 
          if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
          if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
            {
            {
              /* Saturate on overflow.  */
              /* Saturate on overflow.  */
              exp = EXPMAX;
              exp = EXPMAX;
              fraction = ((fractype) 1 << FRACBITS) - 1;
              fraction = ((fractype) 1 << FRACBITS) - 1;
            }
            }
        }
        }
    }
    }
 
 
  /* We previously used bitfields to store the number, but this doesn't
  /* We previously used bitfields to store the number, but this doesn't
     handle little/big endian systems conveniently, so use shifts and
     handle little/big endian systems conveniently, so use shifts and
     masks */
     masks */
#ifdef FLOAT_BIT_ORDER_MISMATCH
#ifdef FLOAT_BIT_ORDER_MISMATCH
  dst.bits.fraction = fraction;
  dst.bits.fraction = fraction;
  dst.bits.exp = exp;
  dst.bits.exp = exp;
  dst.bits.sign = sign;
  dst.bits.sign = sign;
#else
#else
# if defined TFLOAT && defined HALFFRACBITS
# if defined TFLOAT && defined HALFFRACBITS
 {
 {
   halffractype high, low, unity;
   halffractype high, low, unity;
   int lowsign, lowexp;
   int lowsign, lowexp;
 
 
   unity = (halffractype) 1 << HALFFRACBITS;
   unity = (halffractype) 1 << HALFFRACBITS;
 
 
   /* Set HIGH to the high double's significand, masking out the implicit 1.
   /* Set HIGH to the high double's significand, masking out the implicit 1.
      Set LOW to the low double's full significand.  */
      Set LOW to the low double's full significand.  */
   high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
   high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
   low = fraction & (unity * 2 - 1);
   low = fraction & (unity * 2 - 1);
 
 
   /* Get the initial sign and exponent of the low double.  */
   /* Get the initial sign and exponent of the low double.  */
   lowexp = exp - HALFFRACBITS - 1;
   lowexp = exp - HALFFRACBITS - 1;
   lowsign = sign;
   lowsign = sign;
 
 
   /* HIGH should be rounded like a normal double, making |LOW| <=
   /* HIGH should be rounded like a normal double, making |LOW| <=
      0.5 ULP of HIGH.  Assume round-to-nearest.  */
      0.5 ULP of HIGH.  Assume round-to-nearest.  */
   if (exp < EXPMAX)
   if (exp < EXPMAX)
     if (low > unity || (low == unity && (high & 1) == 1))
     if (low > unity || (low == unity && (high & 1) == 1))
       {
       {
         /* Round HIGH up and adjust LOW to match.  */
         /* Round HIGH up and adjust LOW to match.  */
         high++;
         high++;
         if (high == unity)
         if (high == unity)
           {
           {
             /* May make it infinite, but that's OK.  */
             /* May make it infinite, but that's OK.  */
             high = 0;
             high = 0;
             exp++;
             exp++;
           }
           }
         low = unity * 2 - low;
         low = unity * 2 - low;
         lowsign ^= 1;
         lowsign ^= 1;
       }
       }
 
 
   high |= (halffractype) exp << HALFFRACBITS;
   high |= (halffractype) exp << HALFFRACBITS;
   high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
   high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
 
 
   if (exp == EXPMAX || exp == 0 || low == 0)
   if (exp == EXPMAX || exp == 0 || low == 0)
     low = 0;
     low = 0;
   else
   else
     {
     {
       while (lowexp > 0 && low < unity)
       while (lowexp > 0 && low < unity)
         {
         {
           low <<= 1;
           low <<= 1;
           lowexp--;
           lowexp--;
         }
         }
 
 
       if (lowexp <= 0)
       if (lowexp <= 0)
         {
         {
           halffractype roundmsb, round;
           halffractype roundmsb, round;
           int shift;
           int shift;
 
 
           shift = 1 - lowexp;
           shift = 1 - lowexp;
           roundmsb = (1 << (shift - 1));
           roundmsb = (1 << (shift - 1));
           round = low & ((roundmsb << 1) - 1);
           round = low & ((roundmsb << 1) - 1);
 
 
           low >>= shift;
           low >>= shift;
           lowexp = 0;
           lowexp = 0;
 
 
           if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
           if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
             {
             {
               low++;
               low++;
               if (low == unity)
               if (low == unity)
                 /* LOW rounds up to the smallest normal number.  */
                 /* LOW rounds up to the smallest normal number.  */
                 lowexp++;
                 lowexp++;
             }
             }
         }
         }
 
 
       low &= unity - 1;
       low &= unity - 1;
       low |= (halffractype) lowexp << HALFFRACBITS;
       low |= (halffractype) lowexp << HALFFRACBITS;
       low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
       low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
     }
     }
   dst.value_raw = ((fractype) high << HALFSHIFT) | low;
   dst.value_raw = ((fractype) high << HALFSHIFT) | low;
 }
 }
# else
# else
  dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
  dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
  dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
  dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
  dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
  dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
# endif
# endif
#endif
#endif
 
 
#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
#ifdef TFLOAT
#ifdef TFLOAT
  {
  {
    qrtrfractype tmp1 = dst.words[0];
    qrtrfractype tmp1 = dst.words[0];
    qrtrfractype tmp2 = dst.words[1];
    qrtrfractype tmp2 = dst.words[1];
    dst.words[0] = dst.words[3];
    dst.words[0] = dst.words[3];
    dst.words[1] = dst.words[2];
    dst.words[1] = dst.words[2];
    dst.words[2] = tmp2;
    dst.words[2] = tmp2;
    dst.words[3] = tmp1;
    dst.words[3] = tmp1;
  }
  }
#else
#else
  {
  {
    halffractype tmp = dst.words[0];
    halffractype tmp = dst.words[0];
    dst.words[0] = dst.words[1];
    dst.words[0] = dst.words[1];
    dst.words[1] = tmp;
    dst.words[1] = tmp;
  }
  }
#endif
#endif
#endif
#endif
 
 
  return dst.value;
  return dst.value;
}
}
#endif
#endif
 
 
#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
void
void
unpack_d (FLO_union_type * src, fp_number_type * dst)
unpack_d (FLO_union_type * src, fp_number_type * dst)
{
{
  /* We previously used bitfields to store the number, but this doesn't
  /* We previously used bitfields to store the number, but this doesn't
     handle little/big endian systems conveniently, so use shifts and
     handle little/big endian systems conveniently, so use shifts and
     masks */
     masks */
  fractype fraction;
  fractype fraction;
  int exp;
  int exp;
  int sign;
  int sign;
 
 
#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
  FLO_union_type swapped;
  FLO_union_type swapped;
 
 
#ifdef TFLOAT
#ifdef TFLOAT
  swapped.words[0] = src->words[3];
  swapped.words[0] = src->words[3];
  swapped.words[1] = src->words[2];
  swapped.words[1] = src->words[2];
  swapped.words[2] = src->words[1];
  swapped.words[2] = src->words[1];
  swapped.words[3] = src->words[0];
  swapped.words[3] = src->words[0];
#else
#else
  swapped.words[0] = src->words[1];
  swapped.words[0] = src->words[1];
  swapped.words[1] = src->words[0];
  swapped.words[1] = src->words[0];
#endif
#endif
  src = &swapped;
  src = &swapped;
#endif
#endif
 
 
#ifdef FLOAT_BIT_ORDER_MISMATCH
#ifdef FLOAT_BIT_ORDER_MISMATCH
  fraction = src->bits.fraction;
  fraction = src->bits.fraction;
  exp = src->bits.exp;
  exp = src->bits.exp;
  sign = src->bits.sign;
  sign = src->bits.sign;
#else
#else
# if defined TFLOAT && defined HALFFRACBITS
# if defined TFLOAT && defined HALFFRACBITS
 {
 {
   halffractype high, low;
   halffractype high, low;
 
 
   high = src->value_raw >> HALFSHIFT;
   high = src->value_raw >> HALFSHIFT;
   low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
   low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
 
 
   fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
   fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
   fraction <<= FRACBITS - HALFFRACBITS;
   fraction <<= FRACBITS - HALFFRACBITS;
   exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
   exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
   sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
   sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
 
 
   if (exp != EXPMAX && exp != 0 && low != 0)
   if (exp != EXPMAX && exp != 0 && low != 0)
     {
     {
       int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
       int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
       int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
       int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
       int shift;
       int shift;
       fractype xlow;
       fractype xlow;
 
 
       xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
       xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
       if (lowexp)
       if (lowexp)
         xlow |= (((halffractype)1) << HALFFRACBITS);
         xlow |= (((halffractype)1) << HALFFRACBITS);
       else
       else
         lowexp = 1;
         lowexp = 1;
       shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
       shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
       if (shift > 0)
       if (shift > 0)
         xlow <<= shift;
         xlow <<= shift;
       else if (shift < 0)
       else if (shift < 0)
         xlow >>= -shift;
         xlow >>= -shift;
       if (sign == lowsign)
       if (sign == lowsign)
         fraction += xlow;
         fraction += xlow;
       else if (fraction >= xlow)
       else if (fraction >= xlow)
         fraction -= xlow;
         fraction -= xlow;
       else
       else
         {
         {
           /* The high part is a power of two but the full number is lower.
           /* The high part is a power of two but the full number is lower.
              This code will leave the implicit 1 in FRACTION, but we'd
              This code will leave the implicit 1 in FRACTION, but we'd
              have added that below anyway.  */
              have added that below anyway.  */
           fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
           fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
           exp--;
           exp--;
         }
         }
     }
     }
 }
 }
# else
# else
  fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
  fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
  exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
  exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
  sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
  sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
# endif
# endif
#endif
#endif
 
 
  dst->sign = sign;
  dst->sign = sign;
  if (exp == 0)
  if (exp == 0)
    {
    {
      /* Hmm.  Looks like 0 */
      /* Hmm.  Looks like 0 */
      if (fraction == 0
      if (fraction == 0
#ifdef NO_DENORMALS
#ifdef NO_DENORMALS
          || 1
          || 1
#endif
#endif
          )
          )
        {
        {
          /* tastes like zero */
          /* tastes like zero */
          dst->class = CLASS_ZERO;
          dst->class = CLASS_ZERO;
        }
        }
      else
      else
        {
        {
          /* Zero exponent with nonzero fraction - it's denormalized,
          /* Zero exponent with nonzero 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 = exp - EXPBIAS + 1;
          dst->normal_exp = 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 (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
  else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
           && __builtin_expect (exp == EXPMAX, 0))
           && __builtin_expect (exp == EXPMAX, 0))
    {
    {
      /* 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
        {
        {
          /* Nonzero fraction, means nan */
          /* Nonzero fraction, means nan */
#ifdef QUIET_NAN_NEGATED
#ifdef QUIET_NAN_NEGATED
          if ((fraction & QUIET_NAN) == 0)
          if ((fraction & QUIET_NAN) == 0)
#else
#else
          if (fraction & QUIET_NAN)
          if (fraction & QUIET_NAN)
#endif
#endif
            {
            {
              dst->class = CLASS_QNAN;
              dst->class = CLASS_QNAN;
            }
            }
          else
          else
            {
            {
              dst->class = CLASS_SNAN;
              dst->class = CLASS_SNAN;
            }
            }
          /* 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 = exp - EXPBIAS;
      dst->normal_exp = exp - EXPBIAS;
      dst->class = CLASS_NUMBER;
      dst->class = CLASS_NUMBER;
      dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
      dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
    }
    }
}
}
#endif /* L_unpack_df || L_unpack_sf */
#endif /* L_unpack_df || L_unpack_sf */
 
 
#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
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))
    {
    {
      if (iszero (a))
      if (iszero (a))
        {
        {
          *tmp = *a;
          *tmp = *a;
          tmp->sign = a->sign & b->sign;
          tmp->sign = a->sign & b->sign;
          return tmp;
          return tmp;
        }
        }
      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;
    int sdiff;
    int sdiff;
 
 
    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;
    sdiff = diff;
    sdiff = diff;
 
 
    if (diff < 0)
    if (diff < 0)
      diff = -diff;
      diff = -diff;
    if (diff < FRAC_NBITS)
    if (diff < FRAC_NBITS)
      {
      {
        if (sdiff > 0)
        if (sdiff > 0)
          {
          {
            b_normal_exp += diff;
            b_normal_exp += diff;
            LSHIFT (b_fraction, diff);
            LSHIFT (b_fraction, diff);
          }
          }
        else if (sdiff < 0)
        else if (sdiff < 0)
          {
          {
            a_normal_exp += diff;
            a_normal_exp += diff;
            LSHIFT (a_fraction, diff);
            LSHIFT (a_fraction, diff);
          }
          }
      }
      }
    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, 1);
      LSHIFT (tmp->fraction.ll, 1);
      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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &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);
}
}
#endif /* L_addsub_sf || L_addsub_df */
#endif /* L_addsub_sf || L_addsub_df */
 
 
#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
static inline __attribute__ ((__always_inline__)) fp_number_type *
static inline __attribute__ ((__always_inline__)) 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 numbers to get a
  /* Calculate the mantissa by multiplying both numbers to get a
     twice-as-wide number.  */
     twice-as-wide number.  */
  {
  {
#if defined(NO_DI_MODE) || defined(TFLOAT)
#if defined(NO_DI_MODE) || defined(TFLOAT)
    {
    {
      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;
 
 
      /* ??? 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 USIs to get a UDI, we're safe.  */
    /* Multiplying two USIs to get a UDI, we're safe.  */
    {
    {
      UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
      UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
 
 
      high = answer >> BITS_PER_SI;
      high = answer >> BITS_PER_SI;
      low = answer;
      low = answer;
    }
    }
#else
#else
    /* fractype is DImode, but we need the result to be twice as wide.
    /* fractype is DImode, but we need the result to be twice as wide.
       Assuming a widening multiply from DImode to TImode is not
       Assuming a widening multiply from DImode to TImode is not
       available, build one by hand.  */
       available, build one by hand.  */
    {
    {
      USItype nl = a->fraction.ll;
      USItype nl = a->fraction.ll;
      USItype nh = a->fraction.ll >> BITS_PER_SI;
      USItype nh = a->fraction.ll >> BITS_PER_SI;
      USItype ml = b->fraction.ll;
      USItype ml = b->fraction.ll;
      USItype mh = b->fraction.ll >> BITS_PER_SI;
      USItype mh = b->fraction.ll >> BITS_PER_SI;
      UDItype pp_ll = (UDItype) ml * nl;
      UDItype pp_ll = (UDItype) ml * nl;
      UDItype pp_hl = (UDItype) mh * nl;
      UDItype pp_hl = (UDItype) mh * nl;
      UDItype pp_lh = (UDItype) ml * nh;
      UDItype pp_lh = (UDItype) ml * nh;
      UDItype pp_hh = (UDItype) mh * nh;
      UDItype pp_hh = (UDItype) 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 += (UDItype)1 << BITS_PER_SI;
        res2 += (UDItype)1 << BITS_PER_SI;
      pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
      pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
      res0 = pp_ll + pp_hl;
      res0 = pp_ll + pp_hl;
      if (res0 < pp_ll)
      if (res0 < pp_ll)
        res2++;
        res2++;
      res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
      res2 += (ps_hh__ >> BITS_PER_SI) + 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
    + FRAC_NBITS - (FRACBITS + NGARDS);
    + FRAC_NBITS - (FRACBITS + NGARDS);
  tmp->sign = a->sign != b->sign;
  tmp->sign = a->sign != b->sign;
  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;
    }
    }
 
 
  if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
  if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
    {
    {
      if (high & (1 << NGARDS))
      if (high & (1 << NGARDS))
        {
        {
          /* Because we're half way, we would round to even by adding
          /* Because we're half way, we would round to even by adding
             GARDROUND + 1, except that's also done in the packing
             GARDROUND + 1, except that's also done in the packing
             function, and rounding twice will lose precision and cause
             function, and rounding twice will lose precision and cause
             the result to be too far off.  Example: 32-bit floats with
             the result to be too far off.  Example: 32-bit floats with
             bit patterns 0xfff * 0x3f800400 ~= 0xfff (less than 0.5ulp
             bit patterns 0xfff * 0x3f800400 ~= 0xfff (less than 0.5ulp
             off), not 0x1000 (more than 0.5ulp off).  */
             off), not 0x1000 (more than 0.5ulp off).  */
        }
        }
      else if (low)
      else if (low)
        {
        {
          /* We're a further than half way by a small amount corresponding
          /* We're a further than half way by a small amount corresponding
             to the bits set in "low".  Knowing that, we round here and
             to the bits set in "low".  Knowing that, we round here and
             not in pack_d, because there we don't have "low" available
             not in pack_d, because there we don't have "low" available
             anymore.  */
             anymore.  */
          high += GARDROUND + 1;
          high += GARDROUND + 1;
 
 
          /* Avoid further rounding in pack_d.  */
          /* Avoid further rounding in pack_d.  */
          high &= ~(fractype) GARDMASK;
          high &= ~(fractype) GARDMASK;
        }
        }
    }
    }
  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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &b);
 
 
  res = _fpmul_parts (&a, &b, &tmp);
  res = _fpmul_parts (&a, &b, &tmp);
 
 
  return pack_d (res);
  return pack_d (res);
}
}
#endif /* L_mul_sf || L_mul_df || L_mul_tf */
#endif /* L_mul_sf || L_mul_df || L_mul_tf */
 
 
#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
static inline __attribute__ ((__always_inline__)) fp_number_type *
static inline __attribute__ ((__always_inline__)) fp_number_type *
_fpdiv_parts (fp_number_type * a,
_fpdiv_parts (fp_number_type * a,
              fp_number_type * b)
              fp_number_type * b)
{
{
  fractype bit;
  fractype bit;
  fractype numerator;
  fractype numerator;
  fractype denominator;
  fractype denominator;
  fractype quotient;
  fractype quotient;
 
 
  if (isnan (a))
  if (isnan (a))
    {
    {
      return a;
      return a;
    }
    }
  if (isnan (b))
  if (isnan (b))
    {
    {
      return b;
      return b;
    }
    }
 
 
  a->sign = a->sign ^ b->sign;
  a->sign = a->sign ^ b->sign;
 
 
  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;
    }
    }
 
 
  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 a;
      return a;
    }
    }
 
 
  /* 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 */
  {
  {
    /* 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 (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
    if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
      {
      {
        if (quotient & (1 << NGARDS))
        if (quotient & (1 << NGARDS))
          {
          {
            /* Because we're half way, we would round to even by adding
            /* Because we're half way, we would round to even by adding
               GARDROUND + 1, except that's also done in the packing
               GARDROUND + 1, except that's also done in the packing
               function, and rounding twice will lose precision and cause
               function, and rounding twice will lose precision and cause
               the result to be too far off.  */
               the result to be too far off.  */
          }
          }
        else if (numerator)
        else if (numerator)
          {
          {
            /* We're a further than half way by the small amount
            /* We're a further than half way by the small amount
               corresponding to the bits set in "numerator".  Knowing
               corresponding to the bits set in "numerator".  Knowing
               that, we round here and not in pack_d, because there we
               that, we round here and not in pack_d, because there we
               don't have "numerator" available anymore.  */
               don't have "numerator" available anymore.  */
            quotient += GARDROUND + 1;
            quotient += GARDROUND + 1;
 
 
            /* Avoid further rounding in pack_d.  */
            /* Avoid further rounding in pack_d.  */
            quotient &= ~(fractype) GARDMASK;
            quotient &= ~(fractype) GARDMASK;
          }
          }
      }
      }
 
 
    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 *res;
  fp_number_type *res;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &b);
 
 
  res = _fpdiv_parts (&a, &b);
  res = _fpdiv_parts (&a, &b);
 
 
  return pack_d (res);
  return pack_d (res);
}
}
#endif /* L_div_sf || L_div_df */
#endif /* L_div_sf || L_div_df */
 
 
#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
    || defined(L_fpcmp_parts_tf)
    || defined(L_fpcmp_parts_tf)
/* 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
 */
 */
 
 
int
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 nonzero, just line up the columns...
       So since unordered must be nonzero, 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;
}
}
#endif
#endif
 
 
#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &b);
 
 
  return __fpcmp_parts (&a, &b);
  return __fpcmp_parts (&a, &b);
}
}
#endif /* L_compare_sf || L_compare_df */
#endif /* L_compare_sf || L_compare_df */
 
 
#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.  */
 
 
#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &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 /* L_eq_sf || L_eq_df */
#endif /* L_eq_sf || L_eq_df */
 
 
#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &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) ;
}
}
#endif /* L_ne_sf || L_ne_df */
#endif /* L_ne_sf || L_ne_df */
 
 
#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &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 /* L_gt_sf || L_gt_df */
#endif /* L_gt_sf || L_gt_df */
 
 
#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &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 /* L_ge_sf || L_ge_df */
#endif /* L_ge_sf || L_ge_df */
 
 
#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &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 /* L_lt_sf || L_lt_df */
#endif /* L_lt_sf || L_lt_df */
 
 
#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &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 /* L_le_sf || L_le_df */
#endif /* L_le_sf || L_le_df */
 
 
#endif /* ! US_SOFTWARE_GOFAST */
#endif /* ! US_SOFTWARE_GOFAST */
 
 
#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
CMPtype
CMPtype
_unord_f2 (FLO_type arg_a, FLO_type arg_b)
_unord_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;
  FLO_union_type au, bu;
  FLO_union_type au, bu;
 
 
  au.value = arg_a;
  au.value = arg_a;
  bu.value = arg_b;
  bu.value = arg_b;
 
 
  unpack_d (&au, &a);
  unpack_d (&au, &a);
  unpack_d (&bu, &b);
  unpack_d (&bu, &b);
 
 
  return (isnan (&a) || isnan (&b));
  return (isnan (&a) || isnan (&b));
}
}
#endif /* L_unord_sf || L_unord_df */
#endif /* L_unord_sf || L_unord_df */
 
 
#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
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
    {
    {
      USItype uarg;
      USItype uarg;
      int shift;
      int shift;
      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 == (- MAX_SI_INT - 1))
          if (arg_a == (- MAX_SI_INT - 1))
            {
            {
              return (FLO_type)(- MAX_SI_INT - 1);
              return (FLO_type)(- MAX_SI_INT - 1);
            }
            }
          uarg = (-arg_a);
          uarg = (-arg_a);
        }
        }
      else
      else
        uarg = arg_a;
        uarg = arg_a;
 
 
      in.fraction.ll = uarg;
      in.fraction.ll = uarg;
      shift = clzusi (uarg) - (BITS_PER_SI - 1 - FRACBITS - NGARDS);
      shift = clzusi (uarg) - (BITS_PER_SI - 1 - FRACBITS - NGARDS);
      if (shift > 0)
      if (shift > 0)
        {
        {
          in.fraction.ll <<= shift;
          in.fraction.ll <<= shift;
          in.normal_exp -= shift;
          in.normal_exp -= shift;
        }
        }
    }
    }
  return pack_d (&in);
  return pack_d (&in);
}
}
#endif /* L_si_to_sf || L_si_to_df */
#endif /* L_si_to_sf || L_si_to_df */
 
 
#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
FLO_type
FLO_type
usi_to_float (USItype arg_a)
usi_to_float (USItype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
 
 
  in.sign = 0;
  in.sign = 0;
  if (!arg_a)
  if (!arg_a)
    {
    {
      in.class = CLASS_ZERO;
      in.class = CLASS_ZERO;
    }
    }
  else
  else
    {
    {
      int shift;
      int shift;
      in.class = CLASS_NUMBER;
      in.class = CLASS_NUMBER;
      in.normal_exp = FRACBITS + NGARDS;
      in.normal_exp = FRACBITS + NGARDS;
      in.fraction.ll = arg_a;
      in.fraction.ll = arg_a;
 
 
      shift = clzusi (arg_a) - (BITS_PER_SI - 1 - FRACBITS - NGARDS);
      shift = clzusi (arg_a) - (BITS_PER_SI - 1 - FRACBITS - NGARDS);
      if (shift < 0)
      if (shift < 0)
        {
        {
          fractype guard = in.fraction.ll & (((fractype)1 << -shift) - 1);
          fractype guard = in.fraction.ll & (((fractype)1 << -shift) - 1);
          in.fraction.ll >>= -shift;
          in.fraction.ll >>= -shift;
          in.fraction.ll |= (guard != 0);
          in.fraction.ll |= (guard != 0);
          in.normal_exp -= shift;
          in.normal_exp -= shift;
        }
        }
      else if (shift > 0)
      else if (shift > 0)
        {
        {
          in.fraction.ll <<= shift;
          in.fraction.ll <<= shift;
          in.normal_exp -= shift;
          in.normal_exp -= shift;
        }
        }
    }
    }
  return pack_d (&in);
  return pack_d (&in);
}
}
#endif
#endif
 
 
#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
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;
  FLO_union_type au;
  FLO_union_type au;
 
 
  au.value = arg_a;
  au.value = arg_a;
  unpack_d (&au, &a);
  unpack_d (&au, &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)-1 : MAX_SI_INT;
    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
  /* 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 > BITS_PER_SI - 2)
  if (a.normal_exp > BITS_PER_SI - 2)
    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);
}
}
#endif /* L_sf_to_si || L_df_to_si */
#endif /* L_sf_to_si || L_df_to_si */
 
 
#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
/* 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;
  FLO_union_type au;
  FLO_union_type au;
 
 
  au.value = arg_a;
  au.value = arg_a;
  unpack_d (&au, &a);
  unpack_d (&au, &a);
 
 
  if (iszero (&a))
  if (iszero (&a))
    return 0;
    return 0;
  if (isnan (&a))
  if (isnan (&a))
    return 0;
    return 0;
  /* it is a negative number */
  /* it is a negative number */
  if (a.sign)
  if (a.sign)
    return 0;
    return 0;
  /* get reasonable MAX_USI_INT...  */
  /* get reasonable MAX_USI_INT...  */
  if (isinf (&a))
  if (isinf (&a))
    return MAX_USI_INT;
    return MAX_USI_INT;
  /* 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 > BITS_PER_SI - 1)
  if (a.normal_exp > BITS_PER_SI - 1)
    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 << (a.normal_exp - (FRACBITS + NGARDS));
    return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
  else
  else
    return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
    return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
}
}
#endif /* US_SOFTWARE_GOFAST */
#endif /* US_SOFTWARE_GOFAST */
#endif /* L_sf_to_usi || L_df_to_usi */
#endif /* L_sf_to_usi || L_df_to_usi */
 
 
#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
FLO_type
FLO_type
negate (FLO_type arg_a)
negate (FLO_type arg_a)
{
{
  fp_number_type a;
  fp_number_type a;
  FLO_union_type au;
  FLO_union_type au;
 
 
  au.value = arg_a;
  au.value = arg_a;
  unpack_d (&au, &a);
  unpack_d (&au, &a);
 
 
  flip_sign (&a);
  flip_sign (&a);
  return pack_d (&a);
  return pack_d (&a);
}
}
#endif /* L_negate_sf || L_negate_df */
#endif /* L_negate_sf || L_negate_df */
 
 
#ifdef FLOAT
#ifdef FLOAT
 
 
#if defined(L_make_sf)
#if defined(L_make_sf)
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);
}
}
#endif /* L_make_sf */
#endif /* L_make_sf */
 
 
#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.  */
 
 
#if defined(L_sf_to_df)
#if defined(L_sf_to_df)
DFtype
DFtype
sf_to_df (SFtype arg_a)
sf_to_df (SFtype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
  FLO_union_type au;
  FLO_union_type au;
 
 
  au.value = arg_a;
  au.value = arg_a;
  unpack_d (&au, &in);
  unpack_d (&au, &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 /* L_sf_to_df */
#endif /* L_sf_to_df */
 
 
#if defined(L_sf_to_tf) && defined(TMODES)
#if defined(L_sf_to_tf) && defined(TMODES)
TFtype
TFtype
sf_to_tf (SFtype arg_a)
sf_to_tf (SFtype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
  FLO_union_type au;
  FLO_union_type au;
 
 
  au.value = arg_a;
  au.value = arg_a;
  unpack_d (&au, &in);
  unpack_d (&au, &in);
 
 
  return __make_tp (in.class, in.sign, in.normal_exp,
  return __make_tp (in.class, in.sign, in.normal_exp,
                    ((UTItype) in.fraction.ll) << F_T_BITOFF);
                    ((UTItype) in.fraction.ll) << F_T_BITOFF);
}
}
#endif /* L_sf_to_df */
#endif /* L_sf_to_df */
 
 
#endif /* ! FLOAT_ONLY */
#endif /* ! FLOAT_ONLY */
#endif /* FLOAT */
#endif /* FLOAT */
 
 
#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);
 
 
#if defined(L_make_df)
#if defined(L_make_df)
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);
}
}
#endif /* L_make_df */
#endif /* L_make_df */
 
 
#if defined(L_df_to_sf)
#if defined(L_df_to_sf)
SFtype
SFtype
df_to_sf (DFtype arg_a)
df_to_sf (DFtype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
  USItype sffrac;
  USItype sffrac;
  FLO_union_type au;
  FLO_union_type au;
 
 
  au.value = arg_a;
  au.value = arg_a;
  unpack_d (&au, &in);
  unpack_d (&au, &in);
 
 
  sffrac = in.fraction.ll >> F_D_BITOFF;
  sffrac = in.fraction.ll >> F_D_BITOFF;
 
 
  /* We set the lowest guard bit in SFFRAC if we discarded any non
  /* We set the lowest guard bit in SFFRAC if we discarded any non
     zero bits.  */
     zero bits.  */
  if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
  if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
    sffrac |= 1;
    sffrac |= 1;
 
 
  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
}
}
#endif /* L_df_to_sf */
#endif /* L_df_to_sf */
 
 
#if defined(L_df_to_tf) && defined(TMODES) \
#if defined(L_df_to_tf) && defined(TMODES) \
    && !defined(FLOAT) && !defined(TFLOAT)
    && !defined(FLOAT) && !defined(TFLOAT)
TFtype
TFtype
df_to_tf (DFtype arg_a)
df_to_tf (DFtype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
  FLO_union_type au;
  FLO_union_type au;
 
 
  au.value = arg_a;
  au.value = arg_a;
  unpack_d (&au, &in);
  unpack_d (&au, &in);
 
 
  return __make_tp (in.class, in.sign, in.normal_exp,
  return __make_tp (in.class, in.sign, in.normal_exp,
                    ((UTItype) in.fraction.ll) << D_T_BITOFF);
                    ((UTItype) in.fraction.ll) << D_T_BITOFF);
}
}
#endif /* L_sf_to_df */
#endif /* L_sf_to_df */
 
 
#ifdef TFLOAT
#ifdef TFLOAT
#if defined(L_make_tf)
#if defined(L_make_tf)
TFtype
TFtype
__make_tp(fp_class_type class,
__make_tp(fp_class_type class,
             unsigned int sign,
             unsigned int sign,
             int exp,
             int exp,
             UTItype frac)
             UTItype 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);
}
}
#endif /* L_make_tf */
#endif /* L_make_tf */
 
 
#if defined(L_tf_to_df)
#if defined(L_tf_to_df)
DFtype
DFtype
tf_to_df (TFtype arg_a)
tf_to_df (TFtype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
  UDItype sffrac;
  UDItype sffrac;
  FLO_union_type au;
  FLO_union_type au;
 
 
  au.value = arg_a;
  au.value = arg_a;
  unpack_d (&au, &in);
  unpack_d (&au, &in);
 
 
  sffrac = in.fraction.ll >> D_T_BITOFF;
  sffrac = in.fraction.ll >> D_T_BITOFF;
 
 
  /* We set the lowest guard bit in SFFRAC if we discarded any non
  /* We set the lowest guard bit in SFFRAC if we discarded any non
     zero bits.  */
     zero bits.  */
  if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
  if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
    sffrac |= 1;
    sffrac |= 1;
 
 
  return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
  return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
}
}
#endif /* L_tf_to_df */
#endif /* L_tf_to_df */
 
 
#if defined(L_tf_to_sf)
#if defined(L_tf_to_sf)
SFtype
SFtype
tf_to_sf (TFtype arg_a)
tf_to_sf (TFtype arg_a)
{
{
  fp_number_type in;
  fp_number_type in;
  USItype sffrac;
  USItype sffrac;
  FLO_union_type au;
  FLO_union_type au;
 
 
  au.value = arg_a;
  au.value = arg_a;
  unpack_d (&au, &in);
  unpack_d (&au, &in);
 
 
  sffrac = in.fraction.ll >> F_T_BITOFF;
  sffrac = in.fraction.ll >> F_T_BITOFF;
 
 
  /* We set the lowest guard bit in SFFRAC if we discarded any non
  /* We set the lowest guard bit in SFFRAC if we discarded any non
     zero bits.  */
     zero bits.  */
  if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
  if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
    sffrac |= 1;
    sffrac |= 1;
 
 
  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
}
}
#endif /* L_tf_to_sf */
#endif /* L_tf_to_sf */
#endif /* TFLOAT */
#endif /* TFLOAT */
 
 
#endif /* ! FLOAT */
#endif /* ! FLOAT */
#endif /* !EXTENDED_FLOAT_STUBS */
#endif /* !EXTENDED_FLOAT_STUBS */
 
 

powered by: WebSVN 2.1.0

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