Index: compiler-rt/trunk/lib/builtins/CMakeLists.txt =================================================================== --- compiler-rt/trunk/lib/builtins/CMakeLists.txt +++ compiler-rt/trunk/lib/builtins/CMakeLists.txt @@ -270,10 +270,29 @@ arm/unordsf2vfp.S ${GENERIC_SOURCES}) +set(aarch64_SOURCES + comparetf2.c + extenddftf2.c + extendsftf2.c + fixtfdi.c + fixtfsi.c + fixtfti.c + fixunstfdi.c + fixunstfsi.c + fixunstfti.c + floatditf.c + floatsitf.c + floatunditf.c + floatunsitf.c + multc3.c + trunctfdf2.c + trunctfsf2.c + ${GENERIC_SOURCES}) + add_custom_target(builtins) if (NOT WIN32 OR MINGW) - foreach (arch x86_64 i386 i686 arm) + foreach (arch x86_64 i386 i686 arm aarch64) if (CAN_TARGET_${arch}) # Filter out generic versions of routines that are re-implemented in # architecture specific manner. This prevents multiple definitions of the Index: compiler-rt/trunk/lib/builtins/floatditf.c =================================================================== --- compiler-rt/trunk/lib/builtins/floatditf.c +++ compiler-rt/trunk/lib/builtins/floatditf.c @@ -0,0 +1,50 @@ +//===-- lib/floatditf.c - integer -> quad-precision 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 di_int to quad-precision conversion for the +// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even +// mode. +// +//===----------------------------------------------------------------------===// + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +COMPILER_RT_ABI fp_t __floatditf(di_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) + return fromRep(0); + + // All other cases begin by extracting the sign and absolute value of a + rep_t sign = 0; + du_int aAbs = (du_int)a; + if (a < 0) { + sign = signBit; + aAbs = ~(du_int)a + 1U; + } + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - __builtin_clzll(aAbs); + rep_t result; + + // Shift a into the significand field, rounding if it is a right-shift + const int shift = significandBits - exponent; + result = (rep_t)aAbs << shift ^ implicitBit; + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + // Insert the sign bit and return + return fromRep(result | sign); +} + +#endif Index: compiler-rt/trunk/lib/builtins/floatunditf.c =================================================================== --- compiler-rt/trunk/lib/builtins/floatunditf.c +++ compiler-rt/trunk/lib/builtins/floatunditf.c @@ -0,0 +1,40 @@ +//===-- lib/floatunditf.c - uint -> quad-precision 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 du_int to quad-precision conversion for the +// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even +// mode. +// +//===----------------------------------------------------------------------===// + +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) +COMPILER_RT_ABI fp_t __floatunditf(du_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) return fromRep(0); + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - __builtin_clzll(a); + rep_t result; + + // Shift a into the significand field and clear the implicit bit. + const int shift = significandBits - exponent; + result = (rep_t)a << shift ^ implicitBit; + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + return fromRep(result); +} + +#endif Index: compiler-rt/trunk/lib/builtins/multc3.c =================================================================== --- compiler-rt/trunk/lib/builtins/multc3.c +++ compiler-rt/trunk/lib/builtins/multc3.c @@ -0,0 +1,68 @@ +/* ===-- multc3.c - Implement __multc3 -------------------------------------=== + * + * 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 __multc3 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" +#include "int_math.h" + +/* Returns: the product of a + ib and c + id */ + +COMPILER_RT_ABI long double _Complex +__multc3(long double a, long double b, long double c, long double d) +{ + long double ac = a * c; + long double bd = b * d; + long double ad = a * d; + long double bc = b * c; + long double _Complex z; + __real__ z = ac - bd; + __imag__ z = ad + bc; + if (crt_isnan(__real__ z) && crt_isnan(__imag__ z)) { + int recalc = 0; + if (crt_isinf(a) || crt_isinf(b)) { + a = crt_copysignl(crt_isinf(a) ? 1 : 0, a); + b = crt_copysignl(crt_isinf(b) ? 1 : 0, b); + if (crt_isnan(c)) + c = crt_copysignl(0, c); + if (crt_isnan(d)) + d = crt_copysignl(0, d); + recalc = 1; + } + if (crt_isinf(c) || crt_isinf(d)) { + c = crt_copysignl(crt_isinf(c) ? 1 : 0, c); + d = crt_copysignl(crt_isinf(d) ? 1 : 0, d); + if (crt_isnan(a)) + a = crt_copysignl(0, a); + if (crt_isnan(b)) + b = crt_copysignl(0, b); + recalc = 1; + } + if (!recalc && (crt_isinf(ac) || crt_isinf(bd) || + crt_isinf(ad) || crt_isinf(bc))) { + if (crt_isnan(a)) + a = crt_copysignl(0, a); + if (crt_isnan(b)) + b = crt_copysignl(0, b); + if (crt_isnan(c)) + c = crt_copysignl(0, c); + if (crt_isnan(d)) + d = crt_copysignl(0, d); + recalc = 1; + } + if (recalc) { + __real__ z = CRT_INFINITY * (a * c - b * d); + __imag__ z = CRT_INFINITY * (a * d + b * c); + } + } + return z; +} Index: compiler-rt/trunk/test/builtins/Unit/floatditf_test.c =================================================================== --- compiler-rt/trunk/test/builtins/Unit/floatditf_test.c +++ compiler-rt/trunk/test/builtins/Unit/floatditf_test.c @@ -0,0 +1,69 @@ +//===-- floatditf_test.c - Test __floatditf -------------------------------===// +// +// 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 __floatditf for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include "int_lib.h" +#include +#include +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" + +// Returns: long integer converted to long double + +COMPILER_RT_ABI long double __floatditf(long long a); + +int test__floatditf(long long a, uint64_t expectedHi, uint64_t expectedLo) +{ + long double x = __floatditf(a); + int ret = compareResultLD(x, expectedHi, expectedLo); + + if (ret) + printf("error in __floatditf(%Ld) = %.20Lf, " + "expected %.20Lf\n", a, x, fromRep128(expectedHi, expectedLo)); + return ret; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__floatditf(0x7fffffffffffffff, UINT64_C(0x403dffffffffffff), UINT64_C(0xfffc000000000000))) + return 1; + if (test__floatditf(0x123456789abcdef1, UINT64_C(0x403b23456789abcd), UINT64_C(0xef10000000000000))) + return 1; + if (test__floatditf(0x2, UINT64_C(0x4000000000000000), UINT64_C(0x0))) + return 1; + if (test__floatditf(0x1, UINT64_C(0x3fff000000000000), UINT64_C(0x0))) + return 1; + if (test__floatditf(0x0, UINT64_C(0x0), UINT64_C(0x0))) + return 1; + if (test__floatditf(0xffffffffffffffff, UINT64_C(0xbfff000000000000), UINT64_C(0x0))) + return 1; + if (test__floatditf(0xfffffffffffffffe, UINT64_C(0xc000000000000000), UINT64_C(0x0))) + return 1; + if (test__floatditf(-0x123456789abcdef1, UINT64_C(0xc03b23456789abcd), UINT64_C(0xef10000000000000))) + return 1; + if (test__floatditf(0x8000000000000000, UINT64_C(0xc03e000000000000), UINT64_C(0x0))) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +} Index: compiler-rt/trunk/test/builtins/Unit/floatunditf_test.c =================================================================== --- compiler-rt/trunk/test/builtins/Unit/floatunditf_test.c +++ compiler-rt/trunk/test/builtins/Unit/floatunditf_test.c @@ -0,0 +1,67 @@ +//===-- floatunditf_test.c - Test __floatunditf ---------------------------===// +// +// 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 __floatunditf for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include "int_lib.h" +#include +#include +#include + +#if __LDBL_MANT_DIG__ == 113 + +#include "fp_test.h" + +// Returns: long integer converted to long double + +COMPILER_RT_ABI long double __floatunditf(unsigned long long a); + +int test__floatunditf(unsigned long long a, uint64_t expectedHi, uint64_t expectedLo) +{ + long double x = __floatunditf(a); + int ret = compareResultLD(x, expectedHi, expectedLo); + + if (ret) + printf("error in __floatunditf(%Lu) = %.20Lf, " + "expected %.20Lf\n", a, x, fromRep128(expectedHi, expectedLo)); + return ret; +} + +char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; + +#endif + +int main() +{ +#if __LDBL_MANT_DIG__ == 113 + if (test__floatunditf(0xffffffffffffffffULL, UINT64_C(0x403effffffffffff), UINT64_C(0xfffe000000000000))) + return 1; + if (test__floatunditf(0xfffffffffffffffeULL, UINT64_C(0x403effffffffffff), UINT64_C(0xfffc000000000000))) + return 1; + if (test__floatunditf(0x8000000000000000ULL, UINT64_C(0x403e000000000000), UINT64_C(0x0))) + return 1; + if (test__floatunditf(0x7fffffffffffffffULL, UINT64_C(0x403dffffffffffff), UINT64_C(0xfffc000000000000))) + return 1; + if (test__floatunditf(0x123456789abcdef1ULL, UINT64_C(0x403b23456789abcd), UINT64_C(0xef10000000000000))) + return 1; + if (test__floatunditf(0x2ULL, UINT64_C(0x4000000000000000), UINT64_C(0x0))) + return 1; + if (test__floatunditf(0x1ULL, UINT64_C(0x3fff000000000000), UINT64_C(0x0))) + return 1; + if (test__floatunditf(0x0ULL, UINT64_C(0x0), UINT64_C(0x0))) + return 1; + +#else + printf("skipped\n"); + +#endif + return 0; +} Index: compiler-rt/trunk/test/builtins/Unit/multc3_test.c =================================================================== --- compiler-rt/trunk/test/builtins/Unit/multc3_test.c +++ compiler-rt/trunk/test/builtins/Unit/multc3_test.c @@ -13,7 +13,7 @@ #include -#if _ARCH_PPC +#if _ARCH_PPC || __aarch64__ #include "int_lib.h" #include @@ -357,7 +357,7 @@ int main() { -#if _ARCH_PPC +#if _ARCH_PPC || __aarch64__ const unsigned N = sizeof(x) / sizeof(x[0]); unsigned i, j; for (i = 0; i < N; ++i)