diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-01-09 11:12:55 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-01-09 11:12:55 +0900 |
commit | ca371d2854d48c0c22e7aa031df182f96dc85820 (patch) | |
tree | 1c62be8b4da0bfc82fa7ffa1ad5b0e958266cbd1 /arch/x86/include/asm/div64.h | |
parent | 0d376945d0bc0a8f8e00861d506b10e42e8af372 (diff) | |
parent | a0e86bd4252519321b0d102dc4ed90557aa7bee9 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into sh-latest
Conflicts:
arch/arm/mach-shmobile/clock-sh73a0.c
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/x86/include/asm/div64.h')
-rw-r--r-- | arch/x86/include/asm/div64.h | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/arch/x86/include/asm/div64.h b/arch/x86/include/asm/div64.h index 9a2d644c08ef..ced283ac79df 100644 --- a/arch/x86/include/asm/div64.h +++ b/arch/x86/include/asm/div64.h @@ -4,6 +4,7 @@ #ifdef CONFIG_X86_32 #include <linux/types.h> +#include <linux/log2.h> /* * do_div() is NOT a C function. It wants to return @@ -21,15 +22,20 @@ ({ \ unsigned long __upper, __low, __high, __mod, __base; \ __base = (base); \ - asm("":"=a" (__low), "=d" (__high) : "A" (n)); \ - __upper = __high; \ - if (__high) { \ - __upper = __high % (__base); \ - __high = __high / (__base); \ + if (__builtin_constant_p(__base) && is_power_of_2(__base)) { \ + __mod = n & (__base - 1); \ + n >>= ilog2(__base); \ + } else { \ + asm("" : "=a" (__low), "=d" (__high) : "A" (n));\ + __upper = __high; \ + if (__high) { \ + __upper = __high % (__base); \ + __high = __high / (__base); \ + } \ + asm("divl %2" : "=a" (__low), "=d" (__mod) \ + : "rm" (__base), "0" (__low), "1" (__upper)); \ + asm("" : "=A" (n) : "a" (__low), "d" (__high)); \ } \ - asm("divl %2":"=a" (__low), "=d" (__mod) \ - : "rm" (__base), "0" (__low), "1" (__upper)); \ - asm("":"=A" (n) : "a" (__low), "d" (__high)); \ __mod; \ }) |