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

嵌入式Linux

开发平台:

Unix_Linux

  1. #ifndef __ASM_SH_BITOPS_H
  2. #define __ASM_SH_BITOPS_H
  3. #ifdef __KERNEL__
  4. #include <asm/system.h>
  5. /* For __swab32 */
  6. #include <asm/byteorder.h>
  7. static __inline__ void set_bit(int nr, volatile void * addr)
  8. {
  9. int mask;
  10. volatile unsigned int *a = addr;
  11. unsigned long flags;
  12. a += nr >> 5;
  13. mask = 1 << (nr & 0x1f);
  14. save_and_cli(flags);
  15. *a |= mask;
  16. restore_flags(flags);
  17. }
  18. static __inline__ void __set_bit(int nr, volatile void * addr)
  19. {
  20. int mask;
  21. volatile unsigned int *a = addr;
  22. a += nr >> 5;
  23. mask = 1 << (nr & 0x1f);
  24. *a |= mask;
  25. }
  26. /*
  27.  * clear_bit() doesn't provide any barrier for the compiler.
  28.  */
  29. #define smp_mb__before_clear_bit() barrier()
  30. #define smp_mb__after_clear_bit() barrier()
  31. static __inline__ void clear_bit(int nr, volatile void * addr)
  32. {
  33. int mask;
  34. volatile unsigned int *a = addr;
  35. unsigned long flags;
  36. a += nr >> 5;
  37. mask = 1 << (nr & 0x1f);
  38. save_and_cli(flags);
  39. *a &= ~mask;
  40. restore_flags(flags);
  41. }
  42. static __inline__ void __clear_bit(int nr, volatile void * addr)
  43. {
  44. int mask;
  45. volatile unsigned int *a = addr;
  46. a += nr >> 5;
  47. mask = 1 << (nr & 0x1f);
  48. *a &= ~mask;
  49. }
  50. static __inline__ void change_bit(int nr, volatile void * addr)
  51. {
  52. int mask;
  53. volatile unsigned int *a = addr;
  54. unsigned long flags;
  55. a += nr >> 5;
  56. mask = 1 << (nr & 0x1f);
  57. save_and_cli(flags);
  58. *a ^= mask;
  59. restore_flags(flags);
  60. }
  61. static __inline__ void __change_bit(int nr, volatile void * addr)
  62. {
  63. int mask;
  64. volatile unsigned int *a = addr;
  65. a += nr >> 5;
  66. mask = 1 << (nr & 0x1f);
  67. *a ^= mask;
  68. }
  69. static __inline__ int test_and_set_bit(int nr, volatile void * addr)
  70. {
  71. int mask, retval;
  72. volatile unsigned int *a = addr;
  73. unsigned long flags;
  74. a += nr >> 5;
  75. mask = 1 << (nr & 0x1f);
  76. save_and_cli(flags);
  77. retval = (mask & *a) != 0;
  78. *a |= mask;
  79. restore_flags(flags);
  80. return retval;
  81. }
  82. static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
  83. {
  84. int mask, retval;
  85. volatile unsigned int *a = addr;
  86. a += nr >> 5;
  87. mask = 1 << (nr & 0x1f);
  88. retval = (mask & *a) != 0;
  89. *a |= mask;
  90. return retval;
  91. }
  92. static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
  93. {
  94. int mask, retval;
  95. volatile unsigned int *a = addr;
  96. unsigned long flags;
  97. a += nr >> 5;
  98. mask = 1 << (nr & 0x1f);
  99. save_and_cli(flags);
  100. retval = (mask & *a) != 0;
  101. *a &= ~mask;
  102. restore_flags(flags);
  103. return retval;
  104. }
  105. static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
  106. {
  107. int mask, retval;
  108. volatile unsigned int *a = addr;
  109. a += nr >> 5;
  110. mask = 1 << (nr & 0x1f);
  111. retval = (mask & *a) != 0;
  112. *a &= ~mask;
  113. return retval;
  114. }
  115. static __inline__ int test_and_change_bit(int nr, volatile void * addr)
  116. {
  117. int mask, retval;
  118. volatile unsigned int *a = addr;
  119. unsigned long flags;
  120. a += nr >> 5;
  121. mask = 1 << (nr & 0x1f);
  122. save_and_cli(flags);
  123. retval = (mask & *a) != 0;
  124. *a ^= mask;
  125. restore_flags(flags);
  126. return retval;
  127. }
  128. static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
  129. {
  130. int mask, retval;
  131. volatile unsigned int *a = addr;
  132. a += nr >> 5;
  133. mask = 1 << (nr & 0x1f);
  134. retval = (mask & *a) != 0;
  135. *a ^= mask;
  136. return retval;
  137. }
  138. static __inline__ int test_bit(int nr, const volatile void *addr)
  139. {
  140. return 1UL & (((const volatile unsigned int *) addr)[nr >> 5] >> (nr & 31));
  141. }
  142. static __inline__ unsigned long ffz(unsigned long word)
  143. {
  144. unsigned long result;
  145. __asm__("1:nt"
  146. "shlr %1nt"
  147. "bt/s 1bnt"
  148. " add #1, %0"
  149. : "=r" (result), "=r" (word)
  150. : "0" (~0L), "1" (word)
  151. : "t");
  152. return result;
  153. }
  154. static __inline__ int find_next_zero_bit(void *addr, int size, int offset)
  155. {
  156. unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
  157. unsigned long result = offset & ~31UL;
  158. unsigned long tmp;
  159. if (offset >= size)
  160. return size;
  161. size -= result;
  162. offset &= 31UL;
  163. if (offset) {
  164. tmp = *(p++);
  165. tmp |= ~0UL >> (32-offset);
  166. if (size < 32)
  167. goto found_first;
  168. if (~tmp)
  169. goto found_middle;
  170. size -= 32;
  171. result += 32;
  172. }
  173. while (size & ~31UL) {
  174. if (~(tmp = *(p++)))
  175. goto found_middle;
  176. result += 32;
  177. size -= 32;
  178. }
  179. if (!size)
  180. return result;
  181. tmp = *p;
  182. found_first:
  183. tmp |= ~0UL << size;
  184. found_middle:
  185. return result + ffz(tmp);
  186. }
  187. #define find_first_zero_bit(addr, size) 
  188.         find_next_zero_bit((addr), (size), 0)
  189. /*
  190.  * ffs: find first bit set. This is defined the same way as
  191.  * the libc and compiler builtin ffs routines, therefore
  192.  * differs in spirit from the above ffz (man ffs).
  193.  */
  194. #define ffs(x) generic_ffs(x)
  195. /*
  196.  * hweightN: returns the hamming weight (i.e. the number
  197.  * of bits set) of a N-bit word
  198.  */
  199. #define hweight32(x) generic_hweight32(x)
  200. #define hweight16(x) generic_hweight16(x)
  201. #define hweight8(x) generic_hweight8(x)
  202. #ifdef __LITTLE_ENDIAN__
  203. #define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr))
  204. #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr))
  205. #define ext2_test_bit(nr, addr) test_bit((nr), (addr))
  206. #define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size))
  207. #define ext2_find_next_zero_bit(addr, size, offset) 
  208.                 find_next_zero_bit((addr), (size), (offset))
  209. #else
  210. static __inline__ int ext2_set_bit(int nr, volatile void * addr)
  211. {
  212. int mask, retval;
  213. unsigned long flags;
  214. volatile unsigned char *ADDR = (unsigned char *) addr;
  215. ADDR += nr >> 3;
  216. mask = 1 << (nr & 0x07);
  217. save_and_cli(flags);
  218. retval = (mask & *ADDR) != 0;
  219. *ADDR |= mask;
  220. restore_flags(flags);
  221. return retval;
  222. }
  223. static __inline__ int ext2_clear_bit(int nr, volatile void * addr)
  224. {
  225. int mask, retval;
  226. unsigned long flags;
  227. volatile unsigned char *ADDR = (unsigned char *) addr;
  228. ADDR += nr >> 3;
  229. mask = 1 << (nr & 0x07);
  230. save_and_cli(flags);
  231. retval = (mask & *ADDR) != 0;
  232. *ADDR &= ~mask;
  233. restore_flags(flags);
  234. return retval;
  235. }
  236. static __inline__ int ext2_test_bit(int nr, const volatile void * addr)
  237. {
  238. int mask;
  239. const volatile unsigned char *ADDR = (const unsigned char *) addr;
  240. ADDR += nr >> 3;
  241. mask = 1 << (nr & 0x07);
  242. return ((mask & *ADDR) != 0);
  243. }
  244. #define ext2_find_first_zero_bit(addr, size) 
  245.         ext2_find_next_zero_bit((addr), (size), 0)
  246. static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
  247. {
  248. unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
  249. unsigned long result = offset & ~31UL;
  250. unsigned long tmp;
  251. if (offset >= size)
  252. return size;
  253. size -= result;
  254. offset &= 31UL;
  255. if(offset) {
  256. /* We hold the little endian value in tmp, but then the
  257.  * shift is illegal. So we could keep a big endian value
  258.  * in tmp, like this:
  259.  *
  260.  * tmp = __swab32(*(p++));
  261.  * tmp |= ~0UL >> (32-offset);
  262.  *
  263.  * but this would decrease preformance, so we change the
  264.  * shift:
  265.  */
  266. tmp = *(p++);
  267. tmp |= __swab32(~0UL >> (32-offset));
  268. if(size < 32)
  269. goto found_first;
  270. if(~tmp)
  271. goto found_middle;
  272. size -= 32;
  273. result += 32;
  274. }
  275. while(size & ~31UL) {
  276. if(~(tmp = *(p++)))
  277. goto found_middle;
  278. result += 32;
  279. size -= 32;
  280. }
  281. if(!size)
  282. return result;
  283. tmp = *p;
  284. found_first:
  285. /* tmp is little endian, so we would have to swab the shift,
  286.  * see above. But then we have to swab tmp below for ffz, so
  287.  * we might as well do this here.
  288.  */
  289. return result + ffz(__swab32(tmp) | (~0UL << size));
  290. found_middle:
  291. return result + ffz(__swab32(tmp));
  292. }
  293. #endif
  294. /* Bitmap functions for the minix filesystem.  */
  295. #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
  296. #define minix_set_bit(nr,addr) set_bit(nr,addr)
  297. #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
  298. #define minix_test_bit(nr,addr) test_bit(nr,addr)
  299. #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
  300. #endif /* __KERNEL__ */
  301. #endif /* __ASM_SH_BITOPS_H */