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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [real.c] - Diff between revs 38 and 154

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

Rev 38 Rev 154
/* real.c - software floating point emulation.
/* real.c - software floating point emulation.
   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
   2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
   2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
   Contributed by Stephen L. Moshier (moshier@world.std.com).
   Contributed by Stephen L. Moshier (moshier@world.std.com).
   Re-written by Richard Henderson <rth@redhat.com>
   Re-written by Richard Henderson <rth@redhat.com>
 
 
   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 3, or (at your option) any later
   Software Foundation; either version 3, or (at your option) any later
   version.
   version.
 
 
   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 COPYING3.  If not see
   along with GCC; see the file COPYING3.  If not see
   <http://www.gnu.org/licenses/>.  */
   <http://www.gnu.org/licenses/>.  */
 
 
#include "config.h"
#include "config.h"
#include "system.h"
#include "system.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tm.h"
#include "tm.h"
#include "tree.h"
#include "tree.h"
#include "toplev.h"
#include "toplev.h"
#include "real.h"
#include "real.h"
#include "tm_p.h"
#include "tm_p.h"
#include "dfp.h"
#include "dfp.h"
 
 
/* The floating point model used internally is not exactly IEEE 754
/* The floating point model used internally is not exactly IEEE 754
   compliant, and close to the description in the ISO C99 standard,
   compliant, and close to the description in the ISO C99 standard,
   section 5.2.4.2.2 Characteristics of floating types.
   section 5.2.4.2.2 Characteristics of floating types.
 
 
   Specifically
   Specifically
 
 
        x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
        x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
 
 
        where
        where
                s = sign (+- 1)
                s = sign (+- 1)
                b = base or radix, here always 2
                b = base or radix, here always 2
                e = exponent
                e = exponent
                p = precision (the number of base-b digits in the significand)
                p = precision (the number of base-b digits in the significand)
                f_k = the digits of the significand.
                f_k = the digits of the significand.
 
 
   We differ from typical IEEE 754 encodings in that the entire
   We differ from typical IEEE 754 encodings in that the entire
   significand is fractional.  Normalized significands are in the
   significand is fractional.  Normalized significands are in the
   range [0.5, 1.0).
   range [0.5, 1.0).
 
 
   A requirement of the model is that P be larger than the largest
   A requirement of the model is that P be larger than the largest
   supported target floating-point type by at least 2 bits.  This gives
   supported target floating-point type by at least 2 bits.  This gives
   us proper rounding when we truncate to the target type.  In addition,
   us proper rounding when we truncate to the target type.  In addition,
   E must be large enough to hold the smallest supported denormal number
   E must be large enough to hold the smallest supported denormal number
   in a normalized form.
   in a normalized form.
 
 
   Both of these requirements are easily satisfied.  The largest target
   Both of these requirements are easily satisfied.  The largest target
   significand is 113 bits; we store at least 160.  The smallest
   significand is 113 bits; we store at least 160.  The smallest
   denormal number fits in 17 exponent bits; we store 27.
   denormal number fits in 17 exponent bits; we store 27.
 
 
   Note that the decimal string conversion routines are sensitive to
   Note that the decimal string conversion routines are sensitive to
   rounding errors.  Since the raw arithmetic routines do not themselves
   rounding errors.  Since the raw arithmetic routines do not themselves
   have guard digits or rounding, the computation of 10**exp can
   have guard digits or rounding, the computation of 10**exp can
   accumulate more than a few digits of error.  The previous incarnation
   accumulate more than a few digits of error.  The previous incarnation
   of real.c successfully used a 144-bit fraction; given the current
   of real.c successfully used a 144-bit fraction; given the current
   layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits.
   layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits.
 
 
   Target floating point models that use base 16 instead of base 2
   Target floating point models that use base 16 instead of base 2
   (i.e. IBM 370), are handled during round_for_format, in which we
   (i.e. IBM 370), are handled during round_for_format, in which we
   canonicalize the exponent to be a multiple of 4 (log2(16)), and
   canonicalize the exponent to be a multiple of 4 (log2(16)), and
   adjust the significand to match.  */
   adjust the significand to match.  */
 
 
 
 
/* Used to classify two numbers simultaneously.  */
/* Used to classify two numbers simultaneously.  */
#define CLASS2(A, B)  ((A) << 2 | (B))
#define CLASS2(A, B)  ((A) << 2 | (B))
 
 
#if HOST_BITS_PER_LONG != 64 && HOST_BITS_PER_LONG != 32
#if HOST_BITS_PER_LONG != 64 && HOST_BITS_PER_LONG != 32
 #error "Some constant folding done by hand to avoid shift count warnings"
 #error "Some constant folding done by hand to avoid shift count warnings"
#endif
#endif
 
 
static void get_zero (REAL_VALUE_TYPE *, int);
static void get_zero (REAL_VALUE_TYPE *, int);
static void get_canonical_qnan (REAL_VALUE_TYPE *, int);
static void get_canonical_qnan (REAL_VALUE_TYPE *, int);
static void get_canonical_snan (REAL_VALUE_TYPE *, int);
static void get_canonical_snan (REAL_VALUE_TYPE *, int);
static void get_inf (REAL_VALUE_TYPE *, int);
static void get_inf (REAL_VALUE_TYPE *, int);
static bool sticky_rshift_significand (REAL_VALUE_TYPE *,
static bool sticky_rshift_significand (REAL_VALUE_TYPE *,
                                       const REAL_VALUE_TYPE *, unsigned int);
                                       const REAL_VALUE_TYPE *, unsigned int);
static void rshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
static void rshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
                                unsigned int);
                                unsigned int);
static void lshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
static void lshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
                                unsigned int);
                                unsigned int);
static void lshift_significand_1 (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
static void lshift_significand_1 (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
static bool add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *,
static bool add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *,
                              const REAL_VALUE_TYPE *);
                              const REAL_VALUE_TYPE *);
static bool sub_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
static bool sub_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
                              const REAL_VALUE_TYPE *, int);
                              const REAL_VALUE_TYPE *, int);
static void neg_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
static void neg_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
static int cmp_significands (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
static int cmp_significands (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
static int cmp_significand_0 (const REAL_VALUE_TYPE *);
static int cmp_significand_0 (const REAL_VALUE_TYPE *);
static void set_significand_bit (REAL_VALUE_TYPE *, unsigned int);
static void set_significand_bit (REAL_VALUE_TYPE *, unsigned int);
static void clear_significand_bit (REAL_VALUE_TYPE *, unsigned int);
static void clear_significand_bit (REAL_VALUE_TYPE *, unsigned int);
static bool test_significand_bit (REAL_VALUE_TYPE *, unsigned int);
static bool test_significand_bit (REAL_VALUE_TYPE *, unsigned int);
static void clear_significand_below (REAL_VALUE_TYPE *, unsigned int);
static void clear_significand_below (REAL_VALUE_TYPE *, unsigned int);
static bool div_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
static bool div_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
                              const REAL_VALUE_TYPE *);
                              const REAL_VALUE_TYPE *);
static void normalize (REAL_VALUE_TYPE *);
static void normalize (REAL_VALUE_TYPE *);
 
 
static bool do_add (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
static bool do_add (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
                    const REAL_VALUE_TYPE *, int);
                    const REAL_VALUE_TYPE *, int);
static bool do_multiply (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
static bool do_multiply (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
                         const REAL_VALUE_TYPE *);
                         const REAL_VALUE_TYPE *);
static bool do_divide (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
static bool do_divide (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
                       const REAL_VALUE_TYPE *);
                       const REAL_VALUE_TYPE *);
static int do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
static int do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
static void do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
static void do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
 
 
static unsigned long rtd_divmod (REAL_VALUE_TYPE *, REAL_VALUE_TYPE *);
static unsigned long rtd_divmod (REAL_VALUE_TYPE *, REAL_VALUE_TYPE *);
 
 
static const REAL_VALUE_TYPE * ten_to_ptwo (int);
static const REAL_VALUE_TYPE * ten_to_ptwo (int);
static const REAL_VALUE_TYPE * ten_to_mptwo (int);
static const REAL_VALUE_TYPE * ten_to_mptwo (int);
static const REAL_VALUE_TYPE * real_digit (int);
static const REAL_VALUE_TYPE * real_digit (int);
static void times_pten (REAL_VALUE_TYPE *, int);
static void times_pten (REAL_VALUE_TYPE *, int);
 
 
static void round_for_format (const struct real_format *, REAL_VALUE_TYPE *);
static void round_for_format (const struct real_format *, REAL_VALUE_TYPE *);


/* Initialize R with a positive zero.  */
/* Initialize R with a positive zero.  */
 
 
static inline void
static inline void
get_zero (REAL_VALUE_TYPE *r, int sign)
get_zero (REAL_VALUE_TYPE *r, int sign)
{
{
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
  r->sign = sign;
  r->sign = sign;
}
}
 
 
/* Initialize R with the canonical quiet NaN.  */
/* Initialize R with the canonical quiet NaN.  */
 
 
static inline void
static inline void
get_canonical_qnan (REAL_VALUE_TYPE *r, int sign)
get_canonical_qnan (REAL_VALUE_TYPE *r, int sign)
{
{
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
  r->cl = rvc_nan;
  r->cl = rvc_nan;
  r->sign = sign;
  r->sign = sign;
  r->canonical = 1;
  r->canonical = 1;
}
}
 
 
static inline void
static inline void
get_canonical_snan (REAL_VALUE_TYPE *r, int sign)
get_canonical_snan (REAL_VALUE_TYPE *r, int sign)
{
{
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
  r->cl = rvc_nan;
  r->cl = rvc_nan;
  r->sign = sign;
  r->sign = sign;
  r->signalling = 1;
  r->signalling = 1;
  r->canonical = 1;
  r->canonical = 1;
}
}
 
 
static inline void
static inline void
get_inf (REAL_VALUE_TYPE *r, int sign)
get_inf (REAL_VALUE_TYPE *r, int sign)
{
{
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
  r->cl = rvc_inf;
  r->cl = rvc_inf;
  r->sign = sign;
  r->sign = sign;
}
}
 
 


/* Right-shift the significand of A by N bits; put the result in the
/* Right-shift the significand of A by N bits; put the result in the
   significand of R.  If any one bits are shifted out, return true.  */
   significand of R.  If any one bits are shifted out, return true.  */
 
 
static bool
static bool
sticky_rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
sticky_rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
                           unsigned int n)
                           unsigned int n)
{
{
  unsigned long sticky = 0;
  unsigned long sticky = 0;
  unsigned int i, ofs = 0;
  unsigned int i, ofs = 0;
 
 
  if (n >= HOST_BITS_PER_LONG)
  if (n >= HOST_BITS_PER_LONG)
    {
    {
      for (i = 0, ofs = n / HOST_BITS_PER_LONG; i < ofs; ++i)
      for (i = 0, ofs = n / HOST_BITS_PER_LONG; i < ofs; ++i)
        sticky |= a->sig[i];
        sticky |= a->sig[i];
      n &= HOST_BITS_PER_LONG - 1;
      n &= HOST_BITS_PER_LONG - 1;
    }
    }
 
 
  if (n != 0)
  if (n != 0)
    {
    {
      sticky |= a->sig[ofs] & (((unsigned long)1 << n) - 1);
      sticky |= a->sig[ofs] & (((unsigned long)1 << n) - 1);
      for (i = 0; i < SIGSZ; ++i)
      for (i = 0; i < SIGSZ; ++i)
        {
        {
          r->sig[i]
          r->sig[i]
            = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n)
            = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n)
               | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1])
               | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1])
                  << (HOST_BITS_PER_LONG - n)));
                  << (HOST_BITS_PER_LONG - n)));
        }
        }
    }
    }
  else
  else
    {
    {
      for (i = 0; ofs + i < SIGSZ; ++i)
      for (i = 0; ofs + i < SIGSZ; ++i)
        r->sig[i] = a->sig[ofs + i];
        r->sig[i] = a->sig[ofs + i];
      for (; i < SIGSZ; ++i)
      for (; i < SIGSZ; ++i)
        r->sig[i] = 0;
        r->sig[i] = 0;
    }
    }
 
 
  return sticky != 0;
  return sticky != 0;
}
}
 
 
/* Right-shift the significand of A by N bits; put the result in the
/* Right-shift the significand of A by N bits; put the result in the
   significand of R.  */
   significand of R.  */
 
 
static void
static void
rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
                    unsigned int n)
                    unsigned int n)
{
{
  unsigned int i, ofs = n / HOST_BITS_PER_LONG;
  unsigned int i, ofs = n / HOST_BITS_PER_LONG;
 
 
  n &= HOST_BITS_PER_LONG - 1;
  n &= HOST_BITS_PER_LONG - 1;
  if (n != 0)
  if (n != 0)
    {
    {
      for (i = 0; i < SIGSZ; ++i)
      for (i = 0; i < SIGSZ; ++i)
        {
        {
          r->sig[i]
          r->sig[i]
            = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n)
            = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n)
               | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1])
               | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1])
                  << (HOST_BITS_PER_LONG - n)));
                  << (HOST_BITS_PER_LONG - n)));
        }
        }
    }
    }
  else
  else
    {
    {
      for (i = 0; ofs + i < SIGSZ; ++i)
      for (i = 0; ofs + i < SIGSZ; ++i)
        r->sig[i] = a->sig[ofs + i];
        r->sig[i] = a->sig[ofs + i];
      for (; i < SIGSZ; ++i)
      for (; i < SIGSZ; ++i)
        r->sig[i] = 0;
        r->sig[i] = 0;
    }
    }
}
}
 
 
/* Left-shift the significand of A by N bits; put the result in the
/* Left-shift the significand of A by N bits; put the result in the
   significand of R.  */
   significand of R.  */
 
 
static void
static void
lshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
lshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
                    unsigned int n)
                    unsigned int n)
{
{
  unsigned int i, ofs = n / HOST_BITS_PER_LONG;
  unsigned int i, ofs = n / HOST_BITS_PER_LONG;
 
 
  n &= HOST_BITS_PER_LONG - 1;
  n &= HOST_BITS_PER_LONG - 1;
  if (n == 0)
  if (n == 0)
    {
    {
      for (i = 0; ofs + i < SIGSZ; ++i)
      for (i = 0; ofs + i < SIGSZ; ++i)
        r->sig[SIGSZ-1-i] = a->sig[SIGSZ-1-i-ofs];
        r->sig[SIGSZ-1-i] = a->sig[SIGSZ-1-i-ofs];
      for (; i < SIGSZ; ++i)
      for (; i < SIGSZ; ++i)
        r->sig[SIGSZ-1-i] = 0;
        r->sig[SIGSZ-1-i] = 0;
    }
    }
  else
  else
    for (i = 0; i < SIGSZ; ++i)
    for (i = 0; i < SIGSZ; ++i)
      {
      {
        r->sig[SIGSZ-1-i]
        r->sig[SIGSZ-1-i]
          = (((ofs + i >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs]) << n)
          = (((ofs + i >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs]) << n)
             | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs-1])
             | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs-1])
                >> (HOST_BITS_PER_LONG - n)));
                >> (HOST_BITS_PER_LONG - n)));
      }
      }
}
}
 
 
/* Likewise, but N is specialized to 1.  */
/* Likewise, but N is specialized to 1.  */
 
 
static inline void
static inline void
lshift_significand_1 (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
lshift_significand_1 (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
{
{
  unsigned int i;
  unsigned int i;
 
 
  for (i = SIGSZ - 1; i > 0; --i)
  for (i = SIGSZ - 1; i > 0; --i)
    r->sig[i] = (a->sig[i] << 1) | (a->sig[i-1] >> (HOST_BITS_PER_LONG - 1));
    r->sig[i] = (a->sig[i] << 1) | (a->sig[i-1] >> (HOST_BITS_PER_LONG - 1));
  r->sig[0] = a->sig[0] << 1;
  r->sig[0] = a->sig[0] << 1;
}
}
 
 
/* Add the significands of A and B, placing the result in R.  Return
/* Add the significands of A and B, placing the result in R.  Return
   true if there was carry out of the most significant word.  */
   true if there was carry out of the most significant word.  */
 
 
static inline bool
static inline bool
add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
                  const REAL_VALUE_TYPE *b)
                  const REAL_VALUE_TYPE *b)
{
{
  bool carry = false;
  bool carry = false;
  int i;
  int i;
 
 
  for (i = 0; i < SIGSZ; ++i)
  for (i = 0; i < SIGSZ; ++i)
    {
    {
      unsigned long ai = a->sig[i];
      unsigned long ai = a->sig[i];
      unsigned long ri = ai + b->sig[i];
      unsigned long ri = ai + b->sig[i];
 
 
      if (carry)
      if (carry)
        {
        {
          carry = ri < ai;
          carry = ri < ai;
          carry |= ++ri == 0;
          carry |= ++ri == 0;
        }
        }
      else
      else
        carry = ri < ai;
        carry = ri < ai;
 
 
      r->sig[i] = ri;
      r->sig[i] = ri;
    }
    }
 
 
  return carry;
  return carry;
}
}
 
 
/* Subtract the significands of A and B, placing the result in R.  CARRY is
/* Subtract the significands of A and B, placing the result in R.  CARRY is
   true if there's a borrow incoming to the least significant word.
   true if there's a borrow incoming to the least significant word.
   Return true if there was borrow out of the most significant word.  */
   Return true if there was borrow out of the most significant word.  */
 
 
