cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

div64.c (5212B)


      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 <linux/export.h>
     23#include <linux/math.h>
     24#include <linux/math64.h>
     25#include <linux/log2.h>
     26
     27/* Not needed on 64bit architectures */
     28#if BITS_PER_LONG == 32
     29
     30#ifndef __div64_32
     31uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
     32{
     33	uint64_t rem = *n;
     34	uint64_t b = base;
     35	uint64_t res, d = 1;
     36	uint32_t high = rem >> 32;
     37
     38	/* Reduce the thing a bit first */
     39	res = 0;
     40	if (high >= base) {
     41		high /= base;
     42		res = (uint64_t) high << 32;
     43		rem -= (uint64_t) (high*base) << 32;
     44	}
     45
     46	while ((int64_t)b > 0 && b < rem) {
     47		b = b+b;
     48		d = d+d;
     49	}
     50
     51	do {
     52		if (rem >= b) {
     53			rem -= b;
     54			res += d;
     55		}
     56		b >>= 1;
     57		d >>= 1;
     58	} while (d);
     59
     60	*n = res;
     61	return rem;
     62}
     63EXPORT_SYMBOL(__div64_32);
     64#endif
     65
     66/**
     67 * div_s64_rem - signed 64bit divide with 64bit divisor and remainder
     68 * @dividend:	64bit dividend
     69 * @divisor:	64bit divisor
     70 * @remainder:  64bit remainder
     71 */
     72#ifndef div_s64_rem
     73s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
     74{
     75	u64 quotient;
     76
     77	if (dividend < 0) {
     78		quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
     79		*remainder = -*remainder;
     80		if (divisor > 0)
     81			quotient = -quotient;
     82	} else {
     83		quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
     84		if (divisor < 0)
     85			quotient = -quotient;
     86	}
     87	return quotient;
     88}
     89EXPORT_SYMBOL(div_s64_rem);
     90#endif
     91
     92/**
     93 * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
     94 * @dividend:	64bit dividend
     95 * @divisor:	64bit divisor
     96 * @remainder:  64bit remainder
     97 *
     98 * This implementation is a comparable to algorithm used by div64_u64.
     99 * But this operation, which includes math for calculating the remainder,
    100 * is kept distinct to avoid slowing down the div64_u64 operation on 32bit
    101 * systems.
    102 */
    103#ifndef div64_u64_rem
    104u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
    105{
    106	u32 high = divisor >> 32;
    107	u64 quot;
    108
    109	if (high == 0) {
    110		u32 rem32;
    111		quot = div_u64_rem(dividend, divisor, &rem32);
    112		*remainder = rem32;
    113	} else {
    114		int n = fls(high);
    115		quot = div_u64(dividend >> n, divisor >> n);
    116
    117		if (quot != 0)
    118			quot--;
    119
    120		*remainder = dividend - quot * divisor;
    121		if (*remainder >= divisor) {
    122			quot++;
    123			*remainder -= divisor;
    124		}
    125	}
    126
    127	return quot;
    128}
    129EXPORT_SYMBOL(div64_u64_rem);
    130#endif
    131
    132/**
    133 * div64_u64 - unsigned 64bit divide with 64bit divisor
    134 * @dividend:	64bit dividend
    135 * @divisor:	64bit divisor
    136 *
    137 * This implementation is a modified version of the algorithm proposed
    138 * by the book 'Hacker's Delight'.  The original source and full proof
    139 * can be found here and is available for use without restriction.
    140 *
    141 * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt'
    142 */
    143#ifndef div64_u64
    144u64 div64_u64(u64 dividend, u64 divisor)
    145{
    146	u32 high = divisor >> 32;
    147	u64 quot;
    148
    149	if (high == 0) {
    150		quot = div_u64(dividend, divisor);
    151	} else {
    152		int n = fls(high);
    153		quot = div_u64(dividend >> n, divisor >> n);
    154
    155		if (quot != 0)
    156			quot--;
    157		if ((dividend - quot * divisor) >= divisor)
    158			quot++;
    159	}
    160
    161	return quot;
    162}
    163EXPORT_SYMBOL(div64_u64);
    164#endif
    165
    166/**
    167 * div64_s64 - signed 64bit divide with 64bit divisor
    168 * @dividend:	64bit dividend
    169 * @divisor:	64bit divisor
    170 */
    171#ifndef div64_s64
    172s64 div64_s64(s64 dividend, s64 divisor)
    173{
    174	s64 quot, t;
    175
    176	quot = div64_u64(abs(dividend), abs(divisor));
    177	t = (dividend ^ divisor) >> 63;
    178
    179	return (quot ^ t) - t;
    180}
    181EXPORT_SYMBOL(div64_s64);
    182#endif
    183
    184#endif /* BITS_PER_LONG == 32 */
    185
    186/*
    187 * Iterative div/mod for use when dividend is not expected to be much
    188 * bigger than divisor.
    189 */
    190u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
    191{
    192	return __iter_div_u64_rem(dividend, divisor, remainder);
    193}
    194EXPORT_SYMBOL(iter_div_u64_rem);
    195
    196#ifndef mul_u64_u64_div_u64
    197u64 mul_u64_u64_div_u64(u64 a, u64 b, u64 c)
    198{
    199	u64 res = 0, div, rem;
    200	int shift;
    201
    202	/* can a * b overflow ? */
    203	if (ilog2(a) + ilog2(b) > 62) {
    204		/*
    205		 * (b * a) / c is equal to
    206		 *
    207		 *      (b / c) * a +
    208		 *      (b % c) * a / c
    209		 *
    210		 * if nothing overflows. Can the 1st multiplication
    211		 * overflow? Yes, but we do not care: this can only
    212		 * happen if the end result can't fit in u64 anyway.
    213		 *
    214		 * So the code below does
    215		 *
    216		 *      res = (b / c) * a;
    217		 *      b = b % c;
    218		 */
    219		div = div64_u64_rem(b, c, &rem);
    220		res = div * a;
    221		b = rem;
    222
    223		shift = ilog2(a) + ilog2(b) - 62;
    224		if (shift > 0) {
    225			/* drop precision */
    226			b >>= shift;
    227			c >>= shift;
    228			if (!c)
    229				return res;
    230		}
    231	}
    232
    233	return res + div64_u64(a * b, c);
    234}
    235EXPORT_SYMBOL(mul_u64_u64_div_u64);
    236#endif