bitops.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _H8300_BITOPS_H
  3. #define _H8300_BITOPS_H
  4. /*
  5. * Copyright 1992, Linus Torvalds.
  6. * Copyright 2002, Yoshinori Sato
  7. */
  8. #include <linux/compiler.h>
  9. #ifdef __KERNEL__
  10. #ifndef _LINUX_BITOPS_H
  11. #error only <linux/bitops.h> can be included directly
  12. #endif
  13. /*
  14. * Function prototypes to keep gcc -Wall happy
  15. */
  16. /*
  17. * ffz = Find First Zero in word. Undefined if no zero exists,
  18. * so code should check against ~0UL first..
  19. */
  20. static inline unsigned long ffz(unsigned long word)
  21. {
  22. unsigned long result;
  23. result = -1;
  24. __asm__("1:\n\t"
  25. "shlr.l %2\n\t"
  26. "adds #1,%0\n\t"
  27. "bcs 1b"
  28. : "=r"(result)
  29. : "0"(result), "r"(word));
  30. return result;
  31. }
  32. #define H8300_GEN_BITOP(FNAME, OP) \
  33. static inline void FNAME(int nr, volatile unsigned long *addr) \
  34. { \
  35. unsigned char *b_addr; \
  36. unsigned char bit = nr & 7; \
  37. \
  38. b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \
  39. if (__builtin_constant_p(nr)) { \
  40. __asm__(OP " %1,%0" : "+WU"(*b_addr) : "i"(nr & 7)); \
  41. } else { \
  42. __asm__(OP " %s1,%0" : "+WU"(*b_addr) : "r"(bit)); \
  43. } \
  44. }
  45. /*
  46. * clear_bit() doesn't provide any barrier for the compiler.
  47. */
  48. #define smp_mb__before_clear_bit() barrier()
  49. #define smp_mb__after_clear_bit() barrier()
  50. H8300_GEN_BITOP(set_bit, "bset")
  51. H8300_GEN_BITOP(clear_bit, "bclr")
  52. H8300_GEN_BITOP(change_bit, "bnot")
  53. #define __set_bit(nr, addr) set_bit((nr), (addr))
  54. #define __clear_bit(nr, addr) clear_bit((nr), (addr))
  55. #define __change_bit(nr, addr) change_bit((nr), (addr))
  56. #undef H8300_GEN_BITOP
  57. static inline int test_bit(int nr, const unsigned long *addr)
  58. {
  59. int ret = 0;
  60. unsigned char *b_addr;
  61. unsigned char bit = nr & 7;
  62. b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3);
  63. if (__builtin_constant_p(nr)) {
  64. __asm__("bld %Z2,%1\n\t"
  65. "rotxl %0\n\t"
  66. : "=r"(ret)
  67. : "WU"(*b_addr), "i"(nr & 7), "0"(ret) : "cc");
  68. } else {
  69. __asm__("btst %w2,%1\n\t"
  70. "beq 1f\n\t"
  71. "inc.l #1,%0\n"
  72. "1:"
  73. : "=r"(ret)
  74. : "WU"(*b_addr), "r"(bit), "0"(ret) : "cc");
  75. }
  76. return ret;
  77. }
  78. #define __test_bit(nr, addr) test_bit(nr, addr)
  79. #define H8300_GEN_TEST_BITOP(FNNAME, OP) \
  80. static inline int FNNAME(int nr, void *addr) \
  81. { \
  82. int retval = 0; \
  83. char ccrsave; \
  84. unsigned char *b_addr; \
  85. unsigned char bit = nr & 7; \
  86. \
  87. b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \
  88. if (__builtin_constant_p(nr)) { \
  89. __asm__("stc ccr,%s2\n\t" \
  90. "orc #0x80,ccr\n\t" \
  91. "bld %4,%1\n\t" \
  92. OP " %4,%1\n\t" \
  93. "rotxl.l %0\n\t" \
  94. "ldc %s2,ccr" \
  95. : "=r"(retval), "+WU" (*b_addr), "=&r"(ccrsave) \
  96. : "0"(retval), "i"(nr & 7) : "cc"); \
  97. } else { \
  98. __asm__("stc ccr,%t3\n\t" \
  99. "orc #0x80,ccr\n\t" \
  100. "btst %s3,%1\n\t" \
  101. OP " %s3,%1\n\t" \
  102. "beq 1f\n\t" \
  103. "inc.l #1,%0\n\t" \
  104. "1:\n" \
  105. "ldc %t3,ccr" \
  106. : "=r"(retval), "+WU" (*b_addr) \
  107. : "0" (retval), "r"(bit) : "cc"); \
  108. } \
  109. return retval; \
  110. } \
  111. \
  112. static inline int __ ## FNNAME(int nr, void *addr) \
  113. { \
  114. int retval = 0; \
  115. unsigned char *b_addr; \
  116. unsigned char bit = nr & 7; \
  117. \
  118. b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \
  119. if (__builtin_constant_p(nr)) { \
  120. __asm__("bld %3,%1\n\t" \
  121. OP " %3,%1\n\t" \
  122. "rotxl.l %0\n\t" \
  123. : "=r"(retval), "+WU"(*b_addr) \
  124. : "0" (retval), "i"(nr & 7)); \
  125. } else { \
  126. __asm__("btst %s3,%1\n\t" \
  127. OP " %s3,%1\n\t" \
  128. "beq 1f\n\t" \
  129. "inc.l #1,%0\n\t" \
  130. "1:" \
  131. : "=r"(retval), "+WU"(*b_addr) \
  132. : "0" (retval), "r"(bit)); \
  133. } \
  134. return retval; \
  135. }
  136. H8300_GEN_TEST_BITOP(test_and_set_bit, "bset")
  137. H8300_GEN_TEST_BITOP(test_and_clear_bit, "bclr")
  138. H8300_GEN_TEST_BITOP(test_and_change_bit, "bnot")
  139. #undef H8300_GEN_TEST_BITOP
  140. #include <asm-generic/bitops/ffs.h>
  141. static inline unsigned long __ffs(unsigned long word)
  142. {
  143. unsigned long result;
  144. result = -1;
  145. __asm__("1:\n\t"
  146. "shlr.l %2\n\t"
  147. "adds #1,%0\n\t"
  148. "bcc 1b"
  149. : "=r" (result)
  150. : "0"(result), "r"(word));
  151. return result;
  152. }
  153. #include <asm-generic/bitops/find.h>
  154. #include <asm-generic/bitops/sched.h>
  155. #include <asm-generic/bitops/hweight.h>
  156. #include <asm-generic/bitops/lock.h>
  157. #include <asm-generic/bitops/le.h>
  158. #include <asm-generic/bitops/ext2-atomic.h>
  159. #endif /* __KERNEL__ */
  160. #include <asm-generic/bitops/fls.h>
  161. #include <asm-generic/bitops/__fls.h>
  162. #include <asm-generic/bitops/fls64.h>
  163. #endif /* _H8300_BITOPS_H */