]>
Commit | Line | Data |
---|---|---|
171d809d GU |
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> | |
2db56e86 | 16 | #include <asm/barrier.h> |
171d809d GU |
17 | |
18 | /* | |
19 | * Bit access functions vary across the ColdFire and 68k families. | |
20 | * So we will break them out here, and then macro in the ones we want. | |
21 | * | |
22 | * ColdFire - supports standard bset/bclr/bchg with register operand only | |
23 | * 68000 - supports standard bset/bclr/bchg with memory operand | |
24 | * >= 68020 - also supports the bfset/bfclr/bfchg instructions | |
25 | * | |
26 | * Although it is possible to use only the bset/bclr/bchg with register | |
27 | * operands on all platforms you end up with larger generated code. | |
28 | * So we use the best form possible on a given platform. | |
29 | */ | |
30 | ||
31 | static inline void bset_reg_set_bit(int nr, volatile unsigned long *vaddr) | |
32 | { | |
33 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
34 | ||
35 | __asm__ __volatile__ ("bset %1,(%0)" | |
36 | : | |
37 | : "a" (p), "di" (nr & 7) | |
38 | : "memory"); | |
39 | } | |
40 | ||
41 | static inline void bset_mem_set_bit(int nr, volatile unsigned long *vaddr) | |
42 | { | |
43 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
44 | ||
45 | __asm__ __volatile__ ("bset %1,%0" | |
46 | : "+m" (*p) | |
47 | : "di" (nr & 7)); | |
48 | } | |
49 | ||
50 | static inline void bfset_mem_set_bit(int nr, volatile unsigned long *vaddr) | |
51 | { | |
52 | __asm__ __volatile__ ("bfset %1{%0:#1}" | |
53 | : | |
54 | : "d" (nr ^ 31), "o" (*vaddr) | |
55 | : "memory"); | |
56 | } | |
57 | ||
58 | #if defined(CONFIG_COLDFIRE) | |
59 | #define set_bit(nr, vaddr) bset_reg_set_bit(nr, vaddr) | |
60 | #elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) | |
61 | #define set_bit(nr, vaddr) bset_mem_set_bit(nr, vaddr) | |
62 | #else | |
63 | #define set_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ | |
64 | bset_mem_set_bit(nr, vaddr) : \ | |
65 | bfset_mem_set_bit(nr, vaddr)) | |
66 | #endif | |
67 | ||
68 | #define __set_bit(nr, vaddr) set_bit(nr, vaddr) | |
69 | ||
70 | ||
171d809d GU |
71 | static inline void bclr_reg_clear_bit(int nr, volatile unsigned long *vaddr) |
72 | { | |
73 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
74 | ||
75 | __asm__ __volatile__ ("bclr %1,(%0)" | |
76 | : | |
77 | : "a" (p), "di" (nr & 7) | |
78 | : "memory"); | |
79 | } | |
80 | ||
81 | static inline void bclr_mem_clear_bit(int nr, volatile unsigned long *vaddr) | |
82 | { | |
83 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
84 | ||
85 | __asm__ __volatile__ ("bclr %1,%0" | |
86 | : "+m" (*p) | |
87 | : "di" (nr & 7)); | |
88 | } | |
89 | ||
90 | static inline void bfclr_mem_clear_bit(int nr, volatile unsigned long *vaddr) | |
91 | { | |
92 | __asm__ __volatile__ ("bfclr %1{%0:#1}" | |
93 | : | |
94 | : "d" (nr ^ 31), "o" (*vaddr) | |
95 | : "memory"); | |
96 | } | |
97 | ||
98 | #if defined(CONFIG_COLDFIRE) | |
99 | #define clear_bit(nr, vaddr) bclr_reg_clear_bit(nr, vaddr) | |
100 | #elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) | |
101 | #define clear_bit(nr, vaddr) bclr_mem_clear_bit(nr, vaddr) | |
102 | #else | |
103 | #define clear_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ | |
104 | bclr_mem_clear_bit(nr, vaddr) : \ | |
105 | bfclr_mem_clear_bit(nr, vaddr)) | |
106 | #endif | |
107 | ||
108 | #define __clear_bit(nr, vaddr) clear_bit(nr, vaddr) | |
109 | ||
110 | ||
111 | static inline void bchg_reg_change_bit(int nr, volatile unsigned long *vaddr) | |
112 | { | |
113 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
114 | ||
115 | __asm__ __volatile__ ("bchg %1,(%0)" | |
116 | : | |
117 | : "a" (p), "di" (nr & 7) | |
118 | : "memory"); | |
119 | } | |
120 | ||
121 | static inline void bchg_mem_change_bit(int nr, volatile unsigned long *vaddr) | |
122 | { | |
123 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
124 | ||
125 | __asm__ __volatile__ ("bchg %1,%0" | |
126 | : "+m" (*p) | |
127 | : "di" (nr & 7)); | |
128 | } | |
129 | ||
130 | static inline void bfchg_mem_change_bit(int nr, volatile unsigned long *vaddr) | |
131 | { | |
132 | __asm__ __volatile__ ("bfchg %1{%0:#1}" | |
133 | : | |
134 | : "d" (nr ^ 31), "o" (*vaddr) | |
135 | : "memory"); | |
136 | } | |
137 | ||
138 | #if defined(CONFIG_COLDFIRE) | |
139 | #define change_bit(nr, vaddr) bchg_reg_change_bit(nr, vaddr) | |
140 | #elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) | |
141 | #define change_bit(nr, vaddr) bchg_mem_change_bit(nr, vaddr) | |
142 | #else | |
143 | #define change_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ | |
144 | bchg_mem_change_bit(nr, vaddr) : \ | |
145 | bfchg_mem_change_bit(nr, vaddr)) | |
146 | #endif | |
147 | ||
148 | #define __change_bit(nr, vaddr) change_bit(nr, vaddr) | |
149 | ||
150 | ||
066def56 | 151 | static inline int test_bit(int nr, const volatile unsigned long *vaddr) |
171d809d GU |
152 | { |
153 | return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0; | |
154 | } | |
155 | ||
156 | ||
157 | static inline int bset_reg_test_and_set_bit(int nr, | |
158 | volatile unsigned long *vaddr) | |
159 | { | |
160 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
161 | char retval; | |
162 | ||
163 | __asm__ __volatile__ ("bset %2,(%1); sne %0" | |
164 | : "=d" (retval) | |
165 | : "a" (p), "di" (nr & 7) | |
166 | : "memory"); | |
167 | return retval; | |
168 | } | |
169 | ||
170 | static inline int bset_mem_test_and_set_bit(int nr, | |
171 | volatile unsigned long *vaddr) | |
172 | { | |
173 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
174 | char retval; | |
175 | ||
176 | __asm__ __volatile__ ("bset %2,%1; sne %0" | |
177 | : "=d" (retval), "+m" (*p) | |
178 | : "di" (nr & 7)); | |
179 | return retval; | |
180 | } | |
181 | ||
182 | static inline int bfset_mem_test_and_set_bit(int nr, | |
183 | volatile unsigned long *vaddr) | |
184 | { | |
185 | char retval; | |
186 | ||
187 | __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0" | |
188 | : "=d" (retval) | |
189 | : "d" (nr ^ 31), "o" (*vaddr) | |
190 | : "memory"); | |
191 | return retval; | |
192 | } | |
193 | ||
194 | #if defined(CONFIG_COLDFIRE) | |
195 | #define test_and_set_bit(nr, vaddr) bset_reg_test_and_set_bit(nr, vaddr) | |
196 | #elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) | |
197 | #define test_and_set_bit(nr, vaddr) bset_mem_test_and_set_bit(nr, vaddr) | |
198 | #else | |
199 | #define test_and_set_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ | |
200 | bset_mem_test_and_set_bit(nr, vaddr) : \ | |
201 | bfset_mem_test_and_set_bit(nr, vaddr)) | |
202 | #endif | |
203 | ||
204 | #define __test_and_set_bit(nr, vaddr) test_and_set_bit(nr, vaddr) | |
205 | ||
206 | ||
207 | static inline int bclr_reg_test_and_clear_bit(int nr, | |
208 | volatile unsigned long *vaddr) | |
209 | { | |
210 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
211 | char retval; | |
212 | ||
213 | __asm__ __volatile__ ("bclr %2,(%1); sne %0" | |
214 | : "=d" (retval) | |
215 | : "a" (p), "di" (nr & 7) | |
216 | : "memory"); | |
217 | return retval; | |
218 | } | |
219 | ||
220 | static inline int bclr_mem_test_and_clear_bit(int nr, | |
221 | volatile unsigned long *vaddr) | |
222 | { | |
223 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
224 | char retval; | |
225 | ||
226 | __asm__ __volatile__ ("bclr %2,%1; sne %0" | |
227 | : "=d" (retval), "+m" (*p) | |
228 | : "di" (nr & 7)); | |
229 | return retval; | |
230 | } | |
231 | ||
232 | static inline int bfclr_mem_test_and_clear_bit(int nr, | |
233 | volatile unsigned long *vaddr) | |
234 | { | |
235 | char retval; | |
236 | ||
237 | __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0" | |
238 | : "=d" (retval) | |
239 | : "d" (nr ^ 31), "o" (*vaddr) | |
240 | : "memory"); | |
241 | return retval; | |
242 | } | |
243 | ||
244 | #if defined(CONFIG_COLDFIRE) | |
245 | #define test_and_clear_bit(nr, vaddr) bclr_reg_test_and_clear_bit(nr, vaddr) | |
246 | #elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) | |
247 | #define test_and_clear_bit(nr, vaddr) bclr_mem_test_and_clear_bit(nr, vaddr) | |
248 | #else | |
249 | #define test_and_clear_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ | |
250 | bclr_mem_test_and_clear_bit(nr, vaddr) : \ | |
251 | bfclr_mem_test_and_clear_bit(nr, vaddr)) | |
252 | #endif | |
253 | ||
254 | #define __test_and_clear_bit(nr, vaddr) test_and_clear_bit(nr, vaddr) | |
255 | ||
256 | ||
257 | static inline int bchg_reg_test_and_change_bit(int nr, | |
258 | volatile unsigned long *vaddr) | |
259 | { | |
260 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
261 | char retval; | |
262 | ||
263 | __asm__ __volatile__ ("bchg %2,(%1); sne %0" | |
264 | : "=d" (retval) | |
265 | : "a" (p), "di" (nr & 7) | |
266 | : "memory"); | |
267 | return retval; | |
268 | } | |
269 | ||
270 | static inline int bchg_mem_test_and_change_bit(int nr, | |
271 | volatile unsigned long *vaddr) | |
272 | { | |
273 | char *p = (char *)vaddr + (nr ^ 31) / 8; | |
274 | char retval; | |
275 | ||
276 | __asm__ __volatile__ ("bchg %2,%1; sne %0" | |
277 | : "=d" (retval), "+m" (*p) | |
278 | : "di" (nr & 7)); | |
279 | return retval; | |
280 | } | |
281 | ||
282 | static inline int bfchg_mem_test_and_change_bit(int nr, | |
283 | volatile unsigned long *vaddr) | |
284 | { | |
285 | char retval; | |
286 | ||
287 | __asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0" | |
288 | : "=d" (retval) | |
289 | : "d" (nr ^ 31), "o" (*vaddr) | |
290 | : "memory"); | |
291 | return retval; | |
292 | } | |
293 | ||
294 | #if defined(CONFIG_COLDFIRE) | |
295 | #define test_and_change_bit(nr, vaddr) bchg_reg_test_and_change_bit(nr, vaddr) | |
296 | #elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) | |
297 | #define test_and_change_bit(nr, vaddr) bchg_mem_test_and_change_bit(nr, vaddr) | |
298 | #else | |
299 | #define test_and_change_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ | |
300 | bchg_mem_test_and_change_bit(nr, vaddr) : \ | |
301 | bfchg_mem_test_and_change_bit(nr, vaddr)) | |
302 | #endif | |
303 | ||
304 | #define __test_and_change_bit(nr, vaddr) test_and_change_bit(nr, vaddr) | |
305 | ||
306 | ||
307 | /* | |
308 | * The true 68020 and more advanced processors support the "bfffo" | |
309 | * instruction for finding bits. ColdFire and simple 68000 parts | |
310 | * (including CPU32) do not support this. They simply use the generic | |
311 | * functions. | |
312 | */ | |
313 | #if defined(CONFIG_CPU_HAS_NO_BITFIELDS) | |
314 | #include <asm-generic/bitops/find.h> | |
315 | #include <asm-generic/bitops/ffz.h> | |
316 | #else | |
317 | ||
318 | static inline int find_first_zero_bit(const unsigned long *vaddr, | |
319 | unsigned size) | |
320 | { | |
321 | const unsigned long *p = vaddr; | |
322 | int res = 32; | |
323 | unsigned int words; | |
324 | unsigned long num; | |
325 | ||
326 | if (!size) | |
327 | return 0; | |
328 | ||
329 | words = (size + 31) >> 5; | |
330 | while (!(num = ~*p++)) { | |
331 | if (!--words) | |
332 | goto out; | |
333 | } | |
334 | ||
335 | __asm__ __volatile__ ("bfffo %1{#0,#0},%0" | |
336 | : "=d" (res) : "d" (num & -num)); | |
337 | res ^= 31; | |
338 | out: | |
339 | res += ((long)p - (long)vaddr - 4) * 8; | |
340 | return res < size ? res : size; | |
341 | } | |
342 | #define find_first_zero_bit find_first_zero_bit | |
343 | ||
344 | static inline int find_next_zero_bit(const unsigned long *vaddr, int size, | |
345 | int offset) | |
346 | { | |
347 | const unsigned long *p = vaddr + (offset >> 5); | |
348 | int bit = offset & 31UL, res; | |
349 | ||
350 | if (offset >= size) | |
351 | return size; | |
352 | ||
353 | if (bit) { | |
354 | unsigned long num = ~*p++ & (~0UL << bit); | |
355 | offset -= bit; | |
356 | ||
357 | /* Look for zero in first longword */ | |
358 | __asm__ __volatile__ ("bfffo %1{#0,#0},%0" | |
359 | : "=d" (res) : "d" (num & -num)); | |
360 | if (res < 32) { | |
361 | offset += res ^ 31; | |
362 | return offset < size ? offset : size; | |
363 | } | |
364 | offset += 32; | |
365 | ||
366 | if (offset >= size) | |
367 | return size; | |
368 | } | |
369 | /* No zero yet, search remaining full bytes for a zero */ | |
370 | return offset + find_first_zero_bit(p, size - offset); | |
371 | } | |
372 | #define find_next_zero_bit find_next_zero_bit | |
373 | ||
374 | static inline int find_first_bit(const unsigned long *vaddr, unsigned size) | |
375 | { | |
376 | const unsigned long *p = vaddr; | |
377 | int res = 32; | |
378 | unsigned int words; | |
379 | unsigned long num; | |
380 | ||
381 | if (!size) | |
382 | return 0; | |
383 | ||
384 | words = (size + 31) >> 5; | |
385 | while (!(num = *p++)) { | |
386 | if (!--words) | |
387 | goto out; | |
388 | } | |
389 | ||
390 | __asm__ __volatile__ ("bfffo %1{#0,#0},%0" | |
391 | : "=d" (res) : "d" (num & -num)); | |
392 | res ^= 31; | |
393 | out: | |
394 | res += ((long)p - (long)vaddr - 4) * 8; | |
395 | return res < size ? res : size; | |
396 | } | |
397 | #define find_first_bit find_first_bit | |
398 | ||
399 | static inline int find_next_bit(const unsigned long *vaddr, int size, | |
400 | int offset) | |
401 | { | |
402 | const unsigned long *p = vaddr + (offset >> 5); | |
403 | int bit = offset & 31UL, res; | |
404 | ||
405 | if (offset >= size) | |
406 | return size; | |
407 | ||
408 | if (bit) { | |
409 | unsigned long num = *p++ & (~0UL << bit); | |
410 | offset -= bit; | |
411 | ||
412 | /* Look for one in first longword */ | |
413 | __asm__ __volatile__ ("bfffo %1{#0,#0},%0" | |
414 | : "=d" (res) : "d" (num & -num)); | |
415 | if (res < 32) { | |
416 | offset += res ^ 31; | |
417 | return offset < size ? offset : size; | |
418 | } | |
419 | offset += 32; | |
420 | ||
421 | if (offset >= size) | |
422 | return size; | |
423 | } | |
424 | /* No one yet, search remaining full bytes for a one */ | |
425 | return offset + find_first_bit(p, size - offset); | |
426 | } | |
427 | #define find_next_bit find_next_bit | |
428 | ||
429 | /* | |
430 | * ffz = Find First Zero in word. Undefined if no zero exists, | |
431 | * so code should check against ~0UL first.. | |
432 | */ | |
433 | static inline unsigned long ffz(unsigned long word) | |
434 | { | |
435 | int res; | |
436 | ||
437 | __asm__ __volatile__ ("bfffo %1{#0,#0},%0" | |
438 | : "=d" (res) : "d" (~word & -~word)); | |
439 | return res ^ 31; | |
440 | } | |
441 | ||
442 | #endif | |
443 | ||
444 | #ifdef __KERNEL__ | |
445 | ||
446 | #if defined(CONFIG_CPU_HAS_NO_BITFIELDS) | |
447 | ||
448 | /* | |
449 | * The newer ColdFire family members support a "bitrev" instruction | |
450 | * and we can use that to implement a fast ffs. Older Coldfire parts, | |
451 | * and normal 68000 parts don't have anything special, so we use the | |
452 | * generic functions for those. | |
453 | */ | |
454 | #if (defined(__mcfisaaplus__) || defined(__mcfisac__)) && \ | |
455 | !defined(CONFIG_M68000) && !defined(CONFIG_MCPU32) | |
456 | static inline int __ffs(int x) | |
457 | { | |
458 | __asm__ __volatile__ ("bitrev %0; ff1 %0" | |
459 | : "=d" (x) | |
460 | : "0" (x)); | |
461 | return x; | |
462 | } | |
463 | ||
464 | static inline int ffs(int x) | |
465 | { | |
466 | if (!x) | |
467 | return 0; | |
468 | return __ffs(x) + 1; | |
469 | } | |
470 | ||
471 | #else | |
472 | #include <asm-generic/bitops/ffs.h> | |
473 | #include <asm-generic/bitops/__ffs.h> | |
474 | #endif | |
475 | ||
476 | #include <asm-generic/bitops/fls.h> | |
477 | #include <asm-generic/bitops/__fls.h> | |
478 | ||
49148020 | 479 | #else |
171d809d GU |
480 | |
481 | /* | |
482 | * ffs: find first bit set. This is defined the same way as | |
483 | * the libc and compiler builtin ffs routines, therefore | |
484 | * differs in spirit from the above ffz (man ffs). | |
485 | */ | |
486 | static inline int ffs(int x) | |
487 | { | |
488 | int cnt; | |
489 | ||
490 | __asm__ ("bfffo %1{#0:#0},%0" | |
491 | : "=d" (cnt) | |
492 | : "dm" (x & -x)); | |
493 | return 32 - cnt; | |
494 | } | |
495 | #define __ffs(x) (ffs(x) - 1) | |
496 | ||
497 | /* | |
498 | * fls: find last bit set. | |
499 | */ | |
500 | static inline int fls(int x) | |
501 | { | |
502 | int cnt; | |
503 | ||
504 | __asm__ ("bfffo %1{#0,#0},%0" | |
505 | : "=d" (cnt) | |
506 | : "dm" (x)); | |
507 | return 32 - cnt; | |
508 | } | |
509 | ||
510 | static inline int __fls(int x) | |
511 | { | |
512 | return fls(x) - 1; | |
513 | } | |
514 | ||
49148020 | 515 | #endif |
171d809d GU |
516 | |
517 | #include <asm-generic/bitops/ext2-atomic.h> | |
518 | #include <asm-generic/bitops/le.h> | |
519 | #include <asm-generic/bitops/fls64.h> | |
520 | #include <asm-generic/bitops/sched.h> | |
521 | #include <asm-generic/bitops/hweight.h> | |
522 | #include <asm-generic/bitops/lock.h> | |
523 | #endif /* __KERNEL__ */ | |
524 | ||
525 | #endif /* _M68K_BITOPS_H */ |