diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-02-16 12:18:50 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-02-18 16:31:35 -0500 |
commit | 102fa15c3f14565f2edb9f08f08ea3f2bf123dc9 (patch) | |
tree | e4b753ec35e1cf543ab580df9b36b03086f9909c | |
parent | 151fd6acd94e12ef3a7d5fa0911a2590690c493f (diff) |
[MIPS] Use MIPS R2 instructions for bitops.
Add R2 optimized variants of clear_bit, set_bit and test_and_clear_bit.
With gcc 4.1.1 this saves 1592 bytes on a defconfig (minus IPv6) kernel.
Turns out that R2 bitop instructions are no gain for the other bitop
functions.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | include/asm-mips/bitops.h | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h index 06c08228a525..89436b96ad66 100644 --- a/include/asm-mips/bitops.h +++ b/include/asm-mips/bitops.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (c) 1994 - 1997, 1999, 2000, 06 Ralf Baechle (ralf@linux-mips.org) | 6 | * Copyright (c) 1994 - 1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org) |
7 | * Copyright (c) 1999, 2000 Silicon Graphics, Inc. | 7 | * Copyright (c) 1999, 2000 Silicon Graphics, Inc. |
8 | */ | 8 | */ |
9 | #ifndef _ASM_BITOPS_H | 9 | #ifndef _ASM_BITOPS_H |
@@ -24,11 +24,15 @@ | |||
24 | #define SZLONG_MASK 31UL | 24 | #define SZLONG_MASK 31UL |
25 | #define __LL "ll " | 25 | #define __LL "ll " |
26 | #define __SC "sc " | 26 | #define __SC "sc " |
27 | #define __INS "ins " | ||
28 | #define __EXT "ext " | ||
27 | #elif (_MIPS_SZLONG == 64) | 29 | #elif (_MIPS_SZLONG == 64) |
28 | #define SZLONG_LOG 6 | 30 | #define SZLONG_LOG 6 |
29 | #define SZLONG_MASK 63UL | 31 | #define SZLONG_MASK 63UL |
30 | #define __LL "lld " | 32 | #define __LL "lld " |
31 | #define __SC "scd " | 33 | #define __SC "scd " |
34 | #define __INS "dins " | ||
35 | #define __EXT "dext " | ||
32 | #endif | 36 | #endif |
33 | 37 | ||
34 | /* | 38 | /* |
@@ -62,6 +66,19 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) | |||
62 | " .set mips0 \n" | 66 | " .set mips0 \n" |
63 | : "=&r" (temp), "=m" (*m) | 67 | : "=&r" (temp), "=m" (*m) |
64 | : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m)); | 68 | : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m)); |
69 | #ifdef CONFIG_CPU_MIPSR2 | ||
70 | } else if (__builtin_constant_p(nr)) { | ||
71 | __asm__ __volatile__( | ||
72 | "1: " __LL "%0, %1 # set_bit \n" | ||
73 | " " __INS "%0, %4, %2, 1 \n" | ||
74 | " " __SC "%0, %1 \n" | ||
75 | " beqz %0, 2f \n" | ||
76 | " .subsection 2 \n" | ||
77 | "2: b 1b \n" | ||
78 | " .previous \n" | ||
79 | : "=&r" (temp), "=m" (*m) | ||
80 | : "ir" (nr & SZLONG_MASK), "m" (*m), "r" (~0)); | ||
81 | #endif /* CONFIG_CPU_MIPSR2 */ | ||
65 | } else if (cpu_has_llsc) { | 82 | } else if (cpu_has_llsc) { |
66 | __asm__ __volatile__( | 83 | __asm__ __volatile__( |
67 | " .set mips3 \n" | 84 | " .set mips3 \n" |
@@ -113,6 +130,19 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) | |||
113 | " .set mips0 \n" | 130 | " .set mips0 \n" |
114 | : "=&r" (temp), "=m" (*m) | 131 | : "=&r" (temp), "=m" (*m) |
115 | : "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m)); | 132 | : "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m)); |
133 | #ifdef CONFIG_CPU_MIPSR2 | ||
134 | } else if (__builtin_constant_p(nr)) { | ||
135 | __asm__ __volatile__( | ||
136 | "1: " __LL "%0, %1 # clear_bit \n" | ||
137 | " " __INS "%0, $0, %2, 1 \n" | ||
138 | " " __SC "%0, %1 \n" | ||
139 | " beqz %0, 2f \n" | ||
140 | " .subsection 2 \n" | ||
141 | "2: b 1b \n" | ||
142 | " .previous \n" | ||
143 | : "=&r" (temp), "=m" (*m) | ||
144 | : "ir" (nr & SZLONG_MASK), "m" (*m)); | ||
145 | #endif /* CONFIG_CPU_MIPSR2 */ | ||
116 | } else if (cpu_has_llsc) { | 146 | } else if (cpu_has_llsc) { |
117 | __asm__ __volatile__( | 147 | __asm__ __volatile__( |
118 | " .set mips3 \n" | 148 | " .set mips3 \n" |
@@ -291,6 +321,26 @@ static inline int test_and_clear_bit(unsigned long nr, | |||
291 | : "memory"); | 321 | : "memory"); |
292 | 322 | ||
293 | return res != 0; | 323 | return res != 0; |
324 | #ifdef CONFIG_CPU_MIPSR2 | ||
325 | } else if (__builtin_constant_p(nr)) { | ||
326 | unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); | ||
327 | unsigned long temp, res; | ||
328 | |||
329 | __asm__ __volatile__( | ||
330 | "1: " __LL "%0, %1 # test_and_clear_bit \n" | ||
331 | " " __EXT "%2, %0, %3, 1 \n" | ||
332 | " " __INS "%0, $0, %3, 1 \n" | ||
333 | " " __SC "%0, %1 \n" | ||
334 | " beqz %0, 2f \n" | ||
335 | " .subsection 2 \n" | ||
336 | "2: b 1b \n" | ||
337 | " .previous \n" | ||
338 | : "=&r" (temp), "=m" (*m), "=&r" (res) | ||
339 | : "ri" (nr & SZLONG_MASK), "m" (*m) | ||
340 | : "memory"); | ||
341 | |||
342 | return res; | ||
343 | #endif | ||
294 | } else if (cpu_has_llsc) { | 344 | } else if (cpu_has_llsc) { |
295 | unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); | 345 | unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); |
296 | unsigned long temp, res; | 346 | unsigned long temp, res; |