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
*/
#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)
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)
#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)
}
+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)
}
+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)
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;
}
}
}
+
+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)
{
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;
/* 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 */