1
2
3
4
5
6
7
8
9
10
11#ifndef _ASM_DIV64
12#define _ASM_DIV64
13
14#include <linux/types.h>
15
16extern void ____unhandled_size_in_do_div___(void);
17
18
19
20
21
22
23
24
25#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
26# define CLOBBER_MDR_CC "mdr", "cc"
27#else
28# define CLOBBER_MDR_CC "cc"
29#endif
30
31
32
33
34
35
36#define do_div(n, base) \
37({ \
38 unsigned __rem = 0; \
39 if (sizeof(n) <= 4) { \
40 asm("mov %1,mdr \n" \
41 "divu %2,%0 \n" \
42 "mov mdr,%1 \n" \
43 : "+r"(n), "=d"(__rem) \
44 : "r"(base), "1"(__rem) \
45 : CLOBBER_MDR_CC \
46 ); \
47 } else if (sizeof(n) <= 8) { \
48 union { \
49 unsigned long long l; \
50 u32 w[2]; \
51 } __quot; \
52 __quot.l = n; \
53 asm("mov %0,mdr \n" \
54 "divu %3,%1 \n" \
55 \
56 \
57 "divu %3,%2 \n" \
58 \
59 \
60 "mov mdr,%0 \n" \
61 : "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0]) \
62 : "r"(base), "0"(__rem), "1"(__quot.w[1]), \
63 "2"(__quot.w[0]) \
64 : CLOBBER_MDR_CC \
65 ); \
66 n = __quot.l; \
67 } else { \
68 ____unhandled_size_in_do_div___(); \
69 } \
70 __rem; \
71})
72
73
74
75
76
77
78static inline __attribute__((const))
79unsigned __muldiv64u(unsigned val, unsigned mult, unsigned div)
80{
81 unsigned result;
82
83 asm("mulu %2,%0 \n"
84 "divu %3,%0 \n"
85
86 : "=r"(result)
87 : "0"(val), "ir"(mult), "r"(div)
88 : CLOBBER_MDR_CC
89 );
90
91 return result;
92}
93
94
95
96
97
98
99static inline __attribute__((const))
100signed __muldiv64s(signed val, signed mult, signed div)
101{
102 signed result;
103
104 asm("mul %2,%0 \n"
105 "div %3,%0 \n"
106
107 : "=r"(result)
108 : "0"(val), "ir"(mult), "r"(div)
109 : CLOBBER_MDR_CC
110 );
111
112 return result;
113}
114
115#endif
116