| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | #ifndef __ASM_ARM_DIV64 | 
 | 2 | #define __ASM_ARM_DIV64 | 
 | 3 |  | 
 | 4 | #include <asm/system.h> | 
 | 5 |  | 
 | 6 | /* | 
 | 7 |  * The semantics of do_div() are: | 
 | 8 |  * | 
 | 9 |  * uint32_t do_div(uint64_t *n, uint32_t base) | 
 | 10 |  * { | 
 | 11 |  * 	uint32_t remainder = *n % base; | 
 | 12 |  * 	*n = *n / base; | 
 | 13 |  * 	return remainder; | 
 | 14 |  * } | 
 | 15 |  * | 
 | 16 |  * In other words, a 64-bit dividend with a 32-bit divisor producing | 
 | 17 |  * a 64-bit result and a 32-bit remainder.  To accomplish this optimally | 
 | 18 |  * we call a special __do_div64 helper with completely non standard | 
 | 19 |  * calling convention for arguments and results (beware). | 
 | 20 |  */ | 
 | 21 |  | 
 | 22 | #ifdef __ARMEB__ | 
 | 23 | #define __xh "r0" | 
 | 24 | #define __xl "r1" | 
 | 25 | #else | 
 | 26 | #define __xl "r0" | 
 | 27 | #define __xh "r1" | 
 | 28 | #endif | 
 | 29 |  | 
 | 30 | #define do_div(n,base)						\ | 
 | 31 | ({								\ | 
 | 32 | 	register unsigned int __base      asm("r4") = base;	\ | 
 | 33 | 	register unsigned long long __n   asm("r0") = n;	\ | 
 | 34 | 	register unsigned long long __res asm("r2");		\ | 
 | 35 | 	register unsigned int __rem       asm(__xh);		\ | 
 | 36 | 	asm(	__asmeq("%0", __xh)				\ | 
 | 37 | 		__asmeq("%1", "r2")				\ | 
 | 38 | 		__asmeq("%2", "r0")				\ | 
 | 39 | 		__asmeq("%3", "r4")				\ | 
 | 40 | 		"bl	__do_div64"				\ | 
 | 41 | 		: "=r" (__rem), "=r" (__res)			\ | 
 | 42 | 		: "r" (__n), "r" (__base)			\ | 
 | 43 | 		: "ip", "lr", "cc");				\ | 
 | 44 | 	n = __res;						\ | 
 | 45 | 	__rem;							\ | 
 | 46 | }) | 
 | 47 |  | 
 | 48 | #endif |