summaryrefslogtreecommitdiff
path: root/lib/fixsfsi.c
diff options
context:
space:
mode:
authorStephen Canon <scanon@apple.com>2010-07-02 22:10:58 +0000
committerStephen Canon <scanon@apple.com>2010-07-02 22:10:58 +0000
commit0ef6213cf2363ad443b92a2a7396e7c3fb32c630 (patch)
tree6fe3224bcc023a1ea0e70e41d92c994f55f64c91 /lib/fixsfsi.c
parent26e5f16341a8fcb99778cdeedc812e87ae756a69 (diff)
downloadcompiler-rt-0ef6213cf2363ad443b92a2a7396e7c3fb32c630.tar.gz
compiler-rt-0ef6213cf2363ad443b92a2a7396e7c3fb32c630.tar.bz2
compiler-rt-0ef6213cf2363ad443b92a2a7396e7c3fb32c630.tar.xz
float- and double-to-integer soft-float conversions for compiler-rt
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@107524 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/fixsfsi.c')
-rw-r--r--lib/fixsfsi.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/fixsfsi.c b/lib/fixsfsi.c
new file mode 100644
index 00000000..ff793771
--- /dev/null
+++ b/lib/fixsfsi.c
@@ -0,0 +1,45 @@
+//===-- lib/fixsfsi.c - Single-precision -> integer conversion ----*- C -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. 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.
+//
+//===----------------------------------------------------------------------===//
+
+#define SINGLE_PRECISION
+#include "fp_lib.h"
+
+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));
+ }
+}