~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-s390/bitops.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.