940f7dee2a34af98a29846876266d5e75d64bc10
[lunaix-os.git] / lunaix-os / arch / i386 / includes / sys / muldiv64.h
1 #ifndef __LUNAIX_MULDIV64_H
2 #define __LUNAIX_MULDIV64_H
3
4 #include <lunaix/spike.h>
5 #include <lunaix/types.h>
6
7 #define do_udiv64(n, base)                                                     \
8     ({                                                                         \
9         unsigned long __upper, __low, __high, __mod, __base;                   \
10         __base = (base);                                                       \
11         if (__builtin_constant_p(__base) && is_pot(__base)) {                  \
12             __mod = n & (__base - 1);                                          \
13             n >>= ILOG2(__base);                                               \
14         } else {                                                               \
15             asm("" : "=a"(__low), "=d"(__high) : "A"(n));                      \
16             __upper = __high;                                                  \
17             if (__high) {                                                      \
18                 __upper = __high % (__base);                                   \
19                 __high = __high / (__base);                                    \
20             }                                                                  \
21             asm("divl %2"                                                      \
22                 : "=a"(__low), "=d"(__mod)                                     \
23                 : "rm"(__base), "0"(__low), "1"(__upper));                     \
24             asm("" : "=A"(n) : "a"(__low), "d"(__high));                       \
25         }                                                                      \
26         __mod;                                                                 \
27     })
28
29 static inline u64_t
30 udiv64(u64_t n, unsigned int base)
31 {
32     do_udiv64(n, base);
33
34     return n;
35 }
36
37 static inline unsigned int
38 umod64(u64_t n, unsigned int base)
39 {
40     return do_udiv64(n, base);
41 }
42
43 #endif /* __LUNAIX_MULDIV64_H */