LCOV - code coverage report
Current view: top level - lib - div64.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 14 60 23.3 %
Date: 2015-04-12 14:34:49 Functions: 2 6 33.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
       3             :  *
       4             :  * Based on former do_div() implementation from asm-parisc/div64.h:
       5             :  *      Copyright (C) 1999 Hewlett-Packard Co
       6             :  *      Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
       7             :  *
       8             :  *
       9             :  * Generic C version of 64bit/32bit division and modulo, with
      10             :  * 64bit result and 32bit remainder.
      11             :  *
      12             :  * The fast case for (n>>32 == 0) is handled inline by do_div(). 
      13             :  *
      14             :  * Code generated for this function might be very inefficient
      15             :  * for some CPUs. __div64_32() can be overridden by linking arch-specific
      16             :  * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.
      17             :  */
      18             : 
      19             : #include <linux/export.h>
      20             : #include <linux/kernel.h>
      21             : #include <linux/math64.h>
      22             : 
      23             : /* Not needed on 64bit architectures */
      24             : #if BITS_PER_LONG == 32
      25             : 
      26           0 : uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
      27             : {
      28           0 :         uint64_t rem = *n;
      29           0 :         uint64_t b = base;
      30             :         uint64_t res, d = 1;
      31           0 :         uint32_t high = rem >> 32;
      32             : 
      33             :         /* Reduce the thing a bit first */
      34             :         res = 0;
      35           0 :         if (high >= base) {
      36           0 :                 high /= base;
      37           0 :                 res = (uint64_t) high << 32;
      38           0 :                 rem -= (uint64_t) (high*base) << 32;
      39             :         }
      40             : 
      41           0 :         while ((int64_t)b > 0 && b < rem) {
      42           0 :                 b = b+b;
      43           0 :                 d = d+d;
      44             :         }
      45             : 
      46             :         do {
      47           0 :                 if (rem >= b) {
      48           0 :                         rem -= b;
      49           0 :                         res += d;
      50             :                 }
      51           0 :                 b >>= 1;
      52           0 :                 d >>= 1;
      53           0 :         } while (d);
      54             : 
      55           0 :         *n = res;
      56           0 :         return rem;
      57             : }
      58             : 
      59             : EXPORT_SYMBOL(__div64_32);
      60             : 
      61             : #ifndef div_s64_rem
      62      235951 : s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
      63             : {
      64             :         u64 quotient;
      65             : 
      66      235951 :         if (dividend < 0) {
      67           1 :                 quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
      68           1 :                 *remainder = -*remainder;
      69           1 :                 if (divisor > 0)
      70           1 :                         quotient = -quotient;
      71             :         } else {
      72      235950 :                 quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
      73      235950 :                 if (divisor < 0)
      74           0 :                         quotient = -quotient;
      75             :         }
      76      235951 :         return quotient;
      77             : }
      78             : EXPORT_SYMBOL(div_s64_rem);
      79             : #endif
      80             : 
      81             : /**
      82             :  * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
      83             :  * @dividend:   64bit dividend
      84             :  * @divisor:    64bit divisor
      85             :  * @remainder:  64bit remainder
      86             :  *
      87             :  * This implementation is a comparable to algorithm used by div64_u64.
      88             :  * But this operation, which includes math for calculating the remainder,
      89             :  * is kept distinct to avoid slowing down the div64_u64 operation on 32bit
      90             :  * systems.
      91             :  */
      92             : #ifndef div64_u64_rem
      93           0 : u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
      94             : {
      95           0 :         u32 high = divisor >> 32;
      96             :         u64 quot;
      97             : 
      98           0 :         if (high == 0) {
      99             :                 u32 rem32;
     100           0 :                 quot = div_u64_rem(dividend, divisor, &rem32);
     101           0 :                 *remainder = rem32;
     102             :         } else {
     103           0 :                 int n = 1 + fls(high);
     104           0 :                 quot = div_u64(dividend >> n, divisor >> n);
     105             : 
     106           0 :                 if (quot != 0)
     107           0 :                         quot--;
     108             : 
     109           0 :                 *remainder = dividend - quot * divisor;
     110           0 :                 if (*remainder >= divisor) {
     111           0 :                         quot++;
     112           0 :                         *remainder -= divisor;
     113             :                 }
     114             :         }
     115             : 
     116           0 :         return quot;
     117             : }
     118             : EXPORT_SYMBOL(div64_u64_rem);
     119             : #endif
     120             : 
     121             : /**
     122             :  * div64_u64 - unsigned 64bit divide with 64bit divisor
     123             :  * @dividend:   64bit dividend
     124             :  * @divisor:    64bit divisor
     125             :  *
     126             :  * This implementation is a modified version of the algorithm proposed
     127             :  * by the book 'Hacker's Delight'.  The original source and full proof
     128             :  * can be found here and is available for use without restriction.
     129             :  *
     130             :  * 'http://www.hackersdelight.org/HDcode/newCode/divDouble.c.txt'
     131             :  */
     132             : #ifndef div64_u64
     133           2 : u64 div64_u64(u64 dividend, u64 divisor)
     134             : {
     135           2 :         u32 high = divisor >> 32;
     136             :         u64 quot;
     137             : 
     138           2 :         if (high == 0) {
     139           2 :                 quot = div_u64(dividend, divisor);
     140             :         } else {
     141           0 :                 int n = 1 + fls(high);
     142           0 :                 quot = div_u64(dividend >> n, divisor >> n);
     143             : 
     144           0 :                 if (quot != 0)
     145           0 :                         quot--;
     146           0 :                 if ((dividend - quot * divisor) >= divisor)
     147           0 :                         quot++;
     148             :         }
     149             : 
     150           2 :         return quot;
     151             : }
     152             : EXPORT_SYMBOL(div64_u64);
     153             : #endif
     154             : 
     155             : /**
     156             :  * div64_s64 - signed 64bit divide with 64bit divisor
     157             :  * @dividend:   64bit dividend
     158             :  * @divisor:    64bit divisor
     159             :  */
     160             : #ifndef div64_s64
     161           0 : s64 div64_s64(s64 dividend, s64 divisor)
     162             : {
     163             :         s64 quot, t;
     164             : 
     165           0 :         quot = div64_u64(abs64(dividend), abs64(divisor));
     166           0 :         t = (dividend ^ divisor) >> 63;
     167             : 
     168           0 :         return (quot ^ t) - t;
     169             : }
     170             : EXPORT_SYMBOL(div64_s64);
     171             : #endif
     172             : 
     173             : #endif /* BITS_PER_LONG == 32 */
     174             : 
     175             : /*
     176             :  * Iterative div/mod for use when dividend is not expected to be much
     177             :  * bigger than divisor.
     178             :  */
     179           0 : u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
     180             : {
     181           0 :         return __iter_div_u64_rem(dividend, divisor, remainder);
     182             : }
     183             : EXPORT_SYMBOL(iter_div_u64_rem);

Generated by: LCOV version 1.11