diff --git a/contrib/compiler-rt/lib/builtins/fixdfdi.c b/contrib/compiler-rt/lib/builtins/fixdfdi.c index 86f9f6ce8db3..67b124a16bbc 100644 --- a/contrib/compiler-rt/lib/builtins/fixdfdi.c +++ b/contrib/compiler-rt/lib/builtins/fixdfdi.c @@ -6,40 +6,17 @@ * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== - * - * This file implements __fixdfdi for the compiler_rt library. - * - * ===----------------------------------------------------------------------=== */ -#include "int_lib.h" - -/* Returns: convert a to a signed long long, rounding toward zero. */ - -/* Assumption: double is a IEEE 64 bit floating point type - * su_int is a 32 bit integral type - * value in double is representable in di_int (no range checking performed) - */ - -/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ - +#define DOUBLE_PRECISION +#include "fp_lib.h" ARM_EABI_FNALIAS(d2lz, fixdfdi) +typedef di_int fixint_t; +typedef du_int fixuint_t; +#include "fp_fixint_impl.inc" + COMPILER_RT_ABI di_int -__fixdfdi(double a) -{ - double_bits fb; - fb.f = a; - int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023; - if (e < 0) - return 0; - di_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31; - dwords r; - r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000; - r.s.low = fb.u.s.low; - if (e > 52) - r.all <<= (e - 52); - else - r.all >>= (52 - e); - return (r.all ^ s) - s; -} +__fixdfdi(fp_t a) { + return __fixint(a); +} diff --git a/contrib/compiler-rt/lib/builtins/fixdfsi.c b/contrib/compiler-rt/lib/builtins/fixdfsi.c index 88b2ff5e74a0..704e65bc43a1 100644 --- a/contrib/compiler-rt/lib/builtins/fixdfsi.c +++ b/contrib/compiler-rt/lib/builtins/fixdfsi.c @@ -1,50 +1,22 @@ -//===-- 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 double-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. -// -//===----------------------------------------------------------------------===// +/* ===-- fixdfsi.c - Implement __fixdfsi -----------------------------------=== + * + * 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. + * + * ===----------------------------------------------------------------------=== + */ #define DOUBLE_PRECISION #include "fp_lib.h" - -#include "int_lib.h" +typedef si_int fixint_t; +typedef su_int fixuint_t; +#include "fp_fixint_impl.inc" ARM_EABI_FNALIAS(d2iz, fixdfsi) -COMPILER_RT_ABI int +COMPILER_RT_ABI si_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 __fixint(a); } diff --git a/contrib/compiler-rt/lib/builtins/fixdfti.c b/contrib/compiler-rt/lib/builtins/fixdfti.c index 2c27f4bae3b9..aaf225e74f86 100644 --- a/contrib/compiler-rt/lib/builtins/fixdfti.c +++ b/contrib/compiler-rt/lib/builtins/fixdfti.c @@ -6,40 +6,21 @@ * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== - * - * This file implements __fixdfti for the compiler_rt library. - * - * ===----------------------------------------------------------------------=== */ #include "int_lib.h" #ifdef CRT_HAS_128BIT +#define DOUBLE_PRECISION +#include "fp_lib.h" -/* Returns: convert a to a signed long long, rounding toward zero. */ - -/* Assumption: double is a IEEE 64 bit floating point type - * su_int is a 32 bit integral type - * value in double is representable in ti_int (no range checking performed) - */ - -/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ +typedef ti_int fixint_t; +typedef tu_int fixuint_t; +#include "fp_fixint_impl.inc" COMPILER_RT_ABI ti_int -__fixdfti(double a) -{ - double_bits fb; - fb.f = a; - int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023; - if (e < 0) - return 0; - ti_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31; - ti_int r = 0x0010000000000000uLL | (0x000FFFFFFFFFFFFFuLL & fb.u.all); - if (e > 52) - r <<= (e - 52); - else - r >>= (52 - e); - return (r ^ s) - s; +__fixdfti(fp_t a) { + return __fixint(a); } #endif /* CRT_HAS_128BIT */ diff --git a/contrib/compiler-rt/lib/builtins/fixsfdi.c b/contrib/compiler-rt/lib/builtins/fixsfdi.c index 4f6cfdd7a5c6..835ff852d3e9 100644 --- a/contrib/compiler-rt/lib/builtins/fixsfdi.c +++ b/contrib/compiler-rt/lib/builtins/fixsfdi.c @@ -1,43 +1,23 @@ /* ===-- fixsfdi.c - Implement __fixsfdi -----------------------------------=== * - * The LLVM Compiler Infrastructure + * 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 __fixsfdi for the compiler_rt library. - * - * ===----------------------------------------------------------------------=== */ -#include "int_lib.h" - -/* Returns: convert a to a signed long long, rounding toward zero. */ - -/* Assumption: float is a IEEE 32 bit floating point type - * su_int is a 32 bit integral type - * value in float is representable in di_int (no range checking performed) - */ - -/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */ +#define SINGLE_PRECISION +#include "fp_lib.h" ARM_EABI_FNALIAS(f2lz, fixsfdi) +typedef di_int fixint_t; +typedef du_int fixuint_t; +#include "fp_fixint_impl.inc" + COMPILER_RT_ABI di_int -__fixsfdi(float a) -{ - float_bits fb; - fb.f = a; - int e = ((fb.u & 0x7F800000) >> 23) - 127; - if (e < 0) - return 0; - di_int s = (si_int)(fb.u & 0x80000000) >> 31; - di_int r = (fb.u & 0x007FFFFF) | 0x00800000; - if (e > 23) - r <<= (e - 23); - else - r >>= (23 - e); - return (r ^ s) - s; +__fixsfdi(fp_t a) { + return __fixint(a); } diff --git a/contrib/compiler-rt/lib/builtins/fixsfsi.c b/contrib/compiler-rt/lib/builtins/fixsfsi.c index e3cc42d5255a..f045536d6857 100644 --- a/contrib/compiler-rt/lib/builtins/fixsfsi.c +++ b/contrib/compiler-rt/lib/builtins/fixsfsi.c @@ -1,47 +1,22 @@ -//===-- lib/fixsfsi.c - Single-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 single-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. -// -//===----------------------------------------------------------------------===// +/* ===-- fixsfsi.c - Implement __fixsfsi -----------------------------------=== + * + * 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. + * + * ===----------------------------------------------------------------------=== + */ #define SINGLE_PRECISION #include "fp_lib.h" +typedef si_int fixint_t; +typedef su_int fixuint_t; +#include "fp_fixint_impl.inc" ARM_EABI_FNALIAS(f2iz, fixsfsi) -COMPILER_RT_ABI int +COMPILER_RT_ABI si_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 __fixint(a); } diff --git a/contrib/compiler-rt/lib/builtins/fixsfti.c b/contrib/compiler-rt/lib/builtins/fixsfti.c index 6a1a1c6d5465..3a159b3e18e4 100644 --- a/contrib/compiler-rt/lib/builtins/fixsfti.c +++ b/contrib/compiler-rt/lib/builtins/fixsfti.c @@ -6,40 +6,21 @@ * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== - * - * This file implements __fixsfti for the compiler_rt library. - * - * ===----------------------------------------------------------------------=== */ #include "int_lib.h" #ifdef CRT_HAS_128BIT +#define SINGLE_PRECISION +#include "fp_lib.h" -/* Returns: convert a to a signed long long, rounding toward zero. */ - -/* Assumption: float is a IEEE 32 bit floating point type - * su_int is a 32 bit integral type - * value in float is representable in ti_int (no range checking performed) - */ - -/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */ +typedef ti_int fixint_t; +typedef tu_int fixuint_t; +#include "fp_fixint_impl.inc" COMPILER_RT_ABI ti_int -__fixsfti(float a) -{ - float_bits fb; - fb.f = a; - int e = ((fb.u & 0x7F800000) >> 23) - 127; - if (e < 0) - return 0; - ti_int s = (si_int)(fb.u & 0x80000000) >> 31; - ti_int r = (fb.u & 0x007FFFFF) | 0x00800000; - if (e > 23) - r <<= (e - 23); - else - r >>= (23 - e); - return (r ^ s) - s; +__fixsfti(fp_t a) { + return __fixint(a); } #endif /* CRT_HAS_128BIT */ diff --git a/contrib/compiler-rt/lib/builtins/fixtfdi.c b/contrib/compiler-rt/lib/builtins/fixtfdi.c new file mode 100644 index 000000000000..bc9dea1f4f81 --- /dev/null +++ b/contrib/compiler-rt/lib/builtins/fixtfdi.c @@ -0,0 +1,23 @@ +/* ===-- fixtfdi.c - Implement __fixtfdi -----------------------------------=== + * + * 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. + * + * ===----------------------------------------------------------------------=== + */ + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +typedef di_int fixint_t; +typedef du_int fixuint_t; +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI di_int +__fixtfdi(fp_t a) { + return __fixint(a); +} +#endif diff --git a/contrib/compiler-rt/lib/builtins/fixtfsi.c b/contrib/compiler-rt/lib/builtins/fixtfsi.c new file mode 100644 index 000000000000..feb3de885090 --- /dev/null +++ b/contrib/compiler-rt/lib/builtins/fixtfsi.c @@ -0,0 +1,23 @@ +/* ===-- fixtfsi.c - Implement __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. + * + * ===----------------------------------------------------------------------=== + */ + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +typedef si_int fixint_t; +typedef su_int fixuint_t; +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI si_int +__fixtfsi(fp_t a) { + return __fixint(a); +} +#endif diff --git a/contrib/compiler-rt/lib/builtins/fixtfti.c b/contrib/compiler-rt/lib/builtins/fixtfti.c new file mode 100644 index 000000000000..ee4ada85cb4a --- /dev/null +++ b/contrib/compiler-rt/lib/builtins/fixtfti.c @@ -0,0 +1,23 @@ +/* ===-- fixtfti.c - Implement __fixtfti -----------------------------------=== + * + * 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. + * + * ===----------------------------------------------------------------------=== + */ + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +typedef ti_int fixint_t; +typedef tu_int fixuint_t; +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI ti_int +__fixtfti(fp_t a) { + return __fixint(a); +} +#endif diff --git a/contrib/compiler-rt/lib/builtins/fixunsdfdi.c b/contrib/compiler-rt/lib/builtins/fixunsdfdi.c index 9e6371390d5c..f4f689e3993f 100644 --- a/contrib/compiler-rt/lib/builtins/fixunsdfdi.c +++ b/contrib/compiler-rt/lib/builtins/fixunsdfdi.c @@ -6,42 +6,16 @@ * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== - * - * This file implements __fixunsdfdi for the compiler_rt library. - * - * ===----------------------------------------------------------------------=== */ -#include "int_lib.h" - -/* Returns: convert a to a unsigned long long, rounding toward zero. - * Negative values all become zero. - */ - -/* Assumption: double is a IEEE 64 bit floating point type - * du_int is a 64 bit integral type - * value in double is representable in du_int or is negative - * (no range checking performed) - */ - -/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ +#define DOUBLE_PRECISION +#include "fp_lib.h" +typedef du_int fixuint_t; +#include "fp_fixuint_impl.inc" ARM_EABI_FNALIAS(d2ulz, fixunsdfdi) COMPILER_RT_ABI du_int -__fixunsdfdi(double a) -{ - double_bits fb; - fb.f = a; - int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023; - if (e < 0 || (fb.u.s.high & 0x80000000)) - return 0; - udwords r; - r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000; - r.s.low = fb.u.s.low; - if (e > 52) - r.all <<= (e - 52); - else - r.all >>= (52 - e); - return r.all; +__fixunsdfdi(fp_t a) { + return __fixuint(a); } diff --git a/contrib/compiler-rt/lib/builtins/fixunsdfsi.c b/contrib/compiler-rt/lib/builtins/fixunsdfsi.c index c6a3c755e90f..232d342d77da 100644 --- a/contrib/compiler-rt/lib/builtins/fixunsdfsi.c +++ b/contrib/compiler-rt/lib/builtins/fixunsdfsi.c @@ -6,39 +6,16 @@ * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== - * - * This file implements __fixunsdfsi for the compiler_rt library. - * - * ===----------------------------------------------------------------------=== */ -#include "int_lib.h" - -/* Returns: convert a to a unsigned int, rounding toward zero. - * Negative values all become zero. - */ - -/* Assumption: double is a IEEE 64 bit floating point type - * su_int is a 32 bit integral type - * value in double is representable in su_int or is negative - * (no range checking performed) - */ - -/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ +#define DOUBLE_PRECISION +#include "fp_lib.h" +typedef su_int fixuint_t; +#include "fp_fixuint_impl.inc" ARM_EABI_FNALIAS(d2uiz, fixunsdfsi) COMPILER_RT_ABI su_int -__fixunsdfsi(double a) -{ - double_bits fb; - fb.f = a; - int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023; - if (e < 0 || (fb.u.s.high & 0x80000000)) - return 0; - return ( - 0x80000000u | - ((fb.u.s.high & 0x000FFFFF) << 11) | - (fb.u.s.low >> 21) - ) >> (31 - e); +__fixunsdfsi(fp_t a) { + return __fixuint(a); } diff --git a/contrib/compiler-rt/lib/builtins/fixunsdfti.c b/contrib/compiler-rt/lib/builtins/fixunsdfti.c index cc6c84ff5cb5..c3d7df97fbd8 100644 --- a/contrib/compiler-rt/lib/builtins/fixunsdfti.c +++ b/contrib/compiler-rt/lib/builtins/fixunsdfti.c @@ -6,42 +6,18 @@ * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== - * - * This file implements __fixunsdfti for the compiler_rt library. - * - * ===----------------------------------------------------------------------=== */ #include "int_lib.h" #ifdef CRT_HAS_128BIT - -/* Returns: convert a to a unsigned long long, rounding toward zero. - * Negative values all become zero. - */ - -/* Assumption: double is a IEEE 64 bit floating point type - * tu_int is a 64 bit integral type - * value in double is representable in tu_int or is negative - * (no range checking performed) - */ - -/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ +#define DOUBLE_PRECISION +#include "fp_lib.h" +typedef tu_int fixuint_t; +#include "fp_fixuint_impl.inc" COMPILER_RT_ABI tu_int -__fixunsdfti(double a) -{ - double_bits fb; - fb.f = a; - int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023; - if (e < 0 || (fb.u.s.high & 0x80000000)) - return 0; - tu_int r = 0x0010000000000000uLL | (fb.u.all & 0x000FFFFFFFFFFFFFuLL); - if (e > 52) - r <<= (e - 52); - else - r >>= (52 - e); - return r; +__fixunsdftti(fp_t a) { + return __fixuint(a); } - #endif /* CRT_HAS_128BIT */ diff --git a/contrib/compiler-rt/lib/builtins/fixunssfdi.c b/contrib/compiler-rt/lib/builtins/fixunssfdi.c index 69d5952e9607..cd21cfd1859b 100644 --- a/contrib/compiler-rt/lib/builtins/fixunssfdi.c +++ b/contrib/compiler-rt/lib/builtins/fixunssfdi.c @@ -6,39 +6,16 @@ * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== - * - * This file implements __fixunssfdi for the compiler_rt library. - * - * ===----------------------------------------------------------------------=== */ -#include "int_lib.h" -/* Returns: convert a to a unsigned long long, rounding toward zero. - * Negative values all become zero. - */ - -/* Assumption: float is a IEEE 32 bit floating point type - * du_int is a 64 bit integral type - * value in float is representable in du_int or is negative - * (no range checking performed) - */ - -/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */ +#define SINGLE_PRECISION +#include "fp_lib.h" +typedef du_int fixuint_t; +#include "fp_fixuint_impl.inc" ARM_EABI_FNALIAS(f2ulz, fixunssfdi) COMPILER_RT_ABI du_int -__fixunssfdi(float a) -{ - float_bits fb; - fb.f = a; - int e = ((fb.u & 0x7F800000) >> 23) - 127; - if (e < 0 || (fb.u & 0x80000000)) - return 0; - du_int r = (fb.u & 0x007FFFFF) | 0x00800000; - if (e > 23) - r <<= (e - 23); - else - r >>= (23 - e); - return r; +__fixunssfdi(fp_t a) { + return __fixuint(a); } diff --git a/contrib/compiler-rt/lib/builtins/fixunssfsi.c b/contrib/compiler-rt/lib/builtins/fixunssfsi.c index e034139ea277..cc2b05bd84f8 100644 --- a/contrib/compiler-rt/lib/builtins/fixunssfsi.c +++ b/contrib/compiler-rt/lib/builtins/fixunssfsi.c @@ -12,34 +12,14 @@ * ===----------------------------------------------------------------------=== */ -#include "int_lib.h" - -/* Returns: convert a to a unsigned int, rounding toward zero. - * Negative values all become zero. - */ - -/* Assumption: float is a IEEE 32 bit floating point type - * su_int is a 32 bit integral type - * value in float is representable in su_int or is negative - * (no range checking performed) - */ - -/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */ +#define SINGLE_PRECISION +#include "fp_lib.h" +typedef su_int fixuint_t; +#include "fp_fixuint_impl.inc" ARM_EABI_FNALIAS(f2uiz, fixunssfsi) COMPILER_RT_ABI su_int -__fixunssfsi(float a) -{ - float_bits fb; - fb.f = a; - int e = ((fb.u & 0x7F800000) >> 23) - 127; - if (e < 0 || (fb.u & 0x80000000)) - return 0; - su_int r = (fb.u & 0x007FFFFF) | 0x00800000; - if (e > 23) - r <<= (e - 23); - else - r >>= (23 - e); - return r; +__fixunssfsi(fp_t a) { + return __fixuint(a); } diff --git a/contrib/compiler-rt/lib/builtins/fixunssfti.c b/contrib/compiler-rt/lib/builtins/fixunssfti.c index 4da9e242ad05..9593153745c5 100644 --- a/contrib/compiler-rt/lib/builtins/fixunssfti.c +++ b/contrib/compiler-rt/lib/builtins/fixunssfti.c @@ -12,36 +12,12 @@ * ===----------------------------------------------------------------------=== */ -#include "int_lib.h" - -#ifdef CRT_HAS_128BIT - -/* Returns: convert a to a unsigned long long, rounding toward zero. - * Negative values all become zero. - */ - -/* Assumption: float is a IEEE 32 bit floating point type - * tu_int is a 64 bit integral type - * value in float is representable in tu_int or is negative - * (no range checking performed) - */ - -/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */ +#if defined(CRT_HAS_128BIT) +typedef tu_int fixuint_t; +#include "fp_fixuint_impl.inc" COMPILER_RT_ABI tu_int -__fixunssfti(float a) -{ - float_bits fb; - fb.f = a; - int e = ((fb.u & 0x7F800000) >> 23) - 127; - if (e < 0 || (fb.u & 0x80000000)) - return 0; - tu_int r = (fb.u & 0x007FFFFF) | 0x00800000; - if (e > 23) - r <<= (e - 23); - else - r >>= (23 - e); - return r; +__fixunssfti(fp_t a) { + return __fixuint(a); } - -#endif /* CRT_HAS_128BIT */ +#endif diff --git a/contrib/compiler-rt/lib/builtins/fixunstfdi.c b/contrib/compiler-rt/lib/builtins/fixunstfdi.c new file mode 100644 index 000000000000..b2995f65834a --- /dev/null +++ b/contrib/compiler-rt/lib/builtins/fixunstfdi.c @@ -0,0 +1,22 @@ +/* ===-- fixunstfdi.c - Implement __fixunstfdi -----------------------------=== + * + * 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. + * + * ===----------------------------------------------------------------------=== + */ + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +typedef du_int fixuint_t; +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI du_int +__fixunstfdi(fp_t a) { + return __fixuint(a); +} +#endif diff --git a/contrib/compiler-rt/lib/builtins/fixunstfsi.c b/contrib/compiler-rt/lib/builtins/fixunstfsi.c new file mode 100644 index 000000000000..b5d3f6a7d38d --- /dev/null +++ b/contrib/compiler-rt/lib/builtins/fixunstfsi.c @@ -0,0 +1,22 @@ +/* ===-- 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. + * + * ===----------------------------------------------------------------------=== + */ + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +typedef su_int fixuint_t; +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI su_int +__fixunstfsi(fp_t a) { + return __fixuint(a); +} +#endif diff --git a/contrib/compiler-rt/lib/builtins/fixunstfti.c b/contrib/compiler-rt/lib/builtins/fixunstfti.c new file mode 100644 index 000000000000..22ff9dfc0339 --- /dev/null +++ b/contrib/compiler-rt/lib/builtins/fixunstfti.c @@ -0,0 +1,22 @@ +/* ===-- 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. + * + * ===----------------------------------------------------------------------=== + */ + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +typedef tu_int fixuint_t; +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI tu_int +__fixunstfti(fp_t a) { + return __fixuint(a); +} +#endif diff --git a/contrib/compiler-rt/lib/builtins/fixunsxfdi.c b/contrib/compiler-rt/lib/builtins/fixunsxfdi.c index 7224d467e7c9..075304e78dc9 100644 --- a/contrib/compiler-rt/lib/builtins/fixunsxfdi.c +++ b/contrib/compiler-rt/lib/builtins/fixunsxfdi.c @@ -38,6 +38,8 @@ __fixunsxfdi(long double a) int e = (fb.u.high.s.low & 0x00007FFF) - 16383; if (e < 0 || (fb.u.high.s.low & 0x00008000)) return 0; + if ((unsigned)e > sizeof(du_int) * CHAR_BIT) + return ~(du_int)0; return fb.u.low.all >> (63 - e); } diff --git a/contrib/compiler-rt/lib/builtins/fixunsxfsi.c b/contrib/compiler-rt/lib/builtins/fixunsxfsi.c index df0a18e2c1ab..c3c70f743de8 100644 --- a/contrib/compiler-rt/lib/builtins/fixunsxfsi.c +++ b/contrib/compiler-rt/lib/builtins/fixunsxfsi.c @@ -23,7 +23,6 @@ /* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes * su_int is a 32 bit integral type * value in long double is representable in su_int or is negative - * (no range checking performed) */ /* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee | @@ -38,6 +37,8 @@ __fixunsxfsi(long double a) int e = (fb.u.high.s.low & 0x00007FFF) - 16383; if (e < 0 || (fb.u.high.s.low & 0x00008000)) return 0; + if ((unsigned)e > sizeof(su_int) * CHAR_BIT) + return ~(su_int)0; return fb.u.low.s.high >> (31 - e); } diff --git a/contrib/compiler-rt/lib/builtins/fixunsxfti.c b/contrib/compiler-rt/lib/builtins/fixunsxfti.c index 42e507304718..fb39d00ff5b2 100644 --- a/contrib/compiler-rt/lib/builtins/fixunsxfti.c +++ b/contrib/compiler-rt/lib/builtins/fixunsxfti.c @@ -21,9 +21,8 @@ */ /* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes - * tu_int is a 64 bit integral type + * tu_int is a 128 bit integral type * value in long double is representable in tu_int or is negative - * (no range checking performed) */ /* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee | @@ -38,6 +37,8 @@ __fixunsxfti(long double a) int e = (fb.u.high.s.low & 0x00007FFF) - 16383; if (e < 0 || (fb.u.high.s.low & 0x00008000)) return 0; + if ((unsigned)e > sizeof(tu_int) * CHAR_BIT) + return ~(tu_int)0; tu_int r = fb.u.low.all; if (e > 63) r <<= (e - 63); diff --git a/contrib/compiler-rt/lib/builtins/fixxfdi.c b/contrib/compiler-rt/lib/builtins/fixxfdi.c index afc79d8664d8..011787f9e4b4 100644 --- a/contrib/compiler-rt/lib/builtins/fixxfdi.c +++ b/contrib/compiler-rt/lib/builtins/fixxfdi.c @@ -19,7 +19,7 @@ /* Returns: convert a to a signed long long, rounding toward zero. */ /* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes - * su_int is a 32 bit integral type + * di_int is a 64 bit integral type * value in long double is representable in di_int (no range checking performed) */ @@ -30,11 +30,15 @@ COMPILER_RT_ABI di_int __fixxfdi(long double a) { + const di_int di_max = (di_int)((~(du_int)0) / 2); + const di_int di_min = -di_max - 1; long_double_bits fb; fb.f = a; int e = (fb.u.high.s.low & 0x00007FFF) - 16383; if (e < 0) return 0; + if ((unsigned)e >= sizeof(di_int) * CHAR_BIT) + return a > 0 ? di_max : di_min; di_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15); di_int r = fb.u.low.all; r = (du_int)r >> (63 - e); diff --git a/contrib/compiler-rt/lib/builtins/fixxfti.c b/contrib/compiler-rt/lib/builtins/fixxfti.c index 3d0a279b3842..968a4f0d5eea 100644 --- a/contrib/compiler-rt/lib/builtins/fixxfti.c +++ b/contrib/compiler-rt/lib/builtins/fixxfti.c @@ -19,8 +19,8 @@ /* Returns: convert a to a signed long long, rounding toward zero. */ /* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes - * su_int is a 32 bit integral type - * value in long double is representable in ti_int (no range checking performed) + * ti_int is a 128 bit integral type + * value in long double is representable in ti_int */ /* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee | @@ -30,6 +30,8 @@ COMPILER_RT_ABI ti_int __fixxfti(long double a) { + const ti_int ti_max = (ti_int)((~(tu_int)0) / 2); + const ti_int ti_min = -ti_max - 1; long_double_bits fb; fb.f = a; int e = (fb.u.high.s.low & 0x00007FFF) - 16383; @@ -37,6 +39,8 @@ __fixxfti(long double a) return 0; ti_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15); ti_int r = fb.u.low.all; + if ((unsigned)e >= sizeof(ti_int) * CHAR_BIT) + return a > 0 ? ti_max : ti_min; if (e > 63) r <<= (e - 63); else diff --git a/contrib/compiler-rt/lib/builtins/fp_fixint_impl.inc b/contrib/compiler-rt/lib/builtins/fp_fixint_impl.inc new file mode 100644 index 000000000000..035e87ca10e0 --- /dev/null +++ b/contrib/compiler-rt/lib/builtins/fp_fixint_impl.inc @@ -0,0 +1,41 @@ +//===-- 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. +// +//===----------------------------------------------------------------------===// + +#include "fp_lib.h" + +static inline fixint_t __fixint(fp_t a) { + const fixint_t fixint_max = (fixint_t)((~(fixuint_t)0) / 2); + const fixint_t fixint_min = -fixint_max - 1; + // Break a into sign, exponent, significand + const rep_t aRep = toRep(a); + const rep_t aAbs = aRep & absMask; + const fixint_t sign = aRep & signBit ? -1 : 1; + const int exponent = (aAbs >> significandBits) - exponentBias; + const rep_t significand = (aAbs & significandMask) | implicitBit; + + // If exponent is negative, the result is zero. + if (exponent < 0) + return 0; + + // If the value is too large for the integer type, saturate. + if ((unsigned)exponent >= sizeof(fixint_t) * CHAR_BIT) + return sign == 1 ? fixint_max : fixint_min; + + // If 0 <= exponent < significandBits, right shift to get the result. + // Otherwise, shift left. + if (exponent < significandBits) + return sign * (significand >> (significandBits - exponent)); + else + return sign * ((fixint_t)significand << (exponent - significandBits)); +} diff --git a/contrib/compiler-rt/lib/builtins/fp_fixuint_impl.inc b/contrib/compiler-rt/lib/builtins/fp_fixuint_impl.inc new file mode 100644 index 000000000000..5fefab0e2d8a --- /dev/null +++ b/contrib/compiler-rt/lib/builtins/fp_fixuint_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 unsigned integer conversion for the +// compiler-rt library. +// +//===----------------------------------------------------------------------===// + +#include "fp_lib.h" + +static inline fixuint_t __fixuint(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 either the value or the exponent is negative, the result is zero. + if (sign == -1 || exponent < 0) + return 0; + + // If the value is too large for the integer type, saturate. + if ((unsigned)exponent > sizeof(fixuint_t) * CHAR_BIT) + return ~(fixuint_t)0; + + // If 0 <= exponent < significandBits, right shift to get the result. + // Otherwise, shift left. + if (exponent < significandBits) + return significand >> (significandBits - exponent); + else + return (fixuint_t)significand << (exponent - significandBits); +} diff --git a/lib/libcompiler_rt/Makefile b/lib/libcompiler_rt/Makefile index e4eecbff7b24..d70549c6b19a 100644 --- a/lib/libcompiler_rt/Makefile +++ b/lib/libcompiler_rt/Makefile @@ -55,12 +55,18 @@ SRCF= absvdi2 \ fixdfti \ fixsfdi \ fixsfti \ + fixtfdi \ + fixtfsi \ + fixtfti \ fixunsdfdi \ fixunsdfsi \ fixunsdfti \ fixunssfdi \ fixunssfsi \ fixunssfti \ + fixunstfdi \ + fixunstfsi \ + fixunstfti \ fixunsxfdi \ fixunsxfsi \ fixunsxfti \