]> rtime.felk.cvut.cz Git - mcf548x/linux.git/blob - arch/m68k/include/asm/bitops_coldfire.h
b974269141b99d2bdf9ca533d93119ad2482d63a
[mcf548x/linux.git] / arch / m68k / include / asm / bitops_coldfire.h
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 #ifndef _LINUX_BITOPS_H
12 #error only <linux/bitops.h> can be included directly
13 #endif
14
15 #include <linux/compiler.h>
16
17 #define test_and_set_bit(nr,vaddr)                      \
18   (__builtin_constant_p(nr) ?                           \
19    __constant_coldfire_test_and_set_bit(nr, vaddr) :    \
20    __generic_coldfire_test_and_set_bit(nr, vaddr))
21
22
23 static __inline__ int __constant_coldfire_test_and_set_bit(int nr,
24         volatile void *vaddr)
25 {
26         char retval;
27         volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
28
29         __asm__ __volatile__ ("bset %2,%1; sne %0"
30              : "=d" (retval), "+QUd" (*p)
31              : "di" (nr & 7));
32         return retval;
33 }
34
35 static __inline__ int __generic_coldfire_test_and_set_bit(int nr,
36         volatile void *vaddr)
37 {
38         char retval;
39
40         __asm__ __volatile__ ("bset %2,%1; sne %0"
41              : "=d" (retval), "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
42              : "d" (nr)
43              : "memory");
44         return retval;
45 }
46 #define __test_and_set_bit(nr, vaddr) test_and_set_bit(nr, vaddr)
47
48 #define set_bit(nr,vaddr)                       \
49   (__builtin_constant_p(nr) ?                   \
50    __constant_coldfire_set_bit(nr, vaddr) :     \
51    __generic_coldfire_set_bit(nr, vaddr))
52
53 static __inline__ void __constant_coldfire_set_bit(int nr,
54         volatile void *vaddr)
55 {
56         volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
57         __asm__ __volatile__ ("bset %1,%0"
58              : "+QUd" (*p) : "di" (nr & 7));
59 }
60
61 static __inline__ void __generic_coldfire_set_bit(int nr, volatile void *vaddr)
62 {
63         __asm__ __volatile__ ("bset %1,%0"
64              : "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
65              : "d" (nr)
66              : "memory");
67 }
68 #define __set_bit(nr, vaddr) set_bit(nr, vaddr)
69
70 #define test_and_clear_bit(nr, vaddr)                   \
71   (__builtin_constant_p(nr) ?                           \
72    __constant_coldfire_test_and_clear_bit(nr, vaddr) :  \
73    __generic_coldfire_test_and_clear_bit(nr, vaddr))
74
75 static __inline__ int __constant_coldfire_test_and_clear_bit(int nr,
76         volatile void *vaddr)
77 {
78         char retval;
79         volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
80
81         __asm__ __volatile__ ("bclr %2,%1; sne %0"
82              : "=d" (retval), "+QUd" (*p)
83              : "id" (nr & 7));
84
85         return retval;
86 }
87
88 static __inline__ int __generic_coldfire_test_and_clear_bit(int nr,
89         volatile void *vaddr)
90 {
91         char retval;
92
93         __asm__ __volatile__ ("bclr %2,%1; sne %0"
94              : "=d" (retval), "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
95              : "d" (nr & 7)
96              : "memory");
97
98         return retval;
99 }
100 #define __test_and_clear_bit(nr, vaddr) test_and_clear_bit(nr, vaddr)
101
102 /*
103  * clear_bit() doesn't provide any barrier for the compiler.
104  */
105 #define smp_mb__before_clear_bit()      barrier()
106 #define smp_mb__after_clear_bit()       barrier()
107
108 #define clear_bit(nr,vaddr)                     \
109   (__builtin_constant_p(nr) ?                   \
110    __constant_coldfire_clear_bit(nr, vaddr) :   \
111    __generic_coldfire_clear_bit(nr, vaddr))
112
113 static __inline__ void __constant_coldfire_clear_bit(int nr,
114         volatile void *vaddr)
115 {
116         volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
117         __asm__ __volatile__ ("bclr %1,%0"
118              : "+QUd" (*p) : "id" (nr & 7));
119 }
120
121 static __inline__ void __generic_coldfire_clear_bit(int nr,
122         volatile void *vaddr)
123 {
124         __asm__ __volatile__ ("bclr %1,%0"
125              : "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
126              : "d" (nr)
127              : "memory");
128 }
129 #define __clear_bit(nr, vaddr) clear_bit(nr, vaddr)
130
131 #define test_and_change_bit(nr, vaddr)                  \
132   (__builtin_constant_p(nr) ?                           \
133    __constant_coldfire_test_and_change_bit(nr, vaddr) : \
134    __generic_coldfire_test_and_change_bit(nr, vaddr))
135
136 static __inline__ int __constant_coldfire_test_and_change_bit(int nr,
137         volatile void *vaddr)
138 {
139         char retval;
140         volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
141
142         __asm__ __volatile__ ("bchg %2,%1; sne %0"
143              : "=d" (retval), "+QUd" (*p)
144              : "id" (nr & 7));
145
146         return retval;
147 }
148
149 static __inline__ int __generic_coldfire_test_and_change_bit(int nr,
150         volatile void *vaddr)
151 {
152         char retval;
153
154         __asm__ __volatile__ ("bchg %2,%1; sne %0"
155              : "=d" (retval), "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
156              : "id" (nr)
157              : "memory");
158
159         return retval;
160 }
161 #define __test_and_change_bit(nr, vaddr) test_and_change_bit(nr, vaddr)
162 #define __change_bit(nr, vaddr) change_bit(nr, vaddr)
163
164 #define change_bit(nr,vaddr)                    \
165   (__builtin_constant_p(nr) ?                   \
166    __constant_coldfire_change_bit(nr, vaddr) :  \
167    __generic_coldfire_change_bit(nr, vaddr))
168
169 static __inline__ void __constant_coldfire_change_bit(int nr,
170         volatile void *vaddr)
171 {
172         volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
173         __asm__ __volatile__ ("bchg %1,%0"
174              : "+QUd" (*p) : "id" (nr & 7));
175 }
176
177 static __inline__ void __generic_coldfire_change_bit(int nr,
178         volatile void *vaddr)
179 {
180         __asm__ __volatile__ ("bchg %1,%0"
181              : "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
182              : "d" (nr)
183              : "memory");
184 }
185
186 static inline int test_bit(int nr, const unsigned long *vaddr)
187 {
188         return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0;
189 }
190
191 static __inline__ unsigned long ffz(unsigned long word)
192 {
193         unsigned long result = 0;
194
195         while (word & 1) {
196                 result++;
197                 word >>= 1;
198         }
199         return result;
200 }
201
202 /* find_next_zero_bit() finds the first zero bit in a bit string of length
203  * 'size' bits, starting the search at bit 'offset'.  This is largely based
204  * on Linus's ALPHA routines.
205  */
206 static __inline__ unsigned long find_next_zero_bit(void *addr,
207         unsigned long size, unsigned long offset)
208 {
209         unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
210         unsigned long result = offset & ~31UL;
211         unsigned long tmp;
212
213         if (offset >= size)
214                 return size;
215         size -= result;
216         offset &= 31UL;
217         if (offset) {
218                 tmp = *(p++);
219                 tmp |= ~0UL >> (32-offset);
220                 if (size < 32)
221                         goto found_first;
222                 if (~tmp)
223                         goto found_middle;
224                 size -= 32;
225                 result += 32;
226         }
227         while (size & ~31UL) {
228                 tmp = *(p++);
229                 if (~tmp)
230                         goto found_middle;
231                 result += 32;
232                 size -= 32;
233         }
234         if (!size)
235                 return result;
236         tmp = *p;
237
238 found_first:
239         tmp |= ~0UL >> size;
240 found_middle:
241         return result + ffz(tmp);
242 }
243
244 #define find_first_zero_bit(addr, size) find_next_zero_bit(((void *)addr), \
245                 (size), 0)
246
247 /* Ported from included/linux/bitops.h  */
248 static __inline__ int ffs(int x)
249 {
250         int r = 1;
251
252         if (!x)
253                 return 0;
254         if (!(x & 0xffff)) {
255                 x >>= 16;
256                 r += 16;
257         }
258         if (!(x & 0xff)) {
259                 x >>= 8;
260                 r += 8;
261         }
262         if (!(x & 0xf)) {
263                 x >>= 4;
264                 r += 4;
265         }
266         if (!(x & 3)) {
267                 x >>= 2;
268                 r += 2;
269         }
270         if (!(x & 1)) {
271                 x >>= 1;
272                 r += 1;
273         }
274         return r;
275 }
276 #define __ffs(x) (ffs(x) - 1)
277
278 /* find_next_bit - find the next set bit in a memory region
279  * (from asm-ppc/bitops.h)
280  */
281 static __inline__ unsigned long find_next_bit(const unsigned long *addr,
282         unsigned long size, unsigned long offset)
283 {
284         unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
285         unsigned int result = offset & ~31UL;
286         unsigned int tmp;
287
288         if (offset >= size)
289                 return size;
290         size -= result;
291         offset &= 31UL;
292         if (offset) {
293                 tmp = *p++;
294                 tmp &= ~0UL << offset;
295                 if (size < 32)
296                         goto found_first;
297                 if (tmp)
298                         goto found_middle;
299                 size -= 32;
300                 result += 32;
301         }
302         while (size >= 32) {
303                 tmp = *p++;
304                 if (tmp != 0)
305                         goto found_middle;
306                 result += 32;
307                 size -= 32;
308         }
309         if (!size)
310                 return result;
311         tmp = *p;
312
313 found_first:
314         tmp &= ~0UL >> (32 - size);
315         if (tmp == 0UL)        /* Are any bits set? */
316                 return result + size; /* Nope. */
317 found_middle:
318         return result + __ffs(tmp);
319 }
320
321 #define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
322
323 #ifdef __KERNEL__
324
325 /* Ported from include/linux/bitops.h */
326 static  __inline__ int fls(int x)
327 {
328         int r = 32;
329
330         if (!x)
331                 return 0;
332         if (!(x & 0xffff0000u)) {
333                 x <<= 16;
334                 r -= 16;
335         }
336         if (!(x & 0xff000000u)) {
337                 x <<= 8;
338                 r -= 8;
339         }
340         if (!(x & 0xf0000000u)) {
341                 x <<= 4;
342                 r -= 4;
343         }
344         if (!(x & 0xc0000000u)) {
345                 x <<= 2;
346                 r -= 2;
347         }
348         if (!(x & 0x80000000u)) {
349                 x <<= 1;
350                 r -= 1;
351         }
352         return r;
353 }
354
355 #include <asm-generic/bitops/fls64.h>
356 #include <asm-generic/bitops/sched.h>
357 #include <asm-generic/bitops/hweight.h>
358 #include <asm-generic/bitops/lock.h>
359
360 #define minix_find_first_zero_bit(addr, size)   find_next_zero_bit((addr), \
361                                                         (size), 0)
362 #define minix_test_and_set_bit(nr, addr)        test_and_set_bit((nr), \
363                                                         (unsigned long *)(addr))
364 #define minix_set_bit(nr, addr)                 set_bit((nr), \
365                                                         (unsigned long *)(addr))
366 #define minix_test_and_clear_bit(nr, addr)      test_and_clear_bit((nr), \
367                                                         (unsigned long *)(addr))
368
369 static inline int minix_test_bit(int nr, const volatile unsigned long *vaddr)
370 {
371         int     *a = (int *)vaddr;
372         int     mask;
373
374         a += nr >> 5;
375         mask = 1 << (nr & 0x1f);
376         return ((mask & *a) != 0);
377 }
378
379 #define ext2_set_bit(nr, addr)                  test_and_set_bit((nr) ^ 24, \
380                                                         (unsigned long *)(addr))
381 #define ext2_set_bit_atomic(lock, nr, addr)     test_and_set_bit((nr) ^ 24, \
382                                                         (unsigned long *)(addr))
383 #define ext2_clear_bit(nr, addr)                test_and_clear_bit((nr) ^ 24, \
384                                                         (unsigned long *)(addr))
385 #define ext2_clear_bit_atomic(lock, nr, addr)   test_and_clear_bit((nr) ^ 24, \
386                                                         (unsigned long *)(addr))
387
388 static inline int ext2_test_bit(int nr, const void *vaddr)
389 {
390         const unsigned char *p = vaddr;
391         return (p[nr >> 3] & (1U << (nr & 7))) != 0;
392 }
393
394 static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size)
395 {
396         const unsigned long *p = vaddr, *addr = vaddr;
397         int res;
398
399         if (!size)
400                 return 0;
401
402         size = (size >> 5) + ((size & 31) > 0);
403         while (*p++ == ~0UL) {
404                 if (--size == 0)
405                         return (p - addr) << 5;
406         }
407
408         --p;
409         for (res = 0; res < 32; res++)
410                 if (!ext2_test_bit (res, p))
411                         break;
412         return (p - addr) * 32 + res;
413 }
414
415 static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size,
416                                           unsigned offset)
417 {
418         const unsigned long *addr = vaddr;
419         const unsigned long *p = addr + (offset >> 5);
420         int bit = offset & 31UL, res;
421
422         if (offset >= size)
423                 return size;
424
425         if (bit) {
426                 /* Look for zero in first longword */
427                 for (res = bit; res < 32; res++)
428                         if (!ext2_test_bit (res, p))
429                                 return (p - addr) * 32 + res;
430                 p++;
431         }
432         /* No zero yet, search remaining full bytes for a zero */
433         res = ext2_find_first_zero_bit(p, size - 32 * (p - addr));
434         return (p - addr) * 32 + res;
435 }
436
437 #endif /* KERNEL */
438
439 #endif /* _M68K_BITOPS_H */