bit_test.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2010 iptelorg GmbH
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. *
  18. * History
  19. * -------
  20. * 2010-04-26 Initial version (Miklos)
  21. * 2011-01-05 bit_test_and_reset added (Miklos)
  22. */
  23. /* Bit test functions:
  24. * - int bit_test(int offset, unsigned int *addr)
  25. * Returns the bit found at offset position
  26. * in a bitstring pointed by addr.
  27. *
  28. * - int bit_test_and_set(int offset, unsigned int *addr)
  29. * Returns the bit found at offset position
  30. * in a bitstring pointed by addr, and sets
  31. * the bit at the given offset.
  32. *
  33. * - int bit_test_and_reset(int offset, unsigned int *addr)
  34. * Returns the bit found at offset position
  35. * in a bitstring pointed by addr, and resets
  36. * the bit at the given offset.
  37. *
  38. * Note that 0 <= offset <= 128, Make sure that addr points to
  39. * a large enough memory area.
  40. */
  41. #ifndef _BIT_TEST_H
  42. #define _BIT_TEST_H
  43. /* fix __CPU_i386 -> __CPU_x86 */
  44. #if defined __CPU_i386 && ! defined __CPU_x86
  45. #define __CPU_x86
  46. #endif
  47. #ifdef CC_GCC_LIKE_ASM
  48. #if defined __CPU_x86 || defined __CPU_x86_64
  49. #define BIT_TEST_ASM
  50. #endif
  51. #endif
  52. #ifdef BIT_TEST_ASM
  53. /* Returns the bit found at offset position in the bitstring
  54. * pointed by addr.
  55. * Note that the CPU can access 4 bytes starting from addr,
  56. * hence 0 <= offset < 128 holds. Make sure that addr points
  57. * to a memory area that is large enough.
  58. */
  59. static inline int bit_test(int offset, unsigned int *addr)
  60. {
  61. unsigned char v;
  62. asm volatile(
  63. " bt %2, %1 \n\t"
  64. " setc %0 \n\t"
  65. : "=qm" (v) : "m" (*addr), "r" (offset)
  66. );
  67. return (int)v;
  68. }
  69. /* Returns the bit found at offset position in the bitstring
  70. * pointed by addr and sets it to 1.
  71. * Note that the CPU can access 4 bytes starting from addr,
  72. * hence 0 <= offset < 128 holds. Make sure that addr points
  73. * to a memory area that is large enough.
  74. */
  75. static inline int bit_test_and_set(int offset, unsigned int *addr)
  76. {
  77. unsigned char v;
  78. asm volatile(
  79. " bts %2, %1 \n\t"
  80. " setc %0 \n\t"
  81. : "=qm" (v) : "m" (*addr), "r" (offset)
  82. );
  83. return (int)v;
  84. }
  85. /* Returns the bit found at offset position in the bitstring
  86. * pointed by addr and resets it to 0.
  87. * Note that the CPU can access 4 bytes starting from addr,
  88. * hence 0 <= offset < 128 holds. Make sure that addr points
  89. * to a memory area that is large enough.
  90. */
  91. static inline int bit_test_and_reset(int offset, unsigned int *addr)
  92. {
  93. unsigned char v;
  94. asm volatile(
  95. " btr %2, %1 \n\t"
  96. " setc %0 \n\t"
  97. : "=qm" (v) : "m" (*addr), "r" (offset)
  98. );
  99. return (int)v;
  100. }
  101. #else /* BIT_TEST_ASM */
  102. /* Returns the bit found at offset position in the bitstring
  103. * pointed by addr.
  104. * Note that offset can be grater than 32, make sure that addr points
  105. * to a memory area that is large enough.
  106. */
  107. static inline int bit_test(int offset, unsigned int *addr)
  108. {
  109. return ((*(addr + offset/32)) & (1U << (offset % 32))) ? 1 : 0;
  110. }
  111. /* Returns the bit found at offset position in the bitstring
  112. * pointed by addr and sets it to 1.
  113. * Note that offset can be grater than 32, make sure that addr points
  114. * to a memory area that is large enough.
  115. */
  116. static inline int bit_test_and_set(int offset, unsigned int *addr)
  117. {
  118. unsigned int *i;
  119. int mask, res;
  120. i = addr + offset/32;
  121. mask = 1U << (offset % 32);
  122. res = ((*i) & mask) ? 1 : 0;
  123. (*i) |= mask;
  124. return res;
  125. }
  126. /* Returns the bit found at offset position in the bitstring
  127. * pointed by addr and resets it to 0.
  128. * Note that offset can be grater than 32, make sure that addr points
  129. * to a memory area that is large enough.
  130. */
  131. static inline int bit_test_and_reset(int offset, unsigned int *addr)
  132. {
  133. unsigned int *i;
  134. int mask, res;
  135. i = addr + offset/32;
  136. mask = 1U << (offset % 32);
  137. res = ((*i) & mask) ? 1 : 0;
  138. (*i) &= ~mask;
  139. return res;
  140. }
  141. #endif /* BIT_TEST_ASM */
  142. #endif /* #ifndef _BIT_TEST_H */