Index: lib/builtins/fixdfdi.c =================================================================== --- lib/builtins/fixdfdi.c +++ 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); +} Index: lib/builtins/fixdfsi.c =================================================================== --- lib/builtins/fixdfsi.c +++ 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); } Index: lib/builtins/fixdfti.c =================================================================== --- lib/builtins/fixdfti.c +++ 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 */ Index: lib/builtins/fixsfdi.c =================================================================== --- lib/builtins/fixsfdi.c +++ 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); } Index: lib/builtins/fixsfsi.c =================================================================== --- lib/builtins/fixsfsi.c +++ 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); } Index: lib/builtins/fixsfti.c =================================================================== --- lib/builtins/fixsfti.c +++ 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 */ Index: lib/builtins/fixtfdi.c =================================================================== --- lib/builtins/fixtfdi.c +++ 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_fixuint_impl.inc" + +COMPILER_RT_ABI di_int +__fixtfdi(fp_t a) { + return __fixint(a); +} +#endif Index: lib/builtins/fixtfsi.c =================================================================== --- lib/builtins/fixtfsi.c +++ 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_fixuint_impl.inc" + +COMPILER_RT_ABI si_int +__fixtfsi(fp_t a) { + return __fixint(a); +} +#endif Index: lib/builtins/fixtfti.c =================================================================== --- lib/builtins/fixtfti.c +++ 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_fixuint_impl.inc" + +COMPILER_RT_ABI ti_int +__fixtfti(fp_t a) { + return __fixint(a); +} +#endif Index: lib/builtins/fixunsdfdi.c =================================================================== --- lib/builtins/fixunsdfdi.c +++ 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); } Index: lib/builtins/fixunsdfsi.c =================================================================== --- lib/builtins/fixunsdfsi.c +++ 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); } Index: lib/builtins/fixunsdfti.c =================================================================== --- lib/builtins/fixunsdfti.c +++ 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 */ Index: lib/builtins/fixunssfdi.c =================================================================== --- lib/builtins/fixunssfdi.c +++ 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); } Index: lib/builtins/fixunssfsi.c =================================================================== --- lib/builtins/fixunssfsi.c +++ 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); } Index: lib/builtins/fixunssfti.c =================================================================== --- lib/builtins/fixunssfti.c +++ 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 Index: lib/builtins/fixunstfdi.c =================================================================== --- lib/builtins/fixunstfdi.c +++ 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 Index: lib/builtins/fixunstfsi.c =================================================================== --- lib/builtins/fixunstfsi.c +++ 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 Index: lib/builtins/fixunstfti.c =================================================================== --- lib/builtins/fixunstfti.c +++ 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 Index: lib/builtins/fixunsxfdi.c =================================================================== --- lib/builtins/fixunsxfdi.c +++ lib/builtins/fixunsxfdi.c @@ -38,6 +38,8 @@ 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); } Index: lib/builtins/fixunsxfsi.c =================================================================== --- lib/builtins/fixunsxfsi.c +++ 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 @@ 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); } Index: lib/builtins/fixunsxfti.c =================================================================== --- lib/builtins/fixunsxfti.c +++ 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 @@ int e = (fb.u.high.s.low & 0x00007FFF) - 16383; if (e < 0 || (fb.u.high.s.low & 0x00008000)) return 0; + if (e > sizeof(tu_int) * CHAR_BIT) + return ~(tu_int)0; tu_int r = fb.u.low.all; if (e > 63) r <<= (e - 63); Index: lib/builtins/fixxfdi.c =================================================================== --- lib/builtins/fixxfdi.c +++ 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); Index: lib/builtins/fixxfti.c =================================================================== --- lib/builtins/fixxfti.c +++ 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 @@ return 0; ti_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15); ti_int r = fb.u.low.all; + if (exponent >= sizeof(ti_int) * CHAR_BIT) + return a > 0 ? ti_max : ti_min; if (e > 63) r <<= (e - 63); else Index: lib/builtins/fp_fixint_impl.inc =================================================================== --- lib/builtins/fp_fixint_impl.inc +++ 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)); +} Index: lib/builtins/fp_fixuint_impl.inc =================================================================== --- lib/builtins/fp_fixuint_impl.inc +++ 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); +} 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; +}