static inline bool
static inline bool
sub_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
sub_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
                  const REAL_VALUE_TYPE *b, int carry)
                  const REAL_VALUE_TYPE *b, int carry)
{
{
  int i;
  int i;
 
 
  for (i = 0; i < SIGSZ; ++i)
  for (i = 0; i < SIGSZ; ++i)
    {
    {
      unsigned long ai = a->sig[i];
      unsigned long ai = a->sig[i];
      unsigned long ri = ai - b->sig[i];
      unsigned long ri = ai - b->sig[i];
 
 
      if (carry)
      if (carry)
        {
        {
          carry = ri > ai;
          carry = ri > ai;
          carry |= ~--ri == 0;
          carry |= ~--ri == 0;
        }
        }
      else
      else
        carry = ri > ai;
        carry = ri > ai;
 
 
      r->sig[i] = ri;
      r->sig[i] = ri;
    }
    }
 
 
  return carry;
  return carry;
}
}
 
 
/* Negate the significand A, placing the result in R.  */
/* Negate the significand A, placing the result in R.  */
 
 
static inline void
static inline void
neg_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
neg_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
{
{
  bool carry = true;
  bool carry = true;
  int i;
  int i;
 
 
  for (i = 0; i < SIGSZ; ++i)
  for (i = 0; i < SIGSZ; ++i)
    {
    {
      unsigned long ri, ai = a->sig[i];
      unsigned long ri, ai = a->sig[i];
 
 
      if (carry)
      if (carry)
        {
        {
          if (ai)
          if (ai)
            {
            {
              ri = -ai;
              ri = -ai;
              carry = false;
              carry = false;
            }
            }
          else
          else
            ri = ai;
            ri = ai;
        }
        }
      else
      else
        ri = ~ai;
        ri = ~ai;
 
 
      r->sig[i] = ri;
      r->sig[i] = ri;
    }
    }
}
}
 
 
/* Compare significands.  Return tri-state vs zero.  */
/* Compare significands.  Return tri-state vs zero.  */
 
 
static inline int
static inline int
cmp_significands (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
cmp_significands (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
{
{
  int i;
  int i;
 
 
  for (i = SIGSZ - 1; i >= 0; --i)
  for (i = SIGSZ - 1; i >= 0; --i)
    {
    {
      unsigned long ai = a->sig[i];
      unsigned long ai = a->sig[i];
      unsigned long bi = b->sig[i];
      unsigned long bi = b->sig[i];
 
 
      if (ai > bi)
      if (ai > bi)
        return 1;
        return 1;
      if (ai < bi)
      if (ai < bi)
        return -1;
        return -1;
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
/* Return true if A is nonzero.  */
/* Return true if A is nonzero.  */
 
 
static inline int
static inline int
cmp_significand_0 (const REAL_VALUE_TYPE *a)
cmp_significand_0 (const REAL_VALUE_TYPE *a)
{
{
  int i;
  int i;
 
 
  for (i = SIGSZ - 1; i >= 0; --i)
  for (i = SIGSZ - 1; i >= 0; --i)
    if (a->sig[i])
    if (a->sig[i])
      return 1;
      return 1;
 
 
  return 0;
  return 0;
}
}
 
 
/* Set bit N of the significand of R.  */
/* Set bit N of the significand of R.  */
 
 
static inline void
static inline void
set_significand_bit (REAL_VALUE_TYPE *r, unsigned int n)
set_significand_bit (REAL_VALUE_TYPE *r, unsigned int n)
{
{
  r->sig[n / HOST_BITS_PER_LONG]
  r->sig[n / HOST_BITS_PER_LONG]
    |= (unsigned long)1 << (n % HOST_BITS_PER_LONG);
    |= (unsigned long)1 << (n % HOST_BITS_PER_LONG);
}
}
 
 
/* Clear bit N of the significand of R.  */
/* Clear bit N of the significand of R.  */
 
 
static inline void
static inline void
clear_significand_bit (REAL_VALUE_TYPE *r, unsigned int n)
clear_significand_bit (REAL_VALUE_TYPE *r, unsigned int n)
{
{
  r->sig[n / HOST_BITS_PER_LONG]
  r->sig[n / HOST_BITS_PER_LONG]
    &= ~((unsigned long)1 << (n % HOST_BITS_PER_LONG));
    &= ~((unsigned long)1 << (n % HOST_BITS_PER_LONG));
}
}
 
 
/* Test bit N of the significand of R.  */
/* Test bit N of the significand of R.  */
 
 
static inline bool
static inline bool
test_significand_bit (REAL_VALUE_TYPE *r, unsigned int n)
test_significand_bit (REAL_VALUE_TYPE *r, unsigned int n)
{
{
  /* ??? Compiler bug here if we return this expression directly.
  /* ??? Compiler bug here if we return this expression directly.
     The conversion to bool strips the "&1" and we wind up testing
     The conversion to bool strips the "&1" and we wind up testing
     e.g. 2 != 0 -> true.  Seen in gcc version 3.2 20020520.  */
     e.g. 2 != 0 -> true.  Seen in gcc version 3.2 20020520.  */
  int t = (r->sig[n / HOST_BITS_PER_LONG] >> (n % HOST_BITS_PER_LONG)) & 1;
  int t = (r->sig[n / HOST_BITS_PER_LONG] >> (n % HOST_BITS_PER_LONG)) & 1;
  return t;
  return t;
}
}
 
 
/* Clear bits 0..N-1 of the significand of R.  */
/* Clear bits 0..N-1 of the significand of R.  */
 
 
static void
static void
clear_significand_below (REAL_VALUE_TYPE *r, unsigned int n)
clear_significand_below (REAL_VALUE_TYPE *r, unsigned int n)
{
{
  int i, w = n / HOST_BITS_PER_LONG;
  int i, w = n / HOST_BITS_PER_LONG;
 
 
  for (i = 0; i < w; ++i)
  for (i = 0; i < w; ++i)
    r->sig[i] = 0;
    r->sig[i] = 0;
 
 
  r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1);
  r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1);
}
}
 
 
/* Divide the significands of A and B, placing the result in R.  Return
/* Divide the significands of A and B, placing the result in R.  Return
   true if the division was inexact.  */
   true if the division was inexact.  */
 
 
static inline bool
static inline bool
div_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
div_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
                  const REAL_VALUE_TYPE *b)
                  const REAL_VALUE_TYPE *b)
{
{
  REAL_VALUE_TYPE u;
  REAL_VALUE_TYPE u;
  int i, bit = SIGNIFICAND_BITS - 1;
  int i, bit = SIGNIFICAND_BITS - 1;
  unsigned long msb, inexact;
  unsigned long msb, inexact;
 
 
  u = *a;
  u = *a;
  memset (r->sig, 0, sizeof (r->sig));
  memset (r->sig, 0, sizeof (r->sig));
 
 
  msb = 0;
  msb = 0;
  goto start;
  goto start;
  do
  do
    {
    {
      msb = u.sig[SIGSZ-1] & SIG_MSB;
      msb = u.sig[SIGSZ-1] & SIG_MSB;
      lshift_significand_1 (&u, &u);
      lshift_significand_1 (&u, &u);
    start:
    start:
      if (msb || cmp_significands (&u, b) >= 0)
      if (msb || cmp_significands (&u, b) >= 0)
        {
        {
          sub_significands (&u, &u, b, 0);
          sub_significands (&u, &u, b, 0);
          set_significand_bit (r, bit);
          set_significand_bit (r, bit);
        }
        }
    }
    }
  while (--bit >= 0);
  while (--bit >= 0);
 
 
  for (i = 0, inexact = 0; i < SIGSZ; i++)
  for (i = 0, inexact = 0; i < SIGSZ; i++)
    inexact |= u.sig[i];
    inexact |= u.sig[i];
 
 
  return inexact != 0;
  return inexact != 0;
}
}
 
 
/* Adjust the exponent and significand of R such that the most
/* Adjust the exponent and significand of R such that the most
   significant bit is set.  We underflow to zero and overflow to
   significant bit is set.  We underflow to zero and overflow to
   infinity here, without denormals.  (The intermediate representation
   infinity here, without denormals.  (The intermediate representation
   exponent is large enough to handle target denormals normalized.)  */
   exponent is large enough to handle target denormals normalized.)  */
 
 
static void
static void
normalize (REAL_VALUE_TYPE *r)
normalize (REAL_VALUE_TYPE *r)
{
{
  int shift = 0, exp;
  int shift = 0, exp;
  int i, j;
  int i, j;
 
 
  if (r->decimal)
  if (r->decimal)
    return;
    return;
 
 
  /* Find the first word that is nonzero.  */
  /* Find the first word that is nonzero.  */
  for (i = SIGSZ - 1; i >= 0; i--)
  for (i = SIGSZ - 1; i >= 0; i--)
    if (r->sig[i] == 0)
    if (r->sig[i] == 0)
      shift += HOST_BITS_PER_LONG;
      shift += HOST_BITS_PER_LONG;
    else
    else
      break;
      break;
 
 
  /* Zero significand flushes to zero.  */
  /* Zero significand flushes to zero.  */
  if (i < 0)
  if (i < 0)
    {
    {
      r->cl = rvc_zero;
      r->cl = rvc_zero;
      SET_REAL_EXP (r, 0);
      SET_REAL_EXP (r, 0);
      return;
      return;
    }
    }
 
 
  /* Find the first bit that is nonzero.  */
  /* Find the first bit that is nonzero.  */
  for (j = 0; ; j++)
  for (j = 0; ; j++)
    if (r->sig[i] & ((unsigned long)1 << (HOST_BITS_PER_LONG - 1 - j)))
    if (r->sig[i] & ((unsigned long)1 << (HOST_BITS_PER_LONG - 1 - j)))
      break;
      break;
  shift += j;
  shift += j;
 
 
  if (shift > 0)
  if (shift > 0)
    {
    {
      exp = REAL_EXP (r) - shift;
      exp = REAL_EXP (r) - shift;
      if (exp > MAX_EXP)
      if (exp > MAX_EXP)
        get_inf (r, r->sign);
        get_inf (r, r->sign);
      else if (exp < -MAX_EXP)
      else if (exp < -MAX_EXP)
        get_zero (r, r->sign);
        get_zero (r, r->sign);
      else
      else
        {
        {
          SET_REAL_EXP (r, exp);
          SET_REAL_EXP (r, exp);
          lshift_significand (r, r, shift);
          lshift_significand (r, r, shift);
        }
        }
    }
    }
}
}


/* Calculate R = A + (SUBTRACT_P ? -B : B).  Return true if the
/* Calculate R = A + (SUBTRACT_P ? -B : B).  Return true if the
   result may be inexact due to a loss of precision.  */
   result may be inexact due to a loss of precision.  */
 
 
static bool
static bool
do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
        const REAL_VALUE_TYPE *b, int subtract_p)
        const REAL_VALUE_TYPE *b, int subtract_p)
{
{
  int dexp, sign, exp;
  int dexp, sign, exp;
  REAL_VALUE_TYPE t;
  REAL_VALUE_TYPE t;
  bool inexact = false;
  bool inexact = false;
 
 
  /* Determine if we need to add or subtract.  */
  /* Determine if we need to add or subtract.  */
  sign = a->sign;
  sign = a->sign;
  subtract_p = (sign ^ b->sign) ^ subtract_p;
  subtract_p = (sign ^ b->sign) ^ subtract_p;
 
 
  switch (CLASS2 (a->cl, b->cl))
  switch (CLASS2 (a->cl, b->cl))
    {
    {
    case CLASS2 (rvc_zero, rvc_zero):
    case CLASS2 (rvc_zero, rvc_zero):
      /* -0 + -0 = -0, -0 - +0 = -0; all other cases yield +0.  */
      /* -0 + -0 = -0, -0 - +0 = -0; all other cases yield +0.  */
      get_zero (r, sign & !subtract_p);
      get_zero (r, sign & !subtract_p);
      return false;
      return false;
 
 
    case CLASS2 (rvc_zero, rvc_normal):
    case CLASS2 (rvc_zero, rvc_normal):
    case CLASS2 (rvc_zero, rvc_inf):
    case CLASS2 (rvc_zero, rvc_inf):
    case CLASS2 (rvc_zero, rvc_nan):
    case CLASS2 (rvc_zero, rvc_nan):
      /* 0 + ANY = ANY.  */
      /* 0 + ANY = ANY.  */
    case CLASS2 (rvc_normal, rvc_nan):
    case CLASS2 (rvc_normal, rvc_nan):
    case CLASS2 (rvc_inf, rvc_nan):
    case CLASS2 (rvc_inf, rvc_nan):
    case CLASS2 (rvc_nan, rvc_nan):
    case CLASS2 (rvc_nan, rvc_nan):
      /* ANY + NaN = NaN.  */
      /* ANY + NaN = NaN.  */
    case CLASS2 (rvc_normal, rvc_inf):
    case CLASS2 (rvc_normal, rvc_inf):
      /* R + Inf = Inf.  */
      /* R + Inf = Inf.  */
      *r = *b;
      *r = *b;
      r->sign = sign ^ subtract_p;
      r->sign = sign ^ subtract_p;
      return false;
      return false;
 
 
    case CLASS2 (rvc_normal, rvc_zero):
    case CLASS2 (rvc_normal, rvc_zero):
    case CLASS2 (rvc_inf, rvc_zero):
    case CLASS2 (rvc_inf, rvc_zero):
    case CLASS2 (rvc_nan, rvc_zero):
    case CLASS2 (rvc_nan, rvc_zero):
      /* ANY + 0 = ANY.  */
      /* ANY + 0 = ANY.  */
    case CLASS2 (rvc_nan, rvc_normal):
    case CLASS2 (rvc_nan, rvc_normal):
    case CLASS2 (rvc_nan, rvc_inf):
    case CLASS2 (rvc_nan, rvc_inf):
      /* NaN + ANY = NaN.  */
      /* NaN + ANY = NaN.  */
    case CLASS2 (rvc_inf, rvc_normal):
    case CLASS2 (rvc_inf, rvc_normal):
      /* Inf + R = Inf.  */
      /* Inf + R = Inf.  */
      *r = *a;
      *r = *a;
      return false;
      return false;
 
 
    case CLASS2 (rvc_inf, rvc_inf):
    case CLASS2 (rvc_inf, rvc_inf):
      if (subtract_p)
      if (subtract_p)
        /* Inf - Inf = NaN.  */
        /* Inf - Inf = NaN.  */
        get_canonical_qnan (r, 0);
        get_canonical_qnan (r, 0);
      else
      else
        /* Inf + Inf = Inf.  */
        /* Inf + Inf = Inf.  */
        *r = *a;
        *r = *a;
      return false;
      return false;
 
 
    case CLASS2 (rvc_normal, rvc_normal):
    case CLASS2 (rvc_normal, rvc_normal):
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  /* Swap the arguments such that A has the larger exponent.  */
  /* Swap the arguments such that A has the larger exponent.  */
  dexp = REAL_EXP (a) - REAL_EXP (b);
  dexp = REAL_EXP (a) - REAL_EXP (b);
  if (dexp < 0)
  if (dexp < 0)
    {
    {
      const REAL_VALUE_TYPE *t;
      const REAL_VALUE_TYPE *t;
      t = a, a = b, b = t;
      t = a, a = b, b = t;
      dexp = -dexp;
      dexp = -dexp;
      sign ^= subtract_p;
      sign ^= subtract_p;
    }
    }
  exp = REAL_EXP (a);
  exp = REAL_EXP (a);
 
 
  /* If the exponents are not identical, we need to shift the
  /* If the exponents are not identical, we need to shift the
     significand of B down.  */
     significand of B down.  */
  if (dexp > 0)
  if (dexp > 0)
    {
    {
      /* If the exponents are too far apart, the significands
      /* If the exponents are too far apart, the significands
         do not overlap, which makes the subtraction a noop.  */
         do not overlap, which makes the subtraction a noop.  */
      if (dexp >= SIGNIFICAND_BITS)
      if (dexp >= SIGNIFICAND_BITS)
        {
        {
          *r = *a;
          *r = *a;
          r->sign = sign;
          r->sign = sign;
          return true;
          return true;
        }
        }
 
 
      inexact |= sticky_rshift_significand (&t, b, dexp);
      inexact |= sticky_rshift_significand (&t, b, dexp);
      b = &t;
      b = &t;
    }
    }
 
 
  if (subtract_p)
  if (subtract_p)
    {
    {
      if (sub_significands (r, a, b, inexact))
      if (sub_significands (r, a, b, inexact))
        {
        {
          /* We got a borrow out of the subtraction.  That means that
          /* We got a borrow out of the subtraction.  That means that
             A and B had the same exponent, and B had the larger
             A and B had the same exponent, and B had the larger
             significand.  We need to swap the sign and negate the
             significand.  We need to swap the sign and negate the
             significand.  */
             significand.  */
          sign ^= 1;
          sign ^= 1;
          neg_significand (r, r);
          neg_significand (r, r);
        }
        }
    }
    }
  else
  else
    {
    {
      if (add_significands (r, a, b))
      if (add_significands (r, a, b))
        {
        {
          /* We got carry out of the addition.  This means we need to
          /* We got carry out of the addition.  This means we need to
             shift the significand back down one bit and increase the
             shift the significand back down one bit and increase the
             exponent.  */
             exponent.  */
          inexact |= sticky_rshift_significand (r, r, 1);
          inexact |= sticky_rshift_significand (r, r, 1);
          r->sig[SIGSZ-1] |= SIG_MSB;
          r->sig[SIGSZ-1] |= SIG_MSB;
          if (++exp > MAX_EXP)
          if (++exp > MAX_EXP)
            {
            {
              get_inf (r, sign);
              get_inf (r, sign);
              return true;
              return true;
            }
            }
        }
        }
    }
    }
 
 
  r->cl = rvc_normal;
  r->cl = rvc_normal;
  r->sign = sign;
  r->sign = sign;
  SET_REAL_EXP (r, exp);
  SET_REAL_EXP (r, exp);
  /* Zero out the remaining fields.  */
  /* Zero out the remaining fields.  */
  r->signalling = 0;
  r->signalling = 0;
  r->canonical = 0;
  r->canonical = 0;
  r->decimal = 0;
  r->decimal = 0;
 
 
  /* Re-normalize the result.  */
  /* Re-normalize the result.  */
  normalize (r);
  normalize (r);
 
 
  /* Special case: if the subtraction results in zero, the result
  /* Special case: if the subtraction results in zero, the result
     is positive.  */
     is positive.  */
  if (r->cl == rvc_zero)
  if (r->cl == rvc_zero)
    r->sign = 0;
    r->sign = 0;
  else
  else
    r->sig[0] |= inexact;
    r->sig[0] |= inexact;
 
 
  return inexact;
  return inexact;
}
}
 
 
/* Calculate R = A * B.  Return true if the result may be inexact.  */
/* Calculate R = A * B.  Return true if the result may be inexact.  */
 
 
static bool
static bool
do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
             const REAL_VALUE_TYPE *b)
             const REAL_VALUE_TYPE *b)
{
{
  REAL_VALUE_TYPE u, t, *rr;
  REAL_VALUE_TYPE u, t, *rr;
  unsigned int i, j, k;
  unsigned int i, j, k;
  int sign = a->sign ^ b->sign;
  int sign = a->sign ^ b->sign;
  bool inexact = false;
  bool inexact = false;
 
 
  switch (CLASS2 (a->cl, b->cl))
  switch (CLASS2 (a->cl, b->cl))
    {
    {
    case CLASS2 (rvc_zero, rvc_zero):
    case CLASS2 (rvc_zero, rvc_zero):
    case CLASS2 (rvc_zero, rvc_normal):
    case CLASS2 (rvc_zero, rvc_normal):
    case CLASS2 (rvc_normal, rvc_zero):
    case CLASS2 (rvc_normal, rvc_zero):
      /* +-0 * ANY = 0 with appropriate sign.  */
      /* +-0 * ANY = 0 with appropriate sign.  */
      get_zero (r, sign);
      get_zero (r, sign);
      return false;
      return false;
 
 
    case CLASS2 (rvc_zero, rvc_nan):
    case CLASS2 (rvc_zero, rvc_nan):
    case CLASS2 (rvc_normal, rvc_nan):
    case CLASS2 (rvc_normal, rvc_nan):
    case CLASS2 (rvc_inf, rvc_nan):
    case CLASS2 (rvc_inf, rvc_nan):
    case CLASS2 (rvc_nan, rvc_nan):
    case CLASS2 (rvc_nan, rvc_nan):
      /* ANY * NaN = NaN.  */
      /* ANY * NaN = NaN.  */
      *r = *b;
      *r = *b;
      r->sign = sign;
      r->sign = sign;
      return false;
      return false;
 
 
    case CLASS2 (rvc_nan, rvc_zero):
    case CLASS2 (rvc_nan, rvc_zero):
    case CLASS2 (rvc_nan, rvc_normal):
    case CLASS2 (rvc_nan, rvc_normal):
    case CLASS2 (rvc_nan, rvc_inf):
    case CLASS2 (rvc_nan, rvc_inf):
      /* NaN * ANY = NaN.  */
      /* NaN * ANY = NaN.  */
      *r = *a;
      *r = *a;
      r->sign = sign;
      r->sign = sign;
      return false;
      return false;
 
 
    case CLASS2 (rvc_zero, rvc_inf):
    case CLASS2 (rvc_zero, rvc_inf):
    case CLASS2 (rvc_inf, rvc_zero):
    case CLASS2 (rvc_inf, rvc_zero):
      /* 0 * Inf = NaN */
      /* 0 * Inf = NaN */
      get_canonical_qnan (r, sign);
      get_canonical_qnan (r, sign);
      return false;
      return false;
 
 
    case CLASS2 (rvc_inf, rvc_inf):
    case CLASS2 (rvc_inf, rvc_inf):
    case CLASS2 (rvc_normal, rvc_inf):
    case CLASS2 (rvc_normal, rvc_inf):
    case CLASS2 (rvc_inf, rvc_normal):
    case CLASS2 (rvc_inf, rvc_normal):
      /* Inf * Inf = Inf, R * Inf = Inf */
      /* Inf * Inf = Inf, R * Inf = Inf */
      get_inf (r, sign);
      get_inf (r, sign);
      return false;
      return false;
 
 
    case CLASS2 (rvc_normal, rvc_normal):
    case CLASS2 (rvc_normal, rvc_normal):
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (r == a || r == b)
  if (r == a || r == b)
    rr = &t;
    rr = &t;
  else
  else
    rr = r;
    rr = r;
  get_zero (rr, 0);
  get_zero (rr, 0);
 
 
  /* Collect all the partial products.  Since we don't have sure access
  /* Collect all the partial products.  Since we don't have sure access
     to a widening multiply, we split each long into two half-words.
     to a widening multiply, we split each long into two half-words.
 
 
     Consider the long-hand form of a four half-word multiplication:
     Consider the long-hand form of a four half-word multiplication:
 
 
                 A  B  C  D
                 A  B  C  D
              *  E  F  G  H
              *  E  F  G  H
             --------------
             --------------
                DE DF DG DH
                DE DF DG DH
             CE CF CG CH
             CE CF CG CH
          BE BF BG BH
          BE BF BG BH
       AE AF AG AH
       AE AF AG AH
 
 
     We construct partial products of the widened half-word products
     We construct partial products of the widened half-word products
     that are known to not overlap, e.g. DF+DH.  Each such partial
     that are known to not overlap, e.g. DF+DH.  Each such partial
     product is given its proper exponent, which allows us to sum them
     product is given its proper exponent, which allows us to sum them
     and obtain the finished product.  */
     and obtain the finished product.  */
 
 
  for (i = 0; i < SIGSZ * 2; ++i)
  for (i = 0; i < SIGSZ * 2; ++i)
    {
    {
      unsigned long ai = a->sig[i / 2];
      unsigned long ai = a->sig[i / 2];
      if (i & 1)
      if (i & 1)
        ai >>= HOST_BITS_PER_LONG / 2;
        ai >>= HOST_BITS_PER_LONG / 2;
      else
      else
        ai &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
        ai &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
 
 
      if (ai == 0)
      if (ai == 0)
        continue;
        continue;
 
 
      for (j = 0; j < 2; ++j)
      for (j = 0; j < 2; ++j)
        {
        {
          int exp = (REAL_EXP (a) - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2)
          int exp = (REAL_EXP (a) - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2)
                     + (REAL_EXP (b) - (1-j)*(HOST_BITS_PER_LONG/2)));
                     + (REAL_EXP (b) - (1-j)*(HOST_BITS_PER_LONG/2)));
 
 
          if (exp > MAX_EXP)
          if (exp > MAX_EXP)
            {
            {
              get_inf (r, sign);
              get_inf (r, sign);
              return true;
              return true;
            }
            }
          if (exp < -MAX_EXP)
          if (exp < -MAX_EXP)
            {
            {
              /* Would underflow to zero, which we shouldn't bother adding.  */
              /* Would underflow to zero, which we shouldn't bother adding.  */
              inexact = true;
              inexact = true;
              continue;
              continue;
            }
            }
 
 
          memset (&u, 0, sizeof (u));
          memset (&u, 0, sizeof (u));
          u.cl = rvc_normal;
          u.cl = rvc_normal;
          SET_REAL_EXP (&u, exp);
          SET_REAL_EXP (&u, exp);
 
 
          for (k = j; k < SIGSZ * 2; k += 2)
          for (k = j; k < SIGSZ * 2; k += 2)
            {
            {
              unsigned long bi = b->sig[k / 2];
              unsigned long bi = b->sig[k / 2];
              if (k & 1)
              if (k & 1)
                bi >>= HOST_BITS_PER_LONG / 2;
                bi >>= HOST_BITS_PER_LONG / 2;
              else
              else
                bi &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
                bi &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
 
 
              u.sig[k / 2] = ai * bi;
              u.sig[k / 2] = ai * bi;
            }
            }
 
 
          normalize (&u);
          normalize (&u);
          inexact |= do_add (rr, rr, &u, 0);
          inexact |= do_add (rr, rr, &u, 0);
        }
        }
    }
    }
 
 
  rr->sign = sign;
  rr->sign = sign;
  if (rr != r)
  if (rr != r)
    *r = t;
    *r = t;
 
 
  return inexact;
  return inexact;
}
}
 
 
/* Calculate R = A / B.  Return true if the result may be inexact.  */
/* Calculate R = A / B.  Return true if the result may be inexact.  */
 
 
static bool
static bool
do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
           const REAL_VALUE_TYPE *b)
           const REAL_VALUE_TYPE *b)
{
{
  int exp, sign = a->sign ^ b->sign;
  int exp, sign = a->sign ^ b->sign;
  REAL_VALUE_TYPE t, *rr;
  REAL_VALUE_TYPE t, *rr;
  bool inexact;
  bool inexact;
 
 
  switch (CLASS2 (a->cl, b->cl))
  switch (CLASS2 (a->cl, b->cl))
    {
    {
    case CLASS2 (rvc_zero, rvc_zero):
    case CLASS2 (rvc_zero, rvc_zero):
      /* 0 / 0 = NaN.  */
      /* 0 / 0 = NaN.  */
    case CLASS2 (rvc_inf, rvc_inf):
    case CLASS2 (rvc_inf, rvc_inf):
      /* Inf / Inf = NaN.  */
      /* Inf / Inf = NaN.  */
      get_canonical_qnan (r, sign);
      get_canonical_qnan (r, sign);
      return false;
      return false;
 
 
    case CLASS2 (rvc_zero, rvc_normal):
    case CLASS2 (rvc_zero, rvc_normal):
    case CLASS2 (rvc_zero, rvc_inf):
    case CLASS2 (rvc_zero, rvc_inf):
      /* 0 / ANY = 0.  */
      /* 0 / ANY = 0.  */
    case CLASS2 (rvc_normal, rvc_inf):
    case CLASS2 (rvc_normal, rvc_inf):
      /* R / Inf = 0.  */
      /* R / Inf = 0.  */
      get_zero (r, sign);
      get_zero (r, sign);
      return false;
      return false;
 
 
    case CLASS2 (rvc_normal, rvc_zero):
    case CLASS2 (rvc_normal, rvc_zero):
      /* R / 0 = Inf.  */
      /* R / 0 = Inf.  */
    case CLASS2 (rvc_inf, rvc_zero):
    case CLASS2 (rvc_inf, rvc_zero):
      /* Inf / 0 = Inf.  */
      /* Inf / 0 = Inf.  */
      get_inf (r, sign);
      get_inf (r, sign);
      return false;
      return false;
 
 
    case CLASS2 (rvc_zero, rvc_nan):
    case CLASS2 (rvc_zero, rvc_nan):
    case CLASS2 (rvc_normal, rvc_nan):
    case CLASS2 (rvc_normal, rvc_nan):
    case CLASS2 (rvc_inf, rvc_nan):
    case CLASS2 (rvc_inf, rvc_nan):
    case CLASS2 (rvc_nan, rvc_nan):
    case CLASS2 (rvc_nan, rvc_nan):
      /* ANY / NaN = NaN.  */
      /* ANY / NaN = NaN.  */
      *r = *b;
      *r = *b;
      r->sign = sign;
      r->sign = sign;
      return false;
      return false;
 
 
    case CLASS2 (rvc_nan, rvc_zero):
    case CLASS2 (rvc_nan, rvc_zero):
    case CLASS2 (rvc_nan, rvc_normal):
    case CLASS2 (rvc_nan, rvc_normal):
    case CLASS2 (rvc_nan, rvc_inf):
    case CLASS2 (rvc_nan, rvc_inf):
      /* NaN / ANY = NaN.  */
      /* NaN / ANY = NaN.  */
      *r = *a;
      *r = *a;
      r->sign = sign;
      r->sign = sign;
      return false;
      return false;
 
 
    case CLASS2 (rvc_inf, rvc_normal):
    case CLASS2 (rvc_inf, rvc_normal):
      /* Inf / R = Inf.  */
      /* Inf / R = Inf.  */
      get_inf (r, sign);
      get_inf (r, sign);
      return false;
      return false;
 
 
    case CLASS2 (rvc_normal, rvc_normal):
    case CLASS2 (rvc_normal, rvc_normal):
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (r == a || r == b)
  if (r == a || r == b)
    rr = &t;
    rr = &t;
  else
  else
    rr = r;
    rr = r;
 
 
  /* Make sure all fields in the result are initialized.  */
  /* Make sure all fields in the result are initialized.  */
  get_zero (rr, 0);
  get_zero (rr, 0);
  rr->cl = rvc_normal;
  rr->cl = rvc_normal;
  rr->sign = sign;
  rr->sign = sign;
 
 
  exp = REAL_EXP (a) - REAL_EXP (b) + 1;
  exp = REAL_EXP (a) - REAL_EXP (b) + 1;
  if (exp > MAX_EXP)
  if (exp > MAX_EXP)
    {
    {
      get_inf (r, sign);
      get_inf (r, sign);
      return true;
      return true;
    }
    }
  if (exp < -MAX_EXP)
  if (exp < -MAX_EXP)
    {
    {
      get_zero (r, sign);
      get_zero (r, sign);
      return true;
      return true;
    }
    }
  SET_REAL_EXP (rr, exp);
  SET_REAL_EXP (rr, exp);
 
 
  inexact = div_significands (rr, a, b);
  inexact = div_significands (rr, a, b);
 
 
  /* Re-normalize the result.  */
  /* Re-normalize the result.  */
  normalize (rr);
  normalize (rr);
  rr->sig[0] |= inexact;
  rr->sig[0] |= inexact;
 
 
  if (rr != r)
  if (rr != r)
    *r = t;
    *r = t;
 
 
  return inexact;
  return inexact;
}
}
 
 
/* Return a tri-state comparison of A vs B.  Return NAN_RESULT if
/* Return a tri-state comparison of A vs B.  Return NAN_RESULT if
   one of the two operands is a NaN.  */
   one of the two operands is a NaN.  */
 
 
static int
static int
do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
            int nan_result)
            int nan_result)
{
{
  int ret;
  int ret;
 
 
  switch (CLASS2 (a->cl, b->cl))
  switch (CLASS2 (a->cl, b->cl))
    {
    {
    case CLASS2 (rvc_zero, rvc_zero):
    case CLASS2 (rvc_zero, rvc_zero):
      /* Sign of zero doesn't matter for compares.  */
      /* Sign of zero doesn't matter for compares.  */
      return 0;
      return 0;
 
 
    case CLASS2 (rvc_inf, rvc_zero):
    case CLASS2 (rvc_inf, rvc_zero):
    case CLASS2 (rvc_inf, rvc_normal):
    case CLASS2 (rvc_inf, rvc_normal):
    case CLASS2 (rvc_normal, rvc_zero):
    case CLASS2 (rvc_normal, rvc_zero):
      return (a->sign ? -1 : 1);
      return (a->sign ? -1 : 1);
 
 
    case CLASS2 (rvc_inf, rvc_inf):
    case CLASS2 (rvc_inf, rvc_inf):
      return -a->sign - -b->sign;
      return -a->sign - -b->sign;
 
 
    case CLASS2 (rvc_zero, rvc_normal):
    case CLASS2 (rvc_zero, rvc_normal):
    case CLASS2 (rvc_zero, rvc_inf):
    case CLASS2 (rvc_zero, rvc_inf):
    case CLASS2 (rvc_normal, rvc_inf):
    case CLASS2 (rvc_normal, rvc_inf):
      return (b->sign ? 1 : -1);
      return (b->sign ? 1 : -1);
 
 
    case CLASS2 (rvc_zero, rvc_nan):
    case CLASS2 (rvc_zero, rvc_nan):
    case CLASS2 (rvc_normal, rvc_nan):
    case CLASS2 (rvc_normal, rvc_nan):
    case CLASS2 (rvc_inf, rvc_nan):
    case CLASS2 (rvc_inf, rvc_nan):
    case CLASS2 (rvc_nan, rvc_nan):
    case CLASS2 (rvc_nan, rvc_nan):
    case CLASS2 (rvc_nan, rvc_zero):
    case CLASS2 (rvc_nan, rvc_zero):
    case CLASS2 (rvc_nan, rvc_normal):
    case CLASS2 (rvc_nan, rvc_normal):
    case CLASS2 (rvc_nan, rvc_inf):
    case CLASS2 (rvc_nan, rvc_inf):
      return nan_result;
      return nan_result;
 
 
    case CLASS2 (rvc_normal, rvc_normal):
    case CLASS2 (rvc_normal, rvc_normal):
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (a->sign != b->sign)
  if (a->sign != b->sign)
    return -a->sign - -b->sign;
    return -a->sign - -b->sign;
 
 
  if (a->decimal || b->decimal)
  if (a->decimal || b->decimal)
    return decimal_do_compare (a, b, nan_result);
    return decimal_do_compare (a, b, nan_result);
 
 
  if (REAL_EXP (a) > REAL_EXP (b))
  if (REAL_EXP (a) > REAL_EXP (b))
    ret = 1;
    ret = 1;
  else if (REAL_EXP (a) < REAL_EXP (b))
  else if (REAL_EXP (a) < REAL_EXP (b))
    ret = -1;
    ret = -1;
  else
  else
    ret = cmp_significands (a, b);
    ret = cmp_significands (a, b);
 
 
  return (a->sign ? -ret : ret);
  return (a->sign ? -ret : ret);
}
}
 
 
/* Return A truncated to an integral value toward zero.  */
/* Return A truncated to an integral value toward zero.  */
 
 
static void
static void
do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
{
{
  *r = *a;
  *r = *a;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      if (r->decimal)
      if (r->decimal)
        {
        {
          decimal_do_fix_trunc (r, a);
          decimal_do_fix_trunc (r, a);
          return;
          return;
        }
        }
      if (REAL_EXP (r) <= 0)
      if (REAL_EXP (r) <= 0)
        get_zero (r, r->sign);
        get_zero (r, r->sign);
      else if (REAL_EXP (r) < SIGNIFICAND_BITS)
      else if (REAL_EXP (r) < SIGNIFICAND_BITS)
        clear_significand_below (r, SIGNIFICAND_BITS - REAL_EXP (r));
        clear_significand_below (r, SIGNIFICAND_BITS - REAL_EXP (r));
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
}
}
 
 
/* Perform the binary or unary operation described by CODE.
/* Perform the binary or unary operation described by CODE.
   For a unary operation, leave OP1 NULL.  This function returns
   For a unary operation, leave OP1 NULL.  This function returns
   true if the result may be inexact due to loss of precision.  */
   true if the result may be inexact due to loss of precision.  */
 
 
bool
bool
real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
                 const REAL_VALUE_TYPE *op1)
                 const REAL_VALUE_TYPE *op1)
{
{
  enum tree_code code = icode;
  enum tree_code code = icode;
 
 
  if (op0->decimal || (op1 && op1->decimal))
  if (op0->decimal || (op1 && op1->decimal))
    return decimal_real_arithmetic (r, icode, op0, op1);
    return decimal_real_arithmetic (r, icode, op0, op1);
 
 
  switch (code)
  switch (code)
    {
    {
    case PLUS_EXPR:
    case PLUS_EXPR:
      return do_add (r, op0, op1, 0);
      return do_add (r, op0, op1, 0);
 
 
    case MINUS_EXPR:
    case MINUS_EXPR:
      return do_add (r, op0, op1, 1);
      return do_add (r, op0, op1, 1);
 
 
    case MULT_EXPR:
    case MULT_EXPR:
      return do_multiply (r, op0, op1);
      return do_multiply (r, op0, op1);
 
 
    case RDIV_EXPR:
    case RDIV_EXPR:
      return do_divide (r, op0, op1);
      return do_divide (r, op0, op1);
 
 
    case MIN_EXPR:
    case MIN_EXPR:
      if (op1->cl == rvc_nan)
      if (op1->cl == rvc_nan)
        *r = *op1;
        *r = *op1;
      else if (do_compare (op0, op1, -1) < 0)
      else if (do_compare (op0, op1, -1) < 0)
        *r = *op0;
        *r = *op0;
      else
      else
        *r = *op1;
        *r = *op1;
      break;
      break;
 
 
    case MAX_EXPR:
    case MAX_EXPR:
      if (op1->cl == rvc_nan)
      if (op1->cl == rvc_nan)
        *r = *op1;
        *r = *op1;
      else if (do_compare (op0, op1, 1) < 0)
      else if (do_compare (op0, op1, 1) < 0)
        *r = *op1;
        *r = *op1;
      else
      else
        *r = *op0;
        *r = *op0;
      break;
      break;
 
 
    case NEGATE_EXPR:
    case NEGATE_EXPR:
      *r = *op0;
      *r = *op0;
      r->sign ^= 1;
      r->sign ^= 1;
      break;
      break;
 
 
    case ABS_EXPR:
    case ABS_EXPR:
      *r = *op0;
      *r = *op0;
      r->sign = 0;
      r->sign = 0;
      break;
      break;
 
 
    case FIX_TRUNC_EXPR:
    case FIX_TRUNC_EXPR:
      do_fix_trunc (r, op0);
      do_fix_trunc (r, op0);
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
  return false;
  return false;
}
}
 
 
/* Legacy.  Similar, but return the result directly.  */
/* Legacy.  Similar, but return the result directly.  */
 
 
REAL_VALUE_TYPE
REAL_VALUE_TYPE
real_arithmetic2 (int icode, const REAL_VALUE_TYPE *op0,
real_arithmetic2 (int icode, const REAL_VALUE_TYPE *op0,
                  const REAL_VALUE_TYPE *op1)
                  const REAL_VALUE_TYPE *op1)
{
{
  REAL_VALUE_TYPE r;
  REAL_VALUE_TYPE r;
  real_arithmetic (&r, icode, op0, op1);
  real_arithmetic (&r, icode, op0, op1);
  return r;
  return r;
}
}
 
 
bool
bool
real_compare (int icode, const REAL_VALUE_TYPE *op0,
real_compare (int icode, const REAL_VALUE_TYPE *op0,
              const REAL_VALUE_TYPE *op1)
              const REAL_VALUE_TYPE *op1)
{
{
  enum tree_code code = icode;
  enum tree_code code = icode;
 
 
  switch (code)
  switch (code)
    {
    {
    case LT_EXPR:
    case LT_EXPR:
      return do_compare (op0, op1, 1) < 0;
      return do_compare (op0, op1, 1) < 0;
    case LE_EXPR:
    case LE_EXPR:
      return do_compare (op0, op1, 1) <= 0;
      return do_compare (op0, op1, 1) <= 0;
    case GT_EXPR:
    case GT_EXPR:
      return do_compare (op0, op1, -1) > 0;
      return do_compare (op0, op1, -1) > 0;
    case GE_EXPR:
    case GE_EXPR:
      return do_compare (op0, op1, -1) >= 0;
      return do_compare (op0, op1, -1) >= 0;
    case EQ_EXPR:
    case EQ_EXPR:
      return do_compare (op0, op1, -1) == 0;
      return do_compare (op0, op1, -1) == 0;
    case NE_EXPR:
    case NE_EXPR:
      return do_compare (op0, op1, -1) != 0;
      return do_compare (op0, op1, -1) != 0;
    case UNORDERED_EXPR:
    case UNORDERED_EXPR:
      return op0->cl == rvc_nan || op1->cl == rvc_nan;
      return op0->cl == rvc_nan || op1->cl == rvc_nan;
    case ORDERED_EXPR:
    case ORDERED_EXPR:
      return op0->cl != rvc_nan && op1->cl != rvc_nan;
      return op0->cl != rvc_nan && op1->cl != rvc_nan;
    case UNLT_EXPR:
    case UNLT_EXPR:
      return do_compare (op0, op1, -1) < 0;
      return do_compare (op0, op1, -1) < 0;
    case UNLE_EXPR:
    case UNLE_EXPR:
      return do_compare (op0, op1, -1) <= 0;
      return do_compare (op0, op1, -1) <= 0;
    case UNGT_EXPR:
    case UNGT_EXPR:
      return do_compare (op0, op1, 1) > 0;
      return do_compare (op0, op1, 1) > 0;
    case UNGE_EXPR:
    case UNGE_EXPR:
      return do_compare (op0, op1, 1) >= 0;
      return do_compare (op0, op1, 1) >= 0;
    case UNEQ_EXPR:
    case UNEQ_EXPR:
      return do_compare (op0, op1, 0) == 0;
      return do_compare (op0, op1, 0) == 0;
    case LTGT_EXPR:
    case LTGT_EXPR:
      return do_compare (op0, op1, 0) != 0;
      return do_compare (op0, op1, 0) != 0;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
}
}
 
 
/* Return floor log2(R).  */
/* Return floor log2(R).  */
 
 
int
int
real_exponent (const REAL_VALUE_TYPE *r)
real_exponent (const REAL_VALUE_TYPE *r)
{
{
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      return 0;
      return 0;
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      return (unsigned int)-1 >> 1;
      return (unsigned int)-1 >> 1;
    case rvc_normal:
    case rvc_normal:
      return REAL_EXP (r);
      return REAL_EXP (r);
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
}
}
 
 
/* R = OP0 * 2**EXP.  */
/* R = OP0 * 2**EXP.  */
 
 
void
void
real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, int exp)
real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, int exp)
{
{
  *r = *op0;
  *r = *op0;
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      exp += REAL_EXP (op0);
      exp += REAL_EXP (op0);
      if (exp > MAX_EXP)
      if (exp > MAX_EXP)
        get_inf (r, r->sign);
        get_inf (r, r->sign);
      else if (exp < -MAX_EXP)
      else if (exp < -MAX_EXP)
        get_zero (r, r->sign);
        get_zero (r, r->sign);
      else
      else
        SET_REAL_EXP (r, exp);
        SET_REAL_EXP (r, exp);
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
}
}
 
 
/* Determine whether a floating-point value X is infinite.  */
/* Determine whether a floating-point value X is infinite.  */
 
 
bool
bool
real_isinf (const REAL_VALUE_TYPE *r)
real_isinf (const REAL_VALUE_TYPE *r)
{
{
  return (r->cl == rvc_inf);
  return (r->cl == rvc_inf);
}
}
 
 
/* Determine whether a floating-point value X is a NaN.  */
/* Determine whether a floating-point value X is a NaN.  */
 
 
bool
bool
real_isnan (const REAL_VALUE_TYPE *r)
real_isnan (const REAL_VALUE_TYPE *r)
{
{
  return (r->cl == rvc_nan);
  return (r->cl == rvc_nan);
}
}
 
 
/* Determine whether a floating-point value X is negative.  */
/* Determine whether a floating-point value X is negative.  */
 
 
bool
bool
real_isneg (const REAL_VALUE_TYPE *r)
real_isneg (const REAL_VALUE_TYPE *r)
{
{
  return r->sign;
  return r->sign;
}
}
 
 
/* Determine whether a floating-point value X is minus zero.  */
/* Determine whether a floating-point value X is minus zero.  */
 
 
bool
bool
real_isnegzero (const REAL_VALUE_TYPE *r)
real_isnegzero (const REAL_VALUE_TYPE *r)
{
{
  return r->sign && r->cl == rvc_zero;
  return r->sign && r->cl == rvc_zero;
}
}
 
 
/* Compare two floating-point objects for bitwise identity.  */
/* Compare two floating-point objects for bitwise identity.  */
 
 
bool
bool
real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
{
{
  int i;
  int i;
 
 
  if (a->cl != b->cl)
  if (a->cl != b->cl)
    return false;
    return false;
  if (a->sign != b->sign)
  if (a->sign != b->sign)
    return false;
    return false;
 
 
  switch (a->cl)
  switch (a->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
    case rvc_inf:
    case rvc_inf:
      return true;
      return true;
 
 
    case rvc_normal:
    case rvc_normal:
      if (a->decimal != b->decimal)
      if (a->decimal != b->decimal)
        return false;
        return false;
      if (REAL_EXP (a) != REAL_EXP (b))
      if (REAL_EXP (a) != REAL_EXP (b))
        return false;
        return false;
      break;
      break;
 
 
    case rvc_nan:
    case rvc_nan:
      if (a->signalling != b->signalling)
      if (a->signalling != b->signalling)
        return false;
        return false;
      /* The significand is ignored for canonical NaNs.  */
      /* The significand is ignored for canonical NaNs.  */
      if (a->canonical || b->canonical)
      if (a->canonical || b->canonical)
        return a->canonical == b->canonical;
        return a->canonical == b->canonical;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  for (i = 0; i < SIGSZ; ++i)
  for (i = 0; i < SIGSZ; ++i)
    if (a->sig[i] != b->sig[i])
    if (a->sig[i] != b->sig[i])
      return false;
      return false;
 
 
  return true;
  return true;
}
}
 
 
/* Try to change R into its exact multiplicative inverse in machine
/* Try to change R into its exact multiplicative inverse in machine
   mode MODE.  Return true if successful.  */
   mode MODE.  Return true if successful.  */
 
 
bool
bool
exact_real_inverse (enum machine_mode mode, REAL_VALUE_TYPE *r)
exact_real_inverse (enum machine_mode mode, REAL_VALUE_TYPE *r)
{
{
  const REAL_VALUE_TYPE *one = real_digit (1);
  const REAL_VALUE_TYPE *one = real_digit (1);
  REAL_VALUE_TYPE u;
  REAL_VALUE_TYPE u;
  int i;
  int i;
 
 
  if (r->cl != rvc_normal)
  if (r->cl != rvc_normal)
    return false;
    return false;
 
 
  /* Check for a power of two: all significand bits zero except the MSB.  */
  /* Check for a power of two: all significand bits zero except the MSB.  */
  for (i = 0; i < SIGSZ-1; ++i)
  for (i = 0; i < SIGSZ-1; ++i)
    if (r->sig[i] != 0)
    if (r->sig[i] != 0)
      return false;
      return false;
  if (r->sig[SIGSZ-1] != SIG_MSB)
  if (r->sig[SIGSZ-1] != SIG_MSB)
    return false;
    return false;
 
 
  /* Find the inverse and truncate to the required mode.  */
  /* Find the inverse and truncate to the required mode.  */
  do_divide (&u, one, r);
  do_divide (&u, one, r);
  real_convert (&u, mode, &u);
  real_convert (&u, mode, &u);
 
 
  /* The rounding may have overflowed.  */
  /* The rounding may have overflowed.  */
  if (u.cl != rvc_normal)
  if (u.cl != rvc_normal)
    return false;
    return false;
  for (i = 0; i < SIGSZ-1; ++i)
  for (i = 0; i < SIGSZ-1; ++i)
    if (u.sig[i] != 0)
    if (u.sig[i] != 0)
      return false;
      return false;
  if (u.sig[SIGSZ-1] != SIG_MSB)
  if (u.sig[SIGSZ-1] != SIG_MSB)
    return false;
    return false;
 
 
  *r = u;
  *r = u;
  return true;
  return true;
}
}


/* Render R as an integer.  */
/* Render R as an integer.  */
 
 
HOST_WIDE_INT
HOST_WIDE_INT
real_to_integer (const REAL_VALUE_TYPE *r)
real_to_integer (const REAL_VALUE_TYPE *r)
{
{
  unsigned HOST_WIDE_INT i;
  unsigned HOST_WIDE_INT i;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
    underflow:
    underflow:
      return 0;
      return 0;
 
 
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
    overflow:
    overflow:
      i = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
      i = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
      if (!r->sign)
      if (!r->sign)
        i--;
        i--;
      return i;
      return i;
 
 
    case rvc_normal:
    case rvc_normal:
      if (r->decimal)
      if (r->decimal)
        return decimal_real_to_integer (r);
        return decimal_real_to_integer (r);
 
 
      if (REAL_EXP (r) <= 0)
      if (REAL_EXP (r) <= 0)
        goto underflow;
        goto underflow;
      /* Only force overflow for unsigned overflow.  Signed overflow is
      /* Only force overflow for unsigned overflow.  Signed overflow is
         undefined, so it doesn't matter what we return, and some callers
         undefined, so it doesn't matter what we return, and some callers
         expect to be able to use this routine for both signed and
         expect to be able to use this routine for both signed and
         unsigned conversions.  */
         unsigned conversions.  */
      if (REAL_EXP (r) > HOST_BITS_PER_WIDE_INT)
      if (REAL_EXP (r) > HOST_BITS_PER_WIDE_INT)
        goto overflow;
        goto overflow;
 
 
      if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
      if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
        i = r->sig[SIGSZ-1];
        i = r->sig[SIGSZ-1];
      else
      else
        {
        {
          gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG);
          gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG);
          i = r->sig[SIGSZ-1];
          i = r->sig[SIGSZ-1];
          i = i << (HOST_BITS_PER_LONG - 1) << 1;
          i = i << (HOST_BITS_PER_LONG - 1) << 1;
          i |= r->sig[SIGSZ-2];
          i |= r->sig[SIGSZ-2];
        }
        }
 
 
      i >>= HOST_BITS_PER_WIDE_INT - REAL_EXP (r);
      i >>= HOST_BITS_PER_WIDE_INT - REAL_EXP (r);
 
 
      if (r->sign)
      if (r->sign)
        i = -i;
        i = -i;
      return i;
      return i;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
}
}
 
 
/* Likewise, but to an integer pair, HI+LOW.  */
/* Likewise, but to an integer pair, HI+LOW.  */
 
 
void
void
real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
                  const REAL_VALUE_TYPE *r)
                  const REAL_VALUE_TYPE *r)
{
{
  REAL_VALUE_TYPE t;
  REAL_VALUE_TYPE t;
  HOST_WIDE_INT low, high;
  HOST_WIDE_INT low, high;
  int exp;
  int exp;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
    underflow:
    underflow:
      low = high = 0;
      low = high = 0;
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
    overflow:
    overflow:
      high = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
      high = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
      if (r->sign)
      if (r->sign)
        low = 0;
        low = 0;
      else
      else
        {
        {
          high--;
          high--;
          low = -1;
          low = -1;
        }
        }
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      if (r->decimal)
      if (r->decimal)
        {
        {
          decimal_real_to_integer2 (plow, phigh, r);
          decimal_real_to_integer2 (plow, phigh, r);
          return;
          return;
        }
        }
 
 
      exp = REAL_EXP (r);
      exp = REAL_EXP (r);
      if (exp <= 0)
      if (exp <= 0)
        goto underflow;
        goto underflow;
      /* Only force overflow for unsigned overflow.  Signed overflow is
      /* Only force overflow for unsigned overflow.  Signed overflow is
         undefined, so it doesn't matter what we return, and some callers
         undefined, so it doesn't matter what we return, and some callers
         expect to be able to use this routine for both signed and
         expect to be able to use this routine for both signed and
         unsigned conversions.  */
         unsigned conversions.  */
      if (exp > 2*HOST_BITS_PER_WIDE_INT)
      if (exp > 2*HOST_BITS_PER_WIDE_INT)
        goto overflow;
        goto overflow;
 
 
      rshift_significand (&t, r, 2*HOST_BITS_PER_WIDE_INT - exp);
      rshift_significand (&t, r, 2*HOST_BITS_PER_WIDE_INT - exp);
      if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
      if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
        {
        {
          high = t.sig[SIGSZ-1];
          high = t.sig[SIGSZ-1];
          low = t.sig[SIGSZ-2];
          low = t.sig[SIGSZ-2];
        }
        }
      else
      else
        {
        {
          gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG);
          gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG);
          high = t.sig[SIGSZ-1];
          high = t.sig[SIGSZ-1];
          high = high << (HOST_BITS_PER_LONG - 1) << 1;
          high = high << (HOST_BITS_PER_LONG - 1) << 1;
          high |= t.sig[SIGSZ-2];
          high |= t.sig[SIGSZ-2];
 
 
          low = t.sig[SIGSZ-3];
          low = t.sig[SIGSZ-3];
          low = low << (HOST_BITS_PER_LONG - 1) << 1;
          low = low << (HOST_BITS_PER_LONG - 1) << 1;
          low |= t.sig[SIGSZ-4];
          low |= t.sig[SIGSZ-4];
        }
        }
 
 
      if (r->sign)
      if (r->sign)
        {
        {
          if (low == 0)
          if (low == 0)
            high = -high;
            high = -high;
          else
          else
            low = -low, high = ~high;
            low = -low, high = ~high;
        }
        }
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  *plow = low;
  *plow = low;
  *phigh = high;
  *phigh = high;
}
}
 
 
/* A subroutine of real_to_decimal.  Compute the quotient and remainder
/* A subroutine of real_to_decimal.  Compute the quotient and remainder
   of NUM / DEN.  Return the quotient and place the remainder in NUM.
   of NUM / DEN.  Return the quotient and place the remainder in NUM.
   It is expected that NUM / DEN are close enough that the quotient is
   It is expected that NUM / DEN are close enough that the quotient is
   small.  */
   small.  */
 
 
