/* 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, 2002, 2003,
- 2004, 2005 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
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file with other programs, and to distribute
-those programs without any restriction coming from the use of this
-file. (The General Public License restrictions do apply in other
-respects; for example, they cover modification of the file, and
-distribution when not linked into another program.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* As a special exception, if you link this library with other files,
- some of which are compiled with GCC, to produce an executable,
- this library does not by itself cause the resulting executable
- to be covered by the GNU General Public License.
- This exception does not however invalidate any other reasons why
- the executable file might be covered by the GNU General Public License. */
+ 2004, 2005, 2008, 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
/* This implements IEEE 754 format arithmetic, but does not provide a
mechanism for setting the rounding mode, or for generating or handling
#endif
INLINE
-static fp_number_type *
-nan (void)
+static const fp_number_type *
+makenan (void)
{
- /* Discard the const qualifier... */
#ifdef TFLOAT
- return (fp_number_type *) (& __thenan_tf);
+ return & __thenan_tf;
#elif defined FLOAT
- return (fp_number_type *) (& __thenan_sf);
+ return & __thenan_sf;
#else
- return (fp_number_type *) (& __thenan_df);
+ return & __thenan_df;
#endif
}
INLINE
static int
-isnan ( fp_number_type * x)
+isnan (const fp_number_type *x)
{
- return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
+ return __builtin_expect (x->class == CLASS_SNAN || x->class == CLASS_QNAN,
+ 0);
}
INLINE
static int
-isinf ( fp_number_type * x)
+isinf (const fp_number_type * x)
{
- return x->class == CLASS_INFINITY;
+ return __builtin_expect (x->class == CLASS_INFINITY, 0);
}
#endif /* NO_NANS */
INLINE
static int
-iszero ( fp_number_type * x)
+iszero (const fp_number_type * x)
{
return x->class == CLASS_ZERO;
}
x->sign = !x->sign;
}
-extern FLO_type pack_d ( fp_number_type * );
+/* Count leading zeroes in N. */
+INLINE
+static int
+clzusi (USItype n)
+{
+ extern int __clzsi2 (USItype);
+ if (sizeof (USItype) == sizeof (unsigned int))
+ return __builtin_clz (n);
+ else if (sizeof (USItype) == sizeof (unsigned long))
+ return __builtin_clzl (n);
+ else if (sizeof (USItype) == sizeof (unsigned long long))
+ return __builtin_clzll (n);
+ else
+ return __clzsi2 (n);
+}
+
+extern FLO_type pack_d (const fp_number_type * );
#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
FLO_type
-pack_d ( fp_number_type * src)
+pack_d (const fp_number_type *src)
{
FLO_union_type dst;
fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
}
else
{
- if (src->normal_exp < NORMAL_EXPMIN)
+ if (__builtin_expect (src->normal_exp < NORMAL_EXPMIN, 0))
{
#ifdef NO_DENORMALS
/* Go straight to a zero representation if denormals are not
#endif /* NO_DENORMALS */
}
else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
- && src->normal_exp > EXPBIAS)
+ && __builtin_expect (src->normal_exp > EXPBIAS, 0))
{
exp = EXPMAX;
fraction = 0;
dst->fraction.ll = fraction;
}
}
- else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
+ && __builtin_expect (exp == EXPMAX, 0))
{
/* Huge exponent*/
if (fraction == 0)
#endif /* L_unpack_df || L_unpack_sf */
#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
-static fp_number_type *
+static const fp_number_type *
_fpadd_parts (fp_number_type * a,
fp_number_type * b,
fp_number_type * tmp)
{
/* Adding infinities with opposite signs yields a NaN. */
if (isinf (b) && a->sign != b->sign)
- return nan ();
+ return makenan ();
return a;
}
if (isinf (b))
they're the same */
{
int diff;
+ int sdiff;
a_normal_exp = a->normal_exp;
b_normal_exp = b->normal_exp;
b_fraction = b->fraction.ll;
diff = a_normal_exp - b_normal_exp;
+ sdiff = diff;
if (diff < 0)
diff = -diff;
if (diff < FRAC_NBITS)
{
- /* ??? This does shifts one bit at a time. Optimize. */
- while (a_normal_exp > b_normal_exp)
+ if (sdiff > 0)
{
- b_normal_exp++;
- LSHIFT (b_fraction);
+ b_normal_exp += diff;
+ LSHIFT (b_fraction, diff);
}
- while (b_normal_exp > a_normal_exp)
+ else if (sdiff < 0)
{
- a_normal_exp++;
- LSHIFT (a_fraction);
+ a_normal_exp += diff;
+ LSHIFT (a_fraction, diff);
}
}
else
if (tmp->fraction.ll >= IMPLICIT_2)
{
- LSHIFT (tmp->fraction.ll);
+ LSHIFT (tmp->fraction.ll, 1);
tmp->normal_exp++;
}
return tmp;
-
}
FLO_type
fp_number_type a;
fp_number_type b;
fp_number_type tmp;
- fp_number_type *res;
+ const fp_number_type *res;
FLO_union_type au, bu;
au.value = arg_a;
fp_number_type a;
fp_number_type b;
fp_number_type tmp;
- fp_number_type *res;
+ const fp_number_type *res;
FLO_union_type au, bu;
au.value = arg_a;
#endif /* L_addsub_sf || L_addsub_df */
#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
-static inline __attribute__ ((__always_inline__)) fp_number_type *
+static inline __attribute__ ((__always_inline__)) const fp_number_type *
_fpmul_parts ( fp_number_type * a,
fp_number_type * b,
fp_number_type * tmp)
if (isinf (a))
{
if (iszero (b))
- return nan ();
+ return makenan ();
a->sign = a->sign != b->sign;
return a;
}
{
if (iszero (a))
{
- return nan ();
+ return makenan ();
}
b->sign = a->sign != b->sign;
return b;
fp_number_type a;
fp_number_type b;
fp_number_type tmp;
- fp_number_type *res;
+ const fp_number_type *res;
FLO_union_type au, bu;
au.value = arg_a;
#endif /* L_mul_sf || L_mul_df || L_mul_tf */
#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
-static inline __attribute__ ((__always_inline__)) fp_number_type *
+static inline __attribute__ ((__always_inline__)) const fp_number_type *
_fpdiv_parts (fp_number_type * a,
fp_number_type * b)
{
if (isinf (a) || iszero (a))
{
if (a->class == b->class)
- return nan ();
+ return makenan ();
return a;
}
{
fp_number_type a;
fp_number_type b;
- fp_number_type *res;
+ const fp_number_type *res;
FLO_union_type au, bu;
au.value = arg_a;
}
else
{
+ USItype uarg;
+ int shift;
in.normal_exp = FRACBITS + NGARDS;
if (in.sign)
{
{
return (FLO_type)(- MAX_SI_INT - 1);
}
- in.fraction.ll = (-arg_a);
+ uarg = (-arg_a);
}
else
- in.fraction.ll = arg_a;
+ uarg = arg_a;
- while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
+ in.fraction.ll = uarg;
+ shift = clzusi (uarg) - (BITS_PER_SI - 1 - FRACBITS - NGARDS);
+ if (shift > 0)
{
- in.fraction.ll <<= 1;
- in.normal_exp -= 1;
+ in.fraction.ll <<= shift;
+ in.normal_exp -= shift;
}
}
return pack_d (&in);
}
else
{
+ int shift;
in.class = CLASS_NUMBER;
in.normal_exp = FRACBITS + NGARDS;
in.fraction.ll = arg_a;
- while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
- {
- in.fraction.ll >>= 1;
- in.normal_exp += 1;
- }
- while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
+ shift = clzusi (arg_a) - (BITS_PER_SI - 1 - FRACBITS - NGARDS);
+ if (shift < 0)
+ {
+ fractype guard = in.fraction.ll & (((fractype)1 << -shift) - 1);
+ in.fraction.ll >>= -shift;
+ in.fraction.ll |= (guard != 0);
+ in.normal_exp -= shift;
+ }
+ else if (shift > 0)
{
- in.fraction.ll <<= 1;
- in.normal_exp -= 1;
+ in.fraction.ll <<= shift;
+ in.normal_exp -= shift;
}
}
return pack_d (&in);