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 /include/asm-x86/bitops.h | |
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>
Diffstat (limited to 'include/asm-x86/bitops.h')
-rw-r--r-- | include/asm-x86/bitops.h | 99 |
1 files changed, 98 insertions, 1 deletions
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 |