summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/fp-bit.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/config/fp-bit.c')
-rw-r--r--contrib/gcc/config/fp-bit.c250
1 files changed, 204 insertions, 46 deletions
diff --git a/contrib/gcc/config/fp-bit.c b/contrib/gcc/config/fp-bit.c
index 4ee08f1..f4a1e2a 100644
--- a/contrib/gcc/config/fp-bit.c
+++ b/contrib/gcc/config/fp-bit.c
@@ -1,8 +1,7 @@
/* This is a software floating point library which can be used instead of
the floating point routines in libgcc1.c for targets without hardware
- floating point. */
-
-/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ floating point.
+ Copyright (C) 1994, 1995, 1996, 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
@@ -44,6 +43,55 @@ Boston, MA 02111-1307, USA. */
/* The intended way to use this file is to make two copies, add `#define FLOAT'
to one copy, then compile both copies and add them to libgcc.a. */
+/* Defining FINE_GRAINED_LIBRARIES allows one to select which routines
+ from this file are compiled via additional -D options.
+
+ This avoids the need to pull in the entire fp emulation library
+ when only a small number of functions are needed.
+
+ If FINE_GRAINED_LIBRARIES is not defined, then compile every
+ suitable routine. */
+#ifndef FINE_GRAINED_LIBRARIES
+#define L_pack_df
+#define L_unpack_df
+#define L_pack_sf
+#define L_unpack_sf
+#define L_addsub_sf
+#define L_addsub_df
+#define L_mul_sf
+#define L_mul_df
+#define L_div_sf
+#define L_div_df
+#define L_fpcmp_parts_sf
+#define L_fpcmp_parts_df
+#define L_compare_sf
+#define L_compare_df
+#define L_eq_sf
+#define L_eq_df
+#define L_ne_sf
+#define L_ne_df
+#define L_gt_sf
+#define L_gt_df
+#define L_ge_sf
+#define L_ge_df
+#define L_lt_sf
+#define L_lt_df
+#define L_le_sf
+#define L_le_df
+#define L_si_to_sf
+#define L_si_to_df
+#define L_sf_to_si
+#define L_df_to_si
+#define L_f_to_usi
+#define L_df_to_usi
+#define L_negate_sf
+#define L_negate_df
+#define L_make_sf
+#define L_make_df
+#define L_sf_to_df
+#define L_df_to_sf
+#endif
+
/* The following macros can be defined to change the behaviour 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.
@@ -62,6 +110,52 @@ Boston, MA 02111-1307, USA. */
SMALL_MACHINE: Useful when operations on QIs and HIs are faster
than on an SI */
+/* We don't currently support extended floats (long doubles) on machines
+ without hardware to deal with them.
+
+ These stubs are just to keep the linker from complaining about unresolved
+ references which can be pulled in from libio & libstdc++, even if the
+ user isn't using long doubles. However, they may generate an unresolved
+ external to abort if abort is not used by the function, and the stubs
+ are referenced from within libc, since libgcc goes before and after the
+ system library. */
+
+#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(); }
+#else /* !EXTENDED_FLOAT_STUBS, rest of file */
+
+
typedef SFtype __attribute__ ((mode (SF)));
typedef DFtype __attribute__ ((mode (DF)));
@@ -99,8 +193,9 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
# define FRAC_NBITS 32
# define FRACHIGH 0x80000000L
# define FRACHIGH2 0xc0000000L
-# define pack_d pack_f
-# define unpack_d unpack_f
+# define pack_d __pack_f
+# define unpack_d __unpack_f
+# define __fpcmp_parts __fpcmp_parts_f
typedef USItype fractype;
typedef UHItype halffractype;
typedef SFtype FLO_type;
@@ -121,6 +216,9 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
# define FRAC_NBITS 64
# define FRACHIGH 0x8000000000000000LL
# define FRACHIGH2 0xc000000000000000LL
+# define pack_d __pack_d
+# define unpack_d __unpack_d
+# define __fpcmp_parts __fpcmp_parts_d
typedef UDItype fractype;
typedef USItype halffractype;
typedef DFtype FLO_type;
@@ -191,7 +289,9 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
#endif
+#ifndef INLINE
#define INLINE __inline__
+#endif
/* Preserve the sticky-bit when shifting fractions to the right. */
#define LSHIFT(a) { a = (a & 1) | (a >> 1); }
@@ -199,7 +299,7 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
/* numeric parameters */
/* F_D_BITOFF is the number of bits offset between the MSB of the mantissa
of a float and of a double. Assumes there are only two float types.
- (double::FRAC_BITS+double::NGARGS-(float::FRAC_BITS-float::NGARDS))
+ (double::FRAC_BITS+double::NGARDS-(float::FRAC_BITS-float::NGARDS))
*/
#define F_D_BITOFF (52+8-(23+7))
@@ -328,7 +428,10 @@ flip_sign ( fp_number_type * x)
x->sign = !x->sign;
}
-static FLO_type
+extern FLO_type pack_d ( fp_number_type * );
+
+#if defined(L_pack_df) || defined(L_pack_sf)
+FLO_type
pack_d ( fp_number_type * src)
{
FLO_union_type dst;
@@ -414,7 +517,7 @@ pack_d ( fp_number_type * src)
}
/* We previously used bitfields to store the number, but this doesn't
- handle little/big endian systems conviently, so use shifts and
+ handle little/big endian systems conveniently, so use shifts and
masks */
#ifdef FLOAT_BIT_ORDER_MISMATCH
dst.bits.fraction = fraction;
@@ -436,12 +539,16 @@ pack_d ( fp_number_type * src)
return dst.value;
}
+#endif
-static void
+extern void unpack_d (FLO_union_type *, fp_number_type *);
+
+#if defined(L_unpack_df) || defined(L_unpack_sf)
+void
unpack_d (FLO_union_type * src, fp_number_type * dst)
{
/* We previously used bitfields to store the number, but this doesn't
- handle little/big endian systems conviently, so use shifts and
+ handle little/big endian systems conveniently, so use shifts and
masks */
fractype fraction;
int exp;
@@ -504,13 +611,13 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
else
{
/* Non zero fraction, means nan */
- if (sign)
+ if (fraction & QUIET_NAN)
{
- dst->class = CLASS_SNAN;
+ dst->class = CLASS_QNAN;
}
else
{
- dst->class = CLASS_QNAN;
+ dst->class = CLASS_SNAN;
}
/* Keep the fraction part as the nan number */
dst->fraction.ll = fraction;
@@ -524,7 +631,9 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
}
}
+#endif
+#if defined(L_addsub_sf) || defined(L_addsub_df)
static fp_number_type *
_fpadd_parts (fp_number_type * a,
fp_number_type * b,
@@ -559,6 +668,12 @@ _fpadd_parts (fp_number_type * a,
}
if (iszero (b))
{
+ if (iszero (a))
+ {
+ *tmp = *a;
+ tmp->sign = a->sign & b->sign;
+ return tmp;
+ }
return a;
}
if (iszero (a))
@@ -692,8 +807,10 @@ sub (FLO_type arg_a, FLO_type arg_b)
return pack_d (res);
}
+#endif
-static fp_number_type *
+#if defined(L_mul_sf) || defined(L_mul_df)
+static INLINE fp_number_type *
_fpmul_parts ( fp_number_type * a,
fp_number_type * b,
fp_number_type * tmp)
@@ -741,13 +858,13 @@ _fpmul_parts ( fp_number_type * a,
/* Calculate the mantissa by multiplying both 64bit numbers to get a
128 bit number */
{
- fractype x = a->fraction.ll;
- fractype ylow = b->fraction.ll;
- fractype yhigh = 0;
- int bit;
-
#if defined(NO_DI_MODE)
{
+ fractype x = a->fraction.ll;
+ fractype ylow = b->fraction.ll;
+ fractype yhigh = 0;
+ int bit;
+
/* ??? This does multiplies one bit at a time. Optimize. */
for (bit = 0; bit < FRAC_NBITS; bit++)
{
@@ -878,20 +995,18 @@ multiply (FLO_type arg_a, FLO_type arg_b)
return pack_d (res);
}
+#endif
-static fp_number_type *
+#if defined(L_div_sf) || defined(L_div_df)
+static INLINE fp_number_type *
_fpdiv_parts (fp_number_type * a,
fp_number_type * b,
fp_number_type * tmp)
{
- fractype low = 0;
- fractype high = 0;
- fractype r0, r1, y0, y1, bit;
- fractype q;
+ fractype bit;
fractype numerator;
fractype denominator;
fractype quotient;
- fractype remainder;
if (isnan (a))
{
@@ -901,13 +1016,15 @@ _fpdiv_parts (fp_number_type * a,
{
return b;
}
+
+ a->sign = a->sign ^ b->sign;
+
if (isinf (a) || iszero (a))
{
if (a->class == b->class)
return nan ();
return a;
}
- a->sign = a->sign ^ b->sign;
if (isinf (b))
{
@@ -918,15 +1035,12 @@ _fpdiv_parts (fp_number_type * a,
if (iszero (b))
{
a->class = CLASS_INFINITY;
- return b;
+ return a;
}
/* Calculate the mantissa by multiplying both 64bit numbers to get a
128 bit number */
{
- int carry;
- intfrac d0, d1; /* weren't unsigned before ??? */
-
/* quotient =
( numerator / denominator) * 2^(numerator exponent - denominator exponent)
*/
@@ -989,15 +1103,19 @@ divide (FLO_type arg_a, FLO_type arg_b)
return pack_d (res);
}
+#endif
+int __fpcmp_parts (fp_number_type * a, fp_number_type *b);
+
+#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df)
/* according to the demo, fpcmp returns a comparison with 0... thus
a<b -> -1
a==b -> 0
a>b -> +1
*/
-static int
-_fpcmp_parts (fp_number_type * a, fp_number_type * b)
+int
+__fpcmp_parts (fp_number_type * a, fp_number_type * b)
{
#if 0
/* either nan -> unordered. Must be checked outside of this routine. */
@@ -1072,7 +1190,9 @@ _fpcmp_parts (fp_number_type * a, fp_number_type * b)
/* after all that, they're equal. */
return 0;
}
+#endif
+#if defined(L_compare_sf) || defined(L_compare_df)
CMPtype
compare (FLO_type arg_a, FLO_type arg_b)
{
@@ -1082,13 +1202,15 @@ compare (FLO_type arg_a, FLO_type arg_b)
unpack_d ((FLO_union_type *) & arg_a, &a);
unpack_d ((FLO_union_type *) & arg_b, &b);
- return _fpcmp_parts (&a, &b);
+ return __fpcmp_parts (&a, &b);
}
+#endif
#ifndef US_SOFTWARE_GOFAST
/* These should be optimized for their specific tasks someday. */
+#if defined(L_eq_sf) || defined(L_eq_df)
CMPtype
_eq_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1101,9 +1223,11 @@ _eq_f2 (FLO_type arg_a, FLO_type arg_b)
if (isnan (&a) || isnan (&b))
return 1; /* false, truth == 0 */
- return _fpcmp_parts (&a, &b) ;
+ return __fpcmp_parts (&a, &b) ;
}
+#endif
+#if defined(L_ne_sf) || defined(L_ne_df)
CMPtype
_ne_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1116,9 +1240,11 @@ _ne_f2 (FLO_type arg_a, FLO_type arg_b)
if (isnan (&a) || isnan (&b))
return 1; /* true, truth != 0 */
- return _fpcmp_parts (&a, &b) ;
+ return __fpcmp_parts (&a, &b) ;
}
+#endif
+#if defined(L_gt_sf) || defined(L_gt_df)
CMPtype
_gt_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1131,9 +1257,11 @@ _gt_f2 (FLO_type arg_a, FLO_type arg_b)
if (isnan (&a) || isnan (&b))
return -1; /* false, truth > 0 */
- return _fpcmp_parts (&a, &b);
+ return __fpcmp_parts (&a, &b);
}
+#endif
+#if defined(L_ge_sf) || defined(L_ge_df)
CMPtype
_ge_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1145,9 +1273,11 @@ _ge_f2 (FLO_type arg_a, FLO_type arg_b)
if (isnan (&a) || isnan (&b))
return -1; /* false, truth >= 0 */
- return _fpcmp_parts (&a, &b) ;
+ return __fpcmp_parts (&a, &b) ;
}
+#endif
+#if defined(L_lt_sf) || defined(L_lt_df)
CMPtype
_lt_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1160,9 +1290,11 @@ _lt_f2 (FLO_type arg_a, FLO_type arg_b)
if (isnan (&a) || isnan (&b))
return 1; /* false, truth < 0 */
- return _fpcmp_parts (&a, &b);
+ return __fpcmp_parts (&a, &b);
}
+#endif
+#if defined(L_le_sf) || defined(L_le_df)
CMPtype
_le_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1175,11 +1307,13 @@ _le_f2 (FLO_type arg_a, FLO_type arg_b)
if (isnan (&a) || isnan (&b))
return 1; /* false, truth <= 0 */
- return _fpcmp_parts (&a, &b) ;
+ return __fpcmp_parts (&a, &b) ;
}
+#endif
#endif /* ! US_SOFTWARE_GOFAST */
+#if defined(L_si_to_sf) || defined(L_si_to_df)
FLO_type
si_to_float (SItype arg_a)
{
@@ -1215,7 +1349,9 @@ si_to_float (SItype arg_a)
}
return pack_d (&in);
}
+#endif
+#if defined(L_sf_to_si) || defined(L_df_to_si)
SItype
float_to_si (FLO_type arg_a)
{
@@ -1229,7 +1365,7 @@ float_to_si (FLO_type arg_a)
return 0;
/* get reasonable MAX_SI_INT... */
if (isinf (&a))
- return a.sign ? MAX_SI_INT : (-MAX_SI_INT)-1;
+ return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
/* it is a number, but a small one */
if (a.normal_exp < 0)
return 0;
@@ -1238,7 +1374,9 @@ float_to_si (FLO_type arg_a)
tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
return a.sign ? (-tmp) : (tmp);
}
+#endif
+#if defined(L_sf_to_usi) || defined(L_df_to_usi)
#ifdef US_SOFTWARE_GOFAST
/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
we also define them for GOFAST because the ones in libgcc2.c have the
@@ -1256,24 +1394,26 @@ float_to_usi (FLO_type arg_a)
return 0;
if (isnan (&a))
return 0;
- /* get reasonable MAX_USI_INT... */
- if (isinf (&a))
- return a.sign ? MAX_USI_INT : 0;
/* it is a negative number */
if (a.sign)
return 0;
+ /* get reasonable MAX_USI_INT... */
+ if (isinf (&a))
+ return MAX_USI_INT;
/* it is a number, but a small one */
if (a.normal_exp < 0)
return 0;
if (a.normal_exp > 31)
return MAX_USI_INT;
else if (a.normal_exp > (FRACBITS + NGARDS))
- return a.fraction.ll << ((FRACBITS + NGARDS) - a.normal_exp);
+ return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
else
return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
}
#endif
+#endif
+#if defined(L_negate_sf) || defined(L_negate_df)
FLO_type
negate (FLO_type arg_a)
{
@@ -1283,9 +1423,11 @@ negate (FLO_type arg_a)
flip_sign (&a);
return pack_d (&a);
}
+#endif
#ifdef FLOAT
+#if defined(L_make_sf)
SFtype
__make_fp(fp_class_type class,
unsigned int sign,
@@ -1300,6 +1442,7 @@ __make_fp(fp_class_type class,
in.fraction.ll = frac;
return pack_d (&in);
}
+#endif
#ifndef FLOAT_ONLY
@@ -1310,6 +1453,7 @@ __make_fp(fp_class_type class,
extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype frac);
+#if defined(L_sf_to_df)
DFtype
sf_to_df (SFtype arg_a)
{
@@ -1319,6 +1463,7 @@ sf_to_df (SFtype arg_a)
return __make_dp (in.class, in.sign, in.normal_exp,
((UDItype) in.fraction.ll) << F_D_BITOFF);
}
+#endif
#endif
#endif
@@ -1327,6 +1472,7 @@ sf_to_df (SFtype arg_a)
extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
+#if defined(L_make_df)
DFtype
__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
{
@@ -1338,15 +1484,27 @@ __make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
in.fraction.ll = frac;
return pack_d (&in);
}
+#endif
+#if defined(L_df_to_sf)
SFtype
df_to_sf (DFtype arg_a)
{
fp_number_type in;
+ USItype sffrac;
unpack_d ((FLO_union_type *) & arg_a, &in);
- return __make_fp (in.class, in.sign, in.normal_exp,
- in.fraction.ll >> F_D_BITOFF);
+
+ sffrac = in.fraction.ll >> F_D_BITOFF;
+
+ /* We set the lowest guard bit in SFFRAC if we discarded any non
+ zero bits. */
+ if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
+ sffrac |= 1;
+
+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
}
+#endif
#endif
+#endif /* !EXTENDED_FLOAT_STUBS */
OpenPOWER on IntegriCloud