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