Update Copyright year range in all files maintained by GDB.
[deliverable/binutils-gdb.git] / sim / common / sim-fpu.c
index 3214bb4dd4fbf2e394f909b2cb4bce6923a233fa..8c1b4b24925e61ff75a9edaaefa6ec5d364dd3d5 100644 (file)
@@ -2,29 +2,20 @@
    of the floating point routines in libgcc1.c for targets without
    hardware floating point.  */
 
-/* Copyright (C) 1994,1997-1998 Free Software Foundation, Inc.
-
-This file 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 Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file with other programs, and to distribute
-those programs without any restriction coming from the use of this
-file.  (The General Public License restrictions do apply in other
-respects; for example, they cover modification of the file, and
-distribution when not linked into another program.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
+/* Copyright 1994-2014 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* As a special exception, if you link this library with other files,
    some of which are compiled with GCC, to produce an executable,
@@ -51,25 +42,30 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "sim-assert.h"
 
 
-/* Debugging support. */
+/* Debugging support.
+   If digits is -1, then print all digits.  */
 
 static void
 print_bits (unsigned64 x,
            int msbit,
+           int digits,
            sim_fpu_print_func print,
            void *arg)
 {
   unsigned64 bit = LSBIT64 (msbit);
   int i = 4;
-  while (bit)
+  while (bit && digits)
     {
       if (i == 0)
        print (arg, ",");
+
       if ((x & bit))
        print (arg, "1");
       else
        print (arg, "0");
       bit >>= 1;
+
+      if (digits > 0) digits--;
       i = (i + 1) % 4;
     }
 }
@@ -81,7 +77,7 @@ print_bits (unsigned64 x,
 typedef union {
   double d;
   unsigned64 i;
-} sim_fpu_map;  
+} sim_fpu_map;
 
 
 /* A packed IEEE floating point number.
@@ -97,7 +93,7 @@ typedef union {
 
    Zero (0 == BIASEDEXP && FRAC == 0):
    (sign ? "-" : "+") 0.0
-   
+
    Infinity (BIASEDEXP == EXPMAX && FRAC == 0):
    (sign ? "-" : "+") "infinity"
 
@@ -196,7 +192,11 @@ pack_fpu (const sim_fpu *src,
       /* force fraction to correct class */
       fraction = src->fraction;
       fraction >>= NR_GUARDS;
+#ifdef SIM_QUIET_NAN_NEGATED
+      fraction |= QUIET_NAN - 1;
+#else
       fraction |= QUIET_NAN;
+#endif
       break;
     case sim_fpu_class_snan:
       sign = src->sign;
@@ -204,7 +204,11 @@ pack_fpu (const sim_fpu *src,
       /* force fraction to correct class */
       fraction = src->fraction;
       fraction >>= NR_GUARDS;
+#ifdef SIM_QUIET_NAN_NEGATED
+      fraction |= QUIET_NAN;
+#else
       fraction &= ~QUIET_NAN;
+#endif
       break;
     case sim_fpu_class_infinity:
       sign = src->sign;
@@ -249,7 +253,7 @@ pack_fpu (const sim_fpu *src,
          /* Infinity */
          sign = src->sign;
          exp = EXPMAX;
-         fraction = 0; 
+         fraction = 0;
        }
       else
        {
@@ -304,7 +308,7 @@ pack_fpu (const sim_fpu *src,
              (long) LSEXTRACTED32 (packed, 23 - 1, 0));
     }
 #endif
-  
+
   return packed;
 }
 
@@ -325,6 +329,7 @@ unpack_fpu (sim_fpu *dst, unsigned64 packed, int is_double)
          /* tastes like zero */
          dst->class = sim_fpu_class_zero;
          dst->sign = sign;
