This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / sim / common / sim-fpu.c
index 184f802492e0d9439e725b7ae69e20eacfa0d6ed..abf746a9b685d47af860429cc7b4e02ca744ac06 100644 (file)
@@ -2,7 +2,7 @@
    of the floating point routines in libgcc1.c for targets without
    hardware floating point.  */
 
-/* Copyright (C) 1994,1997 Free Software Foundation, Inc.
+/* 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
@@ -110,11 +110,16 @@ typedef union {
    */
 
 #define NR_EXPBITS  (is_double ?   11 :   8)
-#define NR_FRACBITS (is_double ?   52 :  23)
+#define NR_FRACBITS (is_double ?   52 : 23)
 #define SIGNBIT     (is_double ? MSBIT64 (0) : MSBIT64 (32))
 
-#define EXPMAX      ((unsigned) (is_double ? 2047 : 255))
-#define EXPBIAS     (is_double ? 1023 : 127)
+#define EXPMAX32    (255)
+#define EXMPAX64    (2047)
+#define EXPMAX      ((unsigned) (is_double ? EXMPAX64 : EXPMAX32))
+
+#define EXPBIAS32   (127)
+#define EXPBIAS64   (1023)
+#define EXPBIAS     (is_double ? EXPBIAS64 : EXPBIAS32)
 
 #define QUIET_NAN   LSBIT64 (NR_FRACBITS - 1)
 
