diff options
Diffstat (limited to 'lib/builtins')
45 files changed, 754 insertions, 386 deletions
diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt index 4d102c615003..98d518a83e2c 100644 --- a/lib/builtins/CMakeLists.txt +++ b/lib/builtins/CMakeLists.txt @@ -44,6 +44,7 @@ set(GENERIC_SOURCES    enable_execute_stack.c    eprintf.c    extendsfdf2.c +  extendhfsf2.c    ffsdi2.c    ffsti2.c    fixdfdi.c @@ -123,7 +124,9 @@ set(GENERIC_SOURCES    subvti3.c    subtf3.c    trampoline_setup.c +  truncdfhf2.c    truncdfsf2.c +  truncsfhf2.c    ucmpdi2.c    ucmpti2.c    udivdi3.c @@ -151,6 +154,12 @@ set(x86_64_SOURCES    x86_64/floatundixf.S    ${GENERIC_SOURCES}) +if(WIN32) +  set(x86_64_SOURCES +      ${x86_64_SOURCES} +      x86_64/chkstk.S) +endif() +  set(i386_SOURCES    i386/ashldi3.S    i386/ashrdi3.S @@ -168,6 +177,12 @@ set(i386_SOURCES    i386/umoddi3.S    ${GENERIC_SOURCES}) +if(WIN32) +  set(i386_SOURCES +      ${i386_SOURCES} +      i386/chkstk.S) +endif() +  set(i686_SOURCES    ${i386_SOURCES}) @@ -257,7 +272,7 @@ set(arm_SOURCES  add_custom_target(builtins) -if (NOT WIN32) +if (NOT WIN32 OR MINGW)    foreach (arch x86_64 i386 i686 arm)      if (CAN_TARGET_${arch})        # Filter out generic versions of routines that are re-implemented in diff --git a/lib/builtins/atomic_flag_clear.c b/lib/builtins/atomic_flag_clear.c new file mode 100644 index 000000000000..15984cd5267d --- /dev/null +++ b/lib/builtins/atomic_flag_clear.c @@ -0,0 +1,19 @@ +/*===-- atomic_flag_clear.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 atomic_flag_clear from C11's stdatomic.h. + * + *===------------------------------------------------------------------------=== + */ + +#include <stdatomic.h> +#undef atomic_flag_clear +void atomic_flag_clear(volatile atomic_flag *object) { +  return __c11_atomic_store(&(object)->_Value, 0, __ATOMIC_SEQ_CST); +} diff --git a/lib/builtins/atomic_flag_clear_explicit.c b/lib/builtins/atomic_flag_clear_explicit.c new file mode 100644 index 000000000000..0f7859c2cd82 --- /dev/null +++ b/lib/builtins/atomic_flag_clear_explicit.c @@ -0,0 +1,20 @@ +/*===-- atomic_flag_clear_explicit.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 atomic_flag_clear_explicit from C11's stdatomic.h. + * + *===------------------------------------------------------------------------=== + */ + +#include <stdatomic.h> +#undef atomic_flag_clear_explicit +void atomic_flag_clear_explicit(volatile atomic_flag *object, +                                memory_order order) { +  return __c11_atomic_store(&(object)->_Value, 0, order); +} diff --git a/lib/builtins/atomic_flag_test_and_set.c b/lib/builtins/atomic_flag_test_and_set.c new file mode 100644 index 000000000000..07209fc02d5e --- /dev/null +++ b/lib/builtins/atomic_flag_test_and_set.c @@ -0,0 +1,19 @@ +/*===-- atomic_flag_test_and_set.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 atomic_flag_test_and_set from C11's stdatomic.h. + * + *===------------------------------------------------------------------------=== + */ + +#include <stdatomic.h> +#undef atomic_flag_test_and_set +_Bool atomic_flag_test_and_set(volatile atomic_flag *object) { +  return __c11_atomic_exchange(&(object)->_Value, 1, __ATOMIC_SEQ_CST); +} diff --git a/lib/builtins/atomic_flag_test_and_set_explicit.c b/lib/builtins/atomic_flag_test_and_set_explicit.c new file mode 100644 index 000000000000..eaa5be08df46 --- /dev/null +++ b/lib/builtins/atomic_flag_test_and_set_explicit.c @@ -0,0 +1,20 @@ +/*===-- atomic_flag_test_and_set_explicit.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 atomic_flag_test_and_set_explicit from C11's stdatomic.h + * + *===------------------------------------------------------------------------=== + */ + +#include <stdatomic.h> +#undef atomic_flag_test_and_set_explicit +_Bool atomic_flag_test_and_set_explicit(volatile atomic_flag *object, +                                        memory_order order) { +  return __c11_atomic_exchange(&(object)->_Value, 1, order); +} diff --git a/lib/builtins/atomic_signal_fence.c b/lib/builtins/atomic_signal_fence.c new file mode 100644 index 000000000000..ad292d2f1c72 --- /dev/null +++ b/lib/builtins/atomic_signal_fence.c @@ -0,0 +1,19 @@ +/*===-- atomic_signal_fence.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 atomic_signal_fence from C11's stdatomic.h. + * + *===------------------------------------------------------------------------=== + */ + +#include <stdatomic.h> +#undef atomic_signal_fence +void atomic_signal_fence(memory_order order) { +  __c11_atomic_signal_fence(order); +} diff --git a/lib/builtins/atomic_thread_fence.c b/lib/builtins/atomic_thread_fence.c new file mode 100644 index 000000000000..71f698c9de75 --- /dev/null +++ b/lib/builtins/atomic_thread_fence.c @@ -0,0 +1,19 @@ +/*===-- atomic_thread_fence.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 atomic_thread_fence from C11's stdatomic.h. + * + *===------------------------------------------------------------------------=== + */ + +#include <stdatomic.h> +#undef atomic_thread_fence +void atomic_thread_fence(memory_order order) { +  __c11_atomic_thread_fence(order); +} diff --git a/lib/builtins/clear_cache.c b/lib/builtins/clear_cache.c index 8dc0fb1c5907..ede7659a051d 100644 --- a/lib/builtins/clear_cache.c +++ b/lib/builtins/clear_cache.c @@ -9,11 +9,12 @@   */  #include "int_lib.h" +#include <stddef.h>  #if __APPLE__    #include <libkern/OSCacheControl.h>  #endif -#if defined(__FreeBSD__) && defined(__arm__) +#if (defined(__FreeBSD__) || defined(__Bitrig__)) && defined(__arm__)    #include <sys/types.h>    #include <machine/sysarch.h>  #endif @@ -25,6 +26,7 @@  #if defined(__mips__)    #include <sys/cachectl.h>    #include <sys/syscall.h> +  #include <unistd.h>    #if defined(__ANDROID__) && defined(__LP64__)      /*       * clear_mips_cache - Invalidates instruction cache for Mips. @@ -89,7 +91,7 @@ void __clear_cache(void *start, void *end) {   * so there is nothing to do   */  #elif defined(__arm__) && !defined(__APPLE__) -    #if defined(__FreeBSD__) || defined(__NetBSD__) +    #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__Bitrig__)          struct arm_sync_icache_args arg;          arg.addr = (uintptr_t)start; @@ -126,6 +128,7 @@ void __clear_cache(void *start, void *end) {  #elif defined(__aarch64__) && !defined(__APPLE__)    uint64_t xstart = (uint64_t)(uintptr_t) start;    uint64_t xend = (uint64_t)(uintptr_t) end; +  uint64_t addr;    // Get Cache Type Info    uint64_t ctr_el0; @@ -136,12 +139,12 @@ void __clear_cache(void *start, void *end) {     * uintptr_t in case this runs in an IPL32 environment.     */    const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15); -  for (uint64_t addr = xstart; addr < xend; addr += dcache_line_size) +  for (addr = xstart; addr < xend; addr += dcache_line_size)      __asm __volatile("dc cvau, %0" :: "r"(addr));    __asm __volatile("dsb ish");    const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15); -  for (uint64_t addr = xstart; addr < xend; addr += icache_line_size) +  for (addr = xstart; addr < xend; addr += icache_line_size)      __asm __volatile("ic ivau, %0" :: "r"(addr));    __asm __volatile("isb sy");  #else diff --git a/lib/builtins/enable_execute_stack.c b/lib/builtins/enable_execute_stack.c index 63d836b31d17..23e494051adf 100644 --- a/lib/builtins/enable_execute_stack.c +++ b/lib/builtins/enable_execute_stack.c @@ -10,7 +10,9 @@  #include "int_lib.h" +#ifndef _WIN32  #include <sys/mman.h> +#endif  /* #include "config.h"   * FIXME: CMake - include when cmake system is ready. @@ -18,9 +20,14 @@   */  #define HAVE_SYSCONF 1 +#ifdef _WIN32 +#include <windef.h> +#include <winbase.h> +#else  #ifndef __APPLE__  #include <unistd.h>  #endif /* __APPLE__ */ +#endif /* _WIN32 */  #if __LP64__  	#define TRAMPOLINE_SIZE 48 @@ -40,6 +47,12 @@ COMPILER_RT_ABI void  __enable_execute_stack(void* addr)  { +#if _WIN32 +	MEMORY_BASIC_INFORMATION mbi; +	if (!VirtualQuery (addr, &mbi, sizeof(mbi))) +		return; /* We should probably assert here because there is no return value */ +	VirtualProtect (mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect); +#else  #if __APPLE__  	/* On Darwin, pagesize is always 4096 bytes */  	const uintptr_t pageSize = 4096; @@ -55,4 +68,5 @@ __enable_execute_stack(void* addr)  	unsigned char* endPage = (unsigned char*)((p+TRAMPOLINE_SIZE+pageSize) & pageAlignMask);  	size_t length = endPage - startPage;  	(void) mprotect((void *)startPage, length, PROT_READ | PROT_WRITE | PROT_EXEC); +#endif  } diff --git a/lib/builtins/extendhfsf2.c b/lib/builtins/extendhfsf2.c new file mode 100644 index 000000000000..7524e2ea7ed6 --- /dev/null +++ b/lib/builtins/extendhfsf2.c @@ -0,0 +1,23 @@ +//===-- lib/extendhfsf2.c - half -> single 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. +// +//===----------------------------------------------------------------------===// +// + +#define SRC_HALF +#define DST_SINGLE +#include "fp_extend_impl.inc" + +// Use a forwarding definition and noinline to implement a poor man's alias, +// as there isn't a good cross-platform way of defining one. +COMPILER_RT_ABI __attribute__((noinline)) float __extendhfsf2(uint16_t a) { +    return __extendXfYf2__(a); +} + +COMPILER_RT_ABI float __gnu_h2f_ieee(uint16_t a) { +    return __extendhfsf2(a); +} diff --git a/lib/builtins/fixdfdi.c b/lib/builtins/fixdfdi.c index 86f9f6ce8db3..14283ef42e61 100644 --- a/lib/builtins/fixdfdi.c +++ b/lib/builtins/fixdfdi.c @@ -6,40 +6,41 @@   * 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. */ +#define DOUBLE_PRECISION +#include "fp_lib.h" +ARM_EABI_FNALIAS(d2lz, fixdfdi) -/* 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) +#ifndef __SOFT_FP__ +/* Support for systems that have hardware floating-point; can set the invalid + * flag as a side-effect of computation.   */ -/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ - -ARM_EABI_FNALIAS(d2lz, fixdfdi) +COMPILER_RT_ABI du_int __fixunsdfdi(double a);  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; -}  +    if (a < 0.0) { +        return -__fixunsdfdi(-a); +    } +    return __fixunsdfdi(a); +} + +#else +/* Support for systems that don't have hardware floating-point; there are no + * flags to set, and we don't want to code-gen to an unknown soft-float + * implementation. + */ + +typedef di_int fixint_t; +typedef du_int fixuint_t; +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI di_int +__fixdfdi(fp_t a) { +    return __fixint(a); +} + +#endif diff --git a/lib/builtins/fixdfsi.c b/lib/builtins/fixdfsi.c index 88b2ff5e74a0..704e65bc43a1 100644 --- a/lib/builtins/fixdfsi.c +++ b/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/lib/builtins/fixdfti.c b/lib/builtins/fixdfti.c index 2c27f4bae3b9..aaf225e74f86 100644 --- a/lib/builtins/fixdfti.c +++ b/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/lib/builtins/fixsfdi.c b/lib/builtins/fixsfdi.c index 4f6cfdd7a5c6..fab47e272a25 100644 --- a/lib/builtins/fixsfdi.c +++ b/lib/builtins/fixsfdi.c @@ -1,43 +1,47 @@  /* ===-- 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" +#define SINGLE_PRECISION +#include "fp_lib.h" -/* Returns: convert a to a signed long long, rounding toward zero. */ +ARM_EABI_FNALIAS(f2lz, fixsfdi) -/* 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) +#ifndef __SOFT_FP__ +/* Support for systems that have hardware floating-point; can set the invalid + * flag as a side-effect of computation.   */ -/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */ - -ARM_EABI_FNALIAS(f2lz, fixsfdi) +COMPILER_RT_ABI du_int __fixunssfdi(float a);  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; +    if (a < 0.0f) { +        return -__fixunssfdi(-a); +    } +    return __fixunssfdi(a);  } + +#else +/* Support for systems that don't have hardware floating-point; there are no + * flags to set, and we don't want to code-gen to an unknown soft-float + * implementation. + */ + +typedef di_int fixint_t; +typedef du_int fixuint_t; +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI di_int +__fixsfdi(fp_t a) { +    return __fixint(a); +} + +#endif diff --git a/lib/builtins/fixsfsi.c b/lib/builtins/fixsfsi.c index e3cc42d5255a..f045536d6857 100644 --- a/lib/builtins/fixsfsi.c +++ b/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/lib/builtins/fixsfti.c b/lib/builtins/fixsfti.c index 6a1a1c6d5465..3a159b3e18e4 100644 --- a/lib/builtins/fixsfti.c +++ b/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/lib/builtins/fixtfdi.c b/lib/builtins/fixtfdi.c new file mode 100644 index 000000000000..bc9dea1f4f81 --- /dev/null +++ b/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/lib/builtins/fixtfsi.c b/lib/builtins/fixtfsi.c new file mode 100644 index 000000000000..feb3de885090 --- /dev/null +++ b/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/lib/builtins/fixtfti.c b/lib/builtins/fixtfti.c new file mode 100644 index 000000000000..ee4ada85cb4a --- /dev/null +++ b/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/lib/builtins/fixunsdfdi.c b/lib/builtins/fixunsdfdi.c index 9e6371390d5c..2e0d87eacf05 100644 --- a/lib/builtins/fixunsdfdi.c +++ b/lib/builtins/fixunsdfdi.c @@ -6,42 +6,39 @@   * Source Licenses. See LICENSE.TXT for details.   *   * ===----------------------------------------------------------------------=== - * - * This file implements __fixunsdfdi for the compiler_rt library. - * - * ===----------------------------------------------------------------------===   */ -#include "int_lib.h" +#define DOUBLE_PRECISION +#include "fp_lib.h" -/* Returns: convert a to a unsigned long long, rounding toward zero. - *          Negative values all become zero. - */ +ARM_EABI_FNALIAS(d2ulz, fixunsdfdi) -/* 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) +#ifndef __SOFT_FP__ +/* Support for systems that have hardware floating-point; can set the invalid + * flag as a side-effect of computation.   */ -/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ - -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; +    if (a <= 0.0) return 0; +    su_int high = a/0x1p32f; +    su_int low = a - (double)high*0x1p32f; +    return ((du_int)high << 32) | low;  } + +#else +/* Support for systems that don't have hardware floating-point; there are no + * flags to set, and we don't want to code-gen to an unknown soft-float + * implementation. + */ + +typedef du_int fixuint_t; +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI du_int +__fixunsdfdi(fp_t a) { +    return __fixuint(a); +} + +#endif diff --git a/lib/builtins/fixunsdfsi.c b/lib/builtins/fixunsdfsi.c index c6a3c755e90f..232d342d77da 100644 --- a/lib/builtins/fixunsdfsi.c +++ b/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/lib/builtins/fixunsdfti.c b/lib/builtins/fixunsdfti.c index cc6c84ff5cb5..f8046a02632b 100644 --- a/lib/builtins/fixunsdfti.c +++ b/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; +__fixunsdfti(fp_t a) { +    return __fixuint(a);  } -  #endif /* CRT_HAS_128BIT */ diff --git a/lib/builtins/fixunssfdi.c b/lib/builtins/fixunssfdi.c index 69d5952e9607..5a154e82cff4 100644 --- a/lib/builtins/fixunssfdi.c +++ b/lib/builtins/fixunssfdi.c @@ -6,39 +6,40 @@   * 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"  ARM_EABI_FNALIAS(f2ulz, fixunssfdi) +#ifndef __SOFT_FP__ +/* Support for systems that have hardware floating-point; can set the invalid + * flag as a side-effect of computation. + */ +  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; +    if (a <= 0.0f) return 0; +    double da = a; +    su_int high = da/0x1p32f; +    su_int low = da - (double)high*0x1p32f; +    return ((du_int)high << 32) | low; +} + +#else +/* Support for systems that don't have hardware floating-point; there are no + * flags to set, and we don't want to code-gen to an unknown soft-float + * implementation. + */ + +typedef du_int fixuint_t; +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI du_int +__fixunssfdi(fp_t a) { +    return __fixuint(a);  } + +#endif diff --git a/lib/builtins/fixunssfsi.c b/lib/builtins/fixunssfsi.c index e034139ea277..cc2b05bd84f8 100644 --- a/lib/builtins/fixunssfsi.c +++ b/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/lib/builtins/fixunssfti.c b/lib/builtins/fixunssfti.c index 4da9e242ad05..862d7bd6c7af 100644 --- a/lib/builtins/fixunssfti.c +++ b/lib/builtins/fixunssfti.c @@ -12,36 +12,15 @@   * ===----------------------------------------------------------------------===   */ -#include "int_lib.h" +#define SINGLE_PRECISION +#include "fp_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/lib/builtins/fixunstfdi.c b/lib/builtins/fixunstfdi.c new file mode 100644 index 000000000000..b2995f65834a --- /dev/null +++ b/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/lib/builtins/fixunstfsi.c b/lib/builtins/fixunstfsi.c new file mode 100644 index 000000000000..b5d3f6a7d38d --- /dev/null +++ b/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/lib/builtins/fixunstfti.c b/lib/builtins/fixunstfti.c new file mode 100644 index 000000000000..22ff9dfc0339 --- /dev/null +++ b/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/lib/builtins/fixunsxfdi.c b/lib/builtins/fixunsxfdi.c index 7224d467e7c9..075304e78dc9 100644 --- a/lib/builtins/fixunsxfdi.c +++ b/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/lib/builtins/fixunsxfsi.c b/lib/builtins/fixunsxfsi.c index df0a18e2c1ab..c3c70f743de8 100644 --- a/lib/builtins/fixunsxfsi.c +++ b/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/lib/builtins/fixunsxfti.c b/lib/builtins/fixunsxfti.c index 42e507304718..fb39d00ff5b2 100644 --- a/lib/builtins/fixunsxfti.c +++ b/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/lib/builtins/fixxfdi.c b/lib/builtins/fixxfdi.c index afc79d8664d8..011787f9e4b4 100644 --- a/lib/builtins/fixxfdi.c +++ b/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/lib/builtins/fixxfti.c b/lib/builtins/fixxfti.c index 3d0a279b3842..968a4f0d5eea 100644 --- a/lib/builtins/fixxfti.c +++ b/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/lib/builtins/fp_extend.h b/lib/builtins/fp_extend.h index fff676eeca8c..5c2b92310df1 100644 --- a/lib/builtins/fp_extend.h +++ b/lib/builtins/fp_extend.h @@ -39,11 +39,24 @@ static inline int src_rep_t_clz(src_rep_t a) {  #endif  } +#elif defined SRC_HALF +typedef uint16_t src_t; +typedef uint16_t src_rep_t; +#define SRC_REP_C UINT16_C +static const int srcSigBits = 10; +#define src_rep_t_clz __builtin_clz +  #else -#error Source should be single precision or double precision! +#error Source should be half, single, or double precision!  #endif //end source precision -#if defined DST_DOUBLE +#if defined DST_SINGLE +typedef float dst_t; +typedef uint32_t dst_rep_t; +#define DST_REP_C UINT32_C +static const int dstSigBits = 23; + +#elif defined DST_DOUBLE  typedef double dst_t;  typedef uint64_t dst_rep_t;  #define DST_REP_C UINT64_C @@ -56,7 +69,7 @@ typedef __uint128_t dst_rep_t;  static const int dstSigBits = 112;  #else -#error Destination should be double precision or quad precision! +#error Destination should be single, double, or quad precision!  #endif //end destination precision  // End of specialization parameters.  Two helper routines for conversion to and diff --git a/lib/builtins/fp_extend_impl.inc b/lib/builtins/fp_extend_impl.inc index f6953ff4bfae..edcfa8d2329d 100644 --- a/lib/builtins/fp_extend_impl.inc +++ b/lib/builtins/fp_extend_impl.inc @@ -66,7 +66,9 @@ static inline dst_t __extendXfYf2__(src_t a) {      const src_rep_t sign = aRep & srcSignMask;      dst_rep_t absResult; -    if (aAbs - srcMinNormal < srcInfinity - srcMinNormal) { +    // If sizeof(src_rep_t) < sizeof(int), the subtraction result is promoted +    // to (signed) int.  To avoid that, explicitly cast to src_rep_t. +    if ((src_rep_t)(aAbs - srcMinNormal) < srcInfinity - srcMinNormal) {          // a is a normal number.          // Extend to the destination type by shifting the significand and          // exponent into the proper position and rebiasing the exponent. diff --git a/lib/builtins/fp_fixint_impl.inc b/lib/builtins/fp_fixint_impl.inc new file mode 100644 index 000000000000..035e87ca10e0 --- /dev/null +++ b/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/lib/builtins/fp_fixuint_impl.inc b/lib/builtins/fp_fixuint_impl.inc new file mode 100644 index 000000000000..5fefab0e2d8a --- /dev/null +++ b/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/builtins/fp_trunc.h b/lib/builtins/fp_trunc.h index 49a9aebbc67d..373ba1b0411d 100644 --- a/lib/builtins/fp_trunc.h +++ b/lib/builtins/fp_trunc.h @@ -16,7 +16,13 @@  #include "int_lib.h" -#if defined SRC_DOUBLE +#if defined SRC_SINGLE +typedef float src_t; +typedef uint32_t src_rep_t; +#define SRC_REP_C UINT32_C +static const int srcSigBits = 23; + +#elif defined SRC_DOUBLE  typedef double src_t;  typedef uint64_t src_rep_t;  #define SRC_REP_C UINT64_C @@ -44,6 +50,12 @@ typedef uint32_t dst_rep_t;  #define DST_REP_C UINT32_C  static const int dstSigBits = 23; +#elif defined DST_HALF +typedef uint16_t dst_t; +typedef uint16_t dst_rep_t; +#define DST_REP_C UINT16_C +static const int dstSigBits = 10; +  #else  #error Destination should be single precision or double precision!  #endif //end destination precision diff --git a/lib/builtins/fp_trunc_impl.inc b/lib/builtins/fp_trunc_impl.inc index 21bffae02bf4..372e8d6014dd 100644 --- a/lib/builtins/fp_trunc_impl.inc +++ b/lib/builtins/fp_trunc_impl.inc @@ -99,7 +99,7 @@ static inline dst_t __truncXfYf2__(src_t a) {          absResult |= dstQNaN;          absResult |= ((aAbs & srcNaNCode) >> (srcSigBits - dstSigBits)) & dstNaNCode;      } -    else if (aAbs > overflow) { +    else if (aAbs >= overflow) {          // a overflows to infinity.          absResult = (dst_rep_t)dstInfExp << dstSigBits;      } diff --git a/lib/builtins/i386/chkstk.S b/lib/builtins/i386/chkstk.S new file mode 100644 index 000000000000..3733d722ef19 --- /dev/null +++ b/lib/builtins/i386/chkstk.S @@ -0,0 +1,34 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +// _chkstk routine +// This routine is windows specific +// http://msdn.microsoft.com/en-us/library/ms648426.aspx + +#ifdef __i386__ + +.text +.balign 4 +DEFINE_COMPILERRT_FUNCTION(__chkstk_ms) +        push   %ecx +        push   %eax +        cmp    $0x1000,%eax +        lea    12(%esp),%ecx +        jb     1f +2: +        sub    $0x1000,%ecx +        orl    $0,(%ecx) +        sub    $0x1000,%eax +        cmp    $0x1000,%eax +        ja     2b +1: +        sub    %eax,%ecx +        orl    $0,(%ecx) +        pop    %eax +        pop    %ecx +        ret +END_COMPILERRT_FUNCTION(__chkstk_ms) + +#endif // __i386__ diff --git a/lib/builtins/int_endianness.h b/lib/builtins/int_endianness.h index 4b35bde079e8..7995ddbb953c 100644 --- a/lib/builtins/int_endianness.h +++ b/lib/builtins/int_endianness.h @@ -16,6 +16,20 @@  #ifndef INT_ENDIANNESS_H  #define INT_ENDIANNESS_H +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ +    defined(__ORDER_LITTLE_ENDIAN__) + +/* Clang and GCC provide built-in endianness definitions. */ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN    1 +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN    0 +#endif /* __BYTE_ORDER__ */ + +#else /* Compilers other than Clang or GCC. */ +  #if defined(__SVR4) && defined(__sun)  #include <sys/byteorder.h> @@ -84,18 +98,6 @@  /* .. */ -#if defined(__linux__) - -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define _YUGA_LITTLE_ENDIAN 0 -#define _YUGA_BIG_ENDIAN    1 -#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define _YUGA_LITTLE_ENDIAN 1 -#define _YUGA_BIG_ENDIAN    0 -#endif /* __BYTE_ORDER__ */ - -#endif /* GNU/Linux */ -  #if defined(_WIN32)  #define _YUGA_LITTLE_ENDIAN 1 @@ -103,6 +105,8 @@  #endif /* Windows */ +#endif /* Clang or GCC. */ +  /* . */  #if !defined(_YUGA_LITTLE_ENDIAN) || !defined(_YUGA_BIG_ENDIAN) diff --git a/lib/builtins/int_lib.h b/lib/builtins/int_lib.h index ff314da986f1..bca5d81d4414 100644 --- a/lib/builtins/int_lib.h +++ b/lib/builtins/int_lib.h @@ -28,7 +28,11 @@  # define COMPILER_RT_ABI __attribute__((pcs("aapcs")))  #else  # define ARM_EABI_FNALIAS(aeabi_name, name) -# define COMPILER_RT_ABI +# if defined(__arm__) && defined(_WIN32) +#   define COMPILER_RT_ABI __attribute__((pcs("aapcs"))) +# else +#   define COMPILER_RT_ABI +# endif  #endif  #if defined(__NetBSD__) && (defined(_KERNEL) || defined(_STANDALONE)) diff --git a/lib/builtins/truncdfhf2.c b/lib/builtins/truncdfhf2.c new file mode 100644 index 000000000000..0852df369625 --- /dev/null +++ b/lib/builtins/truncdfhf2.c @@ -0,0 +1,16 @@ +//===-- lib/truncdfhf2.c - double -> half 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. +// +//===----------------------------------------------------------------------===// + +#define SRC_DOUBLE +#define DST_HALF +#include "fp_trunc_impl.inc" + +COMPILER_RT_ABI uint16_t __truncdfhf2(double a) { +    return __truncXfYf2__(a); +} diff --git a/lib/builtins/truncsfhf2.c b/lib/builtins/truncsfhf2.c new file mode 100644 index 000000000000..381e590c342f --- /dev/null +++ b/lib/builtins/truncsfhf2.c @@ -0,0 +1,22 @@ +//===-- lib/truncsfhf2.c - single -> half 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. +// +//===----------------------------------------------------------------------===// + +#define SRC_SINGLE +#define DST_HALF +#include "fp_trunc_impl.inc" + +// Use a forwarding definition and noinline to implement a poor man's alias, +// as there isn't a good cross-platform way of defining one. +COMPILER_RT_ABI __attribute__((noinline)) uint16_t __truncsfhf2(float a) { +    return __truncXfYf2__(a); +} + +COMPILER_RT_ABI uint16_t __gnu_f2h_ieee(float a) { +    return __truncsfhf2(a); +} diff --git a/lib/builtins/x86_64/chkstk.S b/lib/builtins/x86_64/chkstk.S new file mode 100644 index 000000000000..5759e84498c6 --- /dev/null +++ b/lib/builtins/x86_64/chkstk.S @@ -0,0 +1,39 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +// _chkstk routine +// This routine is windows specific +// http://msdn.microsoft.com/en-us/library/ms648426.aspx + +// Notes from r227519 +// MSVC x64s __chkstk and cygmings ___chkstk_ms do not adjust %rsp +// themselves. It also does not clobber %rax so we can reuse it when +// adjusting %rsp. + +#ifdef __x86_64__ + +.text +.balign 4 +DEFINE_COMPILERRT_FUNCTION(___chkstk_ms) +        push   %rcx +        push   %rax +        cmp    $0x1000,%rax +        lea    24(%rsp),%rcx +        jb     1f +2: +        sub    $0x1000,%rcx +        orl    $0,(%rcx) +        sub    $0x1000,%rax +        cmp    $0x1000,%rax +        ja     2b +1: +        sub    %rax,%rcx +        orl    $0,(%rcx) +        pop    %rax +        pop    %rcx +        ret +END_COMPILERRT_FUNCTION(___chkstk_ms) + +#endif // __x86_64__  | 
