/* * include/asm-mips/div64.h * * Copyright (C) 2000 Maciej W. Rozycki * * 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 #include /* * No traps on overflows for any of these... */ #if (_MIPS_ISA == _MIPS_ISA_MIPS1 ) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \ (_MIPS_ISA == _MIPS_ISA_MIPS32) #define do_div64_32(res, high, low, base) ({ \ unsigned long __quot, __mod; \ unsigned long __cf, __tmp, __i; \ \ __asm__(".set push\n\t" \ ".set noat\n\t" \ ".set noreorder\n\t" \ "b 1f\n\t" \ " li %4,0x21\n" \ "0:\n\t" \ "sll $1,%0,0x1\n\t" \ "srl %3,%0,0x1f\n\t" \ "or %0,$1,$2\n\t" \ "sll %1,%1,0x1\n\t" \ "sll %2,%2,0x1\n" \ "1:\n\t" \ "bnez %3,2f\n\t" \ "sltu $2,%0,%z5\n\t" \ "bnez $2,3f\n\t" \ "2:\n\t" \ " addiu %4,%4,-1\n\t" \ "subu %0,%0,%z5\n\t" \ "addiu %2,%2,1\n" \ "3:\n\t" \ "bnez %4,0b\n\t" \ " srl $2,%1,0x1f\n\t" \ ".set pop" \ : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ "=&r" (__i) \ : "Jr" (base), "0" (high), "1" (low), "2" (0), "3" (0) \ /* Aarrgh! Ran out of gcc's limit on constraints... */ \ : "$1", "$2"); \ \ (res) = __quot; \ __mod; }) #define do_div(n, base) ({ \ unsigned long long __quot; \ unsigned long __upper, __low, __high, __mod; \ \ __quot = (n); \ __high = __quot >> 32; \ __low = __quot; \ __upper = __high; \ \ if (__high) \ __asm__("divu $0,%z2,%z3" \ : "=h" (__upper), "=l" (__high) \ : "Jr" (__high), "Jr" (base)); \ \ __mod = do_div64_32(__low, __upper, __low, base); \ \ __quot = __high; \ __quot = __quot << 32 | __low; \ (n) = __quot; \ __mod; }) #else #define do_div64_32(res, high, low, base) ({ \ unsigned long __quot, __mod, __r0; \ \ __asm__("dsll32 %2,%z3,0\n\t" \ "or %2,%2,%z4\n\t" \ "ddivu $0,%2,%z5" \ : "=h" (__mod), "=l" (__quot), "=&r" (__r0) \ : "Jr" (high), "Jr" (low), "Jr" (base)); \ \ (res) = __quot; \ __mod; }) #define do_div(n, base) ({ \ unsigned long long __quot; \ unsigned long __mod, __r0; \ \ __quot = (n); \ \ __asm__("dsll32 %2,%M3,0\n\t" \ "or %2,%2,%L3\n\t" \ "ddivu $0,%2,%z4\n\t" \ "mflo %L1\n\t" \ "dsra32 %M1,%L1,0\n\t" \ "dsll32 %L1,%L1,0\n\t" \ "dsra32 %L1,%L1,0" \ : "=h" (__mod), "=r" (__quot), "=&r" (__r0) \ : "r" (n), "Jr" (base)); \ \ (n) = __quot; \ __mod; }) #endif #endif /* _ASM_DIV64_H */