diff options
author | Alexander van Heukelum <heukelum@mailshack.com> | 2008-03-15 08:04:42 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-26 13:21:16 -0400 |
commit | 12d9c8420b9daa1da3d9e090640fb24bcd0deba2 (patch) | |
tree | 60affb5bdc5b857dfb3969234659caedbf2ff02a | |
parent | 64970b68d2b3ed32b964b0b30b1b98518fde388e (diff) |
x86: merge the simple bitops and move them to bitops.h
Some of those can be written in such a way that the same
inline assembly can be used to generate both 32 bit and
64 bit code.
For ffs and fls, x86_64 unconditionally used the cmov
instruction and i386 unconditionally used a conditional
branch over a mov instruction. In the current patch I
chose to select the version based on the availability
of the cmov instruction instead. A small detail here is
that x86_64 did not previously set CONFIG_X86_CMOV=y.
Improved comments for ffs, ffz, fls and variations.
Signed-off-by: Alexander van Heukelum <heukelum@fastmail.fm>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/Kconfig.cpu | 2 | ||||
-rw-r--r-- | include/asm-x86/bitops.h | 99 | ||||
-rw-r--r-- | include/asm-x86/bitops_32.h | 64 | ||||
-rw-r--r-- | include/asm-x86/bitops_64.h | 76 |
4 files changed, 99 insertions, 142 deletions
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 4da3cdb9c1b1..cf3ff2c5cef2 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu | |||
@@ -398,7 +398,7 @@ config X86_TSC | |||
398 | # generates cmov. | 398 | # generates cmov. |
399 | config X86_CMOV | 399 | config X86_CMOV |
400 | def_bool y | 400 | def_bool y |
401 | depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7) | 401 | depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || X86_64) |
402 | 402 | ||
403 | config X86_MINIMUM_CPU_FAMILY | 403 | config X86_MINIMUM_CPU_FAMILY |
404 | int | 404 | int |
diff --git a/include/asm-x86/bitops.h b/include/asm-x86/bitops.h index 1ae7b270a1ef..1b6f547cb6bd 100644 --- a/include/asm-x86/bitops.h +++ b/include/asm-x86/bitops.h | |||
@@ -67,7 +67,6 @@ static inline void __set_bit(int nr, volatile void *addr) | |||
67 | : "Ir" (nr) : "memory"); | 67 | : "Ir" (nr) : "memory"); |
68 | } | 68 | } |
69 | 69 | ||
70 | |||
71 | /** | 70 | /** |
72 | * clear_bit - Clears a bit in memory | 71 | * clear_bit - Clears a bit in memory |
73 | * @nr: Bit to clear | 72 | * @nr: Bit to clear |
@@ -304,6 +303,104 @@ static int test_bit(int nr, const volatile unsigned long *addr); | |||
304 | 303 | ||
305 | #undef BASE_ADDR | 304 | #undef BASE_ADDR |
306 | #undef BIT_ADDR | 305 | #undef BIT_ADDR |
306 | /** | ||
307 | * __ffs - find first set bit in word | ||
308 | * @word: The word to search | ||
309 | * | ||
310 | * Undefined if no bit exists, so code should check against 0 first. | ||
311 | */ | ||
312 | static inline unsigned long __ffs(unsigned long word) | ||
313 | { | ||
314 | __asm__("bsf %1,%0" | ||
315 | :"=r" (word) | ||
316 | :"rm" (word)); | ||
317 | return word; | ||
318 | } | ||
319 | |||
320 | /** | ||
321 | * ffz - find first zero bit in word | ||
322 | * @word: The word to search | ||
323 | * | ||
324 | * Undefined if no zero exists, so code should check against ~0UL first. | ||
325 | */ | ||
326 | static inline unsigned long ffz(unsigned long word) | ||
327 | { | ||
328 | __asm__("bsf %1,%0" | ||
329 | :"=r" (word) | ||
330 | :"r" (~word)); | ||
331 | return word; | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * __fls: find last set bit in word | ||
336 | * @word: The word to search | ||
337 | * | ||
338 | * Undefined if no zero exists, so code should check against ~0UL first. | ||
339 | */ | ||
340 | static inline unsigned long __fls(unsigned long word) | ||
341 | { | ||
342 | __asm__("bsr %1,%0" | ||
343 | :"=r" (word) | ||
344 | :"rm" (word)); | ||
345 | return word; | ||
346 | } | ||
347 | |||
348 | #ifdef __KERNEL__ | ||
349 | /** | ||
350 | * ffs - find first set bit in word | ||
351 | * @x: the word to search | ||
352 | * | ||
353 | * This is defined the same way as the libc and compiler builtin ffs | ||
354 | * routines, therefore differs in spirit from the other bitops. | ||
355 | * | ||
356 | * ffs(value) returns 0 if value is 0 or the position of the first | ||
357 | * set bit if value is nonzero. The first (least significant) bit | ||
358 | * is at position 1. | ||
359 | */ | ||
360 | static inline int ffs(int x) | ||
361 | { | ||
362 | int r; | ||
363 | #ifdef CONFIG_X86_CMOV | ||
364 | __asm__("bsfl %1,%0\n\t" | ||
365 | "cmovzl %2,%0" | ||
366 | : "=r" (r) : "rm" (x), "r" (-1)); | ||
367 | #else | ||
368 | __asm__("bsfl %1,%0\n\t" | ||
369 | "jnz 1f\n\t" | ||
370 | "movl $-1,%0\n" | ||
371 | "1:" : "=r" (r) : "rm" (x)); | ||
372 | #endif | ||
373 | return r + 1; | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * fls - find last set bit in word | ||
378 | * @x: the word to search | ||
379 | * | ||
380 | * This is defined in a similar way as the libc and compiler builtin | ||
381 | * ffs, but returns the position of the most significant set bit. | ||
382 | * | ||
383 | * fls(value) returns 0 if value is 0 or the position of the last | ||
384 | * set bit if value is nonzero. The last (most significant) bit is | ||
385 | * at position 32. | ||
386 | */ | ||
387 | static inline int fls(int x) | ||
388 | { | ||
389 | int r; | ||
390 | #ifdef CONFIG_X86_CMOV | ||
391 | __asm__("bsrl %1,%0\n\t" | ||
392 | "cmovzl %2,%0" | ||
393 | : "=&r" (r) : "rm" (x), "rm" (-1)); | ||
394 | #else | ||
395 | __asm__("bsrl %1,%0\n\t" | ||
396 | "jnz 1f\n\t" | ||
397 | "movl $-1,%0\n" | ||
398 | "1:" : "=r" (r) : "rm" (x)); | ||
399 | #endif | ||
400 | return r + 1; | ||
401 | } | ||
402 | #endif /* __KERNEL__ */ | ||
403 | |||
307 | #undef ADDR | 404 | #undef ADDR |
308 | 405 | ||
309 | #ifdef CONFIG_X86_32 | 406 | #ifdef CONFIG_X86_32 |
diff --git a/include/asm-x86/bitops_32.h b/include/asm-x86/bitops_32.h index 7c9ed759afb2..3ed64b21b765 100644 --- a/include/asm-x86/bitops_32.h +++ b/include/asm-x86/bitops_32.h | |||
@@ -40,20 +40,6 @@ static inline int find_first_zero_bit(const unsigned long *addr, unsigned size) | |||
40 | } | 40 | } |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * __ffs - find first bit in word. | ||
44 | * @word: The word to search | ||
45 | * | ||
46 | * Undefined if no bit exists, so code should check against 0 first. | ||
47 | */ | ||
48 | static inline unsigned long __ffs(unsigned long word) | ||
49 | { | ||
50 | __asm__("bsfl %1,%0" | ||
51 | :"=r" (word) | ||
52 | :"rm" (word)); | ||
53 | return word; | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * find_first_bit - find the first set bit in a memory region | 43 | * find_first_bit - find the first set bit in a memory region |
58 | * @addr: The address to start the search at | 44 | * @addr: The address to start the search at |
59 | * @size: The maximum size to search | 45 | * @size: The maximum size to search |
@@ -74,60 +60,10 @@ static inline unsigned find_first_bit(const unsigned long *addr, unsigned size) | |||
74 | return x; | 60 | return x; |
75 | } | 61 | } |
76 | 62 | ||
77 | /** | ||
78 | * ffz - find first zero in word. | ||
79 | * @word: The word to search | ||
80 | * | ||
81 | * Undefined if no zero exists, so code should check against ~0UL first. | ||
82 | */ | ||
83 | static inline unsigned long ffz(unsigned long word) | ||
84 | { | ||
85 | __asm__("bsfl %1,%0" | ||
86 | :"=r" (word) | ||
87 | :"r" (~word)); | ||
88 | return word; | ||
89 | } | ||
90 | |||
91 | #ifdef __KERNEL__ | 63 | #ifdef __KERNEL__ |
92 | 64 | ||
93 | #include <asm-generic/bitops/sched.h> | 65 | #include <asm-generic/bitops/sched.h> |
94 | 66 | ||
95 | /** | ||
96 | * ffs - find first bit set | ||
97 | * @x: the word to search | ||
98 | * | ||
99 | * This is defined the same way as | ||
100 | * the libc and compiler builtin ffs routines, therefore | ||
101 | * differs in spirit from the above ffz() (man ffs). | ||
102 | */ | ||
103 | static inline int ffs(int x) | ||
104 | { | ||
105 | int r; | ||
106 | |||
107 | __asm__("bsfl %1,%0\n\t" | ||
108 | "jnz 1f\n\t" | ||
109 | "movl $-1,%0\n" | ||
110 | "1:" : "=r" (r) : "rm" (x)); | ||
111 | return r+1; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * fls - find last bit set | ||
116 | * @x: the word to search | ||
117 | * | ||
118 | * This is defined the same way as ffs(). | ||
119 | */ | ||
120 | static inline int fls(int x) | ||
121 | { | ||
122 | int r; | ||
123 | |||
124 | __asm__("bsrl %1,%0\n\t" | ||
125 | "jnz 1f\n\t" | ||
126 | "movl $-1,%0\n" | ||
127 | "1:" : "=r" (r) : "rm" (x)); | ||
128 | return r+1; | ||
129 | } | ||
130 | |||
131 | #include <asm-generic/bitops/hweight.h> | 67 | #include <asm-generic/bitops/hweight.h> |
132 | 68 | ||
133 | #endif /* __KERNEL__ */ | 69 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-x86/bitops_64.h b/include/asm-x86/bitops_64.h index 7118ef2cc4ec..a5fbe7a02a3f 100644 --- a/include/asm-x86/bitops_64.h +++ b/include/asm-x86/bitops_64.h | |||
@@ -35,71 +35,11 @@ static inline void set_bit_string(unsigned long *bitmap, unsigned long i, | |||
35 | } | 35 | } |
36 | } | 36 | } |
37 | 37 | ||
38 | /** | ||
39 | * ffz - find first zero in word. | ||
40 | * @word: The word to search | ||
41 | * | ||
42 | * Undefined if no zero exists, so code should check against ~0UL first. | ||
43 | */ | ||
44 | static inline unsigned long ffz(unsigned long word) | ||
45 | { | ||
46 | __asm__("bsfq %1,%0" | ||
47 | :"=r" (word) | ||
48 | :"r" (~word)); | ||
49 | return word; | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * __ffs - find first bit in word. | ||
54 | * @word: The word to search | ||
55 | * | ||
56 | * Undefined if no bit exists, so code should check against 0 first. | ||
57 | */ | ||
58 | static inline unsigned long __ffs(unsigned long word) | ||
59 | { | ||
60 | __asm__("bsfq %1,%0" | ||
61 | :"=r" (word) | ||
62 | :"rm" (word)); | ||
63 | return word; | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * __fls: find last bit set. | ||
68 | * @word: The word to search | ||
69 | * | ||
70 | * Undefined if no zero exists, so code should check against ~0UL first. | ||
71 | */ | ||
72 | static inline unsigned long __fls(unsigned long word) | ||
73 | { | ||
74 | __asm__("bsrq %1,%0" | ||
75 | :"=r" (word) | ||
76 | :"rm" (word)); | ||
77 | return word; | ||
78 | } | ||
79 | |||
80 | #ifdef __KERNEL__ | 38 | #ifdef __KERNEL__ |
81 | 39 | ||
82 | #include <asm-generic/bitops/sched.h> | 40 | #include <asm-generic/bitops/sched.h> |
83 | 41 | ||
84 | /** | 42 | /** |
85 | * ffs - find first bit set | ||
86 | * @x: the word to search | ||
87 | * | ||
88 | * This is defined the same way as | ||
89 | * the libc and compiler builtin ffs routines, therefore | ||
90 | * differs in spirit from the above ffz (man ffs). | ||
91 | */ | ||
92 | static inline int ffs(int x) | ||
93 | { | ||
94 | int r; | ||
95 | |||
96 | __asm__("bsfl %1,%0\n\t" | ||
97 | "cmovzl %2,%0" | ||
98 | : "=r" (r) : "rm" (x), "r" (-1)); | ||
99 | return r+1; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * fls64 - find last bit set in 64 bit word | 43 | * fls64 - find last bit set in 64 bit word |
104 | * @x: the word to search | 44 | * @x: the word to search |
105 | * | 45 | * |
@@ -112,22 +52,6 @@ static inline int fls64(__u64 x) | |||
112 | return __fls(x) + 1; | 52 | return __fls(x) + 1; |
113 | } | 53 | } |
114 | 54 | ||
115 | /** | ||
116 | * fls - find last bit set | ||
117 | * @x: the word to search | ||
118 | * | ||
119 | * This is defined the same way as ffs. | ||
120 | */ | ||
121 | static inline int fls(int x) | ||
122 | { | ||
123 | int r; | ||
124 | |||
125 | __asm__("bsrl %1,%0\n\t" | ||
126 | "cmovzl %2,%0" | ||
127 | : "=&r" (r) : "rm" (x), "rm" (-1)); | ||
128 | return r+1; | ||
129 | } | ||
130 | |||
131 | #define ARCH_HAS_FAST_MULTIPLIER 1 | 55 | #define ARCH_HAS_FAST_MULTIPLIER 1 |
132 | 56 | ||
133 | #include <asm-generic/bitops/hweight.h> | 57 | #include <asm-generic/bitops/hweight.h> |