diff options
Diffstat (limited to 'gcc-4.2.1-5666.3/gcc/config/arm/_fixdfdi.c')
-rw-r--r-- | gcc-4.2.1-5666.3/gcc/config/arm/_fixdfdi.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/gcc-4.2.1-5666.3/gcc/config/arm/_fixdfdi.c b/gcc-4.2.1-5666.3/gcc/config/arm/_fixdfdi.c new file mode 100644 index 000000000..f88067192 --- /dev/null +++ b/gcc-4.2.1-5666.3/gcc/config/arm/_fixdfdi.c @@ -0,0 +1,84 @@ +/* APPLE LOCAL file 5316398 improved float/double -> int64 functions */ +#include <stdint.h> + +int64_t +__fixdfdi (double x) +{ + union { double d; uint64_t u; } u = {x}; + uint64_t fabsx = u.u & 0x7fffffffffffffffULL; + uint32_t exp = fabsx >> 52; + int64_t result = 0; + + /* for very large and reasonably small values, regular int converter + works fine */ + if (exp >= 52U + 1023U) /* if( |x| >= 0x1.0p52 || isnan( x ) ) */ + { + /* early out for error cases |x| >= 0x1.0p63 || isnan(x) */ + if (exp >= 1023U + 63U) + { + /* special case for x == -0x1.0p63 */ + if (-0x1.0p63 == x) + return 0x8000000000000000ULL; + + /* huge, Inf, NaN */ + result = (int32_t) x; /* grab sign bit */ + result >>= 63; /* splat it across value */ + /* return either 0x8000000000000000 or 0x7fffffffffffffff + according to sign bit */ + result ^= 0x7fffffffffffffffULL; + + return result; + } + + /* 0x1.0p52 <= |x| < 0x1.0p63 always integer, but too big. Chop + off some of the top. */ + u.u &= 0xFFFFFFFF00000000ULL; /* truncate off some low bits */ + x -= u.d; /* get remainder */ + + /* accumulate the high part into result */ + int32_t hi = u.d * 0x1.0p-32; + result += (int64_t) hi << 32; + } + else + { /* |x| < 0x1.0p52 */ + + /* early out for |x| < 0x1.0p31 -- use hardware 32-bit conversion */ + if (exp < 1023U + 31U) + return (int64_t) ((int32_t) x); + + /* The integer result fits in the significand, but there may be + some fractional bits. Value is too large to use 32-bit + hardware. + + create a mask that covers the high 32-bit part of the number + and the whole integer part. */ + uint64_t intMask = (int64_t) 0xFFF0000000000000LL >> (exp - 1023); + + /* extract the full integer (round to integer in round to zero + rounding mode) */ + u.u &= intMask; + + /* find the fractional part */ + double fraction = x - u.d; + + /* save the integer part */ + x = u.d; + + /* set inexact as needed */ + result = (int32_t) fraction; /* always 0 */ + } + + /* xi is < 2**53 now and integer. Convert to integer representation. */ + if (x < 0.0) + { + u.d = x - 0x1.0p52; + result -= u.u & 0x000FFFFFFFFFFFFFULL; + } + else + { + u.d = x + 0x1.0p52; + result += u.u & 0x000FFFFFFFFFFFFFULL; + } + + return result; +} |