bitops-op32.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_SH_BITOPS_OP32_H
  3. #define __ASM_SH_BITOPS_OP32_H
  4. /*
  5. * The bit modifying instructions on SH-2A are only capable of working
  6. * with a 3-bit immediate, which signifies the shift position for the bit
  7. * being worked on.
  8. */
  9. #if defined(__BIG_ENDIAN)
  10. #define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
  11. #define BYTE_NUMBER(nr) ((nr ^ BITOP_LE_SWIZZLE) / BITS_PER_BYTE)
  12. #define BYTE_OFFSET(nr) ((nr ^ BITOP_LE_SWIZZLE) % BITS_PER_BYTE)
  13. #else
  14. #define BYTE_NUMBER(nr) ((nr) / BITS_PER_BYTE)
  15. #define BYTE_OFFSET(nr) ((nr) % BITS_PER_BYTE)
  16. #endif
  17. #define IS_IMMEDIATE(nr) (__builtin_constant_p(nr))
  18. static inline void __set_bit(int nr, volatile unsigned long *addr)
  19. {
  20. if (IS_IMMEDIATE(nr)) {
  21. __asm__ __volatile__ (
  22. "bset.b %1, @(%O2,%0) ! __set_bit\n\t"
  23. : "+r" (addr)
  24. : "i" (BYTE_OFFSET(nr)), "i" (BYTE_NUMBER(nr))
  25. : "t", "memory"
  26. );
  27. } else {
  28. unsigned long mask = BIT_MASK(nr);
  29. unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  30. *p |= mask;
  31. }
  32. }
  33. static inline void __clear_bit(int nr, volatile unsigned long *addr)
  34. {
  35. if (IS_IMMEDIATE(nr)) {
  36. __asm__ __volatile__ (
  37. "bclr.b %1, @(%O2,%0) ! __clear_bit\n\t"
  38. : "+r" (addr)
  39. : "i" (BYTE_OFFSET(nr)),
  40. "i" (BYTE_NUMBER(nr))
  41. : "t", "memory"
  42. );
  43. } else {
  44. unsigned long mask = BIT_MASK(nr);
  45. unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  46. *p &= ~mask;
  47. }
  48. }
  49. /**
  50. * __change_bit - Toggle a bit in memory
  51. * @nr: the bit to change
  52. * @addr: the address to start counting from
  53. *
  54. * Unlike change_bit(), this function is non-atomic and may be reordered.
  55. * If it's called on the same region of memory simultaneously, the effect
  56. * may be that only one operation succeeds.
  57. */
  58. static inline void __change_bit(int nr, volatile unsigned long *addr)
  59. {
  60. if (IS_IMMEDIATE(nr)) {
  61. __asm__ __volatile__ (
  62. "bxor.b %1, @(%O2,%0) ! __change_bit\n\t"
  63. : "+r" (addr)
  64. : "i" (BYTE_OFFSET(nr)),
  65. "i" (BYTE_NUMBER(nr))
  66. : "t", "memory"
  67. );
  68. } else {
  69. unsigned long mask = BIT_MASK(nr);
  70. unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  71. *p ^= mask;
  72. }
  73. }
  74. /**
  75. * __test_and_set_bit - Set a bit and return its old value
  76. * @nr: Bit to set
  77. * @addr: Address to count from
  78. *
  79. * This operation is non-atomic and can be reordered.
  80. * If two examples of this operation race, one can appear to succeed
  81. * but actually fail. You must protect multiple accesses with a lock.
  82. */
  83. static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
  84. {
  85. unsigned long mask = BIT_MASK(nr);
  86. unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  87. unsigned long old = *p;
  88. *p = old | mask;
  89. return (old & mask) != 0;
  90. }
  91. /**
  92. * __test_and_clear_bit - Clear a bit and return its old value
  93. * @nr: Bit to clear
  94. * @addr: Address to count from
  95. *
  96. * This operation is non-atomic and can be reordered.
  97. * If two examples of this operation race, one can appear to succeed
  98. * but actually fail. You must protect multiple accesses with a lock.
  99. */
  100. static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
  101. {
  102. unsigned long mask = BIT_MASK(nr);
  103. unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  104. unsigned long old = *p;
  105. *p = old & ~mask;
  106. return (old & mask) != 0;
  107. }
  108. /* WARNING: non atomic and it can be reordered! */
  109. static inline int __test_and_change_bit(int nr,
  110. volatile unsigned long *addr)
  111. {
  112. unsigned long mask = BIT_MASK(nr);
  113. unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  114. unsigned long old = *p;
  115. *p = old ^ mask;
  116. return (old & mask) != 0;
  117. }
  118. /**
  119. * test_bit - Determine whether a bit is set
  120. * @nr: bit number to test
  121. * @addr: Address to start counting from
  122. */
  123. static inline int test_bit(int nr, const volatile unsigned long *addr)
  124. {
  125. return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
  126. }
  127. #endif /* __ASM_SH_BITOPS_OP32_H */