diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2010-10-29 14:08:24 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-10-29 14:08:24 -0400 |
commit | 7837314d141c661c70bc13c5050694413ecfe14a (patch) | |
tree | de137b1d2945d2490bc1dcdf6d76eac6006f7ab0 | |
parent | 18cb657ca1bafe635f368346a1676fb04c512edf (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/Makefile | 3 | ||||
-rw-r--r-- | arch/mips/include/asm/atomic.h | 208 | ||||
-rw-r--r-- | arch/mips/include/asm/bitops.h | 270 | ||||
-rw-r--r-- | arch/mips/include/asm/cmpxchg.h | 7 | ||||
-rw-r--r-- | arch/mips/include/asm/system.h | 52 |
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 |
49 | endif | 49 | endif |
50 | 50 | ||
51 | ifndef CONFIG_FUNCTION_TRACER | ||
52 | cflags-y := -ffunction-sections | ||
53 | endif | ||
54 | ifdef CONFIG_FUNCTION_GRAPH_TRACER | 51 | ifdef 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 | ||