aboutsummaryrefslogtreecommitdiff
path: root/lib/builtins
diff options
context:
space:
mode:
Diffstat (limited to 'lib/builtins')
-rw-r--r--lib/builtins/CMakeLists.txt17
-rw-r--r--lib/builtins/atomic_flag_clear.c19
-rw-r--r--lib/builtins/atomic_flag_clear_explicit.c20
-rw-r--r--lib/builtins/atomic_flag_test_and_set.c19
-rw-r--r--lib/builtins/atomic_flag_test_and_set_explicit.c20
-rw-r--r--lib/builtins/atomic_signal_fence.c19
-rw-r--r--lib/builtins/atomic_thread_fence.c19
-rw-r--r--lib/builtins/clear_cache.c11
-rw-r--r--lib/builtins/enable_execute_stack.c14
-rw-r--r--lib/builtins/extendhfsf2.c23
-rw-r--r--lib/builtins/fixdfdi.c57
-rw-r--r--lib/builtins/fixdfsi.c56
-rw-r--r--lib/builtins/fixdfti.c33
-rw-r--r--lib/builtins/fixsfdi.c54
-rw-r--r--lib/builtins/fixsfsi.c53
-rw-r--r--lib/builtins/fixsfti.c33
-rw-r--r--lib/builtins/fixtfdi.c23
-rw-r--r--lib/builtins/fixtfsi.c23
-rw-r--r--lib/builtins/fixtfti.c23
-rw-r--r--lib/builtins/fixunsdfdi.c55
-rw-r--r--lib/builtins/fixunsdfsi.c35
-rw-r--r--lib/builtins/fixunsdfti.c36
-rw-r--r--lib/builtins/fixunssfdi.c55
-rw-r--r--lib/builtins/fixunssfsi.c32
-rw-r--r--lib/builtins/fixunssfti.c37
-rw-r--r--lib/builtins/fixunstfdi.c22
-rw-r--r--lib/builtins/fixunstfsi.c22
-rw-r--r--lib/builtins/fixunstfti.c22
-rw-r--r--lib/builtins/fixunsxfdi.c2
-rw-r--r--lib/builtins/fixunsxfsi.c3
-rw-r--r--lib/builtins/fixunsxfti.c5
-rw-r--r--lib/builtins/fixxfdi.c6
-rw-r--r--lib/builtins/fixxfti.c8
-rw-r--r--lib/builtins/fp_extend.h19
-rw-r--r--lib/builtins/fp_extend_impl.inc4
-rw-r--r--lib/builtins/fp_fixint_impl.inc41
-rw-r--r--lib/builtins/fp_fixuint_impl.inc39
-rw-r--r--lib/builtins/fp_trunc.h14
-rw-r--r--lib/builtins/fp_trunc_impl.inc2
-rw-r--r--lib/builtins/i386/chkstk.S34
-rw-r--r--lib/builtins/int_endianness.h28
-rw-r--r--lib/builtins/int_lib.h6
-rw-r--r--lib/builtins/truncdfhf2.c16
-rw-r--r--lib/builtins/truncsfhf2.c22
-rw-r--r--lib/builtins/x86_64/chkstk.S39
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__