From 2418f4f28f8467b92a6177af32d05737ebf6206c Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Thu, 1 May 2008 04:34:25 -0700 Subject: introduce explicit signed/unsigned 64bit divide The current do_div doesn't explicitly say that it's unsigned and the signed counterpart is missing, which is e.g. needed when dealing with time values. This introduces 64bit signed/unsigned divide functions which also attempts to cleanup the somewhat awkward calling API, which often requires the use of temporary variables for the dividend. To avoid the need for temporary variables everywhere for the remainder, each divide variant also provides a version which doesn't return the remainder. Each architecture can now provide optimized versions of these function, otherwise generic fallback implementations will be used. As an example I provided an alternative for the current x86 divide, which avoids the asm casts and using an union allows gcc to generate better code. It also avoids the upper divde in a few more cases, where the result is known (i.e. upper quotient is zero). Signed-off-by: Roman Zippel Cc: john stultz Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/div64.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'lib/div64.c') diff --git a/lib/div64.c b/lib/div64.c index b71cf93c529a..689bd76833fa 100644 --- a/lib/div64.c +++ b/lib/div64.c @@ -16,9 +16,8 @@ * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S. */ -#include #include -#include +#include /* Not needed on 64bit architectures */ #if BITS_PER_LONG == 32 @@ -58,6 +57,26 @@ uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base) EXPORT_SYMBOL(__div64_32); +#ifndef div_s64_rem +s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder) +{ + u64 quotient; + + if (dividend < 0) { + quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder); + *remainder = -*remainder; + if (divisor > 0) + quotient = -quotient; + } else { + quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder); + if (divisor < 0) + quotient = -quotient; + } + return quotient; +} +EXPORT_SYMBOL(div_s64_rem); +#endif + /* 64bit divisor, dividend and result. dynamic precision */ uint64_t div64_64(uint64_t dividend, uint64_t divisor) { -- cgit From 6f6d6a1a6a1336431a6cba60ace9e97c3a496a19 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Thu, 1 May 2008 04:34:28 -0700 Subject: rename div64_64 to div64_u64 Rename div64_64 to div64_u64 to make it consistent with the other divide functions, so it clearly includes the type of the divide. Move its definition to math64.h as currently no architecture overrides the generic implementation. They can still override it of course, but the duplicated declarations are avoided. Signed-off-by: Roman Zippel Cc: Avi Kivity Cc: Russell King Cc: Geert Uytterhoeven Cc: Ralf Baechle Cc: David Howells Cc: Jeff Dike Cc: Ingo Molnar Cc: "David S. Miller" Cc: Patrick McHardy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/div64.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/div64.c') diff --git a/lib/div64.c b/lib/div64.c index 689bd76833fa..bb5bd0c0f030 100644 --- a/lib/div64.c +++ b/lib/div64.c @@ -78,9 +78,10 @@ EXPORT_SYMBOL(div_s64_rem); #endif /* 64bit divisor, dividend and result. dynamic precision */ -uint64_t div64_64(uint64_t dividend, uint64_t divisor) +#ifndef div64_u64 +u64 div64_u64(u64 dividend, u64 divisor) { - uint32_t high, d; + u32 high, d; high = divisor >> 32; if (high) { @@ -91,10 +92,9 @@ uint64_t div64_64(uint64_t dividend, uint64_t divisor) } else d = divisor; - do_div(dividend, d); - - return dividend; + return div_u64(dividend, d); } -EXPORT_SYMBOL(div64_64); +EXPORT_SYMBOL(div64_u64); +#endif #endif /* BITS_PER_LONG == 32 */ -- cgit