File: /usr/src/linux/include/asm-s390/bitops.h
1 #ifndef _S390_BITOPS_H
2 #define _S390_BITOPS_H
3
4 /*
5 * include/asm-s390/bitops.h
6 *
7 * S390 version
8 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
9 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
10 *
11 * Derived from "include/asm-i386/bitops.h"
12 * Copyright (C) 1992, Linus Torvalds
13 *
14 */
15 #include <linux/config.h>
16
17 /*
18 * bit 0 is the LSB of *addr; bit 31 is the MSB of *addr;
19 * bit 32 is the LSB of *(addr+4). That combined with the
20 * big endian byte order on S390 give the following bit
21 * order in memory:
22 * 1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 \
23 * 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
24 * after that follows the next long with bit numbers
25 * 3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
26 * 2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
27 * The reason for this bit ordering is the fact that
28 * in the architecture independent code bits operations
29 * of the form "flags |= (1 << bitnr)" are used INTERMIXED
30 * with operation of the form "set_bit(bitnr, flags)".
31 */
32
33 /* set ALIGN_CS to 1 if the SMP safe bit operations should
34 * align the address to 4 byte boundary. It seems to work
35 * without the alignment.
36 */
37 #ifdef __KERNEL__
38 #define ALIGN_CS 0
39 #else
40 #define ALIGN_CS 1
41 #ifndef CONFIG_SMP
42 #error "bitops won't work without CONFIG_SMP"
43 #endif
44 #endif
45
46 /* bitmap tables from arch/S390/kernel/bitmap.S */
47 extern const char _oi_bitmap[];
48 extern const char _ni_bitmap[];
49 extern const char _zb_findmap[];
50
51 #ifdef CONFIG_SMP
52 /*
53 * SMP save set_bit routine based on compare and swap (CS)
54 */
55 static __inline__ void set_bit_cs(int nr, volatile void * addr)
56 {
57 __asm__ __volatile__(
58 #if ALIGN_CS == 1
59 " lhi 1,3\n" /* CS must be aligned on 4 byte b. */
60 " nr 1,%1\n" /* isolate last 2 bits of address */
61 " xr %1,1\n" /* make addr % 4 == 0 */
62 " sll 1,3\n"
63 " ar %0,1\n" /* add alignement to bitnr */
64 #endif
65 " lhi 1,31\n"
66 " nr 1,%0\n" /* make shift value */
67 " xr %0,1\n"
68 " srl %0,3\n"
69 " lhi 2,1\n"
70 " la %1,0(%0,%1)\n" /* calc. address for CS */
71 " sll 2,0(1)\n" /* make OR mask */
72 " l %0,0(%1)\n"
73 "0: lr 1,%0\n" /* CS loop starts here */
74 " or 1,2\n" /* set bit */
75 " cs %0,1,0(%1)\n"
76 " jl 0b"
77 : "+a" (nr), "+a" (addr) :
78 : "cc", "memory", "1", "2" );
79 }
80
81 /*
82 * SMP save clear_bit routine based on compare and swap (CS)
83 */
84 static __inline__ void clear_bit_cs(int nr, volatile void * addr)
85 {
86 static const int mask = -1;
87 __asm__ __volatile__(
88 #if ALIGN_CS == 1
89 " lhi 1,3\n" /* CS must be aligned on 4 byte b. */
90 " nr 1,%1\n" /* isolate last 2 bits of address */
91 " xr %1,1\n" /* make addr % 4 == 0 */
92 " sll 1,3\n"
93 " ar %0,1\n" /* add alignement to bitnr */
94 #endif
95 " lhi 1,31\n"
96 " nr 1,%0\n" /* make shift value */
97 " xr %0,1\n"
98 " srl %0,3\n"
99 " lhi 2,1\n"
100 " la %1,0(%0,%1)\n" /* calc. address for CS */
101 " sll 2,0(1)\n"
102 " x 2,%2\n" /* make AND mask */
103 " l %0,0(%1)\n"
104 "0: lr 1,%0\n" /* CS loop starts here */
105 " nr 1,2\n" /* clear bit */
106 " cs %0,1,0(%1)\n"
107 " jl 0b"
108 : "+a" (nr), "+a" (addr) : "m" (mask)
109 : "cc", "memory", "1", "2" );
110 }
111
112 /*
113 * SMP save change_bit routine based on compare and swap (CS)
114 */
115 static __inline__ void change_bit_cs(int nr, volatile void * addr)
116 {
117 __asm__ __volatile__(
118 #if ALIGN_CS == 1
119 " lhi 1,3\n" /* CS must be aligned on 4 byte b. */
120 " nr 1,%1\n" /* isolate last 2 bits of address */
121 " xr %1,1\n" /* make addr % 4 == 0 */
122 " sll 1,3\n"
123 " ar %0,1\n" /* add alignement to bitnr */
124 #endif
125 " lhi 1,31\n"
126 " nr 1,%0\n" /* make shift value */
127 " xr %0,1\n"
128 " srl %0,3\n"
129 " lhi 2,1\n"
130 " la %1,0(%0,%1)\n" /* calc. address for CS */
131 " sll 2,0(1)\n" /* make XR mask */
132 " l %0,0(%1)\n"
133 "0: lr 1,%0\n" /* CS loop starts here */
134 " xr 1,2\n" /* change bit */
135 " cs %0,1,0(%1)\n"
136 " jl 0b"
137 : "+a" (nr), "+a" (addr) :
138 : "cc", "memory", "1", "2" );
139 }
140
141 /*
142 * SMP save test_and_set_bit routine based on compare and swap (CS)
143 */
144 static __inline__ int test_and_set_bit_cs(int nr, volatile void * addr)
145 {
146 __asm__ __volatile__(
147 #if ALIGN_CS == 1
148 " lhi 1,3\n" /* CS must be aligned on 4 byte b. */
149 " nr 1,%1\n" /* isolate last 2 bits of address */
150 " xr %1,1\n" /* make addr % 4 == 0 */
151 " sll 1,3\n"
152 " ar %0,1\n" /* add alignement to bitnr */
153 #endif
154 " lhi 1,31\n"
155 " nr 1,%0\n" /* make shift value */
156 " xr %0,1\n"
157 " srl %0,3\n"
158 " la %1,0(%0,%1)\n" /* calc. address for CS */
159 " lhi 2,1\n"
160 " sll 2,0(1)\n" /* make OR mask */
161 " l %0,0(%1)\n"
162 "0: lr 1,%0\n" /* CS loop starts here */
163 " or 1,2\n" /* set bit */
164 " cs %0,1,0(%1)\n"
165 " jl 0b\n"
166 " nr %0,2\n" /* isolate old bit */
167 : "+a" (nr), "+a" (addr) :
168 : "cc", "memory", "1", "2" );
169 return nr;
170 }
171
172 /*
173 * SMP save test_and_clear_bit routine based on compare and swap (CS)
174 */
175 static __inline__ int test_and_clear_bit_cs(int nr, volatile void * addr)
176 {
177 static const int mask = -1;
178 __asm__ __volatile__(
179 #if ALIGN_CS == 1
180 " lhi 1,3\n" /* CS must be aligned on 4 byte b. */
181 " nr 1,%1\n" /* isolate last 2 bits of address */
182 " xr %1,1\n" /* make addr % 4 == 0 */
183 " sll 1,3\n"
184 " ar %0,1\n" /* add alignement to bitnr */
185 #endif
186 " lhi 1,31\n"
187 " nr 1,%0\n" /* make shift value */
188 " xr %0,1\n"
189 " srl %0,3\n"
190 " la %1,0(%0,%1)\n" /* calc. address for CS */
191 " lhi 2,1\n"
192 " sll 2,0(1)\n"
193 " x 2,%2\n" /* make AND mask */
194 " l %0,0(%1)\n"
195 "0: lr 1,%0\n" /* CS loop starts here */
196 " nr 1,2\n" /* clear bit */
197 " cs %0,1,0(%1)\n"
198 " jl 0b\n"
199 " x 2,%2\n"
200 " nr %0,2\n" /* isolate old bit */
201 : "+a" (nr), "+a" (addr) : "m" (mask)
202 : "cc", "memory", "1", "2" );
203 return nr;
204 }
205
206 /*
207 * SMP save test_and_change_bit routine based on compare and swap (CS)
208 */
209 static __inline__ int test_and_change_bit_cs(int nr, volatile void * addr)
210 {
211 __asm__ __volatile__(
212 #if ALIGN_CS == 1
213 " lhi 1,3\n" /* CS must be aligned on 4 byte b. */
214 " nr 1,%1\n" /* isolate last 2 bits of address */
215 " xr %1,1\n" /* make addr % 4 == 0 */
216 " sll 1,3\n"
217 " ar %0,1\n" /* add alignement to bitnr */
218 #endif
219 " lhi 1,31\n"
220 " nr 1,%0\n" /* make shift value */
221 " xr %0,1\n"
222 " srl %0,3\n"
223 " la %1,0(%0,%1)\n" /* calc. address for CS */
224 " lhi 2,1\n"
225 " sll 2,0(1)\n" /* make OR mask */
226 " l %0,0(%1)\n"
227 "0: lr 1,%0\n" /* CS loop starts here */
228 " xr 1,2\n" /* change bit */
229 " cs %0,1,0(%1)\n"
230 " jl 0b\n"
231 " nr %0,2\n" /* isolate old bit */
232 : "+a" (nr), "+a" (addr) :
233 : "cc", "memory", "1", "2" );
234 return nr;
235 }
236 #endif /* CONFIG_SMP */
237
238 /*
239 * fast, non-SMP set_bit routine
240 */
241 static __inline__ void __set_bit(int nr, volatile void * addr)
242 {
243 __asm__ __volatile__(
244 " lhi 2,24\n"
245 " lhi 1,7\n"
246 " xr 2,%0\n"
247 " nr 1,%0\n"
248 " srl 2,3\n"
249 " la 2,0(2,%1)\n"
250 " la 1,0(1,%2)\n"
251 " oc 0(1,2),0(1)"
252 : : "r" (nr), "a" (addr), "a" (&_oi_bitmap)
253 : "cc", "memory", "1", "2" );
254 }
255
256 static __inline__ void
257 __constant_set_bit(const int nr, volatile void * addr)
258 {
259 switch (nr&7) {
260 case 0:
261 __asm__ __volatile__ ("la 1,%0\n\t"
262 "oi 0(1),0x01"
263 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
264 : : "1", "cc", "memory");
265 break;
266 case 1:
267 __asm__ __volatile__ ("la 1,%0\n\t"
268 "oi 0(1),0x02"
269 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
270 : : "1", "cc", "memory" );
271 break;
272 case 2:
273 __asm__ __volatile__ ("la 1,%0\n\t"
274 "oi 0(1),0x04"
275 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
276 : : "1", "cc", "memory" );
277 break;
278 case 3:
279 __asm__ __volatile__ ("la 1,%0\n\t"
280 "oi 0(1),0x08"
281 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
282 : : "1", "cc", "memory" );
283 break;
284 case 4:
285 __asm__ __volatile__ ("la 1,%0\n\t"
286 "oi 0(1),0x10"
287 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
288 : : "1", "cc", "memory" );
289 break;
290 case 5:
291 __asm__ __volatile__ ("la 1,%0\n\t"
292 "oi 0(1),0x20"
293 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
294 : : "1", "cc", "memory" );
295 break;
296 case 6:
297 __asm__ __volatile__ ("la 1,%0\n\t"
298 "oi 0(1),0x40"
299 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
300 : : "1", "cc", "memory" );
301 break;
302 case 7:
303 __asm__ __volatile__ ("la 1,%0\n\t"
304 "oi 0(1),0x80"
305 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
306 : : "1", "cc", "memory" );
307 break;
308 }
309 }
310
311 #define set_bit_simple(nr,addr) \
312 (__builtin_constant_p((nr)) ? \
313 __constant_set_bit((nr),(addr)) : \
314 __set_bit((nr),(addr)) )
315
316 /*
317 * fast, non-SMP clear_bit routine
318 */
319 static __inline__ void
320 __clear_bit(int nr, volatile void * addr)
321 {
322 __asm__ __volatile__(
323 " lhi 2,24\n"
324 " lhi 1,7\n"
325 " xr 2,%0\n"
326 " nr 1,%0\n"
327 " srl 2,3\n"
328 " la 2,0(2,%1)\n"
329 " la 1,0(1,%2)\n"
330 " nc 0(1,2),0(1)"
331 : : "r" (nr), "a" (addr), "a" (&_ni_bitmap)
332 : "cc", "memory", "1", "2" );
333 }
334
335 static __inline__ void
336 __constant_clear_bit(const int nr, volatile void * addr)
337 {
338 switch (nr&7) {
339 case 0:
340 __asm__ __volatile__ ("la 1,%0\n\t"
341 "ni 0(1),0xFE"
342 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
343 : : "1", "cc", "memory" );
344 break;
345 case 1:
346 __asm__ __volatile__ ("la 1,%0\n\t"
347 "ni 0(1),0xFD"
348 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
349 : : "1", "cc", "memory" );
350 break;
351 case 2:
352 __asm__ __volatile__ ("la 1,%0\n\t"
353 "ni 0(1),0xFB"
354 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
355 : : "1", "cc", "memory" );
356 break;
357 case 3:
358 __asm__ __volatile__ ("la 1,%0\n\t"
359 "ni 0(1),0xF7"
360 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
361 : : "1", "cc", "memory" );
362 break;
363 case 4:
364 __asm__ __volatile__ ("la 1,%0\n\t"
365 "ni 0(1),0xEF"
366 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
367 : : "cc", "memory" );
368 break;
369 case 5:
370 __asm__ __volatile__ ("la 1,%0\n\t"
371 "ni 0(1),0xDF"
372 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
373 : : "1", "cc", "memory" );
374 break;
375 case 6:
376 __asm__ __volatile__ ("la 1,%0\n\t"
377 "ni 0(1),0xBF"
378 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
379 : : "1", "cc", "memory" );
380 break;
381 case 7:
382 __asm__ __volatile__ ("la 1,%0\n\t"
383 "ni 0(1),0x7F"
384 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
385 : : "1", "cc", "memory" );
386 break;
387 }
388 }
389
390 #define clear_bit_simple(nr,addr) \
391 (__builtin_constant_p((nr)) ? \
392 __constant_clear_bit((nr),(addr)) : \
393 __clear_bit((nr),(addr)) )
394
395 /*
396 * fast, non-SMP change_bit routine
397 */
398 static __inline__ void __change_bit(int nr, volatile void * addr)
399 {
400 __asm__ __volatile__(
401 " lhi 2,24\n"
402 " lhi 1,7\n"
403 " xr 2,%0\n"
404 " nr 1,%0\n"
405 " srl 2,3\n"
406 " la 2,0(2,%1)\n"
407 " la 1,0(1,%2)\n"
408 " xc 0(1,2),0(1)"
409 : : "r" (nr), "a" (addr), "a" (&_oi_bitmap)
410 : "cc", "memory", "1", "2" );
411 }
412
413 static __inline__ void
414 __constant_change_bit(const int nr, volatile void * addr)
415 {
416 switch (nr&7) {
417 case 0:
418 __asm__ __volatile__ ("la 1,%0\n\t"
419 "xi 0(1),0x01"
420 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
421 : : "cc", "memory" );
422 break;
423 case 1:
424 __asm__ __volatile__ ("la 1,%0\n\t"
425 "xi 0(1),0x02"
426 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
427 : : "cc", "memory" );
428 break;
429 case 2:
430 __asm__ __volatile__ ("la 1,%0\n\t"
431 "xi 0(1),0x04"
432 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
433 : : "cc", "memory" );
434 break;
435 case 3:
436 __asm__ __volatile__ ("la 1,%0\n\t"
437 "xi 0(1),0x08"
438 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
439 : : "cc", "memory" );
440 break;
441 case 4:
442 __asm__ __volatile__ ("la 1,%0\n\t"
443 "xi 0(1),0x10"
444 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
445 : : "cc", "memory" );
446 break;
447 case 5:
448 __asm__ __volatile__ ("la 1,%0\n\t"
449 "xi 0(1),0x20"
450 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
451 : : "1", "cc", "memory" );
452 break;
453 case 6:
454 __asm__ __volatile__ ("la 1,%0\n\t"
455 "xi 0(1),0x40"
456 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
457 : : "1", "cc", "memory" );
458 break;
459 case 7:
460 __asm__ __volatile__ ("la 1,%0\n\t"
461 "xi 0(1),0x80"
462 : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
463 : : "1", "cc", "memory" );
464 break;
465 }
466 }
467
468 #define change_bit_simple(nr,addr) \
469 (__builtin_constant_p((nr)) ? \
470 __constant_change_bit((nr),(addr)) : \
471 __change_bit((nr),(addr)) )
472
473 /*
474 * fast, non-SMP test_and_set_bit routine
475 */
476 static __inline__ int test_and_set_bit_simple(int nr, volatile void * addr)
477 {
478 static const int mask = 1;
479 int oldbit;
480 __asm__ __volatile__(
481 " lhi 1,24\n"
482 " lhi 2,7\n"
483 " xr 1,%1\n"
484 " nr 2,1\n"
485 " srl 1,3\n"
486 " la 1,0(1,%2)\n"
487 " ic %0,0(1)\n"
488 " srl %0,0(2)\n"
489 " n %0,%4\n"
490 " la 2,0(2,%3)\n"
491 " oc 0(1,1),0(2)"
492 : "=d&" (oldbit) : "r" (nr), "a" (addr),
493 "a" (&_oi_bitmap), "m" (mask)
494 : "cc", "memory", "1", "2" );
495 return oldbit;
496 }
497 #define __test_and_set_bit(X,Y) test_and_set_bit_simple(X,Y)
498
499 /*
500 * fast, non-SMP test_and_clear_bit routine
501 */
502 static __inline__ int test_and_clear_bit_simple(int nr, volatile void * addr)
503 {
504 static const int mask = 1;
505 int oldbit;
506
507 __asm__ __volatile__(
508 " lhi 1,24\n"
509 " lhi 2,7\n"
510 " xr 1,%1\n"
511 " nr 2,1\n"
512 " srl 1,3\n"
513 " la 1,0(1,%2)\n"
514 " ic %0,0(1)\n"
515 " srl %0,0(2)\n"
516 " n %0,%4\n"
517 " la 2,0(2,%3)\n"
518 " nc 0(1,1),0(2)"
519 : "=d&" (oldbit) : "r" (nr), "a" (addr),
520 "a" (&_ni_bitmap), "m" (mask)
521 : "cc", "memory", "1", "2" );
522 return oldbit;
523 }
524 #define __test_and_clear_bit(X,Y) test_and_clear_bit_simple(X,Y)
525
526 /*
527 * fast, non-SMP test_and_change_bit routine
528 */
529 static __inline__ int test_and_change_bit_simple(int nr, volatile void * addr)
530 {
531 static const int mask = 1;
532 int oldbit;
533
534 __asm__ __volatile__(
535 " lhi 1,24\n"
536 " lhi 2,7\n"
537 " xr 1,%1\n"
538 " nr 2,1\n"
539 " srl 1,3\n"
540 " la 1,0(1,%2)\n"
541 " ic %0,0(1)\n"
542 " srl %0,0(2)\n"
543 " n %0,%4\n"
544 " la 2,0(2,%3)\n"
545 " xc 0(1,1),0(2)"
546 : "=d&" (oldbit) : "r" (nr), "a" (addr),
547 "a" (&_oi_bitmap), "m" (mask)
548 : "cc", "memory", "1", "2" );
549 return oldbit;
550 }
551 #define __test_and_change_bit(X,Y) test_and_change_bit_simple(X,Y)
552
553 #ifdef CONFIG_SMP
554 #define set_bit set_bit_cs
555 #define clear_bit clear_bit_cs
556 #define change_bit change_bit_cs
557 #define test_and_set_bit test_and_set_bit_cs
558 #define test_and_clear_bit test_and_clear_bit_cs
559 #define test_and_change_bit test_and_change_bit_cs
560 #else
561 #define set_bit set_bit_simple
562 #define clear_bit clear_bit_simple
563 #define change_bit change_bit_simple
564 #define test_and_set_bit test_and_set_bit_simple
565 #define test_and_clear_bit test_and_clear_bit_simple
566 #define test_and_change_bit test_and_change_bit_simple
567 #endif
568
569
570 /*
571 * This routine doesn't need to be atomic.
572 */
573
574 static __inline__ int __test_bit(int nr, volatile void * addr)
575 {
576 static const int mask = 1;
577 int oldbit;
578
579 __asm__ __volatile__(
580 " lhi 2,24\n"
581 " lhi 1,7\n"
582 " xr 2,%1\n"
583 " nr 1,%1\n"
584 " srl 2,3\n"
585 " ic %0,0(2,%2)\n"
586 " srl %0,0(1)\n"
587 " n %0,%3"
588 : "=d&" (oldbit) : "r" (nr), "a" (addr),
589 "m" (mask)
590 : "cc", "1", "2" );
591 return oldbit;
592 }
593
594 static __inline__ int __constant_test_bit(int nr, volatile void * addr) {
595 return (((volatile char *) addr)[(nr>>3)^3] & (1<<(nr&7))) != 0;
596 }
597
598 #define test_bit(nr,addr) \
599 (__builtin_constant_p((nr)) ? \
600 __constant_test_bit((nr),(addr)) : \
601 __test_bit((nr),(addr)) )
602
603 /*
604 * Find-bit routines..
605 */
606 static __inline__ int find_first_zero_bit(void * addr, unsigned size)
607 {
608 static const int mask = 0xffL;
609 int res;
610
611 if (!size)
612 return 0;
613 __asm__(" lhi 0,-1\n"
614 " lr 1,%1\n"
615 " ahi 1,31\n"
616 " srl 1,5\n"
617 " sr 2,2\n"
618 "0: c 0,0(2,%2)\n"
619 " jne 1f\n"
620 " ahi 2,4\n"
621 " brct 1,0b\n"
622 " lr 2,%1\n"
623 " j 4f\n"
624 "1: l 1,0(2,%2)\n"
625 " sll 2,3\n"
626 " tml 1,0xFFFF\n"
627 " jno 2f\n"
628 " ahi 2,16\n"
629 " srl 1,16\n"
630 "2: tml 1,0x00FF\n"
631 " jno 3f\n"
632 " ahi 2,8\n"
633 " srl 1,8\n"
634 "3: n 1,%3\n"
635 " ic 1,0(1,%4)\n"
636 " n 1,%3\n"
637 " ar 2,1\n"
638 "4: lr %0,2"
639 : "=d" (res) : "a" (size), "a" (addr),
640 "m" (mask), "a" (&_zb_findmap)
641 : "cc", "0", "1", "2" );
642 return (res < size) ? res : size;
643 }
644
645 static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
646 {
647 static const int mask = 0xffL;
648 unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
649 unsigned long bitvec;
650 int set, bit = offset & 31, res;
651
652 if (bit) {
653 /*
654 * Look for zero in first word
655 */
656 bitvec = (*p) >> bit;
657 __asm__(" lr 1,%1\n"
658 " sr %0,%0\n"
659 " tml 1,0xFFFF\n"
660 " jno 0f\n"
661 " ahi %0,16\n"
662 " srl 1,16\n"
663 "0: tml 1,0x00FF\n"
664 " jno 1f\n"
665 " ahi %0,8\n"
666 " srl 1,8\n"
667 "1: n 1,%2\n"
668 " ic 1,0(1,%3)\n"
669 " n 1,%2\n"
670 " ar %0,1"
671 : "=d&" (set) : "d" (bitvec),
672 "m" (mask), "a" (&_zb_findmap)
673 : "cc", "1" );
674 if (set < (32 - bit))
675 return set + offset;
676 offset += 32 - bit;
677 p++;
678 }
679 /*
680 * No zero yet, search remaining full words for a zero
681 */
682 res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
683 return (offset + res);
684 }
685
686 /*
687 * ffz = Find First Zero in word. Undefined if no zero exists,
688 * so code should check against ~0UL first..
689 */
690 static __inline__ unsigned long ffz(unsigned long word)
691 {
692 static const int mask = 0xffL;
693 int result;
694
695 __asm__(" lr 1,%1\n"
696 " sr %0,%0\n"
697 " tml 1,0xFFFF\n"
698 " jno 0f\n"
699 " ahi %0,16\n"
700 " srl 1,16\n"
701 "0: tml 1,0x00FF\n"
702 " jno 1f\n"
703 " ahi %0,8\n"
704 " srl 1,8\n"
705 "1: n 1,%2\n"
706 " ic 1,0(1,%3)\n"
707 " n 1,%2\n"
708 " ar %0,1"
709 : "=d&" (result) : "d" (word),
710 "m" (mask), "a" (&_zb_findmap)
711 : "cc", "1" );
712
713 return result;
714 }
715
716 /*
717 * ffs: find first bit set. This is defined the same way as
718 * the libc and compiler builtin ffs routines, therefore
719 * differs in spirit from the above ffz (man ffs).
720 */
721
722 extern int __inline__ ffs (int x)
723 {
724 int r;
725
726 if (x == 0)
727 return 0;
728 __asm__(" lr %%r1,%1\n"
729 " sr %0,%0\n"
730 " tml %%r1,0xFFFF\n"
731 " jnz 0f\n"
732 " ahi %0,16\n"
733 " srl %%r1,16\n"
734 "0: tml %%r1,0x00FF\n"
735 " jnz 1f\n"
736 " ahi %0,8\n"
737 " srl %%r1,8\n"
738 "1: tml %%r1,0x000F\n"
739 " jnz 2f\n"
740 " ahi %0,4\n"
741 " srl %%r1,4\n"
742 "2: tml %%r1,0x0003\n"
743 " jnz 3f\n"
744 " ahi %0,2\n"
745 " srl %%r1,2\n"
746 "3: tml %%r1,0x0001\n"
747 " jnz 4f\n"
748 " ahi %0,1\n"
749 "4:"
750 : "=&d" (r) : "d" (x) : "cc", "1" );
751 return r+1;
752 }
753
754 /*
755 * hweightN: returns the hamming weight (i.e. the number
756 * of bits set) of a N-bit word
757 */
758
759 #define hweight32(x) generic_hweight32(x)
760 #define hweight16(x) generic_hweight16(x)
761 #define hweight8(x) generic_hweight8(x)
762
763
764 #ifdef __KERNEL__
765
766 /*
767 * ATTENTION: intel byte ordering convention for ext2 and minix !!
768 * bit 0 is the LSB of addr; bit 31 is the MSB of addr;
769 * bit 32 is the LSB of (addr+4).
770 * That combined with the little endian byte order of Intel gives the
771 * following bit order in memory:
772 * 07 06 05 04 03 02 01 00 15 14 13 12 11 10 09 08 \
773 * 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
774 */
775
776 #define ext2_set_bit(nr, addr) test_and_set_bit((nr)^24, addr)
777 #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr)^24, addr)
778 #define ext2_test_bit(nr, addr) test_bit((nr)^24, addr)
779 static __inline__ int ext2_find_first_zero_bit(void *vaddr, unsigned size)
780 {
781 int res;
782
783 if (!size)
784 return 0;
785 __asm__(" lhi 0,-1\n"
786 " lr 1,%1\n"
787 " ahi 1,31\n"
788 " srl 1,5\n"
789 " sr 2,2\n"
790 "0: c 0,0(2,%2)\n"
791 " jne 1f\n"
792 " ahi 2,4\n"
793 " brct 1,0b\n"
794 " lr 2,%1\n"
795 " j 4f\n"
796 "1: l 1,0(2,%2)\n"
797 " sll 2,3\n"
798 " lhi 0,0xff\n"
799 " ahi 2,24\n"
800 " tmh 1,0xFFFF\n"
801 " jo 2f\n"
802 " ahi 2,-16\n"
803 " srl 1,16\n"
804 "2: tml 1,0xFF00\n"
805 " jo 3f\n"
806 " ahi 2,-8\n"
807 " srl 1,8\n"
808 "3: nr 1,0\n"
809 " ic 1,0(1,%3)\n"
810 " ar 2,1\n"
811 "4: lr %0,2"
812 : "=d" (res) : "a" (size), "a" (vaddr),
813 "a" (&_zb_findmap)
814 : "cc", "0", "1", "2" );
815 return (res < size) ? res : size;
816 }
817
818 static __inline__ int
819 ext2_find_next_zero_bit(void *vaddr, unsigned size, unsigned offset)
820 {
821 unsigned long *addr = vaddr;
822 unsigned long *p = addr + (offset >> 5);
823 unsigned long word;
824 int bit = offset & 31UL, res;
825
826 if (offset >= size)
827 return size;
828
829 if (bit) {
830 __asm__(" ic %0,0(%1)\n"
831 " icm %0,2,1(%1)\n"
832 " icm %0,4,2(%1)\n"
833 " icm %0,8,3(%1)"
834 : "=&a" (word) : "a" (p) : "cc" );
835 word >>= bit;
836 res = bit;
837 /* Look for zero in first longword */
838 __asm__(" lhi 0,0xff\n"
839 " tml %1,0xffff\n"
840 " jno 0f\n"
841 " ahi %0,16\n"
842 " srl %1,16\n"
843 "0: tml %1,0x00ff\n"
844 " jno 1f\n"
845 " ahi %0,8\n"
846 " srl %1,8\n"
847 "1: nr %1,0\n"
848 " ic %1,0(%1,%2)\n"
849 " alr %0,%1"
850 : "+&d" (res), "+&a" (word)
851 : "a" (&_zb_findmap)
852 : "cc", "0" );
853 if (res < 32)
854 return (p - addr)*32 + res;
855 p++;
856 }
857 /* No zero yet, search remaining full bytes for a zero */
858 res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
859 return (p - addr) * 32 + res;
860 }
861
862 /* Bitmap functions for the minix filesystem. */
863 /* FIXME !!! */
864 #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
865 #define minix_set_bit(nr,addr) set_bit(nr,addr)
866 #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
867 #define minix_test_bit(nr,addr) test_bit(nr,addr)
868 #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
869
870 #endif /* __KERNEL__ */
871
872 #endif /* _S390_BITOPS_H */
873