+         dst->normal_exp = 0;
        }
       else
        {
@@ -356,10 +361,17 @@ unpack_fpu (sim_fpu *dst, unsigned64 packed, int is_double)
        }
       else
        {
+         int qnan;
+
          /* Non zero fraction, means NaN */
          dst->sign = sign;
          dst->fraction = (fraction << NR_GUARDS);
-         if (fraction >= QUIET_NAN)
+#ifdef SIM_QUIET_NAN_NEGATED
+         qnan = (fraction & QUIET_NAN) == 0;
+#else
+         qnan = fraction >= QUIET_NAN;
+#endif
+         if (qnan)
            dst->class = sim_fpu_class_qnan;
          else
            dst->class = sim_fpu_class_snan;
@@ -515,6 +527,7 @@ i2fpu (sim_fpu *f, signed64 i, int is_64bit)
     {
       f->class = sim_fpu_class_zero;
       f->sign = 0;
+      f->normal_exp = 0;
     }
   else
     {
@@ -522,7 +535,7 @@ i2fpu (sim_fpu *f, signed64 i, int is_64bit)
       f->sign = (i < 0);
       f->normal_exp = NR_FRAC_GUARD;
 
-      if (f->sign) 
+      if (f->sign)
        {
          /* Special case for minint, since there is no corresponding
             +ve integer representation for it */
@@ -539,7 +552,7 @@ i2fpu (sim_fpu *f, signed64 i, int is_64bit)
 
       if (f->fraction >= IMPLICIT_2)
        {
-         do 
+         do
            {
              f->fraction = (f->fraction >> 1) | (f->fraction & 1);
              f->normal_exp += 1;
@@ -643,6 +656,7 @@ u2fpu (sim_fpu *f, unsigned64 u, int is_64bit)
     {
       f->class = sim_fpu_class_zero;
       f->sign = 0;
+      f->normal_exp = 0;
     }
   else
     {
@@ -881,7 +895,7 @@ do_round (sim_fpu *f,
       return 0;
       break;
     case sim_fpu_class_snan:
-      /* Quieten a SignalingNaN */ 
+      /* Quieten a SignalingNaN */
       f->class = sim_fpu_class_qnan;
       return sim_fpu_status_invalid_snan;
       break;
@@ -1356,14 +1370,14 @@ sim_fpu_mul (sim_fpu *f,
     res2 += ((ps_hh__ >> 32) & 0xffffffff) + pp_hh;
     high = res2;
     low = res0;
-    
+
     f->normal_exp = l->normal_exp + r->normal_exp;
     f->sign = l->sign ^ r->sign;
     f->class = sim_fpu_class_number;
 
     /* Input is bounded by [1,2)   ;   [2^60,2^61)
        Output is bounded by [1,4)  ;   [2^120,2^122) */
+
     /* Adjust the exponent according to where the decimal point ended
        up in the high 64 bit word.  In the source the decimal point
        was at NR_FRAC_GUARD. */
@@ -1375,14 +1389,6 @@ sim_fpu_mul (sim_fpu *f,
     ASSERT (high >= LSBIT64 ((NR_FRAC_GUARD * 2) - 64));
     ASSERT (LSBIT64 (((NR_FRAC_GUARD + 1) * 2) - 64) < IMPLICIT_1);
 
-#if 0
-    printf ("\n");
-    print_bits (high, 63, (sim_fpu_print_func*)fprintf, stdout);
-    printf (";");
-    print_bits (low, 63, (sim_fpu_print_func*)fprintf, stdout);
-    printf ("\n");
-#endif
-
     /* normalize */
     do
       {
@@ -1394,13 +1400,6 @@ sim_fpu_mul (sim_fpu *f,
       }
     while (high < IMPLICIT_1);
 
-#if 0
-    print_bits (high, 63, (sim_fpu_print_func*)fprintf, stdout);
-    printf (";");
-    print_bits (low, 63, (sim_fpu_print_func*)fprintf, stdout);
-    printf ("\n");
-#endif
-
     ASSERT (high >= IMPLICIT_1 && high < IMPLICIT_2);
     if (low != 0)
       {
@@ -1511,7 +1510,7 @@ sim_fpu_div (sim_fpu *f,
        f->normal_exp--;
       }
     ASSERT (numerator >= denominator);
-    
+
     /* Gain extra precision, already used one spare bit */
     numerator <<=    NR_SPARE;
     denominator <<=  NR_SPARE;
@@ -1530,16 +1529,6 @@ sim_fpu_div (sim_fpu *f,
        numerator <<= 1;
       }
 
-#if 0
-    printf ("\n");
-    print_bits (quotient, 63, (sim_fpu_print_func*)fprintf, stdout);
-    printf ("\n");
-    print_bits (numerator, 63, (sim_fpu_print_func*)fprintf, stdout);
-    printf ("\n");
-    print_bits (denominator, 63, (sim_fpu_print_func*)fprintf, stdout);
-    printf ("\n");
-#endif
-
     /* discard (but save) the extra bits */
     if ((quotient & LSMASK64 (NR_SPARE -1, 0)))
       quotient = (quotient >> NR_SPARE) | 1;
@@ -1620,7 +1609,7 @@ sim_fpu_max (sim_fpu *f,
     }
   ASSERT (l->sign == r->sign);
   if (l->normal_exp > r->normal_exp
-      || (l->normal_exp == r->normal_exp && 
+      || (l->normal_exp == r->normal_exp &&
          l->fraction > r->fraction))
     {
       /* |l| > |r| */
@@ -1703,7 +1692,7 @@ sim_fpu_min (sim_fpu *f,
     }
   ASSERT (l->sign == r->sign);
   if (l->normal_exp > r->normal_exp
-      || (l->normal_exp == r->normal_exp && 
+      || (l->normal_exp == r->normal_exp &&
          l->fraction > r->fraction))
     {
       /* |l| > |r| */
@@ -1750,19 +1739,13 @@ INLINE_SIM_FPU (int)
 sim_fpu_abs (sim_fpu *f,
             const sim_fpu *r)
 {
+  *f = *r;
+  f->sign = 0;
   if (sim_fpu_is_snan (r))
     {
-      *f = *r;
       f->class = sim_fpu_class_qnan;
       return sim_fpu_status_invalid_snan;
     }
-  if (sim_fpu_is_qnan (r))
-    {
-      *f = *r;
-      return 0;
-    }
-  *f = *r;
-  f->sign = 0;
   return 0;
 }
 
@@ -1771,33 +1754,7 @@ INLINE_SIM_FPU (int)
 sim_fpu_inv (sim_fpu *f,
             const sim_fpu *r)
 {
-  if (sim_fpu_is_snan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_qnan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return 0;
-    }
-  if (sim_fpu_is_infinity (r))
-    {
-      *f = sim_fpu_zero;
-      f->sign = r->sign;
-      return 0;
-    }
-  if (sim_fpu_is_zero (r))
-    {
-      f->class = sim_fpu_class_infinity;
-      f->sign = r->sign;
-      return sim_fpu_status_invalid_div0;
-    }
-  *f = *r;
-  f->normal_exp = - r->normal_exp;
-  return 0;
+  return sim_fpu_div (f, &sim_fpu_one, r);
 }
 
 
@@ -1819,6 +1776,7 @@ sim_fpu_sqrt (sim_fpu *f,
     {
       f->class = sim_fpu_class_zero;
       f->sign = r->sign;
+      f->normal_exp = 0;
       return 0;
     }
   if (sim_fpu_is_infinity (r))
@@ -1849,20 +1807,20 @@ sim_fpu_sqrt (sim_fpu *f,
    *
    * Developed at SunPro, a Sun Microsystems, Inc. business.
    * Permission to use, copy, modify, and distribute this
-   * software is freely granted, provided that this notice 
+   * software is freely granted, provided that this notice
    * is preserved.
    * ====================================================
    */
-  
+
   /* __ieee754_sqrt(x)
    * Return correctly rounded sqrt.
    *           ------------------------------------------
    *           |  Use the hardware sqrt if you have one |
    *           ------------------------------------------
-   * Method: 
-   *   Bit by bit method using integer arithmetic. (Slow, but portable) 
+   * Method:
+   *   Bit by bit method using integer arithmetic. (Slow, but portable)
    *   1. Normalization
-   *   Scale x to y in [1,4) with even powers of 2: 
+   *   Scale x to y in [1,4) with even powers of 2:
    *   find an integer k such that  1 <= (y=x*2^(2k)) < 4, then
    *           sqrt(x) = 2^k * sqrt(y)
    -
@@ -1882,9 +1840,9 @@ sim_fpu_sqrt (sim_fpu *f,
    *                                     i+1         2
    *       s  = 2*q , and      y  =  2   * ( y - q  ).         (1)
    *        i      i            i                 i
-   *                                                        
-   *   To compute q    from q , one checks whether 
-   *               i+1       i                       
+   *
+   *   To compute q    from q , one checks whether
+   *               i+1       i
    *
    *                         -(i+1) 2
    *                   (q + 2      ) <= y.                     (2)
@@ -1894,12 +1852,12 @@ sim_fpu_sqrt (sim_fpu *f,
    *                          i+1   i             i+1   i
    *
    *   With some algebric manipulation, it is not difficult to see
-   *   that (2) is equivalent to 
+   *   that (2) is equivalent to
    *                             -(i+1)
    *                   s  +  2       <= y                      (3)
    *                    i                i
    *
-   *   The advantage of (3) is that s  and y  can be computed by 
+   *   The advantage of (3) is that s  and y  can be computed by
    *                                 i      i
    *   the following recurrence formula:
    *       if (3) is false
@@ -1915,15 +1873,15 @@ sim_fpu_sqrt (sim_fpu *f,
    *                       -i                      -(i+1)
    *       s     =  s  + 2  ,  y    = y  -  s  - 2             (5)
    *         i+1      i          i+1    i     i
-   *                           
+   *
    -
    -                                                   -(i+1)
-   -                      NOTE: y    = 2 (y  -  s  -  2      )                 
+   -                      NOTE: y    = 2 (y  -  s  -  2      )
    -                             i+1       i     i
    -
-   *   One may easily use induction to prove (4) and (5). 
+   *   One may easily use induction to prove (4) and (5).
    *   Note. Since the left hand side of (3) contain only i+2 bits,
-   *         it does not necessary to do a full (53-bit) comparison 
+   *         it does not necessary to do a full (53-bit) comparison
    *         in (3).
    *   3. Final rounding
    *   After generating the 53 bits result, we compute one more bit.
@@ -1933,7 +1891,7 @@ sim_fpu_sqrt (sim_fpu *f,
    *   The rounding mode can be detected by checking whether
    *   huge + tiny is equal to huge, and whether huge - tiny is
    *   equal to huge for some floating point number "huge" and "tiny".
-   *           
+   *
    * Special cases:
    *   sqrt(+-0) = +-0         ... exact
    *   sqrt(inf) = inf
@@ -1968,7 +1926,7 @@ sim_fpu_sqrt (sim_fpu *f,
     b = IMPLICIT_1;
     q = 0;
     s = 0;
-    
+
     while (b)
       {
        unsigned64 t = s + b;
@@ -2230,6 +2188,22 @@ sim_fpu_exp (const sim_fpu *d)
 }
 
 
+INLINE_SIM_FPU (unsigned64)
+sim_fpu_fraction (const sim_fpu *d)
+{
+  return d->fraction;
+}
+
+
+INLINE_SIM_FPU (unsigned64)
+sim_fpu_guard (const sim_fpu *d, int is_double)
+{
+  unsigned64 rv;
+  unsigned64 guardmask = LSMASK64 (NR_GUARDS - 1, 0);
+  rv = (d->fraction & guardmask) >> NR_PAD;
+  return rv;
+}
+
 
 INLINE_SIM_FPU (int)
 sim_fpu_is (const sim_fpu *d)
@@ -2450,10 +2424,10 @@ sim_fpu_gt (int *is,
 
 #if EXTERN_SIM_FPU_P
 const sim_fpu sim_fpu_zero = {
-  sim_fpu_class_zero,
+  sim_fpu_class_zero, 0, 0, 0
 };
 const sim_fpu sim_fpu_qnan = {
-  sim_fpu_class_qnan,
+  sim_fpu_class_qnan, 0, 0, 0
 };
 const sim_fpu sim_fpu_one = {
   sim_fpu_class_number, 0, IMPLICIT_1, 0
@@ -2476,18 +2450,27 @@ INLINE_SIM_FPU (void)
 sim_fpu_print_fpu (const sim_fpu *f,
                   sim_fpu_print_func *print,
                   void *arg)
+{
+  sim_fpu_printn_fpu (f, print, -1, arg);
+}
+
+INLINE_SIM_FPU (void)
+sim_fpu_printn_fpu (const sim_fpu *f,
+                  sim_fpu_print_func *print,
+                  int digits,
+                  void *arg)
 {
   print (arg, "%s", f->sign ? "-" : "+");
   switch (f->class)
     {
     case sim_fpu_class_qnan:
       print (arg, "0.");
-      print_bits (f->fraction, NR_FRAC_GUARD - 1, print, arg);
+      print_bits (f->fraction, NR_FRAC_GUARD - 1, digits, print, arg);
       print (arg, "*QuietNaN");
       break;
     case sim_fpu_class_snan:
       print (arg, "0.");
-      print_bits (f->fraction, NR_FRAC_GUARD - 1, print, arg);
+      print_bits (f->fraction, NR_FRAC_GUARD - 1, digits, print, arg);
       print (arg, "*SignalNaN");
       break;
     case sim_fpu_class_zero:
@@ -2499,8 +2482,8 @@ sim_fpu_print_fpu (const sim_fpu *f,
     case sim_fpu_class_number:
     case sim_fpu_class_denorm:
       print (arg, "1.");
-      print_bits (f->fraction, NR_FRAC_GUARD - 1, print, arg);
-      print (arg, "*2^%+-5d", f->normal_exp);
+      print_bits (f->fraction, NR_FRAC_GUARD - 1, digits, print, arg);
+      print (arg, "*2^%+d", f->normal_exp);
       ASSERT (f->fraction >= IMPLICIT_1);
       ASSERT (f->fraction < IMPLICIT_2);
     }
@@ -2513,7 +2496,7 @@ sim_fpu_print_status (int status,
                      void *arg)
 {
   int i = 1;
-  char *prefix = "";
+  const char *prefix = "";
   while (status >= i)
     {
       switch ((sim_fpu_status) (status & i))
@@ -2548,27 +2531,21 @@ sim_fpu_print_status (int status,
        case sim_fpu_status_invalid_sqrt:
          print (arg, "%sSQRT", prefix);
          break;
-         break;
        case sim_fpu_status_inexact:
          print (arg, "%sX", prefix);
          break;
-         break;
        case sim_fpu_status_overflow:
          print (arg, "%sO", prefix);
          break;
-         break;
        case sim_fpu_status_underflow:
          print (arg, "%sU", prefix);
          break;
-         break;
        case sim_fpu_status_invalid_div0:
          print (arg, "%s/", prefix);
          break;
-         break;
        case sim_fpu_status_rounded:
          print (arg, "%sR", prefix);
          break;
-         break;
        }
       i <<= 1;
       prefix = ",";
This page took 0.029969 seconds and 4 git commands to generate.