static unsigned long
static unsigned long
rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den)
rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den)
{
{
  unsigned long q, msb;
  unsigned long q, msb;
  int expn = REAL_EXP (num), expd = REAL_EXP (den);
  int expn = REAL_EXP (num), expd = REAL_EXP (den);
 
 
  if (expn < expd)
  if (expn < expd)
    return 0;
    return 0;
 
 
  q = msb = 0;
  q = msb = 0;
  goto start;
  goto start;
  do
  do
    {
    {
      msb = num->sig[SIGSZ-1] & SIG_MSB;
      msb = num->sig[SIGSZ-1] & SIG_MSB;
      q <<= 1;
      q <<= 1;
      lshift_significand_1 (num, num);
      lshift_significand_1 (num, num);
    start:
    start:
      if (msb || cmp_significands (num, den) >= 0)
      if (msb || cmp_significands (num, den) >= 0)
        {
        {
          sub_significands (num, num, den, 0);
          sub_significands (num, num, den, 0);
          q |= 1;
          q |= 1;
        }
        }
    }
    }
  while (--expn >= expd);
  while (--expn >= expd);
 
 
  SET_REAL_EXP (num, expd);
  SET_REAL_EXP (num, expd);
  normalize (num);
  normalize (num);
 
 
  return q;
  return q;
}
}
 
 
/* Render R as a decimal floating point constant.  Emit DIGITS significant
/* Render R as a decimal floating point constant.  Emit DIGITS significant
   digits in the result, bounded by BUF_SIZE.  If DIGITS is 0, choose the
   digits in the result, bounded by BUF_SIZE.  If DIGITS is 0, choose the
   maximum for the representation.  If CROP_TRAILING_ZEROS, strip trailing
   maximum for the representation.  If CROP_TRAILING_ZEROS, strip trailing
   zeros.  */
   zeros.  */
 
 
#define M_LOG10_2       0.30102999566398119521
#define M_LOG10_2       0.30102999566398119521
 
 
void
void
real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
                 size_t digits, int crop_trailing_zeros)
                 size_t digits, int crop_trailing_zeros)
{
{
  const REAL_VALUE_TYPE *one, *ten;
  const REAL_VALUE_TYPE *one, *ten;
  REAL_VALUE_TYPE r, pten, u, v;
  REAL_VALUE_TYPE r, pten, u, v;
  int dec_exp, cmp_one, digit;
  int dec_exp, cmp_one, digit;
  size_t max_digits;
  size_t max_digits;
  char *p, *first, *last;
  char *p, *first, *last;
  bool sign;
  bool sign;
 
 
  r = *r_orig;
  r = *r_orig;
  switch (r.cl)
  switch (r.cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      strcpy (str, (r.sign ? "-0.0" : "0.0"));
      strcpy (str, (r.sign ? "-0.0" : "0.0"));
      return;
      return;
    case rvc_normal:
    case rvc_normal:
      break;
      break;
    case rvc_inf:
    case rvc_inf:
      strcpy (str, (r.sign ? "-Inf" : "+Inf"));
      strcpy (str, (r.sign ? "-Inf" : "+Inf"));
      return;
      return;
    case rvc_nan:
    case rvc_nan:
      /* ??? Print the significand as well, if not canonical?  */
      /* ??? Print the significand as well, if not canonical?  */
      strcpy (str, (r.sign ? "-NaN" : "+NaN"));
      strcpy (str, (r.sign ? "-NaN" : "+NaN"));
      return;
      return;
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (r.decimal)
  if (r.decimal)
    {
    {
      decimal_real_to_decimal (str, &r, buf_size, digits, crop_trailing_zeros);
      decimal_real_to_decimal (str, &r, buf_size, digits, crop_trailing_zeros);
      return;
      return;
    }
    }
 
 
  /* Bound the number of digits printed by the size of the representation.  */
  /* Bound the number of digits printed by the size of the representation.  */
  max_digits = SIGNIFICAND_BITS * M_LOG10_2;
  max_digits = SIGNIFICAND_BITS * M_LOG10_2;
  if (digits == 0 || digits > max_digits)
  if (digits == 0 || digits > max_digits)
    digits = max_digits;
    digits = max_digits;
 
 
  /* Estimate the decimal exponent, and compute the length of the string it
  /* Estimate the decimal exponent, and compute the length of the string it
     will print as.  Be conservative and add one to account for possible
     will print as.  Be conservative and add one to account for possible
     overflow or rounding error.  */
     overflow or rounding error.  */
  dec_exp = REAL_EXP (&r) * M_LOG10_2;
  dec_exp = REAL_EXP (&r) * M_LOG10_2;
  for (max_digits = 1; dec_exp ; max_digits++)
  for (max_digits = 1; dec_exp ; max_digits++)
    dec_exp /= 10;
    dec_exp /= 10;
 
 
  /* Bound the number of digits printed by the size of the output buffer.  */
  /* Bound the number of digits printed by the size of the output buffer.  */
  max_digits = buf_size - 1 - 1 - 2 - max_digits - 1;
  max_digits = buf_size - 1 - 1 - 2 - max_digits - 1;
  gcc_assert (max_digits <= buf_size);
  gcc_assert (max_digits <= buf_size);
  if (digits > max_digits)
  if (digits > max_digits)
    digits = max_digits;
    digits = max_digits;
 
 
  one = real_digit (1);
  one = real_digit (1);
  ten = ten_to_ptwo (0);
  ten = ten_to_ptwo (0);
 
 
  sign = r.sign;
  sign = r.sign;
  r.sign = 0;
  r.sign = 0;
 
 
  dec_exp = 0;
  dec_exp = 0;
  pten = *one;
  pten = *one;
 
 
  cmp_one = do_compare (&r, one, 0);
  cmp_one = do_compare (&r, one, 0);
  if (cmp_one > 0)
  if (cmp_one > 0)
    {
    {
      int m;
      int m;
 
 
      /* Number is greater than one.  Convert significand to an integer
      /* Number is greater than one.  Convert significand to an integer
         and strip trailing decimal zeros.  */
         and strip trailing decimal zeros.  */
 
 
      u = r;
      u = r;
      SET_REAL_EXP (&u, SIGNIFICAND_BITS - 1);
      SET_REAL_EXP (&u, SIGNIFICAND_BITS - 1);
 
 
      /* Largest M, such that 10**2**M fits within SIGNIFICAND_BITS.  */
      /* Largest M, such that 10**2**M fits within SIGNIFICAND_BITS.  */
      m = floor_log2 (max_digits);
      m = floor_log2 (max_digits);
 
 
      /* Iterate over the bits of the possible powers of 10 that might
      /* Iterate over the bits of the possible powers of 10 that might
         be present in U and eliminate them.  That is, if we find that
         be present in U and eliminate them.  That is, if we find that
         10**2**M divides U evenly, keep the division and increase
         10**2**M divides U evenly, keep the division and increase
         DEC_EXP by 2**M.  */
         DEC_EXP by 2**M.  */
      do
      do
        {
        {
          REAL_VALUE_TYPE t;
          REAL_VALUE_TYPE t;
 
 
          do_divide (&t, &u, ten_to_ptwo (m));
          do_divide (&t, &u, ten_to_ptwo (m));
          do_fix_trunc (&v, &t);
          do_fix_trunc (&v, &t);
          if (cmp_significands (&v, &t) == 0)
          if (cmp_significands (&v, &t) == 0)
            {
            {
              u = t;
              u = t;
              dec_exp += 1 << m;
              dec_exp += 1 << m;
            }
            }
        }
        }
      while (--m >= 0);
      while (--m >= 0);
 
 
      /* Revert the scaling to integer that we performed earlier.  */
      /* Revert the scaling to integer that we performed earlier.  */
      SET_REAL_EXP (&u, REAL_EXP (&u) + REAL_EXP (&r)
      SET_REAL_EXP (&u, REAL_EXP (&u) + REAL_EXP (&r)
                    - (SIGNIFICAND_BITS - 1));
                    - (SIGNIFICAND_BITS - 1));
      r = u;
      r = u;
 
 
      /* Find power of 10.  Do this by dividing out 10**2**M when
      /* Find power of 10.  Do this by dividing out 10**2**M when
         this is larger than the current remainder.  Fill PTEN with
         this is larger than the current remainder.  Fill PTEN with
         the power of 10 that we compute.  */
         the power of 10 that we compute.  */
      if (REAL_EXP (&r) > 0)
      if (REAL_EXP (&r) > 0)
        {
        {
          m = floor_log2 ((int)(REAL_EXP (&r) * M_LOG10_2)) + 1;
          m = floor_log2 ((int)(REAL_EXP (&r) * M_LOG10_2)) + 1;
          do
          do
            {
            {
              const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m);
              const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m);
              if (do_compare (&u, ptentwo, 0) >= 0)
              if (do_compare (&u, ptentwo, 0) >= 0)
                {
                {
                  do_divide (&u, &u, ptentwo);
                  do_divide (&u, &u, ptentwo);
                  do_multiply (&pten, &pten, ptentwo);
                  do_multiply (&pten, &pten, ptentwo);
                  dec_exp += 1 << m;
                  dec_exp += 1 << m;
                }
                }
            }
            }
          while (--m >= 0);
          while (--m >= 0);
        }
        }
      else
      else
        /* We managed to divide off enough tens in the above reduction
        /* We managed to divide off enough tens in the above reduction
           loop that we've now got a negative exponent.  Fall into the
           loop that we've now got a negative exponent.  Fall into the
           less-than-one code to compute the proper value for PTEN.  */
           less-than-one code to compute the proper value for PTEN.  */
        cmp_one = -1;
        cmp_one = -1;
    }
    }
  if (cmp_one < 0)
  if (cmp_one < 0)
    {
    {
      int m;
      int m;
 
 
      /* Number is less than one.  Pad significand with leading
      /* Number is less than one.  Pad significand with leading
         decimal zeros.  */
         decimal zeros.  */
 
 
      v = r;
      v = r;
      while (1)
      while (1)
        {
        {
          /* Stop if we'd shift bits off the bottom.  */
          /* Stop if we'd shift bits off the bottom.  */
          if (v.sig[0] & 7)
          if (v.sig[0] & 7)
            break;
            break;
 
 
          do_multiply (&u, &v, ten);
          do_multiply (&u, &v, ten);
 
 
          /* Stop if we're now >= 1.  */
          /* Stop if we're now >= 1.  */
          if (REAL_EXP (&u) > 0)
          if (REAL_EXP (&u) > 0)
            break;
            break;
 
 
          v = u;
          v = u;
          dec_exp -= 1;
          dec_exp -= 1;
        }
        }
      r = v;
      r = v;
 
 
      /* Find power of 10.  Do this by multiplying in P=10**2**M when
      /* Find power of 10.  Do this by multiplying in P=10**2**M when
         the current remainder is smaller than 1/P.  Fill PTEN with the
         the current remainder is smaller than 1/P.  Fill PTEN with the
         power of 10 that we compute.  */
         power of 10 that we compute.  */
      m = floor_log2 ((int)(-REAL_EXP (&r) * M_LOG10_2)) + 1;
      m = floor_log2 ((int)(-REAL_EXP (&r) * M_LOG10_2)) + 1;
      do
      do
        {
        {
          const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m);
          const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m);
          const REAL_VALUE_TYPE *ptenmtwo = ten_to_mptwo (m);
          const REAL_VALUE_TYPE *ptenmtwo = ten_to_mptwo (m);
 
 
          if (do_compare (&v, ptenmtwo, 0) <= 0)
          if (do_compare (&v, ptenmtwo, 0) <= 0)
            {
            {
              do_multiply (&v, &v, ptentwo);
              do_multiply (&v, &v, ptentwo);
              do_multiply (&pten, &pten, ptentwo);
              do_multiply (&pten, &pten, ptentwo);
              dec_exp -= 1 << m;
              dec_exp -= 1 << m;
            }
            }
        }
        }
      while (--m >= 0);
      while (--m >= 0);
 
 
      /* Invert the positive power of 10 that we've collected so far.  */
      /* Invert the positive power of 10 that we've collected so far.  */
      do_divide (&pten, one, &pten);
      do_divide (&pten, one, &pten);
    }
    }
 
 
  p = str;
  p = str;
  if (sign)
  if (sign)
    *p++ = '-';
    *p++ = '-';
  first = p++;
  first = p++;
 
 
  /* At this point, PTEN should contain the nearest power of 10 smaller
  /* At this point, PTEN should contain the nearest power of 10 smaller
     than R, such that this division produces the first digit.
     than R, such that this division produces the first digit.
 
 
     Using a divide-step primitive that returns the complete integral
     Using a divide-step primitive that returns the complete integral
     remainder avoids the rounding error that would be produced if
     remainder avoids the rounding error that would be produced if
     we were to use do_divide here and then simply multiply by 10 for
     we were to use do_divide here and then simply multiply by 10 for
     each subsequent digit.  */
     each subsequent digit.  */
 
 
  digit = rtd_divmod (&r, &pten);
  digit = rtd_divmod (&r, &pten);
 
 
  /* Be prepared for error in that division via underflow ...  */
  /* Be prepared for error in that division via underflow ...  */
  if (digit == 0 && cmp_significand_0 (&r))
  if (digit == 0 && cmp_significand_0 (&r))
    {
    {
      /* Multiply by 10 and try again.  */
      /* Multiply by 10 and try again.  */
      do_multiply (&r, &r, ten);
      do_multiply (&r, &r, ten);
      digit = rtd_divmod (&r, &pten);
      digit = rtd_divmod (&r, &pten);
      dec_exp -= 1;
      dec_exp -= 1;
      gcc_assert (digit != 0);
      gcc_assert (digit != 0);
    }
    }
 
 
  /* ... or overflow.  */
  /* ... or overflow.  */
  if (digit == 10)
  if (digit == 10)
    {
    {
      *p++ = '1';
      *p++ = '1';
      if (--digits > 0)
      if (--digits > 0)
        *p++ = '0';
        *p++ = '0';
      dec_exp += 1;
      dec_exp += 1;
    }
    }
  else
  else
    {
    {
      gcc_assert (digit <= 10);
      gcc_assert (digit <= 10);
      *p++ = digit + '0';
      *p++ = digit + '0';
    }
    }
 
 
  /* Generate subsequent digits.  */
  /* Generate subsequent digits.  */
  while (--digits > 0)
  while (--digits > 0)
    {
    {
      do_multiply (&r, &r, ten);
      do_multiply (&r, &r, ten);
      digit = rtd_divmod (&r, &pten);
      digit = rtd_divmod (&r, &pten);
      *p++ = digit + '0';
      *p++ = digit + '0';
    }
    }
  last = p;
  last = p;
 
 
  /* Generate one more digit with which to do rounding.  */
  /* Generate one more digit with which to do rounding.  */
  do_multiply (&r, &r, ten);
  do_multiply (&r, &r, ten);
  digit = rtd_divmod (&r, &pten);
  digit = rtd_divmod (&r, &pten);
 
 
  /* Round the result.  */
  /* Round the result.  */
  if (digit == 5)
  if (digit == 5)
    {
    {
      /* Round to nearest.  If R is nonzero there are additional
      /* Round to nearest.  If R is nonzero there are additional
         nonzero digits to be extracted.  */
         nonzero digits to be extracted.  */
      if (cmp_significand_0 (&r))
      if (cmp_significand_0 (&r))
        digit++;
        digit++;
      /* Round to even.  */
      /* Round to even.  */
      else if ((p[-1] - '0') & 1)
      else if ((p[-1] - '0') & 1)
        digit++;
        digit++;
    }
    }
  if (digit > 5)
  if (digit > 5)
    {
    {
      while (p > first)
      while (p > first)
        {
        {
          digit = *--p;
          digit = *--p;
          if (digit == '9')
          if (digit == '9')
            *p = '0';
            *p = '0';
          else
          else
            {
            {
              *p = digit + 1;
              *p = digit + 1;
              break;
              break;
            }
            }
        }
        }
 
 
      /* Carry out of the first digit.  This means we had all 9's and
      /* Carry out of the first digit.  This means we had all 9's and
         now have all 0's.  "Prepend" a 1 by overwriting the first 0.  */
         now have all 0's.  "Prepend" a 1 by overwriting the first 0.  */
      if (p == first)
      if (p == first)
        {
        {
          first[1] = '1';
          first[1] = '1';
          dec_exp++;
          dec_exp++;
        }
        }
    }
    }
 
 
  /* Insert the decimal point.  */
  /* Insert the decimal point.  */
  first[0] = first[1];
  first[0] = first[1];
  first[1] = '.';
  first[1] = '.';
 
 
  /* If requested, drop trailing zeros.  Never crop past "1.0".  */
  /* If requested, drop trailing zeros.  Never crop past "1.0".  */
  if (crop_trailing_zeros)
  if (crop_trailing_zeros)
    while (last > first + 3 && last[-1] == '0')
    while (last > first + 3 && last[-1] == '0')
      last--;
      last--;
 
 
  /* Append the exponent.  */
  /* Append the exponent.  */
  sprintf (last, "e%+d", dec_exp);
  sprintf (last, "e%+d", dec_exp);
}
}
 
 
/* Render R as a hexadecimal floating point constant.  Emit DIGITS
/* Render R as a hexadecimal floating point constant.  Emit DIGITS
   significant digits in the result, bounded by BUF_SIZE.  If DIGITS is 0,
   significant digits in the result, bounded by BUF_SIZE.  If DIGITS is 0,
   choose the maximum for the representation.  If CROP_TRAILING_ZEROS,
   choose the maximum for the representation.  If CROP_TRAILING_ZEROS,
   strip trailing zeros.  */
   strip trailing zeros.  */
 
 
