Index: lib/builtins/fixdfsi.c =================================================================== --- lib/builtins/fixdfsi.c +++ lib/builtins/fixdfsi.c @@ -15,36 +15,11 @@ #define DOUBLE_PRECISION #include "fp_lib.h" - -#include "int_lib.h" +#include "fp_fixsi_impl.inc" ARM_EABI_FNALIAS(d2iz, fixdfsi) COMPILER_RT_ABI int __fixdfsi(fp_t a) { - - // Break a into sign, exponent, significand - const rep_t aRep = toRep(a); - const rep_t aAbs = aRep & absMask; - const int sign = aRep & signBit ? -1 : 1; - const int exponent = (aAbs >> significandBits) - exponentBias; - const rep_t significand = (aAbs & significandMask) | implicitBit; - - // If 0 < exponent < significandBits, right shift to get the result. - if ((unsigned int)exponent < significandBits) { - return sign * (significand >> (significandBits - exponent)); - } - - // If exponent is negative, the result is zero. - else if (exponent < 0) { - return 0; - } - - // If significandBits < exponent, left shift to get the result. This shift - // may end up being larger than the type width, which incurs undefined - // behavior, but the conversion itself is undefined in that case, so - // whatever the compiler decides to do is fine. - else { - return sign * (significand << (exponent - significandBits)); - } + return __fixXsi(a); } Index: lib/builtins/fixsfsi.c =================================================================== --- lib/builtins/fixsfsi.c +++ lib/builtins/fixsfsi.c @@ -15,33 +15,11 @@ #define SINGLE_PRECISION #include "fp_lib.h" +#include "fp_fixsi_impl.inc" ARM_EABI_FNALIAS(f2iz, fixsfsi) COMPILER_RT_ABI int __fixsfsi(fp_t a) { - // Break a into sign, exponent, significand - const rep_t aRep = toRep(a); - const rep_t aAbs = aRep & absMask; - const int sign = aRep & signBit ? -1 : 1; - const int exponent = (aAbs >> significandBits) - exponentBias; - const rep_t significand = (aAbs & significandMask) | implicitBit; - - // If 0 < exponent < significandBits, right shift to get the result. - if ((unsigned int)exponent < significandBits) { - return sign * (significand >> (significandBits - exponent)); - } - - // If exponent is negative, the result is zero. - else if (exponent < 0) { - return 0; - } - - // If significandBits < exponent, left shift to get the result. This shift - // may end up being larger than the type width, which incurs undefined - // behavior, but the conversion itself is undefined in that case, so - // whatever the compiler decides to do is fine. - else { - return sign * (significand << (exponent - significandBits)); - } + return __fixXsi(a); } Index: lib/builtins/fixtfsi.c =================================================================== --- lib/builtins/fixtfsi.c +++ lib/builtins/fixtfsi.c @@ -0,0 +1,26 @@ +//===-- lib/fixtfsi.c - Quad-precision -> integer conversion ------*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements quad-precision to integer conversion for the +// compiler-rt library. No range checking is performed; the behavior of this +// conversion is undefined for out of range values in the C standard. +// +//===----------------------------------------------------------------------===// + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +#include "fp_fixsi_impl.inc" + +COMPILER_RT_ABI int __fixtfsi(fp_t a) { + return __fixXsi(a); +} + +#endif Index: lib/builtins/fixunstfsi.c =================================================================== --- lib/builtins/fixunstfsi.c +++ lib/builtins/fixunstfsi.c @@ -0,0 +1,47 @@ +/* ===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __fixunstfsi for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +/* Returns: convert a to a unsigned int, rounding toward zero. + * Negative values all become zero. + */ + +/* Assumption: long double is a IEEE 128 bit floating point type + * su_int is a 32 bit integral type + * value in long double is representable in su_int or is negative + * (no range checking performed) + */ + +/* seee eeee eeee eeee mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm + mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ + +COMPILER_RT_ABI su_int +__fixunstfsi(long double a) +{ + long_double_bits fb; + fb.f = a; + int e = ((fb.u.high.s.high & 0x7FFF0000) >> 16) - 16383; + if (e < 0 || (fb.u.high.s.high & 0x80000000)) + return 0; + return ( + 0x80000000u | + ((fb.u.high.s.high & 0x0000FFFF) << 15) | + (fb.u.high.s.low >> 17) + ) >> (31 - e); +} + +#endif Index: lib/builtins/fp_fixsi_impl.inc =================================================================== --- lib/builtins/fp_fixsi_impl.inc +++ lib/builtins/fp_fixsi_impl.inc @@ -0,0 +1,39 @@ +//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements float to integer conversion for the +// compiler-rt library. No range checking is performed; the behavior of this +// conversion is undefined for out of range values in the C standard. +// +//===----------------------------------------------------------------------===// + +#include "fp_lib.h" + +static inline int __fixXsi(fp_t a) { + // Break a into sign, exponent, significand + const rep_t aRep = toRep(a); + const rep_t aAbs = aRep & absMask; + const int sign = aRep & signBit ? -1 : 1; + const int exponent = (aAbs >> significandBits) - exponentBias; + const rep_t significand = (aAbs & significandMask) | implicitBit; + + // If 0 <= exponent < significandBits, right shift to get the result. + if ((unsigned int)exponent < significandBits) + return sign * (significand >> (significandBits - exponent)); + + // If exponent is negative, the result is zero. + if (exponent < 0) + return 0; + + // If significandBits < exponent, left shift to get the result. This shift + // may end up being larger than the type width, which incurs undefined + // behavior, but the conversion itself is undefined in that case, so + // whatever the compiler decides to do is fine. + return sign * (significand << (exponent - significandBits)); +} Index: test/builtins/Unit/fixtfsi_test.c =================================================================== --- test/builtins/Unit/fixtfsi_test.c +++ test/builtins/Unit/fixtfsi_test.c @@ -0,0 +1,65 @@ +//===--------------- fixtfsi_test.c - Test __fixtfsi ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests __fixtfsi for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" + +int __fixtfsi(long double a); + +int test__fixtfsi(long double a, int expected) +{ + int x = __fixtfsi(a); + int ret = (x != expected); + + if (ret){ + printf("error in test__fixtfsi(%.20Lf) = %d, " + "expected %d\n", a, x, expected); + } + return ret; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__fixtfsi(makeInf128(), 0x7fffffff)) + return 1; + if (test__fixtfsi(0, 0x0)) + return 1; + if (test__fixtfsi(0x1.23456789abcdefp+5, 0x24)) + return 1; + if (test__fixtfsi(0x1.23456789abcdefp-3, 0x0)) + return 1; + if (test__fixtfsi(0x1.23456789abcdefp+20, 0x123456)) + return 1; + if (test__fixtfsi(0x1.23456789abcdefp+40, 0x7fffffff)) + return 1; + if (test__fixtfsi(0x1.23456789abcdefp+256, 0x7fffffff)) + return 1; + if (test__fixtfsi(-0x1.23456789abcdefp+20, 0xffedcbaa)) + return 1; + if (test__fixtfsi(-0x1.23456789abcdefp+40, 0x80000001)) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +} Index: test/builtins/Unit/fixunstfsi_test.c =================================================================== --- test/builtins/Unit/fixunstfsi_test.c +++ test/builtins/Unit/fixunstfsi_test.c @@ -0,0 +1,64 @@ +//===--------------- fixunstfsi_test.c - Test __fixunstfsi ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests __fixunstfsi for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" + +unsigned int __fixunstfsi(long double a); + +int test__fixunstfsi(long double a, unsigned int expected) +{ + unsigned int x = __fixunstfsi(a); + int ret = (x != expected); + + if (ret) + { + printf("error in test__fixunstfsi(%.20Lf) = %u, " + "expected %u\n", a, x, expected); + } + return ret; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__fixunstfsi(makeInf128(), UINT32_C(0xffffffff))) + return 1; + if (test__fixunstfsi(0, UINT32_C(0x0))) + return 1; + if (test__fixunstfsi(0x1.23456789abcdefp+5, UINT32_C(0x24))) + return 1; + if (test__fixunstfsi(0x1.23456789abcdefp-3, UINT32_C(0x0))) + return 1; + if (test__fixunstfsi(0x1.23456789abcdefp+20, UINT32_C(0x123456))) + return 1; + if (test__fixunstfsi(0x1.23456789abcdefp+40, UINT32_C(0xffffffff))) + return 1; + if (test__fixunstfsi(0x1.23456789abcdefp+256, UINT32_C(0xffffffff))) + return 1; + if (test__fixunstfsi(-0x1.23456789abcdefp+3, UINT32_C(0x0))) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +}