1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 1995, Russell King.
3*4882a593Smuzhiyun * Various bits and pieces copyrights include:
4*4882a593Smuzhiyun * Linus Torvalds (test_bit).
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Please note that the code in this file should never be included
9*4882a593Smuzhiyun * from user space. Many of these are not implemented in assembler
10*4882a593Smuzhiyun * since they would be too costly. Also, they require priviledged
11*4882a593Smuzhiyun * instructions (which are not available from user mode) to ensure
12*4882a593Smuzhiyun * that they are atomic.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #ifndef __ASM_ARM_BITOPS_H
16*4882a593Smuzhiyun #define __ASM_ARM_BITOPS_H
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #ifdef __KERNEL__
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include <asm/proc-armv/system.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define smp_mb__before_clear_bit() do { } while (0)
23*4882a593Smuzhiyun #define smp_mb__after_clear_bit() do { } while (0)
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /*
26*4882a593Smuzhiyun * Function prototypes to keep gcc -Wall happy.
27*4882a593Smuzhiyun */
28*4882a593Smuzhiyun extern void set_bit(int nr, volatile void * addr);
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun extern void clear_bit(int nr, volatile void * addr);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun extern void change_bit(int nr, volatile void * addr);
33*4882a593Smuzhiyun
__change_bit(int nr,volatile void * addr)34*4882a593Smuzhiyun static inline void __change_bit(int nr, volatile void *addr)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun unsigned long mask = BIT_MASK(nr);
37*4882a593Smuzhiyun unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun *p ^= mask;
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun
__test_and_set_bit(int nr,volatile void * addr)42*4882a593Smuzhiyun static inline int __test_and_set_bit(int nr, volatile void *addr)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun unsigned long mask = BIT_MASK(nr);
45*4882a593Smuzhiyun unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
46*4882a593Smuzhiyun unsigned long old = *p;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun *p = old | mask;
49*4882a593Smuzhiyun return (old & mask) != 0;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun
test_and_set_bit(int nr,volatile void * addr)52*4882a593Smuzhiyun static inline int test_and_set_bit(int nr, volatile void * addr)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun unsigned long flags = 0;
55*4882a593Smuzhiyun int out;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun local_irq_save(flags);
58*4882a593Smuzhiyun out = __test_and_set_bit(nr, addr);
59*4882a593Smuzhiyun local_irq_restore(flags);
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun return out;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
__test_and_clear_bit(int nr,volatile void * addr)64*4882a593Smuzhiyun static inline int __test_and_clear_bit(int nr, volatile void *addr)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun unsigned long mask = BIT_MASK(nr);
67*4882a593Smuzhiyun unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
68*4882a593Smuzhiyun unsigned long old = *p;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun *p = old & ~mask;
71*4882a593Smuzhiyun return (old & mask) != 0;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
test_and_clear_bit(int nr,volatile void * addr)74*4882a593Smuzhiyun static inline int test_and_clear_bit(int nr, volatile void * addr)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun unsigned long flags = 0;
77*4882a593Smuzhiyun int out;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun local_irq_save(flags);
80*4882a593Smuzhiyun out = __test_and_clear_bit(nr, addr);
81*4882a593Smuzhiyun local_irq_restore(flags);
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun return out;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun extern int test_and_change_bit(int nr, volatile void * addr);
87*4882a593Smuzhiyun
__test_and_change_bit(int nr,volatile void * addr)88*4882a593Smuzhiyun static inline int __test_and_change_bit(int nr, volatile void *addr)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun unsigned long mask = BIT_MASK(nr);
91*4882a593Smuzhiyun unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
92*4882a593Smuzhiyun unsigned long old = *p;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun *p = old ^ mask;
95*4882a593Smuzhiyun return (old & mask) != 0;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /*
99*4882a593Smuzhiyun * This routine doesn't need to be atomic.
100*4882a593Smuzhiyun */
test_bit(int nr,const void * addr)101*4882a593Smuzhiyun static inline int test_bit(int nr, const void * addr)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7));
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
__ilog2(unsigned int x)106*4882a593Smuzhiyun static inline int __ilog2(unsigned int x)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun return generic_fls(x) - 1;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun /*
112*4882a593Smuzhiyun * ffz = Find First Zero in word. Undefined if no zero exists,
113*4882a593Smuzhiyun * so code should check against ~0UL first..
114*4882a593Smuzhiyun */
ffz(unsigned long word)115*4882a593Smuzhiyun static inline unsigned long ffz(unsigned long word)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun int k;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun word = ~word;
120*4882a593Smuzhiyun k = 31;
121*4882a593Smuzhiyun if (word & 0x0000ffff) { k -= 16; word <<= 16; }
122*4882a593Smuzhiyun if (word & 0x00ff0000) { k -= 8; word <<= 8; }
123*4882a593Smuzhiyun if (word & 0x0f000000) { k -= 4; word <<= 4; }
124*4882a593Smuzhiyun if (word & 0x30000000) { k -= 2; word <<= 2; }
125*4882a593Smuzhiyun if (word & 0x40000000) { k -= 1; }
126*4882a593Smuzhiyun return k;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
find_next_zero_bit(void * addr,int size,int offset)129*4882a593Smuzhiyun static inline int find_next_zero_bit(void *addr, int size, int offset)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun unsigned long *p = ((unsigned long *)addr) + (offset >> 5);
132*4882a593Smuzhiyun unsigned long result = offset & ~31UL;
133*4882a593Smuzhiyun unsigned long tmp;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun if (offset >= size)
136*4882a593Smuzhiyun return size;
137*4882a593Smuzhiyun size -= result;
138*4882a593Smuzhiyun offset &= 31UL;
139*4882a593Smuzhiyun if (offset) {
140*4882a593Smuzhiyun tmp = *(p++);
141*4882a593Smuzhiyun tmp |= ~0UL >> (32-offset);
142*4882a593Smuzhiyun if (size < 32)
143*4882a593Smuzhiyun goto found_first;
144*4882a593Smuzhiyun if (~tmp)
145*4882a593Smuzhiyun goto found_middle;
146*4882a593Smuzhiyun size -= 32;
147*4882a593Smuzhiyun result += 32;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun while (size & ~31UL) {
150*4882a593Smuzhiyun tmp = *(p++);
151*4882a593Smuzhiyun if (~tmp)
152*4882a593Smuzhiyun goto found_middle;
153*4882a593Smuzhiyun result += 32;
154*4882a593Smuzhiyun size -= 32;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun if (!size)
157*4882a593Smuzhiyun return result;
158*4882a593Smuzhiyun tmp = *p;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun found_first:
161*4882a593Smuzhiyun tmp |= ~0UL >> size;
162*4882a593Smuzhiyun found_middle:
163*4882a593Smuzhiyun return result + ffz(tmp);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun /*
167*4882a593Smuzhiyun * hweightN: returns the hamming weight (i.e. the number
168*4882a593Smuzhiyun * of bits set) of a N-bit word
169*4882a593Smuzhiyun */
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun #define hweight32(x) generic_hweight32(x)
172*4882a593Smuzhiyun #define hweight16(x) generic_hweight16(x)
173*4882a593Smuzhiyun #define hweight8(x) generic_hweight8(x)
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun #define find_first_zero_bit(addr, size) \
176*4882a593Smuzhiyun find_next_zero_bit((addr), (size), 0)
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun #define ext2_set_bit test_and_set_bit
179*4882a593Smuzhiyun #define ext2_clear_bit test_and_clear_bit
180*4882a593Smuzhiyun #define ext2_test_bit test_bit
181*4882a593Smuzhiyun #define ext2_find_first_zero_bit find_first_zero_bit
182*4882a593Smuzhiyun #define ext2_find_next_zero_bit find_next_zero_bit
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /* Bitmap functions for the minix filesystem. */
185*4882a593Smuzhiyun #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
186*4882a593Smuzhiyun #define minix_set_bit(nr,addr) set_bit(nr,addr)
187*4882a593Smuzhiyun #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
188*4882a593Smuzhiyun #define minix_test_bit(nr,addr) test_bit(nr,addr)
189*4882a593Smuzhiyun #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun #endif /* __KERNEL__ */
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun #include <asm-generic/bitops/__fls.h>
194*4882a593Smuzhiyun #include <asm-generic/bitops/__ffs.h>
195*4882a593Smuzhiyun #include <asm-generic/bitops/fls.h>
196*4882a593Smuzhiyun #include <asm-generic/bitops/fls64.h>
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun #endif /* _ARM_BITOPS_H */
199