void
void
real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size,
real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size,
                     size_t digits, int crop_trailing_zeros)
                     size_t digits, int crop_trailing_zeros)
{
{
  int i, j, exp = REAL_EXP (r);
  int i, j, exp = REAL_EXP (r);
  char *p, *first;
  char *p, *first;
  char exp_buf[16];
  char exp_buf[16];
  size_t max_digits;
  size_t max_digits;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      exp = 0;
      exp = 0;
      break;
      break;
    case rvc_normal:
    case rvc_normal:
      break;
      break;
    case rvc_inf:
    case rvc_inf:
      strcpy (str, (r->sign ? "-Inf" : "+Inf"));
      strcpy (str, (r->sign ? "-Inf" : "+Inf"));
      return;
      return;
    case rvc_nan:
    case rvc_nan:
      /* ??? Print the significand as well, if not canonical?  */
      /* ??? Print the significand as well, if not canonical?  */
      strcpy (str, (r->sign ? "-NaN" : "+NaN"));
      strcpy (str, (r->sign ? "-NaN" : "+NaN"));
      return;
      return;
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (r->decimal)
  if (r->decimal)
    {
    {
      /* Hexadecimal format for decimal floats is not interesting. */
      /* Hexadecimal format for decimal floats is not interesting. */
      strcpy (str, "N/A");
      strcpy (str, "N/A");
      return;
      return;
    }
    }
 
 
  if (digits == 0)
  if (digits == 0)
    digits = SIGNIFICAND_BITS / 4;
    digits = SIGNIFICAND_BITS / 4;
 
 
  /* Bound the number of digits printed by the size of the output buffer.  */
  /* Bound the number of digits printed by the size of the output buffer.  */
 
 
  sprintf (exp_buf, "p%+d", exp);
  sprintf (exp_buf, "p%+d", exp);
  max_digits = buf_size - strlen (exp_buf) - r->sign - 4 - 1;
  max_digits = buf_size - strlen (exp_buf) - r->sign - 4 - 1;
  gcc_assert (max_digits <= buf_size);
  gcc_assert (max_digits <= buf_size);
  if (digits > max_digits)
  if (digits > max_digits)
    digits = max_digits;
    digits = max_digits;
 
 
  p = str;
  p = str;
  if (r->sign)
  if (r->sign)
    *p++ = '-';
    *p++ = '-';
  *p++ = '0';
  *p++ = '0';
  *p++ = 'x';
  *p++ = 'x';
  *p++ = '0';
  *p++ = '0';
  *p++ = '.';
  *p++ = '.';
  first = p;
  first = p;
 
 
  for (i = SIGSZ - 1; i >= 0; --i)
  for (i = SIGSZ - 1; i >= 0; --i)
    for (j = HOST_BITS_PER_LONG - 4; j >= 0; j -= 4)
    for (j = HOST_BITS_PER_LONG - 4; j >= 0; j -= 4)
      {
      {
        *p++ = "0123456789abcdef"[(r->sig[i] >> j) & 15];
        *p++ = "0123456789abcdef"[(r->sig[i] >> j) & 15];
        if (--digits == 0)
        if (--digits == 0)
          goto out;
          goto out;
      }
      }
 
 
 out:
 out:
  if (crop_trailing_zeros)
  if (crop_trailing_zeros)
    while (p > first + 1 && p[-1] == '0')
    while (p > first + 1 && p[-1] == '0')
      p--;
      p--;
 
 
  sprintf (p, "p%+d", exp);
  sprintf (p, "p%+d", exp);
}
}
 
 
/* Initialize R from a decimal or hexadecimal string.  The string is
/* Initialize R from a decimal or hexadecimal string.  The string is
   assumed to have been syntax checked already.  */
   assumed to have been syntax checked already.  */
 
 
void
void
real_from_string (REAL_VALUE_TYPE *r, const char *str)
real_from_string (REAL_VALUE_TYPE *r, const char *str)
{
{
  int exp = 0;
  int exp = 0;
  bool sign = false;
  bool sign = false;
 
 
  get_zero (r, 0);
  get_zero (r, 0);
 
 
  if (*str == '-')
  if (*str == '-')
    {
    {
      sign = true;
      sign = true;
      str++;
      str++;
    }
    }
  else if (*str == '+')
  else if (*str == '+')
    str++;
    str++;
 
 
  if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
  if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
    {
    {
      /* Hexadecimal floating point.  */
      /* Hexadecimal floating point.  */
      int pos = SIGNIFICAND_BITS - 4, d;
      int pos = SIGNIFICAND_BITS - 4, d;
 
 
      str += 2;
      str += 2;
 
 
      while (*str == '0')
      while (*str == '0')
        str++;
        str++;
      while (1)
      while (1)
        {
        {
          d = hex_value (*str);
          d = hex_value (*str);
          if (d == _hex_bad)
          if (d == _hex_bad)
            break;
            break;
          if (pos >= 0)
          if (pos >= 0)
            {
            {
              r->sig[pos / HOST_BITS_PER_LONG]
              r->sig[pos / HOST_BITS_PER_LONG]
                |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
                |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
              pos -= 4;
              pos -= 4;
            }
            }
          else if (d)
          else if (d)
            /* Ensure correct rounding by setting last bit if there is
            /* Ensure correct rounding by setting last bit if there is
               a subsequent nonzero digit.  */
               a subsequent nonzero digit.  */
            r->sig[0] |= 1;
            r->sig[0] |= 1;
          exp += 4;
          exp += 4;
          str++;
          str++;
        }
        }
      if (*str == '.')
      if (*str == '.')
        {
        {
          str++;
          str++;
          if (pos == SIGNIFICAND_BITS - 4)
          if (pos == SIGNIFICAND_BITS - 4)
            {
            {
              while (*str == '0')
              while (*str == '0')
                str++, exp -= 4;
                str++, exp -= 4;
            }
            }
          while (1)
          while (1)
            {
            {
              d = hex_value (*str);
              d = hex_value (*str);
              if (d == _hex_bad)
              if (d == _hex_bad)
                break;
                break;
              if (pos >= 0)
              if (pos >= 0)
                {
                {
                  r->sig[pos / HOST_BITS_PER_LONG]
                  r->sig[pos / HOST_BITS_PER_LONG]
                    |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
                    |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
                  pos -= 4;
                  pos -= 4;
                }
                }
              else if (d)
              else if (d)
                /* Ensure correct rounding by setting last bit if there is
                /* Ensure correct rounding by setting last bit if there is
                   a subsequent nonzero digit.  */
                   a subsequent nonzero digit.  */
                r->sig[0] |= 1;
                r->sig[0] |= 1;
              str++;
              str++;
            }
            }
        }
        }
 
 
      /* If the mantissa is zero, ignore the exponent.  */
      /* If the mantissa is zero, ignore the exponent.  */
      if (!cmp_significand_0 (r))
      if (!cmp_significand_0 (r))
        goto underflow;
        goto underflow;
 
 
      if (*str == 'p' || *str == 'P')
      if (*str == 'p' || *str == 'P')
        {
        {
          bool exp_neg = false;
          bool exp_neg = false;
 
 
          str++;
          str++;
          if (*str == '-')
          if (*str == '-')
            {
            {
              exp_neg = true;
              exp_neg = true;
              str++;
              str++;
            }
            }
          else if (*str == '+')
          else if (*str == '+')
            str++;
            str++;
 
 
          d = 0;
          d = 0;
          while (ISDIGIT (*str))
          while (ISDIGIT (*str))
            {
            {
              d *= 10;
              d *= 10;
              d += *str - '0';
              d += *str - '0';
              if (d > MAX_EXP)
              if (d > MAX_EXP)
                {
                {
                  /* Overflowed the exponent.  */
                  /* Overflowed the exponent.  */
                  if (exp_neg)
                  if (exp_neg)
                    goto underflow;
                    goto underflow;
                  else
                  else
                    goto overflow;
                    goto overflow;
                }
                }
              str++;
              str++;
            }
            }
          if (exp_neg)
          if (exp_neg)
            d = -d;
            d = -d;
 
 
          exp += d;
          exp += d;
        }
        }
 
 
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      SET_REAL_EXP (r, exp);
      SET_REAL_EXP (r, exp);
 
 
      normalize (r);
      normalize (r);
    }
    }
  else
  else
    {
    {
      /* Decimal floating point.  */
      /* Decimal floating point.  */
      const REAL_VALUE_TYPE *ten = ten_to_ptwo (0);
      const REAL_VALUE_TYPE *ten = ten_to_ptwo (0);
      int d;
      int d;
 
 
      while (*str == '0')
      while (*str == '0')
        str++;
        str++;
      while (ISDIGIT (*str))
      while (ISDIGIT (*str))
        {
        {
          d = *str++ - '0';
          d = *str++ - '0';
          do_multiply (r, r, ten);
          do_multiply (r, r, ten);
          if (d)
          if (d)
            do_add (r, r, real_digit (d), 0);
            do_add (r, r, real_digit (d), 0);
        }
        }
      if (*str == '.')
      if (*str == '.')
        {
        {
          str++;
          str++;
          if (r->cl == rvc_zero)
          if (r->cl == rvc_zero)
            {
            {
              while (*str == '0')
              while (*str == '0')
                str++, exp--;
                str++, exp--;
            }
            }
          while (ISDIGIT (*str))
          while (ISDIGIT (*str))
            {
            {
              d = *str++ - '0';
              d = *str++ - '0';
              do_multiply (r, r, ten);
              do_multiply (r, r, ten);
              if (d)
              if (d)
                do_add (r, r, real_digit (d), 0);
                do_add (r, r, real_digit (d), 0);
              exp--;
              exp--;
            }
            }
        }
        }
 
 
      /* If the mantissa is zero, ignore the exponent.  */
      /* If the mantissa is zero, ignore the exponent.  */
      if (r->cl == rvc_zero)
      if (r->cl == rvc_zero)
        goto underflow;
        goto underflow;
 
 
      if (*str == 'e' || *str == 'E')
      if (*str == 'e' || *str == 'E')
        {
        {
          bool exp_neg = false;
          bool exp_neg = false;
 
 
          str++;
          str++;
          if (*str == '-')
          if (*str == '-')
            {
            {
              exp_neg = true;
              exp_neg = true;
              str++;
              str++;
            }
            }
          else if (*str == '+')
          else if (*str == '+')
            str++;
            str++;
 
 
          d = 0;
          d = 0;
          while (ISDIGIT (*str))
          while (ISDIGIT (*str))
            {
            {
              d *= 10;
              d *= 10;
              d += *str - '0';
              d += *str - '0';
              if (d > MAX_EXP)
              if (d > MAX_EXP)
                {
                {
                  /* Overflowed the exponent.  */
                  /* Overflowed the exponent.  */
                  if (exp_neg)
                  if (exp_neg)
                    goto underflow;
                    goto underflow;
                  else
                  else
                    goto overflow;
                    goto overflow;
                }
                }
              str++;
              str++;
            }
            }
          if (exp_neg)
          if (exp_neg)
            d = -d;
            d = -d;
          exp += d;
          exp += d;
        }
        }
 
 
      if (exp)
      if (exp)
        times_pten (r, exp);
        times_pten (r, exp);
    }
    }
 
 
  r->sign = sign;
  r->sign = sign;
  return;
  return;
 
 
 underflow:
 underflow:
  get_zero (r, sign);
  get_zero (r, sign);
  return;
  return;
 
 
 overflow:
 overflow:
  get_inf (r, sign);
  get_inf (r, sign);
  return;
  return;
}
}
 
 
/* Legacy.  Similar, but return the result directly.  */
/* Legacy.  Similar, but return the result directly.  */
 
 
REAL_VALUE_TYPE
REAL_VALUE_TYPE
real_from_string2 (const char *s, enum machine_mode mode)
real_from_string2 (const char *s, enum machine_mode mode)
{
{
  REAL_VALUE_TYPE r;
  REAL_VALUE_TYPE r;
 
 
  real_from_string (&r, s);
  real_from_string (&r, s);
  if (mode != VOIDmode)
  if (mode != VOIDmode)
    real_convert (&r, mode, &r);
    real_convert (&r, mode, &r);
 
 
  return r;
  return r;
}
}
 
 
/* Initialize R from string S and desired MODE. */
/* Initialize R from string S and desired MODE. */
 
 
void
void
real_from_string3 (REAL_VALUE_TYPE *r, const char *s, enum machine_mode mode)
real_from_string3 (REAL_VALUE_TYPE *r, const char *s, enum machine_mode mode)
{
{
  if (DECIMAL_FLOAT_MODE_P (mode))
  if (DECIMAL_FLOAT_MODE_P (mode))
    decimal_real_from_string (r, s);
    decimal_real_from_string (r, s);
  else
  else
    real_from_string (r, s);
    real_from_string (r, s);
 
 
  if (mode != VOIDmode)
  if (mode != VOIDmode)
    real_convert (r, mode, r);
    real_convert (r, mode, r);
}
}
 
 
/* Initialize R from the integer pair HIGH+LOW.  */
/* Initialize R from the integer pair HIGH+LOW.  */
 
 
void
void
real_from_integer (REAL_VALUE_TYPE *r, enum machine_mode mode,
real_from_integer (REAL_VALUE_TYPE *r, enum machine_mode mode,
                   unsigned HOST_WIDE_INT low, HOST_WIDE_INT high,
                   unsigned HOST_WIDE_INT low, HOST_WIDE_INT high,
                   int unsigned_p)
                   int unsigned_p)
{
{
  if (low == 0 && high == 0)
  if (low == 0 && high == 0)
    get_zero (r, 0);
    get_zero (r, 0);
  else
  else
    {
    {
      memset (r, 0, sizeof (*r));
      memset (r, 0, sizeof (*r));
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = high < 0 && !unsigned_p;
      r->sign = high < 0 && !unsigned_p;
      SET_REAL_EXP (r, 2 * HOST_BITS_PER_WIDE_INT);
      SET_REAL_EXP (r, 2 * HOST_BITS_PER_WIDE_INT);
 
 
      if (r->sign)
      if (r->sign)
        {
        {
          high = ~high;
          high = ~high;
          if (low == 0)
          if (low == 0)
            high += 1;
            high += 1;
          else
          else
            low = -low;
            low = -low;
        }
        }
 
 
      if (HOST_BITS_PER_LONG == HOST_BITS_PER_WIDE_INT)
      if (HOST_BITS_PER_LONG == HOST_BITS_PER_WIDE_INT)
        {
        {
          r->sig[SIGSZ-1] = high;
          r->sig[SIGSZ-1] = high;
          r->sig[SIGSZ-2] = low;
          r->sig[SIGSZ-2] = low;
        }
        }
      else
      else
        {
        {
          gcc_assert (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT);
          gcc_assert (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT);
          r->sig[SIGSZ-1] = high >> (HOST_BITS_PER_LONG - 1) >> 1;
          r->sig[SIGSZ-1] = high >> (HOST_BITS_PER_LONG - 1) >> 1;
          r->sig[SIGSZ-2] = high;
          r->sig[SIGSZ-2] = high;
          r->sig[SIGSZ-3] = low >> (HOST_BITS_PER_LONG - 1) >> 1;
          r->sig[SIGSZ-3] = low >> (HOST_BITS_PER_LONG - 1) >> 1;
          r->sig[SIGSZ-4] = low;
          r->sig[SIGSZ-4] = low;
        }
        }
 
 
      normalize (r);
      normalize (r);
    }
    }
 
 
  if (mode != VOIDmode)
  if (mode != VOIDmode)
    real_convert (r, mode, r);
    real_convert (r, mode, r);
}
}
 
 
/* Returns 10**2**N.  */
/* Returns 10**2**N.  */
 
 
static const REAL_VALUE_TYPE *
static const REAL_VALUE_TYPE *
ten_to_ptwo (int n)
ten_to_ptwo (int n)
{
{
  static REAL_VALUE_TYPE tens[EXP_BITS];
  static REAL_VALUE_TYPE tens[EXP_BITS];
 
 
  gcc_assert (n >= 0);
  gcc_assert (n >= 0);
  gcc_assert (n < EXP_BITS);
  gcc_assert (n < EXP_BITS);
 
 
  if (tens[n].cl == rvc_zero)
  if (tens[n].cl == rvc_zero)
    {
    {
      if (n < (HOST_BITS_PER_WIDE_INT == 64 ? 5 : 4))
      if (n < (HOST_BITS_PER_WIDE_INT == 64 ? 5 : 4))
        {
        {
          HOST_WIDE_INT t = 10;
          HOST_WIDE_INT t = 10;
          int i;
          int i;
 
 
          for (i = 0; i < n; ++i)
          for (i = 0; i < n; ++i)
            t *= t;
            t *= t;
 
 
          real_from_integer (&tens[n], VOIDmode, t, 0, 1);
          real_from_integer (&tens[n], VOIDmode, t, 0, 1);
        }
        }
      else
      else
        {
        {
          const REAL_VALUE_TYPE *t = ten_to_ptwo (n - 1);
          const REAL_VALUE_TYPE *t = ten_to_ptwo (n - 1);
          do_multiply (&tens[n], t, t);
          do_multiply (&tens[n], t, t);
        }
        }
    }
    }
 
 
  return &tens[n];
  return &tens[n];
}
}
 
 
/* Returns 10**(-2**N).  */
/* Returns 10**(-2**N).  */
 
 
static const REAL_VALUE_TYPE *
static const REAL_VALUE_TYPE *
ten_to_mptwo (int n)
ten_to_mptwo (int n)
{
{
  static REAL_VALUE_TYPE tens[EXP_BITS];
  static REAL_VALUE_TYPE tens[EXP_BITS];
 
 
  gcc_assert (n >= 0);
  gcc_assert (n >= 0);
  gcc_assert (n < EXP_BITS);
  gcc_assert (n < EXP_BITS);
 
 
  if (tens[n].cl == rvc_zero)
  if (tens[n].cl == rvc_zero)
    do_divide (&tens[n], real_digit (1), ten_to_ptwo (n));
    do_divide (&tens[n], real_digit (1), ten_to_ptwo (n));
 
 
  return &tens[n];
  return &tens[n];
}
}
 
 
/* Returns N.  */
/* Returns N.  */
 
 
static const REAL_VALUE_TYPE *
static const REAL_VALUE_TYPE *
real_digit (int n)
real_digit (int n)
{
{
  static REAL_VALUE_TYPE num[10];
  static REAL_VALUE_TYPE num[10];
 
 
  gcc_assert (n >= 0);
  gcc_assert (n >= 0);
  gcc_assert (n <= 9);
  gcc_assert (n <= 9);
 
 
  if (n > 0 && num[n].cl == rvc_zero)
  if (n > 0 && num[n].cl == rvc_zero)
    real_from_integer (&num[n], VOIDmode, n, 0, 1);
    real_from_integer (&num[n], VOIDmode, n, 0, 1);
 
 
  return &num[n];
  return &num[n];
}
}
 
 
/* Multiply R by 10**EXP.  */
/* Multiply R by 10**EXP.  */
 
 
static void
static void
times_pten (REAL_VALUE_TYPE *r, int exp)
times_pten (REAL_VALUE_TYPE *r, int exp)
{
{
  REAL_VALUE_TYPE pten, *rr;
  REAL_VALUE_TYPE pten, *rr;
  bool negative = (exp < 0);
  bool negative = (exp < 0);
  int i;
  int i;
 
 
  if (negative)
  if (negative)
    {
    {
      exp = -exp;
      exp = -exp;
      pten = *real_digit (1);
      pten = *real_digit (1);
      rr = &pten;
      rr = &pten;
    }
    }
  else
  else
    rr = r;
    rr = r;
 
 
  for (i = 0; exp > 0; ++i, exp >>= 1)
  for (i = 0; exp > 0; ++i, exp >>= 1)
    if (exp & 1)
    if (exp & 1)
      do_multiply (rr, rr, ten_to_ptwo (i));
      do_multiply (rr, rr, ten_to_ptwo (i));
 
 
  if (negative)
  if (negative)
    do_divide (r, r, &pten);
    do_divide (r, r, &pten);
}
}
 
 
/* Fills R with +Inf.  */
/* Fills R with +Inf.  */
 
 
void
void
real_inf (REAL_VALUE_TYPE *r)
real_inf (REAL_VALUE_TYPE *r)
{
{
  get_inf (r, 0);
  get_inf (r, 0);
}
}
 
 
/* Fills R with a NaN whose significand is described by STR.  If QUIET,
/* Fills R with a NaN whose significand is described by STR.  If QUIET,
   we force a QNaN, else we force an SNaN.  The string, if not empty,
   we force a QNaN, else we force an SNaN.  The string, if not empty,
   is parsed as a number and placed in the significand.  Return true
   is parsed as a number and placed in the significand.  Return true
   if the string was successfully parsed.  */
   if the string was successfully parsed.  */
 
 
bool
bool
real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
          enum machine_mode mode)
          enum machine_mode mode)
{
{
  const struct real_format *fmt;
  const struct real_format *fmt;
 
 
  fmt = REAL_MODE_FORMAT (mode);
  fmt = REAL_MODE_FORMAT (mode);
  gcc_assert (fmt);
  gcc_assert (fmt);
 
 
  if (*str == 0)
  if (*str == 0)
    {
    {
      if (quiet)
      if (quiet)
        get_canonical_qnan (r, 0);
        get_canonical_qnan (r, 0);
      else
      else
        get_canonical_snan (r, 0);
        get_canonical_snan (r, 0);
    }
    }
  else
  else
    {
    {
      int base = 10, d;
      int base = 10, d;
 
 
      memset (r, 0, sizeof (*r));
      memset (r, 0, sizeof (*r));
      r->cl = rvc_nan;
      r->cl = rvc_nan;
 
 
      /* Parse akin to strtol into the significand of R.  */
      /* Parse akin to strtol into the significand of R.  */
 
 
      while (ISSPACE (*str))
      while (ISSPACE (*str))
        str++;
        str++;
      if (*str == '-')
      if (*str == '-')
        str++;
        str++;
      else if (*str == '+')
      else if (*str == '+')
        str++;
        str++;
      if (*str == '0')
      if (*str == '0')
        {
        {
          str++;
          str++;
          if (*str == 'x' || *str == 'X')
          if (*str == 'x' || *str == 'X')
            {
            {
              base = 16;
              base = 16;
              str++;
              str++;
            }
            }
          else
          else
            base = 8;
            base = 8;
        }
        }
 
 
      while ((d = hex_value (*str)) < base)
      while ((d = hex_value (*str)) < base)
        {
        {
          REAL_VALUE_TYPE u;
          REAL_VALUE_TYPE u;
 
 
          switch (base)
          switch (base)
            {
            {
            case 8:
            case 8:
              lshift_significand (r, r, 3);
              lshift_significand (r, r, 3);
              break;
              break;
            case 16:
            case 16:
              lshift_significand (r, r, 4);
              lshift_significand (r, r, 4);
              break;
              break;
            case 10:
            case 10:
              lshift_significand_1 (&u, r);
              lshift_significand_1 (&u, r);
              lshift_significand (r, r, 3);
              lshift_significand (r, r, 3);
              add_significands (r, r, &u);
              add_significands (r, r, &u);
              break;
              break;
            default:
            default:
              gcc_unreachable ();
              gcc_unreachable ();
            }
            }
 
 
          get_zero (&u, 0);
          get_zero (&u, 0);
          u.sig[0] = d;
          u.sig[0] = d;
          add_significands (r, r, &u);
          add_significands (r, r, &u);
 
 
          str++;
          str++;
        }
        }
 
 
      /* Must have consumed the entire string for success.  */
      /* Must have consumed the entire string for success.  */
      if (*str != 0)
      if (*str != 0)
        return false;
        return false;
 
 
      /* Shift the significand into place such that the bits
      /* Shift the significand into place such that the bits
         are in the most significant bits for the format.  */
         are in the most significant bits for the format.  */
      lshift_significand (r, r, SIGNIFICAND_BITS - fmt->pnan);
      lshift_significand (r, r, SIGNIFICAND_BITS - fmt->pnan);
 
 
      /* Our MSB is always unset for NaNs.  */
      /* Our MSB is always unset for NaNs.  */
      r->sig[SIGSZ-1] &= ~SIG_MSB;
      r->sig[SIGSZ-1] &= ~SIG_MSB;
 
 
      /* Force quiet or signalling NaN.  */
      /* Force quiet or signalling NaN.  */
      r->signalling = !quiet;
      r->signalling = !quiet;
    }
    }
 
 
  return true;
  return true;
}
}
 
 
/* Fills R with the largest finite value representable in mode MODE.
/* Fills R with the largest finite value representable in mode MODE.
   If SIGN is nonzero, R is set to the most negative finite value.  */
   If SIGN is nonzero, R is set to the most negative finite value.  */
 
 
void
void
real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
{
{
  const struct real_format *fmt;
  const struct real_format *fmt;
  int np2;
  int np2;
 
 
  fmt = REAL_MODE_FORMAT (mode);
  fmt = REAL_MODE_FORMAT (mode);
  gcc_assert (fmt);
  gcc_assert (fmt);
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (fmt->b == 10)
  if (fmt->b == 10)
    decimal_real_maxval (r, sign, mode);
    decimal_real_maxval (r, sign, mode);
  else
  else
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = sign;
      r->sign = sign;
      SET_REAL_EXP (r, fmt->emax * fmt->log2_b);
      SET_REAL_EXP (r, fmt->emax * fmt->log2_b);
 
 
      np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b;
      np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b;
      memset (r->sig, -1, SIGSZ * sizeof (unsigned long));
      memset (r->sig, -1, SIGSZ * sizeof (unsigned long));
      clear_significand_below (r, np2);
      clear_significand_below (r, np2);
 
 
      if (fmt->pnan < fmt->p)
      if (fmt->pnan < fmt->p)
        /* This is an IBM extended double format made up of two IEEE
        /* This is an IBM extended double format made up of two IEEE
           doubles.  The value of the long double is the sum of the
           doubles.  The value of the long double is the sum of the
           values of the two parts.  The most significant part is
           values of the two parts.  The most significant part is
           required to be the value of the long double rounded to the
           required to be the value of the long double rounded to the
           nearest double.  Rounding means we need a slightly smaller
           nearest double.  Rounding means we need a slightly smaller
           value for LDBL_MAX.  */
           value for LDBL_MAX.  */
        clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan);
        clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan);
    }
    }
}
}
 
 
/* Fills R with 2**N.  */
/* Fills R with 2**N.  */
 
 
void
void
real_2expN (REAL_VALUE_TYPE *r, int n)
real_2expN (REAL_VALUE_TYPE *r, int n)
{
{
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  n++;
  n++;
  if (n > MAX_EXP)
  if (n > MAX_EXP)
    r->cl = rvc_inf;
    r->cl = rvc_inf;
  else if (n < -MAX_EXP)
  else if (n < -MAX_EXP)
    ;
    ;
  else
  else
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      SET_REAL_EXP (r, n);
      SET_REAL_EXP (r, n);
      r->sig[SIGSZ-1] = SIG_MSB;
      r->sig[SIGSZ-1] = SIG_MSB;
    }
    }
}
}
 
 


