aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2010-10-29 14:08:24 -0400
committerRalf Baechle <ralf@linux-mips.org>2010-10-29 14:08:24 -0400
commit7837314d141c661c70bc13c5050694413ecfe14a (patch)
treede137b1d2945d2490bc1dcdf6d76eac6006f7ab0
parent18cb657ca1bafe635f368346a1676fb04c512edf (diff)
MIPS: Get rid of branches to .subsections.
It was a nice optimization - on paper at least. In practice it results in branches that may exceed the maximum legal range for a branch. We can fight that problem with -ffunction-sections but -ffunction-sections again is incompatible with -pg used by the function tracer. By rewriting the loop around all simple LL/SC blocks to C we reduce the amount of inline assembler and at the same time allow GCC to often fill the branch delay slots with something sensible or whatever else clever optimization it may have up in its sleeve. With this optimization gone we also no longer need -ffunction-sections, so drop it. This optimization was originally introduced in 2.6.21, commit 5999eca25c1fd4b9b9aca7833b04d10fe4bc877d (linux-mips.org) rsp. f65e4fa8e0c6022ad58dc88d1b11b12589ed7f9f (kernel.org). Original fix for the issues which caused me to pull this optimization by Paul Gortmaker <paul.gortmaker@windriver.com>. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/Makefile3
-rw-r--r--arch/mips/include/asm/atomic.h208
-rw-r--r--arch/mips/include/asm/bitops.h270
-rw-r--r--arch/mips/include/asm/cmpxchg.h7
-rw-r--r--arch/mips/include/asm/system.h52
5 files changed, 243 insertions, 297 deletions
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index f4a4b663ebb3..1a81240102c5 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -48,9 +48,6 @@ ifneq ($(SUBARCH),$(ARCH))
48 endif 48 endif
49endif 49endif
50 50
51ifndef CONFIG_FUNCTION_TRACER
52cflags-y := -ffunction-sections
53endif
54ifdef CONFIG_FUNCTION_GRAPH_TRACER 51ifdef CONFIG_FUNCTION_GRAPH_TRACER
55 ifndef KBUILD_MCOUNT_RA_ADDRESS 52 ifndef KBUILD_MCOUNT_RA_ADDRESS
56 ifeq ($(call cc-option-yn,-mmcount-ra-address), y) 53 ifeq ($(call cc-option-yn,-mmcount-ra-address), y)
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 47d87da379f9..4a02fe891ab6 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -64,18 +64,16 @@ static __inline__ void atomic_add(int i, atomic_t * v)
64 } else if (kernel_uses_llsc) { 64 } else if (kernel_uses_llsc) {
65 int temp; 65 int temp;
66 66
67 __asm__ __volatile__( 67 do {
68 " .set mips3 \n" 68 __asm__ __volatile__(
69 "1: ll %0, %1 # atomic_add \n" 69 " .set mips3 \n"
70 " addu %0, %2 \n" 70 " ll %0, %1 # atomic_add \n"
71 " sc %0, %1 \n" 71 " addu %0, %2 \n"
72 " beqz %0, 2f \n" 72 " sc %0, %1 \n"
73 " .subsection 2 \n" 73 " .set mips0 \n"
74 "2: b 1b \n" 74 : "=&r" (temp), "=m" (v->counter)
75 " .previous \n" 75 : "Ir" (i), "m" (v->counter));
76 " .set mips0 \n" 76 } while (unlikely(!temp));
77 : "=&r" (temp), "=m" (v->counter)
78 : "Ir" (i), "m" (v->counter));
79 } else { 77 } else {
80 unsigned long flags; 78 unsigned long flags;
81 79
@@ -109,18 +107,16 @@ static __inline__ void atomic_sub(int i, atomic_t * v)
109 } else if (kernel_uses_llsc) { 107 } else if (kernel_uses_llsc) {
110 int temp; 108 int temp;
111 109
112 __asm__ __volatile__( 110 do {
113 " .set mips3 \n" 111 __asm__ __volatile__(
114 "1: ll %0, %1 # atomic_sub \n" 112 " .set mips3 \n"
115 " subu %0, %2 \n" 113 " ll %0, %1 # atomic_sub \n"
116 " sc %0, %1 \n" 114 " subu %0, %2 \n"
117 " beqz %0, 2f \n" 115 " sc %0, %1 \n"
118 " .subsection 2 \n" 116 " .set mips0 \n"
119 "2: b 1b \n" 117 : "=&r" (temp), "=m" (v->counter)
120 " .previous \n" 118 : "Ir" (i), "m" (v->counter));
121 " .set mips0 \n" 119 } while (unlikely(!temp));
122 : "=&r" (temp), "=m" (v->counter)
123 : "Ir" (i), "m" (v->counter));
124 } else { 120 } else {
125 unsigned long flags; 121 unsigned long flags;
126 122
@@ -156,20 +152,19 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
156 } else if (kernel_uses_llsc) { 152 } else if (kernel_uses_llsc) {
157 int temp; 153 int temp;
158 154
159 __asm__ __volatile__( 155 do {
160 " .set mips3 \n" 156 __asm__ __volatile__(
161 "1: ll %1, %2 # atomic_add_return \n" 157 " .set mips3 \n"
162 " addu %0, %1, %3 \n" 158 " ll %1, %2 # atomic_add_return \n"
163 " sc %0, %2 \n" 159 " addu %0, %1, %3 \n"
164 " beqz %0, 2f \n" 160 " sc %0, %2 \n"
165 " addu %0, %1, %3 \n" 161 " .set mips0 \n"
166 " .subsection 2 \n" 162 : "=&r" (result), "=&r" (temp), "=m" (v->counter)
167 "2: b 1b \n" 163 : "Ir" (i), "m" (v->counter)
168 " .previous \n" 164 : "memory");
169 " .set mips0 \n" 165 } while (unlikely(!result));
170 : "=&r" (result), "=&r" (temp), "=m" (v->counter) 166
171 : "Ir" (i), "m" (v->counter) 167 result = temp + i;
172 : "memory");
173 } else { 168 } else {
174 unsigned long flags; 169 unsigned long flags;
175 170
@@ -205,23 +200,24 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
205 : "=&r" (result), "=&r" (temp), "=m" (v->counter) 200 : "=&r" (result), "=&r" (temp), "=m" (v->counter)
206 : "Ir" (i), "m" (v->counter) 201 : "Ir" (i), "m" (v->counter)
207 : "memory"); 202 : "memory");
203
204 result = temp - i;
208 } else if (kernel_uses_llsc) { 205 } else if (kernel_uses_llsc) {
209 int temp; 206 int temp;
210 207
211 __asm__ __volatile__( 208 do {
212 " .set mips3 \n" 209 __asm__ __volatile__(
213 "1: ll %1, %2 # atomic_sub_return \n" 210 " .set mips3 \n"
214 " subu %0, %1, %3 \n" 211 " ll %1, %2 # atomic_sub_return \n"
215 " sc %0, %2 \n" 212 " subu %0, %1, %3 \n"
216 " beqz %0, 2f \n" 213 " sc %0, %2 \n"
217 " subu %0, %1, %3 \n" 214 " .set mips0 \n"
218 " .subsection 2 \n" 215 : "=&r" (result), "=&r" (temp), "=m" (v->counter)
219 "2: b 1b \n" 216 : "Ir" (i), "m" (v->counter)
220 " .previous \n" 217 : "memory");
221 " .set mips0 \n" 218 } while (unlikely(!result));
222 : "=&r" (result), "=&r" (temp), "=m" (v->counter) 219
223 : "Ir" (i), "m" (v->counter) 220 result = temp - i;
224 : "memory");
225 } else { 221 } else {
226 unsigned long flags; 222 unsigned long flags;
227 223
@@ -279,12 +275,9 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
279 " bltz %0, 1f \n" 275 " bltz %0, 1f \n"
280 " sc %0, %2 \n" 276 " sc %0, %2 \n"
281 " .set noreorder \n" 277 " .set noreorder \n"
282 " beqz %0, 2f \n" 278 " beqz %0, 1b \n"
283 " subu %0, %1, %3 \n" 279 " subu %0, %1, %3 \n"
284 " .set reorder \n" 280 " .set reorder \n"
285 " .subsection 2 \n"
286 "2: b 1b \n"
287 " .previous \n"
288 "1: \n" 281 "1: \n"
289 " .set mips0 \n" 282 " .set mips0 \n"
290 : "=&r" (result), "=&r" (temp), "=m" (v->counter) 283 : "=&r" (result), "=&r" (temp), "=m" (v->counter)
@@ -443,18 +436,16 @@ static __inline__ void atomic64_add(long i, atomic64_t * v)
443 } else if (kernel_uses_llsc) { 436 } else if (kernel_uses_llsc) {
444 long temp; 437 long temp;
445 438
446 __asm__ __volatile__( 439 do {
447 " .set mips3 \n" 440 __asm__ __volatile__(
448 "1: lld %0, %1 # atomic64_add \n" 441 " .set mips3 \n"
449 " daddu %0, %2 \n" 442 " lld %0, %1 # atomic64_add \n"
450 " scd %0, %1 \n" 443 " daddu %0, %2 \n"
451 " beqz %0, 2f \n" 444 " scd %0, %1 \n"
452 " .subsection 2 \n" 445 " .set mips0 \n"
453 "2: b 1b \n" 446 : "=&r" (temp), "=m" (v->counter)
454 " .previous \n" 447 : "Ir" (i), "m" (v->counter));
455 " .set mips0 \n" 448 } while (unlikely(!temp));
456 : "=&r" (temp), "=m" (v->counter)
457 : "Ir" (i), "m" (v->counter));
458 } else { 449 } else {
459 unsigned long flags; 450 unsigned long flags;
460 451
@@ -488,18 +479,16 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v)
488 } else if (kernel_uses_llsc) { 479 } else if (kernel_uses_llsc) {
489 long temp; 480 long temp;
490 481
491 __asm__ __volatile__( 482 do {
492 " .set mips3 \n" 483 __asm__ __volatile__(
493 "1: lld %0, %1 # atomic64_sub \n" 484 " .set mips3 \n"
494 " dsubu %0, %2 \n" 485 " lld %0, %1 # atomic64_sub \n"
495 " scd %0, %1 \n" 486 " dsubu %0, %2 \n"
496 " beqz %0, 2f \n" 487 " scd %0, %1 \n"
497 " .subsection 2 \n" 488 " .set mips0 \n"
498 "2: b 1b \n" 489 : "=&r" (temp), "=m" (v->counter)
499 " .previous \n" 490 : "Ir" (i), "m" (v->counter));
500 " .set mips0 \n" 491 } while (unlikely(!temp));
501 : "=&r" (temp), "=m" (v->counter)
502 : "Ir" (i), "m" (v->counter));
503 } else { 492 } else {
504 unsigned long flags; 493 unsigned long flags;
505 494
@@ -535,20 +524,19 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
535 } else if (kernel_uses_llsc) { 524 } else if (kernel_uses_llsc) {
536 long temp; 525 long temp;
537 526
538 __asm__ __volatile__( 527 do {
539 " .set mips3 \n" 528 __asm__ __volatile__(
540 "1: lld %1, %2 # atomic64_add_return \n" 529 " .set mips3 \n"
541 " daddu %0, %1, %3 \n" 530 " lld %1, %2 # atomic64_add_return \n"
542 " scd %0, %2 \n" 531 " daddu %0, %1, %3 \n"
543 " beqz %0, 2f \n" 532 " scd %0, %2 \n"
544 " daddu %0, %1, %3 \n" 533 " .set mips0 \n"
545 " .subsection 2 \n" 534 : "=&r" (result), "=&r" (temp), "=m" (v->counter)
546 "2: b 1b \n" 535 : "Ir" (i), "m" (v->counter)
547 " .previous \n" 536 : "memory");
548 " .set mips0 \n" 537 } while (unlikely(!result));
549 : "=&r" (result), "=&r" (temp), "=m" (v->counter) 538
550 : "Ir" (i), "m" (v->counter) 539 result = temp + i;
551 : "memory");
552 } else { 540 } else {
553 unsigned long flags; 541 unsigned long flags;
554 542
@@ -587,20 +575,19 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
587 } else if (kernel_uses_llsc) { 575 } else if (kernel_uses_llsc) {
588 long temp; 576 long temp;
589 577
590 __asm__ __volatile__( 578 do {
591 " .set mips3 \n" 579 __asm__ __volatile__(
592 "1: lld %1, %2 # atomic64_sub_return \n" 580 " .set mips3 \n"
593 " dsubu %0, %1, %3 \n" 581 " lld %1, %2 # atomic64_sub_return \n"
594 " scd %0, %2 \n" 582 " dsubu %0, %1, %3 \n"
595 " beqz %0, 2f \n" 583 " scd %0, %2 \n"
596 " dsubu %0, %1, %3 \n" 584 " .set mips0 \n"
597 " .subsection 2 \n" 585 : "=&r" (result), "=&r" (temp), "=m" (v->counter)
598 "2: b 1b \n" 586 : "Ir" (i), "m" (v->counter)
599 " .previous \n" 587 : "memory");
600 " .set mips0 \n" 588 } while (unlikely(!result));
601 : "=&r" (result), "=&r" (temp), "=m" (v->counter) 589
602 : "Ir" (i), "m" (v->counter) 590 result = temp - i;
603 : "memory");
604 } else { 591 } else {
605 unsigned long flags; 592 unsigned long flags;
606 593
@@ -658,12 +645,9 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
658 " bltz %0, 1f \n" 645 " bltz %0, 1f \n"
659 " scd %0, %2 \n" 646 " scd %0, %2 \n"
660 " .set noreorder \n" 647 " .set noreorder \n"
661 " beqz %0, 2f \n" 648 " beqz %0, 1b \n"
662 " dsubu %0, %1, %3 \n" 649 " dsubu %0, %1, %3 \n"
663 " .set reorder \n" 650 " .set reorder \n"
664 " .subsection 2 \n"
665 "2: b 1b \n"
666 " .previous \n"
667 "1: \n" 651 "1: \n"
668 " .set mips0 \n" 652 " .set mips0 \n"
669 : "=&r" (result), "=&r" (temp), "=m" (v->counter) 653 : "=&r" (result), "=&r" (temp), "=m" (v->counter)
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index b0ce7ca2851f..50b4ef288c53 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -73,30 +73,26 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
73 : "ir" (1UL << bit), "m" (*m)); 73 : "ir" (1UL << bit), "m" (*m));
74#ifdef CONFIG_CPU_MIPSR2 74#ifdef CONFIG_CPU_MIPSR2
75 } else if (kernel_uses_llsc && __builtin_constant_p(bit)) { 75 } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
76 __asm__ __volatile__( 76 do {
77 "1: " __LL "%0, %1 # set_bit \n" 77 __asm__ __volatile__(
78 " " __INS "%0, %4, %2, 1 \n" 78 " " __LL "%0, %1 # set_bit \n"
79 " " __SC "%0, %1 \n" 79 " " __INS "%0, %3, %2, 1 \n"
80 " beqz %0, 2f \n" 80 " " __SC "%0, %1 \n"
81 " .subsection 2 \n" 81 : "=&r" (temp), "+m" (*m)
82 "2: b 1b \n" 82 : "ir" (bit), "r" (~0));
83 " .previous \n" 83 } while (unlikely(!temp));
84 : "=&r" (temp), "=m" (*m)
85 : "ir" (bit), "m" (*m), "r" (~0));
86#endif /* CONFIG_CPU_MIPSR2 */ 84#endif /* CONFIG_CPU_MIPSR2 */
87 } else if (kernel_uses_llsc) { 85 } else if (kernel_uses_llsc) {
88 __asm__ __volatile__( 86 do {
89 " .set mips3 \n" 87 __asm__ __volatile__(
90 "1: " __LL "%0, %1 # set_bit \n" 88 " .set mips3 \n"
91 " or %0, %2 \n" 89 " " __LL "%0, %1 # set_bit \n"
92 " " __SC "%0, %1 \n" 90 " or %0, %2 \n"
93 " beqz %0, 2f \n" 91 " " __SC "%0, %1 \n"
94 " .subsection 2 \n" 92 " .set mips0 \n"
95 "2: b 1b \n" 93 : "=&r" (temp), "+m" (*m)
96 " .previous \n" 94 : "ir" (1UL << bit));
97 " .set mips0 \n" 95 } while (unlikely(!temp));
98 : "=&r" (temp), "=m" (*m)
99 : "ir" (1UL << bit), "m" (*m));
100 } else { 96 } else {
101 volatile unsigned long *a = addr; 97 volatile unsigned long *a = addr;
102 unsigned long mask; 98 unsigned long mask;
@@ -134,34 +130,30 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
134 " " __SC "%0, %1 \n" 130 " " __SC "%0, %1 \n"
135 " beqzl %0, 1b \n" 131 " beqzl %0, 1b \n"
136 " .set mips0 \n" 132 " .set mips0 \n"
137 : "=&r" (temp), "=m" (*m) 133 : "=&r" (temp), "+m" (*m)
138 : "ir" (~(1UL << bit)), "m" (*m)); 134 : "ir" (~(1UL << bit)));
139#ifdef CONFIG_CPU_MIPSR2 135#ifdef CONFIG_CPU_MIPSR2
140 } else if (kernel_uses_llsc && __builtin_constant_p(bit)) { 136 } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
141 __asm__ __volatile__( 137 do {
142 "1: " __LL "%0, %1 # clear_bit \n" 138 __asm__ __volatile__(
143 " " __INS "%0, $0, %2, 1 \n" 139 " " __LL "%0, %1 # clear_bit \n"
144 " " __SC "%0, %1 \n" 140 " " __INS "%0, $0, %2, 1 \n"
145 " beqz %0, 2f \n" 141 " " __SC "%0, %1 \n"
146 " .subsection 2 \n" 142 : "=&r" (temp), "+m" (*m)
147 "2: b 1b \n" 143 : "ir" (bit));
148 " .previous \n" 144 } while (unlikely(!temp));
149 : "=&r" (temp), "=m" (*m)
150 : "ir" (bit), "m" (*m));
151#endif /* CONFIG_CPU_MIPSR2 */ 145#endif /* CONFIG_CPU_MIPSR2 */
152 } else if (kernel_uses_llsc) { 146 } else if (kernel_uses_llsc) {
153 __asm__ __volatile__( 147 do {
154 " .set mips3 \n" 148 __asm__ __volatile__(
155 "1: " __LL "%0, %1 # clear_bit \n" 149 " .set mips3 \n"
156 " and %0, %2 \n" 150 " " __LL "%0, %1 # clear_bit \n"
157 " " __SC "%0, %1 \n" 151 " and %0, %2 \n"
158 " beqz %0, 2f \n" 152 " " __SC "%0, %1 \n"
159 " .subsection 2 \n" 153 " .set mips0 \n"
160 "2: b 1b \n" 154 : "=&r" (temp), "+m" (*m)
161 " .previous \n" 155 : "ir" (~(1UL << bit)));
162 " .set mips0 \n" 156 } while (unlikely(!temp));
163 : "=&r" (temp), "=m" (*m)
164 : "ir" (~(1UL << bit)), "m" (*m));
165 } else { 157 } else {
166 volatile unsigned long *a = addr; 158 volatile unsigned long *a = addr;
167 unsigned long mask; 159 unsigned long mask;
@@ -213,24 +205,22 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
213 " " __SC "%0, %1 \n" 205 " " __SC "%0, %1 \n"
214 " beqzl %0, 1b \n" 206 " beqzl %0, 1b \n"
215 " .set mips0 \n" 207 " .set mips0 \n"
216 : "=&r" (temp), "=m" (*m) 208 : "=&r" (temp), "+m" (*m)
217 : "ir" (1UL << bit), "m" (*m)); 209 : "ir" (1UL << bit));
218 } else if (kernel_uses_llsc) { 210 } else if (kernel_uses_llsc) {
219 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); 211 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
220 unsigned long temp; 212 unsigned long temp;
221 213
222 __asm__ __volatile__( 214 do {
223 " .set mips3 \n" 215 __asm__ __volatile__(
224 "1: " __LL "%0, %1 # change_bit \n" 216 " .set mips3 \n"
225 " xor %0, %2 \n" 217 " " __LL "%0, %1 # change_bit \n"
226 " " __SC "%0, %1 \n" 218 " xor %0, %2 \n"
227 " beqz %0, 2f \n" 219 " " __SC "%0, %1 \n"
228 " .subsection 2 \n" 220 " .set mips0 \n"
229 "2: b 1b \n" 221 : "=&r" (temp), "+m" (*m)
230 " .previous \n" 222 : "ir" (1UL << bit));
231 " .set mips0 \n" 223 } while (unlikely(!temp));
232 : "=&r" (temp), "=m" (*m)
233 : "ir" (1UL << bit), "m" (*m));
234 } else { 224 } else {
235 volatile unsigned long *a = addr; 225 volatile unsigned long *a = addr;
236 unsigned long mask; 226 unsigned long mask;
@@ -272,30 +262,26 @@ static inline int test_and_set_bit(unsigned long nr,
272 " beqzl %2, 1b \n" 262 " beqzl %2, 1b \n"
273 " and %2, %0, %3 \n" 263 " and %2, %0, %3 \n"
274 " .set mips0 \n" 264 " .set mips0 \n"
275 : "=&r" (temp), "=m" (*m), "=&r" (res) 265 : "=&r" (temp), "+m" (*m), "=&r" (res)
276 : "r" (1UL << bit), "m" (*m) 266 : "r" (1UL << bit)
277 : "memory"); 267 : "memory");
278 } else if (kernel_uses_llsc) { 268 } else if (kernel_uses_llsc) {
279 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); 269 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
280 unsigned long temp; 270 unsigned long temp;
281 271
282 __asm__ __volatile__( 272 do {
283 " .set push \n" 273 __asm__ __volatile__(
284 " .set noreorder \n" 274 " .set mips3 \n"
285 " .set mips3 \n" 275 " " __LL "%0, %1 # test_and_set_bit \n"
286 "1: " __LL "%0, %1 # test_and_set_bit \n" 276 " or %2, %0, %3 \n"
287 " or %2, %0, %3 \n" 277 " " __SC "%2, %1 \n"
288 " " __SC "%2, %1 \n" 278 " .set mips0 \n"
289 " beqz %2, 2f \n" 279 : "=&r" (temp), "+m" (*m), "=&r" (res)
290 " and %2, %0, %3 \n" 280 : "r" (1UL << bit)
291 " .subsection 2 \n" 281 : "memory");
292 "2: b 1b \n" 282 } while (unlikely(!res));
293 " nop \n" 283
294 " .previous \n" 284 res = temp & (1UL << bit);
295 " .set pop \n"
296 : "=&r" (temp), "=m" (*m), "=&r" (res)
297 : "r" (1UL << bit), "m" (*m)
298 : "memory");
299 } else { 285 } else {
300 volatile unsigned long *a = addr; 286 volatile unsigned long *a = addr;
301 unsigned long mask; 287 unsigned long mask;
@@ -340,30 +326,26 @@ static inline int test_and_set_bit_lock(unsigned long nr,
340 " beqzl %2, 1b \n" 326 " beqzl %2, 1b \n"
341 " and %2, %0, %3 \n" 327 " and %2, %0, %3 \n"
342 " .set mips0 \n" 328 " .set mips0 \n"
343 : "=&r" (temp), "=m" (*m), "=&r" (res) 329 : "=&r" (temp), "+m" (*m), "=&r" (res)
344 : "r" (1UL << bit), "m" (*m) 330 : "r" (1UL << bit)
345 : "memory"); 331 : "memory");
346 } else if (kernel_uses_llsc) { 332 } else if (kernel_uses_llsc) {
347 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); 333 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
348 unsigned long temp; 334 unsigned long temp;
349 335
350 __asm__ __volatile__( 336 do {
351 " .set push \n" 337 __asm__ __volatile__(
352 " .set noreorder \n" 338 " .set mips3 \n"
353 " .set mips3 \n" 339 " " __LL "%0, %1 # test_and_set_bit \n"
354 "1: " __LL "%0, %1 # test_and_set_bit \n" 340 " or %2, %0, %3 \n"
355 " or %2, %0, %3 \n" 341 " " __SC "%2, %1 \n"
356 " " __SC "%2, %1 \n" 342 " .set mips0 \n"
357 " beqz %2, 2f \n" 343 : "=&r" (temp), "+m" (*m), "=&r" (res)
358 " and %2, %0, %3 \n" 344 : "r" (1UL << bit)
359 " .subsection 2 \n" 345 : "memory");
360 "2: b 1b \n" 346 } while (unlikely(!res));
361 " nop \n" 347
362 " .previous \n" 348 res = temp & (1UL << bit);
363 " .set pop \n"
364 : "=&r" (temp), "=m" (*m), "=&r" (res)
365 : "r" (1UL << bit), "m" (*m)
366 : "memory");
367 } else { 349 } else {
368 volatile unsigned long *a = addr; 350 volatile unsigned long *a = addr;
369 unsigned long mask; 351 unsigned long mask;
@@ -410,49 +392,43 @@ static inline int test_and_clear_bit(unsigned long nr,
410 " beqzl %2, 1b \n" 392 " beqzl %2, 1b \n"
411 " and %2, %0, %3 \n" 393 " and %2, %0, %3 \n"
412 " .set mips0 \n" 394 " .set mips0 \n"
413 : "=&r" (temp), "=m" (*m), "=&r" (res) 395 : "=&r" (temp), "+m" (*m), "=&r" (res)
414 : "r" (1UL << bit), "m" (*m) 396 : "r" (1UL << bit)
415 : "memory"); 397 : "memory");
416#ifdef CONFIG_CPU_MIPSR2 398#ifdef CONFIG_CPU_MIPSR2
417 } else if (kernel_uses_llsc && __builtin_constant_p(nr)) { 399 } else if (kernel_uses_llsc && __builtin_constant_p(nr)) {
418 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); 400 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
419 unsigned long temp; 401 unsigned long temp;
420 402
421 __asm__ __volatile__( 403 do {
422 "1: " __LL "%0, %1 # test_and_clear_bit \n" 404 __asm__ __volatile__(
423 " " __EXT "%2, %0, %3, 1 \n" 405 " " __LL "%0, %1 # test_and_clear_bit \n"
424 " " __INS "%0, $0, %3, 1 \n" 406 " " __EXT "%2, %0, %3, 1 \n"
425 " " __SC "%0, %1 \n" 407 " " __INS "%0, $0, %3, 1 \n"
426 " beqz %0, 2f \n" 408 " " __SC "%0, %1 \n"
427 " .subsection 2 \n" 409 : "=&r" (temp), "+m" (*m), "=&r" (res)
428 "2: b 1b \n" 410 : "ir" (bit)
429 " .previous \n" 411 : "memory");
430 : "=&r" (temp), "=m" (*m), "=&r" (res) 412 } while (unlikely(!temp));
431 : "ir" (bit), "m" (*m)
432 : "memory");
433#endif 413#endif
434 } else if (kernel_uses_llsc) { 414 } else if (kernel_uses_llsc) {
435 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); 415 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
436 unsigned long temp; 416 unsigned long temp;
437 417
438 __asm__ __volatile__( 418 do {
439 " .set push \n" 419 __asm__ __volatile__(
440 " .set noreorder \n" 420 " .set mips3 \n"
441 " .set mips3 \n" 421 " " __LL "%0, %1 # test_and_clear_bit \n"
442 "1: " __LL "%0, %1 # test_and_clear_bit \n" 422 " or %2, %0, %3 \n"
443 " or %2, %0, %3 \n" 423 " xor %2, %3 \n"
444 " xor %2, %3 \n" 424 " " __SC "%2, %1 \n"
445 " " __SC "%2, %1 \n" 425 " .set mips0 \n"
446 " beqz %2, 2f \n" 426 : "=&r" (temp), "+m" (*m), "=&r" (res)
447 " and %2, %0, %3 \n" 427 : "r" (1UL << bit)
448 " .subsection 2 \n" 428 : "memory");
449 "2: b 1b \n" 429 } while (unlikely(!res));
450 " nop \n" 430
451 " .previous \n" 431 res = temp & (1UL << bit);
452 " .set pop \n"
453 : "=&r" (temp), "=m" (*m), "=&r" (res)
454 : "r" (1UL << bit), "m" (*m)
455 : "memory");
456 } else { 432 } else {
457 volatile unsigned long *a = addr; 433 volatile unsigned long *a = addr;
458 unsigned long mask; 434 unsigned long mask;
@@ -499,30 +475,26 @@ static inline int test_and_change_bit(unsigned long nr,
499 " beqzl %2, 1b \n" 475 " beqzl %2, 1b \n"
500 " and %2, %0, %3 \n" 476 " and %2, %0, %3 \n"
501 " .set mips0 \n" 477 " .set mips0 \n"
502 : "=&r" (temp), "=m" (*m), "=&r" (res) 478 : "=&r" (temp), "+m" (*m), "=&r" (res)
503 : "r" (1UL << bit), "m" (*m) 479 : "r" (1UL << bit)
504 : "memory"); 480 : "memory");
505 } else if (kernel_uses_llsc) { 481 } else if (kernel_uses_llsc) {
506 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); 482 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
507 unsigned long temp; 483 unsigned long temp;
508 484
509 __asm__ __volatile__( 485 do {
510 " .set push \n" 486 __asm__ __volatile__(
511 " .set noreorder \n" 487 " .set mips3 \n"
512 " .set mips3 \n" 488 " " __LL "%0, %1 # test_and_change_bit \n"
513 "1: " __LL "%0, %1 # test_and_change_bit \n" 489 " xor %2, %0, %3 \n"
514 " xor %2, %0, %3 \n" 490 " " __SC "\t%2, %1 \n"
515 " " __SC "\t%2, %1 \n" 491 " .set mips0 \n"
516 " beqz %2, 2f \n" 492 : "=&r" (temp), "+m" (*m), "=&r" (res)
517 " and %2, %0, %3 \n" 493 : "r" (1UL << bit)
518 " .subsection 2 \n" 494 : "memory");
519 "2: b 1b \n" 495 } while (unlikely(!res));
520 " nop \n" 496
521 " .previous \n" 497 res = temp & (1UL << bit);
522 " .set pop \n"
523 : "=&r" (temp), "=m" (*m), "=&r" (res)
524 : "r" (1UL << bit), "m" (*m)
525 : "memory");
526 } else { 498 } else {
527 volatile unsigned long *a = addr; 499 volatile unsigned long *a = addr;
528 unsigned long mask; 500 unsigned long mask;
diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h
index 2d28017e95d0..d8d1c2805ac7 100644
--- a/arch/mips/include/asm/cmpxchg.h
+++ b/arch/mips/include/asm/cmpxchg.h
@@ -44,12 +44,9 @@
44 " move $1, %z4 \n" \ 44 " move $1, %z4 \n" \
45 " .set mips3 \n" \ 45 " .set mips3 \n" \
46 " " st " $1, %1 \n" \ 46 " " st " $1, %1 \n" \
47 " beqz $1, 3f \n" \ 47 " beqz $1, 1b \n" \
48 "2: \n" \
49 " .subsection 2 \n" \
50 "3: b 1b \n" \
51 " .previous \n" \
52 " .set pop \n" \ 48 " .set pop \n" \
49 "2: \n" \
53 : "=&r" (__ret), "=R" (*m) \ 50 : "=&r" (__ret), "=R" (*m) \
54 : "R" (*m), "Jr" (old), "Jr" (new) \ 51 : "R" (*m), "Jr" (old), "Jr" (new) \
55 : "memory"); \ 52 : "memory"); \
diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h
index bb937ccfba1e..6018c80ce37a 100644
--- a/arch/mips/include/asm/system.h
+++ b/arch/mips/include/asm/system.h
@@ -115,21 +115,19 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
115 } else if (kernel_uses_llsc) { 115 } else if (kernel_uses_llsc) {
116 unsigned long dummy; 116 unsigned long dummy;
117 117
118 __asm__ __volatile__( 118 do {
119 " .set mips3 \n" 119 __asm__ __volatile__(
120 "1: ll %0, %3 # xchg_u32 \n" 120 " .set mips3 \n"
121 " .set mips0 \n" 121 " ll %0, %3 # xchg_u32 \n"
122 " move %2, %z4 \n" 122 " .set mips0 \n"
123 " .set mips3 \n" 123 " move %2, %z4 \n"
124 " sc %2, %1 \n" 124 " .set mips3 \n"
125 " beqz %2, 2f \n" 125 " sc %2, %1 \n"
126 " .subsection 2 \n" 126 " .set mips0 \n"
127 "2: b 1b \n" 127 : "=&r" (retval), "=m" (*m), "=&r" (dummy)
128 " .previous \n" 128 : "R" (*m), "Jr" (val)
129 " .set mips0 \n" 129 : "memory");
130 : "=&r" (retval), "=m" (*m), "=&r" (dummy) 130 } while (unlikely(!dummy));
131 : "R" (*m), "Jr" (val)
132 : "memory");
133 } else { 131 } else {
134 unsigned long flags; 132 unsigned long flags;
135 133
@@ -167,19 +165,17 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
167 } else if (kernel_uses_llsc) { 165 } else if (kernel_uses_llsc) {
168 unsigned long dummy; 166 unsigned long dummy;
169 167
170 __asm__ __volatile__( 168 do {
171 " .set mips3 \n" 169 __asm__ __volatile__(
172 "1: lld %0, %3 # xchg_u64 \n" 170 " .set mips3 \n"
173 " move %2, %z4 \n" 171 " lld %0, %3 # xchg_u64 \n"
174 " scd %2, %1 \n" 172 " move %2, %z4 \n"
175 " beqz %2, 2f \n" 173 " scd %2, %1 \n"
176 " .subsection 2 \n" 174 " .set mips0 \n"
177 "2: b 1b \n" 175 : "=&r" (retval), "=m" (*m), "=&r" (dummy)
178 " .previous \n" 176 : "R" (*m), "Jr" (val)
179 " .set mips0 \n" 177 : "memory");
180 : "=&r" (retval), "=m" (*m), "=&r" (dummy) 178 } while (unlikely(!dummy));
181 : "R" (*m), "Jr" (val)
182 : "memory");
183 } else { 179 } else {
184 unsigned long flags; 180 unsigned long flags;
185 181