@@ -128,10 +133,16 @@ typedef union {
    64 bit - <IMPLICIT_1:1><FRACBITS:52><GUARDS:8><PAD:00>
    32 bit - <IMPLICIT_1:1><FRACBITS:23><GUARDS:7><PAD:30> */
 
-#define NR_PAD    (is_double ? 0 : 30)
-#define PADMASK   (is_double ? 0 : LSMASK64 (29, 0))
-#define NR_GUARDS  ((is_double ? 8 :  7 ) + NR_PAD)
+#define NR_PAD32    (30)
+#define NR_PAD64    (0)
+#define NR_PAD      (is_double ? NR_PAD64 : NR_PAD32)
+#define PADMASK     (is_double ? 0 : LSMASK64 (NR_PAD32 - 1, 0))
+
+#define NR_GUARDS32 (7 + NR_PAD32)
+#define NR_GUARDS64 (8 + NR_PAD64)
+#define NR_GUARDS  (is_double ? NR_GUARDS64 : NR_GUARDS32)
 #define GUARDMASK  LSMASK64 (NR_GUARDS - 1, 0)
+
 #define GUARDMSB   LSBIT64  (NR_GUARDS - 1)
 #define GUARDLSB   LSBIT64  (NR_PAD)
 #define GUARDROUND LSMASK64 (NR_GUARDS - 2, 0)
@@ -145,6 +156,9 @@ typedef union {
 #define FRAC32MASK LSMASK64 (63, NR_FRAC_GUARD - 32 + 1)
 
 #define NORMAL_EXPMIN (-(EXPBIAS)+1)
+
+#define NORMAL_EXPMAX32 (EXPBIAS32)
+#define NORMAL_EXPMAX64 (EXPBIAS64)
 #define NORMAL_EXPMAX (EXPBIAS)
 
 
@@ -698,6 +712,40 @@ sim_fpu_to64 (unsigned64 *u,
 }
 
 
+INLINE_SIM_FPU (void)
+sim_fpu_fractionto (sim_fpu *f,
+                   int sign,
+                   int normal_exp,
+                   unsigned64 fraction,
+                   int precision)
+{
+  int shift = (NR_FRAC_GUARD - precision);
+  f->class = sim_fpu_class_number;
+  f->sign = sign;
+  f->normal_exp = normal_exp;
+  /* shift the fraction to where sim-fpu expects it */
+  if (shift >= 0)
+    f->fraction = (fraction << shift);
+  else
+    f->fraction = (fraction >> -shift);
+  f->fraction |= IMPLICIT_1;
+}
+
+
+INLINE_SIM_FPU (unsigned64)
+sim_fpu_tofraction (const sim_fpu *d,
+                   int precision)
+{
+  /* we have NR_FRAC_GUARD bits, we want only PRECISION bits */
+  int shift = (NR_FRAC_GUARD - precision);
+  unsigned64 fraction = (d->fraction & ~IMPLICIT_1);
+  if (shift >= 0)
+    return fraction >> shift;
+  else
+    return fraction << -shift;
+}
+
+
 /* Rounding */
 
 STATIC_INLINE_SIM_FPU (int)
@@ -1511,6 +1559,172 @@ sim_fpu_div (sim_fpu *f,
 }
 
 
+INLINE_SIM_FPU (int)
+sim_fpu_max (sim_fpu *f,
+            const sim_fpu *l,
+            const sim_fpu *r)
+{
+  if (sim_fpu_is_snan (l))
+    {
+      *f = *l;
+      f->class = sim_fpu_class_qnan;
+      return sim_fpu_status_invalid_snan;
+    }
+  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 (l))
+    {
+      *f = *l;
+      return 0;
+    }
+  if (sim_fpu_is_qnan (r))
+    {
+      *f = *r;
+      return 0;
+    }
+  if (sim_fpu_is_infinity (l))
+    {
+      if (sim_fpu_is_infinity (r)
+         && l->sign == r->sign)
+       {
+         *f = sim_fpu_qnan;
+         return sim_fpu_status_invalid_isi;
+       }
+      if (l->sign)
+       *f = *r; /* -inf < anything */
+      else
+       *f = *l; /* +inf > anthing */
+      return 0;
+    }
+  if (sim_fpu_is_infinity (r))
+    {
+      if (r->sign)
+       *f = *l; /* anything > -inf */
+      else
+       *f = *r; /* anthing < +inf */
+      return 0;
+    }
+  if (l->sign > r->sign)
+    {
+      *f = *r; /* -ve < +ve */
+      return 0;
+    }
+  if (l->sign < r->sign)
+    {
+      *f = *l; /* +ve > -ve */
+      return 0;
+    }
+  ASSERT (l->sign == r->sign);
+  if (l->normal_exp > r->normal_exp
+      || (l->normal_exp == r->normal_exp && 
+         l->fraction > r->fraction))
+    {
+      /* |l| > |r| */
+      if (l->sign)
+       *f = *r; /* -ve < -ve */
+      else
+       *f = *l; /* +ve > +ve */
+      return 0;
+    }
+  else
+    {
+      /* |l| <= |r| */
+      if (l->sign)
+       *f = *l; /* -ve > -ve */
+      else
+       *f = *r; /* +ve < +ve */
+      return 0;
+    }
+}
+
+
+INLINE_SIM_FPU (int)
+sim_fpu_min (sim_fpu *f,
+            const sim_fpu *l,
+            const sim_fpu *r)
+{
+  if (sim_fpu_is_snan (l))
+    {
+      *f = *l;
+      f->class = sim_fpu_class_qnan;
+      return sim_fpu_status_invalid_snan;
+    }
+  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 (l))
+    {
+      *f = *l;
+      return 0;
+    }
+  if (sim_fpu_is_qnan (r))
+    {
+      *f = *r;
+      return 0;
+    }
+  if (sim_fpu_is_infinity (l))
+    {
+      if (sim_fpu_is_infinity (r)
+         && l->sign == r->sign)
+       {
+         *f = sim_fpu_qnan;
+         return sim_fpu_status_invalid_isi;
+       }
+      if (l->sign)
+       *f = *l; /* -inf < anything */
+      else
+       *f = *r; /* +inf > anthing */
+      return 0;
+    }
+  if (sim_fpu_is_infinity (r))
+    {
+      if (r->sign)
+       *f = *r; /* anything > -inf */
+      else
+       *f = *l; /* anything < +inf */
+      return 0;
+    }
+  if (l->sign > r->sign)
+    {
+      *f = *l; /* -ve < +ve */
+      return 0;
+    }
+  if (l->sign < r->sign)
+    {
+      *f = *r; /* +ve > -ve */
+      return 0;
+    }
+  ASSERT (l->sign == r->sign);
+  if (l->normal_exp > r->normal_exp
+      || (l->normal_exp == r->normal_exp && 
+         l->fraction > r->fraction))
+    {
+      /* |l| > |r| */
+      if (l->sign)
+       *f = *l; /* -ve < -ve */
+      else
+       *f = *r; /* +ve > +ve */
+      return 0;
+    }
+  else
+    {
+      /* |l| <= |r| */
+      if (l->sign)
+       *f = *r; /* -ve > -ve */
+      else
+       *f = *l; /* +ve < +ve */
+      return 0;
+    }
+}
+
+
 INLINE_SIM_FPU (int)
 sim_fpu_neg (sim_fpu *f,
             const sim_fpu *r)
