xref: /openbmc/linux/include/asm-generic/div64.h (revision 911918aa7ef6f868c135505b0015e42072c54682)
11da177e4SLinus Torvalds #ifndef _ASM_GENERIC_DIV64_H
21da177e4SLinus Torvalds #define _ASM_GENERIC_DIV64_H
31da177e4SLinus Torvalds /*
41da177e4SLinus Torvalds  * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
51da177e4SLinus Torvalds  * Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * The semantics of do_div() are:
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * uint32_t do_div(uint64_t *n, uint32_t base)
101da177e4SLinus Torvalds  * {
111da177e4SLinus Torvalds  * 	uint32_t remainder = *n % base;
121da177e4SLinus Torvalds  * 	*n = *n / base;
131da177e4SLinus Torvalds  * 	return remainder;
141da177e4SLinus Torvalds  * }
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  * NOTE: macro parameter n is evaluated multiple times,
171da177e4SLinus Torvalds  *       beware of side effects!
181da177e4SLinus Torvalds  */
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds #include <linux/types.h>
211da177e4SLinus Torvalds #include <linux/compiler.h>
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #if BITS_PER_LONG == 64
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds # define do_div(n,base) ({					\
261da177e4SLinus Torvalds 	uint32_t __base = (base);				\
271da177e4SLinus Torvalds 	uint32_t __rem;						\
281da177e4SLinus Torvalds 	__rem = ((uint64_t)(n)) % __base;			\
291da177e4SLinus Torvalds 	(n) = ((uint64_t)(n)) / __base;				\
301da177e4SLinus Torvalds 	__rem;							\
311da177e4SLinus Torvalds  })
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds #elif BITS_PER_LONG == 32
341da177e4SLinus Torvalds 
35*911918aaSNicolas Pitre #include <linux/log2.h>
36*911918aaSNicolas Pitre 
371da177e4SLinus Torvalds extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds /* The unnecessary pointer compare is there
401da177e4SLinus Torvalds  * to check for type safety (n must be 64bit)
411da177e4SLinus Torvalds  */
421da177e4SLinus Torvalds # define do_div(n,base) ({				\
431da177e4SLinus Torvalds 	uint32_t __base = (base);			\
441da177e4SLinus Torvalds 	uint32_t __rem;					\
451da177e4SLinus Torvalds 	(void)(((typeof((n)) *)0) == ((uint64_t *)0));	\
46*911918aaSNicolas Pitre 	if (__builtin_constant_p(__base) &&		\
47*911918aaSNicolas Pitre 	    is_power_of_2(__base)) {			\
48*911918aaSNicolas Pitre 		__rem = (n) & (__base - 1);		\
49*911918aaSNicolas Pitre 		(n) >>= ilog2(__base);			\
50*911918aaSNicolas Pitre 	} else if (likely(((n) >> 32) == 0)) {		\
511da177e4SLinus Torvalds 		__rem = (uint32_t)(n) % __base;		\
521da177e4SLinus Torvalds 		(n) = (uint32_t)(n) / __base;		\
531da177e4SLinus Torvalds 	} else 						\
541da177e4SLinus Torvalds 		__rem = __div64_32(&(n), __base);	\
551da177e4SLinus Torvalds 	__rem;						\
561da177e4SLinus Torvalds  })
571da177e4SLinus Torvalds 
581da177e4SLinus Torvalds #else /* BITS_PER_LONG == ?? */
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds # error do_div() does not yet support the C64
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds #endif /* BITS_PER_LONG */
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds #endif /* _ASM_GENERIC_DIV64_H */
65