Code-base clean-up and refactoring (#47)
[lunaix-os.git] / lunaix-os / arch / x86 / includes / asm / muldiv64.h
diff --git a/lunaix-os/arch/x86/includes/asm/muldiv64.h b/lunaix-os/arch/x86/includes/asm/muldiv64.h
new file mode 100644 (file)
index 0000000..c575685
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef __LUNAIX_MULDIV64_H
+#define __LUNAIX_MULDIV64_H
+
+#include <lunaix/spike.h>
+#include <lunaix/types.h>
+
+#ifdef CONFIG_ARCH_I386
+#define do_udiv64(n, base)                                                     \
+    ({                                                                         \
+        unsigned long __upper, __low, __high, __mod, __base;                   \
+        __base = (base);                                                       \
+        if (__builtin_constant_p(__base) && is_pot(__base)) {                  \
+            __mod = n & (__base - 1);                                          \
+            n >>= ilog2(__base);                                               \
+        } else {                                                               \
+            asm("" : "=a"(__low), "=d"(__high) : "A"(n));                      \
+            __upper = __high;                                                  \
+            if (__high) {                                                      \
+                __upper = __high % (__base);                                   \
+                __high = __high / (__base);                                    \
+            }                                                                  \
+            asm("divl %2"                                                      \
+                : "=a"(__low), "=d"(__mod)                                     \
+                : "rm"(__base), "0"(__low), "1"(__upper));                     \
+            asm("" : "=A"(n) : "a"(__low), "d"(__high));                       \
+        }                                                                      \
+        __mod;                                                                 \
+    })
+#else
+    #define do_udiv64(n, base)  \
+        ({                      \
+            n = (n) / (base);   \
+            (n) % (base);       \
+        })
+#endif
+
+static inline u64_t
+udiv64(u64_t n, unsigned int base)
+{
+    do_udiv64(n, base);
+
+    return n;
+}
+
+static inline unsigned int
+umod64(u64_t n, unsigned int base)
+{
+    return do_udiv64(n, base);
+}
+
+#endif /* __LUNAIX_MULDIV64_H */