summaryrefslogtreecommitdiff
path: root/gcc/config/fp-bit.c
diff options
context:
space:
mode:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-22 00:38:30 +0000
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-22 00:38:30 +0000
commit4f5bcdbdf334ba80e3f4890bb752e457601f3e9e (patch)
treecf1224f63a9636c4333be5cb2d3cabfe2eec233d /gcc/config/fp-bit.c
parent624e1eec9297f70ad0a205f71092eaa6863dc87b (diff)
downloadgcc-4f5bcdbdf334ba80e3f4890bb752e457601f3e9e.tar.gz
* config/fp-bit.c (clzusi): New function.
(si_to_float, usi_to_float): Use it to compute proper shift. (usi_to_float): Preserve guard bits when shifting right. * libgcc-std.ver (GCC_4.2.0): New version. * libgcc2.c (__floatundixf, __floatunditf, __floatundidf, __floatundisf): New functions. * libgcc2.h (__floatundixf, __floatunditf, __floatundidf, __floatundisf): Declare. * mklibgcc.in (lib2funcs): Add _floatundidf, _floatundisf, _floatundixf, and _floatunditf. * optabs.c (expand_float): If target does not define a pattern for signed or unsigned conversion, use an unsigned libcall instead of a signed one. (init_optabs): Initialize ufloat_optab. testsuite: * gcc.c-torture/execute/floatunsisf-1.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@107345 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/fp-bit.c')
-rw-r--r--gcc/config/fp-bit.c50
1 files changed, 37 insertions, 13 deletions
diff --git a/gcc/config/fp-bit.c b/gcc/config/fp-bit.c
index 4c637cb70ae..ccf927e8c3b 100644
--- a/gcc/config/fp-bit.c
+++ b/gcc/config/fp-bit.c
@@ -186,6 +186,22 @@ flip_sign ( fp_number_type * x)
x->sign = !x->sign;
}
+/* 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 ( fp_number_type * );
#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
@@ -1334,6 +1350,8 @@ si_to_float (SItype arg_a)
}
else
{
+ USItype uarg;
+ int shift;
in.normal_exp = FRACBITS + NGARDS;
if (in.sign)
{
@@ -1343,15 +1361,17 @@ si_to_float (SItype arg_a)
{
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);
@@ -1371,19 +1391,23 @@ usi_to_float (USItype arg_a)
}
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);