aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-x86/bitops.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-x86/bitops.h')
-rw-r--r--include/asm-x86/bitops.h28
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 */
46static inline void set_bit(int nr, volatile unsigned long *addr) 57static 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 */
75static inline void clear_bit(int nr, volatile unsigned long *addr) 90static 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/*