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