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