bitops.h
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:28k
源码类别:

嵌入式Linux

开发平台:

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