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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef _ALPHA_BITOPS_H
  2. #define _ALPHA_BITOPS_H
  3. #include <linux/config.h>
  4. #include <linux/kernel.h>
  5. /*
  6.  * Copyright 1994, Linus Torvalds.
  7.  */
  8. /*
  9.  * These have to be done with inline assembly: that way the bit-setting
  10.  * is guaranteed to be atomic. All bit operations return 0 if the bit
  11.  * was cleared before the operation and != 0 if it was not.
  12.  *
  13.  * To get proper branch prediction for the main line, we must branch
  14.  * forward to code at the end of this object's .text section, then
  15.  * branch back to restart the operation.
  16.  *
  17.  * bit 0 is the LSB of addr; bit 64 is the LSB of (addr+1).
  18.  */
  19. static inline void
  20. set_bit(unsigned long nr, volatile void * addr)
  21. {
  22. unsigned long temp;
  23. int *m = ((int *) addr) + (nr >> 5);
  24. __asm__ __volatile__(
  25. "1: ldl_l %0,%3n"
  26. " bis %0,%2,%0n"
  27. " stl_c %0,%1n"
  28. " beq %0,2fn"
  29. ".subsection 2n"
  30. "2: br 1bn"
  31. ".previous"
  32. :"=&r" (temp), "=m" (*m)
  33. :"Ir" (1UL << (nr & 31)), "m" (*m));
  34. }
  35. /*
  36.  * WARNING: non atomic version.
  37.  */
  38. static inline void
  39. __set_bit(unsigned long nr, volatile void * addr)
  40. {
  41. int *m = ((int *) addr) + (nr >> 5);
  42. *m |= 1 << (nr & 31);
  43. }
  44. #define smp_mb__before_clear_bit() smp_mb()
  45. #define smp_mb__after_clear_bit() smp_mb()
  46. static inline void
  47. clear_bit(unsigned long nr, volatile void * addr)
  48. {
  49. unsigned long temp;
  50. int *m = ((int *) addr) + (nr >> 5);
  51. __asm__ __volatile__(
  52. "1: ldl_l %0,%3n"
  53. " and %0,%2,%0n"
  54. " stl_c %0,%1n"
  55. " beq %0,2fn"
  56. ".subsection 2n"
  57. "2: br 1bn"
  58. ".previous"
  59. :"=&r" (temp), "=m" (*m)
  60. :"Ir" (~(1UL << (nr & 31))), "m" (*m));
  61. }
  62. /*
  63.  * WARNING: non atomic version.
  64.  */
  65. static __inline__ void
  66. __change_bit(unsigned long nr, volatile void * addr)
  67. {
  68. int *m = ((int *) addr) + (nr >> 5);
  69. *m ^= 1 << (nr & 31);
  70. }
  71. static inline void
  72. change_bit(unsigned long nr, volatile void * addr)
  73. {
  74. unsigned long temp;
  75. int *m = ((int *) addr) + (nr >> 5);
  76. __asm__ __volatile__(
  77. "1: ldl_l %0,%3n"
  78. " xor %0,%2,%0n"
  79. " stl_c %0,%1n"
  80. " beq %0,2fn"
  81. ".subsection 2n"
  82. "2: br 1bn"
  83. ".previous"
  84. :"=&r" (temp), "=m" (*m)
  85. :"Ir" (1UL << (nr & 31)), "m" (*m));
  86. }
  87. static inline int
  88. test_and_set_bit(unsigned long nr, volatile void *addr)
  89. {
  90. unsigned long oldbit;
  91. unsigned long temp;
  92. int *m = ((int *) addr) + (nr >> 5);
  93. __asm__ __volatile__(
  94. "1: ldl_l %0,%4n"
  95. " and %0,%3,%2n"
  96. " bne %2,2fn"
  97. " xor %0,%3,%0n"
  98. " stl_c %0,%1n"
  99. " beq %0,3fn"
  100. "2:n"
  101. #ifdef CONFIG_SMP
  102. " mbn"
  103. #endif
  104. ".subsection 2n"
  105. "3: br 1bn"
  106. ".previous"
  107. :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
  108. :"Ir" (1UL << (nr & 31)), "m" (*m) : "memory");
  109. return oldbit != 0;
  110. }
  111. /*
  112.  * WARNING: non atomic version.
  113.  */
  114. static inline int
  115. __test_and_set_bit(unsigned long nr, volatile void * addr)
  116. {
  117. unsigned long mask = 1 << (nr & 0x1f);
  118. int *m = ((int *) addr) + (nr >> 5);
  119. int old = *m;
  120. *m = old | mask;
  121. return (old & mask) != 0;
  122. }
  123. static inline int
  124. test_and_clear_bit(unsigned long nr, volatile void * addr)
  125. {
  126. unsigned long oldbit;
  127. unsigned long temp;
  128. int *m = ((int *) addr) + (nr >> 5);
  129. __asm__ __volatile__(
  130. "1: ldl_l %0,%4n"
  131. " and %0,%3,%2n"
  132. " beq %2,2fn"
  133. " xor %0,%3,%0n"
  134. " stl_c %0,%1n"
  135. " beq %0,3fn"
  136. "2:n"
  137. #ifdef CONFIG_SMP
  138. " mbn"
  139. #endif
  140. ".subsection 2n"
  141. "3: br 1bn"
  142. ".previous"
  143. :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
  144. :"Ir" (1UL << (nr & 31)), "m" (*m) : "memory");
  145. return oldbit != 0;
  146. }
  147. /*
  148.  * WARNING: non atomic version.
  149.  */
  150. static inline int
  151. __test_and_clear_bit(unsigned long nr, volatile void * addr)
  152. {
  153. unsigned long mask = 1 << (nr & 0x1f);
  154. int *m = ((int *) addr) + (nr >> 5);
  155. int old = *m;
  156. *m = old & ~mask;
  157. return (old & mask) != 0;
  158. }
  159. /*
  160.  * WARNING: non atomic version.
  161.  */
  162. static __inline__ int
  163. __test_and_change_bit(unsigned long nr, volatile void * addr)
  164. {
  165. unsigned long mask = 1 << (nr & 0x1f);
  166. int *m = ((int *) addr) + (nr >> 5);
  167. int old = *m;
  168. *m = old ^ mask;
  169. return (old & mask) != 0;
  170. }
  171. static inline int
  172. test_and_change_bit(unsigned long nr, volatile void * addr)
  173. {
  174. unsigned long oldbit;
  175. unsigned long temp;
  176. int *m = ((int *) addr) + (nr >> 5);
  177. __asm__ __volatile__(
  178. "1: ldl_l %0,%4n"
  179. " and %0,%3,%2n"
  180. " xor %0,%3,%0n"
  181. " stl_c %0,%1n"
  182. " beq %0,3fn"
  183. #ifdef CONFIG_SMP
  184. " mbn"
  185. #endif
  186. ".subsection 2n"
  187. "3: br 1bn"
  188. ".previous"
  189. :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
  190. :"Ir" (1UL << (nr & 31)), "m" (*m) : "memory");
  191. return oldbit != 0;
  192. }
  193. static inline int
  194. test_bit(int nr, volatile void * addr)
  195. {
  196. return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL;
  197. }
  198. /*
  199.  * ffz = Find First Zero in word. Undefined if no zero exists,
  200.  * so code should check against ~0UL first..
  201.  *
  202.  * Do a binary search on the bits.  Due to the nature of large
  203.  * constants on the alpha, it is worthwhile to split the search.
  204.  */
  205. static inline unsigned long ffz_b(unsigned long x)
  206. {
  207. unsigned long sum = 0;
  208. x = ~x & -~x; /* set first 0 bit, clear others */
  209. if (x & 0xF0) sum += 4;
  210. if (x & 0xCC) sum += 2;
  211. if (x & 0xAA) sum += 1;
  212. return sum;
  213. }
  214. static inline unsigned long ffz(unsigned long word)
  215. {
  216. #if defined(__alpha_cix__) && defined(__alpha_fix__)
  217. /* Whee.  EV67 can calculate it directly.  */
  218. unsigned long result;
  219. __asm__("cttz %1,%0" : "=r"(result) : "r"(~word));
  220. return result;
  221. #else
  222. unsigned long bits, qofs, bofs;
  223. __asm__("cmpbge %1,%2,%0" : "=r"(bits) : "r"(word), "r"(~0UL));
  224. qofs = ffz_b(bits);
  225. __asm__("extbl %1,%2,%0" : "=r"(bits) : "r"(word), "r"(qofs));
  226. bofs = ffz_b(bits);
  227. return qofs*8 + bofs;
  228. #endif
  229. }
  230. #ifdef __KERNEL__
  231. /*
  232.  * ffs: find first bit set. This is defined the same way as
  233.  * the libc and compiler builtin ffs routines, therefore
  234.  * differs in spirit from the above ffz (man ffs).
  235.  */
  236. static inline int ffs(int word)
  237. {
  238. int result = ffz(~word);
  239. return word ? result+1 : 0;
  240. }
  241. /* Compute powers of two for the given integer.  */
  242. static inline int floor_log2(unsigned long word)
  243. {
  244. long bit;
  245. #if defined(__alpha_cix__) && defined(__alpha_fix__)
  246. __asm__("ctlz %1,%0" : "=r"(bit) : "r"(word));
  247. return 63 - bit;
  248. #else
  249. for (bit = -1; word ; bit++)
  250. word >>= 1;
  251. return bit;
  252. #endif
  253. }
  254. static inline int ceil_log2(unsigned int word)
  255. {
  256. long bit = floor_log2(word);
  257. return bit + (word > (1UL << bit));
  258. }
  259. /*
  260.  * hweightN: returns the hamming weight (i.e. the number
  261.  * of bits set) of a N-bit word
  262.  */
  263. #if defined(__alpha_cix__) && defined(__alpha_fix__)
  264. /* Whee.  EV67 can calculate it directly.  */
  265. static inline unsigned long hweight64(unsigned long w)
  266. {
  267. unsigned long result;
  268. __asm__("ctpop %1,%0" : "=r"(result) : "r"(w));
  269. return result;
  270. }
  271. #define hweight32(x) hweight64((x) & 0xfffffffful)
  272. #define hweight16(x) hweight64((x) & 0xfffful)
  273. #define hweight8(x)  hweight64((x) & 0xfful)
  274. #else
  275. #define hweight32(x) generic_hweight32(x)
  276. #define hweight16(x) generic_hweight16(x)
  277. #define hweight8(x)  generic_hweight8(x)
  278. #endif
  279. #endif /* __KERNEL__ */
  280. /*
  281.  * Find next zero bit in a bitmap reasonably efficiently..
  282.  */
  283. static inline unsigned long
  284. find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
  285. {
  286. unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
  287. unsigned long result = offset & ~63UL;
  288. unsigned long tmp;
  289. if (offset >= size)
  290. return size;
  291. size -= result;
  292. offset &= 63UL;
  293. if (offset) {
  294. tmp = *(p++);
  295. tmp |= ~0UL >> (64-offset);
  296. if (size < 64)
  297. goto found_first;
  298. if (~tmp)
  299. goto found_middle;
  300. size -= 64;
  301. result += 64;
  302. }
  303. while (size & ~63UL) {
  304. if (~(tmp = *(p++)))
  305. goto found_middle;
  306. result += 64;
  307. size -= 64;
  308. }
  309. if (!size)
  310. return result;
  311. tmp = *p;
  312. found_first:
  313. tmp |= ~0UL << size;
  314. if (tmp == ~0UL)        /* Are any bits zero? */
  315. return result + size; /* Nope. */
  316. found_middle:
  317. return result + ffz(tmp);
  318. }
  319. /*
  320.  * The optimizer actually does good code for this case..
  321.  */
  322. #define find_first_zero_bit(addr, size) 
  323. find_next_zero_bit((addr), (size), 0)
  324. #ifdef __KERNEL__
  325. #define ext2_set_bit                 __test_and_set_bit
  326. #define ext2_clear_bit               __test_and_clear_bit
  327. #define ext2_test_bit                test_bit
  328. #define ext2_find_first_zero_bit     find_first_zero_bit
  329. #define ext2_find_next_zero_bit      find_next_zero_bit
  330. /* Bitmap functions for the minix filesystem.  */
  331. #define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
  332. #define minix_set_bit(nr,addr) __set_bit(nr,addr)
  333. #define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
  334. #define minix_test_bit(nr,addr) test_bit(nr,addr)
  335. #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
  336. #endif /* __KERNEL__ */
  337. #endif /* _ALPHA_BITOPS_H */