openpcd/firmware/include/asm/div64.h @ master
1 | 2a2d6309 | (no author) | #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
|