1 #ifndef _M68K_BITOPS_H
2 #define _M68K_BITOPS_H
3 /*
4 * Copyright 1992, Linus Torvalds.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11 /*
12 * Require 68020 or better.
13 *
14 * They use the standard big-endian m680x0 bit ordering.
15 */
16
17 #define test_and_set_bit(nr,vaddr) \
18 (__builtin_constant_p(nr) ? \
19 __constant_test_and_set_bit(nr, vaddr) : \
20 __generic_test_and_set_bit(nr, vaddr))
21
22 extern __inline__ int __constant_test_and_set_bit(int nr,void * vaddr)
23 {
24 char retval;
25
26 __asm__ __volatile__ ("bset %1,%2; sne %0"
27 : "=d" (retval)
28 : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3]));
29
30 return retval;
31 }
32
33 extern __inline__ int __generic_test_and_set_bit(int nr,void * vaddr)
34 {
35 char retval;
36
37 __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
38 : "=d" (retval) : "d" (nr^31), "a" (vaddr));
39
40 return retval;
41 }
42
43 #define set_bit(nr,vaddr) \
44 (__builtin_constant_p(nr) ? \
45 __constant_set_bit(nr, vaddr) : \
46 __generic_set_bit(nr, vaddr))
47
48 extern __inline__ void __constant_set_bit(int nr, void * vaddr)
49 {
50 __asm__ __volatile__ ("bset %0,%1"
51 : : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3]));
52 }
53
54 extern __inline__ void __generic_set_bit(int nr, void * vaddr)
55 {
56 __asm__ __volatile__ ("bfset %1@{%0:#1}"
57 : : "d" (nr^31), "a" (vaddr));
58 }
59
60 #define test_and_clear_bit(nr,vaddr) \
61 (__builtin_constant_p(nr) ? \
62 __constant_test_and_clear_bit(nr, vaddr) : \
63 __generic_test_and_clear_bit(nr, vaddr))
64
65 extern __inline__ int __constant_test_and_clear_bit(int nr, void * vaddr)
66 {
67 char retval;
68
69 __asm__ __volatile__ ("bclr %1,%2; sne %0"
70 : "=d" (retval)
71 : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3]));
72
73 return retval;
74 }
75
76 extern __inline__ int __generic_test_and_clear_bit(int nr, void * vaddr)
77 {
78 char retval;
79
80 __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
81 : "=d" (retval) : "d" (nr^31), "a" (vaddr));
82
83 return retval;
84 }
85
86 /*
87 * clear_bit() doesn't provide any barrier for the compiler.
88 */
89 #define smp_mb__before_clear_bit() barrier()
90 #define smp_mb__after_clear_bit() barrier()
91
92 #define clear_bit(nr,vaddr) \
93 (__builtin_constant_p(nr) ? \
94 __constant_clear_bit(nr, vaddr) : \
95 __generic_clear_bit(nr, vaddr))
96
97 extern __inline__ void __constant_clear_bit(int nr, void * vaddr)
98 {
99 __asm__ __volatile__ ("bclr %0,%1"
100 : : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3]));
101 }
102
103 extern __inline__ void __generic_clear_bit(int nr, void * vaddr)
104 {
105 __asm__ __volatile__ ("bfclr %1@{%0:#1}"
106 : : "d" (nr^31), "a" (vaddr));
107 }
108
109 #define test_and_change_bit(nr,vaddr) \
110 (__builtin_constant_p(nr) ? \
111 __constant_test_and_change_bit(nr, vaddr) : \
112 __generic_test_and_change_bit(nr, vaddr))
113
114 extern __inline__ int __constant_test_and_change_bit(int nr, void * vaddr)
115 {
116 char retval;
117
118 __asm__ __volatile__ ("bchg %1,%2; sne %0"
119 : "=d" (retval)
120 : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3]));
121
122 return retval;
123 }
124
125 extern __inline__ int __generic_test_and_change_bit(int nr, void * vaddr)
126 {
127 char retval;
128
129 __asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0"
130 : "=d" (retval) : "d" (nr^31), "a" (vaddr));
131
132 return retval;
133 }
134
135 #define change_bit(nr,vaddr) \
136 (__builtin_constant_p(nr) ? \
137 __constant_change_bit(nr, vaddr) : \
138 __generic_change_bit(nr, vaddr))
139
140 extern __inline__ void __constant_change_bit(int nr, void * vaddr)
141 {
142 __asm__ __volatile__ ("bchg %0,%1"
143 : : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3]));
144 }
145
146 extern __inline__ void __generic_change_bit(int nr, void * vaddr)
147 {
148 __asm__ __volatile__ ("bfchg %1@{%0:#1}"
149 : : "d" (nr^31), "a" (vaddr));
150 }
151
152 extern __inline__ int test_bit(int nr, const void * vaddr)
153 {
154 return ((1UL << (nr & 31)) & (((const unsigned int *) vaddr)[nr >> 5])) != 0;
155 }
156
157 extern __inline__ int find_first_zero_bit(void * vaddr, unsigned size)
158 {
159 unsigned long *p = vaddr, *addr = vaddr;
160 unsigned long allones = ~0UL;
161 int res;
162 unsigned long num;
163
164 if (!size)
165 return 0;
166
167 size = (size >> 5) + ((size & 31) > 0);
168 while (*p++ == allones)
169 {
170 if (--size == 0)
171 return (p - addr) << 5;
172 }
173
174 num = ~*--p;
175 __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
176 : "=d" (res) : "d" (num & -num));
177 return ((p - addr) << 5) + (res ^ 31);
178 }
179
180 extern __inline__ int find_next_zero_bit (void *vaddr, int size,
181 int offset)
182 {
183 unsigned long *addr = vaddr;
184 unsigned long *p = addr + (offset >> 5);
185 int set = 0, bit = offset & 31UL, res;
186
187 if (offset >= size)
188 return size;
189
190 if (bit) {
191 unsigned long num = ~*p & (~0UL << bit);
192
193 /* Look for zero in first longword */
194 __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
195 : "=d" (res) : "d" (num & -num));
196 if (res < 32)
197 return (offset & ~31UL) + (res ^ 31);
198 set = 32 - bit;
199 p++;
200 }
201 /* No zero yet, search remaining full bytes for a zero */
202 res = find_first_zero_bit (p, size - 32 * (p - addr));
203 return (offset + set + res);
204 }
205
206 /*
207 * ffz = Find First Zero in word. Undefined if no zero exists,
208 * so code should check against ~0UL first..
209 */
210 extern __inline__ unsigned long ffz(unsigned long word)
211 {
212 int res;
213
214 __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
215 : "=d" (res) : "d" (~word & -~word));
216 return res ^ 31;
217 }
218
219 #ifdef __KERNEL__
220
221 /*
222 * ffs: find first bit set. This is defined the same way as
223 * the libc and compiler builtin ffs routines, therefore
224 * differs in spirit from the above ffz (man ffs).
225 */
226
227 extern __inline__ int ffs(int x)
228 {
229 int cnt;
230
231 asm ("bfffo %1{#0:#0}" : "=d" (cnt) : "dm" (x & -x));
232
233 return 32 - cnt;
234 }
235
236 /*
237 * hweightN: returns the hamming weight (i.e. the number
238 * of bits set) of a N-bit word
239 */
240
241 #define hweight32(x) generic_hweight32(x)
242 #define hweight16(x) generic_hweight16(x)
243 #define hweight8(x) generic_hweight8(x)
244
245 /* Bitmap functions for the minix filesystem */
246
247 extern __inline__ int
248 minix_find_first_zero_bit (const void *vaddr, unsigned size)
249 {
250 const unsigned short *p = vaddr, *addr = vaddr;
251 int res;
252 unsigned short num;
253
254 if (!size)
255 return 0;
256
257 size = (size >> 4) + ((size & 15) > 0);
258 while (*p++ == 0xffff)
259 {
260 if (--size == 0)
261 return (p - addr) << 4;
262 }
263
264 num = ~*--p;
265 __asm__ __volatile__ ("bfffo %1{#16,#16},%0"
266 : "=d" (res) : "d" (num & -num));
267 return ((p - addr) << 4) + (res ^ 31);
268 }
269
270 extern __inline__ int
271 minix_test_and_set_bit (int nr, void *vaddr)
272 {
273 char retval;
274
275 __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
276 : "=d" (retval) : "d" (nr^15), "m" (*(char *)vaddr));
277
278 return retval;
279 }
280
281 #define minix_set_bit(nr,addr) ((void)minix_test_and_set_bit(nr,addr))
282
283 extern __inline__ int
284 minix_test_and_clear_bit (int nr, void *vaddr)
285 {
286 char retval;
287
288 __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
289 : "=d" (retval) : "d" (nr^15), "m" (*(char *) vaddr));
290
291 return retval;
292 }
293
294 extern __inline__ int
295 minix_test_bit (int nr, const void *vaddr)
296 {
297 return ((1U << (nr & 15)) & (((const unsigned short *) vaddr)[nr >> 4])) != 0;
298 }
299
300 /* Bitmap functions for the ext2 filesystem. */
301
302 extern __inline__ int
303 ext2_set_bit (int nr, void *vaddr)
304 {
305 char retval;
306
307 __asm__ __volatile__ ("bfset %2{%1,#1}; sne %0"
308 : "=d" (retval) : "d" (nr^7), "m" (*(char *) vaddr));
309
310 return retval;
311 }
312
313 extern __inline__ int
314 ext2_clear_bit (int nr, void *vaddr)
315 {
316 char retval;
317
318 __asm__ __volatile__ ("bfclr %2{%1,#1}; sne %0"
319 : "=d" (retval) : "d" (nr^7), "m" (*(char *) vaddr));
320
321 return retval;
322 }
323
324 extern __inline__ int
325 ext2_test_bit (int nr, const void *vaddr)
326 {
327 return ((1U << (nr & 7)) & (((const unsigned char *) vaddr)[nr >> 3])) != 0;
328 }
329
330 extern __inline__ int
331 ext2_find_first_zero_bit (const void *vaddr, unsigned size)
332 {
333 const unsigned long *p = vaddr, *addr = vaddr;
334 int res;
335
336 if (!size)
337 return 0;
338
339 size = (size >> 5) + ((size & 31) > 0);
340 while (*p++ == ~0UL)
341 {
342 if (--size == 0)
343 return (p - addr) << 5;
344 }
345
346 --p;
347 for (res = 0; res < 32; res++)
348 if (!ext2_test_bit (res, p))
349 break;
350 return (p - addr) * 32 + res;
351 }
352
353 extern __inline__ int
354 ext2_find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset)
355 {
356 const unsigned long *addr = vaddr;
357 const unsigned long *p = addr + (offset >> 5);
358 int bit = offset & 31UL, res;
359
360 if (offset >= size)
361 return size;
362
363 if (bit) {
364 /* Look for zero in first longword */
365 for (res = bit; res < 32; res++)
366 if (!ext2_test_bit (res, p))
367 return (p - addr) * 32 + res;
368 p++;
369 }
370 /* No zero yet, search remaining full bytes for a zero */
371 res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
372 return (p - addr) * 32 + res;
373 }
374
375 #endif /* __KERNEL__ */
376
377 #endif /* _M68K_BITOPS_H */
378
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.