Line data Source code
1 : #ifndef _LINUX_MATH64_H
2 : #define _LINUX_MATH64_H
3 :
4 : #include <linux/types.h>
5 : #include <asm/div64.h>
6 :
7 : #if BITS_PER_LONG == 64
8 :
9 : /**
10 : * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
11 : *
12 : * This is commonly provided by 32bit archs to provide an optimized 64bit
13 : * divide.
14 : */
15 : static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
16 : {
17 : *remainder = dividend % divisor;
18 : return dividend / divisor;
19 : }
20 :
21 : /**
22 : * div_s64_rem - signed 64bit divide with 32bit divisor with remainder
23 : */
24 : static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
25 : {
26 : *remainder = dividend % divisor;
27 : return dividend / divisor;
28 : }
29 :
30 : /**
31 : * div64_u64 - unsigned 64bit divide with 64bit divisor
32 : */
33 : static inline u64 div64_u64(u64 dividend, u64 divisor)
34 : {
35 1 : return dividend / divisor;
36 : }
37 :
38 : #elif BITS_PER_LONG == 32
39 :
40 : #ifndef div_u64_rem
41 : static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
42 : {
43 : *remainder = do_div(dividend, divisor);
44 : return dividend;
45 : }
46 : #endif
47 :
48 : #ifndef div_s64_rem
49 : extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
50 : #endif
51 :
52 : #ifndef div64_u64
53 : extern u64 div64_u64(u64 dividend, u64 divisor);
54 : #endif
55 :
56 : #endif /* BITS_PER_LONG */
57 :
58 : /**
59 : * div_u64 - unsigned 64bit divide with 32bit divisor
60 : *
61 : * This is the most common 64bit divide and should be used if possible,
62 : * as many 32bit archs can optimize this variant better than a full 64bit
63 : * divide.
64 : */
65 : #ifndef div_u64
66 : static inline u64 div_u64(u64 dividend, u32 divisor)
67 : {
68 : u32 remainder;
69 : return div_u64_rem(dividend, divisor, &remainder);
70 : }
71 : #endif
72 :
73 : /**
74 : * div_s64 - signed 64bit divide with 32bit divisor
75 : */
76 : #ifndef div_s64
77 : static inline s64 div_s64(s64 dividend, s32 divisor)
78 : {
79 : s32 remainder;
80 : return div_s64_rem(dividend, divisor, &remainder);
81 : }
82 : #endif
83 :
84 : u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder);
85 :
86 : static __always_inline u32
87 : __iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
88 : {
89 : u32 ret = 0;
90 :
91 : while (dividend >= divisor) {
92 : /* The following asm() prevents the compiler from
93 : optimising this loop into a modulo operation. */
94 : asm("" : "+rm"(dividend));
95 :
96 : dividend -= divisor;
97 : ret++;
98 : }
99 :
100 : *remainder = dividend;
101 :
102 : return ret;
103 : }
104 :
105 : #endif /* _LINUX_MATH64_H */
|