static void
static void
round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
{
{
  int p2, np2, i, w;
  int p2, np2, i, w;
  unsigned long sticky;
  unsigned long sticky;
  bool guard, lsb;
  bool guard, lsb;
  int emin2m1, emax2;
  int emin2m1, emax2;
 
 
  if (r->decimal)
  if (r->decimal)
    {
    {
      if (fmt->b == 10)
      if (fmt->b == 10)
        {
        {
          decimal_round_for_format (fmt, r);
          decimal_round_for_format (fmt, r);
          return;
          return;
        }
        }
      /* FIXME. We can come here via fp_easy_constant
      /* FIXME. We can come here via fp_easy_constant
         (e.g. -O0 on '_Decimal32 x = 1.0 + 2.0dd'), but have not
         (e.g. -O0 on '_Decimal32 x = 1.0 + 2.0dd'), but have not
         investigated whether this convert needs to be here, or
         investigated whether this convert needs to be here, or
         something else is missing. */
         something else is missing. */
      decimal_real_convert (r, DFmode, r);
      decimal_real_convert (r, DFmode, r);
    }
    }
 
 
  p2 = fmt->p * fmt->log2_b;
  p2 = fmt->p * fmt->log2_b;
  emin2m1 = (fmt->emin - 1) * fmt->log2_b;
  emin2m1 = (fmt->emin - 1) * fmt->log2_b;
  emax2 = fmt->emax * fmt->log2_b;
  emax2 = fmt->emax * fmt->log2_b;
 
 
  np2 = SIGNIFICAND_BITS - p2;
  np2 = SIGNIFICAND_BITS - p2;
  switch (r->cl)
  switch (r->cl)
    {
    {
    underflow:
    underflow:
      get_zero (r, r->sign);
      get_zero (r, r->sign);
    case rvc_zero:
    case rvc_zero:
      if (!fmt->has_signed_zero)
      if (!fmt->has_signed_zero)
        r->sign = 0;
        r->sign = 0;
      return;
      return;
 
 
    overflow:
    overflow:
      get_inf (r, r->sign);
      get_inf (r, r->sign);
    case rvc_inf:
    case rvc_inf:
      return;
      return;
 
 
    case rvc_nan:
    case rvc_nan:
      clear_significand_below (r, np2);
      clear_significand_below (r, np2);
      return;
      return;
 
 
    case rvc_normal:
    case rvc_normal:
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  /* If we're not base2, normalize the exponent to a multiple of
  /* If we're not base2, normalize the exponent to a multiple of
     the true base.  */
     the true base.  */
  if (fmt->log2_b != 1)
  if (fmt->log2_b != 1)
    {
    {
      int shift;
      int shift;
 
 
      gcc_assert (fmt->b != 10);
      gcc_assert (fmt->b != 10);
      shift = REAL_EXP (r) & (fmt->log2_b - 1);
      shift = REAL_EXP (r) & (fmt->log2_b - 1);
      if (shift)
      if (shift)
        {
        {
          shift = fmt->log2_b - shift;
          shift = fmt->log2_b - shift;
          r->sig[0] |= sticky_rshift_significand (r, r, shift);
          r->sig[0] |= sticky_rshift_significand (r, r, shift);
          SET_REAL_EXP (r, REAL_EXP (r) + shift);
          SET_REAL_EXP (r, REAL_EXP (r) + shift);
        }
        }
    }
    }
 
 
  /* Check the range of the exponent.  If we're out of range,
  /* Check the range of the exponent.  If we're out of range,
     either underflow or overflow.  */
     either underflow or overflow.  */
  if (REAL_EXP (r) > emax2)
  if (REAL_EXP (r) > emax2)
    goto overflow;
    goto overflow;
  else if (REAL_EXP (r) <= emin2m1)
  else if (REAL_EXP (r) <= emin2m1)
    {
    {
      int diff;
      int diff;
 
 
      if (!fmt->has_denorm)
      if (!fmt->has_denorm)
        {
        {
          /* Don't underflow completely until we've had a chance to round.  */
          /* Don't underflow completely until we've had a chance to round.  */
          if (REAL_EXP (r) < emin2m1)
          if (REAL_EXP (r) < emin2m1)
            goto underflow;
            goto underflow;
        }
        }
      else
      else
        {
        {
          diff = emin2m1 - REAL_EXP (r) + 1;
          diff = emin2m1 - REAL_EXP (r) + 1;
          if (diff > p2)
          if (diff > p2)
            goto underflow;
            goto underflow;
 
 
          /* De-normalize the significand.  */
          /* De-normalize the significand.  */
          r->sig[0] |= sticky_rshift_significand (r, r, diff);
          r->sig[0] |= sticky_rshift_significand (r, r, diff);
          SET_REAL_EXP (r, REAL_EXP (r) + diff);
          SET_REAL_EXP (r, REAL_EXP (r) + diff);
        }
        }
    }
    }
 
 
  /* There are P2 true significand bits, followed by one guard bit,
  /* There are P2 true significand bits, followed by one guard bit,
     followed by one sticky bit, followed by stuff.  Fold nonzero
     followed by one sticky bit, followed by stuff.  Fold nonzero
     stuff into the sticky bit.  */
     stuff into the sticky bit.  */
 
 
  sticky = 0;
  sticky = 0;
  for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i)
  for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i)
    sticky |= r->sig[i];
    sticky |= r->sig[i];
  sticky |=
  sticky |=
    r->sig[w] & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1);
    r->sig[w] & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1);
 
 
  guard = test_significand_bit (r, np2 - 1);
  guard = test_significand_bit (r, np2 - 1);
  lsb = test_significand_bit (r, np2);
  lsb = test_significand_bit (r, np2);
 
 
  /* Round to even.  */
  /* Round to even.  */
  if (guard && (sticky || lsb))
  if (guard && (sticky || lsb))
    {
    {
      REAL_VALUE_TYPE u;
      REAL_VALUE_TYPE u;
      get_zero (&u, 0);
      get_zero (&u, 0);
      set_significand_bit (&u, np2);
      set_significand_bit (&u, np2);
 
 
      if (add_significands (r, r, &u))
      if (add_significands (r, r, &u))
        {
        {
          /* Overflow.  Means the significand had been all ones, and
          /* Overflow.  Means the significand had been all ones, and
             is now all zeros.  Need to increase the exponent, and
             is now all zeros.  Need to increase the exponent, and
             possibly re-normalize it.  */
             possibly re-normalize it.  */
          SET_REAL_EXP (r, REAL_EXP (r) + 1);
          SET_REAL_EXP (r, REAL_EXP (r) + 1);
          if (REAL_EXP (r) > emax2)
          if (REAL_EXP (r) > emax2)
            goto overflow;
            goto overflow;
          r->sig[SIGSZ-1] = SIG_MSB;
          r->sig[SIGSZ-1] = SIG_MSB;
 
 
          if (fmt->log2_b != 1)
          if (fmt->log2_b != 1)
            {
            {
              int shift = REAL_EXP (r) & (fmt->log2_b - 1);
              int shift = REAL_EXP (r) & (fmt->log2_b - 1);
              if (shift)
              if (shift)
                {
                {
                  shift = fmt->log2_b - shift;
                  shift = fmt->log2_b - shift;
                  rshift_significand (r, r, shift);
                  rshift_significand (r, r, shift);
                  SET_REAL_EXP (r, REAL_EXP (r) + shift);
                  SET_REAL_EXP (r, REAL_EXP (r) + shift);
                  if (REAL_EXP (r) > emax2)
                  if (REAL_EXP (r) > emax2)
                    goto overflow;
                    goto overflow;
                }
                }
            }
            }
        }
        }
    }
    }
 
 
  /* Catch underflow that we deferred until after rounding.  */
  /* Catch underflow that we deferred until after rounding.  */
  if (REAL_EXP (r) <= emin2m1)
  if (REAL_EXP (r) <= emin2m1)
    goto underflow;
    goto underflow;
 
 
  /* Clear out trailing garbage.  */
  /* Clear out trailing garbage.  */
  clear_significand_below (r, np2);
  clear_significand_below (r, np2);
}
}
 
 
/* Extend or truncate to a new mode.  */
/* Extend or truncate to a new mode.  */
 
 
void
void
real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode,
real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode,
              const REAL_VALUE_TYPE *a)
              const REAL_VALUE_TYPE *a)
{
{
  const struct real_format *fmt;
  const struct real_format *fmt;
 
 
  fmt = REAL_MODE_FORMAT (mode);
  fmt = REAL_MODE_FORMAT (mode);
  gcc_assert (fmt);
  gcc_assert (fmt);
 
 
  *r = *a;
  *r = *a;
 
 
  if (a->decimal || fmt->b == 10)
  if (a->decimal || fmt->b == 10)
    decimal_real_convert (r, mode, a);
    decimal_real_convert (r, mode, a);
 
 
  round_for_format (fmt, r);
  round_for_format (fmt, r);
 
 
  /* round_for_format de-normalizes denormals.  Undo just that part.  */
  /* round_for_format de-normalizes denormals.  Undo just that part.  */
  if (r->cl == rvc_normal)
  if (r->cl == rvc_normal)
    normalize (r);
    normalize (r);
}
}
 
 
/* Legacy.  Likewise, except return the struct directly.  */
/* Legacy.  Likewise, except return the struct directly.  */
 
 
REAL_VALUE_TYPE
REAL_VALUE_TYPE
real_value_truncate (enum machine_mode mode, REAL_VALUE_TYPE a)
real_value_truncate (enum machine_mode mode, REAL_VALUE_TYPE a)
{
{
  REAL_VALUE_TYPE r;
  REAL_VALUE_TYPE r;
  real_convert (&r, mode, &a);
  real_convert (&r, mode, &a);
  return r;
  return r;
}
}
 
 
/* Return true if truncating to MODE is exact.  */
/* Return true if truncating to MODE is exact.  */
 
 
bool
bool
exact_real_truncate (enum machine_mode mode, const REAL_VALUE_TYPE *a)
exact_real_truncate (enum machine_mode mode, const REAL_VALUE_TYPE *a)
{
{
  const struct real_format *fmt;
  const struct real_format *fmt;
  REAL_VALUE_TYPE t;
  REAL_VALUE_TYPE t;
  int emin2m1;
  int emin2m1;
 
 
  fmt = REAL_MODE_FORMAT (mode);
  fmt = REAL_MODE_FORMAT (mode);
  gcc_assert (fmt);
  gcc_assert (fmt);
 
 
  /* Don't allow conversion to denormals.  */
  /* Don't allow conversion to denormals.  */
  emin2m1 = (fmt->emin - 1) * fmt->log2_b;
  emin2m1 = (fmt->emin - 1) * fmt->log2_b;
  if (REAL_EXP (a) <= emin2m1)
  if (REAL_EXP (a) <= emin2m1)
    return false;
    return false;
 
 
  /* After conversion to the new mode, the value must be identical.  */
  /* After conversion to the new mode, the value must be identical.  */
  real_convert (&t, mode, a);
  real_convert (&t, mode, a);
  return real_identical (&t, a);
  return real_identical (&t, a);
}
}
 
 
/* Write R to the given target format.  Place the words of the result
/* Write R to the given target format.  Place the words of the result
   in target word order in BUF.  There are always 32 bits in each
   in target word order in BUF.  There are always 32 bits in each
   long, no matter the size of the host long.
   long, no matter the size of the host long.
 
 
   Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE.  */
   Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE.  */
 
 
long
long
real_to_target_fmt (long *buf, const REAL_VALUE_TYPE *r_orig,
real_to_target_fmt (long *buf, const REAL_VALUE_TYPE *r_orig,
                    const struct real_format *fmt)
                    const struct real_format *fmt)
{
{
  REAL_VALUE_TYPE r;
  REAL_VALUE_TYPE r;
  long buf1;
  long buf1;
 
 
  r = *r_orig;
  r = *r_orig;
  round_for_format (fmt, &r);
  round_for_format (fmt, &r);
 
 
  if (!buf)
  if (!buf)
    buf = &buf1;
    buf = &buf1;
  (*fmt->encode) (fmt, buf, &r);
  (*fmt->encode) (fmt, buf, &r);
 
 
  return *buf;
  return *buf;
}
}
 
 
/* Similar, but look up the format from MODE.  */
/* Similar, but look up the format from MODE.  */
 
 
long
long
real_to_target (long *buf, const REAL_VALUE_TYPE *r, enum machine_mode mode)
real_to_target (long *buf, const REAL_VALUE_TYPE *r, enum machine_mode mode)
{
{
  const struct real_format *fmt;
  const struct real_format *fmt;
 
 
  fmt = REAL_MODE_FORMAT (mode);
  fmt = REAL_MODE_FORMAT (mode);
  gcc_assert (fmt);
  gcc_assert (fmt);
 
 
  return real_to_target_fmt (buf, r, fmt);
  return real_to_target_fmt (buf, r, fmt);
}
}
 
 
/* Read R from the given target format.  Read the words of the result
/* Read R from the given target format.  Read the words of the result
   in target word order in BUF.  There are always 32 bits in each
   in target word order in BUF.  There are always 32 bits in each
   long, no matter the size of the host long.  */
   long, no matter the size of the host long.  */
 
 
void
void
real_from_target_fmt (REAL_VALUE_TYPE *r, const long *buf,
real_from_target_fmt (REAL_VALUE_TYPE *r, const long *buf,
                      const struct real_format *fmt)
                      const struct real_format *fmt)
{
{
  (*fmt->decode) (fmt, r, buf);
  (*fmt->decode) (fmt, r, buf);
}
}
 
 
/* Similar, but look up the format from MODE.  */
/* Similar, but look up the format from MODE.  */
 
 
void
void
real_from_target (REAL_VALUE_TYPE *r, const long *buf, enum machine_mode mode)
real_from_target (REAL_VALUE_TYPE *r, const long *buf, enum machine_mode mode)
{
{
  const struct real_format *fmt;
  const struct real_format *fmt;
 
 
  fmt = REAL_MODE_FORMAT (mode);
  fmt = REAL_MODE_FORMAT (mode);
  gcc_assert (fmt);
  gcc_assert (fmt);
 
 
  (*fmt->decode) (fmt, r, buf);
  (*fmt->decode) (fmt, r, buf);
}
}
 
 
/* Return the number of bits of the largest binary value that the
/* Return the number of bits of the largest binary value that the
   significand of MODE will hold.  */
   significand of MODE will hold.  */
/* ??? Legacy.  Should get access to real_format directly.  */
/* ??? Legacy.  Should get access to real_format directly.  */
 
 
int
int
significand_size (enum machine_mode mode)
significand_size (enum machine_mode mode)
{
{
  const struct real_format *fmt;
  const struct real_format *fmt;
 
 
  fmt = REAL_MODE_FORMAT (mode);
  fmt = REAL_MODE_FORMAT (mode);
  if (fmt == NULL)
  if (fmt == NULL)
    return 0;
    return 0;
 
 
  if (fmt->b == 10)
  if (fmt->b == 10)
    {
    {
      /* Return the size in bits of the largest binary value that can be
      /* Return the size in bits of the largest binary value that can be
         held by the decimal coefficient for this mode.  This is one more
         held by the decimal coefficient for this mode.  This is one more
         than the number of bits required to hold the largest coefficient
         than the number of bits required to hold the largest coefficient
         of this mode.  */
         of this mode.  */
      double log2_10 = 3.3219281;
      double log2_10 = 3.3219281;
      return fmt->p * log2_10;
      return fmt->p * log2_10;
    }
    }
  return fmt->p * fmt->log2_b;
  return fmt->p * fmt->log2_b;
}
}
 
 
/* Return a hash value for the given real value.  */
/* Return a hash value for the given real value.  */
/* ??? The "unsigned int" return value is intended to be hashval_t,
/* ??? The "unsigned int" return value is intended to be hashval_t,
   but I didn't want to pull hashtab.h into real.h.  */
   but I didn't want to pull hashtab.h into real.h.  */
 
 
unsigned int
unsigned int
real_hash (const REAL_VALUE_TYPE *r)
real_hash (const REAL_VALUE_TYPE *r)
{
{
  unsigned int h;
  unsigned int h;
  size_t i;
  size_t i;
 
 
  h = r->cl | (r->sign << 2);
  h = r->cl | (r->sign << 2);
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
    case rvc_inf:
    case rvc_inf:
      return h;
      return h;
 
 
    case rvc_normal:
    case rvc_normal:
      h |= REAL_EXP (r) << 3;
      h |= REAL_EXP (r) << 3;
      break;
      break;
 
 
    case rvc_nan:
    case rvc_nan:
      if (r->signalling)
      if (r->signalling)
        h ^= (unsigned int)-1;
        h ^= (unsigned int)-1;
      if (r->canonical)
      if (r->canonical)
        return h;
        return h;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (sizeof(unsigned long) > sizeof(unsigned int))
  if (sizeof(unsigned long) > sizeof(unsigned int))
    for (i = 0; i < SIGSZ; ++i)
    for (i = 0; i < SIGSZ; ++i)
      {
      {
        unsigned long s = r->sig[i];
        unsigned long s = r->sig[i];
        h ^= s ^ (s >> (HOST_BITS_PER_LONG / 2));
        h ^= s ^ (s >> (HOST_BITS_PER_LONG / 2));
      }
      }
  else
  else
    for (i = 0; i < SIGSZ; ++i)
    for (i = 0; i < SIGSZ; ++i)
      h ^= r->sig[i];
      h ^= r->sig[i];
 
 
  return h;
  return h;
}
}


/* IEEE single-precision format.  */
/* IEEE single-precision format.  */
 
 
static void encode_ieee_single (const struct real_format *fmt,
static void encode_ieee_single (const struct real_format *fmt,
                                long *, const REAL_VALUE_TYPE *);
                                long *, const REAL_VALUE_TYPE *);
static void decode_ieee_single (const struct real_format *,
static void decode_ieee_single (const struct real_format *,
                                REAL_VALUE_TYPE *, const long *);
                                REAL_VALUE_TYPE *, const long *);
 
 
