diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-06-24 10:57:00 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-06-24 10:57:00 +0100 |
commit | c764820ae6c300900aecc04dab691b14f4152f13 (patch) | |
tree | b105569caa7337be0fcb2db2b3d3acca66378455 /xen/common/lib.c | |
parent | 448dac02973ea594c7d5a9ba31da3b6e3ae1ef2d (diff) | |
download | xen-c764820ae6c300900aecc04dab691b14f4152f13.tar.gz xen-c764820ae6c300900aecc04dab691b14f4152f13.tar.bz2 xen-c764820ae6c300900aecc04dab691b14f4152f13.zip |
Move muldiv64 out and make it as a public function.
muldiv64 is used to caculate u64*u32/u32, and we
will use it for TSC scaling.
Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/common/lib.c')
-rw-r--r-- | xen/common/lib.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/xen/common/lib.c b/xen/common/lib.c index 2f1a005ca4..579512a4c5 100644 --- a/xen/common/lib.c +++ b/xen/common/lib.c @@ -401,6 +401,35 @@ s64 __moddi3(s64 a, s64 b) #endif /* BITS_PER_LONG == 32 */ +/* Compute with 96 bit intermediate result: (a*b)/c */ +uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) +{ +#ifdef __x86_64__ + asm ( "mul %%rdx; div %%rcx" : "=a" (a) : "0" (a), "d" (b), "c" (c) ); + return a; +#else + union { + uint64_t ll; + struct { +#ifdef WORDS_BIGENDIAN + uint32_t high, low; +#else + uint32_t low, high; +#endif + } l; + } u, res; + uint64_t rl, rh; + + u.ll = a; + rl = (uint64_t)u.l.low * (uint64_t)b; + rh = (uint64_t)u.l.high * (uint64_t)b; + rh += (rl >> 32); + res.l.high = rh / c; + res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; + return res.ll; +#endif +} + unsigned long long parse_size_and_unit(const char *s, const char **ps) { unsigned long long ret; |