xref: /dflybsd-src/sys/dev/drm/include/linux/math64.h (revision 563a794d0be644e68c7cbe435d71320432b64ede)
1*563a794dSFrançois Tigeot /*-
2*563a794dSFrançois Tigeot  * Copyright (c) 2007 Cisco Systems, Inc.  All rights reserved.
3*563a794dSFrançois Tigeot  * Copyright (c) 2014 Mellanox Technologies, Ltd. All rights reserved.
4*563a794dSFrançois Tigeot  * All rights reserved.
5*563a794dSFrançois Tigeot  *
6*563a794dSFrançois Tigeot  * Redistribution and use in source and binary forms, with or without
7*563a794dSFrançois Tigeot  * modification, are permitted provided that the following conditions
8*563a794dSFrançois Tigeot  * are met:
9*563a794dSFrançois Tigeot  * 1. Redistributions of source code must retain the above copyright
10*563a794dSFrançois Tigeot  *    notice unmodified, this list of conditions, and the following
11*563a794dSFrançois Tigeot  *    disclaimer.
12*563a794dSFrançois Tigeot  * 2. Redistributions in binary form must reproduce the above copyright
13*563a794dSFrançois Tigeot  *    notice, this list of conditions and the following disclaimer in the
14*563a794dSFrançois Tigeot  *    documentation and/or other materials provided with the distribution.
15*563a794dSFrançois Tigeot  *
16*563a794dSFrançois Tigeot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*563a794dSFrançois Tigeot  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*563a794dSFrançois Tigeot  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*563a794dSFrançois Tigeot  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*563a794dSFrançois Tigeot  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*563a794dSFrançois Tigeot  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*563a794dSFrançois Tigeot  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*563a794dSFrançois Tigeot  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*563a794dSFrançois Tigeot  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*563a794dSFrançois Tigeot  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*563a794dSFrançois Tigeot  */
27*563a794dSFrançois Tigeot 
28*563a794dSFrançois Tigeot #ifndef _LINUX_MATH64_H
29*563a794dSFrançois Tigeot #define _LINUX_MATH64_H
30*563a794dSFrançois Tigeot 
31*563a794dSFrançois Tigeot #include <linux/types.h>
32*563a794dSFrançois Tigeot #include <linux/bitops.h>
33*563a794dSFrançois Tigeot 
34*563a794dSFrançois Tigeot #if BITS_PER_LONG == 64
35*563a794dSFrançois Tigeot 
36*563a794dSFrançois Tigeot # define do_div(n, base) ({                                    \
37*563a794dSFrançois Tigeot 	uint32_t __base = (base);                               \
38*563a794dSFrançois Tigeot 	uint32_t __rem;                                         \
39*563a794dSFrançois Tigeot 	__rem = ((uint64_t)(n)) % __base;                       \
40*563a794dSFrançois Tigeot 	(n) = ((uint64_t)(n)) / __base;                         \
41*563a794dSFrançois Tigeot 	__rem;                                                  \
42*563a794dSFrançois Tigeot })
43*563a794dSFrançois Tigeot 
44*563a794dSFrançois Tigeot /**
45*563a794dSFrançois Tigeot * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
46*563a794dSFrançois Tigeot *
47*563a794dSFrançois Tigeot * This is commonly provided by 32bit archs to provide an optimized 64bit
48*563a794dSFrançois Tigeot * divide.
49*563a794dSFrançois Tigeot */
50*563a794dSFrançois Tigeot static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
51*563a794dSFrançois Tigeot {
52*563a794dSFrançois Tigeot         *remainder = dividend % divisor;
53*563a794dSFrançois Tigeot         return dividend / divisor;
54*563a794dSFrançois Tigeot }
55*563a794dSFrançois Tigeot 
56*563a794dSFrançois Tigeot 
57*563a794dSFrançois Tigeot #elif BITS_PER_LONG == 32
58*563a794dSFrançois Tigeot 
59*563a794dSFrançois Tigeot static uint32_t __div64_32(uint64_t *n, uint32_t base)
60*563a794dSFrançois Tigeot {
61*563a794dSFrançois Tigeot 	uint64_t rem = *n;
62*563a794dSFrançois Tigeot 	uint64_t b = base;
63*563a794dSFrançois Tigeot 	uint64_t res, d = 1;
64*563a794dSFrançois Tigeot 	uint32_t high = rem >> 32;
65*563a794dSFrançois Tigeot 
66*563a794dSFrançois Tigeot 	/* Reduce the thing a bit first */
67*563a794dSFrançois Tigeot 	res = 0;
68*563a794dSFrançois Tigeot 	if (high >= base) {
69*563a794dSFrançois Tigeot 		high /= base;
70*563a794dSFrançois Tigeot 		res = (uint64_t) high << 32;
71*563a794dSFrançois Tigeot 		rem -= (uint64_t) (high*base) << 32;
72*563a794dSFrançois Tigeot 	}
73*563a794dSFrançois Tigeot 
74*563a794dSFrançois Tigeot 	while ((int64_t)b > 0 && b < rem) {
75*563a794dSFrançois Tigeot 		b = b+b;
76*563a794dSFrançois Tigeot 		d = d+d;
77*563a794dSFrançois Tigeot 	}
78*563a794dSFrançois Tigeot 
79*563a794dSFrançois Tigeot 	do {
80*563a794dSFrançois Tigeot 		if (rem >= b) {
81*563a794dSFrançois Tigeot 			rem -= b;
82*563a794dSFrançois Tigeot 			res += d;
83*563a794dSFrançois Tigeot 		}
84*563a794dSFrançois Tigeot 		b >>= 1;
85*563a794dSFrançois Tigeot 		d >>= 1;
86*563a794dSFrançois Tigeot 	} while (d);
87*563a794dSFrançois Tigeot 
88*563a794dSFrançois Tigeot 	*n = res;
89*563a794dSFrançois Tigeot 	return rem;
90*563a794dSFrançois Tigeot }
91*563a794dSFrançois Tigeot 
92*563a794dSFrançois Tigeot # define do_div(n, base) ({                            \
93*563a794dSFrançois Tigeot 	uint32_t __base = (base);                       \
94*563a794dSFrançois Tigeot 	uint32_t __rem;                                 \
95*563a794dSFrançois Tigeot 	(void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
96*563a794dSFrançois Tigeot 	if (likely(((n) >> 32) == 0)) {                 \
97*563a794dSFrançois Tigeot 		__rem = (uint32_t)(n) % __base;         \
98*563a794dSFrançois Tigeot 		(n) = (uint32_t)(n) / __base;           \
99*563a794dSFrançois Tigeot 	} else                                          \
100*563a794dSFrançois Tigeot 		__rem = __div64_32(&(n), __base);       \
101*563a794dSFrançois Tigeot 	__rem;                                          \
102*563a794dSFrançois Tigeot })
103*563a794dSFrançois Tigeot 
104*563a794dSFrançois Tigeot #ifndef div_u64_rem
105*563a794dSFrançois Tigeot static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
106*563a794dSFrançois Tigeot {
107*563a794dSFrançois Tigeot         *remainder = do_div(dividend, divisor);
108*563a794dSFrançois Tigeot         return dividend;
109*563a794dSFrançois Tigeot }
110*563a794dSFrançois Tigeot #endif
111*563a794dSFrançois Tigeot 
112*563a794dSFrançois Tigeot #endif /* BITS_PER_LONG */
113*563a794dSFrançois Tigeot 
114*563a794dSFrançois Tigeot 
115*563a794dSFrançois Tigeot 
116*563a794dSFrançois Tigeot /**
117*563a794dSFrançois Tigeot  ** div_u64 - unsigned 64bit divide with 32bit divisor
118*563a794dSFrançois Tigeot  **
119*563a794dSFrançois Tigeot  ** This is the most common 64bit divide and should be used if possible,
120*563a794dSFrançois Tigeot  ** as many 32bit archs can optimize this variant better than a full 64bit
121*563a794dSFrançois Tigeot  ** divide.
122*563a794dSFrançois Tigeot  *  */
123*563a794dSFrançois Tigeot #ifndef div_u64
124*563a794dSFrançois Tigeot 
125*563a794dSFrançois Tigeot static inline u64 div_u64(u64 dividend, u32 divisor)
126*563a794dSFrançois Tigeot {
127*563a794dSFrançois Tigeot         u32 remainder;
128*563a794dSFrançois Tigeot         return div_u64_rem(dividend, divisor, &remainder);
129*563a794dSFrançois Tigeot }
130*563a794dSFrançois Tigeot #endif
131*563a794dSFrançois Tigeot 
132*563a794dSFrançois Tigeot #endif	/* _LINUX_MATH64_H */
133