bitops.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  4. */
  5. #ifndef _ASM_BITOPS_H
  6. #define _ASM_BITOPS_H
  7. #ifndef _LINUX_BITOPS_H
  8. #error only <linux/bitops.h> can be included directly
  9. #endif
  10. #ifndef __ASSEMBLY__
  11. #include <linux/types.h>
  12. #include <linux/compiler.h>
  13. #ifdef CONFIG_ISA_ARCOMPACT
  14. /*
  15. * Count the number of zeros, starting from MSB
  16. * Helper for fls( ) friends
  17. * This is a pure count, so (1-32) or (0-31) doesn't apply
  18. * It could be 0 to 32, based on num of 0's in there
  19. * clz(0x8000_0000) = 0, clz(0xFFFF_FFFF)=0, clz(0) = 32, clz(1) = 31
  20. */
  21. static inline __attribute__ ((const)) int clz(unsigned int x)
  22. {
  23. unsigned int res;
  24. __asm__ __volatile__(
  25. " norm.f %0, %1 \n"
  26. " mov.n %0, 0 \n"
  27. " add.p %0, %0, 1 \n"
  28. : "=r"(res)
  29. : "r"(x)
  30. : "cc");
  31. return res;
  32. }
  33. static inline int constant_fls(unsigned int x)
  34. {
  35. int r = 32;
  36. if (!x)
  37. return 0;
  38. if (!(x & 0xffff0000u)) {
  39. x <<= 16;
  40. r -= 16;
  41. }
  42. if (!(x & 0xff000000u)) {
  43. x <<= 8;
  44. r -= 8;
  45. }
  46. if (!(x & 0xf0000000u)) {
  47. x <<= 4;
  48. r -= 4;
  49. }
  50. if (!(x & 0xc0000000u)) {
  51. x <<= 2;
  52. r -= 2;
  53. }
  54. if (!(x & 0x80000000u))
  55. r -= 1;
  56. return r;
  57. }
  58. /*
  59. * fls = Find Last Set in word
  60. * @result: [1-32]
  61. * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
  62. */
  63. static inline __attribute__ ((const)) int fls(unsigned int x)
  64. {
  65. if (__builtin_constant_p(x))
  66. return constant_fls(x);
  67. return 32 - clz(x);
  68. }
  69. /*
  70. * __fls: Similar to fls, but zero based (0-31)
  71. */
  72. static inline __attribute__ ((const)) unsigned long __fls(unsigned long x)
  73. {
  74. if (!x)
  75. return 0;
  76. else
  77. return fls(x) - 1;
  78. }
  79. /*
  80. * ffs = Find First Set in word (LSB to MSB)
  81. * @result: [1-32], 0 if all 0's
  82. */
  83. #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
  84. /*
  85. * __ffs: Similar to ffs, but zero based (0-31)
  86. */
  87. static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
  88. {
  89. if (!word)
  90. return word;
  91. return ffs(word) - 1;
  92. }
  93. #else /* CONFIG_ISA_ARCV2 */
  94. /*
  95. * fls = Find Last Set in word
  96. * @result: [1-32]
  97. * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
  98. */
  99. static inline __attribute__ ((const)) int fls(unsigned int x)
  100. {
  101. int n;
  102. asm volatile(
  103. " fls.f %0, %1 \n" /* 0:31; 0(Z) if src 0 */
  104. " add.nz %0, %0, 1 \n" /* 0:31 -> 1:32 */
  105. : "=r"(n) /* Early clobber not needed */
  106. : "r"(x)
  107. : "cc");
  108. return n;
  109. }
  110. /*
  111. * __fls: Similar to fls, but zero based (0-31). Also 0 if no bit set
  112. */
  113. static inline __attribute__ ((const)) unsigned long __fls(unsigned long x)
  114. {
  115. /* FLS insn has exactly same semantics as the API */
  116. return __builtin_arc_fls(x);
  117. }
  118. /*
  119. * ffs = Find First Set in word (LSB to MSB)
  120. * @result: [1-32], 0 if all 0's
  121. */
  122. static inline __attribute__ ((const)) int ffs(unsigned int x)
  123. {
  124. int n;
  125. asm volatile(
  126. " ffs.f %0, %1 \n" /* 0:31; 31(Z) if src 0 */
  127. " add.nz %0, %0, 1 \n" /* 0:31 -> 1:32 */
  128. " mov.z %0, 0 \n" /* 31(Z)-> 0 */
  129. : "=r"(n) /* Early clobber not needed */
  130. : "r"(x)
  131. : "cc");
  132. return n;
  133. }
  134. /*
  135. * __ffs: Similar to ffs, but zero based (0-31)
  136. */
  137. static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
  138. {
  139. unsigned long n;
  140. asm volatile(
  141. " ffs.f %0, %1 \n" /* 0:31; 31(Z) if src 0 */
  142. " mov.z %0, 0 \n" /* 31(Z)-> 0 */
  143. : "=r"(n)
  144. : "r"(x)
  145. : "cc");
  146. return n;
  147. }
  148. #endif /* CONFIG_ISA_ARCOMPACT */
  149. /*
  150. * ffz = Find First Zero in word.
  151. * @return:[0-31], 32 if all 1's
  152. */
  153. #define ffz(x) __ffs(~(x))
  154. #include <asm-generic/bitops/hweight.h>
  155. #include <asm-generic/bitops/fls64.h>
  156. #include <asm-generic/bitops/sched.h>
  157. #include <asm-generic/bitops/lock.h>
  158. #include <asm-generic/bitops/atomic.h>
  159. #include <asm-generic/bitops/non-atomic.h>
  160. #include <asm-generic/bitops/le.h>
  161. #include <asm-generic/bitops/ext2-atomic-setbit.h>
  162. #endif /* !__ASSEMBLY__ */
  163. #endif