]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - arch/mips/include/asm/div64.h
MIPS: Reinstate platform `__div64_32' handler
[mirror_ubuntu-hirsute-kernel.git] / arch / mips / include / asm / div64.h
index dc5ea57364408a0ee2b302c169273274a78934f4..b252300e299dd1d54eaf090aba49c24e09fd6c60 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000, 2004  Maciej W. Rozycki
+ * Copyright (C) 2000, 2004, 2021  Maciej W. Rozycki
  * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -9,25 +9,18 @@
 #ifndef __ASM_DIV64_H
 #define __ASM_DIV64_H
 
-#include <asm-generic/div64.h>
-
-#if BITS_PER_LONG == 64
+#include <asm/bitsperlong.h>
 
-#include <linux/types.h>
+#if BITS_PER_LONG == 32
 
 /*
  * No traps on overflows for any of these...
  */
 
-#define __div64_32(n, base)                                            \
-({                                                                     \
+#define do_div64_32(res, high, low, base) ({                           \
        unsigned long __cf, __tmp, __tmp2, __i;                         \
        unsigned long __quot32, __mod32;                                \
-       unsigned long __high, __low;                                    \
-       unsigned long long __n;                                         \
                                                                        \
-       __high = *__n >> 32;                                            \
-       __low = __n;                                                    \
        __asm__(                                                        \
        "       .set    push                                    \n"     \
        "       .set    noat                                    \n"     \
        "       subu    %0, %0, %z6                             \n"     \
        "       addiu   %2, %2, 1                               \n"     \
        "3:                                                     \n"     \
-       "       bnez    %4, 0b\n\t"                                     \
-       "        srl    %5, %1, 0x1f\n\t"                               \
+       "       bnez    %4, 0b                                  \n"     \
+       "        srl    %5, %1, 0x1f                            \n"     \
        "       .set    pop"                                            \
        : "=&r" (__mod32), "=&r" (__tmp),                               \
          "=&r" (__quot32), "=&r" (__cf),                               \
          "=&r" (__i), "=&r" (__tmp2)                                   \
-       : "Jr" (base), "0" (__high), "1" (__low));                      \
+       : "Jr" (base), "0" (high), "1" (low));                          \
                                                                        \
-       (__n) = __quot32;                                               \
+       (res) = __quot32;                                               \
        __mod32;                                                        \
 })
 
-#endif /* BITS_PER_LONG == 64 */
+#define __div64_32(n, base) ({                                         \
+       unsigned long __upper, __low, __high, __radix;                  \
+       unsigned long long __modquot;                                   \
+       unsigned long long __quot;                                      \
+       unsigned long long __div;                                       \
+       unsigned long __mod;                                            \
+                                                                       \
+       __div = (*n);                                                   \
+       __radix = (base);                                               \
+                                                                       \
+       __high = __div >> 32;                                           \
+       __low = __div;                                                  \
+       __upper = __high;                                               \
+                                                                       \
+       if (__high) {                                                   \
+               __asm__("divu   $0, %z1, %z2"                           \
+               : "=x" (__modquot)                                      \
+               : "Jr" (__high), "Jr" (__radix));                       \
+               __upper = __modquot >> 32;                              \
+               __high = __modquot;                                     \
+       }                                                               \
+                                                                       \
+       __mod = do_div64_32(__low, __upper, __low, __radix);            \
+                                                                       \
+       __quot = __high;                                                \
+       __quot = __quot << 32 | __low;                                  \
+       (*n) = __quot;                                                  \
+       __mod;                                                          \
+})
+
+#endif /* BITS_PER_LONG == 32 */
+
+#include <asm-generic/div64.h>
 
 #endif /* __ASM_DIV64_H */