bitops.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * These are too big to be inlined.
  3. */
  4. #include <linux/kernel.h>
  5. #include <linux/module.h>
  6. #include <linux/bitops.h>
  7. #include <asm/byteorder.h>
  8. unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
  9. unsigned long offset)
  10. {
  11. const unsigned long *p = addr + (offset >> 6);
  12. unsigned long result = offset & ~63UL;
  13. unsigned long tmp;
  14. if (offset >= size)
  15. return size;
  16. size -= result;
  17. offset &= 63UL;
  18. if (offset) {
  19. tmp = *(p++);
  20. tmp |= ~0UL >> (64 - offset);
  21. if (size < 64)
  22. goto found_first;
  23. if (~tmp)
  24. goto found_middle;
  25. size -= 64;
  26. result += 64;
  27. }
  28. while (size & ~63UL) {
  29. if (~(tmp = *(p++)))
  30. goto found_middle;
  31. result += 64;
  32. size -= 64;
  33. }
  34. if (!size)
  35. return result;
  36. tmp = *p;
  37. found_first:
  38. tmp |= ~0UL << size;
  39. if (tmp == ~0UL) /* Are any bits zero? */
  40. return result + size; /* Nope. */
  41. found_middle:
  42. return result + ffz(tmp);
  43. }
  44. EXPORT_SYMBOL(find_next_zero_bit);
  45. unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
  46. unsigned long offset)
  47. {
  48. const unsigned long *p = addr + (offset >> 6);
  49. unsigned long result = offset & ~63UL;
  50. unsigned long tmp;
  51. if (offset >= size)
  52. return size;
  53. size -= result;
  54. offset &= 63UL;
  55. if (offset) {
  56. tmp = *(p++);
  57. tmp &= (~0UL << offset);
  58. if (size < 64)
  59. goto found_first;
  60. if (tmp)
  61. goto found_middle;
  62. size -= 64;
  63. result += 64;
  64. }
  65. while (size & ~63UL) {
  66. if ((tmp = *(p++)))
  67. goto found_middle;
  68. result += 64;
  69. size -= 64;
  70. }
  71. if (!size)
  72. return result;
  73. tmp = *p;
  74. found_first:
  75. tmp &= (~0UL >> (64 - size));
  76. if (tmp == 0UL) /* Are any bits set? */
  77. return result + size; /* Nope. */
  78. found_middle:
  79. return result + __ffs(tmp);
  80. }
  81. EXPORT_SYMBOL(find_next_bit);
  82. static inline unsigned int ext2_ilog2(unsigned int x)
  83. {
  84. int lz;
  85. asm("cntlzw %0,%1": "=r"(lz):"r"(x));
  86. return 31 - lz;
  87. }
  88. static inline unsigned int ext2_ffz(unsigned int x)
  89. {
  90. u32 rc;
  91. if ((x = ~x) == 0)
  92. return 32;
  93. rc = ext2_ilog2(x & -x);
  94. return rc;
  95. }
  96. unsigned long find_next_zero_le_bit(const unsigned long *addr, unsigned long size,
  97. unsigned long offset)
  98. {
  99. const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5);
  100. unsigned int result = offset & ~31;
  101. unsigned int tmp;
  102. if (offset >= size)
  103. return size;
  104. size -= result;
  105. offset &= 31;
  106. if (offset) {
  107. tmp = cpu_to_le32p(p++);
  108. tmp |= ~0U >> (32 - offset); /* bug or feature ? */
  109. if (size < 32)
  110. goto found_first;
  111. if (tmp != ~0)
  112. goto found_middle;
  113. size -= 32;
  114. result += 32;
  115. }
  116. while (size >= 32) {
  117. if ((tmp = cpu_to_le32p(p++)) != ~0)
  118. goto found_middle;
  119. result += 32;
  120. size -= 32;
  121. }
  122. if (!size)
  123. return result;
  124. tmp = cpu_to_le32p(p);
  125. found_first:
  126. tmp |= ~0 << size;
  127. if (tmp == ~0) /* Are any bits zero? */
  128. return result + size; /* Nope. */
  129. found_middle:
  130. return result + ext2_ffz(tmp);
  131. }
  132. EXPORT_SYMBOL(find_next_zero_le_bit);