diff options
Diffstat (limited to 'include/asm-x86/bitops.h')
-rw-r--r-- | include/asm-x86/bitops.h | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/include/asm-x86/bitops.h b/include/asm-x86/bitops.h index 7d2494bdc660..ab7635a4acd9 100644 --- a/include/asm-x86/bitops.h +++ b/include/asm-x86/bitops.h | |||
@@ -23,11 +23,22 @@ | |||
23 | #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) | 23 | #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) |
24 | /* Technically wrong, but this avoids compilation errors on some gcc | 24 | /* Technically wrong, but this avoids compilation errors on some gcc |
25 | versions. */ | 25 | versions. */ |
26 | #define ADDR "=m" (*(volatile long *) addr) | 26 | #define BITOP_ADDR(x) "=m" (*(volatile long *) (x)) |
27 | #else | 27 | #else |
28 | #define ADDR "+m" (*(volatile long *) addr) | 28 | #define BITOP_ADDR(x) "+m" (*(volatile long *) (x)) |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | #define ADDR BITOP_ADDR(addr) | ||
32 | |||
33 | /* | ||
34 | * We do the locked ops that don't return the old value as | ||
35 | * a mask operation on a byte. | ||
36 | */ | ||
37 | #define IS_IMMEDIATE(nr) \ | ||
38 | (__builtin_constant_p(nr)) | ||
39 | #define CONST_MASK_ADDR BITOP_ADDR(addr + (nr>>3)) | ||
40 | #define CONST_MASK (1 << (nr & 7)) | ||
41 | |||
31 | /** | 42 | /** |
32 | * set_bit - Atomically set a bit in memory | 43 | * set_bit - Atomically set a bit in memory |
33 | * @nr: the bit to set | 44 | * @nr: the bit to set |
@@ -43,11 +54,15 @@ | |||
43 | * Note that @nr may be almost arbitrarily large; this function is not | 54 | * Note that @nr may be almost arbitrarily large; this function is not |
44 | * restricted to acting on a single-word quantity. | 55 | * restricted to acting on a single-word quantity. |
45 | */ | 56 | */ |
46 | static inline void set_bit(int nr, volatile unsigned long *addr) | 57 | static inline void set_bit(unsigned int nr, volatile unsigned long *addr) |
47 | { | 58 | { |
48 | asm volatile(LOCK_PREFIX "bts %1,%0" : ADDR : "Ir" (nr) : "memory"); | 59 | if (IS_IMMEDIATE(nr)) |
60 | asm volatile(LOCK_PREFIX "orb %1,%0" : CONST_MASK_ADDR : "i" (CONST_MASK) : "memory"); | ||
61 | else | ||
62 | asm volatile(LOCK_PREFIX "bts %1,%0" : ADDR : "Ir" (nr) : "memory"); | ||
49 | } | 63 | } |
50 | 64 | ||
65 | |||
51 | /** | 66 | /** |
52 | * __set_bit - Set a bit in memory | 67 | * __set_bit - Set a bit in memory |
53 | * @nr: the bit to set | 68 | * @nr: the bit to set |
@@ -74,7 +89,10 @@ static inline void __set_bit(int nr, volatile unsigned long *addr) | |||
74 | */ | 89 | */ |
75 | static inline void clear_bit(int nr, volatile unsigned long *addr) | 90 | static inline void clear_bit(int nr, volatile unsigned long *addr) |
76 | { | 91 | { |
77 | asm volatile(LOCK_PREFIX "btr %1,%0" : ADDR : "Ir" (nr)); | 92 | if (IS_IMMEDIATE(nr)) |
93 | asm volatile(LOCK_PREFIX "andb %1,%0" : CONST_MASK_ADDR : "i" (~CONST_MASK)); | ||
94 | else | ||
95 | asm volatile(LOCK_PREFIX "btr %1,%0" : ADDR : "Ir" (nr)); | ||
78 | } | 96 | } |
79 | 97 | ||
80 | /* | 98 | /* |