diff options
author | jsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-22 00:38:30 +0000 |
---|---|---|
committer | jsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-22 00:38:30 +0000 |
commit | 4f5bcdbdf334ba80e3f4890bb752e457601f3e9e (patch) | |
tree | cf1224f63a9636c4333be5cb2d3cabfe2eec233d /gcc/config/fp-bit.c | |
parent | 624e1eec9297f70ad0a205f71092eaa6863dc87b (diff) | |
download | gcc-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.c | 50 |
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); |