18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com> 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Based on former do_div() implementation from asm-parisc/div64.h: 68c2ecf20Sopenharmony_ci * Copyright (C) 1999 Hewlett-Packard Co 78c2ecf20Sopenharmony_ci * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Generic C version of 64bit/32bit division and modulo, with 118c2ecf20Sopenharmony_ci * 64bit result and 32bit remainder. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The fast case for (n>>32 == 0) is handled inline by do_div(). 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Code generated for this function might be very inefficient 168c2ecf20Sopenharmony_ci * for some CPUs. __div64_32() can be overridden by linking arch-specific 178c2ecf20Sopenharmony_ci * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S 188c2ecf20Sopenharmony_ci * or by defining a preprocessor macro in arch/include/asm/div64.h. 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <linux/export.h> 228c2ecf20Sopenharmony_ci#include <linux/kernel.h> 238c2ecf20Sopenharmony_ci#include <linux/math64.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* Not needed on 64bit architectures */ 268c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 32 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#ifndef __div64_32 298c2ecf20Sopenharmony_ciuint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci uint64_t rem = *n; 328c2ecf20Sopenharmony_ci uint64_t b = base; 338c2ecf20Sopenharmony_ci uint64_t res, d = 1; 348c2ecf20Sopenharmony_ci uint32_t high = rem >> 32; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci /* Reduce the thing a bit first */ 378c2ecf20Sopenharmony_ci res = 0; 388c2ecf20Sopenharmony_ci if (high >= base) { 398c2ecf20Sopenharmony_ci high /= base; 408c2ecf20Sopenharmony_ci res = (uint64_t) high << 32; 418c2ecf20Sopenharmony_ci rem -= (uint64_t) (high*base) << 32; 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci while ((int64_t)b > 0 && b < rem) { 458c2ecf20Sopenharmony_ci b = b+b; 468c2ecf20Sopenharmony_ci d = d+d; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci do { 508c2ecf20Sopenharmony_ci if (rem >= b) { 518c2ecf20Sopenharmony_ci rem -= b; 528c2ecf20Sopenharmony_ci res += d; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci b >>= 1; 558c2ecf20Sopenharmony_ci d >>= 1; 568c2ecf20Sopenharmony_ci } while (d); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci *n = res; 598c2ecf20Sopenharmony_ci return rem; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__div64_32); 628c2ecf20Sopenharmony_ci#endif 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/** 658c2ecf20Sopenharmony_ci * div_s64_rem - signed 64bit divide with 64bit divisor and remainder 668c2ecf20Sopenharmony_ci * @dividend: 64bit dividend 678c2ecf20Sopenharmony_ci * @divisor: 64bit divisor 688c2ecf20Sopenharmony_ci * @remainder: 64bit remainder 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_ci#ifndef div_s64_rem 718c2ecf20Sopenharmony_cis64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci u64 quotient; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (dividend < 0) { 768c2ecf20Sopenharmony_ci quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder); 778c2ecf20Sopenharmony_ci *remainder = -*remainder; 788c2ecf20Sopenharmony_ci if (divisor > 0) 798c2ecf20Sopenharmony_ci quotient = -quotient; 808c2ecf20Sopenharmony_ci } else { 818c2ecf20Sopenharmony_ci quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder); 828c2ecf20Sopenharmony_ci if (divisor < 0) 838c2ecf20Sopenharmony_ci quotient = -quotient; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci return quotient; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(div_s64_rem); 888c2ecf20Sopenharmony_ci#endif 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/** 918c2ecf20Sopenharmony_ci * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder 928c2ecf20Sopenharmony_ci * @dividend: 64bit dividend 938c2ecf20Sopenharmony_ci * @divisor: 64bit divisor 948c2ecf20Sopenharmony_ci * @remainder: 64bit remainder 958c2ecf20Sopenharmony_ci * 968c2ecf20Sopenharmony_ci * This implementation is a comparable to algorithm used by div64_u64. 978c2ecf20Sopenharmony_ci * But this operation, which includes math for calculating the remainder, 988c2ecf20Sopenharmony_ci * is kept distinct to avoid slowing down the div64_u64 operation on 32bit 998c2ecf20Sopenharmony_ci * systems. 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_ci#ifndef div64_u64_rem 1028c2ecf20Sopenharmony_ciu64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci u32 high = divisor >> 32; 1058c2ecf20Sopenharmony_ci u64 quot; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if (high == 0) { 1088c2ecf20Sopenharmony_ci u32 rem32; 1098c2ecf20Sopenharmony_ci quot = div_u64_rem(dividend, divisor, &rem32); 1108c2ecf20Sopenharmony_ci *remainder = rem32; 1118c2ecf20Sopenharmony_ci } else { 1128c2ecf20Sopenharmony_ci int n = fls(high); 1138c2ecf20Sopenharmony_ci quot = div_u64(dividend >> n, divisor >> n); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (quot != 0) 1168c2ecf20Sopenharmony_ci quot--; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci *remainder = dividend - quot * divisor; 1198c2ecf20Sopenharmony_ci if (*remainder >= divisor) { 1208c2ecf20Sopenharmony_ci quot++; 1218c2ecf20Sopenharmony_ci *remainder -= divisor; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci return quot; 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(div64_u64_rem); 1288c2ecf20Sopenharmony_ci#endif 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/** 1318c2ecf20Sopenharmony_ci * div64_u64 - unsigned 64bit divide with 64bit divisor 1328c2ecf20Sopenharmony_ci * @dividend: 64bit dividend 1338c2ecf20Sopenharmony_ci * @divisor: 64bit divisor 1348c2ecf20Sopenharmony_ci * 1358c2ecf20Sopenharmony_ci * This implementation is a modified version of the algorithm proposed 1368c2ecf20Sopenharmony_ci * by the book 'Hacker's Delight'. The original source and full proof 1378c2ecf20Sopenharmony_ci * can be found here and is available for use without restriction. 1388c2ecf20Sopenharmony_ci * 1398c2ecf20Sopenharmony_ci * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt' 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_ci#ifndef div64_u64 1428c2ecf20Sopenharmony_ciu64 div64_u64(u64 dividend, u64 divisor) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci u32 high = divisor >> 32; 1458c2ecf20Sopenharmony_ci u64 quot; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci if (high == 0) { 1488c2ecf20Sopenharmony_ci quot = div_u64(dividend, divisor); 1498c2ecf20Sopenharmony_ci } else { 1508c2ecf20Sopenharmony_ci int n = fls(high); 1518c2ecf20Sopenharmony_ci quot = div_u64(dividend >> n, divisor >> n); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (quot != 0) 1548c2ecf20Sopenharmony_ci quot--; 1558c2ecf20Sopenharmony_ci if ((dividend - quot * divisor) >= divisor) 1568c2ecf20Sopenharmony_ci quot++; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return quot; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(div64_u64); 1628c2ecf20Sopenharmony_ci#endif 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci/** 1658c2ecf20Sopenharmony_ci * div64_s64 - signed 64bit divide with 64bit divisor 1668c2ecf20Sopenharmony_ci * @dividend: 64bit dividend 1678c2ecf20Sopenharmony_ci * @divisor: 64bit divisor 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_ci#ifndef div64_s64 1708c2ecf20Sopenharmony_cis64 div64_s64(s64 dividend, s64 divisor) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci s64 quot, t; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci quot = div64_u64(abs(dividend), abs(divisor)); 1758c2ecf20Sopenharmony_ci t = (dividend ^ divisor) >> 63; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci return (quot ^ t) - t; 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(div64_s64); 1808c2ecf20Sopenharmony_ci#endif 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci#endif /* BITS_PER_LONG == 32 */ 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci/* 1858c2ecf20Sopenharmony_ci * Iterative div/mod for use when dividend is not expected to be much 1868c2ecf20Sopenharmony_ci * bigger than divisor. 1878c2ecf20Sopenharmony_ci */ 1888c2ecf20Sopenharmony_ciu32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci return __iter_div_u64_rem(dividend, divisor, remainder); 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ciEXPORT_SYMBOL(iter_div_u64_rem); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci#ifndef mul_u64_u64_div_u64 1958c2ecf20Sopenharmony_ciu64 mul_u64_u64_div_u64(u64 a, u64 b, u64 c) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci u64 res = 0, div, rem; 1988c2ecf20Sopenharmony_ci int shift; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci /* can a * b overflow ? */ 2018c2ecf20Sopenharmony_ci if (ilog2(a) + ilog2(b) > 62) { 2028c2ecf20Sopenharmony_ci /* 2038c2ecf20Sopenharmony_ci * (b * a) / c is equal to 2048c2ecf20Sopenharmony_ci * 2058c2ecf20Sopenharmony_ci * (b / c) * a + 2068c2ecf20Sopenharmony_ci * (b % c) * a / c 2078c2ecf20Sopenharmony_ci * 2088c2ecf20Sopenharmony_ci * if nothing overflows. Can the 1st multiplication 2098c2ecf20Sopenharmony_ci * overflow? Yes, but we do not care: this can only 2108c2ecf20Sopenharmony_ci * happen if the end result can't fit in u64 anyway. 2118c2ecf20Sopenharmony_ci * 2128c2ecf20Sopenharmony_ci * So the code below does 2138c2ecf20Sopenharmony_ci * 2148c2ecf20Sopenharmony_ci * res = (b / c) * a; 2158c2ecf20Sopenharmony_ci * b = b % c; 2168c2ecf20Sopenharmony_ci */ 2178c2ecf20Sopenharmony_ci div = div64_u64_rem(b, c, &rem); 2188c2ecf20Sopenharmony_ci res = div * a; 2198c2ecf20Sopenharmony_ci b = rem; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci shift = ilog2(a) + ilog2(b) - 62; 2228c2ecf20Sopenharmony_ci if (shift > 0) { 2238c2ecf20Sopenharmony_ci /* drop precision */ 2248c2ecf20Sopenharmony_ci b >>= shift; 2258c2ecf20Sopenharmony_ci c >>= shift; 2268c2ecf20Sopenharmony_ci if (!c) 2278c2ecf20Sopenharmony_ci return res; 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci return res + div64_u64(a * b, c); 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mul_u64_u64_div_u64); 2348c2ecf20Sopenharmony_ci#endif 235