bitops.h 5.3 KB

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