div64.h 2.6 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
Ralf Bächle's avatar
Ralf Bächle committed
2
 * Copyright (C) 2000, 2004  Maciej W. Rozycki
Ralf Bächle's avatar
Ralf Bächle committed
3
 * Copyright (C) 2003 Ralf Baechle
Linus Torvalds's avatar
Linus Torvalds committed
4 5 6 7 8 9 10 11
 *
 * 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

Ralf Bächle's avatar
Ralf Bächle committed
12 13
#if (_MIPS_SZLONG == 32)

Ralf Bächle's avatar
Ralf Bächle committed
14 15
#include <asm/compiler.h>

Linus Torvalds's avatar
Linus Torvalds committed
16
/*
Linus Torvalds's avatar
Linus Torvalds committed
17
 * No traps on overflows for any of these...
Linus Torvalds's avatar
Linus Torvalds committed
18
 */
Linus Torvalds's avatar
Linus Torvalds committed
19 20 21

#define do_div64_32(res, high, low, base) ({ \
	unsigned long __quot, __mod; \
22
	unsigned long __cf, __tmp, __tmp2, __i; \
Linus Torvalds's avatar
Linus Torvalds committed
23 24 25 26
	\
	__asm__(".set	push\n\t" \
		".set	noat\n\t" \
		".set	noreorder\n\t" \
27 28
		"move	%2, $0\n\t" \
		"move	%3, $0\n\t" \
Linus Torvalds's avatar
Linus Torvalds committed
29
		"b	1f\n\t" \
30
		" li	%4, 0x21\n" \
Linus Torvalds's avatar
Linus Torvalds committed
31
		"0:\n\t" \
32 33 34 35 36
		"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" \
Linus Torvalds's avatar
Linus Torvalds committed
37
		"1:\n\t" \
38 39 40
		"bnez	%3, 2f\n\t" \
		" sltu	%5, %0, %z6\n\t" \
		"bnez	%5, 3f\n" \
Linus Torvalds's avatar
Linus Torvalds committed
41
		"2:\n\t" \
42 43 44
		" addiu	%4, %4, -1\n\t" \
		"subu	%0, %0, %z6\n\t" \
		"addiu	%2, %2, 1\n" \
Linus Torvalds's avatar
Linus Torvalds committed
45
		"3:\n\t" \
46 47
		"bnez	%4, 0b\n\t" \
		" srl	%5, %1, 0x1f\n\t" \
Linus Torvalds's avatar
Linus Torvalds committed
48 49
		".set	pop" \
		: "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
50 51
		  "=&r" (__i), "=&r" (__tmp2) \
		: "Jr" (base), "0" (high), "1" (low)); \
Linus Torvalds's avatar
Linus Torvalds committed
52 53 54 55 56 57
	\
	(res) = __quot; \
	__mod; })

#define do_div(n, base) ({ \
	unsigned long long __quot; \
58 59 60 61 62 63
	unsigned long __mod; \
	unsigned long long __div; \
	unsigned long __upper, __low, __high, __base; \
	\
	__div = (n); \
	__base = (base); \
Linus Torvalds's avatar
Linus Torvalds committed
64
	\
65 66
	__high = __div >> 32; \
	__low = __div; \
Linus Torvalds's avatar
Linus Torvalds committed
67 68 69
	__upper = __high; \
	\
	if (__high) \
70
		__asm__("divu	$0, %z2, %z3" \
Linus Torvalds's avatar
Linus Torvalds committed
71
			: "=h" (__upper), "=l" (__high) \
Ralf Bächle's avatar
Ralf Bächle committed
72 73
			: "Jr" (__high), "Jr" (__base) \
			: GCC_REG_ACCUM); \
Linus Torvalds's avatar
Linus Torvalds committed
74
	\
75
	__mod = do_div64_32(__low, __upper, __low, __base); \
Linus Torvalds's avatar
Linus Torvalds committed
76 77 78 79 80
	\
	__quot = __high; \
	__quot = __quot << 32 | __low; \
	(n) = __quot; \
	__mod; })
Ralf Bächle's avatar
Ralf Bächle committed
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
#endif /* (_MIPS_SZLONG == 32) */

#if (_MIPS_SZLONG == 64)

/*
 * Don't use this one in new code
 */
#define do_div64_32(res, high, low, base) ({ \
	unsigned int __quot, __mod; \
	unsigned long __div; \
	unsigned int __low, __high, __base; \
	\
	__high = (high); \
	__low = (low); \
	__div = __high; \
	__div = __div << 32 | __low; \
	__base = (base); \
	\
	__mod = __div % __base; \
	__div = __div / __base; \
	\
	__quot = __div; \
	(res) = __quot; \
	__mod; })

/*
 * 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; })

#endif /* (_MIPS_SZLONG == 64) */
Linus Torvalds's avatar
Linus Torvalds committed
126

Linus Torvalds's avatar
Linus Torvalds committed
127
#endif /* _ASM_DIV64_H */