Home | History | Annotate | Download | only in asm-arm
      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
     49