/* This is a software floating point library which can be used
for targets without hardware floating point.
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002
Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
#include "tconfig.h"
#include "fp-bit.h"
-/* The following macros can be defined to change the behaviour of this file:
+/* The following macros can be defined to change the behavior of this file:
FLOAT: Implement a `float', aka SFmode, fp library. If this is not
defined, then this file implements a `double', aka DFmode, fp library.
FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
are referenced from within libc, since libgcc goes before and after the
system library. */
+#ifdef DECLARE_LIBRARY_RENAMES
+ DECLARE_LIBRARY_RENAMES
+#endif
+
#ifdef EXTENDED_FLOAT_STUBS
-__truncxfsf2 (){ abort(); }
-__extendsfxf2 (){ abort(); }
-__addxf3 (){ abort(); }
-__divxf3 (){ abort(); }
-__eqxf2 (){ abort(); }
-__extenddfxf2 (){ abort(); }
-__gtxf2 (){ abort(); }
-__lexf2 (){ abort(); }
-__ltxf2 (){ abort(); }
-__mulxf3 (){ abort(); }
-__negxf2 (){ abort(); }
-__nexf2 (){ abort(); }
-__subxf3 (){ abort(); }
-__truncxfdf2 (){ abort(); }
-
-__trunctfsf2 (){ abort(); }
-__extendsftf2 (){ abort(); }
-__addtf3 (){ abort(); }
-__divtf3 (){ abort(); }
-__eqtf2 (){ abort(); }
-__extenddftf2 (){ abort(); }
-__gttf2 (){ abort(); }
-__letf2 (){ abort(); }
-__lttf2 (){ abort(); }
-__multf3 (){ abort(); }
-__negtf2 (){ abort(); }
-__netf2 (){ abort(); }
-__subtf3 (){ abort(); }
-__trunctfdf2 (){ abort(); }
-__gexf2 (){ abort(); }
-__fixxfsi (){ abort(); }
-__floatsixf (){ abort(); }
+extern void abort (void);
+void __extendsfxf2 (void) { abort(); }
+void __extenddfxf2 (void) { abort(); }
+void __truncxfdf2 (void) { abort(); }
+void __truncxfsf2 (void) { abort(); }
+void __fixxfsi (void) { abort(); }
+void __floatsixf (void) { abort(); }
+void __addxf3 (void) { abort(); }
+void __subxf3 (void) { abort(); }
+void __mulxf3 (void) { abort(); }
+void __divxf3 (void) { abort(); }
+void __negxf2 (void) { abort(); }
+void __eqxf2 (void) { abort(); }
+void __nexf2 (void) { abort(); }
+void __gtxf2 (void) { abort(); }
+void __gexf2 (void) { abort(); }
+void __lexf2 (void) { abort(); }
+void __ltxf2 (void) { abort(); }
+
+void __extendsftf2 (void) { abort(); }
+void __extenddftf2 (void) { abort(); }
+void __trunctfdf2 (void) { abort(); }
+void __trunctfsf2 (void) { abort(); }
+void __fixtfsi (void) { abort(); }
+void __floatsitf (void) { abort(); }
+void __addtf3 (void) { abort(); }
+void __subtf3 (void) { abort(); }
+void __multf3 (void) { abort(); }
+void __divtf3 (void) { abort(); }
+void __negtf2 (void) { abort(); }
+void __eqtf2 (void) { abort(); }
+void __netf2 (void) { abort(); }
+void __gttf2 (void) { abort(); }
+void __getf2 (void) { abort(); }
+void __letf2 (void) { abort(); }
+void __lttf2 (void) { abort(); }
#else /* !EXTENDED_FLOAT_STUBS, rest of file */
/* IEEE "special" number predicates */
static fp_number_type *
nan (void)
{
- /* Discard the const qualifier... */
+ /* Discard the const qualifier... */
#ifdef FLOAT
return (fp_number_type *) (& __thenan_sf);
#else
int sign = src->sign;
int exp = 0;
- if (isnan (src))
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
+ {
+ /* We can't represent these values accurately. By using the
+ largest possible magnitude, we guarantee that the conversion
+ of infinity is at least as big as any finite number. */
+ exp = EXPMAX;
+ fraction = ((fractype) 1 << FRACBITS) - 1;
+ }
+ else if (isnan (src))
{
exp = EXPMAX;
if (src->class == CLASS_QNAN || 1)
{
if (src->normal_exp < NORMAL_EXPMIN)
{
+#ifdef NO_DENORMALS
+ /* Go straight to a zero representation if denormals are not
+ supported. The denormal handling would be harmless but
+ isn't unnecessary. */
+ exp = 0;
+ fraction = 0;
+#else /* NO_DENORMALS */
/* This number's exponent is too low to fit into the bits
available in the number, so we'll store 0 in the exponent and
shift the fraction to the right to make up for it. */
exp += 1;
}
fraction >>= NGARDS;
+#endif /* NO_DENORMALS */
}
- else if (src->normal_exp > EXPBIAS)
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
+ && src->normal_exp > EXPBIAS)
{
exp = EXPMAX;
fraction = 0;
else
{
exp = src->normal_exp + EXPBIAS;
- /* IF the gard bits are the all zero, but the first, then we're
- half way between two numbers, choose the one which makes the
- lsb of the answer 0. */
- if ((fraction & GARDMASK) == GARDMSB)
- {
- if (fraction & (1 << NGARDS))
- fraction += GARDROUND + 1;
- }
- else
+ if (!ROUND_TOWARDS_ZERO)
{
- /* Add a one to the guards to round up */
- fraction += GARDROUND;
+ /* IF the gard bits are the all zero, but the first, then we're
+ half way between two numbers, choose the one which makes the
+ lsb of the answer 0. */
+ if ((fraction & GARDMASK) == GARDMSB)
+ {
+ if (fraction & (1 << NGARDS))
+ fraction += GARDROUND + 1;
+ }
+ else
+ {
+ /* Add a one to the guards to round up */
+ fraction += GARDROUND;
+ }
+ if (fraction >= IMPLICIT_2)
+ {
+ fraction >>= 1;
+ exp += 1;
+ }
}
- if (fraction >= IMPLICIT_2)
+ fraction >>= NGARDS;
+
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
{
- fraction >>= 1;
- exp += 1;
+ /* Saturate on overflow. */
+ exp = EXPMAX;
+ fraction = ((fractype) 1 << FRACBITS) - 1;
}
- fraction >>= NGARDS;
}
}
}
else
{
- /* Zero exponent with non zero fraction - it's denormalized,
+ /* Zero exponent with nonzero fraction - it's denormalized,
so there isn't a leading implicit one - we'll shift it so
it gets one. */
dst->normal_exp = exp - EXPBIAS + 1;
dst->fraction.ll = fraction;
}
}
- else if (exp == EXPMAX)
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
{
/* Huge exponent*/
if (fraction == 0)
}
else
{
- /* Non zero fraction, means nan */
+ /* Nonzero fraction, means nan */
if (fraction & QUIET_NAN)
{
dst->class = CLASS_QNAN;
#endif /* L_addsub_sf || L_addsub_df */
#if defined(L_mul_sf) || defined(L_mul_df)
-static INLINE fp_number_type *
+static inline __attribute__ ((__always_inline__)) fp_number_type *
_fpmul_parts ( fp_number_type * a,
fp_number_type * b,
fp_number_type * tmp)
high |= 1;
low <<= 1;
}
- /* rounding is tricky. if we only round if it won't make us round later. */
+ /* rounding is tricky. if we only round if it won't make us round later. */
#if 0
if (low & FRACHIGH2)
{
if (((high & GARDMASK) != GARDMSB)
&& (((high + 1) & GARDMASK) == GARDMSB))
{
- /* don't round, it gets done again later. */
+ /* don't round, it gets done again later. */
}
else
{
}
}
#endif
- if ((high & GARDMASK) == GARDMSB)
+ if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
{
if (high & (1 << NGARDS))
{
#endif /* L_mul_sf || L_mul_df */
#if defined(L_div_sf) || defined(L_div_df)
-static INLINE fp_number_type *
+static inline __attribute__ ((__always_inline__)) fp_number_type *
_fpdiv_parts (fp_number_type * a,
fp_number_type * b)
{
numerator *= 2;
}
- if ((quotient & GARDMASK) == GARDMSB)
+ if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
{
if (quotient & (1 << NGARDS))
{
__fpcmp_parts (fp_number_type * a, fp_number_type * b)
{
#if 0
- /* either nan -> unordered. Must be checked outside of this routine. */
+ /* either nan -> unordered. Must be checked outside of this routine. */
if (isnan (a) && isnan (b))
{
return 1; /* still unordered! */
-------+--------+--------
-inf(1)| a>b(1) | a==b(0)
-------+--------+--------
- So since unordered must be non zero, just line up the columns...
+ So since unordered must be nonzero, just line up the columns...
*/
return b->sign - a->sign;
}
- /* but not both... */
+ /* but not both... */
if (isinf (a))
{
return a->sign ? -1 : 1;
{
return a->sign ? -1 : 1;
}
- /* now both are "normal". */
+ /* now both are "normal". */
if (a->sign != b->sign)
{
/* opposite signs */
{
return a->sign ? 1 : -1;
}
- /* same exponents; check size. */
+ /* same exponents; check size. */
if (a->fraction.ll > b->fraction.ll)
{
return a->sign ? -1 : 1;
{
return a->sign ? 1 : -1;
}
- /* after all that, they're equal. */
+ /* after all that, they're equal. */
return 0;
}
#endif
}
#endif /* L_le_sf || L_le_df */
+#endif /* ! US_SOFTWARE_GOFAST */
+
#if defined(L_unord_sf) || defined(L_unord_df)
CMPtype
_unord_f2 (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_unord_sf || L_unord_df */
-#endif /* ! US_SOFTWARE_GOFAST */
-
#if defined(L_si_to_sf) || defined(L_si_to_df)
FLO_type
si_to_float (SItype arg_a)
return 0;
if (isnan (&a))
return 0;
- /* get reasonable MAX_SI_INT... */
+ /* get reasonable MAX_SI_INT... */
if (isinf (&a))
return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
/* it is a number, but a small one */
/* it is a negative number */
if (a.sign)
return 0;
- /* get reasonable MAX_USI_INT... */
+ /* get reasonable MAX_USI_INT... */
if (isinf (&a))
return MAX_USI_INT;
/* it is a number, but a small one */