diff options
author | Stephen Canon <scanon@apple.com> | 2010-07-04 16:53:39 +0000 |
---|---|---|
committer | Stephen Canon <scanon@apple.com> | 2010-07-04 16:53:39 +0000 |
commit | 12a7d094b185795f478308f4fc27b43abebdde07 (patch) | |
tree | 6ad04e67a188e220fa510c6f21f9c9f66e5c43ef /lib/fp_lib.h | |
parent | c9d2b05ea63194c54f5f69aa35062c3f925c75ca (diff) | |
download | compiler-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.h | 27 |
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 |