static void
static void
encode_ieee_single (const struct real_format *fmt, long *buf,
encode_ieee_single (const struct real_format *fmt, long *buf,
                    const REAL_VALUE_TYPE *r)
                    const REAL_VALUE_TYPE *r)
{
{
  unsigned long image, sig, exp;
  unsigned long image, sig, exp;
  unsigned long sign = r->sign;
  unsigned long sign = r->sign;
  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
 
 
  image = sign << 31;
  image = sign << 31;
  sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
  sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
      if (fmt->has_inf)
      if (fmt->has_inf)
        image |= 255 << 23;
        image |= 255 << 23;
      else
      else
        image |= 0x7fffffff;
        image |= 0x7fffffff;
      break;
      break;
 
 
    case rvc_nan:
    case rvc_nan:
      if (fmt->has_nans)
      if (fmt->has_nans)
        {
        {
          if (r->canonical)
          if (r->canonical)
            sig = 0;
            sig = 0;
          if (r->signalling == fmt->qnan_msb_set)
          if (r->signalling == fmt->qnan_msb_set)
            sig &= ~(1 << 22);
            sig &= ~(1 << 22);
          else
          else
            sig |= 1 << 22;
            sig |= 1 << 22;
          /* We overload qnan_msb_set here: it's only clear for
          /* We overload qnan_msb_set here: it's only clear for
             mips_ieee_single, which wants all mantissa bits but the
             mips_ieee_single, which wants all mantissa bits but the
             quiet/signalling one set in canonical NaNs (at least
             quiet/signalling one set in canonical NaNs (at least
             Quiet ones).  */
             Quiet ones).  */
          if (r->canonical && !fmt->qnan_msb_set)
          if (r->canonical && !fmt->qnan_msb_set)
            sig |= (1 << 22) - 1;
            sig |= (1 << 22) - 1;
          else if (sig == 0)
          else if (sig == 0)
            sig = 1 << 21;
            sig = 1 << 21;
 
 
          image |= 255 << 23;
          image |= 255 << 23;
          image |= sig;
          image |= sig;
        }
        }
      else
      else
        image |= 0x7fffffff;
        image |= 0x7fffffff;
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
      /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
         whereas the intermediate representation is 0.F x 2**exp.
         whereas the intermediate representation is 0.F x 2**exp.
         Which means we're off by one.  */
         Which means we're off by one.  */
      if (denormal)
      if (denormal)
        exp = 0;
        exp = 0;
      else
      else
      exp = REAL_EXP (r) + 127 - 1;
      exp = REAL_EXP (r) + 127 - 1;
      image |= exp << 23;
      image |= exp << 23;
      image |= sig;
      image |= sig;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  buf[0] = image;
  buf[0] = image;
}
}
 
 
static void
static void
decode_ieee_single (const struct real_format *fmt, REAL_VALUE_TYPE *r,
decode_ieee_single (const struct real_format *fmt, REAL_VALUE_TYPE *r,
                    const long *buf)
                    const long *buf)
{
{
  unsigned long image = buf[0] & 0xffffffff;
  unsigned long image = buf[0] & 0xffffffff;
  bool sign = (image >> 31) & 1;
  bool sign = (image >> 31) & 1;
  int exp = (image >> 23) & 0xff;
  int exp = (image >> 23) & 0xff;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
  image <<= HOST_BITS_PER_LONG - 24;
  image <<= HOST_BITS_PER_LONG - 24;
  image &= ~SIG_MSB;
  image &= ~SIG_MSB;
 
 
  if (exp == 0)
  if (exp == 0)
    {
    {
      if (image && fmt->has_denorm)
      if (image && fmt->has_denorm)
        {
        {
          r->cl = rvc_normal;
          r->cl = rvc_normal;
          r->sign = sign;
          r->sign = sign;
          SET_REAL_EXP (r, -126);
          SET_REAL_EXP (r, -126);
          r->sig[SIGSZ-1] = image << 1;
          r->sig[SIGSZ-1] = image << 1;
          normalize (r);
          normalize (r);
        }
        }
      else if (fmt->has_signed_zero)
      else if (fmt->has_signed_zero)
        r->sign = sign;
        r->sign = sign;
    }
    }
  else if (exp == 255 && (fmt->has_nans || fmt->has_inf))
  else if (exp == 255 && (fmt->has_nans || fmt->has_inf))
    {
    {
      if (image)
      if (image)
        {
        {
          r->cl = rvc_nan;
          r->cl = rvc_nan;
          r->sign = sign;
          r->sign = sign;
          r->signalling = (((image >> (HOST_BITS_PER_LONG - 2)) & 1)
          r->signalling = (((image >> (HOST_BITS_PER_LONG - 2)) & 1)
                           ^ fmt->qnan_msb_set);
                           ^ fmt->qnan_msb_set);
          r->sig[SIGSZ-1] = image;
          r->sig[SIGSZ-1] = image;
        }
        }
      else
      else
        {
        {
          r->cl = rvc_inf;
          r->cl = rvc_inf;
          r->sign = sign;
          r->sign = sign;
        }
        }
    }
    }
  else
  else
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = sign;
      r->sign = sign;
      SET_REAL_EXP (r, exp - 127 + 1);
      SET_REAL_EXP (r, exp - 127 + 1);
      r->sig[SIGSZ-1] = image | SIG_MSB;
      r->sig[SIGSZ-1] = image | SIG_MSB;
    }
    }
}
}
 
 
const struct real_format ieee_single_format =
const struct real_format ieee_single_format =
  {
  {
    encode_ieee_single,
    encode_ieee_single,
    decode_ieee_single,
    decode_ieee_single,
    2,
    2,
    1,
    1,
    24,
    24,
    24,
    24,
    -125,
    -125,
    128,
    128,
    31,
    31,
    31,
    31,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };
 
 
const struct real_format mips_single_format =
const struct real_format mips_single_format =
  {
  {
    encode_ieee_single,
    encode_ieee_single,
    decode_ieee_single,
    decode_ieee_single,
    2,
    2,
    1,
    1,
    24,
    24,
    24,
    24,
    -125,
    -125,
    128,
    128,
    31,
    31,
    31,
    31,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    false
    false
  };
  };
 
 


/* IEEE double-precision format.  */
/* IEEE double-precision format.  */
 
 
static void encode_ieee_double (const struct real_format *fmt,
static void encode_ieee_double (const struct real_format *fmt,
                                long *, const REAL_VALUE_TYPE *);
                                long *, const REAL_VALUE_TYPE *);
static void decode_ieee_double (const struct real_format *,
static void decode_ieee_double (const struct real_format *,
                                REAL_VALUE_TYPE *, const long *);
                                REAL_VALUE_TYPE *, const long *);
 
 
static void
static void
encode_ieee_double (const struct real_format *fmt, long *buf,
encode_ieee_double (const struct real_format *fmt, long *buf,
                    const REAL_VALUE_TYPE *r)
                    const REAL_VALUE_TYPE *r)
{
{
  unsigned long image_lo, image_hi, sig_lo, sig_hi, exp;
  unsigned long image_lo, image_hi, sig_lo, sig_hi, exp;
  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
 
 
  image_hi = r->sign << 31;
  image_hi = r->sign << 31;
  image_lo = 0;
  image_lo = 0;
 
 
  if (HOST_BITS_PER_LONG == 64)
  if (HOST_BITS_PER_LONG == 64)
    {
    {
      sig_hi = r->sig[SIGSZ-1];
      sig_hi = r->sig[SIGSZ-1];
      sig_lo = (sig_hi >> (64 - 53)) & 0xffffffff;
      sig_lo = (sig_hi >> (64 - 53)) & 0xffffffff;
      sig_hi = (sig_hi >> (64 - 53 + 1) >> 31) & 0xfffff;
      sig_hi = (sig_hi >> (64 - 53 + 1) >> 31) & 0xfffff;
    }
    }
  else
  else
    {
    {
      sig_hi = r->sig[SIGSZ-1];
      sig_hi = r->sig[SIGSZ-1];
      sig_lo = r->sig[SIGSZ-2];
      sig_lo = r->sig[SIGSZ-2];
      sig_lo = (sig_hi << 21) | (sig_lo >> 11);
      sig_lo = (sig_hi << 21) | (sig_lo >> 11);
      sig_hi = (sig_hi >> 11) & 0xfffff;
      sig_hi = (sig_hi >> 11) & 0xfffff;
    }
    }
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
      if (fmt->has_inf)
      if (fmt->has_inf)
        image_hi |= 2047 << 20;
        image_hi |= 2047 << 20;
      else
      else
        {
        {
          image_hi |= 0x7fffffff;
          image_hi |= 0x7fffffff;
          image_lo = 0xffffffff;
          image_lo = 0xffffffff;
        }
        }
      break;
      break;
 
 
    case rvc_nan:
    case rvc_nan:
      if (fmt->has_nans)
      if (fmt->has_nans)
        {
        {
          if (r->canonical)
          if (r->canonical)
            sig_hi = sig_lo = 0;
            sig_hi = sig_lo = 0;
          if (r->signalling == fmt->qnan_msb_set)
          if (r->signalling == fmt->qnan_msb_set)
            sig_hi &= ~(1 << 19);
            sig_hi &= ~(1 << 19);
          else
          else
            sig_hi |= 1 << 19;
            sig_hi |= 1 << 19;
          /* We overload qnan_msb_set here: it's only clear for
          /* We overload qnan_msb_set here: it's only clear for
             mips_ieee_single, which wants all mantissa bits but the
             mips_ieee_single, which wants all mantissa bits but the
             quiet/signalling one set in canonical NaNs (at least
             quiet/signalling one set in canonical NaNs (at least
             Quiet ones).  */
             Quiet ones).  */
          if (r->canonical && !fmt->qnan_msb_set)
          if (r->canonical && !fmt->qnan_msb_set)
            {
            {
              sig_hi |= (1 << 19) - 1;
              sig_hi |= (1 << 19) - 1;
              sig_lo = 0xffffffff;
              sig_lo = 0xffffffff;
            }
            }
          else if (sig_hi == 0 && sig_lo == 0)
          else if (sig_hi == 0 && sig_lo == 0)
            sig_hi = 1 << 18;
            sig_hi = 1 << 18;
 
 
          image_hi |= 2047 << 20;
          image_hi |= 2047 << 20;
          image_hi |= sig_hi;
          image_hi |= sig_hi;
          image_lo = sig_lo;
          image_lo = sig_lo;
        }
        }
      else
      else
        {
        {
          image_hi |= 0x7fffffff;
          image_hi |= 0x7fffffff;
          image_lo = 0xffffffff;
          image_lo = 0xffffffff;
        }
        }
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
      /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
         whereas the intermediate representation is 0.F x 2**exp.
         whereas the intermediate representation is 0.F x 2**exp.
         Which means we're off by one.  */
         Which means we're off by one.  */
      if (denormal)
      if (denormal)
        exp = 0;
        exp = 0;
      else
      else
        exp = REAL_EXP (r) + 1023 - 1;
        exp = REAL_EXP (r) + 1023 - 1;
      image_hi |= exp << 20;
      image_hi |= exp << 20;
      image_hi |= sig_hi;
      image_hi |= sig_hi;
      image_lo = sig_lo;
      image_lo = sig_lo;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    buf[0] = image_hi, buf[1] = image_lo;
    buf[0] = image_hi, buf[1] = image_lo;
  else
  else
    buf[0] = image_lo, buf[1] = image_hi;
    buf[0] = image_lo, buf[1] = image_hi;
}
}
 
 
static void
static void
decode_ieee_double (const struct real_format *fmt, REAL_VALUE_TYPE *r,
decode_ieee_double (const struct real_format *fmt, REAL_VALUE_TYPE *r,
                    const long *buf)
                    const long *buf)
{
{
  unsigned long image_hi, image_lo;
  unsigned long image_hi, image_lo;
  bool sign;
  bool sign;
  int exp;
  int exp;
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    image_hi = buf[0], image_lo = buf[1];
    image_hi = buf[0], image_lo = buf[1];
  else
  else
    image_lo = buf[0], image_hi = buf[1];
    image_lo = buf[0], image_hi = buf[1];
  image_lo &= 0xffffffff;
  image_lo &= 0xffffffff;
  image_hi &= 0xffffffff;
  image_hi &= 0xffffffff;
 
 
  sign = (image_hi >> 31) & 1;
  sign = (image_hi >> 31) & 1;
  exp = (image_hi >> 20) & 0x7ff;
  exp = (image_hi >> 20) & 0x7ff;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  image_hi <<= 32 - 21;
  image_hi <<= 32 - 21;
  image_hi |= image_lo >> 21;
  image_hi |= image_lo >> 21;
  image_hi &= 0x7fffffff;
  image_hi &= 0x7fffffff;
  image_lo <<= 32 - 21;
  image_lo <<= 32 - 21;
 
 
  if (exp == 0)
  if (exp == 0)
    {
    {
      if ((image_hi || image_lo) && fmt->has_denorm)
      if ((image_hi || image_lo) && fmt->has_denorm)
        {
        {
          r->cl = rvc_normal;
          r->cl = rvc_normal;
          r->sign = sign;
          r->sign = sign;
          SET_REAL_EXP (r, -1022);
          SET_REAL_EXP (r, -1022);
          if (HOST_BITS_PER_LONG == 32)
          if (HOST_BITS_PER_LONG == 32)
            {
            {
              image_hi = (image_hi << 1) | (image_lo >> 31);
              image_hi = (image_hi << 1) | (image_lo >> 31);
              image_lo <<= 1;
              image_lo <<= 1;
              r->sig[SIGSZ-1] = image_hi;
              r->sig[SIGSZ-1] = image_hi;
              r->sig[SIGSZ-2] = image_lo;
              r->sig[SIGSZ-2] = image_lo;
            }
            }
          else
          else
            {
            {
              image_hi = (image_hi << 31 << 2) | (image_lo << 1);
              image_hi = (image_hi << 31 << 2) | (image_lo << 1);
              r->sig[SIGSZ-1] = image_hi;
              r->sig[SIGSZ-1] = image_hi;
            }
            }
          normalize (r);
          normalize (r);
        }
        }
      else if (fmt->has_signed_zero)
      else if (fmt->has_signed_zero)
        r->sign = sign;
        r->sign = sign;
    }
    }
  else if (exp == 2047 && (fmt->has_nans || fmt->has_inf))
  else if (exp == 2047 && (fmt->has_nans || fmt->has_inf))
    {
    {
      if (image_hi || image_lo)
      if (image_hi || image_lo)
        {
        {
          r->cl = rvc_nan;
          r->cl = rvc_nan;
          r->sign = sign;
          r->sign = sign;
          r->signalling = ((image_hi >> 30) & 1) ^ fmt->qnan_msb_set;
          r->signalling = ((image_hi >> 30) & 1) ^ fmt->qnan_msb_set;
          if (HOST_BITS_PER_LONG == 32)
          if (HOST_BITS_PER_LONG == 32)
            {
            {
              r->sig[SIGSZ-1] = image_hi;
              r->sig[SIGSZ-1] = image_hi;
              r->sig[SIGSZ-2] = image_lo;
              r->sig[SIGSZ-2] = image_lo;
            }
            }
          else
          else
            r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo;
            r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo;
        }
        }
      else
      else
        {
        {
          r->cl = rvc_inf;
          r->cl = rvc_inf;
          r->sign = sign;
          r->sign = sign;
        }
        }
    }
    }
  else
  else
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = sign;
      r->sign = sign;
      SET_REAL_EXP (r, exp - 1023 + 1);
      SET_REAL_EXP (r, exp - 1023 + 1);
      if (HOST_BITS_PER_LONG == 32)
      if (HOST_BITS_PER_LONG == 32)
        {
        {
          r->sig[SIGSZ-1] = image_hi | SIG_MSB;
          r->sig[SIGSZ-1] = image_hi | SIG_MSB;
          r->sig[SIGSZ-2] = image_lo;
          r->sig[SIGSZ-2] = image_lo;
        }
        }
      else
      else
        r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo | SIG_MSB;
        r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo | SIG_MSB;
    }
    }
}
}
 
 
const struct real_format ieee_double_format =
const struct real_format ieee_double_format =
  {
  {
    encode_ieee_double,
    encode_ieee_double,
    decode_ieee_double,
    decode_ieee_double,
    2,
    2,
    1,
    1,
    53,
    53,
    53,
    53,
    -1021,
    -1021,
    1024,
    1024,
    63,
    63,
    63,
    63,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };
 
 
const struct real_format mips_double_format =
const struct real_format mips_double_format =
  {
  {
    encode_ieee_double,
    encode_ieee_double,
    decode_ieee_double,
    decode_ieee_double,
    2,
    2,
    1,
    1,
    53,
    53,
    53,
    53,
    -1021,
    -1021,
    1024,
    1024,
    63,
    63,
    63,
    63,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    false
    false
  };
  };
 
 


/* IEEE extended real format.  This comes in three flavors: Intel's as
/* IEEE extended real format.  This comes in three flavors: Intel's as
   a 12 byte image, Intel's as a 16 byte image, and Motorola's.  Intel
   a 12 byte image, Intel's as a 16 byte image, and Motorola's.  Intel
   12- and 16-byte images may be big- or little endian; Motorola's is
   12- and 16-byte images may be big- or little endian; Motorola's is
   always big endian.  */
   always big endian.  */
 
 
/* Helper subroutine which converts from the internal format to the
/* Helper subroutine which converts from the internal format to the
   12-byte little-endian Intel format.  Functions below adjust this
   12-byte little-endian Intel format.  Functions below adjust this
   for the other possible formats.  */
   for the other possible formats.  */
static void
static void
encode_ieee_extended (const struct real_format *fmt, long *buf,
encode_ieee_extended (const struct real_format *fmt, long *buf,
                      const REAL_VALUE_TYPE *r)
                      const REAL_VALUE_TYPE *r)
{
{
  unsigned long image_hi, sig_hi, sig_lo;
  unsigned long image_hi, sig_hi, sig_lo;
  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
 
 
  image_hi = r->sign << 15;
  image_hi = r->sign << 15;
  sig_hi = sig_lo = 0;
  sig_hi = sig_lo = 0;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
      if (fmt->has_inf)
      if (fmt->has_inf)
        {
        {
          image_hi |= 32767;
          image_hi |= 32767;
 
 
          /* Intel requires the explicit integer bit to be set, otherwise
          /* Intel requires the explicit integer bit to be set, otherwise
             it considers the value a "pseudo-infinity".  Motorola docs
             it considers the value a "pseudo-infinity".  Motorola docs
             say it doesn't care.  */
             say it doesn't care.  */
          sig_hi = 0x80000000;
          sig_hi = 0x80000000;
        }
        }
      else
      else
        {
        {
          image_hi |= 32767;
          image_hi |= 32767;
          sig_lo = sig_hi = 0xffffffff;
          sig_lo = sig_hi = 0xffffffff;
        }
        }
      break;
      break;
 
 
    case rvc_nan:
    case rvc_nan:
      if (fmt->has_nans)
      if (fmt->has_nans)
        {
        {
          image_hi |= 32767;
          image_hi |= 32767;
          if (HOST_BITS_PER_LONG == 32)
          if (HOST_BITS_PER_LONG == 32)
            {
            {
              sig_hi = r->sig[SIGSZ-1];
              sig_hi = r->sig[SIGSZ-1];
              sig_lo = r->sig[SIGSZ-2];
              sig_lo = r->sig[SIGSZ-2];
            }
            }
          else
          else
            {
            {
              sig_lo = r->sig[SIGSZ-1];
              sig_lo = r->sig[SIGSZ-1];
              sig_hi = sig_lo >> 31 >> 1;
              sig_hi = sig_lo >> 31 >> 1;
              sig_lo &= 0xffffffff;
              sig_lo &= 0xffffffff;
            }
            }
          if (r->signalling == fmt->qnan_msb_set)
          if (r->signalling == fmt->qnan_msb_set)
            sig_hi &= ~(1 << 30);
            sig_hi &= ~(1 << 30);
          else
          else
            sig_hi |= 1 << 30;
            sig_hi |= 1 << 30;
          if ((sig_hi & 0x7fffffff) == 0 && sig_lo == 0)
          if ((sig_hi & 0x7fffffff) == 0 && sig_lo == 0)
            sig_hi = 1 << 29;
            sig_hi = 1 << 29;
 
 
          /* Intel requires the explicit integer bit to be set, otherwise
          /* Intel requires the explicit integer bit to be set, otherwise
             it considers the value a "pseudo-nan".  Motorola docs say it
             it considers the value a "pseudo-nan".  Motorola docs say it
             doesn't care.  */
             doesn't care.  */
          sig_hi |= 0x80000000;
          sig_hi |= 0x80000000;
        }
        }
      else
      else
        {
        {
          image_hi |= 32767;
          image_hi |= 32767;
          sig_lo = sig_hi = 0xffffffff;
          sig_lo = sig_hi = 0xffffffff;
        }
        }
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      {
      {
        int exp = REAL_EXP (r);
        int exp = REAL_EXP (r);
 
 
        /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
        /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
           whereas the intermediate representation is 0.F x 2**exp.
           whereas the intermediate representation is 0.F x 2**exp.
           Which means we're off by one.
           Which means we're off by one.
 
 
           Except for Motorola, which consider exp=0 and explicit
           Except for Motorola, which consider exp=0 and explicit
           integer bit set to continue to be normalized.  In theory
           integer bit set to continue to be normalized.  In theory
           this discrepancy has been taken care of by the difference
           this discrepancy has been taken care of by the difference
           in fmt->emin in round_for_format.  */
           in fmt->emin in round_for_format.  */
 
 
        if (denormal)
        if (denormal)
          exp = 0;
          exp = 0;
        else
        else
          {
          {
            exp += 16383 - 1;
            exp += 16383 - 1;
            gcc_assert (exp >= 0);
            gcc_assert (exp >= 0);
          }
          }
        image_hi |= exp;
        image_hi |= exp;
 
 
        if (HOST_BITS_PER_LONG == 32)
        if (HOST_BITS_PER_LONG == 32)
          {
          {
            sig_hi = r->sig[SIGSZ-1];
            sig_hi = r->sig[SIGSZ-1];
            sig_lo = r->sig[SIGSZ-2];
            sig_lo = r->sig[SIGSZ-2];
          }
          }
        else
        else
          {
          {
            sig_lo = r->sig[SIGSZ-1];
            sig_lo = r->sig[SIGSZ-1];
            sig_hi = sig_lo >> 31 >> 1;
            sig_hi = sig_lo >> 31 >> 1;
            sig_lo &= 0xffffffff;
            sig_lo &= 0xffffffff;
          }
          }
      }
      }
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi;
  buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi;
}
}
 
 
/* Convert from the internal format to the 12-byte Motorola format
/* Convert from the internal format to the 12-byte Motorola format
   for an IEEE extended real.  */
   for an IEEE extended real.  */
static void
static void
encode_ieee_extended_motorola (const struct real_format *fmt, long *buf,
encode_ieee_extended_motorola (const struct real_format *fmt, long *buf,
                               const REAL_VALUE_TYPE *r)
                               const REAL_VALUE_TYPE *r)
{
{
  long intermed[3];
  long intermed[3];
  encode_ieee_extended (fmt, intermed, r);
  encode_ieee_extended (fmt, intermed, r);
 
 
  /* Motorola chips are assumed always to be big-endian.  Also, the
  /* Motorola chips are assumed always to be big-endian.  Also, the
     padding in a Motorola extended real goes between the exponent and
     padding in a Motorola extended real goes between the exponent and
     the mantissa.  At this point the mantissa is entirely within
     the mantissa.  At this point the mantissa is entirely within
     elements 0 and 1 of intermed, and the exponent entirely within
     elements 0 and 1 of intermed, and the exponent entirely within
     element 2, so all we have to do is swap the order around, and
     element 2, so all we have to do is swap the order around, and
     shift element 2 left 16 bits.  */
     shift element 2 left 16 bits.  */
  buf[0] = intermed[2] << 16;
  buf[0] = intermed[2] << 16;
  buf[1] = intermed[1];
  buf[1] = intermed[1];
  buf[2] = intermed[0];
  buf[2] = intermed[0];
}
}
 
 
/* Convert from the internal format to the 12-byte Intel format for
/* Convert from the internal format to the 12-byte Intel format for
   an IEEE extended real.  */
   an IEEE extended real.  */
static void
static void
encode_ieee_extended_intel_96 (const struct real_format *fmt, long *buf,
encode_ieee_extended_intel_96 (const struct real_format *fmt, long *buf,
                               const REAL_VALUE_TYPE *r)
                               const REAL_VALUE_TYPE *r)
{
{
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    {
    {
      /* All the padding in an Intel-format extended real goes at the high
      /* All the padding in an Intel-format extended real goes at the high
         end, which in this case is after the mantissa, not the exponent.
         end, which in this case is after the mantissa, not the exponent.
         Therefore we must shift everything down 16 bits.  */
         Therefore we must shift everything down 16 bits.  */
      long intermed[3];
      long intermed[3];
      encode_ieee_extended (fmt, intermed, r);
      encode_ieee_extended (fmt, intermed, r);
      buf[0] = ((intermed[2] << 16) | ((unsigned long)(intermed[1] & 0xFFFF0000) >> 16));
      buf[0] = ((intermed[2] << 16) | ((unsigned long)(intermed[1] & 0xFFFF0000) >> 16));
      buf[1] = ((intermed[1] << 16) | ((unsigned long)(intermed[0] & 0xFFFF0000) >> 16));
      buf[1] = ((intermed[1] << 16) | ((unsigned long)(intermed[0] & 0xFFFF0000) >> 16));
      buf[2] =  (intermed[0] << 16);
      buf[2] =  (intermed[0] << 16);
    }
    }
  else
  else
    /* encode_ieee_extended produces what we want directly.  */
    /* encode_ieee_extended produces what we want directly.  */
    encode_ieee_extended (fmt, buf, r);
    encode_ieee_extended (fmt, buf, r);
}
}
 
 
/* Convert from the internal format to the 16-byte Intel format for
/* Convert from the internal format to the 16-byte Intel format for
   an IEEE extended real.  */
   an IEEE extended real.  */
static void
static void
encode_ieee_extended_intel_128 (const struct real_format *fmt, long *buf,
encode_ieee_extended_intel_128 (const struct real_format *fmt, long *buf,
                                const REAL_VALUE_TYPE *r)
                                const REAL_VALUE_TYPE *r)
{
{
  /* All the padding in an Intel-format extended real goes at the high end.  */
  /* All the padding in an Intel-format extended real goes at the high end.  */
  encode_ieee_extended_intel_96 (fmt, buf, r);
  encode_ieee_extended_intel_96 (fmt, buf, r);
  buf[3] = 0;
  buf[3] = 0;
}
}
 
 
/* As above, we have a helper function which converts from 12-byte
/* As above, we have a helper function which converts from 12-byte
   little-endian Intel format to internal format.  Functions below
   little-endian Intel format to internal format.  Functions below
   adjust for the other possible formats.  */
   adjust for the other possible formats.  */
static void
static void
decode_ieee_extended (const struct real_format *fmt, REAL_VALUE_TYPE *r,
decode_ieee_extended (const struct real_format *fmt, REAL_VALUE_TYPE *r,
                      const long *buf)
                      const long *buf)
{
{
  unsigned long image_hi, sig_hi, sig_lo;
  unsigned long image_hi, sig_hi, sig_lo;
  bool sign;
  bool sign;
  int exp;
  int exp;
 
 
  sig_lo = buf[0], sig_hi = buf[1], image_hi = buf[2];
  sig_lo = buf[0], sig_hi = buf[1], image_hi = buf[2];
  sig_lo &= 0xffffffff;
  sig_lo &= 0xffffffff;
  sig_hi &= 0xffffffff;
  sig_hi &= 0xffffffff;
  image_hi &= 0xffffffff;
  image_hi &= 0xffffffff;
 
 
  sign = (image_hi >> 15) & 1;
  sign = (image_hi >> 15) & 1;
  exp = image_hi & 0x7fff;
  exp = image_hi & 0x7fff;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (exp == 0)
  if (exp == 0)
    {
    {
      if ((sig_hi || sig_lo) && fmt->has_denorm)
      if ((sig_hi || sig_lo) && fmt->has_denorm)
        {
        {
          r->cl = rvc_normal;
          r->cl = rvc_normal;
          r->sign = sign;
          r->sign = sign;
 
 
          /* When the IEEE format contains a hidden bit, we know that
          /* When the IEEE format contains a hidden bit, we know that
             it's zero at this point, and so shift up the significand
             it's zero at this point, and so shift up the significand
             and decrease the exponent to match.  In this case, Motorola
             and decrease the exponent to match.  In this case, Motorola
             defines the explicit integer bit to be valid, so we don't
             defines the explicit integer bit to be valid, so we don't
             know whether the msb is set or not.  */
             know whether the msb is set or not.  */
          SET_REAL_EXP (r, fmt->emin);
          SET_REAL_EXP (r, fmt->emin);
          if (HOST_BITS_PER_LONG == 32)
          if (HOST_BITS_PER_LONG == 32)
            {
            {
              r->sig[SIGSZ-1] = sig_hi;
              r->sig[SIGSZ-1] = sig_hi;
              r->sig[SIGSZ-2] = sig_lo;
              r->sig[SIGSZ-2] = sig_lo;
            }
            }
          else
          else
            r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
            r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
 
 
          normalize (r);
          normalize (r);
        }
        }
      else if (fmt->has_signed_zero)
      else if (fmt->has_signed_zero)
        r->sign = sign;
        r->sign = sign;
    }
    }
  else if (exp == 32767 && (fmt->has_nans || fmt->has_inf))
  else if (exp == 32767 && (fmt->has_nans || fmt->has_inf))
    {
    {
      /* See above re "pseudo-infinities" and "pseudo-nans".
      /* See above re "pseudo-infinities" and "pseudo-nans".
         Short summary is that the MSB will likely always be
         Short summary is that the MSB will likely always be
         set, and that we don't care about it.  */
         set, and that we don't care about it.  */
      sig_hi &= 0x7fffffff;
      sig_hi &= 0x7fffffff;
 
 
      if (sig_hi || sig_lo)
      if (sig_hi || sig_lo)
        {
        {
          r->cl = rvc_nan;
          r->cl = rvc_nan;
          r->sign = sign;
          r->sign = sign;
          r->signalling = ((sig_hi >> 30) & 1) ^ fmt->qnan_msb_set;
          r->signalling = ((sig_hi >> 30) & 1) ^ fmt->qnan_msb_set;
          if (HOST_BITS_PER_LONG == 32)
          if (HOST_BITS_PER_LONG == 32)
            {
            {
              r->sig[SIGSZ-1] = sig_hi;
              r->sig[SIGSZ-1] = sig_hi;
              r->sig[SIGSZ-2] = sig_lo;
              r->sig[SIGSZ-2] = sig_lo;
            }
            }
          else
          else
            r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
            r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
        }
        }
      else
      else
        {
        {
          r->cl = rvc_inf;
          r->cl = rvc_inf;
          r->sign = sign;
          r->sign = sign;
        }
        }
    }
    }
  else
  else
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = sign;
      r->sign = sign;
      SET_REAL_EXP (r, exp - 16383 + 1);
      SET_REAL_EXP (r, exp - 16383 + 1);
      if (HOST_BITS_PER_LONG == 32)
      if (HOST_BITS_PER_LONG == 32)
        {
        {
          r->sig[SIGSZ-1] = sig_hi;
          r->sig[SIGSZ-1] = sig_hi;
          r->sig[SIGSZ-2] = sig_lo;
          r->sig[SIGSZ-2] = sig_lo;
        }
        }
      else
      else
        r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
        r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
    }
    }
}
}
 
 
/* Convert from the internal format to the 12-byte Motorola format
/* Convert from the internal format to the 12-byte Motorola format
   for an IEEE extended real.  */
   for an IEEE extended real.  */
static void
static void
decode_ieee_extended_motorola (const struct real_format *fmt, REAL_VALUE_TYPE *r,
decode_ieee_extended_motorola (const struct real_format *fmt, REAL_VALUE_TYPE *r,
                               const long *buf)
                               const long *buf)
{
{
  long intermed[3];
  long intermed[3];
 
 
  /* Motorola chips are assumed always to be big-endian.  Also, the
  /* Motorola chips are assumed always to be big-endian.  Also, the
     padding in a Motorola extended real goes between the exponent and
     padding in a Motorola extended real goes between the exponent and
     the mantissa; remove it.  */
     the mantissa; remove it.  */
  intermed[0] = buf[2];
  intermed[0] = buf[2];
  intermed[1] = buf[1];
  intermed[1] = buf[1];
  intermed[2] = (unsigned long)buf[0] >> 16;
  intermed[2] = (unsigned long)buf[0] >> 16;
 
 
  decode_ieee_extended (fmt, r, intermed);
  decode_ieee_extended (fmt, r, intermed);
}
}
 
 
/* Convert from the internal format to the 12-byte Intel format for
/* Convert from the internal format to the 12-byte Intel format for
   an IEEE extended real.  */
   an IEEE extended real.  */
static void
static void
decode_ieee_extended_intel_96 (const struct real_format *fmt, REAL_VALUE_TYPE *r,
decode_ieee_extended_intel_96 (const struct real_format *fmt, REAL_VALUE_TYPE *r,
                               const long *buf)
                               const long *buf)
{
{
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    {
    {
      /* All the padding in an Intel-format extended real goes at the high
      /* All the padding in an Intel-format extended real goes at the high
         end, which in this case is after the mantissa, not the exponent.
         end, which in this case is after the mantissa, not the exponent.
         Therefore we must shift everything up 16 bits.  */
         Therefore we must shift everything up 16 bits.  */
      long intermed[3];
      long intermed[3];
 
 
      intermed[0] = (((unsigned long)buf[2] >> 16) | (buf[1] << 16));
      intermed[0] = (((unsigned long)buf[2] >> 16) | (buf[1] << 16));
      intermed[1] = (((unsigned long)buf[1] >> 16) | (buf[0] << 16));
      intermed[1] = (((unsigned long)buf[1] >> 16) | (buf[0] << 16));
      intermed[2] =  ((unsigned long)buf[0] >> 16);
      intermed[2] =  ((unsigned long)buf[0] >> 16);
 
 
      decode_ieee_extended (fmt, r, intermed);
      decode_ieee_extended (fmt, r, intermed);
    }
    }
  else
  else
    /* decode_ieee_extended produces what we want directly.  */
    /* decode_ieee_extended produces what we want directly.  */
    decode_ieee_extended (fmt, r, buf);
    decode_ieee_extended (fmt, r, buf);
}
}
 
 
/* Convert from the internal format to the 16-byte Intel format for
/* Convert from the internal format to the 16-byte Intel format for
   an IEEE extended real.  */
   an IEEE extended real.  */
