/src/barebox/lib/math/div64.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0 |
2 | | /* |
3 | | * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com> |
4 | | * |
5 | | * Based on former do_div() implementation from asm-parisc/div64.h: |
6 | | * Copyright (C) 1999 Hewlett-Packard Co |
7 | | * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com> |
8 | | * |
9 | | * |
10 | | * Generic C version of 64bit/32bit division and modulo, with |
11 | | * 64bit result and 32bit remainder. |
12 | | * |
13 | | * The fast case for (n>>32 == 0) is handled inline by do_div(). |
14 | | * |
15 | | * Code generated for this function might be very inefficient |
16 | | * for some CPUs. __div64_32() can be overridden by linking arch-specific |
17 | | * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S |
18 | | * or by defining a preprocessor macro in arch/include/asm/div64.h. |
19 | | */ |
20 | | |
21 | | #include <linux/bitops.h> |
22 | | #include <module.h> |
23 | | #include <linux/kernel.h> |
24 | | #include <linux/ktime.h> |
25 | | #include <linux/math64.h> |
26 | | #include <linux/log2.h> |
27 | | |
28 | | /* Not needed on 64bit architectures */ |
29 | | #if BITS_PER_LONG == 32 |
30 | | |
31 | | #ifndef __div64_32 |
32 | | uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base) |
33 | | { |
34 | | uint64_t rem = *n; |
35 | | uint64_t b = base; |
36 | | uint64_t res, d = 1; |
37 | | uint32_t high = rem >> 32; |
38 | | |
39 | | /* Reduce the thing a bit first */ |
40 | | res = 0; |
41 | | if (high >= base) { |
42 | | high /= base; |
43 | | res = (uint64_t) high << 32; |
44 | | rem -= (uint64_t) (high*base) << 32; |
45 | | } |
46 | | |
47 | | while ((int64_t)b > 0 && b < rem) { |
48 | | b = b+b; |
49 | | d = d+d; |
50 | | } |
51 | | |
52 | | do { |
53 | | if (rem >= b) { |
54 | | rem -= b; |
55 | | res += d; |
56 | | } |
57 | | b >>= 1; |
58 | | d >>= 1; |
59 | | } while (d); |
60 | | |
61 | | *n = res; |
62 | | return rem; |
63 | | } |
64 | | EXPORT_SYMBOL(__div64_32); |
65 | | #endif |
66 | | |
67 | | /** |
68 | | * div_s64_rem - signed 64bit divide with 64bit divisor and remainder |
69 | | * @dividend: 64bit dividend |
70 | | * @divisor: 64bit divisor |
71 | | * @remainder: 64bit remainder |
72 | | */ |
73 | | #ifndef div_s64_rem |
74 | | s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder) |
75 | | { |
76 | | u64 quotient; |
77 | | |
78 | | if (dividend < 0) { |
79 | | quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder); |
80 | | *remainder = -*remainder; |
81 | | if (divisor > 0) |
82 | | quotient = -quotient; |
83 | | } else { |
84 | | quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder); |
85 | | if (divisor < 0) |
86 | | quotient = -quotient; |
87 | | } |
88 | | return quotient; |
89 | | } |
90 | | EXPORT_SYMBOL(div_s64_rem); |
91 | | #endif |
92 | | |
93 | | /** |
94 | | * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder |
95 | | * @dividend: 64bit dividend |
96 | | * @divisor: 64bit divisor |
97 | | * @remainder: 64bit remainder |
98 | | * |
99 | | * This implementation is a comparable to algorithm used by div64_u64. |
100 | | * But this operation, which includes math for calculating the remainder, |
101 | | * is kept distinct to avoid slowing down the div64_u64 operation on 32bit |
102 | | * systems. |
103 | | */ |
104 | | #ifndef div64_u64_rem |
105 | | u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder) |
106 | | { |
107 | | u32 high = divisor >> 32; |
108 | | u64 quot; |
109 | | |
110 | | if (high == 0) { |
111 | | u32 rem32; |
112 | | quot = div_u64_rem(dividend, divisor, &rem32); |
113 | | *remainder = rem32; |
114 | | } else { |
115 | | int n = fls(high); |
116 | | quot = div_u64(dividend >> n, divisor >> n); |
117 | | |
118 | | if (quot != 0) |
119 | | quot--; |
120 | | |
121 | | *remainder = dividend - quot * divisor; |
122 | | if (*remainder >= divisor) { |
123 | | quot++; |
124 | | *remainder -= divisor; |
125 | | } |
126 | | } |
127 | | |
128 | | return quot; |
129 | | } |
130 | | EXPORT_SYMBOL(div64_u64_rem); |
131 | | #endif |
132 | | |
133 | | /** |
134 | | * div64_u64 - unsigned 64bit divide with 64bit divisor |
135 | | * @dividend: 64bit dividend |
136 | | * @divisor: 64bit divisor |
137 | | * |
138 | | * This implementation is a modified version of the algorithm proposed |
139 | | * by the book 'Hacker's Delight'. The original source and full proof |
140 | | * can be found here and is available for use without restriction. |
141 | | * |
142 | | * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt' |
143 | | */ |
144 | | #ifndef div64_u64 |
145 | | u64 div64_u64(u64 dividend, u64 divisor) |
146 | | { |
147 | | u32 high = divisor >> 32; |
148 | | u64 quot; |
149 | | |
150 | | if (high == 0) { |
151 | | quot = div_u64(dividend, divisor); |
152 | | } else { |
153 | | int n = fls(high); |
154 | | quot = div_u64(dividend >> n, divisor >> n); |
155 | | |
156 | | if (quot != 0) |
157 | | quot--; |
158 | | if ((dividend - quot * divisor) >= divisor) |
159 | | quot++; |
160 | | } |
161 | | |
162 | | return quot; |
163 | | } |
164 | | EXPORT_SYMBOL(div64_u64); |
165 | | #endif |
166 | | |
167 | | /** |
168 | | * div64_s64 - signed 64bit divide with 64bit divisor |
169 | | * @dividend: 64bit dividend |
170 | | * @divisor: 64bit divisor |
171 | | */ |
172 | | #ifndef div64_s64 |
173 | | s64 div64_s64(s64 dividend, s64 divisor) |
174 | | { |
175 | | s64 quot, t; |
176 | | |
177 | | quot = div64_u64(abs(dividend), abs(divisor)); |
178 | | t = (dividend ^ divisor) >> 63; |
179 | | |
180 | | return (quot ^ t) - t; |
181 | | } |
182 | | EXPORT_SYMBOL(div64_s64); |
183 | | #endif |
184 | | |
185 | | #endif /* BITS_PER_LONG == 32 */ |
186 | | |
187 | | /* |
188 | | * Iterative div/mod for use when dividend is not expected to be much |
189 | | * bigger than divisor. |
190 | | */ |
191 | | u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder) |
192 | 0 | { |
193 | 0 | return __iter_div_u64_rem(dividend, divisor, remainder); |
194 | 0 | } |
195 | | EXPORT_SYMBOL(iter_div_u64_rem); |
196 | | |
197 | | #ifndef mul_u64_u64_div_u64 |
198 | | u64 mul_u64_u64_div_u64(u64 a, u64 b, u64 c) |
199 | 0 | { |
200 | 0 | u64 res = 0, div, rem; |
201 | 0 | int shift; |
202 | | |
203 | | /* can a * b overflow ? */ |
204 | 0 | if (ilog2(a) + ilog2(b) > 62) { |
205 | | /* |
206 | | * (b * a) / c is equal to |
207 | | * |
208 | | * (b / c) * a + |
209 | | * (b % c) * a / c |
210 | | * |
211 | | * if nothing overflows. Can the 1st multiplication |
212 | | * overflow? Yes, but we do not care: this can only |
213 | | * happen if the end result can't fit in u64 anyway. |
214 | | * |
215 | | * So the code below does |
216 | | * |
217 | | * res = (b / c) * a; |
218 | | * b = b % c; |
219 | | */ |
220 | 0 | div = div64_u64_rem(b, c, &rem); |
221 | 0 | res = div * a; |
222 | 0 | b = rem; |
223 | |
|
224 | 0 | shift = ilog2(a) + ilog2(b) - 62; |
225 | 0 | if (shift > 0) { |
226 | | /* drop precision */ |
227 | 0 | b >>= shift; |
228 | 0 | c >>= shift; |
229 | 0 | if (!c) |
230 | 0 | return res; |
231 | 0 | } |
232 | 0 | } |
233 | | |
234 | 0 | return res + div64_u64(a * b, c); |
235 | 0 | } |
236 | | #endif |
237 | | |
238 | | /* |
239 | | * Functions for the union type storage format of ktime_t which are |
240 | | * too large for inlining: |
241 | | */ |
242 | | #if BITS_PER_LONG < 64 |
243 | | /* |
244 | | * Divide a ktime value by a nanosecond value |
245 | | */ |
246 | | s64 __ktime_divns(const ktime_t kt, s64 div) |
247 | | { |
248 | | int sft = 0; |
249 | | s64 dclc; |
250 | | u64 tmp; |
251 | | |
252 | | dclc = ktime_to_ns(kt); |
253 | | tmp = dclc < 0 ? -dclc : dclc; |
254 | | |
255 | | /* Make sure the divisor is less than 2^32: */ |
256 | | while (div >> 32) { |
257 | | sft++; |
258 | | div >>= 1; |
259 | | } |
260 | | tmp >>= sft; |
261 | | do_div(tmp, (u32) div); |
262 | | return dclc < 0 ? -tmp : tmp; |
263 | | } |
264 | | EXPORT_SYMBOL_GPL(__ktime_divns); |
265 | | #endif /* BITS_PER_LONG >= 64 */ |