1 #ifndef __ASM_SH_BITOPS_H
2 #define __ASM_SH_BITOPS_H
3
4 #ifdef __KERNEL__
5 #include <asm/system.h>
6 /* For __swab32 */
7 #include <asm/byteorder.h>
8
9 static __inline__ void set_bit(int nr, volatile void * addr)
10 {
11 int mask;
12 volatile unsigned int *a = addr;
13 unsigned long flags;
14
15 a += nr >> 5;
16 mask = 1 << (nr & 0x1f);
17 save_and_cli(flags);
18 *a |= mask;
19 restore_flags(flags);
20 }
21
22 /*
23 * clear_bit() doesn't provide any barrier for the compiler.
24 */
25 #define smp_mb__before_clear_bit() barrier()
26 #define smp_mb__after_clear_bit() barrier()
27 static __inline__ void clear_bit(int nr, volatile void * addr)
28 {
29 int mask;
30 volatile unsigned int *a = addr;
31 unsigned long flags;
32
33 a += nr >> 5;
34 mask = 1 << (nr & 0x1f);
35 save_and_cli(flags);
36 *a &= ~mask;
37 restore_flags(flags);
38 }
39
40 static __inline__ void change_bit(int nr, volatile void * addr)
41 {
42 int mask;
43 volatile unsigned int *a = addr;
44 unsigned long flags;
45
46 a += nr >> 5;
47 mask = 1 << (nr & 0x1f);
48 save_and_cli(flags);
49 *a ^= mask;
50 restore_flags(flags);
51 }
52
53 static __inline__ int test_and_set_bit(int nr, volatile void * addr)
54 {
55 int mask, retval;
56 volatile unsigned int *a = addr;
57 unsigned long flags;
58
59 a += nr >> 5;
60 mask = 1 << (nr & 0x1f);
61 save_and_cli(flags);
62 retval = (mask & *a) != 0;
63 *a |= mask;
64 restore_flags(flags);
65
66 return retval;
67 }
68
69 static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
70 {
71 int mask, retval;
72 volatile unsigned int *a = addr;
73 unsigned long flags;
74
75 a += nr >> 5;
76 mask = 1 << (nr & 0x1f);
77 save_and_cli(flags);
78 retval = (mask & *a) != 0;
79 *a &= ~mask;
80 restore_flags(flags);
81
82 return retval;
83 }
84
85 static __inline__ int test_and_change_bit(int nr, volatile void * addr)
86 {
87 int mask, retval;
88 volatile unsigned int *a = addr;
89 unsigned long flags;
90
91 a += nr >> 5;
92 mask = 1 << (nr & 0x1f);
93 save_and_cli(flags);
94 retval = (mask & *a) != 0;
95 *a ^= mask;
96 restore_flags(flags);
97
98 return retval;
99 }
100
101
102 static __inline__ int test_bit(int nr, const volatile void *addr)
103 {
104 return 1UL & (((const volatile unsigned int *) addr)[nr >> 5] >> (nr & 31));
105 }
106
107 static __inline__ unsigned long ffz(unsigned long word)
108 {
109 unsigned long result;
110
111 __asm__("1:\n\t"
112 "shlr %1\n\t"
113 "bt/s 1b\n\t"
114 " add #1, %0"
115 : "=r" (result), "=r" (word)
116 : "" (~0L), "1" (word)
117 : "t");
118 return result;
119 }
120
121 static __inline__ int find_next_zero_bit(void *addr, int size, int offset)
122 {
123 unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
124 unsigned long result = offset & ~31UL;
125 unsigned long tmp;
126
127 if (offset >= size)
128 return size;
129 size -= result;
130 offset &= 31UL;
131 if (offset) {
132 tmp = *(p++);
133 tmp |= ~0UL >> (32-offset);
134 if (size < 32)
135 goto found_first;
136 if (~tmp)
137 goto found_middle;
138 size -= 32;
139 result += 32;
140 }
141 while (size & ~31UL) {
142 if (~(tmp = *(p++)))
143 goto found_middle;
144 result += 32;
145 size -= 32;
146 }
147 if (!size)
148 return result;
149 tmp = *p;
150
151 found_first:
152 tmp |= ~0UL << size;
153 found_middle:
154 return result + ffz(tmp);
155 }
156
157 #define find_first_zero_bit(addr, size) \
158 find_next_zero_bit((addr), (size), 0)
159
160 #ifdef __LITTLE_ENDIAN__
161 #define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr))
162 #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr))
163 #define ext2_test_bit(nr, addr) test_bit((nr), (addr))
164 #define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size))
165 #define ext2_find_next_zero_bit(addr, size, offset) \
166 find_next_zero_bit((addr), (size), (offset))
167 #else
168 static __inline__ int ext2_set_bit(int nr, volatile void * addr)
169 {
170 int mask, retval;
171 unsigned long flags;
172 volatile unsigned char *ADDR = (unsigned char *) addr;
173
174 ADDR += nr >> 3;
175 mask = 1 << (nr & 0x07);
176 save_and_cli(flags);
177 retval = (mask & *ADDR) != 0;
178 *ADDR |= mask;
179 restore_flags(flags);
180 return retval;
181 }
182
183 static __inline__ int ext2_clear_bit(int nr, volatile void * addr)
184 {
185 int mask, retval;
186 unsigned long flags;
187 volatile unsigned char *ADDR = (unsigned char *) addr;
188
189 ADDR += nr >> 3;
190 mask = 1 << (nr & 0x07);
191 save_and_cli(flags);
192 retval = (mask & *ADDR) != 0;
193 *ADDR &= ~mask;
194 restore_flags(flags);
195 return retval;
196 }
197
198 static __inline__ int ext2_test_bit(int nr, const volatile void * addr)
199 {
200 int mask;
201 const volatile unsigned char *ADDR = (const unsigned char *) addr;
202
203 ADDR += nr >> 3;
204 mask = 1 << (nr & 0x07);
205 return ((mask & *ADDR) != 0);
206 }
207
208 #define ext2_find_first_zero_bit(addr, size) \
209 ext2_find_next_zero_bit((addr), (size), 0)
210
211 static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
212 {
213 unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
214 unsigned long result = offset & ~31UL;
215 unsigned long tmp;
216
217 if (offset >= size)
218 return size;
219 size -= result;
220 offset &= 31UL;
221 if(offset) {
222 /* We hold the little endian value in tmp, but then the
223 * shift is illegal. So we could keep a big endian value
224 * in tmp, like this:
225 *
226 * tmp = __swab32(*(p++));
227 * tmp |= ~0UL >> (32-offset);
228 *
229 * but this would decrease preformance, so we change the
230 * shift:
231 */
232 tmp = *(p++);
233 tmp |= __swab32(~0UL >> (32-offset));
234 if(size < 32)
235 goto found_first;
236 if(~tmp)
237 goto found_middle;
238 size -= 32;
239 result += 32;
240 }
241 while(size & ~31UL) {
242 if(~(tmp = *(p++)))
243 goto found_middle;
244 result += 32;
245 size -= 32;
246 }
247 if(!size)
248 return result;
249 tmp = *p;
250
251 found_first:
252 /* tmp is little endian, so we would have to swab the shift,
253 * see above. But then we have to swab tmp below for ffz, so
254 * we might as well do this here.
255 */
256 return result + ffz(__swab32(tmp) | (~0UL << size));
257 found_middle:
258 return result + ffz(__swab32(tmp));
259 }
260 #endif
261
262 /* Bitmap functions for the minix filesystem. */
263 #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
264 #define minix_set_bit(nr,addr) set_bit(nr,addr)
265 #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
266 #define minix_test_bit(nr,addr) test_bit(nr,addr)
267 #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
268
269 #endif /* __KERNEL__ */
270
271 #endif /* __ASM_SH_BITOPS_H */
272
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.