1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/export.h>
21#include <linux/kernel.h>
22#include <linux/math64.h>
23
24
25#if BITS_PER_LONG == 32
26
27#ifndef __div64_32
28uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
29{
30 uint64_t rem = *n;
31 uint64_t b = base;
32 uint64_t res, d = 1;
33 uint32_t high = rem >> 32;
34
35
36 res = 0;
37 if (high >= base) {
38 high /= base;
39 res = (uint64_t) high << 32;
40 rem -= (uint64_t) (high*base) << 32;
41 }
42
43 while ((int64_t)b > 0 && b < rem) {
44 b = b+b;
45 d = d+d;
46 }
47
48 do {
49 if (rem >= b) {
50 rem -= b;
51 res += d;
52 }
53 b >>= 1;
54 d >>= 1;
55 } while (d);
56
57 *n = res;
58 return rem;
59}
60EXPORT_SYMBOL(__div64_32);
61#endif
62
63#ifndef div_s64_rem
64s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
65{
66 u64 quotient;
67
68 if (dividend < 0) {
69 quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
70 *remainder = -*remainder;
71 if (divisor > 0)
72 quotient = -quotient;
73 } else {
74 quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
75 if (divisor < 0)
76 quotient = -quotient;
77 }
78 return quotient;
79}
80EXPORT_SYMBOL(div_s64_rem);
81#endif
82
83
84
85
86
87
88
89
90
91
92
93
94#ifndef div64_u64_rem
95u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
96{
97 u32 high = divisor >> 32;
98 u64 quot;
99
100 if (high == 0) {
101 u32 rem32;
102 quot = div_u64_rem(dividend, divisor, &rem32);
103 *remainder = rem32;
104 } else {
105 int n = 1 + fls(high);
106 quot = div_u64(dividend >> n, divisor >> n);
107
108 if (quot != 0)
109 quot--;
110
111 *remainder = dividend - quot * divisor;
112 if (*remainder >= divisor) {
113 quot++;
114 *remainder -= divisor;
115 }
116 }
117
118 return quot;
119}
120EXPORT_SYMBOL(div64_u64_rem);
121#endif
122
123
124
125
126
127
128
129
130
131
132
133
134#ifndef div64_u64
135u64 div64_u64(u64 dividend, u64 divisor)
136{
137 u32 high = divisor >> 32;
138 u64 quot;
139
140 if (high == 0) {
141 quot = div_u64(dividend, divisor);
142 } else {
143 int n = 1 + fls(high);
144 quot = div_u64(dividend >> n, divisor >> n);
145
146 if (quot != 0)
147 quot--;
148 if ((dividend - quot * divisor) >= divisor)
149 quot++;
150 }
151
152 return quot;
153}
154EXPORT_SYMBOL(div64_u64);
155#endif
156
157
158
159
160
161
162#ifndef div64_s64
163s64 div64_s64(s64 dividend, s64 divisor)
164{
165 s64 quot, t;
166
167 quot = div64_u64(abs(dividend), abs(divisor));
168 t = (dividend ^ divisor) >> 63;
169
170 return (quot ^ t) - t;
171}
172EXPORT_SYMBOL(div64_s64);
173#endif
174
175#endif
176
177
178
179
180
181u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
182{
183 return __iter_div_u64_rem(dividend, divisor, remainder);
184}
185EXPORT_SYMBOL(iter_div_u64_rem);
186