2 * Copyright (C) 1996 Paul Mackerras.
5 #include <linux/kernel.h>
6 #include <asm/bitops.h>
9 * I left these here since the problems with "cc" make it difficult to keep
10 * them in bitops.h -- Cort
12 void set_bit(int nr
, volatile void *addr
)
15 unsigned int mask
= 1 << (nr
& 0x1f);
16 volatile unsigned int *p
= ((volatile unsigned int *)addr
) + (nr
>> 5);
18 if ((unsigned long)addr
& 3)
19 printk(KERN_ERR
"set_bit(%x, %p)\n", nr
, addr
);
20 __asm__
__volatile__("\n\
25 : "=&r" (t
) /*, "=m" (*p)*/
30 void clear_bit(int nr
, volatile void *addr
)
33 unsigned int mask
= 1 << (nr
& 0x1f);
34 volatile unsigned int *p
= ((volatile unsigned int *)addr
) + (nr
>> 5);
36 if ((unsigned long)addr
& 3)
37 printk(KERN_ERR
"clear_bit(%x, %p)\n", nr
, addr
);
38 __asm__
__volatile__("\n\
43 : "=&r" (t
) /*, "=m" (*p)*/
48 void change_bit(int nr
, volatile void *addr
)
51 unsigned int mask
= 1 << (nr
& 0x1f);
52 volatile unsigned int *p
= ((volatile unsigned int *)addr
) + (nr
>> 5);
54 if ((unsigned long)addr
& 3)
55 printk(KERN_ERR
"change_bit(%x, %p)\n", nr
, addr
);
56 __asm__
__volatile__("\n\
61 : "=&r" (t
) /*, "=m" (*p)*/
66 int test_and_set_bit(int nr
, volatile void *addr
)
69 unsigned int mask
= 1 << (nr
& 0x1f);
70 volatile unsigned int *p
= ((volatile unsigned int *)addr
) + (nr
>> 5);
72 if ((unsigned long)addr
& 3)
73 printk(KERN_ERR
"test_and_set_bit(%x, %p)\n", nr
, addr
);
74 __asm__
__volatile__("\n\
79 : "=&r" (old
), "=&r" (t
) /*, "=m" (*p)*/
83 return (old
& mask
) != 0;
86 int test_and_clear_bit(int nr
, volatile void *addr
)
89 unsigned int mask
= 1 << (nr
& 0x1f);
90 volatile unsigned int *p
= ((volatile unsigned int *)addr
) + (nr
>> 5);
92 if ((unsigned long)addr
& 3)
93 printk(KERN_ERR
"test_and_clear_bit(%x, %p)\n", nr
, addr
);
94 __asm__
__volatile__("\n\
99 : "=&r" (old
), "=&r" (t
) /*, "=m" (*p)*/
100 : "r" (mask
), "r" (p
)
103 return (old
& mask
) != 0;
106 int test_and_change_bit(int nr
, volatile void *addr
)
109 unsigned int mask
= 1 << (nr
& 0x1f);
110 volatile unsigned int *p
= ((volatile unsigned int *)addr
) + (nr
>> 5);
112 if ((unsigned long)addr
& 3)
113 printk(KERN_ERR
"test_and_change_bit(%x, %p)\n", nr
, addr
);
114 __asm__
__volatile__("\n\
119 : "=&r" (old
), "=&r" (t
) /*, "=m" (*p)*/
120 : "r" (mask
), "r" (p
)
123 return (old
& mask
) != 0;
126 /* I put it in bitops.h -- Cort */
128 int ffz(unsigned int x
)
132 x
= ~x
& (x
+1); /* set LS zero to 1, other bits to 0 */
133 __asm__ ("cntlzw %0,%1" : "=r" (n
) : "r" (x
));
138 * This implementation of find_{first,next}_zero_bit was stolen from
139 * Linus' asm-alpha/bitops.h.
142 int find_first_zero_bit(void * addr
, int size
)
144 unsigned int * p
= ((unsigned int *) addr
);
145 unsigned int result
= 0;
150 while (size
& ~31UL) {
161 return result
+ ffz(tmp
);
165 * Find next zero bit in a bitmap reasonably efficiently..
167 int find_next_zero_bit(void * addr
, int size
, int offset
)
169 unsigned int * p
= ((unsigned int *) addr
) + (offset
>> 5);
170 unsigned int result
= offset
& ~31UL;
179 tmp
|= ~0UL >> (32-offset
);
187 while (size
& ~31UL) {
199 return result
+ ffz(tmp
);