bitops-op32.h 3.7 KB

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