162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Based on former do_div() implementation from asm-parisc/div64.h:
662306a36Sopenharmony_ci *	Copyright (C) 1999 Hewlett-Packard Co
762306a36Sopenharmony_ci *	Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Generic C version of 64bit/32bit division and modulo, with
1162306a36Sopenharmony_ci * 64bit result and 32bit remainder.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * The fast case for (n>>32 == 0) is handled inline by do_div().
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * Code generated for this function might be very inefficient
1662306a36Sopenharmony_ci * for some CPUs. __div64_32() can be overridden by linking arch-specific
1762306a36Sopenharmony_ci * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S
1862306a36Sopenharmony_ci * or by defining a preprocessor macro in arch/include/asm/div64.h.
1962306a36Sopenharmony_ci */
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <linux/bitops.h>
2262306a36Sopenharmony_ci#include <linux/export.h>
2362306a36Sopenharmony_ci#include <linux/math.h>
2462306a36Sopenharmony_ci#include <linux/math64.h>
2562306a36Sopenharmony_ci#include <linux/log2.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* Not needed on 64bit architectures */
2862306a36Sopenharmony_ci#if BITS_PER_LONG == 32
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#ifndef __div64_32
3162306a36Sopenharmony_ciuint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	uint64_t rem = *n;
3462306a36Sopenharmony_ci	uint64_t b = base;
3562306a36Sopenharmony_ci	uint64_t res, d = 1;
3662306a36Sopenharmony_ci	uint32_t high = rem >> 32;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	/* Reduce the thing a bit first */
3962306a36Sopenharmony_ci	res = 0;
4062306a36Sopenharmony_ci	if (high >= base) {
4162306a36Sopenharmony_ci		high /= base;
4262306a36Sopenharmony_ci		res = (uint64_t) high << 32;
4362306a36Sopenharmony_ci		rem -= (uint64_t) (high*base) << 32;
4462306a36Sopenharmony_ci	}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	while ((int64_t)b > 0 && b < rem) {
4762306a36Sopenharmony_ci		b = b+b;
4862306a36Sopenharmony_ci		d = d+d;
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	do {
5262306a36Sopenharmony_ci		if (rem >= b) {
5362306a36Sopenharmony_ci			rem -= b;
5462306a36Sopenharmony_ci			res += d;
5562306a36Sopenharmony_ci		}
5662306a36Sopenharmony_ci		b >>= 1;
5762306a36Sopenharmony_ci		d >>= 1;
5862306a36Sopenharmony_ci	} while (d);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	*n = res;
6162306a36Sopenharmony_ci	return rem;
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ciEXPORT_SYMBOL(__div64_32);
6462306a36Sopenharmony_ci#endif
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#ifndef div_s64_rem
6762306a36Sopenharmony_cis64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	u64 quotient;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	if (dividend < 0) {
7262306a36Sopenharmony_ci		quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
7362306a36Sopenharmony_ci		*remainder = -*remainder;
7462306a36Sopenharmony_ci		if (divisor > 0)
7562306a36Sopenharmony_ci			quotient = -quotient;
7662306a36Sopenharmony_ci	} else {
7762306a36Sopenharmony_ci		quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
7862306a36Sopenharmony_ci		if (divisor < 0)
7962306a36Sopenharmony_ci			quotient = -quotient;
8062306a36Sopenharmony_ci	}
8162306a36Sopenharmony_ci	return quotient;
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ciEXPORT_SYMBOL(div_s64_rem);
8462306a36Sopenharmony_ci#endif
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/*
8762306a36Sopenharmony_ci * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
8862306a36Sopenharmony_ci * @dividend:	64bit dividend
8962306a36Sopenharmony_ci * @divisor:	64bit divisor
9062306a36Sopenharmony_ci * @remainder:  64bit remainder
9162306a36Sopenharmony_ci *
9262306a36Sopenharmony_ci * This implementation is a comparable to algorithm used by div64_u64.
9362306a36Sopenharmony_ci * But this operation, which includes math for calculating the remainder,
9462306a36Sopenharmony_ci * is kept distinct to avoid slowing down the div64_u64 operation on 32bit
9562306a36Sopenharmony_ci * systems.
9662306a36Sopenharmony_ci */
9762306a36Sopenharmony_ci#ifndef div64_u64_rem
9862306a36Sopenharmony_ciu64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	u32 high = divisor >> 32;
10162306a36Sopenharmony_ci	u64 quot;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	if (high == 0) {
10462306a36Sopenharmony_ci		u32 rem32;
10562306a36Sopenharmony_ci		quot = div_u64_rem(dividend, divisor, &rem32);
10662306a36Sopenharmony_ci		*remainder = rem32;
10762306a36Sopenharmony_ci	} else {
10862306a36Sopenharmony_ci		int n = fls(high);
10962306a36Sopenharmony_ci		quot = div_u64(dividend >> n, divisor >> n);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		if (quot != 0)
11262306a36Sopenharmony_ci			quot--;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci		*remainder = dividend - quot * divisor;
11562306a36Sopenharmony_ci		if (*remainder >= divisor) {
11662306a36Sopenharmony_ci			quot++;
11762306a36Sopenharmony_ci			*remainder -= divisor;
11862306a36Sopenharmony_ci		}
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	return quot;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ciEXPORT_SYMBOL(div64_u64_rem);
12462306a36Sopenharmony_ci#endif
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/*
12762306a36Sopenharmony_ci * div64_u64 - unsigned 64bit divide with 64bit divisor
12862306a36Sopenharmony_ci * @dividend:	64bit dividend
12962306a36Sopenharmony_ci * @divisor:	64bit divisor
13062306a36Sopenharmony_ci *
13162306a36Sopenharmony_ci * This implementation is a modified version of the algorithm proposed
13262306a36Sopenharmony_ci * by the book 'Hacker's Delight'.  The original source and full proof
13362306a36Sopenharmony_ci * can be found here and is available for use without restriction.
13462306a36Sopenharmony_ci *
13562306a36Sopenharmony_ci * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt'
13662306a36Sopenharmony_ci */
13762306a36Sopenharmony_ci#ifndef div64_u64
13862306a36Sopenharmony_ciu64 div64_u64(u64 dividend, u64 divisor)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	u32 high = divisor >> 32;
14162306a36Sopenharmony_ci	u64 quot;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	if (high == 0) {
14462306a36Sopenharmony_ci		quot = div_u64(dividend, divisor);
14562306a36Sopenharmony_ci	} else {
14662306a36Sopenharmony_ci		int n = fls(high);
14762306a36Sopenharmony_ci		quot = div_u64(dividend >> n, divisor >> n);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		if (quot != 0)
15062306a36Sopenharmony_ci			quot--;
15162306a36Sopenharmony_ci		if ((dividend - quot * divisor) >= divisor)
15262306a36Sopenharmony_ci			quot++;
15362306a36Sopenharmony_ci	}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	return quot;
15662306a36Sopenharmony_ci}
15762306a36Sopenharmony_ciEXPORT_SYMBOL(div64_u64);
15862306a36Sopenharmony_ci#endif
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci#ifndef div64_s64
16162306a36Sopenharmony_cis64 div64_s64(s64 dividend, s64 divisor)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	s64 quot, t;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	quot = div64_u64(abs(dividend), abs(divisor));
16662306a36Sopenharmony_ci	t = (dividend ^ divisor) >> 63;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	return (quot ^ t) - t;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ciEXPORT_SYMBOL(div64_s64);
17162306a36Sopenharmony_ci#endif
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci#endif /* BITS_PER_LONG == 32 */
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci/*
17662306a36Sopenharmony_ci * Iterative div/mod for use when dividend is not expected to be much
17762306a36Sopenharmony_ci * bigger than divisor.
17862306a36Sopenharmony_ci */
17962306a36Sopenharmony_ciu32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	return __iter_div_u64_rem(dividend, divisor, remainder);
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ciEXPORT_SYMBOL(iter_div_u64_rem);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci#ifndef mul_u64_u64_div_u64
18662306a36Sopenharmony_ciu64 mul_u64_u64_div_u64(u64 a, u64 b, u64 c)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	u64 res = 0, div, rem;
18962306a36Sopenharmony_ci	int shift;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	/* can a * b overflow ? */
19262306a36Sopenharmony_ci	if (ilog2(a) + ilog2(b) > 62) {
19362306a36Sopenharmony_ci		/*
19462306a36Sopenharmony_ci		 * (b * a) / c is equal to
19562306a36Sopenharmony_ci		 *
19662306a36Sopenharmony_ci		 *      (b / c) * a +
19762306a36Sopenharmony_ci		 *      (b % c) * a / c
19862306a36Sopenharmony_ci		 *
19962306a36Sopenharmony_ci		 * if nothing overflows. Can the 1st multiplication
20062306a36Sopenharmony_ci		 * overflow? Yes, but we do not care: this can only
20162306a36Sopenharmony_ci		 * happen if the end result can't fit in u64 anyway.
20262306a36Sopenharmony_ci		 *
20362306a36Sopenharmony_ci		 * So the code below does
20462306a36Sopenharmony_ci		 *
20562306a36Sopenharmony_ci		 *      res = (b / c) * a;
20662306a36Sopenharmony_ci		 *      b = b % c;
20762306a36Sopenharmony_ci		 */
20862306a36Sopenharmony_ci		div = div64_u64_rem(b, c, &rem);
20962306a36Sopenharmony_ci		res = div * a;
21062306a36Sopenharmony_ci		b = rem;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci		shift = ilog2(a) + ilog2(b) - 62;
21362306a36Sopenharmony_ci		if (shift > 0) {
21462306a36Sopenharmony_ci			/* drop precision */
21562306a36Sopenharmony_ci			b >>= shift;
21662306a36Sopenharmony_ci			c >>= shift;
21762306a36Sopenharmony_ci			if (!c)
21862306a36Sopenharmony_ci				return res;
21962306a36Sopenharmony_ci		}
22062306a36Sopenharmony_ci	}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	return res + div64_u64(a * b, c);
22362306a36Sopenharmony_ci}
22462306a36Sopenharmony_ciEXPORT_SYMBOL(mul_u64_u64_div_u64);
22562306a36Sopenharmony_ci#endif
226