GNU Linux-libre 4.9.318-gnu1
[releases.git] / arch / mips / include / asm / div64.h
1 /*
2  * Copyright (C) 2000, 2004, 2021  Maciej W. Rozycki
3  * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
4  *
5  * This file is subject to the terms and conditions of the GNU General Public
6  * License.  See the file "COPYING" in the main directory of this archive
7  * for more details.
8  */
9 #ifndef __ASM_DIV64_H
10 #define __ASM_DIV64_H
11
12 #include <asm/bitsperlong.h>
13
14 #if BITS_PER_LONG == 32
15
16 /*
17  * No traps on overflows for any of these...
18  */
19
20 #define do_div64_32(res, high, low, base) ({                            \
21         unsigned long __cf, __tmp, __tmp2, __i;                         \
22         unsigned long __quot32, __mod32;                                \
23                                                                         \
24         __asm__(                                                        \
25         "       .set    push                                    \n"     \
26         "       .set    noat                                    \n"     \
27         "       .set    noreorder                               \n"     \
28         "       move    %2, $0                                  \n"     \
29         "       move    %3, $0                                  \n"     \
30         "       b       1f                                      \n"     \
31         "        li     %4, 0x21                                \n"     \
32         "0:                                                     \n"     \
33         "       sll     $1, %0, 0x1                             \n"     \
34         "       srl     %3, %0, 0x1f                            \n"     \
35         "       or      %0, $1, %5                              \n"     \
36         "       sll     %1, %1, 0x1                             \n"     \
37         "       sll     %2, %2, 0x1                             \n"     \
38         "1:                                                     \n"     \
39         "       bnez    %3, 2f                                  \n"     \
40         "        sltu   %5, %0, %z6                             \n"     \
41         "       bnez    %5, 3f                                  \n"     \
42         "2:                                                     \n"     \
43         "        addiu  %4, %4, -1                              \n"     \
44         "       subu    %0, %0, %z6                             \n"     \
45         "       addiu   %2, %2, 1                               \n"     \
46         "3:                                                     \n"     \
47         "       bnez    %4, 0b                                  \n"     \
48         "        srl    %5, %1, 0x1f                            \n"     \
49         "       .set    pop"                                            \
50         : "=&r" (__mod32), "=&r" (__tmp),                               \
51           "=&r" (__quot32), "=&r" (__cf),                               \
52           "=&r" (__i), "=&r" (__tmp2)                                   \
53         : "Jr" (base), "0" (high), "1" (low));                          \
54                                                                         \
55         (res) = __quot32;                                               \
56         __mod32;                                                        \
57 })
58
59 #define __div64_32(n, base) ({                                          \
60         unsigned long __upper, __low, __high, __radix;                  \
61         unsigned long long __quot;                                      \
62         unsigned long long __div;                                       \
63         unsigned long __mod;                                            \
64                                                                         \
65         __div = (*n);                                                   \
66         __radix = (base);                                               \
67                                                                         \
68         __high = __div >> 32;                                           \
69         __low = __div;                                                  \
70                                                                         \
71         if (__high < __radix) {                                         \
72                 __upper = __high;                                       \
73                 __high = 0;                                             \
74         } else {                                                        \
75                 __upper = __high % __radix;                             \
76                 __high /= __radix;                                      \
77         }                                                               \
78                                                                         \
79         __mod = do_div64_32(__low, __upper, __low, __radix);            \
80                                                                         \
81         __quot = __high;                                                \
82         __quot = __quot << 32 | __low;                                  \
83         (*n) = __quot;                                                  \
84         __mod;                                                          \
85 })
86
87 #endif /* BITS_PER_LONG == 32 */
88
89 #include <asm-generic/div64.h>
90
91 #endif /* __ASM_DIV64_H */