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

嵌入式Linux

开发平台:

Unix_Linux

  1. #ifndef _M68K_BITOPS_H
  2. #define _M68K_BITOPS_H
  3. /*
  4.  * Copyright 1992, Linus Torvalds.
  5.  *
  6.  * This file is subject to the terms and conditions of the GNU General Public
  7.  * License.  See the file COPYING in the main directory of this archive
  8.  * for more details.
  9.  */
  10. /*
  11.  * Require 68020 or better.
  12.  *
  13.  * They use the standard big-endian m680x0 bit ordering.
  14.  */
  15. #define test_and_set_bit(nr,vaddr) 
  16.   (__builtin_constant_p(nr) ? 
  17.    __constant_test_and_set_bit(nr, vaddr) : 
  18.    __generic_test_and_set_bit(nr, vaddr))
  19. extern __inline__ int __constant_test_and_set_bit(int nr,volatile void * vaddr)
  20. {
  21. char retval;
  22. __asm__ __volatile__ ("bset %2,%1; sne %0"
  23.      : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
  24.      : "di" (nr & 7));
  25. return retval;
  26. }
  27. extern __inline__ int __generic_test_and_set_bit(int nr,volatile void * vaddr)
  28. {
  29. char retval;
  30. __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
  31.      : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
  32. return retval;
  33. }
  34. #define set_bit(nr,vaddr) 
  35.   (__builtin_constant_p(nr) ? 
  36.    __constant_set_bit(nr, vaddr) : 
  37.    __generic_set_bit(nr, vaddr))
  38. #define __set_bit(nr,vaddr) set_bit(nr,vaddr) 
  39. extern __inline__ void __constant_set_bit(int nr, volatile void * vaddr)
  40. {
  41. __asm__ __volatile__ ("bset %1,%0"
  42.      : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
  43. }
  44. extern __inline__ void __generic_set_bit(int nr, volatile void * vaddr)
  45. {
  46. __asm__ __volatile__ ("bfset %1@{%0:#1}"
  47.      : : "d" (nr^31), "a" (vaddr) : "memory");
  48. }
  49. #define test_and_clear_bit(nr,vaddr) 
  50.   (__builtin_constant_p(nr) ? 
  51.    __constant_test_and_clear_bit(nr, vaddr) : 
  52.    __generic_test_and_clear_bit(nr, vaddr))
  53. #define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr)
  54. extern __inline__ int __constant_test_and_clear_bit(int nr, volatile void * vaddr)
  55. {
  56. char retval;
  57. __asm__ __volatile__ ("bclr %2,%1; sne %0"
  58.      : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
  59.      : "di" (nr & 7));
  60. return retval;
  61. }
  62. extern __inline__ int __generic_test_and_clear_bit(int nr, volatile void * vaddr)
  63. {
  64. char retval;
  65. __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
  66.      : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
  67. return retval;
  68. }
  69. /*
  70.  * clear_bit() doesn't provide any barrier for the compiler.
  71.  */
  72. #define smp_mb__before_clear_bit() barrier()
  73. #define smp_mb__after_clear_bit() barrier()
  74. #define clear_bit(nr,vaddr) 
  75.   (__builtin_constant_p(nr) ? 
  76.    __constant_clear_bit(nr, vaddr) : 
  77.    __generic_clear_bit(nr, vaddr))
  78. extern __inline__ void __constant_clear_bit(int nr, volatile void * vaddr)
  79. {
  80. __asm__ __volatile__ ("bclr %1,%0"
  81.      : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
  82. }
  83. extern __inline__ void __generic_clear_bit(int nr, volatile void * vaddr)
  84. {
  85. __asm__ __volatile__ ("bfclr %1@{%0:#1}"
  86.      : : "d" (nr^31), "a" (vaddr) : "memory");
  87. }
  88. #define test_and_change_bit(nr,vaddr) 
  89.   (__builtin_constant_p(nr) ? 
  90.    __constant_test_and_change_bit(nr, vaddr) : 
  91.    __generic_test_and_change_bit(nr, vaddr))
  92. #define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr)
  93. #define __change_bit(nr,vaddr) change_bit(nr,vaddr)
  94. extern __inline__ int __constant_test_and_change_bit(int nr, volatile void * vaddr)
  95. {
  96. char retval;
  97. __asm__ __volatile__ ("bchg %2,%1; sne %0"
  98.      : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
  99.      : "di" (nr & 7));
  100. return retval;
  101. }
  102. extern __inline__ int __generic_test_and_change_bit(int nr, volatile void * vaddr)
  103. {
  104. char retval;
  105. __asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0"
  106.      : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
  107. return retval;
  108. }
  109. #define change_bit(nr,vaddr) 
  110.   (__builtin_constant_p(nr) ? 
  111.    __constant_change_bit(nr, vaddr) : 
  112.    __generic_change_bit(nr, vaddr))
  113. extern __inline__ void __constant_change_bit(int nr, volatile void * vaddr)
  114. {
  115. __asm__ __volatile__ ("bchg %1,%0"
  116.      : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
  117. }
  118. extern __inline__ void __generic_change_bit(int nr, volatile void * vaddr)
  119. {
  120. __asm__ __volatile__ ("bfchg %1@{%0:#1}"
  121.      : : "d" (nr^31), "a" (vaddr) : "memory");
  122. }
  123. extern __inline__ int test_bit(int nr, const volatile void * vaddr)
  124. {
  125. return ((1UL << (nr & 31)) & (((const volatile unsigned int *) vaddr)[nr >> 5])) != 0;
  126. }
  127. extern __inline__ int find_first_zero_bit(void * vaddr, unsigned size)
  128. {
  129. unsigned long *p = vaddr, *addr = vaddr;
  130. unsigned long allones = ~0UL;
  131. int res;
  132. unsigned long num;
  133. if (!size)
  134. return 0;
  135. size = (size >> 5) + ((size & 31) > 0);
  136. while (*p++ == allones)
  137. {
  138. if (--size == 0)
  139. return (p - addr) << 5;
  140. }
  141. num = ~*--p;
  142. __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
  143.       : "=d" (res) : "d" (num & -num));
  144. return ((p - addr) << 5) + (res ^ 31);
  145. }
  146. extern __inline__ int find_next_zero_bit (void *vaddr, int size,
  147.       int offset)
  148. {
  149. unsigned long *addr = vaddr;
  150. unsigned long *p = addr + (offset >> 5);
  151. int set = 0, bit = offset & 31UL, res;
  152. if (offset >= size)
  153. return size;
  154. if (bit) {
  155. unsigned long num = ~*p & (~0UL << bit);
  156. /* Look for zero in first longword */
  157. __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
  158.       : "=d" (res) : "d" (num & -num));
  159. if (res < 32)
  160. return (offset & ~31UL) + (res ^ 31);
  161.                 set = 32 - bit;
  162. p++;
  163. }
  164. /* No zero yet, search remaining full bytes for a zero */
  165. res = find_first_zero_bit (p, size - 32 * (p - addr));
  166. return (offset + set + res);
  167. }
  168. /*
  169.  * ffz = Find First Zero in word. Undefined if no zero exists,
  170.  * so code should check against ~0UL first..
  171.  */
  172. extern __inline__ unsigned long ffz(unsigned long word)
  173. {
  174. int res;
  175. __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
  176.       : "=d" (res) : "d" (~word & -~word));
  177. return res ^ 31;
  178. }
  179. #ifdef __KERNEL__
  180. /*
  181.  * ffs: find first bit set. This is defined the same way as
  182.  * the libc and compiler builtin ffs routines, therefore
  183.  * differs in spirit from the above ffz (man ffs).
  184.  */
  185. extern __inline__ int ffs(int x)
  186. {
  187. int cnt;
  188. __asm__ __volatile__("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x));
  189. return 32 - cnt;
  190. }
  191. /*
  192.  * hweightN: returns the hamming weight (i.e. the number
  193.  * of bits set) of a N-bit word
  194.  */
  195. #define hweight32(x) generic_hweight32(x)
  196. #define hweight16(x) generic_hweight16(x)
  197. #define hweight8(x) generic_hweight8(x)
  198. /* Bitmap functions for the minix filesystem */
  199. extern __inline__ int
  200. minix_find_first_zero_bit (const void *vaddr, unsigned size)
  201. {
  202. const unsigned short *p = vaddr, *addr = vaddr;
  203. int res;
  204. unsigned short num;
  205. if (!size)
  206. return 0;
  207. size = (size >> 4) + ((size & 15) > 0);
  208. while (*p++ == 0xffff)
  209. {
  210. if (--size == 0)
  211. return (p - addr) << 4;
  212. }
  213. num = ~*--p;
  214. __asm__ __volatile__ ("bfffo %1{#16,#16},%0"
  215.       : "=d" (res) : "d" (num & -num));
  216. return ((p - addr) << 4) + (res ^ 31);
  217. }
  218. extern __inline__ int
  219. minix_test_and_set_bit (int nr, volatile void *vaddr)
  220. {
  221. char retval;
  222. __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
  223.      : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *)vaddr) : "memory");
  224. return retval;
  225. }
  226. #define minix_set_bit(nr,addr) ((void)minix_test_and_set_bit(nr,addr))
  227. extern __inline__ int
  228. minix_test_and_clear_bit (int nr, volatile void *vaddr)
  229. {
  230. char retval;
  231. __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
  232.      : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *) vaddr) : "memory");
  233. return retval;
  234. }
  235. extern __inline__ int
  236. minix_test_bit (int nr, const volatile void *vaddr)
  237. {
  238. return ((1U << (nr & 15)) & (((const volatile unsigned short *) vaddr)[nr >> 4])) != 0;
  239. }
  240. /* Bitmap functions for the ext2 filesystem. */
  241. extern __inline__ int
  242. ext2_set_bit (int nr, volatile void *vaddr)
  243. {
  244. char retval;
  245. __asm__ __volatile__ ("bfset %2{%1,#1}; sne %0"
  246.      : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory");
  247. return retval;
  248. }
  249. extern __inline__ int
  250. ext2_clear_bit (int nr, volatile void *vaddr)
  251. {
  252. char retval;
  253. __asm__ __volatile__ ("bfclr %2{%1,#1}; sne %0"
  254.      : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory");
  255. return retval;
  256. }
  257. extern __inline__ int
  258. ext2_test_bit (int nr, const volatile void *vaddr)
  259. {
  260. return ((1U << (nr & 7)) & (((const volatile unsigned char *) vaddr)[nr >> 3])) != 0;
  261. }
  262. extern __inline__ int
  263. ext2_find_first_zero_bit (const void *vaddr, unsigned size)
  264. {
  265. const unsigned long *p = vaddr, *addr = vaddr;
  266. int res;
  267. if (!size)
  268. return 0;
  269. size = (size >> 5) + ((size & 31) > 0);
  270. while (*p++ == ~0UL)
  271. {
  272. if (--size == 0)
  273. return (p - addr) << 5;
  274. }
  275. --p;
  276. for (res = 0; res < 32; res++)
  277. if (!ext2_test_bit (res, p))
  278. break;
  279. return (p - addr) * 32 + res;
  280. }
  281. extern __inline__ int
  282. ext2_find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset)
  283. {
  284. const unsigned long *addr = vaddr;
  285. const unsigned long *p = addr + (offset >> 5);
  286. int bit = offset & 31UL, res;
  287. if (offset >= size)
  288. return size;
  289. if (bit) {
  290. /* Look for zero in first longword */
  291. for (res = bit; res < 32; res++)
  292. if (!ext2_test_bit (res, p))
  293. return (p - addr) * 32 + res;
  294. p++;
  295. }
  296. /* No zero yet, search remaining full bytes for a zero */
  297. res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
  298. return (p - addr) * 32 + res;
  299. }
  300. #endif /* __KERNEL__ */
  301. #endif /* _M68K_BITOPS_H */