bitops.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:29k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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