bitops.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * include/asm-xtensa/bitops.h
  3. *
  4. * Atomic operations that C can't guarantee us.Useful for resource counting etc.
  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. * Copyright (C) 2001 - 2007 Tensilica Inc.
  11. */
  12. #ifndef _XTENSA_BITOPS_H
  13. #define _XTENSA_BITOPS_H
  14. #ifdef __KERNEL__
  15. #ifndef _LINUX_BITOPS_H
  16. #error only <linux/bitops.h> can be included directly
  17. #endif
  18. #include <asm/processor.h>
  19. #include <asm/byteorder.h>
  20. #include <asm/barrier.h>
  21. #include <asm-generic/bitops/non-atomic.h>
  22. #if XCHAL_HAVE_NSA
  23. static inline unsigned long __cntlz (unsigned long x)
  24. {
  25. int lz;
  26. asm ("nsau %0, %1" : "=r" (lz) : "r" (x));
  27. return lz;
  28. }
  29. /*
  30. * ffz: Find first zero in word. Undefined if no zero exists.
  31. * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  32. */
  33. static inline int ffz(unsigned long x)
  34. {
  35. return 31 - __cntlz(~x & -~x);
  36. }
  37. /*
  38. * __ffs: Find first bit set in word. Return 0 for bit 0
  39. */
  40. static inline unsigned long __ffs(unsigned long x)
  41. {
  42. return 31 - __cntlz(x & -x);
  43. }
  44. /*
  45. * ffs: Find first bit set in word. This is defined the same way as
  46. * the libc and compiler builtin ffs routines, therefore
  47. * differs in spirit from the above ffz (man ffs).
  48. */
  49. static inline int ffs(unsigned long x)
  50. {
  51. return 32 - __cntlz(x & -x);
  52. }
  53. /*
  54. * fls: Find last (most-significant) bit set in word.
  55. * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
  56. */
  57. static inline int fls (unsigned int x)
  58. {
  59. return 32 - __cntlz(x);
  60. }
  61. /**
  62. * __fls - find last (most-significant) set bit in a long word
  63. * @word: the word to search
  64. *
  65. * Undefined if no set bit exists, so code should check against 0 first.
  66. */
  67. static inline unsigned long __fls(unsigned long word)
  68. {
  69. return 31 - __cntlz(word);
  70. }
  71. #else
  72. /* Use the generic implementation if we don't have the nsa/nsau instructions. */
  73. # include <asm-generic/bitops/ffs.h>
  74. # include <asm-generic/bitops/__ffs.h>
  75. # include <asm-generic/bitops/ffz.h>
  76. # include <asm-generic/bitops/fls.h>
  77. # include <asm-generic/bitops/__fls.h>
  78. #endif
  79. #include <asm-generic/bitops/fls64.h>
  80. #if XCHAL_HAVE_S32C1I
  81. static inline void set_bit(unsigned int bit, volatile unsigned long *p)
  82. {
  83. unsigned long tmp, value;
  84. unsigned long mask = 1UL << (bit & 31);
  85. p += bit >> 5;
  86. __asm__ __volatile__(
  87. "1: l32i %1, %3, 0\n"
  88. " wsr %1, scompare1\n"
  89. " or %0, %1, %2\n"
  90. " s32c1i %0, %3, 0\n"
  91. " bne %0, %1, 1b\n"
  92. : "=&a" (tmp), "=&a" (value)
  93. : "a" (mask), "a" (p)
  94. : "memory");
  95. }
  96. static inline void clear_bit(unsigned int bit, volatile unsigned long *p)
  97. {
  98. unsigned long tmp, value;
  99. unsigned long mask = 1UL << (bit & 31);
  100. p += bit >> 5;
  101. __asm__ __volatile__(
  102. "1: l32i %1, %3, 0\n"
  103. " wsr %1, scompare1\n"
  104. " and %0, %1, %2\n"
  105. " s32c1i %0, %3, 0\n"
  106. " bne %0, %1, 1b\n"
  107. : "=&a" (tmp), "=&a" (value)
  108. : "a" (~mask), "a" (p)
  109. : "memory");
  110. }
  111. static inline void change_bit(unsigned int bit, volatile unsigned long *p)
  112. {
  113. unsigned long tmp, value;
  114. unsigned long mask = 1UL << (bit & 31);
  115. p += bit >> 5;
  116. __asm__ __volatile__(
  117. "1: l32i %1, %3, 0\n"
  118. " wsr %1, scompare1\n"
  119. " xor %0, %1, %2\n"
  120. " s32c1i %0, %3, 0\n"
  121. " bne %0, %1, 1b\n"
  122. : "=&a" (tmp), "=&a" (value)
  123. : "a" (mask), "a" (p)
  124. : "memory");
  125. }
  126. static inline int
  127. test_and_set_bit(unsigned int bit, volatile unsigned long *p)
  128. {
  129. unsigned long tmp, value;
  130. unsigned long mask = 1UL << (bit & 31);
  131. p += bit >> 5;
  132. __asm__ __volatile__(
  133. "1: l32i %1, %3, 0\n"
  134. " wsr %1, scompare1\n"
  135. " or %0, %1, %2\n"
  136. " s32c1i %0, %3, 0\n"
  137. " bne %0, %1, 1b\n"
  138. : "=&a" (tmp), "=&a" (value)
  139. : "a" (mask), "a" (p)
  140. : "memory");
  141. return tmp & mask;
  142. }
  143. static inline int
  144. test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
  145. {
  146. unsigned long tmp, value;
  147. unsigned long mask = 1UL << (bit & 31);
  148. p += bit >> 5;
  149. __asm__ __volatile__(
  150. "1: l32i %1, %3, 0\n"
  151. " wsr %1, scompare1\n"
  152. " and %0, %1, %2\n"
  153. " s32c1i %0, %3, 0\n"
  154. " bne %0, %1, 1b\n"
  155. : "=&a" (tmp), "=&a" (value)
  156. : "a" (~mask), "a" (p)
  157. : "memory");
  158. return tmp & mask;
  159. }
  160. static inline int
  161. test_and_change_bit(unsigned int bit, volatile unsigned long *p)
  162. {
  163. unsigned long tmp, value;
  164. unsigned long mask = 1UL << (bit & 31);
  165. p += bit >> 5;
  166. __asm__ __volatile__(
  167. "1: l32i %1, %3, 0\n"
  168. " wsr %1, scompare1\n"
  169. " xor %0, %1, %2\n"
  170. " s32c1i %0, %3, 0\n"
  171. " bne %0, %1, 1b\n"
  172. : "=&a" (tmp), "=&a" (value)
  173. : "a" (mask), "a" (p)
  174. : "memory");
  175. return tmp & mask;
  176. }
  177. #else
  178. #include <asm-generic/bitops/atomic.h>
  179. #endif /* XCHAL_HAVE_S32C1I */
  180. #include <asm-generic/bitops/find.h>
  181. #include <asm-generic/bitops/le.h>
  182. #include <asm-generic/bitops/ext2-atomic-setbit.h>
  183. #include <asm-generic/bitops/hweight.h>
  184. #include <asm-generic/bitops/lock.h>
  185. #include <asm-generic/bitops/sched.h>
  186. #endif /* __KERNEL__ */
  187. #endif /* _XTENSA_BITOPS_H */