2005-04-16 15:20:36 -07:00
/*
* Copyright ( C ) 2000 , 2004 Maciej W . Rozycki
2007-03-25 19:54:23 -07:00
* Copyright ( C ) 2003 , 07 Ralf Baechle ( ralf @ linux - mips . org )
2005-04-16 15:20:36 -07:00
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
# ifndef _ASM_DIV64_H
# define _ASM_DIV64_H
2007-03-25 19:54:23 -07:00
# include <linux/types.h>
2005-04-16 15:20:36 -07:00
# if (_MIPS_SZLONG == 32)
# include <asm/compiler.h>
/*
* No traps on overflows for any of these . . .
*/
# define do_div64_32(res, high, low, base) ({ \
2007-07-11 00:24:14 +09:00
unsigned long __quot32 , __mod32 ; \
2005-04-16 15:20:36 -07:00
unsigned long __cf , __tmp , __tmp2 , __i ; \
\
__asm__ ( " .set push \n \t " \
" .set noat \n \t " \
" .set noreorder \n \t " \
" move %2, $0 \n \t " \
" move %3, $0 \n \t " \
" b 1f \n \t " \
" li %4, 0x21 \n " \
" 0: \n \t " \
" sll $1, %0, 0x1 \n \t " \
" srl %3, %0, 0x1f \n \t " \
" or %0, $1, %5 \n \t " \
" sll %1, %1, 0x1 \n \t " \
" sll %2, %2, 0x1 \n " \
" 1: \n \t " \
" bnez %3, 2f \n \t " \
" sltu %5, %0, %z6 \n \t " \
" bnez %5, 3f \n " \
" 2: \n \t " \
" addiu %4, %4, -1 \n \t " \
" subu %0, %0, %z6 \n \t " \
" addiu %2, %2, 1 \n " \
" 3: \n \t " \
" bnez %4, 0b \n \t " \
" srl %5, %1, 0x1f \n \t " \
" .set pop " \
2007-07-11 00:24:14 +09:00
: " =&r " ( __mod32 ) , " =&r " ( __tmp ) , \
" =&r " ( __quot32 ) , " =&r " ( __cf ) , \
2005-04-16 15:20:36 -07:00
" =&r " ( __i ) , " =&r " ( __tmp2 ) \
: " Jr " ( base ) , " 0 " ( high ) , " 1 " ( low ) ) ; \
\
2007-07-11 00:24:14 +09:00
( res ) = __quot32 ; \
__mod32 ; } )
2005-04-16 15:20:36 -07:00
# define do_div(n, base) ({ \
unsigned long long __quot ; \
unsigned long __mod ; \
unsigned long long __div ; \
unsigned long __upper , __low , __high , __base ; \
\
__div = ( n ) ; \
__base = ( base ) ; \
\
__high = __div > > 32 ; \
__low = __div ; \
__upper = __high ; \
\
if ( __high ) \
__asm__ ( " divu $0, %z2, %z3 " \
: " =h " ( __upper ) , " =l " ( __high ) \
: " Jr " ( __high ) , " Jr " ( __base ) \
: GCC_REG_ACCUM ) ; \
\
__mod = do_div64_32 ( __low , __upper , __low , __base ) ; \
\
__quot = __high ; \
__quot = __quot < < 32 | __low ; \
( n ) = __quot ; \
__mod ; } )
2007-03-25 19:54:23 -07:00
extern uint64_t div64_64 ( uint64_t dividend , uint64_t divisor ) ;
2005-04-16 15:20:36 -07:00
# endif /* (_MIPS_SZLONG == 32) */
# if (_MIPS_SZLONG == 64)
/*
* Hey , we ' re already 64 - bit , no
* need to play games . .
*/
# define do_div(n, base) ({ \
unsigned long __quot ; \
unsigned int __mod ; \
unsigned long __div ; \
unsigned int __base ; \
\
__div = ( n ) ; \
__base = ( base ) ; \
\
__mod = __div % __base ; \
__quot = __div / __base ; \
\
( n ) = __quot ; \
__mod ; } )
2007-03-25 19:54:23 -07:00
static inline uint64_t div64_64 ( uint64_t dividend , uint64_t divisor )
{
return dividend / divisor ;
}
2005-04-16 15:20:36 -07:00
# endif /* (_MIPS_SZLONG == 64) */
# endif /* _ASM_DIV64_H */