2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 2003 Bernardo Innocenti < bernie @ develer . com >
*
* Based on former do_div ( ) implementation from asm - parisc / div64 . h :
* Copyright ( C ) 1999 Hewlett - Packard Co
* Copyright ( C ) 1999 David Mosberger - Tang < davidm @ hpl . hp . com >
*
*
* Generic C version of 64 bit / 32 bit division and modulo , with
* 64 bit result and 32 bit remainder .
*
* The fast case for ( n > > 32 = = 0 ) is handled inline by do_div ( ) .
*
* Code generated for this function might be very inefficient
* for some CPUs . __div64_32 ( ) can be overridden by linking arch - specific
* assembly versions such as arch / ppc / lib / div64 . S and arch / sh / lib / div64 . S .
*/
# include <linux/module.h>
2008-05-01 15:34:25 +04:00
# include <linux/math64.h>
2005-04-17 02:20:36 +04:00
/* Not needed on 64bit architectures */
# if BITS_PER_LONG == 32
2007-04-11 09:10:39 +04:00
uint32_t __attribute__ ( ( weak ) ) __div64_32 ( uint64_t * n , uint32_t base )
2005-04-17 02:20:36 +04:00
{
uint64_t rem = * n ;
uint64_t b = base ;
uint64_t res , d = 1 ;
uint32_t high = rem > > 32 ;
/* Reduce the thing a bit first */
res = 0 ;
if ( high > = base ) {
high / = base ;
res = ( uint64_t ) high < < 32 ;
rem - = ( uint64_t ) ( high * base ) < < 32 ;
}
while ( ( int64_t ) b > 0 & & b < rem ) {
b = b + b ;
d = d + d ;
}
do {
if ( rem > = b ) {
rem - = b ;
res + = d ;
}
b > > = 1 ;
d > > = 1 ;
} while ( d ) ;
* n = res ;
return rem ;
}
EXPORT_SYMBOL ( __div64_32 ) ;
2008-05-01 15:34:25 +04:00
# ifndef div_s64_rem
s64 div_s64_rem ( s64 dividend , s32 divisor , s32 * remainder )
{
u64 quotient ;
if ( dividend < 0 ) {
quotient = div_u64_rem ( - dividend , abs ( divisor ) , ( u32 * ) remainder ) ;
* remainder = - * remainder ;
if ( divisor > 0 )
quotient = - quotient ;
} else {
quotient = div_u64_rem ( dividend , abs ( divisor ) , ( u32 * ) remainder ) ;
if ( divisor < 0 )
quotient = - quotient ;
}
return quotient ;
}
EXPORT_SYMBOL ( div_s64_rem ) ;
# endif
2007-03-26 06:54:23 +04:00
/* 64bit divisor, dividend and result. dynamic precision */
uint64_t div64_64 ( uint64_t dividend , uint64_t divisor )
{
2007-03-22 22:10:18 +03:00
uint32_t high , d ;
2007-03-26 06:54:23 +04:00
2007-03-22 22:10:18 +03:00
high = divisor > > 32 ;
if ( high ) {
unsigned int shift = fls ( high ) ;
2007-03-26 06:54:23 +04:00
d = divisor > > shift ;
dividend > > = shift ;
2007-03-22 22:10:18 +03:00
} else
d = divisor ;
2007-03-26 06:54:23 +04:00
2007-03-22 22:10:18 +03:00
do_div ( dividend , d ) ;
2007-03-26 06:54:23 +04:00
return dividend ;
}
EXPORT_SYMBOL ( div64_64 ) ;
2005-04-17 02:20:36 +04:00
# endif /* BITS_PER_LONG == 32 */