static void
static void
decode_ieee_extended_intel_128 (const struct real_format *fmt, REAL_VALUE_TYPE *r,
decode_ieee_extended_intel_128 (const struct real_format *fmt, REAL_VALUE_TYPE *r,
                                const long *buf)
                                const long *buf)
{
{
  /* All the padding in an Intel-format extended real goes at the high end.  */
  /* All the padding in an Intel-format extended real goes at the high end.  */
  decode_ieee_extended_intel_96 (fmt, r, buf);
  decode_ieee_extended_intel_96 (fmt, r, buf);
}
}
 
 
const struct real_format ieee_extended_motorola_format =
const struct real_format ieee_extended_motorola_format =
  {
  {
    encode_ieee_extended_motorola,
    encode_ieee_extended_motorola,
    decode_ieee_extended_motorola,
    decode_ieee_extended_motorola,
    2,
    2,
    1,
    1,
    64,
    64,
    64,
    64,
    -16382,
    -16382,
    16384,
    16384,
    95,
    95,
    95,
    95,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };
 
 
const struct real_format ieee_extended_intel_96_format =
const struct real_format ieee_extended_intel_96_format =
  {
  {
    encode_ieee_extended_intel_96,
    encode_ieee_extended_intel_96,
    decode_ieee_extended_intel_96,
    decode_ieee_extended_intel_96,
    2,
    2,
    1,
    1,
    64,
    64,
    64,
    64,
    -16381,
    -16381,
    16384,
    16384,
    79,
    79,
    79,
    79,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };
 
 
const struct real_format ieee_extended_intel_128_format =
const struct real_format ieee_extended_intel_128_format =
  {
  {
    encode_ieee_extended_intel_128,
    encode_ieee_extended_intel_128,
    decode_ieee_extended_intel_128,
    decode_ieee_extended_intel_128,
    2,
    2,
    1,
    1,
    64,
    64,
    64,
    64,
    -16381,
    -16381,
    16384,
    16384,
    79,
    79,
    79,
    79,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };
 
 
/* The following caters to i386 systems that set the rounding precision
/* The following caters to i386 systems that set the rounding precision
   to 53 bits instead of 64, e.g. FreeBSD.  */
   to 53 bits instead of 64, e.g. FreeBSD.  */
const struct real_format ieee_extended_intel_96_round_53_format =
const struct real_format ieee_extended_intel_96_round_53_format =
  {
  {
    encode_ieee_extended_intel_96,
    encode_ieee_extended_intel_96,
    decode_ieee_extended_intel_96,
    decode_ieee_extended_intel_96,
    2,
    2,
    1,
    1,
    53,
    53,
    53,
    53,
    -16381,
    -16381,
    16384,
    16384,
    79,
    79,
    79,
    79,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };


/* IBM 128-bit extended precision format: a pair of IEEE double precision
/* IBM 128-bit extended precision format: a pair of IEEE double precision
   numbers whose sum is equal to the extended precision value.  The number
   numbers whose sum is equal to the extended precision value.  The number
   with greater magnitude is first.  This format has the same magnitude
   with greater magnitude is first.  This format has the same magnitude
   range as an IEEE double precision value, but effectively 106 bits of
   range as an IEEE double precision value, but effectively 106 bits of
   significand precision.  Infinity and NaN are represented by their IEEE
   significand precision.  Infinity and NaN are represented by their IEEE
   double precision value stored in the first number, the second number is
   double precision value stored in the first number, the second number is
   +0.0 or -0.0 for Infinity and don't-care for NaN.  */
   +0.0 or -0.0 for Infinity and don't-care for NaN.  */
 
 
static void encode_ibm_extended (const struct real_format *fmt,
static void encode_ibm_extended (const struct real_format *fmt,
                                 long *, const REAL_VALUE_TYPE *);
                                 long *, const REAL_VALUE_TYPE *);
static void decode_ibm_extended (const struct real_format *,
static void decode_ibm_extended (const struct real_format *,
                                 REAL_VALUE_TYPE *, const long *);
                                 REAL_VALUE_TYPE *, const long *);
 
 
static void
static void
encode_ibm_extended (const struct real_format *fmt, long *buf,
encode_ibm_extended (const struct real_format *fmt, long *buf,
                     const REAL_VALUE_TYPE *r)
                     const REAL_VALUE_TYPE *r)
{
{
  REAL_VALUE_TYPE u, normr, v;
  REAL_VALUE_TYPE u, normr, v;
  const struct real_format *base_fmt;
  const struct real_format *base_fmt;
 
 
  base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
  base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
 
 
  /* Renormlize R before doing any arithmetic on it.  */
  /* Renormlize R before doing any arithmetic on it.  */
  normr = *r;
  normr = *r;
  if (normr.cl == rvc_normal)
  if (normr.cl == rvc_normal)
    normalize (&normr);
    normalize (&normr);
 
 
  /* u = IEEE double precision portion of significand.  */
  /* u = IEEE double precision portion of significand.  */
  u = normr;
  u = normr;
  round_for_format (base_fmt, &u);
  round_for_format (base_fmt, &u);
  encode_ieee_double (base_fmt, &buf[0], &u);
  encode_ieee_double (base_fmt, &buf[0], &u);
 
 
  if (u.cl == rvc_normal)
  if (u.cl == rvc_normal)
    {
    {
      do_add (&v, &normr, &u, 1);
      do_add (&v, &normr, &u, 1);
      /* Call round_for_format since we might need to denormalize.  */
      /* Call round_for_format since we might need to denormalize.  */
      round_for_format (base_fmt, &v);
      round_for_format (base_fmt, &v);
      encode_ieee_double (base_fmt, &buf[2], &v);
      encode_ieee_double (base_fmt, &buf[2], &v);
    }
    }
  else
  else
    {
    {
      /* Inf, NaN, 0 are all representable as doubles, so the
      /* Inf, NaN, 0 are all representable as doubles, so the
         least-significant part can be 0.0.  */
         least-significant part can be 0.0.  */
      buf[2] = 0;
      buf[2] = 0;
      buf[3] = 0;
      buf[3] = 0;
    }
    }
}
}
 
 
static void
static void
decode_ibm_extended (const struct real_format *fmt ATTRIBUTE_UNUSED, REAL_VALUE_TYPE *r,
decode_ibm_extended (const struct real_format *fmt ATTRIBUTE_UNUSED, REAL_VALUE_TYPE *r,
                     const long *buf)
                     const long *buf)
{
{
  REAL_VALUE_TYPE u, v;
  REAL_VALUE_TYPE u, v;
  const struct real_format *base_fmt;
  const struct real_format *base_fmt;
 
 
  base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
  base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
  decode_ieee_double (base_fmt, &u, &buf[0]);
  decode_ieee_double (base_fmt, &u, &buf[0]);
 
 
  if (u.cl != rvc_zero && u.cl != rvc_inf && u.cl != rvc_nan)
  if (u.cl != rvc_zero && u.cl != rvc_inf && u.cl != rvc_nan)
    {
    {
      decode_ieee_double (base_fmt, &v, &buf[2]);
      decode_ieee_double (base_fmt, &v, &buf[2]);
      do_add (r, &u, &v, 0);
      do_add (r, &u, &v, 0);
    }
    }
  else
  else
    *r = u;
    *r = u;
}
}
 
 
const struct real_format ibm_extended_format =
const struct real_format ibm_extended_format =
  {
  {
    encode_ibm_extended,
    encode_ibm_extended,
    decode_ibm_extended,
    decode_ibm_extended,
    2,
    2,
    1,
    1,
    53 + 53,
    53 + 53,
    53,
    53,
    -1021 + 53,
    -1021 + 53,
    1024,
    1024,
    127,
    127,
    -1,
    -1,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };
 
 
const struct real_format mips_extended_format =
const struct real_format mips_extended_format =
  {
  {
    encode_ibm_extended,
    encode_ibm_extended,
    decode_ibm_extended,
    decode_ibm_extended,
    2,
    2,
    1,
    1,
    53 + 53,
    53 + 53,
    53,
    53,
    -1021 + 53,
    -1021 + 53,
    1024,
    1024,
    127,
    127,
    -1,
    -1,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    false
    false
  };
  };
 
 


/* IEEE quad precision format.  */
/* IEEE quad precision format.  */
 
 
static void encode_ieee_quad (const struct real_format *fmt,
static void encode_ieee_quad (const struct real_format *fmt,
                              long *, const REAL_VALUE_TYPE *);
                              long *, const REAL_VALUE_TYPE *);
static void decode_ieee_quad (const struct real_format *,
static void decode_ieee_quad (const struct real_format *,
                              REAL_VALUE_TYPE *, const long *);
                              REAL_VALUE_TYPE *, const long *);
 
 
static void
static void
encode_ieee_quad (const struct real_format *fmt, long *buf,
encode_ieee_quad (const struct real_format *fmt, long *buf,
                  const REAL_VALUE_TYPE *r)
                  const REAL_VALUE_TYPE *r)
{
{
  unsigned long image3, image2, image1, image0, exp;
  unsigned long image3, image2, image1, image0, exp;
  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
  REAL_VALUE_TYPE u;
  REAL_VALUE_TYPE u;
 
 
  image3 = r->sign << 31;
  image3 = r->sign << 31;
  image2 = 0;
  image2 = 0;
  image1 = 0;
  image1 = 0;
  image0 = 0;
  image0 = 0;
 
 
  rshift_significand (&u, r, SIGNIFICAND_BITS - 113);
  rshift_significand (&u, r, SIGNIFICAND_BITS - 113);
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
      if (fmt->has_inf)
      if (fmt->has_inf)
        image3 |= 32767 << 16;
        image3 |= 32767 << 16;
      else
      else
        {
        {
          image3 |= 0x7fffffff;
          image3 |= 0x7fffffff;
          image2 = 0xffffffff;
          image2 = 0xffffffff;
          image1 = 0xffffffff;
          image1 = 0xffffffff;
          image0 = 0xffffffff;
          image0 = 0xffffffff;
        }
        }
      break;
      break;
 
 
    case rvc_nan:
    case rvc_nan:
      if (fmt->has_nans)
      if (fmt->has_nans)
        {
        {
          image3 |= 32767 << 16;
          image3 |= 32767 << 16;
 
 
          if (r->canonical)
          if (r->canonical)
            {
            {
              /* Don't use bits from the significand.  The
              /* Don't use bits from the significand.  The
                 initialization above is right.  */
                 initialization above is right.  */
            }
            }
          else if (HOST_BITS_PER_LONG == 32)
          else if (HOST_BITS_PER_LONG == 32)
            {
            {
              image0 = u.sig[0];
              image0 = u.sig[0];
              image1 = u.sig[1];
              image1 = u.sig[1];
              image2 = u.sig[2];
              image2 = u.sig[2];
              image3 |= u.sig[3] & 0xffff;
              image3 |= u.sig[3] & 0xffff;
            }
            }
          else
          else
            {
            {
              image0 = u.sig[0];
              image0 = u.sig[0];
              image1 = image0 >> 31 >> 1;
              image1 = image0 >> 31 >> 1;
              image2 = u.sig[1];
              image2 = u.sig[1];
              image3 |= (image2 >> 31 >> 1) & 0xffff;
              image3 |= (image2 >> 31 >> 1) & 0xffff;
              image0 &= 0xffffffff;
              image0 &= 0xffffffff;
              image2 &= 0xffffffff;
              image2 &= 0xffffffff;
            }
            }
          if (r->signalling == fmt->qnan_msb_set)
          if (r->signalling == fmt->qnan_msb_set)
            image3 &= ~0x8000;
            image3 &= ~0x8000;
          else
          else
            image3 |= 0x8000;
            image3 |= 0x8000;
          /* We overload qnan_msb_set here: it's only clear for
          /* We overload qnan_msb_set here: it's only clear for
             mips_ieee_single, which wants all mantissa bits but the
             mips_ieee_single, which wants all mantissa bits but the
             quiet/signalling one set in canonical NaNs (at least
             quiet/signalling one set in canonical NaNs (at least
             Quiet ones).  */
             Quiet ones).  */
          if (r->canonical && !fmt->qnan_msb_set)
          if (r->canonical && !fmt->qnan_msb_set)
            {
            {
              image3 |= 0x7fff;
              image3 |= 0x7fff;
              image2 = image1 = image0 = 0xffffffff;
              image2 = image1 = image0 = 0xffffffff;
            }
            }
          else if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
          else if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
            image3 |= 0x4000;
            image3 |= 0x4000;
        }
        }
      else
      else
        {
        {
          image3 |= 0x7fffffff;
          image3 |= 0x7fffffff;
          image2 = 0xffffffff;
          image2 = 0xffffffff;
          image1 = 0xffffffff;
          image1 = 0xffffffff;
          image0 = 0xffffffff;
          image0 = 0xffffffff;
        }
        }
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
      /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
         whereas the intermediate representation is 0.F x 2**exp.
         whereas the intermediate representation is 0.F x 2**exp.
         Which means we're off by one.  */
         Which means we're off by one.  */
      if (denormal)
      if (denormal)
        exp = 0;
        exp = 0;
      else
      else
        exp = REAL_EXP (r) + 16383 - 1;
        exp = REAL_EXP (r) + 16383 - 1;
      image3 |= exp << 16;
      image3 |= exp << 16;
 
 
      if (HOST_BITS_PER_LONG == 32)
      if (HOST_BITS_PER_LONG == 32)
        {
        {
          image0 = u.sig[0];
          image0 = u.sig[0];
          image1 = u.sig[1];
          image1 = u.sig[1];
          image2 = u.sig[2];
          image2 = u.sig[2];
          image3 |= u.sig[3] & 0xffff;
          image3 |= u.sig[3] & 0xffff;
        }
        }
      else
      else
        {
        {
          image0 = u.sig[0];
          image0 = u.sig[0];
          image1 = image0 >> 31 >> 1;
          image1 = image0 >> 31 >> 1;
          image2 = u.sig[1];
          image2 = u.sig[1];
          image3 |= (image2 >> 31 >> 1) & 0xffff;
          image3 |= (image2 >> 31 >> 1) & 0xffff;
          image0 &= 0xffffffff;
          image0 &= 0xffffffff;
          image2 &= 0xffffffff;
          image2 &= 0xffffffff;
        }
        }
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    {
    {
      buf[0] = image3;
      buf[0] = image3;
      buf[1] = image2;
      buf[1] = image2;
      buf[2] = image1;
      buf[2] = image1;
      buf[3] = image0;
      buf[3] = image0;
    }
    }
  else
  else
    {
    {
      buf[0] = image0;
      buf[0] = image0;
      buf[1] = image1;
      buf[1] = image1;
      buf[2] = image2;
      buf[2] = image2;
      buf[3] = image3;
      buf[3] = image3;
    }
    }
}
}
 
 
static void
static void
decode_ieee_quad (const struct real_format *fmt, REAL_VALUE_TYPE *r,
decode_ieee_quad (const struct real_format *fmt, REAL_VALUE_TYPE *r,
                  const long *buf)
                  const long *buf)
{
{
  unsigned long image3, image2, image1, image0;
  unsigned long image3, image2, image1, image0;
  bool sign;
  bool sign;
  int exp;
  int exp;
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    {
    {
      image3 = buf[0];
      image3 = buf[0];
      image2 = buf[1];
      image2 = buf[1];
      image1 = buf[2];
      image1 = buf[2];
      image0 = buf[3];
      image0 = buf[3];
    }
    }
  else
  else
    {
    {
      image0 = buf[0];
      image0 = buf[0];
      image1 = buf[1];
      image1 = buf[1];
      image2 = buf[2];
      image2 = buf[2];
      image3 = buf[3];
      image3 = buf[3];
    }
    }
  image0 &= 0xffffffff;
  image0 &= 0xffffffff;
  image1 &= 0xffffffff;
  image1 &= 0xffffffff;
  image2 &= 0xffffffff;
  image2 &= 0xffffffff;
 
 
  sign = (image3 >> 31) & 1;
  sign = (image3 >> 31) & 1;
  exp = (image3 >> 16) & 0x7fff;
  exp = (image3 >> 16) & 0x7fff;
  image3 &= 0xffff;
  image3 &= 0xffff;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (exp == 0)
  if (exp == 0)
    {
    {
      if ((image3 | image2 | image1 | image0) && fmt->has_denorm)
      if ((image3 | image2 | image1 | image0) && fmt->has_denorm)
        {
        {
          r->cl = rvc_normal;
          r->cl = rvc_normal;
          r->sign = sign;
          r->sign = sign;
 
 
          SET_REAL_EXP (r, -16382 + (SIGNIFICAND_BITS - 112));
          SET_REAL_EXP (r, -16382 + (SIGNIFICAND_BITS - 112));
          if (HOST_BITS_PER_LONG == 32)
          if (HOST_BITS_PER_LONG == 32)
            {
            {
              r->sig[0] = image0;
              r->sig[0] = image0;
              r->sig[1] = image1;
              r->sig[1] = image1;
              r->sig[2] = image2;
              r->sig[2] = image2;
              r->sig[3] = image3;
              r->sig[3] = image3;
            }
            }
          else
          else
            {
            {
              r->sig[0] = (image1 << 31 << 1) | image0;
              r->sig[0] = (image1 << 31 << 1) | image0;
              r->sig[1] = (image3 << 31 << 1) | image2;
              r->sig[1] = (image3 << 31 << 1) | image2;
            }
            }
 
 
          normalize (r);
          normalize (r);
        }
        }
      else if (fmt->has_signed_zero)
      else if (fmt->has_signed_zero)
        r->sign = sign;
        r->sign = sign;
    }
    }
  else if (exp == 32767 && (fmt->has_nans || fmt->has_inf))
  else if (exp == 32767 && (fmt->has_nans || fmt->has_inf))
    {
    {
      if (image3 | image2 | image1 | image0)
      if (image3 | image2 | image1 | image0)
        {
        {
          r->cl = rvc_nan;
          r->cl = rvc_nan;
          r->sign = sign;
          r->sign = sign;
          r->signalling = ((image3 >> 15) & 1) ^ fmt->qnan_msb_set;
          r->signalling = ((image3 >> 15) & 1) ^ fmt->qnan_msb_set;
 
 
          if (HOST_BITS_PER_LONG == 32)
          if (HOST_BITS_PER_LONG == 32)
            {
            {
              r->sig[0] = image0;
              r->sig[0] = image0;
              r->sig[1] = image1;
              r->sig[1] = image1;
              r->sig[2] = image2;
              r->sig[2] = image2;
              r->sig[3] = image3;
              r->sig[3] = image3;
            }
            }
          else
          else
            {
            {
              r->sig[0] = (image1 << 31 << 1) | image0;
              r->sig[0] = (image1 << 31 << 1) | image0;
              r->sig[1] = (image3 << 31 << 1) | image2;
              r->sig[1] = (image3 << 31 << 1) | image2;
            }
            }
          lshift_significand (r, r, SIGNIFICAND_BITS - 113);
          lshift_significand (r, r, SIGNIFICAND_BITS - 113);
        }
        }
      else
      else
        {
        {
          r->cl = rvc_inf;
          r->cl = rvc_inf;
          r->sign = sign;
          r->sign = sign;
        }
        }
    }
    }
  else
  else
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = sign;
      r->sign = sign;
      SET_REAL_EXP (r, exp - 16383 + 1);
      SET_REAL_EXP (r, exp - 16383 + 1);
 
 
      if (HOST_BITS_PER_LONG == 32)
      if (HOST_BITS_PER_LONG == 32)
        {
        {
          r->sig[0] = image0;
          r->sig[0] = image0;
          r->sig[1] = image1;
          r->sig[1] = image1;
          r->sig[2] = image2;
          r->sig[2] = image2;
          r->sig[3] = image3;
          r->sig[3] = image3;
        }
        }
      else
      else
        {
        {
          r->sig[0] = (image1 << 31 << 1) | image0;
          r->sig[0] = (image1 << 31 << 1) | image0;
          r->sig[1] = (image3 << 31 << 1) | image2;
          r->sig[1] = (image3 << 31 << 1) | image2;
        }
        }
      lshift_significand (r, r, SIGNIFICAND_BITS - 113);
      lshift_significand (r, r, SIGNIFICAND_BITS - 113);
      r->sig[SIGSZ-1] |= SIG_MSB;
      r->sig[SIGSZ-1] |= SIG_MSB;
    }
    }
}
}
 
 
const struct real_format ieee_quad_format =
const struct real_format ieee_quad_format =
  {
  {
    encode_ieee_quad,
    encode_ieee_quad,
    decode_ieee_quad,
    decode_ieee_quad,
    2,
    2,
    1,
    1,
    113,
    113,
    113,
    113,
    -16381,
    -16381,
    16384,
    16384,
    127,
    127,
    127,
    127,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };
 
 
const struct real_format mips_quad_format =
const struct real_format mips_quad_format =
  {
  {
    encode_ieee_quad,
    encode_ieee_quad,
    decode_ieee_quad,
    decode_ieee_quad,
    2,
    2,
    1,
    1,
    113,
    113,
    113,
    113,
    -16381,
    -16381,
    16384,
    16384,
    127,
    127,
    127,
    127,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    false
    false
  };
  };


/* Descriptions of VAX floating point formats can be found beginning at
/* Descriptions of VAX floating point formats can be found beginning at
 
 
   http://h71000.www7.hp.com/doc/73FINAL/4515/4515pro_013.html#f_floating_point_format
   http://h71000.www7.hp.com/doc/73FINAL/4515/4515pro_013.html#f_floating_point_format
 
 
   The thing to remember is that they're almost IEEE, except for word
   The thing to remember is that they're almost IEEE, except for word
   order, exponent bias, and the lack of infinities, nans, and denormals.
   order, exponent bias, and the lack of infinities, nans, and denormals.
 
 
   We don't implement the H_floating format here, simply because neither
   We don't implement the H_floating format here, simply because neither
   the VAX or Alpha ports use it.  */
   the VAX or Alpha ports use it.  */
 
 
static void encode_vax_f (const struct real_format *fmt,
static void encode_vax_f (const struct real_format *fmt,
                          long *, const REAL_VALUE_TYPE *);
                          long *, const REAL_VALUE_TYPE *);
static void decode_vax_f (const struct real_format *,
static void decode_vax_f (const struct real_format *,
                          REAL_VALUE_TYPE *, const long *);
                          REAL_VALUE_TYPE *, const long *);
static void encode_vax_d (const struct real_format *fmt,
static void encode_vax_d (const struct real_format *fmt,
                          long *, const REAL_VALUE_TYPE *);
                          long *, const REAL_VALUE_TYPE *);
static void decode_vax_d (const struct real_format *,
static void decode_vax_d (const struct real_format *,
                          REAL_VALUE_TYPE *, const long *);
                          REAL_VALUE_TYPE *, const long *);
static void encode_vax_g (const struct real_format *fmt,
static void encode_vax_g (const struct real_format *fmt,
                          long *, const REAL_VALUE_TYPE *);
                          long *, const REAL_VALUE_TYPE *);
static void decode_vax_g (const struct real_format *,
static void decode_vax_g (const struct real_format *,
                          REAL_VALUE_TYPE *, const long *);
                          REAL_VALUE_TYPE *, const long *);
 
 
static void
static void
encode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
encode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
              const REAL_VALUE_TYPE *r)
              const REAL_VALUE_TYPE *r)
{
{
  unsigned long sign, exp, sig, image;
  unsigned long sign, exp, sig, image;
 
 
  sign = r->sign << 15;
  sign = r->sign << 15;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      image = 0;
      image = 0;
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      image = 0xffff7fff | sign;
      image = 0xffff7fff | sign;
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
      sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
      exp = REAL_EXP (r) + 128;
      exp = REAL_EXP (r) + 128;
 
 
      image = (sig << 16) & 0xffff0000;
      image = (sig << 16) & 0xffff0000;
      image |= sign;
      image |= sign;
      image |= exp << 7;
      image |= exp << 7;
      image |= sig >> 16;
      image |= sig >> 16;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  buf[0] = image;
  buf[0] = image;
}
}
 
 
static void
static void
decode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
              REAL_VALUE_TYPE *r, const long *buf)
              REAL_VALUE_TYPE *r, const long *buf)
{
{
  unsigned long image = buf[0] & 0xffffffff;
  unsigned long image = buf[0] & 0xffffffff;
  int exp = (image >> 7) & 0xff;
  int exp = (image >> 7) & 0xff;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (exp != 0)
  if (exp != 0)
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = (image >> 15) & 1;
      r->sign = (image >> 15) & 1;
      SET_REAL_EXP (r, exp - 128);
      SET_REAL_EXP (r, exp - 128);
 
 
      image = ((image & 0x7f) << 16) | ((image >> 16) & 0xffff);
      image = ((image & 0x7f) << 16) | ((image >> 16) & 0xffff);
      r->sig[SIGSZ-1] = (image << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
      r->sig[SIGSZ-1] = (image << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
    }
    }
}
}
 
 
static void
static void
encode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
encode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
              const REAL_VALUE_TYPE *r)
              const REAL_VALUE_TYPE *r)
{
{
  unsigned long image0, image1, sign = r->sign << 15;
  unsigned long image0, image1, sign = r->sign << 15;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      image0 = image1 = 0;
      image0 = image1 = 0;
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      image0 = 0xffff7fff | sign;
      image0 = 0xffff7fff | sign;
      image1 = 0xffffffff;
      image1 = 0xffffffff;
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      /* Extract the significand into straight hi:lo.  */
      /* Extract the significand into straight hi:lo.  */
      if (HOST_BITS_PER_LONG == 64)
      if (HOST_BITS_PER_LONG == 64)
        {
        {
          image0 = r->sig[SIGSZ-1];
          image0 = r->sig[SIGSZ-1];
          image1 = (image0 >> (64 - 56)) & 0xffffffff;
          image1 = (image0 >> (64 - 56)) & 0xffffffff;
          image0 = (image0 >> (64 - 56 + 1) >> 31) & 0x7fffff;
          image0 = (image0 >> (64 - 56 + 1) >> 31) & 0x7fffff;
        }
        }
      else
      else
        {
        {
          image0 = r->sig[SIGSZ-1];
          image0 = r->sig[SIGSZ-1];
          image1 = r->sig[SIGSZ-2];
          image1 = r->sig[SIGSZ-2];
          image1 = (image0 << 24) | (image1 >> 8);
          image1 = (image0 << 24) | (image1 >> 8);
          image0 = (image0 >> 8) & 0xffffff;
          image0 = (image0 >> 8) & 0xffffff;
        }
        }
 
 
      /* Rearrange the half-words of the significand to match the
      /* Rearrange the half-words of the significand to match the
         external format.  */
         external format.  */
      image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff007f;
      image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff007f;
      image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
      image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
 
 
      /* Add the sign and exponent.  */
      /* Add the sign and exponent.  */
      image0 |= sign;
      image0 |= sign;
      image0 |= (REAL_EXP (r) + 128) << 7;
      image0 |= (REAL_EXP (r) + 128) << 7;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    buf[0] = image1, buf[1] = image0;
    buf[0] = image1, buf[1] = image0;
  else
  else
    buf[0] = image0, buf[1] = image1;
    buf[0] = image0, buf[1] = image1;
}
}
 
 
static void
static void
decode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
              REAL_VALUE_TYPE *r, const long *buf)
              REAL_VALUE_TYPE *r, const long *buf)
{
{
  unsigned long image0, image1;
  unsigned long image0, image1;
  int exp;
  int exp;
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    image1 = buf[0], image0 = buf[1];
    image1 = buf[0], image0 = buf[1];
  else
  else
    image0 = buf[0], image1 = buf[1];
    image0 = buf[0], image1 = buf[1];
  image0 &= 0xffffffff;
  image0 &= 0xffffffff;
  image1 &= 0xffffffff;
  image1 &= 0xffffffff;
 
 
  exp = (image0 >> 7) & 0xff;
  exp = (image0 >> 7) & 0xff;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (exp != 0)
  if (exp != 0)
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = (image0 >> 15) & 1;
      r->sign = (image0 >> 15) & 1;
      SET_REAL_EXP (r, exp - 128);
      SET_REAL_EXP (r, exp - 128);
 
 
      /* Rearrange the half-words of the external format into
      /* Rearrange the half-words of the external format into
         proper ascending order.  */
         proper ascending order.  */
      image0 = ((image0 & 0x7f) << 16) | ((image0 >> 16) & 0xffff);
      image0 = ((image0 & 0x7f) << 16) | ((image0 >> 16) & 0xffff);
      image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff);
      image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff);
 
 
      if (HOST_BITS_PER_LONG == 64)
      if (HOST_BITS_PER_LONG == 64)
        {
        {
          image0 = (image0 << 31 << 1) | image1;
          image0 = (image0 << 31 << 1) | image1;
          image0 <<= 64 - 56;
          image0 <<= 64 - 56;
          image0 |= SIG_MSB;
          image0 |= SIG_MSB;
          r->sig[SIGSZ-1] = image0;
          r->sig[SIGSZ-1] = image0;
        }
        }
      else
      else
        {
        {
          r->sig[SIGSZ-1] = image0;
          r->sig[SIGSZ-1] = image0;
          r->sig[SIGSZ-2] = image1;
          r->sig[SIGSZ-2] = image1;
          lshift_significand (r, r, 2*HOST_BITS_PER_LONG - 56);
          lshift_significand (r, r, 2*HOST_BITS_PER_LONG - 56);
          r->sig[SIGSZ-1] |= SIG_MSB;
          r->sig[SIGSZ-1] |= SIG_MSB;
        }
        }
    }
    }
}
}
 
 
static void
static void
encode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
encode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
              const REAL_VALUE_TYPE *r)
              const REAL_VALUE_TYPE *r)
{
{
  unsigned long image0, image1, sign = r->sign << 15;
  unsigned long image0, image1, sign = r->sign << 15;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      image0 = image1 = 0;
      image0 = image1 = 0;
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      image0 = 0xffff7fff | sign;
      image0 = 0xffff7fff | sign;
      image1 = 0xffffffff;
      image1 = 0xffffffff;
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      /* Extract the significand into straight hi:lo.  */
      /* Extract the significand into straight hi:lo.  */
      if (HOST_BITS_PER_LONG == 64)
      if (HOST_BITS_PER_LONG == 64)
        {
        {
          image0 = r->sig[SIGSZ-1];
          image0 = r->sig[SIGSZ-1];
          image1 = (image0 >> (64 - 53)) & 0xffffffff;
          image1 = (image0 >> (64 - 53)) & 0xffffffff;
          image0 = (image0 >> (64 - 53 + 1) >> 31) & 0xfffff;
          image0 = (image0 >> (64 - 53 + 1) >> 31) & 0xfffff;
        }
        }
      else
      else
        {
        {
          image0 = r->sig[SIGSZ-1];
          image0 = r->sig[SIGSZ-1];
          image1 = r->sig[SIGSZ-2];
          image1 = r->sig[SIGSZ-2];
          image1 = (image0 << 21) | (image1 >> 11);
          image1 = (image0 << 21) | (image1 >> 11);
          image0 = (image0 >> 11) & 0xfffff;
          image0 = (image0 >> 11) & 0xfffff;
        }
        }
 
 
      /* Rearrange the half-words of the significand to match the
      /* Rearrange the half-words of the significand to match the
         external format.  */
         external format.  */
      image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff000f;
      image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff000f;
      image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
      image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
 
 
      /* Add the sign and exponent.  */
      /* Add the sign and exponent.  */
      image0 |= sign;
      image0 |= sign;
      image0 |= (REAL_EXP (r) + 1024) << 4;
      image0 |= (REAL_EXP (r) + 1024) << 4;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    buf[0] = image1, buf[1] = image0;
    buf[0] = image1, buf[1] = image0;
  else
  else
    buf[0] = image0, buf[1] = image1;
    buf[0] = image0, buf[1] = image1;
}
}
 
 
static void
static void
decode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED,
              REAL_VALUE_TYPE *r, const long *buf)
              REAL_VALUE_TYPE *r, const long *buf)
{
{
  unsigned long image0, image1;
  unsigned long image0, image1;
  int exp;
  int exp;
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    image1 = buf[0], image0 = buf[1];
    image1 = buf[0], image0 = buf[1];
  else
  else
    image0 = buf[0], image1 = buf[1];
    image0 = buf[0], image1 = buf[1];
  image0 &= 0xffffffff;
  image0 &= 0xffffffff;
  image1 &= 0xffffffff;
  image1 &= 0xffffffff;
 
 
  exp = (image0 >> 4) & 0x7ff;
  exp = (image0 >> 4) & 0x7ff;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (exp != 0)
  if (exp != 0)
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = (image0 >> 15) & 1;
      r->sign = (image0 >> 15) & 1;
      SET_REAL_EXP (r, exp - 1024);
      SET_REAL_EXP (r, exp - 1024);
 
 
      /* Rearrange the half-words of the external format into
      /* Rearrange the half-words of the external format into
         proper ascending order.  */
         proper ascending order.  */
      image0 = ((image0 & 0xf) << 16) | ((image0 >> 16) & 0xffff);
      image0 = ((image0 & 0xf) << 16) | ((image0 >> 16) & 0xffff);
      image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff);
      image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff);
 
 
      if (HOST_BITS_PER_LONG == 64)
      if (HOST_BITS_PER_LONG == 64)
        {
        {
          image0 = (image0 << 31 << 1) | image1;
          image0 = (image0 << 31 << 1) | image1;
          image0 <<= 64 - 53;
          image0 <<= 64 - 53;
          image0 |= SIG_MSB;
          image0 |= SIG_MSB;
          r->sig[SIGSZ-1] = image0;
          r->sig[SIGSZ-1] = image0;
        }
        }
      else
      else
        {
        {
          r->sig[SIGSZ-1] = image0;
          r->sig[SIGSZ-1] = image0;
          r->sig[SIGSZ-2] = image1;
          r->sig[SIGSZ-2] = image1;
          lshift_significand (r, r, 64 - 53);
          lshift_significand (r, r, 64 - 53);
          r->sig[SIGSZ-1] |= SIG_MSB;
          r->sig[SIGSZ-1] |= SIG_MSB;
        }
        }
    }
    }
}
}
 
 
const struct real_format vax_f_format =
const struct real_format vax_f_format =
  {
  {
    encode_vax_f,
    encode_vax_f,
    decode_vax_f,
    decode_vax_f,
    2,
    2,
    1,
    1,
    24,
    24,
    24,
    24,
    -127,
    -127,
    127,
    127,
    15,
    15,
    15,
    15,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false
    false
  };
  };
 
 
const struct real_format vax_d_format =
const struct real_format vax_d_format =
  {
  {
    encode_vax_d,
    encode_vax_d,
    decode_vax_d,
    decode_vax_d,
    2,
    2,
    1,
    1,
    56,
    56,
    56,
    56,
    -127,
    -127,
    127,
    127,
    15,
    15,
    15,
    15,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false
    false
  };
  };
 
 
const struct real_format vax_g_format =
const struct real_format vax_g_format =
  {
  {
    encode_vax_g,
    encode_vax_g,
    decode_vax_g,
    decode_vax_g,
    2,
    2,
    1,
    1,
    53,
    53,
    53,
    53,
    -1023,
    -1023,
    1023,
    1023,
    15,
    15,
    15,
    15,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false
    false
  };
  };


/* A good reference for these can be found in chapter 9 of
/* A good reference for these can be found in chapter 9 of
   "ESA/390 Principles of Operation", IBM document number SA22-7201-01.
   "ESA/390 Principles of Operation", IBM document number SA22-7201-01.
   An on-line version can be found here:
   An on-line version can be found here:
 
 
   http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/DZ9AR001/9.1?DT=19930923083613
   http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/DZ9AR001/9.1?DT=19930923083613
*/
*/
 
 
static void encode_i370_single (const struct real_format *fmt,
static void encode_i370_single (const struct real_format *fmt,
                                long *, const REAL_VALUE_TYPE *);
                                long *, const REAL_VALUE_TYPE *);
static void decode_i370_single (const struct real_format *,
static void decode_i370_single (const struct real_format *,
                                REAL_VALUE_TYPE *, const long *);
                                REAL_VALUE_TYPE *, const long *);
static void encode_i370_double (const struct real_format *fmt,
static void encode_i370_double (const struct real_format *fmt,
                                long *, const REAL_VALUE_TYPE *);
                                long *, const REAL_VALUE_TYPE *);
static void decode_i370_double (const struct real_format *,
static void decode_i370_double (const struct real_format *,
                                REAL_VALUE_TYPE *, const long *);
                                REAL_VALUE_TYPE *, const long *);
 
 
static void
static void
encode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
encode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
                    long *buf, const REAL_VALUE_TYPE *r)
                    long *buf, const REAL_VALUE_TYPE *r)
{
{
  unsigned long sign, exp, sig, image;
  unsigned long sign, exp, sig, image;
 
 
  sign = r->sign << 31;
  sign = r->sign << 31;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      image = 0;
      image = 0;
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      image = 0x7fffffff | sign;
      image = 0x7fffffff | sign;
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0xffffff;
      sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0xffffff;
      exp = ((REAL_EXP (r) / 4) + 64) << 24;
      exp = ((REAL_EXP (r) / 4) + 64) << 24;
      image = sign | exp | sig;
      image = sign | exp | sig;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  buf[0] = image;
  buf[0] = image;
}
}
 
 
static void
static void
decode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
                    REAL_VALUE_TYPE *r, const long *buf)
                    REAL_VALUE_TYPE *r, const long *buf)
{
{
  unsigned long sign, sig, image = buf[0];
  unsigned long sign, sig, image = buf[0];
  int exp;
  int exp;
 
 
  sign = (image >> 31) & 1;
  sign = (image >> 31) & 1;
  exp = (image >> 24) & 0x7f;
  exp = (image >> 24) & 0x7f;
  sig = image & 0xffffff;
  sig = image & 0xffffff;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (exp || sig)
  if (exp || sig)
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = sign;
      r->sign = sign;
      SET_REAL_EXP (r, (exp - 64) * 4);
      SET_REAL_EXP (r, (exp - 64) * 4);
      r->sig[SIGSZ-1] = sig << (HOST_BITS_PER_LONG - 24);
      r->sig[SIGSZ-1] = sig << (HOST_BITS_PER_LONG - 24);
      normalize (r);
      normalize (r);
    }
    }
}
}
 
 
static void
static void
encode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
encode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
                    long *buf, const REAL_VALUE_TYPE *r)
                    long *buf, const REAL_VALUE_TYPE *r)
{
{
  unsigned long sign, exp, image_hi, image_lo;
  unsigned long sign, exp, image_hi, image_lo;
 
 
  sign = r->sign << 31;
  sign = r->sign << 31;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      image_hi = image_lo = 0;
      image_hi = image_lo = 0;
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      image_hi = 0x7fffffff | sign;
      image_hi = 0x7fffffff | sign;
      image_lo = 0xffffffff;
      image_lo = 0xffffffff;
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      if (HOST_BITS_PER_LONG == 64)
      if (HOST_BITS_PER_LONG == 64)
        {
        {
          image_hi = r->sig[SIGSZ-1];
          image_hi = r->sig[SIGSZ-1];
          image_lo = (image_hi >> (64 - 56)) & 0xffffffff;
          image_lo = (image_hi >> (64 - 56)) & 0xffffffff;
          image_hi = (image_hi >> (64 - 56 + 1) >> 31) & 0xffffff;
          image_hi = (image_hi >> (64 - 56 + 1) >> 31) & 0xffffff;
        }
        }
      else
      else
        {
        {
          image_hi = r->sig[SIGSZ-1];
          image_hi = r->sig[SIGSZ-1];
          image_lo = r->sig[SIGSZ-2];
          image_lo = r->sig[SIGSZ-2];
          image_lo = (image_lo >> 8) | (image_hi << 24);
          image_lo = (image_lo >> 8) | (image_hi << 24);
          image_hi >>= 8;
          image_hi >>= 8;
        }
        }
 
 
      exp = ((REAL_EXP (r) / 4) + 64) << 24;
      exp = ((REAL_EXP (r) / 4) + 64) << 24;
      image_hi |= sign | exp;
      image_hi |= sign | exp;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    buf[0] = image_hi, buf[1] = image_lo;
    buf[0] = image_hi, buf[1] = image_lo;
  else
  else
    buf[0] = image_lo, buf[1] = image_hi;
    buf[0] = image_lo, buf[1] = image_hi;
}
}
 
 
static void
static void
decode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
                    REAL_VALUE_TYPE *r, const long *buf)
                    REAL_VALUE_TYPE *r, const long *buf)
{
{
  unsigned long sign, image_hi, image_lo;
  unsigned long sign, image_hi, image_lo;
  int exp;
  int exp;
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    image_hi = buf[0], image_lo = buf[1];
    image_hi = buf[0], image_lo = buf[1];
  else
  else
    image_lo = buf[0], image_hi = buf[1];
    image_lo = buf[0], image_hi = buf[1];
 
 
  sign = (image_hi >> 31) & 1;
  sign = (image_hi >> 31) & 1;
  exp = (image_hi >> 24) & 0x7f;
  exp = (image_hi >> 24) & 0x7f;
  image_hi &= 0xffffff;
  image_hi &= 0xffffff;
  image_lo &= 0xffffffff;
  image_lo &= 0xffffffff;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (exp || image_hi || image_lo)
  if (exp || image_hi || image_lo)
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
      r->sign = sign;
      r->sign = sign;
      SET_REAL_EXP (r, (exp - 64) * 4 + (SIGNIFICAND_BITS - 56));
      SET_REAL_EXP (r, (exp - 64) * 4 + (SIGNIFICAND_BITS - 56));
 
 
      if (HOST_BITS_PER_LONG == 32)
      if (HOST_BITS_PER_LONG == 32)
        {
        {
          r->sig[0] = image_lo;
          r->sig[0] = image_lo;
          r->sig[1] = image_hi;
          r->sig[1] = image_hi;
        }
        }
      else
      else
        r->sig[0] = image_lo | (image_hi << 31 << 1);
        r->sig[0] = image_lo | (image_hi << 31 << 1);
 
 
      normalize (r);
      normalize (r);
    }
    }
}
}
 
 
const struct real_format i370_single_format =
const struct real_format i370_single_format =
  {
  {
    encode_i370_single,
    encode_i370_single,
    decode_i370_single,
    decode_i370_single,
    16,
    16,
    4,
    4,
    6,
    6,
    6,
    6,
    -64,
    -64,
    63,
    63,
    31,
    31,
    31,
    31,
    false,
    false,
    false,
    false,
    false, /* ??? The encoding does allow for "unnormals".  */
    false, /* ??? The encoding does allow for "unnormals".  */
    false, /* ??? The encoding does allow for "unnormals".  */
    false, /* ??? The encoding does allow for "unnormals".  */
    false
    false
  };
  };
 
 
