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
#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;
}
}
#define PADMASK (is_double ? 0 : LSMASK64 (NR_PAD32 - 1, 0))
#define NR_GUARDS32 (7 + NR_PAD32)
-#define NR_GUARDS64 (8 + NR_PAD32)
+#define NR_GUARDS64 (8 + NR_PAD64)
#define NR_GUARDS (is_double ? NR_GUARDS64 : NR_GUARDS32)
#define GUARDMASK LSMASK64 (NR_GUARDS - 1, 0)
/* tastes like zero */
dst->class = sim_fpu_class_zero;
dst->sign = sign;
+ dst->normal_exp = 0;
}
else
{
{
f->class = sim_fpu_class_zero;
f->sign = 0;
+ f->normal_exp = 0;
}
else
{
{
do
{
- f->fraction >>= 1;
+ f->fraction = (f->fraction >> 1) | (f->fraction & 1);
f->normal_exp += 1;
}
while (f->fraction >= IMPLICIT_2);
{
f->class = sim_fpu_class_zero;
f->sign = 0;
+ f->normal_exp = 0;
}
else
{
}
+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)
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
{
}
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)
{
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;
{
f->class = sim_fpu_class_zero;
f->sign = r->sign;
+ f->normal_exp = 0;
return 0;
}
if (sim_fpu_is_infinity (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_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, };
-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 };
+#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, 0
+};
+const sim_fpu sim_fpu_two = {
+ sim_fpu_class_number, 0, IMPLICIT_1, 1
+};
+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 */
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:
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);
}