1 diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
2 index 7b4553d..c402c37 100644
3 --- a/arch/mips/kernel/asm-offsets.c
4 +++ b/arch/mips/kernel/asm-offsets.c
6 #define offset(string, ptr, member) \
7 __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member)))
8 #define constant(string, member) \
9 - __asm__("\n@@@" string "%X0" : : "ri" (member))
10 + __asm__("\n@@@" string "%0" : : "ri" (member))
11 #define size(string, size) \
12 __asm__("\n@@@" string "%0" : : "i" (sizeof(size)))
13 #define linefeed text("")
14 diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
15 index ab3c3ea..c19c37f 100644
16 --- a/arch/mips/kernel/time.c
17 +++ b/arch/mips/kernel/time.c
18 @@ -281,10 +281,14 @@ static unsigned long fixed_rate_gettimeoffset(void)
19 /* .. relative to previous jiffy (32 bits is enough) */
22 +#ifndef GCC_NO_H_CONSTRAINT
25 : "r" (count), "r" (sll32_usecs_per_cycle)
26 : "lo", GCC_REG_ACCUM);
28 + res = ((uintx_t)count * sll32_usecs_per_cycle) >> BITS_PER_LONG;
33 @@ -337,10 +341,14 @@ static unsigned long calibrate_div32_gettimeoffset(void)
34 /* .. relative to previous jiffy (32 bits is enough) */
37 +#ifndef GCC_NO_H_CONSTRAINT
40 : "r" (count), "r" (quotient)
41 : "lo", GCC_REG_ACCUM);
43 + res = ((uintx_t)count * quotient) >> BITS_PER_LONG;
47 * Due to possible jiffies inconsistencies, we need to check
48 @@ -393,10 +401,14 @@ static unsigned long calibrate_div64_gettimeoffset(void)
49 /* .. relative to previous jiffy (32 bits is enough) */
52 +#ifndef GCC_NO_H_CONSTRAINT
55 : "r" (count), "r" (quotient)
56 : "lo", GCC_REG_ACCUM);
58 + res = ((uintx_t)count * quotient) >> BITS_PER_LONG;
62 * Due to possible jiffies inconsistencies, we need to check
63 @@ -440,7 +452,7 @@ EXPORT_SYMBOL(null_perf_irq);
64 EXPORT_SYMBOL(perf_irq);
66 extern int performance_enabled;
67 -extern int test_all_counters();
68 +extern int test_all_counters(void);
71 * High-level timer interrupt service routines. This function
72 diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
73 index 44b76d3..46ebcb8 100644
74 --- a/arch/mips/lib/Makefile
75 +++ b/arch/mips/lib/Makefile
76 @@ -10,6 +10,6 @@ obj-$(CONFIG_PCI) += iomap-pci.o
78 # libgcc-style stuff needed in the kernel
79 # PR43073: changed from lib-y
80 -obj-y += ashldi3.o ashrdi3.o lshrdi3.o
81 +obj-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o
83 EXTRA_AFLAGS := $(CFLAGS)
84 diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c
85 index e69de29..bb4cb2f 100644
86 --- a/arch/mips/lib/ucmpdi2.c
87 +++ b/arch/mips/lib/ucmpdi2.c
89 +#include <linux/module.h>
93 +word_type __ucmpdi2(unsigned long long a, unsigned long long b)
95 + const DWunion au = {.ll = a};
96 + const DWunion bu = {.ll = b};
98 + if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
100 + else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
102 + if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
104 + else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
109 +EXPORT_SYMBOL(__ucmpdi2);
110 diff --git a/include/asm-mips/compiler.h b/include/asm-mips/compiler.h
111 index 169ae26..4b56fe4 100644
112 --- a/include/asm-mips/compiler.h
113 +++ b/include/asm-mips/compiler.h
115 #ifndef _ASM_COMPILER_H
116 #define _ASM_COMPILER_H
118 +#include <asm/types.h>
120 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
121 #define GCC_REG_ACCUM "$0"
123 #define GCC_REG_ACCUM "accum"
126 +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
127 +#define GCC_NO_H_CONSTRAINT
129 +typedef unsigned int uintx_t __attribute__((mode(TI)));
131 +typedef u64 uintx_t;
135 #endif /* _ASM_COMPILER_H */
136 diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h
137 index 223d156..7c9dc07 100644
138 --- a/include/asm-mips/delay.h
139 +++ b/include/asm-mips/delay.h
140 @@ -36,6 +36,37 @@ static inline void __delay(unsigned long loops)
145 + * convert usecs to loops
147 + * handle removal of 'h' constraint in GCC 4.4
150 +#ifndef GCC_NO_H_CONSTRAINT /* gcc <= 4.3 */
151 +static inline unsigned long __usecs_to_loops(unsigned long usecs, unsigned long lpj)
155 + if (sizeof(long) == 4)
156 + __asm__("multu\t%2, %3"
157 + : "=h" (usecs), "=l" (lo)
158 + : "r" (usecs), "r" (lpj)
160 + else if (sizeof(long) == 8)
161 + __asm__("dmultu\t%2, %3"
162 + : "=h" (usecs), "=l" (lo)
163 + : "r" (usecs), "r" (lpj)
168 +#else /* GCC_NO_H_CONSTRAINT, gcc >= 4.4 */
169 +static inline unsigned long __usecs_to_loops(unsigned long usecs,
172 + return ((uintx_t)usecs * lpj) >> BITS_PER_LONG;
177 * Division by multiplication: you don't have to worry about
178 @@ -50,8 +81,6 @@ static inline void __delay(unsigned long loops)
180 static inline void __udelay(unsigned long usecs, unsigned long lpj)
185 * The rates of 128 is rounded wrongly by the catchall case
186 * for 64-bit. Excessive precission? Probably ...
187 @@ -64,19 +93,7 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj)
188 usecs *= (unsigned long) (((0x8000000000000000ULL / (500000 / HZ)) +
189 0x80000000ULL) >> 32);
192 - if (sizeof(long) == 4)
193 - __asm__("multu\t%2, %3"
194 - : "=h" (usecs), "=l" (lo)
195 - : "r" (usecs), "r" (lpj)
197 - else if (sizeof(long) == 8)
198 - __asm__("dmultu\t%2, %3"
199 - : "=h" (usecs), "=l" (lo)
200 - : "r" (usecs), "r" (lpj)
204 + __delay(__usecs_to_loops(usecs, lpj));
207 #define __udelay_val cpu_data[raw_smp_processor_id()].udelay_val
208 diff --git a/include/asm-mips/div64.h b/include/asm-mips/div64.h
209 index 5f7dcf5..9325185 100644
210 --- a/include/asm-mips/div64.h
211 +++ b/include/asm-mips/div64.h
217 + * __do_divu -- unsigned interger dividing
219 + * handle removal of 'h' constraint in GCC 4.4
221 +#ifndef GCC_NO_H_CONSTRAINT /* gcc <= 4.3*/
222 +#define __do_divu() ({ \
223 + __asm__("divu $0, %z2, %z3" \
224 + : "=h" (__upper), "=l" (__high) \
225 + : "Jr" (__high), "Jr" (__base) \
226 + : GCC_REG_ACCUM); })
227 +#else /* gcc >= 4.4 */
228 +#define __do_divu() ({ \
229 + __upper = (uintx_t)__high % __base; \
230 + __high = (uintx_t)__high / __base; })
233 #define do_div(n, base) ({ \
234 unsigned long long __quot; \
235 unsigned long __mod; \
240 - __asm__("divu $0, %z2, %z3" \
241 - : "=h" (__upper), "=l" (__high) \
242 - : "Jr" (__high), "Jr" (__base) \
243 - : GCC_REG_ACCUM); \
246 __mod = do_div64_32(__low, __upper, __low, __base); \