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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: bitops.h,v 1.38 2001/11/19 18:36:34 davem Exp $
  2.  * bitops.h: Bit string operations on the V9.
  3.  *
  4.  * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
  5.  */
  6. #ifndef _SPARC64_BITOPS_H
  7. #define _SPARC64_BITOPS_H
  8. #include <asm/byteorder.h>
  9. extern long ___test_and_set_bit(unsigned long nr, volatile void *addr);
  10. extern long ___test_and_clear_bit(unsigned long nr, volatile void *addr);
  11. extern long ___test_and_change_bit(unsigned long nr, volatile void *addr);
  12. #define test_and_set_bit(nr,addr) ({___test_and_set_bit(nr,addr)!=0;})
  13. #define test_and_clear_bit(nr,addr) ({___test_and_clear_bit(nr,addr)!=0;})
  14. #define test_and_change_bit(nr,addr) ({___test_and_change_bit(nr,addr)!=0;})
  15. #define set_bit(nr,addr) ((void)___test_and_set_bit(nr,addr))
  16. #define clear_bit(nr,addr) ((void)___test_and_clear_bit(nr,addr))
  17. #define change_bit(nr,addr) ((void)___test_and_change_bit(nr,addr))
  18. /* "non-atomic" versions... */
  19. #define __set_bit(X,Y)
  20. do { unsigned long __nr = (X);
  21. long *__m = ((long *) (Y)) + (__nr >> 6);
  22. *__m |= (1UL << (__nr & 63));
  23. } while (0)
  24. #define __clear_bit(X,Y)
  25. do { unsigned long __nr = (X);
  26. long *__m = ((long *) (Y)) + (__nr >> 6);
  27. *__m &= ~(1UL << (__nr & 63));
  28. } while (0)
  29. #define __change_bit(X,Y)
  30. do { unsigned long __nr = (X);
  31. long *__m = ((long *) (Y)) + (__nr >> 6);
  32. *__m ^= (1UL << (__nr & 63));
  33. } while (0)
  34. #define __test_and_set_bit(X,Y)
  35. ({ unsigned long __nr = (X);
  36. long *__m = ((long *) (Y)) + (__nr >> 6);
  37. long __old = *__m;
  38. long __mask = (1UL << (__nr & 63));
  39. *__m = (__old | __mask);
  40. ((__old & __mask) != 0);
  41. })
  42. #define __test_and_clear_bit(X,Y)
  43. ({ unsigned long __nr = (X);
  44. long *__m = ((long *) (Y)) + (__nr >> 6);
  45. long __old = *__m;
  46. long __mask = (1UL << (__nr & 63));
  47. *__m = (__old & ~__mask);
  48. ((__old & __mask) != 0);
  49. })
  50. #define __test_and_change_bit(X,Y)
  51. ({ unsigned long __nr = (X);
  52. long *__m = ((long *) (Y)) + (__nr >> 6);
  53. long __old = *__m;
  54. long __mask = (1UL << (__nr & 63));
  55. *__m = (__old ^ __mask);
  56. ((__old & __mask) != 0);
  57. })
  58. #define smp_mb__before_clear_bit() do { } while(0)
  59. #define smp_mb__after_clear_bit() do { } while(0)
  60. extern __inline__ int test_bit(int nr, __const__ void *addr)
  61. {
  62. return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL;
  63. }
  64. /* The easy/cheese version for now. */
  65. extern __inline__ unsigned long ffz(unsigned long word)
  66. {
  67. unsigned long result;
  68. #ifdef ULTRA_HAS_POPULATION_COUNT /* Thanks for nothing Sun... */
  69. __asm__ __volatile__(
  70. " brz,pn %0, 1fn"
  71. "  neg %0, %%g1n"
  72. " xnor %0, %%g1, %%g2n"
  73. " popc %%g2, %0n"
  74. "1: " : "=&r" (result)
  75.   : "0" (word)
  76.   : "g1", "g2");
  77. #else
  78. #if 1 /* def EASY_CHEESE_VERSION */
  79. result = 0;
  80. while(word & 1) {
  81. result++;
  82. word >>= 1;
  83. }
  84. #else
  85. unsigned long tmp;
  86. result = 0;
  87. tmp = ~word & -~word;
  88. if (!(unsigned)tmp) {
  89. tmp >>= 32;
  90. result = 32;
  91. }
  92. if (!(unsigned short)tmp) {
  93. tmp >>= 16;
  94. result += 16;
  95. }
  96. if (!(unsigned char)tmp) {
  97. tmp >>= 8;
  98. result += 8;
  99. }
  100. if (tmp & 0xf0) result += 4;
  101. if (tmp & 0xcc) result += 2;
  102. if (tmp & 0xaa) result ++;
  103. #endif
  104. #endif
  105. return result;
  106. }
  107. #ifdef __KERNEL__
  108. /*
  109.  * ffs: find first bit set. This is defined the same way as
  110.  * the libc and compiler builtin ffs routines, therefore
  111.  * differs in spirit from the above ffz (man ffs).
  112.  */
  113. #define ffs(x) generic_ffs(x)
  114. /*
  115.  * hweightN: returns the hamming weight (i.e. the number
  116.  * of bits set) of a N-bit word
  117.  */
  118. #ifdef ULTRA_HAS_POPULATION_COUNT
  119. extern __inline__ unsigned int hweight32(unsigned int w)
  120. {
  121. unsigned int res;
  122. __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
  123. return res;
  124. }
  125. extern __inline__ unsigned int hweight16(unsigned int w)
  126. {
  127. unsigned int res;
  128. __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
  129. return res;
  130. }
  131. extern __inline__ unsigned int hweight8(unsigned int w)
  132. {
  133. unsigned int res;
  134. __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
  135. return res;
  136. }
  137. #else
  138. #define hweight32(x) generic_hweight32(x)
  139. #define hweight16(x) generic_hweight16(x)
  140. #define hweight8(x) generic_hweight8(x)
  141. #endif
  142. #endif /* __KERNEL__ */
  143. /* find_next_zero_bit() finds the first zero bit in a bit string of length
  144.  * 'size' bits, starting the search at bit 'offset'. This is largely based
  145.  * on Linus's ALPHA routines, which are pretty portable BTW.
  146.  */
  147. extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
  148. {
  149. unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
  150. unsigned long result = offset & ~63UL;
  151. unsigned long tmp;
  152. if (offset >= size)
  153. return size;
  154. size -= result;
  155. offset &= 63UL;
  156. if (offset) {
  157. tmp = *(p++);
  158. tmp |= ~0UL >> (64-offset);
  159. if (size < 64)
  160. goto found_first;
  161. if (~tmp)
  162. goto found_middle;
  163. size -= 64;
  164. result += 64;
  165. }
  166. while (size & ~63UL) {
  167. if (~(tmp = *(p++)))
  168. goto found_middle;
  169. result += 64;
  170. size -= 64;
  171. }
  172. if (!size)
  173. return result;
  174. tmp = *p;
  175. found_first:
  176. tmp |= ~0UL << size;
  177. if (tmp == ~0UL)        /* Are any bits zero? */
  178. return result + size; /* Nope. */
  179. found_middle:
  180. return result + ffz(tmp);
  181. }
  182. #define find_first_zero_bit(addr, size) 
  183.         find_next_zero_bit((addr), (size), 0)
  184. extern long ___test_and_set_le_bit(int nr, volatile void *addr);
  185. extern long ___test_and_clear_le_bit(int nr, volatile void *addr);
  186. #define test_and_set_le_bit(nr,addr) ({___test_and_set_le_bit(nr,addr)!=0;})
  187. #define test_and_clear_le_bit(nr,addr) ({___test_and_clear_le_bit(nr,addr)!=0;})
  188. #define set_le_bit(nr,addr) ((void)___test_and_set_le_bit(nr,addr))
  189. #define clear_le_bit(nr,addr) ((void)___test_and_clear_le_bit(nr,addr))
  190. extern __inline__ int test_le_bit(int nr, __const__ void * addr)
  191. {
  192. int mask;
  193. __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
  194. ADDR += nr >> 3;
  195. mask = 1 << (nr & 0x07);
  196. return ((mask & *ADDR) != 0);
  197. }
  198. #define find_first_zero_le_bit(addr, size) 
  199.         find_next_zero_le_bit((addr), (size), 0)
  200. extern __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset)
  201. {
  202. unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
  203. unsigned long result = offset & ~63UL;
  204. unsigned long tmp;
  205. if (offset >= size)
  206. return size;
  207. size -= result;
  208. offset &= 63UL;
  209. if(offset) {
  210. tmp = __swab64p(p++);
  211. tmp |= (~0UL >> (64-offset));
  212. if(size < 64)
  213. goto found_first;
  214. if(~tmp)
  215. goto found_middle;
  216. size -= 64;
  217. result += 64;
  218. }
  219. while(size & ~63) {
  220. if(~(tmp = __swab64p(p++)))
  221. goto found_middle;
  222. result += 64;
  223. size -= 64;
  224. }
  225. if(!size)
  226. return result;
  227. tmp = __swab64p(p);
  228. found_first:
  229. tmp |= (~0UL << size);
  230. if (tmp == ~0UL)        /* Are any bits zero? */
  231. return result + size; /* Nope. */
  232. found_middle:
  233. return result + ffz(tmp);
  234. }
  235. #ifdef __KERNEL__
  236. #define ext2_set_bit test_and_set_le_bit
  237. #define ext2_clear_bit test_and_clear_le_bit
  238. #define ext2_test_bit   test_le_bit
  239. #define ext2_find_first_zero_bit find_first_zero_le_bit
  240. #define ext2_find_next_zero_bit find_next_zero_le_bit
  241. /* Bitmap functions for the minix filesystem.  */
  242. #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
  243. #define minix_set_bit(nr,addr) set_bit(nr,addr)
  244. #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
  245. #define minix_test_bit(nr,addr) test_bit(nr,addr)
  246. #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
  247. #endif /* __KERNEL__ */
  248. #endif /* defined(_SPARC64_BITOPS_H) */