const struct real_format i370_double_format =
const struct real_format i370_double_format =
  {
  {
    encode_i370_double,
    encode_i370_double,
    decode_i370_double,
    decode_i370_double,
    16,
    16,
    4,
    4,
    14,
    14,
    14,
    14,
    -64,
    -64,
    63,
    63,
    63,
    63,
    63,
    63,
    false,
    false,
    false,
    false,
    false, /* ??? The encoding does allow for "unnormals".  */
    false, /* ??? The encoding does allow for "unnormals".  */
    false, /* ??? The encoding does allow for "unnormals".  */
    false, /* ??? The encoding does allow for "unnormals".  */
    false
    false
  };
  };


/* Encode real R into a single precision DFP value in BUF.  */
/* Encode real R into a single precision DFP value in BUF.  */
static void
static void
encode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
encode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
                       long *buf ATTRIBUTE_UNUSED,
                       long *buf ATTRIBUTE_UNUSED,
                       const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
                       const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
{
{
  encode_decimal32 (fmt, buf, r);
  encode_decimal32 (fmt, buf, r);
}
}
 
 
/* Decode a single precision DFP value in BUF into a real R.  */
/* Decode a single precision DFP value in BUF into a real R.  */
static void
static void
decode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
                       REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
                       REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
                       const long *buf ATTRIBUTE_UNUSED)
                       const long *buf ATTRIBUTE_UNUSED)
{
{
  decode_decimal32 (fmt, r, buf);
  decode_decimal32 (fmt, r, buf);
}
}
 
 
/* Encode real R into a double precision DFP value in BUF.  */
/* Encode real R into a double precision DFP value in BUF.  */
static void
static void
encode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
encode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
                       long *buf ATTRIBUTE_UNUSED,
                       long *buf ATTRIBUTE_UNUSED,
                       const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
                       const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
{
{
  encode_decimal64 (fmt, buf, r);
  encode_decimal64 (fmt, buf, r);
}
}
 
 
/* Decode a double precision DFP value in BUF into a real R.  */
/* Decode a double precision DFP value in BUF into a real R.  */
static void
static void
decode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
                       REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
                       REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
                       const long *buf ATTRIBUTE_UNUSED)
                       const long *buf ATTRIBUTE_UNUSED)
{
{
  decode_decimal64 (fmt, r, buf);
  decode_decimal64 (fmt, r, buf);
}
}
 
 
/* Encode real R into a quad precision DFP value in BUF.  */
/* Encode real R into a quad precision DFP value in BUF.  */
static void
static void
encode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
encode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
                     long *buf ATTRIBUTE_UNUSED,
                     long *buf ATTRIBUTE_UNUSED,
                     const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
                     const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
{
{
  encode_decimal128 (fmt, buf, r);
  encode_decimal128 (fmt, buf, r);
}
}
 
 
/* Decode a quad precision DFP value in BUF into a real R.  */
/* Decode a quad precision DFP value in BUF into a real R.  */
static void
static void
decode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
                     REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
                     REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
                     const long *buf ATTRIBUTE_UNUSED)
                     const long *buf ATTRIBUTE_UNUSED)
{
{
  decode_decimal128 (fmt, r, buf);
  decode_decimal128 (fmt, r, buf);
}
}
 
 
/* Single precision decimal floating point (IEEE 754R). */
/* Single precision decimal floating point (IEEE 754R). */
const struct real_format decimal_single_format =
const struct real_format decimal_single_format =
  {
  {
    encode_decimal_single,
    encode_decimal_single,
    decode_decimal_single,
    decode_decimal_single,
    10,
    10,
    1,  /* log10 */
    1,  /* log10 */
    7,
    7,
    7,
    7,
    -95,
    -95,
    96,
    96,
    31,
    31,
    31,
    31,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };
 
 
/* Double precision decimal floating point (IEEE 754R). */
/* Double precision decimal floating point (IEEE 754R). */
const struct real_format decimal_double_format =
const struct real_format decimal_double_format =
  {
  {
    encode_decimal_double,
    encode_decimal_double,
    decode_decimal_double,
    decode_decimal_double,
    10,
    10,
    1,  /* log10 */
    1,  /* log10 */
    16,
    16,
    16,
    16,
    -383,
    -383,
    384,
    384,
    63,
    63,
    63,
    63,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };
 
 
/* Quad precision decimal floating point (IEEE 754R). */
/* Quad precision decimal floating point (IEEE 754R). */
const struct real_format decimal_quad_format =
const struct real_format decimal_quad_format =
  {
  {
    encode_decimal_quad,
    encode_decimal_quad,
    decode_decimal_quad,
    decode_decimal_quad,
    10,
    10,
    1,  /* log10 */
    1,  /* log10 */
    34,
    34,
    34,
    34,
    -6143,
    -6143,
    6144,
    6144,
    127,
    127,
    127,
    127,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
    true
  };
  };


/* The "twos-complement" c4x format is officially defined as
/* The "twos-complement" c4x format is officially defined as
 
 
        x = s(~s).f * 2**e
        x = s(~s).f * 2**e
 
 
   This is rather misleading.  One must remember that F is signed.
   This is rather misleading.  One must remember that F is signed.
   A better description would be
   A better description would be
 
 
        x = -1**s * ((s + 1 + .f) * 2**e
        x = -1**s * ((s + 1 + .f) * 2**e
 
 
   So if we have a (4 bit) fraction of .1000 with a sign bit of 1,
   So if we have a (4 bit) fraction of .1000 with a sign bit of 1,
   that's -1 * (1+1+(-.5)) == -1.5.  I think.
   that's -1 * (1+1+(-.5)) == -1.5.  I think.
 
 
   The constructions here are taken from Tables 5-1 and 5-2 of the
   The constructions here are taken from Tables 5-1 and 5-2 of the
   TMS320C4x User's Guide wherein step-by-step instructions for
   TMS320C4x User's Guide wherein step-by-step instructions for
   conversion from IEEE are presented.  That's close enough to our
   conversion from IEEE are presented.  That's close enough to our
   internal representation so as to make things easy.
   internal representation so as to make things easy.
 
 
   See http://www-s.ti.com/sc/psheets/spru063c/spru063c.pdf  */
   See http://www-s.ti.com/sc/psheets/spru063c/spru063c.pdf  */
 
 
static void encode_c4x_single (const struct real_format *fmt,
static void encode_c4x_single (const struct real_format *fmt,
                               long *, const REAL_VALUE_TYPE *);
                               long *, const REAL_VALUE_TYPE *);
static void decode_c4x_single (const struct real_format *,
static void decode_c4x_single (const struct real_format *,
                               REAL_VALUE_TYPE *, const long *);
                               REAL_VALUE_TYPE *, const long *);
static void encode_c4x_extended (const struct real_format *fmt,
static void encode_c4x_extended (const struct real_format *fmt,
                                 long *, const REAL_VALUE_TYPE *);
                                 long *, const REAL_VALUE_TYPE *);
static void decode_c4x_extended (const struct real_format *,
static void decode_c4x_extended (const struct real_format *,
                                 REAL_VALUE_TYPE *, const long *);
                                 REAL_VALUE_TYPE *, const long *);
 
 
static void
static void
encode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
encode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
                   long *buf, const REAL_VALUE_TYPE *r)
                   long *buf, const REAL_VALUE_TYPE *r)
{
{
  unsigned long image, exp, sig;
  unsigned long image, exp, sig;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      exp = -128;
      exp = -128;
      sig = 0;
      sig = 0;
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      exp = 127;
      exp = 127;
      sig = 0x800000 - r->sign;
      sig = 0x800000 - r->sign;
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      exp = REAL_EXP (r) - 1;
      exp = REAL_EXP (r) - 1;
      sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
      sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
      if (r->sign)
      if (r->sign)
        {
        {
          if (sig)
          if (sig)
            sig = -sig;
            sig = -sig;
          else
          else
            exp--;
            exp--;
          sig |= 0x800000;
          sig |= 0x800000;
        }
        }
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  image = ((exp & 0xff) << 24) | (sig & 0xffffff);
  image = ((exp & 0xff) << 24) | (sig & 0xffffff);
  buf[0] = image;
  buf[0] = image;
}
}
 
 
static void
static void
decode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
                   REAL_VALUE_TYPE *r, const long *buf)
                   REAL_VALUE_TYPE *r, const long *buf)
{
{
  unsigned long image = buf[0];
  unsigned long image = buf[0];
  unsigned long sig;
  unsigned long sig;
  int exp, sf;
  int exp, sf;
 
 
  exp = (((image >> 24) & 0xff) ^ 0x80) - 0x80;
  exp = (((image >> 24) & 0xff) ^ 0x80) - 0x80;
  sf = ((image & 0xffffff) ^ 0x800000) - 0x800000;
  sf = ((image & 0xffffff) ^ 0x800000) - 0x800000;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (exp != -128)
  if (exp != -128)
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
 
 
      sig = sf & 0x7fffff;
      sig = sf & 0x7fffff;
      if (sf < 0)
      if (sf < 0)
        {
        {
          r->sign = 1;
          r->sign = 1;
          if (sig)
          if (sig)
            sig = -sig;
            sig = -sig;
          else
          else
            exp++;
            exp++;
        }
        }
      sig = (sig << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
      sig = (sig << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
 
 
      SET_REAL_EXP (r, exp + 1);
      SET_REAL_EXP (r, exp + 1);
      r->sig[SIGSZ-1] = sig;
      r->sig[SIGSZ-1] = sig;
    }
    }
}
}
 
 
static void
static void
encode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED,
encode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED,
                     long *buf, const REAL_VALUE_TYPE *r)
                     long *buf, const REAL_VALUE_TYPE *r)
{
{
  unsigned long exp, sig;
  unsigned long exp, sig;
 
 
  switch (r->cl)
  switch (r->cl)
    {
    {
    case rvc_zero:
    case rvc_zero:
      exp = -128;
      exp = -128;
      sig = 0;
      sig = 0;
      break;
      break;
 
 
    case rvc_inf:
    case rvc_inf:
    case rvc_nan:
    case rvc_nan:
      exp = 127;
      exp = 127;
      sig = 0x80000000 - r->sign;
      sig = 0x80000000 - r->sign;
      break;
      break;
 
 
    case rvc_normal:
    case rvc_normal:
      exp = REAL_EXP (r) - 1;
      exp = REAL_EXP (r) - 1;
 
 
      sig = r->sig[SIGSZ-1];
      sig = r->sig[SIGSZ-1];
      if (HOST_BITS_PER_LONG == 64)
      if (HOST_BITS_PER_LONG == 64)
        sig = sig >> 1 >> 31;
        sig = sig >> 1 >> 31;
      sig &= 0x7fffffff;
      sig &= 0x7fffffff;
 
 
      if (r->sign)
      if (r->sign)
        {
        {
          if (sig)
          if (sig)
            sig = -sig;
            sig = -sig;
          else
          else
            exp--;
            exp--;
          sig |= 0x80000000;
          sig |= 0x80000000;
        }
        }
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  exp = (exp & 0xff) << 24;
  exp = (exp & 0xff) << 24;
  sig &= 0xffffffff;
  sig &= 0xffffffff;
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    buf[0] = exp, buf[1] = sig;
    buf[0] = exp, buf[1] = sig;
  else
  else
    buf[0] = sig, buf[0] = exp;
    buf[0] = sig, buf[0] = exp;
}
}
 
 
static void
static void
decode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED,
                     REAL_VALUE_TYPE *r, const long *buf)
                     REAL_VALUE_TYPE *r, const long *buf)
{
{
  unsigned long sig;
  unsigned long sig;
  int exp, sf;
  int exp, sf;
 
 
  if (FLOAT_WORDS_BIG_ENDIAN)
  if (FLOAT_WORDS_BIG_ENDIAN)
    exp = buf[0], sf = buf[1];
    exp = buf[0], sf = buf[1];
  else
  else
    sf = buf[0], exp = buf[1];
    sf = buf[0], exp = buf[1];
 
 
  exp = (((exp >> 24) & 0xff) & 0x80) - 0x80;
  exp = (((exp >> 24) & 0xff) & 0x80) - 0x80;
  sf = ((sf & 0xffffffff) ^ 0x80000000) - 0x80000000;
  sf = ((sf & 0xffffffff) ^ 0x80000000) - 0x80000000;
 
 
  memset (r, 0, sizeof (*r));
  memset (r, 0, sizeof (*r));
 
 
  if (exp != -128)
  if (exp != -128)
    {
    {
      r->cl = rvc_normal;
      r->cl = rvc_normal;
 
 
      sig = sf & 0x7fffffff;
      sig = sf & 0x7fffffff;
      if (sf < 0)
      if (sf < 0)
        {
        {
          r->sign = 1;
          r->sign = 1;
          if (sig)
          if (sig)
            sig = -sig;
            sig = -sig;
          else
          else
            exp++;
            exp++;
        }
        }
      if (HOST_BITS_PER_LONG == 64)
      if (HOST_BITS_PER_LONG == 64)
        sig = sig << 1 << 31;
        sig = sig << 1 << 31;
      sig |= SIG_MSB;
      sig |= SIG_MSB;
 
 
      SET_REAL_EXP (r, exp + 1);
      SET_REAL_EXP (r, exp + 1);
      r->sig[SIGSZ-1] = sig;
      r->sig[SIGSZ-1] = sig;
    }
    }
}
}
 
 
const struct real_format c4x_single_format =
const struct real_format c4x_single_format =
  {
  {
    encode_c4x_single,
    encode_c4x_single,
    decode_c4x_single,
    decode_c4x_single,
    2,
    2,
    1,
    1,
    24,
    24,
    24,
    24,
    -126,
    -126,
    128,
    128,
    23,
    23,
    -1,
    -1,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false
    false
  };
  };
 
 
const struct real_format c4x_extended_format =
const struct real_format c4x_extended_format =
  {
  {
    encode_c4x_extended,
    encode_c4x_extended,
    decode_c4x_extended,
    decode_c4x_extended,
    2,
    2,
    1,
    1,
    32,
    32,
    32,
    32,
    -126,
    -126,
    128,
    128,
    31,
    31,
    -1,
    -1,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false
    false
  };
  };
 
 


/* A synthetic "format" for internal arithmetic.  It's the size of the
/* A synthetic "format" for internal arithmetic.  It's the size of the
   internal significand minus the two bits needed for proper rounding.
   internal significand minus the two bits needed for proper rounding.
   The encode and decode routines exist only to satisfy our paranoia
   The encode and decode routines exist only to satisfy our paranoia
   harness.  */
   harness.  */
 
 
static void encode_internal (const struct real_format *fmt,
static void encode_internal (const struct real_format *fmt,
                             long *, const REAL_VALUE_TYPE *);
                             long *, const REAL_VALUE_TYPE *);
static void decode_internal (const struct real_format *,
static void decode_internal (const struct real_format *,
                             REAL_VALUE_TYPE *, const long *);
                             REAL_VALUE_TYPE *, const long *);
 
 
static void
static void
encode_internal (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
encode_internal (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
                 const REAL_VALUE_TYPE *r)
                 const REAL_VALUE_TYPE *r)
{
{
  memcpy (buf, r, sizeof (*r));
  memcpy (buf, r, sizeof (*r));
}
}
 
 
static void
static void
decode_internal (const struct real_format *fmt ATTRIBUTE_UNUSED,
decode_internal (const struct real_format *fmt ATTRIBUTE_UNUSED,
                 REAL_VALUE_TYPE *r, const long *buf)
                 REAL_VALUE_TYPE *r, const long *buf)
{
{
  memcpy (r, buf, sizeof (*r));
  memcpy (r, buf, sizeof (*r));
}
}
 
 
const struct real_format real_internal_format =
const struct real_format real_internal_format =
  {
  {
    encode_internal,
    encode_internal,
    decode_internal,
    decode_internal,
    2,
    2,
    1,
    1,
    SIGNIFICAND_BITS - 2,
    SIGNIFICAND_BITS - 2,
    SIGNIFICAND_BITS - 2,
    SIGNIFICAND_BITS - 2,
    -MAX_EXP,
    -MAX_EXP,
    MAX_EXP,
    MAX_EXP,
    -1,
    -1,
    -1,
    -1,
    true,
    true,
    true,
    true,
    false,
    false,
    true,
    true,
    true
    true
  };
  };


/* Calculate the square root of X in mode MODE, and store the result
/* Calculate the square root of X in mode MODE, and store the result
   in R.  Return TRUE if the operation does not raise an exception.
   in R.  Return TRUE if the operation does not raise an exception.
   For details see "High Precision Division and Square Root",
   For details see "High Precision Division and Square Root",
   Alan H. Karp and Peter Markstein, HP Lab Report 93-93-42, June
   Alan H. Karp and Peter Markstein, HP Lab Report 93-93-42, June
   1993.  http://www.hpl.hp.com/techreports/93/HPL-93-42.pdf.  */
   1993.  http://www.hpl.hp.com/techreports/93/HPL-93-42.pdf.  */
 
 
bool
bool
real_sqrt (REAL_VALUE_TYPE *r, enum machine_mode mode,
real_sqrt (REAL_VALUE_TYPE *r, enum machine_mode mode,
           const REAL_VALUE_TYPE *x)
           const REAL_VALUE_TYPE *x)
{
{
  static REAL_VALUE_TYPE halfthree;
  static REAL_VALUE_TYPE halfthree;
  static bool init = false;
  static bool init = false;
  REAL_VALUE_TYPE h, t, i;
  REAL_VALUE_TYPE h, t, i;
  int iter, exp;
  int iter, exp;
 
 
  /* sqrt(-0.0) is -0.0.  */
  /* sqrt(-0.0) is -0.0.  */
  if (real_isnegzero (x))
  if (real_isnegzero (x))
    {
    {
      *r = *x;
      *r = *x;
      return false;
      return false;
    }
    }
 
 
  /* Negative arguments return NaN.  */
  /* Negative arguments return NaN.  */
  if (real_isneg (x))
  if (real_isneg (x))
    {
    {
      get_canonical_qnan (r, 0);
      get_canonical_qnan (r, 0);
      return false;
      return false;
    }
    }
 
 
  /* Infinity and NaN return themselves.  */
  /* Infinity and NaN return themselves.  */
  if (real_isinf (x) || real_isnan (x))
  if (real_isinf (x) || real_isnan (x))
    {
    {
      *r = *x;
      *r = *x;
      return false;
      return false;
    }
    }
 
 
  if (!init)
  if (!init)
    {
    {
      do_add (&halfthree, &dconst1, &dconsthalf, 0);
      do_add (&halfthree, &dconst1, &dconsthalf, 0);
      init = true;
      init = true;
    }
    }
 
 
  /* Initial guess for reciprocal sqrt, i.  */
  /* Initial guess for reciprocal sqrt, i.  */
  exp = real_exponent (x);
  exp = real_exponent (x);
  real_ldexp (&i, &dconst1, -exp/2);
  real_ldexp (&i, &dconst1, -exp/2);
 
 
  /* Newton's iteration for reciprocal sqrt, i.  */
  /* Newton's iteration for reciprocal sqrt, i.  */
  for (iter = 0; iter < 16; iter++)
  for (iter = 0; iter < 16; iter++)
    {
    {
      /* i(n+1) = i(n) * (1.5 - 0.5*i(n)*i(n)*x).  */
      /* i(n+1) = i(n) * (1.5 - 0.5*i(n)*i(n)*x).  */
      do_multiply (&t, x, &i);
      do_multiply (&t, x, &i);
      do_multiply (&h, &t, &i);
      do_multiply (&h, &t, &i);
      do_multiply (&t, &h, &dconsthalf);
      do_multiply (&t, &h, &dconsthalf);
      do_add (&h, &halfthree, &t, 1);
      do_add (&h, &halfthree, &t, 1);
      do_multiply (&t, &i, &h);
      do_multiply (&t, &i, &h);
 
 
      /* Check for early convergence.  */
      /* Check for early convergence.  */
      if (iter >= 6 && real_identical (&i, &t))
      if (iter >= 6 && real_identical (&i, &t))
        break;
        break;
 
 
      /* ??? Unroll loop to avoid copying.  */
      /* ??? Unroll loop to avoid copying.  */
      i = t;
      i = t;
    }
    }
 
 
  /* Final iteration: r = i*x + 0.5*i*x*(1.0 - i*(i*x)).  */
  /* Final iteration: r = i*x + 0.5*i*x*(1.0 - i*(i*x)).  */
  do_multiply (&t, x, &i);
  do_multiply (&t, x, &i);
  do_multiply (&h, &t, &i);
  do_multiply (&h, &t, &i);
  do_add (&i, &dconst1, &h, 1);
  do_add (&i, &dconst1, &h, 1);
  do_multiply (&h, &t, &i);
  do_multiply (&h, &t, &i);
  do_multiply (&i, &dconsthalf, &h);
  do_multiply (&i, &dconsthalf, &h);
  do_add (&h, &t, &i, 0);
  do_add (&h, &t, &i, 0);
 
 
  /* ??? We need a Tuckerman test to get the last bit.  */
  /* ??? We need a Tuckerman test to get the last bit.  */
 
 
  real_convert (r, mode, &h);
  real_convert (r, mode, &h);
  return true;
  return true;
}
}
 
 
/* Calculate X raised to the integer exponent N in mode MODE and store
/* Calculate X raised to the integer exponent N in mode MODE and store
   the result in R.  Return true if the result may be inexact due to
   the result in R.  Return true if the result may be inexact due to
   loss of precision.  The algorithm is the classic "left-to-right binary
   loss of precision.  The algorithm is the classic "left-to-right binary
   method" described in section 4.6.3 of Donald Knuth's "Seminumerical
   method" described in section 4.6.3 of Donald Knuth's "Seminumerical
   Algorithms", "The Art of Computer Programming", Volume 2.  */
   Algorithms", "The Art of Computer Programming", Volume 2.  */
 
 
bool
bool
real_powi (REAL_VALUE_TYPE *r, enum machine_mode mode,
real_powi (REAL_VALUE_TYPE *r, enum machine_mode mode,
           const REAL_VALUE_TYPE *x, HOST_WIDE_INT n)
           const REAL_VALUE_TYPE *x, HOST_WIDE_INT n)
{
{
  unsigned HOST_WIDE_INT bit;
  unsigned HOST_WIDE_INT bit;
  REAL_VALUE_TYPE t;
  REAL_VALUE_TYPE t;
  bool inexact = false;
  bool inexact = false;
  bool init = false;
  bool init = false;
  bool neg;
  bool neg;
  int i;
  int i;
 
 
  if (n == 0)
  if (n == 0)
    {
    {
      *r = dconst1;
      *r = dconst1;
      return false;
      return false;
    }
    }
  else if (n < 0)
  else if (n < 0)
    {
    {
      /* Don't worry about overflow, from now on n is unsigned.  */
      /* Don't worry about overflow, from now on n is unsigned.  */
      neg = true;
      neg = true;
      n = -n;
      n = -n;
    }
    }
  else
  else
    neg = false;
    neg = false;
 
 
  t = *x;
  t = *x;
  bit = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
  bit = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
  for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
  for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
    {
    {
      if (init)
      if (init)
        {
        {
          inexact |= do_multiply (&t, &t, &t);
          inexact |= do_multiply (&t, &t, &t);
          if (n & bit)
          if (n & bit)
            inexact |= do_multiply (&t, &t, x);
            inexact |= do_multiply (&t, &t, x);
        }
        }
      else if (n & bit)
      else if (n & bit)
        init = true;
        init = true;
      bit >>= 1;
      bit >>= 1;
    }
    }
 
 
  if (neg)
  if (neg)
    inexact |= do_divide (&t, &dconst1, &t);
    inexact |= do_divide (&t, &dconst1, &t);
 
 
  real_convert (r, mode, &t);
  real_convert (r, mode, &t);
  return inexact;
  return inexact;
}
}
 
 
/* Round X to the nearest integer not larger in absolute value, i.e.
/* Round X to the nearest integer not larger in absolute value, i.e.
   towards zero, placing the result in R in mode MODE.  */
   towards zero, placing the result in R in mode MODE.  */
 
 
void
void
real_trunc (REAL_VALUE_TYPE *r, enum machine_mode mode,
real_trunc (REAL_VALUE_TYPE *r, enum machine_mode mode,
            const REAL_VALUE_TYPE *x)
            const REAL_VALUE_TYPE *x)
{
{
  do_fix_trunc (r, x);
  do_fix_trunc (r, x);
  if (mode != VOIDmode)
  if (mode != VOIDmode)
    real_convert (r, mode, r);
    real_convert (r, mode, r);
}
}
 
 
/* Round X to the largest integer not greater in value, i.e. round
/* Round X to the largest integer not greater in value, i.e. round
   down, placing the result in R in mode MODE.  */
   down, placing the result in R in mode MODE.  */
 
 
void
void
real_floor (REAL_VALUE_TYPE *r, enum machine_mode mode,
real_floor (REAL_VALUE_TYPE *r, enum machine_mode mode,
            const REAL_VALUE_TYPE *x)
            const REAL_VALUE_TYPE *x)
{
{
  REAL_VALUE_TYPE t;
  REAL_VALUE_TYPE t;
 
 
  do_fix_trunc (&t, x);
  do_fix_trunc (&t, x);
  if (! real_identical (&t, x) && x->sign)
  if (! real_identical (&t, x) && x->sign)
    do_add (&t, &t, &dconstm1, 0);
    do_add (&t, &t, &dconstm1, 0);
  if (mode != VOIDmode)
  if (mode != VOIDmode)
    real_convert (r, mode, &t);
    real_convert (r, mode, &t);
  else
  else
    *r = t;
    *r = t;
}
}
 
 
/* Round X to the smallest integer not less then argument, i.e. round
/* Round X to the smallest integer not less then argument, i.e. round
   up, placing the result in R in mode MODE.  */
   up, placing the result in R in mode MODE.  */
 
 
void
void
real_ceil (REAL_VALUE_TYPE *r, enum machine_mode mode,
real_ceil (REAL_VALUE_TYPE *r, enum machine_mode mode,
           const REAL_VALUE_TYPE *x)
           const REAL_VALUE_TYPE *x)
{
{
  REAL_VALUE_TYPE t;
  REAL_VALUE_TYPE t;
 
 
  do_fix_trunc (&t, x);
  do_fix_trunc (&t, x);
  if (! real_identical (&t, x) && ! x->sign)
  if (! real_identical (&t, x) && ! x->sign)
    do_add (&t, &t, &dconst1, 0);
    do_add (&t, &t, &dconst1, 0);
  if (mode != VOIDmode)
  if (mode != VOIDmode)
    real_convert (r, mode, &t);
    real_convert (r, mode, &t);
  else
  else
    *r = t;
    *r = t;
}
}
 
 
/* Round X to the nearest integer, but round halfway cases away from
/* Round X to the nearest integer, but round halfway cases away from
   zero.  */
   zero.  */
 
 
void
void
real_round (REAL_VALUE_TYPE *r, enum machine_mode mode,
real_round (REAL_VALUE_TYPE *r, enum machine_mode mode,
            const REAL_VALUE_TYPE *x)
            const REAL_VALUE_TYPE *x)
{
{
  do_add (r, x, &dconsthalf, x->sign);
  do_add (r, x, &dconsthalf, x->sign);
  do_fix_trunc (r, r);
  do_fix_trunc (r, r);
  if (mode != VOIDmode)
  if (mode != VOIDmode)
    real_convert (r, mode, r);
    real_convert (r, mode, r);
}
}
 
 
/* Set the sign of R to the sign of X.  */
/* Set the sign of R to the sign of X.  */
 
 
void
void
real_copysign (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *x)
real_copysign (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *x)
{
{
  r->sign = x->sign;
  r->sign = x->sign;
}
}
 
 
 
 

powered by: WebSVN 2.1.0

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