1#ifndef _M68K_BITOPS_H
2#define _M68K_BITOPS_H
3
4
5
6
7
8
9
10
11
12
13
14
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
22static inline int __constant_test_and_set_bit(int nr, volatile void *vaddr)
23{
24 char retval;
25
26 __asm__ __volatile__ ("bset %2,%1; sne %0"
27 : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
28 : "di" (nr & 7));
29
30 return retval;
31}
32
33static inline int __generic_test_and_set_bit(int nr, volatile void *vaddr)
34{
35 char retval;
36
37 __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
38 : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
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#define __set_bit(nr,vaddr) set_bit(nr,vaddr)
49
50static inline void __constant_set_bit(int nr, volatile void *vaddr)
51{
52 __asm__ __volatile__ ("bset %1,%0"
53 : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
54}
55
56static inline void __generic_set_bit(int nr, volatile void *vaddr)
57{
58 __asm__ __volatile__ ("bfset %1@{%0:#1}"
59 : : "d" (nr^31), "a" (vaddr) : "memory");
60}
61
62#define test_and_clear_bit(nr,vaddr) \
63 (__builtin_constant_p(nr) ? \
64 __constant_test_and_clear_bit(nr, vaddr) : \
65 __generic_test_and_clear_bit(nr, vaddr))
66
67#define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr)
68
69static inline int __constant_test_and_clear_bit(int nr, volatile void *vaddr)
70{
71 char retval;
72
73 __asm__ __volatile__ ("bclr %2,%1; sne %0"
74 : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
75 : "di" (nr & 7));
76
77 return retval;
78}
79
80static inline int __generic_test_and_clear_bit(int nr, volatile void *vaddr)
81{
82 char retval;
83
84 __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
85 : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
86
87 return retval;
88}
89
90
91
92
93#define smp_mb__before_clear_bit() barrier()
94#define smp_mb__after_clear_bit() barrier()
95
96#define clear_bit(nr,vaddr) \
97 (__builtin_constant_p(nr) ? \
98 __constant_clear_bit(nr, vaddr) : \
99 __generic_clear_bit(nr, vaddr))
100
101static inline void __constant_clear_bit(int nr, volatile void *vaddr)
102{
103 __asm__ __volatile__ ("bclr %1,%0"
104 : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
105}
106
107static inline void __generic_clear_bit(int nr, volatile void *vaddr)
108{
109 __asm__ __volatile__ ("bfclr %1@{%0:#1}"
110 : : "d" (nr^31), "a" (vaddr) : "memory");
111}
112
113#define test_and_change_bit(nr,vaddr) \
114 (__builtin_constant_p(nr) ? \
115 __constant_test_and_change_bit(nr, vaddr) : \
116 __generic_test_and_change_bit(nr, vaddr))
117
118#define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr)
119#define __change_bit(nr,vaddr) change_bit(nr,vaddr)
120
121static inline int __constant_test_and_change_bit(int nr, volatile void *vaddr)
122{
123 char retval;
124
125 __asm__ __volatile__ ("bchg %2,%1; sne %0"
126 : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
127 : "di" (nr & 7));
128
129 return retval;
130}
131
132static inline int __generic_test_and_change_bit(int nr, volatile void *vaddr)
133{
134 char retval;
135
136 __asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0"
137 : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
138
139 return retval;
140}
141
142#define change_bit(nr,vaddr) \
143 (__builtin_constant_p(nr) ? \
144 __constant_change_bit(nr, vaddr) : \
145 __generic_change_bit(nr, vaddr))
146
147static inline void __constant_change_bit(int nr, volatile void *vaddr)
148{
149 __asm__ __volatile__ ("bchg %1,%0"
150 : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
151}
152
153static inline void __generic_change_bit(int nr, volatile void *vaddr)
154{
155 __asm__ __volatile__ ("bfchg %1@{%0:#1}"
156 : : "d" (nr^31), "a" (vaddr) : "memory");
157}
158
159static inline int test_bit(int nr, const volatile void *vaddr)
160{
161 return ((1UL << (nr & 31)) & (((const volatile unsigned int *) vaddr)[nr >> 5])) != 0;
162}
163
164static inline int find_first_zero_bit(void *vaddr, unsigned size)
165{
166 unsigned long *p = vaddr, *addr = vaddr;
167 unsigned long allones = ~0UL;
168 int res;
169 unsigned long num;
170
171 if (!size)
172 return 0;
173
174 size = (size >> 5) + ((size & 31) > 0);
175 while (*p++ == allones)
176 {
177 if (--size == 0)
178 return (p - addr) << 5;
179 }
180
181 num = ~*--p;
182 __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
183 : "=d" (res) : "d" (num & -num));
184 return ((p - addr) << 5) + (res ^ 31);
185}
186
187static inline int find_next_zero_bit(void *vaddr, int size, int offset)
188{
189 unsigned long *addr = vaddr;
190 unsigned long *p = addr + (offset >> 5);
191 int set = 0, bit = offset & 31UL, res;
192
193 if (offset >= size)
194 return size;
195
196 if (bit) {
197 unsigned long num = ~*p & (~0UL << bit);
198
199
200 __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
201 : "=d" (res) : "d" (num & -num));
202 if (res < 32)
203 return (offset & ~31UL) + (res ^ 31);
204 set = 32 - bit;
205 p++;
206 }
207
208 res = find_first_zero_bit (p, size - 32 * (p - addr));
209 return (offset + set + res);
210}
211
212
213
214
215
216static inline unsigned long ffz(unsigned long word)
217{
218 int res;
219
220 __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
221 : "=d" (res) : "d" (~word & -~word));
222 return res ^ 31;
223}
224
225#ifdef __KERNEL__
226
227
228
229
230
231
232
233static inline int ffs(int x)
234{
235 int cnt;
236
237 __asm__ __volatile__("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x));
238
239 return 32 - cnt;
240}
241
242
243
244
245
246
247#define hweight32(x) generic_hweight32(x)
248#define hweight16(x) generic_hweight16(x)
249#define hweight8(x) generic_hweight8(x)
250
251
252
253static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size)
254{
255 const unsigned short *p = vaddr, *addr = vaddr;
256 int res;
257 unsigned short num;
258
259 if (!size)
260 return 0;
261
262 size = (size >> 4) + ((size & 15) > 0);
263 while (*p++ == 0xffff)
264 {
265 if (--size == 0)
266 return (p - addr) << 4;
267 }
268
269 num = ~*--p;
270 __asm__ __volatile__ ("bfffo %1{#16,#16},%0"
271 : "=d" (res) : "d" (num & -num));
272 return ((p - addr) << 4) + (res ^ 31);
273}
274
275static inline int minix_test_and_set_bit(int nr, volatile void *vaddr)
276{
277 char retval;
278
279 __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
280 : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *)vaddr) : "memory");
281
282 return retval;
283}
284
285#define minix_set_bit(nr,addr) ((void)minix_test_and_set_bit(nr,addr))
286
287static inline int minix_test_and_clear_bit(int nr, volatile void *vaddr)
288{
289 char retval;
290
291 __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
292 : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *) vaddr) : "memory");
293
294 return retval;
295}
296
297static inline int minix_test_bit(int nr, const volatile void *vaddr)
298{
299 return ((1U << (nr & 15)) & (((const volatile unsigned short *) vaddr)[nr >> 4])) != 0;
300}
301
302
303
304static inline int ext2_set_bit(int nr, volatile void *vaddr)
305{
306 char retval;
307
308 __asm__ __volatile__ ("bfset %2{%1,#1}; sne %0"
309 : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory");
310
311 return retval;
312}
313
314static inline int ext2_clear_bit(int nr, volatile void *vaddr)
315{
316 char retval;
317
318 __asm__ __volatile__ ("bfclr %2{%1,#1}; sne %0"
319 : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory");
320
321 return retval;
322}
323
324static inline int ext2_test_bit(int nr, const volatile void *vaddr)
325{
326 return ((1U << (nr & 7)) & (((const volatile unsigned char *) vaddr)[nr >> 3])) != 0;
327}
328
329static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size)
330{
331 const unsigned long *p = vaddr, *addr = vaddr;
332 int res;
333
334 if (!size)
335 return 0;
336
337 size = (size >> 5) + ((size & 31) > 0);
338 while (*p++ == ~0UL)
339 {
340 if (--size == 0)
341 return (p - addr) << 5;
342 }
343
344 --p;
345 for (res = 0; res < 32; res++)
346 if (!ext2_test_bit (res, p))
347 break;
348 return (p - addr) * 32 + res;
349}
350
351static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size,
352 unsigned offset)
353{
354 const unsigned long *addr = vaddr;
355 const unsigned long *p = addr + (offset >> 5);
356 int bit = offset & 31UL, res;
357
358 if (offset >= size)
359 return size;
360
361 if (bit) {
362
363 for (res = bit; res < 32; res++)
364 if (!ext2_test_bit (res, p))
365 return (p - addr) * 32 + res;
366 p++;
367 }
368
369 res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
370 return (p - addr) * 32 + res;
371}
372
373#endif
374
375#endif
376