summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJoerg Sonnenberger <joerg@bec.de>2015-03-11 21:13:56 +0000
committerJoerg Sonnenberger <joerg@bec.de>2015-03-11 21:13:56 +0000
commit6c015134aead1e20986ebbda8d75e9125e0eeed9 (patch)
tree087bc7b4667f73e29e18876318fc024c41091346 /lib
parent4779d3501762b1c89b54dd852787e410d1dc3e5e (diff)
Refactor float to integer conversion to share the same code.
80bit Intel/PPC long double is excluded due to lacking support for the abstraction. Consistently provide saturation logic. Extend to long double on 128bit IEEE extended platforms. Initial patch with test cases from GuanHong Liu. Reviewed by Steve Canon. Differential Revision: http://reviews.llvm.org/D2804 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@231965 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/builtins/fixdfdi.c41
-rw-r--r--lib/builtins/fixdfsi.c56
-rw-r--r--lib/builtins/fixdfti.c33
-rw-r--r--lib/builtins/fixsfdi.c38
-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.c38
-rw-r--r--lib/builtins/fixunsdfsi.c35
-rw-r--r--lib/builtins/fixunsdfti.c36
-rw-r--r--lib/builtins/fixunssfdi.c35
-rw-r--r--lib/builtins/fixunssfsi.c32
-rw-r--r--lib/builtins/fixunssfti.c36
-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_fixint_impl.inc41
-rw-r--r--lib/builtins/fp_fixuint_impl.inc39
25 files changed, 329 insertions, 376 deletions
diff --git a/lib/builtins/fixdfdi.c b/lib/builtins/fixdfdi.c
index 86f9f6ce8..67b124a16 100644
--- a/lib/builtins/fixdfdi.c
+++ b/lib/builtins/fixdfdi.c
@@ -6,40 +6,17 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixdfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
*/
-#include "int_lib.h"
-
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: double is a IEEE 64 bit floating point type
- * su_int is a 32 bit integral type
- * value in double is representable in di_int (no range checking performed)
- */
-
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
-
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
ARM_EABI_FNALIAS(d2lz, fixdfdi)
+typedef di_int fixint_t;
+typedef du_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
COMPILER_RT_ABI di_int
-__fixdfdi(double a)
-{
- double_bits fb;
- fb.f = a;
- int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
- if (e < 0)
- return 0;
- di_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31;
- dwords r;
- r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
- r.s.low = fb.u.s.low;
- if (e > 52)
- r.all <<= (e - 52);
- else
- r.all >>= (52 - e);
- return (r.all ^ s) - s;
-}
+__fixdfdi(fp_t a) {
+ return __fixint(a);
+}
diff --git a/lib/builtins/fixdfsi.c b/lib/builtins/fixdfsi.c
index 88b2ff5e7..704e65bc4 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 2c27f4bae..aaf225e74 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 4f6cfdd7a..835ff852d 100644
--- a/lib/builtins/fixsfdi.c
+++ b/lib/builtins/fixsfdi.c
@@ -1,43 +1,23 @@
/* ===-- fixsfdi.c - Implement __fixsfdi -----------------------------------===
*
- * The LLVM Compiler Infrastructure
+ * The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixsfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
- */
-
-#include "int_lib.h"
-
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: float is a IEEE 32 bit floating point type
- * su_int is a 32 bit integral type
- * value in float is representable in di_int (no range checking performed)
*/
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#define SINGLE_PRECISION
+#include "fp_lib.h"
ARM_EABI_FNALIAS(f2lz, fixsfdi)
+typedef di_int fixint_t;
+typedef du_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
COMPILER_RT_ABI di_int
-__fixsfdi(float a)
-{
- float_bits fb;
- fb.f = a;
- int e = ((fb.u & 0x7F800000) >> 23) - 127;
- if (e < 0)
- return 0;
- di_int s = (si_int)(fb.u & 0x80000000) >> 31;
- di_int r = (fb.u & 0x007FFFFF) | 0x00800000;
- if (e > 23)
- r <<= (e - 23);
- else
- r >>= (23 - e);
- return (r ^ s) - s;
+__fixsfdi(fp_t a) {
+ return __fixint(a);
}
diff --git a/lib/builtins/fixsfsi.c b/lib/builtins/fixsfsi.c
index e3cc42d52..f045536d6 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 6a1a1c6d5..3a159b3e1 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 000000000..dd3ec0033
--- /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_fixuint_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 000000000..91b9630b6
--- /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_fixuint_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 000000000..41a563848
--- /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_fixuint_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 9e6371390..f4f689e39 100644
--- a/lib/builtins/fixunsdfdi.c
+++ b/lib/builtins/fixunsdfdi.c
@@ -6,42 +6,16 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixunsdfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
- */
-
-#include "int_lib.h"
-
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- * Negative values all become zero.
- */
-
-/* Assumption: double is a IEEE 64 bit floating point type
- * du_int is a 64 bit integral type
- * value in double is representable in du_int or is negative
- * (no range checking performed)
*/
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
+typedef du_int fixuint_t;
+#include "fp_fixuint_impl.inc"
ARM_EABI_FNALIAS(d2ulz, fixunsdfdi)
COMPILER_RT_ABI du_int
-__fixunsdfdi(double a)
-{
- double_bits fb;
- fb.f = a;
- int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
- if (e < 0 || (fb.u.s.high & 0x80000000))
- return 0;
- udwords r;
- r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
- r.s.low = fb.u.s.low;
- if (e > 52)
- r.all <<= (e - 52);
- else
- r.all >>= (52 - e);
- return r.all;
+__fixunsdfdi(fp_t a) {
+ return __fixuint(a);
}
diff --git a/lib/builtins/fixunsdfsi.c b/lib/builtins/fixunsdfsi.c
index c6a3c755e..232d342d7 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 cc6c84ff5..c3d7df97f 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;
+__fixunsdftti(fp_t a) {
+ return __fixuint(a);
}
-
#endif /* CRT_HAS_128BIT */
diff --git a/lib/builtins/fixunssfdi.c b/lib/builtins/fixunssfdi.c
index 69d5952e9..cd21cfd18 100644
--- a/lib/builtins/fixunssfdi.c
+++ b/lib/builtins/fixunssfdi.c
@@ -6,39 +6,16 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixunssfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
- */
-
-#include "int_lib.h"
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- * Negative values all become zero.
- */
-
-/* Assumption: float is a IEEE 32 bit floating point type
- * du_int is a 64 bit integral type
- * value in float is representable in du_int or is negative
- * (no range checking performed)
*/
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#define SINGLE_PRECISION
+#include "fp_lib.h"
+typedef du_int fixuint_t;
+#include "fp_fixuint_impl.inc"
ARM_EABI_FNALIAS(f2ulz, fixunssfdi)
COMPILER_RT_ABI du_int
-__fixunssfdi(float a)
-{
- float_bits fb;
- fb.f = a;
- int e = ((fb.u & 0x7F800000) >> 23) - 127;
- if (e < 0 || (fb.u & 0x80000000))
- return 0;
- du_int r = (fb.u & 0x007FFFFF) | 0x00800000;
- if (e > 23)
- r <<= (e - 23);
- else
- r >>= (23 - e);
- return r;
+__fixunssfdi(fp_t a) {
+ return __fixuint(a);
}
diff --git a/lib/builtins/fixunssfsi.c b/lib/builtins/fixunssfsi.c
index e034139ea..cc2b05bd8 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 4da9e242a..959315374 100644
--- a/lib/builtins/fixunssfti.c
+++ b/lib/builtins/fixunssfti.c
@@ -12,36 +12,12 @@
* ===----------------------------------------------------------------------===
*/
-#include "int_lib.h"
-
-#ifdef CRT_HAS_128BIT
-
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- * Negative values all become zero.
- */
-
-/* Assumption: float is a IEEE 32 bit floating point type
- * tu_int is a 64 bit integral type
- * value in float is representable in tu_int or is negative
- * (no range checking performed)
- */
-
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#if defined(CRT_HAS_128BIT)
+typedef tu_int fixuint_t;
+#include "fp_fixuint_impl.inc"
COMPILER_RT_ABI tu_int
-__fixunssfti(float a)
-{
- float_bits fb;
- fb.f = a;
- int e = ((fb.u & 0x7F800000) >> 23) - 127;
- if (e < 0 || (fb.u & 0x80000000))
- return 0;
- tu_int r = (fb.u & 0x007FFFFF) | 0x00800000;
- if (e > 23)
- r <<= (e - 23);
- else
- r >>= (23 - e);
- return r;
+__fixunssfti(fp_t a) {
+ return __fixuint(a);
}
-
-#endif /* CRT_HAS_128BIT */
+#endif
diff --git a/lib/builtins/fixunstfdi.c b/lib/builtins/fixunstfdi.c
new file mode 100644
index 000000000..b2995f658
--- /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 000000000..b5d3f6a7d
--- /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 000000000..22ff9dfc0
--- /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 7224d467e..075304e78 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 df0a18e2c..c3c70f743 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 42e507304..fb39d00ff 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 afc79d866..011787f9e 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 3d0a279b3..968a4f0d5 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_fixint_impl.inc b/lib/builtins/fp_fixint_impl.inc
new file mode 100644
index 000000000..035e87ca1
--- /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 000000000..5fefab0e2
--- /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);
+}