summaryrefslogtreecommitdiff
path: root/lib/fp_lib.h
diff options
context:
space:
mode:
authorStephen Canon <scanon@apple.com>2010-07-04 16:53:39 +0000
committerStephen Canon <scanon@apple.com>2010-07-04 16:53:39 +0000
commit12a7d094b185795f478308f4fc27b43abebdde07 (patch)
tree6ad04e67a188e220fa510c6f21f9c9f66e5c43ef /lib/fp_lib.h
parentc9d2b05ea63194c54f5f69aa35062c3f925c75ca (diff)
downloadcompiler-rt-12a7d094b185795f478308f4fc27b43abebdde07.tar.gz
compiler-rt-12a7d094b185795f478308f4fc27b43abebdde07.tar.bz2
compiler-rt-12a7d094b185795f478308f4fc27b43abebdde07.tar.xz
Initial implementation of double-precision soft-float division, moved a couple utility functions from the multiplications into the utility header
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@107586 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/fp_lib.h')
-rw-r--r--lib/fp_lib.h27
1 files changed, 27 insertions, 0 deletions
diff --git a/lib/fp_lib.h b/lib/fp_lib.h
index c8c72342..ab425afa 100644
--- a/lib/fp_lib.h
+++ b/lib/fp_lib.h
@@ -37,6 +37,13 @@ static inline int rep_clz(rep_t a) {
return __builtin_clz(a);
}
+// 32x32 --> 64 bit multiply
+static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
+ const uint64_t product = (uint64_t)a*b;
+ *hi = product >> 32;
+ *lo = product;
+}
+
#elif defined DOUBLE_PRECISION
typedef uint64_t rep_t;
@@ -56,6 +63,26 @@ static inline int rep_clz(rep_t a) {
#endif
}
+#define loWord(a) (a & 0xffffffffU)
+#define hiWord(a) (a >> 32)
+
+// 64x64 -> 128 wide multiply for platforms that don't have such an operation;
+// many 64-bit platforms have this operation, but they tend to have hardware
+// floating-point, so we don't bother with a special case for them here.
+static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
+ // Each of the component 32x32 -> 64 products
+ const uint64_t plolo = loWord(a) * loWord(b);
+ const uint64_t plohi = loWord(a) * hiWord(b);
+ const uint64_t philo = hiWord(a) * loWord(b);
+ const uint64_t phihi = hiWord(a) * hiWord(b);
+ // Sum terms that contribute to lo in a way that allows us to get the carry
+ const uint64_t r0 = loWord(plolo);
+ const uint64_t r1 = hiWord(plolo) + loWord(plohi) + loWord(philo);
+ *lo = r0 + (r1 << 32);
+ // Sum terms contributing to hi with the carry from lo
+ *hi = hiWord(plohi) + hiWord(philo) + hiWord(r1) + phihi;
+}
+
#else
#error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
#endif