Home | History | Annotate | Download | only in asm-mips
      1 /*
      2  * Copyright (C) 2000, 2004  Maciej W. Rozycki
      3  * Copyright (C) 2003, 07 Ralf Baechle (ralf (at) 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