xref: /openbmc/linux/arch/mips/include/asm/div64.h (revision 8569c914)
1 /*
2  * Copyright (C) 2000, 2004  Maciej W. Rozycki
3  * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
4  *
5  * This file is subject to the terms and conditions of the GNU General Public
6  * License.  See the file "COPYING" in the main directory of this archive
7  * for more details.
8  */
9 #ifndef _ASM_DIV64_H
10 #define _ASM_DIV64_H
11 
12 #include <linux/types.h>
13 
14 #if (_MIPS_SZLONG == 32)
15 
16 #include <asm/compiler.h>
17 
18 /*
19  * No traps on overflows for any of these...
20  */
21 
22 #define do_div64_32(res, high, low, base) ({ \
23 	unsigned long __quot32, __mod32; \
24 	unsigned long __cf, __tmp, __tmp2, __i; \
25 	\
26 	__asm__(".set	push\n\t" \
27 		".set	noat\n\t" \
28 		".set	noreorder\n\t" \
29 		"move	%2, $0\n\t" \
30 		"move	%3, $0\n\t" \
31 		"b	1f\n\t" \
32 		" li	%4, 0x21\n" \
33 		"0:\n\t" \
34 		"sll	$1, %0, 0x1\n\t" \
35 		"srl	%3, %0, 0x1f\n\t" \
36 		"or	%0, $1, %5\n\t" \
37 		"sll	%1, %1, 0x1\n\t" \
38 		"sll	%2, %2, 0x1\n" \
39 		"1:\n\t" \
40 		"bnez	%3, 2f\n\t" \
41 		" sltu	%5, %0, %z6\n\t" \
42 		"bnez	%5, 3f\n" \
43 		"2:\n\t" \
44 		" addiu	%4, %4, -1\n\t" \
45 		"subu	%0, %0, %z6\n\t" \
46 		"addiu	%2, %2, 1\n" \
47 		"3:\n\t" \
48 		"bnez	%4, 0b\n\t" \
49 		" srl	%5, %1, 0x1f\n\t" \
50 		".set	pop" \
51 		: "=&r" (__mod32), "=&r" (__tmp), \
52 		  "=&r" (__quot32), "=&r" (__cf), \
53 		  "=&r" (__i), "=&r" (__tmp2) \
54 		: "Jr" (base), "0" (high), "1" (low)); \
55 	\
56 	(res) = __quot32; \
57 	__mod32; })
58 
59 #define do_div(n, base) ({ \
60 	unsigned long long __quot; \
61 	unsigned long __mod; \
62 	unsigned long long __div; \
63 	unsigned long __upper, __low, __high, __base; \
64 	\
65 	__div = (n); \
66 	__base = (base); \
67 	\
68 	__high = __div >> 32; \
69 	__low = __div; \
70 	__upper = __high; \
71 	\
72 	if (__high) \
73 		__asm__("divu	$0, %z2, %z3" \
74 			: "=h" (__upper), "=l" (__high) \
75 			: "Jr" (__high), "Jr" (__base) \
76 			: GCC_REG_ACCUM); \
77 	\
78 	__mod = do_div64_32(__low, __upper, __low, __base); \
79 	\
80 	__quot = __high; \
81 	__quot = __quot << 32 | __low; \
82 	(n) = __quot; \
83 	__mod; })
84 
85 #endif /* (_MIPS_SZLONG == 32) */
86 
87 #if (_MIPS_SZLONG == 64)
88 
89 /*
90  * Hey, we're already 64-bit, no
91  * need to play games..
92  */
93 #define do_div(n, base) ({ \
94 	unsigned long __quot; \
95 	unsigned int __mod; \
96 	unsigned long __div; \
97 	unsigned int __base; \
98 	\
99 	__div = (n); \
100 	__base = (base); \
101 	\
102 	__mod = __div % __base; \
103 	__quot = __div / __base; \
104 	\
105 	(n) = __quot; \
106 	__mod; })
107 
108 #endif /* (_MIPS_SZLONG == 64) */
109 
110 #endif /* _ASM_DIV64_H */
111