bitops.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #ifndef _MICROBLAZE_BITOPS_H
  2. #define _MICROBLAZE_BITOPS_H
  3. /*
  4. * Copyright 1992, Linus Torvalds.
  5. */
  6. #include <asm/byteorder.h> /* swab32 */
  7. #include <asm/system.h> /* save_flags */
  8. #include <asm-generic/bitops/fls.h>
  9. #include <asm-generic/bitops/__fls.h>
  10. #include <asm-generic/bitops/fls64.h>
  11. #include <asm-generic/bitops/__ffs.h>
  12. #ifdef __KERNEL__
  13. /*
  14. * Function prototypes to keep gcc -Wall happy
  15. */
  16. /*
  17. * The __ functions are not atomic
  18. */
  19. extern void set_bit(int nr, volatile void * addr);
  20. extern void __set_bit(int nr, volatile void * addr);
  21. extern void clear_bit(int nr, volatile void * addr);
  22. #define __clear_bit(nr, addr) clear_bit(nr, addr)
  23. #define PLATFORM__CLEAR_BIT
  24. extern void change_bit(int nr, volatile void * addr);
  25. extern void __change_bit(int nr, volatile void * addr);
  26. extern int test_and_set_bit(int nr, volatile void * addr);
  27. extern int __test_and_set_bit(int nr, volatile void * addr);
  28. extern int test_and_clear_bit(int nr, volatile void * addr);
  29. extern int __test_and_clear_bit(int nr, volatile void * addr);
  30. extern int test_and_change_bit(int nr, volatile void * addr);
  31. extern int __test_and_change_bit(int nr, volatile void * addr);
  32. extern int __constant_test_bit(int nr, const volatile void * addr);
  33. extern int __test_bit(int nr, volatile void * addr);
  34. extern int find_first_zero_bit(void * addr, unsigned size);
  35. extern int find_next_zero_bit (void * addr, int size, int offset);
  36. /*
  37. * ffz = Find First Zero in word. Undefined if no zero exists,
  38. * so code should check against ~0UL first..
  39. */
  40. extern __inline__ unsigned long ffz(unsigned long word)
  41. {
  42. unsigned long result = 0;
  43. while(word & 1) {
  44. result++;
  45. word >>= 1;
  46. }
  47. return result;
  48. }
  49. extern __inline__ void set_bit(int nr, volatile void * addr)
  50. {
  51. int * a = (int *) addr;
  52. int mask;
  53. unsigned long flags;
  54. a += nr >> 5;
  55. mask = 1 << (nr & 0x1f);
  56. save_flags_cli(flags);
  57. *a |= mask;
  58. restore_flags(flags);
  59. }
  60. extern __inline__ void __set_bit(int nr, volatile void * addr)
  61. {
  62. int * a = (int *) addr;
  63. int mask;
  64. a += nr >> 5;
  65. mask = 1 << (nr & 0x1f);
  66. *a |= mask;
  67. }
  68. #define PLATFORM__SET_BIT
  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. extern __inline__ void clear_bit(int nr, volatile void * addr)
  75. {
  76. int * a = (int *) addr;
  77. int mask;
  78. unsigned long flags;
  79. a += nr >> 5;
  80. mask = 1 << (nr & 0x1f);
  81. save_flags_cli(flags);
  82. *a &= ~mask;
  83. restore_flags(flags);
  84. }
  85. extern __inline__ void change_bit(int nr, volatile void * addr)
  86. {
  87. int mask;
  88. unsigned long flags;
  89. unsigned long *ADDR = (unsigned long *) addr;
  90. ADDR += nr >> 5;
  91. mask = 1 << (nr & 31);
  92. save_flags_cli(flags);
  93. *ADDR ^= mask;
  94. restore_flags(flags);
  95. }
  96. extern __inline__ void __change_bit(int nr, volatile void * addr)
  97. {
  98. int mask;
  99. unsigned long *ADDR = (unsigned long *) addr;
  100. ADDR += nr >> 5;
  101. mask = 1 << (nr & 31);
  102. *ADDR ^= mask;
  103. }
  104. extern __inline__ int test_and_set_bit(int nr, volatile void * addr)
  105. {
  106. int mask, retval;
  107. volatile unsigned int *a = (volatile unsigned int *) addr;
  108. unsigned long flags;
  109. a += nr >> 5;
  110. mask = 1 << (nr & 0x1f);
  111. save_flags_cli(flags);
  112. retval = (mask & *a) != 0;
  113. *a |= mask;
  114. restore_flags(flags);
  115. return retval;
  116. }
  117. extern __inline__ int __test_and_set_bit(int nr, volatile void * addr)
  118. {
  119. int mask, retval;
  120. volatile unsigned int *a = (volatile unsigned int *) addr;
  121. a += nr >> 5;
  122. mask = 1 << (nr & 0x1f);
  123. retval = (mask & *a) != 0;
  124. *a |= mask;
  125. return retval;
  126. }
  127. extern __inline__ int test_and_clear_bit(int nr, volatile void * addr)
  128. {
  129. int mask, retval;
  130. volatile unsigned int *a = (volatile unsigned int *) addr;
  131. unsigned long flags;
  132. a += nr >> 5;
  133. mask = 1 << (nr & 0x1f);
  134. save_flags_cli(flags);
  135. retval = (mask & *a) != 0;
  136. *a &= ~mask;
  137. restore_flags(flags);
  138. return retval;
  139. }
  140. extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
  141. {
  142. int mask, retval;
  143. volatile unsigned int *a = (volatile unsigned int *) addr;
  144. a += nr >> 5;
  145. mask = 1 << (nr & 0x1f);
  146. retval = (mask & *a) != 0;
  147. *a &= ~mask;
  148. return retval;
  149. }
  150. extern __inline__ int test_and_change_bit(int nr, volatile void * addr)
  151. {
  152. int mask, retval;
  153. volatile unsigned int *a = (volatile unsigned int *) addr;
  154. unsigned long flags;
  155. a += nr >> 5;
  156. mask = 1 << (nr & 0x1f);
  157. save_flags_cli(flags);
  158. retval = (mask & *a) != 0;
  159. *a ^= mask;
  160. restore_flags(flags);
  161. return retval;
  162. }
  163. extern __inline__ int __test_and_change_bit(int nr, volatile void * addr)
  164. {
  165. int mask, retval;
  166. volatile unsigned int *a = (volatile unsigned int *) addr;
  167. a += nr >> 5;
  168. mask = 1 << (nr & 0x1f);
  169. retval = (mask & *a) != 0;
  170. *a ^= mask;
  171. return retval;
  172. }
  173. /*
  174. * This routine doesn't need to be atomic.
  175. */
  176. extern __inline__ int __constant_test_bit(int nr, const volatile void * addr)
  177. {
  178. return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
  179. }
  180. extern __inline__ int __test_bit(int nr, volatile void * addr)
  181. {
  182. int * a = (int *) addr;
  183. int mask;
  184. a += nr >> 5;
  185. mask = 1 << (nr & 0x1f);
  186. return ((mask & *a) != 0);
  187. }
  188. #define test_bit(nr,addr) \
  189. (__builtin_constant_p(nr) ? \
  190. __constant_test_bit((nr),(addr)) : \
  191. __test_bit((nr),(addr)))
  192. #define find_first_zero_bit(addr, size) \
  193. find_next_zero_bit((addr), (size), 0)
  194. extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
  195. {
  196. unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
  197. unsigned long result = offset & ~31UL;
  198. unsigned long tmp;
  199. if (offset >= size)
  200. return size;
  201. size -= result;
  202. offset &= 31UL;
  203. if (offset) {
  204. tmp = *(p++);
  205. tmp |= ~0UL >> (32-offset);
  206. if (size < 32)
  207. goto found_first;
  208. if (~tmp)
  209. goto found_middle;
  210. size -= 32;
  211. result += 32;
  212. }
  213. while (size & ~31UL) {
  214. if (~(tmp = *(p++)))
  215. goto found_middle;
  216. result += 32;
  217. size -= 32;
  218. }
  219. if (!size)
  220. return result;
  221. tmp = *p;
  222. found_first:
  223. tmp |= ~0UL >> size;
  224. found_middle:
  225. return result + ffz(tmp);
  226. }
  227. /*
  228. * hweightN: returns the hamming weight (i.e. the number
  229. * of bits set) of a N-bit word
  230. */
  231. #define hweight32(x) generic_hweight32(x)
  232. #define hweight16(x) generic_hweight16(x)
  233. #define hweight8(x) generic_hweight8(x)
  234. extern __inline__ int ext2_set_bit(int nr, volatile void * addr)
  235. {
  236. int mask, retval;
  237. unsigned long flags;
  238. volatile unsigned char *ADDR = (unsigned char *) addr;
  239. ADDR += nr >> 3;
  240. mask = 1 << (nr & 0x07);
  241. save_flags_cli(flags);
  242. retval = (mask & *ADDR) != 0;
  243. *ADDR |= mask;
  244. restore_flags(flags);
  245. return retval;
  246. }
  247. extern __inline__ int ext2_clear_bit(int nr, volatile void * addr)
  248. {
  249. int mask, retval;
  250. unsigned long flags;
  251. volatile unsigned char *ADDR = (unsigned char *) addr;
  252. ADDR += nr >> 3;
  253. mask = 1 << (nr & 0x07);
  254. save_flags_cli(flags);
  255. retval = (mask & *ADDR) != 0;
  256. *ADDR &= ~mask;
  257. restore_flags(flags);
  258. return retval;
  259. }
  260. extern __inline__ int ext2_test_bit(int nr, const volatile void * addr)
  261. {
  262. int mask;
  263. const volatile unsigned char *ADDR = (const unsigned char *) addr;
  264. ADDR += nr >> 3;
  265. mask = 1 << (nr & 0x07);
  266. return ((mask & *ADDR) != 0);
  267. }
  268. #define ext2_find_first_zero_bit(addr, size) \
  269. ext2_find_next_zero_bit((addr), (size), 0)
  270. static inline unsigned long ext2_find_next_zero_bit(void *addr,
  271. unsigned long size, unsigned long offset)
  272. {
  273. unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
  274. unsigned long result = offset & ~31UL;
  275. unsigned long tmp;
  276. if (offset >= size)
  277. return size;
  278. size -= result;
  279. offset &= 31UL;
  280. if(offset) {
  281. /* We hold the little endian value in tmp, but then the
  282. * shift is illegal. So we could keep a big endian value
  283. * in tmp, like this:
  284. *
  285. * tmp = __swab32(*(p++));
  286. * tmp |= ~0UL >> (32-offset);
  287. *
  288. * but this would decrease preformance, so we change the
  289. * shift:
  290. */
  291. tmp = *(p++);
  292. tmp |= __swab32(~0UL >> (32-offset));
  293. if(size < 32)
  294. goto found_first;
  295. if(~tmp)
  296. goto found_middle;
  297. size -= 32;
  298. result += 32;
  299. }
  300. while(size & ~31UL) {
  301. if(~(tmp = *(p++)))
  302. goto found_middle;
  303. result += 32;
  304. size -= 32;
  305. }
  306. if(!size)
  307. return result;
  308. tmp = *p;
  309. found_first:
  310. /* tmp is little endian, so we would have to swab the shift,
  311. * see above. But then we have to swab tmp below for ffz, so
  312. * we might as well do this here.
  313. */
  314. return result + ffz(__swab32(tmp) | (~0UL << size));
  315. found_middle:
  316. return result + ffz(__swab32(tmp));
  317. }
  318. /* Bitmap functions for the minix filesystem. */
  319. #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
  320. #define minix_set_bit(nr,addr) set_bit(nr,addr)
  321. #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
  322. #define minix_test_bit(nr,addr) test_bit(nr,addr)
  323. #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
  324. /**
  325. * hweightN - returns the hamming weight of a N-bit word
  326. * @x: the word to weigh
  327. *
  328. * The Hamming Weight of a number is the total number of bits set in it.
  329. */
  330. #define hweight32(x) generic_hweight32(x)
  331. #define hweight16(x) generic_hweight16(x)
  332. #define hweight8(x) generic_hweight8(x)
  333. #endif /* __KERNEL__ */
  334. #endif /* _MICROBLAZE_BITOPS_H */