xref: /openbmc/linux/include/asm-generic/div64.h (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds #ifndef _ASM_GENERIC_DIV64_H
2*1da177e4SLinus Torvalds #define _ASM_GENERIC_DIV64_H
3*1da177e4SLinus Torvalds /*
4*1da177e4SLinus Torvalds  * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
5*1da177e4SLinus Torvalds  * Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
6*1da177e4SLinus Torvalds  *
7*1da177e4SLinus Torvalds  * The semantics of do_div() are:
8*1da177e4SLinus Torvalds  *
9*1da177e4SLinus Torvalds  * uint32_t do_div(uint64_t *n, uint32_t base)
10*1da177e4SLinus Torvalds  * {
11*1da177e4SLinus Torvalds  * 	uint32_t remainder = *n % base;
12*1da177e4SLinus Torvalds  * 	*n = *n / base;
13*1da177e4SLinus Torvalds  * 	return remainder;
14*1da177e4SLinus Torvalds  * }
15*1da177e4SLinus Torvalds  *
16*1da177e4SLinus Torvalds  * NOTE: macro parameter n is evaluated multiple times,
17*1da177e4SLinus Torvalds  *       beware of side effects!
18*1da177e4SLinus Torvalds  */
19*1da177e4SLinus Torvalds 
20*1da177e4SLinus Torvalds #include <linux/types.h>
21*1da177e4SLinus Torvalds #include <linux/compiler.h>
22*1da177e4SLinus Torvalds 
23*1da177e4SLinus Torvalds #if BITS_PER_LONG == 64
24*1da177e4SLinus Torvalds 
25*1da177e4SLinus Torvalds # define do_div(n,base) ({					\
26*1da177e4SLinus Torvalds 	uint32_t __base = (base);				\
27*1da177e4SLinus Torvalds 	uint32_t __rem;						\
28*1da177e4SLinus Torvalds 	__rem = ((uint64_t)(n)) % __base;			\
29*1da177e4SLinus Torvalds 	(n) = ((uint64_t)(n)) / __base;				\
30*1da177e4SLinus Torvalds 	__rem;							\
31*1da177e4SLinus Torvalds  })
32*1da177e4SLinus Torvalds 
33*1da177e4SLinus Torvalds #elif BITS_PER_LONG == 32
34*1da177e4SLinus Torvalds 
35*1da177e4SLinus Torvalds extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
36*1da177e4SLinus Torvalds 
37*1da177e4SLinus Torvalds /* The unnecessary pointer compare is there
38*1da177e4SLinus Torvalds  * to check for type safety (n must be 64bit)
39*1da177e4SLinus Torvalds  */
40*1da177e4SLinus Torvalds # define do_div(n,base) ({				\
41*1da177e4SLinus Torvalds 	uint32_t __base = (base);			\
42*1da177e4SLinus Torvalds 	uint32_t __rem;					\
43*1da177e4SLinus Torvalds 	(void)(((typeof((n)) *)0) == ((uint64_t *)0));	\
44*1da177e4SLinus Torvalds 	if (likely(((n) >> 32) == 0)) {			\
45*1da177e4SLinus Torvalds 		__rem = (uint32_t)(n) % __base;		\
46*1da177e4SLinus Torvalds 		(n) = (uint32_t)(n) / __base;		\
47*1da177e4SLinus Torvalds 	} else 						\
48*1da177e4SLinus Torvalds 		__rem = __div64_32(&(n), __base);	\
49*1da177e4SLinus Torvalds 	__rem;						\
50*1da177e4SLinus Torvalds  })
51*1da177e4SLinus Torvalds 
52*1da177e4SLinus Torvalds #else /* BITS_PER_LONG == ?? */
53*1da177e4SLinus Torvalds 
54*1da177e4SLinus Torvalds # error do_div() does not yet support the C64
55*1da177e4SLinus Torvalds 
56*1da177e4SLinus Torvalds #endif /* BITS_PER_LONG */
57*1da177e4SLinus Torvalds 
58*1da177e4SLinus Torvalds #endif /* _ASM_GENERIC_DIV64_H */
59