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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: bitops.h,v 1.67 2001/11/19 18:36:34 davem Exp $
  2.  * bitops.h: Bit string operations on the Sparc.
  3.  *
  4.  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
  5.  * Copyright 1996 Eddie C. Dost   (ecd@skynet.be)
  6.  * Copyright 2001 Anton Blanchard (anton@samba.org)
  7.  */
  8. #ifndef _SPARC_BITOPS_H
  9. #define _SPARC_BITOPS_H
  10. #include <linux/kernel.h>
  11. #include <asm/byteorder.h>
  12. #include <asm/system.h>
  13. #ifdef __KERNEL__
  14. /*
  15.  * Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
  16.  * is in the highest of the four bytes and bit '31' is the high bit
  17.  * within the first byte. Sparc is BIG-Endian. Unless noted otherwise
  18.  * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
  19.  */
  20. static __inline__ int test_and_set_bit(unsigned long nr, volatile void *addr)
  21. {
  22. register unsigned long mask asm("g2");
  23. register unsigned long *ADDR asm("g1");
  24. ADDR = ((unsigned long *) addr) + (nr >> 5);
  25. mask = 1 << (nr & 31);
  26. __asm__ __volatile__(
  27. "mov %%o7, %%g4nt"
  28. "call ___set_bitnt"
  29. " add %%o7, 8, %%o7n"
  30. : "=&r" (mask)
  31. : "0" (mask), "r" (ADDR)
  32. : "g3", "g4", "g5", "g7", "memory", "cc");
  33. return mask != 0;
  34. }
  35. static __inline__ void set_bit(unsigned long nr, volatile void *addr)
  36. {
  37. register unsigned long mask asm("g2");
  38. register unsigned long *ADDR asm("g1");
  39. ADDR = ((unsigned long *) addr) + (nr >> 5);
  40. mask = 1 << (nr & 31);
  41. __asm__ __volatile__(
  42. "mov %%o7, %%g4nt"
  43. "call ___set_bitnt"
  44. " add %%o7, 8, %%o7n"
  45. : "=&r" (mask)
  46. : "0" (mask), "r" (ADDR)
  47. : "g3", "g4", "g5", "g7", "cc");
  48. }
  49. static __inline__ int test_and_clear_bit(unsigned long nr, volatile void *addr)
  50. {
  51. register unsigned long mask asm("g2");
  52. register unsigned long *ADDR asm("g1");
  53. ADDR = ((unsigned long *) addr) + (nr >> 5);
  54. mask = 1 << (nr & 31);
  55. __asm__ __volatile__(
  56. "mov %%o7, %%g4nt"
  57. "call ___clear_bitnt"
  58. " add %%o7, 8, %%o7n"
  59. : "=&r" (mask)
  60. : "0" (mask), "r" (ADDR)
  61. : "g3", "g4", "g5", "g7", "memory", "cc");
  62. return mask != 0;
  63. }
  64. static __inline__ void clear_bit(unsigned long nr, volatile void *addr)
  65. {
  66. register unsigned long mask asm("g2");
  67. register unsigned long *ADDR asm("g1");
  68. ADDR = ((unsigned long *) addr) + (nr >> 5);
  69. mask = 1 << (nr & 31);
  70. __asm__ __volatile__(
  71. "mov %%o7, %%g4nt"
  72. "call ___clear_bitnt"
  73. " add %%o7, 8, %%o7n"
  74. : "=&r" (mask)
  75. : "0" (mask), "r" (ADDR)
  76. : "g3", "g4", "g5", "g7", "cc");
  77. }
  78. static __inline__ int test_and_change_bit(unsigned long nr, volatile void *addr)
  79. {
  80. register unsigned long mask asm("g2");
  81. register unsigned long *ADDR asm("g1");
  82. ADDR = ((unsigned long *) addr) + (nr >> 5);
  83. mask = 1 << (nr & 31);
  84. __asm__ __volatile__(
  85. "mov %%o7, %%g4nt"
  86. "call ___change_bitnt"
  87. " add %%o7, 8, %%o7n"
  88. : "=&r" (mask)
  89. : "0" (mask), "r" (ADDR)
  90. : "g3", "g4", "g5", "g7", "memory", "cc");
  91. return mask != 0;
  92. }
  93. static __inline__ void change_bit(unsigned long nr, volatile void *addr)
  94. {
  95. register unsigned long mask asm("g2");
  96. register unsigned long *ADDR asm("g1");
  97. ADDR = ((unsigned long *) addr) + (nr >> 5);
  98. mask = 1 << (nr & 31);
  99. __asm__ __volatile__(
  100. "mov %%o7, %%g4nt"
  101. "call ___change_bitnt"
  102. " add %%o7, 8, %%o7n"
  103. : "=&r" (mask)
  104. : "0" (mask), "r" (ADDR)
  105. : "g3", "g4", "g5", "g7", "cc");
  106. }
  107. /*
  108.  * non-atomic versions
  109.  */
  110. static __inline__ void __set_bit(int nr, volatile void *addr)
  111. {
  112. unsigned long mask = 1UL << (nr & 0x1f);
  113. unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
  114. *p |= mask;
  115. }
  116. static __inline__ void __clear_bit(int nr, volatile void *addr)
  117. {
  118. unsigned long mask = 1UL << (nr & 0x1f);
  119. unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
  120. *p &= ~mask;
  121. }
  122. static __inline__ void __change_bit(int nr, volatile void *addr)
  123. {
  124. unsigned long mask = 1UL << (nr & 0x1f);
  125. unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
  126. *p ^= mask;
  127. }
  128. static __inline__ int __test_and_set_bit(int nr, volatile void *addr)
  129. {
  130. unsigned long mask = 1UL << (nr & 0x1f);
  131. unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
  132. unsigned long old = *p;
  133. *p = old | mask;
  134. return (old & mask) != 0;
  135. }
  136. static __inline__ int __test_and_clear_bit(int nr, volatile void *addr)
  137. {
  138. unsigned long mask = 1UL << (nr & 0x1f);
  139. unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
  140. unsigned long old = *p;
  141. *p = old & ~mask;
  142. return (old & mask) != 0;
  143. }
  144. static __inline__ int __test_and_change_bit(int nr, volatile void *addr)
  145. {
  146. unsigned long mask = 1UL << (nr & 0x1f);
  147. unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
  148. unsigned long old = *p;
  149. *p = old ^ mask;
  150. return (old & mask) != 0;
  151. }
  152. #define smp_mb__before_clear_bit() do { } while(0)
  153. #define smp_mb__after_clear_bit() do { } while(0)
  154. /* The following routine need not be atomic. */
  155. static __inline__ int test_bit(int nr, __const__ void *addr)
  156. {
  157. return (1 & (((__const__ unsigned int *) addr)[nr >> 5] >> (nr & 31))) != 0;
  158. }
  159. /* The easy/cheese version for now. */
  160. static __inline__ unsigned long ffz(unsigned long word)
  161. {
  162. unsigned long result = 0;
  163. while(word & 1) {
  164. result++;
  165. word >>= 1;
  166. }
  167. return result;
  168. }
  169. /*
  170.  * ffs: find first bit set. This is defined the same way as
  171.  * the libc and compiler builtin ffs routines, therefore
  172.  * differs in spirit from the above ffz (man ffs).
  173.  */
  174. #define ffs(x) generic_ffs(x)
  175. /*
  176.  * hweightN: returns the hamming weight (i.e. the number
  177.  * of bits set) of a N-bit word
  178.  */
  179. #define hweight32(x) generic_hweight32(x)
  180. #define hweight16(x) generic_hweight16(x)
  181. #define hweight8(x) generic_hweight8(x)
  182. /*
  183.  * find_next_zero_bit() finds the first zero bit in a bit string of length
  184.  * 'size' bits, starting the search at bit 'offset'. This is largely based
  185.  * on Linus's ALPHA routines, which are pretty portable BTW.
  186.  */
  187. static __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
  188. {
  189. unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
  190. unsigned long result = offset & ~31UL;
  191. unsigned long tmp;
  192. if (offset >= size)
  193. return size;
  194. size -= result;
  195. offset &= 31UL;
  196. if (offset) {
  197. tmp = *(p++);
  198. tmp |= ~0UL >> (32-offset);
  199. if (size < 32)
  200. goto found_first;
  201. if (~tmp)
  202. goto found_middle;
  203. size -= 32;
  204. result += 32;
  205. }
  206. while (size & ~31UL) {
  207. if (~(tmp = *(p++)))
  208. goto found_middle;
  209. result += 32;
  210. size -= 32;
  211. }
  212. if (!size)
  213. return result;
  214. tmp = *p;
  215. found_first:
  216. tmp |= ~0UL << size;
  217. if (tmp == ~0UL)        /* Are any bits zero? */
  218. return result + size; /* Nope. */
  219. found_middle:
  220. return result + ffz(tmp);
  221. }
  222. /*
  223.  * Linus sez that gcc can optimize the following correctly, we'll see if this
  224.  * holds on the Sparc as it does for the ALPHA.
  225.  */
  226. #define find_first_zero_bit(addr, size) 
  227.         find_next_zero_bit((addr), (size), 0)
  228. static __inline__ int test_le_bit(int nr, __const__ void * addr)
  229. {
  230. __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
  231. return (ADDR[nr >> 3] >> (nr & 7)) & 1;
  232. }
  233. /*
  234.  * non-atomic versions
  235.  */
  236. static __inline__ void __set_le_bit(int nr, void *addr)
  237. {
  238. unsigned char *ADDR = (unsigned char *)addr;
  239. ADDR += nr >> 3;
  240. *ADDR |= 1 << (nr & 0x07);
  241. }
  242. static __inline__ void __clear_le_bit(int nr, void *addr)
  243. {
  244. unsigned char *ADDR = (unsigned char *)addr;
  245. ADDR += nr >> 3;
  246. *ADDR &= ~(1 << (nr & 0x07));
  247. }
  248. static __inline__ int __test_and_set_le_bit(int nr, void *addr)
  249. {
  250. int mask, retval;
  251. unsigned char *ADDR = (unsigned char *)addr;
  252. ADDR += nr >> 3;
  253. mask = 1 << (nr & 0x07);
  254. retval = (mask & *ADDR) != 0;
  255. *ADDR |= mask;
  256. return retval;
  257. }
  258. static __inline__ int __test_and_clear_le_bit(int nr, void *addr)
  259. {
  260. int mask, retval;
  261. unsigned char *ADDR = (unsigned char *)addr;
  262. ADDR += nr >> 3;
  263. mask = 1 << (nr & 0x07);
  264. retval = (mask & *ADDR) != 0;
  265. *ADDR &= ~mask;
  266. return retval;
  267. }
  268. static __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset)
  269. {
  270. unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
  271. unsigned long result = offset & ~31UL;
  272. unsigned long tmp;
  273. if (offset >= size)
  274. return size;
  275. size -= result;
  276. offset &= 31UL;
  277. if(offset) {
  278. tmp = *(p++);
  279. tmp |= __swab32(~0UL >> (32-offset));
  280. if(size < 32)
  281. goto found_first;
  282. if(~tmp)
  283. goto found_middle;
  284. size -= 32;
  285. result += 32;
  286. }
  287. while(size & ~31UL) {
  288. if(~(tmp = *(p++)))
  289. goto found_middle;
  290. result += 32;
  291. size -= 32;
  292. }
  293. if(!size)
  294. return result;
  295. tmp = *p;
  296. found_first:
  297. tmp = __swab32(tmp) | (~0UL << size);
  298. if (tmp == ~0UL)        /* Are any bits zero? */
  299. return result + size; /* Nope. */
  300. return result + ffz(tmp);
  301. found_middle:
  302. return result + ffz(__swab32(tmp));
  303. }
  304. #define find_first_zero_le_bit(addr, size) 
  305.         find_next_zero_le_bit((addr), (size), 0)
  306. #define ext2_set_bit __test_and_set_le_bit
  307. #define ext2_clear_bit __test_and_clear_le_bit
  308. #define ext2_test_bit test_le_bit
  309. #define ext2_find_first_zero_bit find_first_zero_le_bit
  310. #define ext2_find_next_zero_bit find_next_zero_le_bit
  311. /* Bitmap functions for the minix filesystem.  */
  312. #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
  313. #define minix_set_bit(nr,addr) set_bit(nr,addr)
  314. #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
  315. #define minix_test_bit(nr,addr) test_bit(nr,addr)
  316. #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
  317. #endif /* __KERNEL__ */
  318. #endif /* defined(_SPARC_BITOPS_H) */