diff options
Diffstat (limited to 'lib/div64.c')
| -rw-r--r-- | lib/div64.c | 45 | 
1 files changed, 43 insertions, 2 deletions
diff --git a/lib/div64.c b/lib/div64.c index 5b491919177..4382ad77777 100644 --- a/lib/div64.c +++ b/lib/div64.c @@ -16,7 +16,8 @@   * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.   */ -#include <linux/module.h> +#include <linux/export.h> +#include <linux/kernel.h>  #include <linux/math64.h>  /* Not needed on 64bit architectures */ @@ -78,6 +79,46 @@ EXPORT_SYMBOL(div_s64_rem);  #endif  /** + * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder + * @dividend:	64bit dividend + * @divisor:	64bit divisor + * @remainder:  64bit remainder + * + * This implementation is a comparable to algorithm used by div64_u64. + * But this operation, which includes math for calculating the remainder, + * is kept distinct to avoid slowing down the div64_u64 operation on 32bit + * systems. + */ +#ifndef div64_u64_rem +u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder) +{ +	u32 high = divisor >> 32; +	u64 quot; + +	if (high == 0) { +		u32 rem32; +		quot = div_u64_rem(dividend, divisor, &rem32); +		*remainder = rem32; +	} else { +		int n = 1 + fls(high); +		quot = div_u64(dividend >> n, divisor >> n); + +		if (quot != 0) +			quot--; + +		*remainder = dividend - quot * divisor; +		if (*remainder >= divisor) { +			quot++; +			*remainder -= divisor; +		} +	} + +	return quot; +} +EXPORT_SYMBOL(div64_u64_rem); +#endif + +/**   * div64_u64 - unsigned 64bit divide with 64bit divisor   * @dividend:	64bit dividend   * @divisor:	64bit divisor @@ -86,7 +127,7 @@ EXPORT_SYMBOL(div_s64_rem);   * by the book 'Hacker's Delight'.  The original source and full proof   * can be found here and is available for use without restriction.   * - * 'http://www.hackersdelight.org/HDcode/newCode/divDouble.c' + * 'http://www.hackersdelight.org/HDcode/newCode/divDouble.c.txt'   */  #ifndef div64_u64  u64 div64_u64(u64 dividend, u64 divisor)  | 
