diff options
Diffstat (limited to 'arch/x86/include/asm/div64.h')
-rw-r--r-- | arch/x86/include/asm/div64.h | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/arch/x86/include/asm/div64.h b/arch/x86/include/asm/div64.h new file mode 100644 index 000000000000..f9530f23f1d6 --- /dev/null +++ b/arch/x86/include/asm/div64.h | |||
@@ -0,0 +1,60 @@ | |||
1 | #ifndef ASM_X86__DIV64_H | ||
2 | #define ASM_X86__DIV64_H | ||
3 | |||
4 | #ifdef CONFIG_X86_32 | ||
5 | |||
6 | #include <linux/types.h> | ||
7 | |||
8 | /* | ||
9 | * do_div() is NOT a C function. It wants to return | ||
10 | * two values (the quotient and the remainder), but | ||
11 | * since that doesn't work very well in C, what it | ||
12 | * does is: | ||
13 | * | ||
14 | * - modifies the 64-bit dividend _in_place_ | ||
15 | * - returns the 32-bit remainder | ||
16 | * | ||
17 | * This ends up being the most efficient "calling | ||
18 | * convention" on x86. | ||
19 | */ | ||
20 | #define do_div(n, base) \ | ||
21 | ({ \ | ||
22 | unsigned long __upper, __low, __high, __mod, __base; \ | ||
23 | __base = (base); \ | ||
24 | asm("":"=a" (__low), "=d" (__high) : "A" (n)); \ | ||
25 | __upper = __high; \ | ||
26 | if (__high) { \ | ||
27 | __upper = __high % (__base); \ | ||
28 | __high = __high / (__base); \ | ||
29 | } \ | ||
30 | asm("divl %2":"=a" (__low), "=d" (__mod) \ | ||
31 | : "rm" (__base), "0" (__low), "1" (__upper)); \ | ||
32 | asm("":"=A" (n) : "a" (__low), "d" (__high)); \ | ||
33 | __mod; \ | ||
34 | }) | ||
35 | |||
36 | static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) | ||
37 | { | ||
38 | union { | ||
39 | u64 v64; | ||
40 | u32 v32[2]; | ||
41 | } d = { dividend }; | ||
42 | u32 upper; | ||
43 | |||
44 | upper = d.v32[1]; | ||
45 | d.v32[1] = 0; | ||
46 | if (upper >= divisor) { | ||
47 | d.v32[1] = upper / divisor; | ||
48 | upper %= divisor; | ||
49 | } | ||
50 | asm ("divl %2" : "=a" (d.v32[0]), "=d" (*remainder) : | ||
51 | "rm" (divisor), "0" (d.v32[0]), "1" (upper)); | ||
52 | return d.v64; | ||
53 | } | ||
54 | #define div_u64_rem div_u64_rem | ||
55 | |||
56 | #else | ||
57 | # include <asm-generic/div64.h> | ||
58 | #endif /* CONFIG_X86_32 */ | ||
59 | |||
60 | #endif /* ASM_X86__DIV64_H */ | ||