aboutsummaryrefslogtreecommitdiff
path: root/libgcc/libgcc2.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/libgcc2.c')
-rw-r--r--libgcc/libgcc2.c41
1 files changed, 13 insertions, 28 deletions
diff --git a/libgcc/libgcc2.c b/libgcc/libgcc2.c
index faefff3..df99c78 100644
--- a/libgcc/libgcc2.c
+++ b/libgcc/libgcc2.c
@@ -2187,36 +2187,21 @@ __fixunssfDI (SFtype a)
if (a < 1)
return 0;
if (a < Wtype_MAXp1_F)
- return (UWtype)a;
+ return (UWtype) a;
if (a < Wtype_MAXp1_F * Wtype_MAXp1_F)
{
- /* Since we know that there are fewer significant bits in the SFmode
- quantity than in a word, we know that we can convert out all the
- significant bits in one step, and thus avoid losing bits. */
-
- /* ??? This following loop essentially performs frexpf. If we could
- use the real libm function, or poke at the actual bits of the fp
- format, it would be significantly faster. */
-
- UWtype shift = 0, counter;
- SFtype msb;
-
- a /= Wtype_MAXp1_F;
- for (counter = W_TYPE_SIZE / 2; counter != 0; counter >>= 1)
- {
- SFtype counterf = (UWtype)1 << counter;
- if (a >= counterf)
- {
- shift |= counter;
- a /= counterf;
- }
- }
-
- /* Rescale into the range of one word, extract the bits of that
- one word, and shift the result into position. */
- a *= Wtype_MAXp1_F;
- counter = a;
- return (DWtype)counter << shift;
+ /* We assume that SFtype -> UWtype and UWtype -> UDWtype casts work
+ properly. Obviously, we *cannot* assume that SFtype -> UDWtype
+ works as expected. */
+ SFtype a_hi, a_lo;
+
+ a_hi = a / Wtype_MAXp1_F;
+ a_lo = a - a_hi * Wtype_MAXp1_F;
+
+ /* A lot of parentheses. This is to make it very clear what is
+ the sequence of operations. */
+ return ((UDWtype) ((UWtype) a_hi)) << W_TYPE_SIZE
+ | (UDWtype) ((UWtype) a_lo);
}
return -1;
#else