diff options
author | Stephen Canon <scanon@apple.com> | 2010-07-02 22:10:58 +0000 |
---|---|---|
committer | Stephen Canon <scanon@apple.com> | 2010-07-02 22:10:58 +0000 |
commit | 0ef6213cf2363ad443b92a2a7396e7c3fb32c630 (patch) | |
tree | 6fe3224bcc023a1ea0e70e41d92c994f55f64c91 | |
parent | 26e5f16341a8fcb99778cdeedc812e87ae756a69 (diff) | |
download | compiler-rt-0ef6213cf2363ad443b92a2a7396e7c3fb32c630.tar.gz |
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
-rw-r--r-- | lib/fixdfsi.c | 45 | ||||
-rw-r--r-- | lib/fixsfsi.c | 45 |
2 files changed, 90 insertions, 0 deletions
diff --git a/lib/fixdfsi.c b/lib/fixdfsi.c new file mode 100644 index 000000000..7d17aedde --- /dev/null +++ b/lib/fixdfsi.c @@ -0,0 +1,45 @@ +//===-- lib/fixdfsi.c - Double-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 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. +// +//===----------------------------------------------------------------------===// + +#define DOUBLE_PRECISION +#include "fp_lib.h" + +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)); + } +} diff --git a/lib/fixsfsi.c b/lib/fixsfsi.c new file mode 100644 index 000000000..ff7937719 --- /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)); + } +} |