bitops.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. /**
  7. * find_first_zero_bit - find the first zero bit in a memory region
  8. * @addr: The address to start the search at
  9. * @size: The maximum size to search
  10. *
  11. * Returns the bit-number of the first zero bit, not the number of the byte
  12. * containing a bit.
  13. */
  14. inline long find_first_zero_bit(const unsigned long * addr, unsigned long size)
  15. {
  16. long d0, d1, d2;
  17. long res;
  18. if (!size)
  19. return 0;
  20. asm volatile(
  21. " repe; scasq\n"
  22. " je 1f\n"
  23. " xorq -8(%%rdi),%%rax\n"
  24. " subq $8,%%rdi\n"
  25. " bsfq %%rax,%%rdx\n"
  26. "1: subq %[addr],%%rdi\n"
  27. " shlq $3,%%rdi\n"
  28. " addq %%rdi,%%rdx"
  29. :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
  30. :"0" (0ULL), "1" ((size + 63) >> 6), "2" (addr), "3" (-1ULL),
  31. [addr] "r" (addr) : "memory");
  32. return res;
  33. }
  34. /**
  35. * find_next_zero_bit - find the first zero bit in a memory region
  36. * @addr: The address to base the search on
  37. * @offset: The bitnumber to start searching at
  38. * @size: The maximum size to search
  39. */
  40. long find_next_zero_bit (const unsigned long * addr, long size, long offset)
  41. {
  42. unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
  43. unsigned long set = 0;
  44. unsigned long res, bit = offset&63;
  45. if (bit) {
  46. /*
  47. * Look for zero in first word
  48. */
  49. asm("bsfq %1,%0\n\t"
  50. "cmoveq %2,%0"
  51. : "=r" (set)
  52. : "r" (~(*p >> bit)), "r"(64L));
  53. if (set < (64 - bit))
  54. return set + offset;
  55. set = 64 - bit;
  56. p++;
  57. }
  58. /*
  59. * No zero yet, search remaining full words for a zero
  60. */
  61. res = find_first_zero_bit ((const unsigned long *)p,
  62. size - 64 * (p - (unsigned long *) addr));
  63. return (offset + set + res);
  64. }
  65. static inline long
  66. __find_first_bit(const unsigned long * addr, unsigned long size)
  67. {
  68. long d0, d1;
  69. long res;
  70. asm volatile(
  71. " repe; scasq\n"
  72. " jz 1f\n"
  73. " subq $8,%%rdi\n"
  74. " bsfq (%%rdi),%%rax\n"
  75. "1: subq %[addr],%%rdi\n"
  76. " shlq $3,%%rdi\n"
  77. " addq %%rdi,%%rax"
  78. :"=a" (res), "=&c" (d0), "=&D" (d1)
  79. :"0" (0ULL),
  80. "1" ((size + 63) >> 6), "2" (addr),
  81. [addr] "r" (addr) : "memory");
  82. return res;
  83. }
  84. /**
  85. * find_first_bit - find the first set bit in a memory region
  86. * @addr: The address to start the search at
  87. * @size: The maximum size to search
  88. *
  89. * Returns the bit-number of the first set bit, not the number of the byte
  90. * containing a bit.
  91. */
  92. long find_first_bit(const unsigned long * addr, unsigned long size)
  93. {
  94. return __find_first_bit(addr,size);
  95. }
  96. /**
  97. * find_next_bit - find the first set bit in a memory region
  98. * @addr: The address to base the search on
  99. * @offset: The bitnumber to start searching at
  100. * @size: The maximum size to search
  101. */
  102. long find_next_bit(const unsigned long * addr, long size, long offset)
  103. {
  104. const unsigned long * p = addr + (offset >> 6);
  105. unsigned long set = 0, bit = offset & 63, res;
  106. if (bit) {
  107. /*
  108. * Look for nonzero in the first 64 bits:
  109. */
  110. asm("bsfq %1,%0\n\t"
  111. "cmoveq %2,%0\n\t"
  112. : "=r" (set)
  113. : "r" (*p >> bit), "r" (64L));
  114. if (set < (64 - bit))
  115. return set + offset;
  116. set = 64 - bit;
  117. p++;
  118. }
  119. /*
  120. * No set bit yet, search remaining full words for a bit
  121. */
  122. res = __find_first_bit (p, size - 64 * (p - addr));
  123. return (offset + set + res);
  124. }
  125. #include <linux/module.h>
  126. EXPORT_SYMBOL(find_next_bit);
  127. EXPORT_SYMBOL(find_first_bit);
  128. EXPORT_SYMBOL(find_first_zero_bit);
  129. EXPORT_SYMBOL(find_next_zero_bit);