@@ -1876,7 +2090,17 @@ INLINE_SIM_FPU (double)
 sim_fpu_2d (const sim_fpu *s)
 {
   sim_fpu_map val;
-  val.i = pack_fpu (s, 1);
+  if (sim_fpu_is_snan (s))
+    {
+      /* gag SNaN's */
+      sim_fpu n = *s;
+      n.class = sim_fpu_class_qnan;
+      val.i = pack_fpu (&n, 1);
+    }
+  else
+    {
+      val.i = pack_fpu (s, 1);
+    }
   return val.d;
 }
 
@@ -1991,6 +2215,22 @@ sim_fpu_is_denorm (const sim_fpu *d)
     }
 }
 
+
+INLINE_SIM_FPU (int)
+sim_fpu_sign (const sim_fpu *d)
+{
+  return d->sign;
+}
+
+
+INLINE_SIM_FPU (int)
+sim_fpu_exp (const sim_fpu *d)
+{
+  return d->normal_exp;
+}
+
+
+
 INLINE_SIM_FPU (int)
 sim_fpu_is (const sim_fpu *d)
 {
@@ -2001,8 +2241,10 @@ sim_fpu_is (const sim_fpu *d)
     case sim_fpu_class_snan:
       return SIM_FPU_IS_SNAN;
     case sim_fpu_class_infinity:
-      return SIM_FPU_IS_NINF;
-      return SIM_FPU_IS_PINF;
+      if (d->sign)
+       return SIM_FPU_IS_NINF;
+      else
+       return SIM_FPU_IS_PINF;
     case sim_fpu_class_number:
       if (d->sign)
        return SIM_FPU_IS_NNUMBER;
@@ -2206,8 +2448,26 @@ sim_fpu_gt (int *is,
 
 /* A number of useful constants */
 
-const sim_fpu sim_fpu_zero = { sim_fpu_class_zero, };
-const sim_fpu sim_fpu_qnan = { sim_fpu_class_qnan, };
+#if EXTERN_SIM_FPU_P
+const sim_fpu sim_fpu_zero = {
+  sim_fpu_class_zero,
+};
+const sim_fpu sim_fpu_qnan = {
+  sim_fpu_class_qnan,
+};
+const sim_fpu sim_fpu_one = {
+  sim_fpu_class_number, 0, IMPLICIT_1, 1
+};
+const sim_fpu sim_fpu_two = {
+  sim_fpu_class_number, 0, IMPLICIT_1, 2
+};
+const sim_fpu sim_fpu_max32 = {
+  sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS32), NORMAL_EXPMAX32
+};
+const sim_fpu sim_fpu_max64 = {
+  sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS64), NORMAL_EXPMAX64
+};
+#endif
 
 
 /* For debugging */
This page took 0.026991 seconds and 4 git commands to generate.