bitops_64.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #include <linux/bitops.h>
  2. #undef find_first_zero_bit
  3. #undef find_next_zero_bit
  4. #undef find_first_bit
  5. #undef find_next_bit
  6. static inline long
  7. __find_first_zero_bit(const unsigned long * addr, unsigned long size)
  8. {
  9. long d0, d1, d2;
  10. long res;
  11. /*
  12. * We must test the size in words, not in bits, because
  13. * otherwise incoming sizes in the range -63..-1 will not run
  14. * any scasq instructions, and then the flags used by the je
  15. * instruction will have whatever random value was in place
  16. * before. Nobody should call us like that, but
  17. * find_next_zero_bit() does when offset and size are at the
  18. * same word and it fails to find a zero itself.
  19. */
  20. size += 63;
  21. size >>= 6;
  22. if (!size)
  23. return 0;
  24. asm volatile(
  25. " repe; scasq\n"
  26. " je 1f\n"
  27. " xorq -8(%%rdi),%%rax\n"
  28. " subq $8,%%rdi\n"
  29. " bsfq %%rax,%%rdx\n"
  30. "1: subq %[addr],%%rdi\n"
  31. " shlq $3,%%rdi\n"
  32. " addq %%rdi,%%rdx"
  33. :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
  34. :"0" (0ULL), "1" (size), "2" (addr), "3" (-1ULL),
  35. [addr] "S" (addr) : "memory");
  36. /*
  37. * Any register would do for [addr] above, but GCC tends to
  38. * prefer rbx over rsi, even though rsi is readily available
  39. * and doesn't have to be saved.
  40. */
  41. return res;
  42. }
  43. /**
  44. * find_first_zero_bit - find the first zero bit in a memory region
  45. * @addr: The address to start the search at
  46. * @size: The maximum size to search
  47. *
  48. * Returns the bit-number of the first zero bit, not the number of the byte
  49. * containing a bit.
  50. */
  51. long find_first_zero_bit(const unsigned long * addr, unsigned long size)
  52. {
  53. return __find_first_zero_bit (addr, size);
  54. }
  55. /**
  56. * find_next_zero_bit - find the first zero bit in a memory region
  57. * @addr: The address to base the search on
  58. * @offset: The bitnumber to start searching at
  59. * @size: The maximum size to search
  60. */
  61. long find_next_zero_bit (const unsigned long * addr, long size, long offset)
  62. {
  63. const unsigned long * p = addr + (offset >> 6);
  64. unsigned long set = 0;
  65. unsigned long res, bit = offset&63;
  66. if (bit) {
  67. /*
  68. * Look for zero in first word
  69. */
  70. asm("bsfq %1,%0\n\t"
  71. "cmoveq %2,%0"
  72. : "=r" (set)
  73. : "r" (~(*p >> bit)), "r"(64L));
  74. if (set < (64 - bit))
  75. return set + offset;
  76. set = 64 - bit;
  77. p++;
  78. }
  79. /*
  80. * No zero yet, search remaining full words for a zero
  81. */
  82. res = __find_first_zero_bit (p, size - 64 * (p - addr));
  83. return (offset + set + res);
  84. }
  85. static inline long
  86. __find_first_bit(const unsigned long * addr, unsigned long size)
  87. {
  88. long d0, d1;
  89. long res;
  90. /*
  91. * We must test the size in words, not in bits, because
  92. * otherwise incoming sizes in the range -63..-1 will not run
  93. * any scasq instructions, and then the flags used by the jz
  94. * instruction will have whatever random value was in place
  95. * before. Nobody should call us like that, but
  96. * find_next_bit() does when offset and size are at the same
  97. * word and it fails to find a one itself.
  98. */
  99. size += 63;
  100. size >>= 6;
  101. if (!size)
  102. return 0;
  103. asm volatile(
  104. " repe; scasq\n"
  105. " jz 1f\n"
  106. " subq $8,%%rdi\n"
  107. " bsfq (%%rdi),%%rax\n"
  108. "1: subq %[addr],%%rdi\n"
  109. " shlq $3,%%rdi\n"
  110. " addq %%rdi,%%rax"
  111. :"=a" (res), "=&c" (d0), "=&D" (d1)
  112. :"0" (0ULL), "1" (size), "2" (addr),
  113. [addr] "r" (addr) : "memory");
  114. return res;
  115. }
  116. /**
  117. * find_first_bit - find the first set bit in a memory region
  118. * @addr: The address to start the search at
  119. * @size: The maximum size to search
  120. *
  121. * Returns the bit-number of the first set bit, not the number of the byte
  122. * containing a bit.
  123. */
  124. long find_first_bit(const unsigned long * addr, unsigned long size)
  125. {
  126. return __find_first_bit(addr,size);
  127. }
  128. /**
  129. * find_next_bit - find the first set bit in a memory region
  130. * @addr: The address to base the search on
  131. * @offset: The bitnumber to start searching at
  132. * @size: The maximum size to search
  133. */
  134. long find_next_bit(const unsigned long * addr, long size, long offset)
  135. {
  136. const unsigned long * p = addr + (offset >> 6);
  137. unsigned long set = 0, bit = offset & 63, res;
  138. if (bit) {
  139. /*
  140. * Look for nonzero in the first 64 bits:
  141. */
  142. asm("bsfq %1,%0\n\t"
  143. "cmoveq %2,%0\n\t"
  144. : "=r" (set)
  145. : "r" (*p >> bit), "r" (64L));
  146. if (set < (64 - bit))
  147. return set + offset;
  148. set = 64 - bit;
  149. p++;
  150. }
  151. /*
  152. * No set bit yet, search remaining full words for a bit
  153. */
  154. res = __find_first_bit (p, size - 64 * (p - addr));
  155. return (offset + set + res);
  156. }
  157. #include <linux/module.h>
  158. EXPORT_SYMBOL(find_next_bit);
  159. EXPORT_SYMBOL(find_first_bit);
  160. EXPORT_SYMBOL(find_first_zero_bit);
  161. EXPORT_SYMBOL(find_next_zero_bit);