blob: d90b9245ea417a418d78db53f9867d47483d8d2f [file] [log] [blame]
Heiko Carstens746479c2013-09-18 11:45:36 +02001/*
2 * MSB0 numbered special bitops handling.
3 *
Heiko Carstens48002bd2015-10-08 13:51:44 +02004 * The bits are numbered:
Heiko Carstens746479c2013-09-18 11:45:36 +02005 * |0..............63|64............127|128...........191|192...........255|
Heiko Carstens746479c2013-09-18 11:45:36 +02006 *
7 * The reason for this bit numbering is the fact that the hardware sets bits
8 * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
9 * from the 'wrong end'.
10 */
11
12#include <linux/compiler.h>
13#include <linux/bitops.h>
14#include <linux/export.h>
15
Heiko Carstens7d7c7b22013-09-23 12:01:44 +020016unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size)
Heiko Carstens746479c2013-09-18 11:45:36 +020017{
18 const unsigned long *p = addr;
19 unsigned long result = 0;
20 unsigned long tmp;
21
22 while (size & ~(BITS_PER_LONG - 1)) {
23 if ((tmp = *(p++)))
24 goto found;
25 result += BITS_PER_LONG;
26 size -= BITS_PER_LONG;
27 }
28 if (!size)
29 return result;
30 tmp = (*p) & (~0UL << (BITS_PER_LONG - size));
31 if (!tmp) /* Are any bits set? */
32 return result + size; /* Nope. */
33found:
34 return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
35}
Heiko Carstens7d7c7b22013-09-23 12:01:44 +020036EXPORT_SYMBOL(find_first_bit_inv);
Heiko Carstens746479c2013-09-18 11:45:36 +020037
Heiko Carstens7d7c7b22013-09-23 12:01:44 +020038unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
39 unsigned long offset)
Heiko Carstens746479c2013-09-18 11:45:36 +020040{
41 const unsigned long *p = addr + (offset / BITS_PER_LONG);
42 unsigned long result = offset & ~(BITS_PER_LONG - 1);
43 unsigned long tmp;
44
45 if (offset >= size)
46 return size;
47 size -= result;
48 offset %= BITS_PER_LONG;
49 if (offset) {
50 tmp = *(p++);
51 tmp &= (~0UL >> offset);
52 if (size < BITS_PER_LONG)
53 goto found_first;
54 if (tmp)
55 goto found_middle;
56 size -= BITS_PER_LONG;
57 result += BITS_PER_LONG;
58 }
59 while (size & ~(BITS_PER_LONG-1)) {
60 if ((tmp = *(p++)))
61 goto found_middle;
62 result += BITS_PER_LONG;
63 size -= BITS_PER_LONG;
64 }
65 if (!size)
66 return result;
67 tmp = *p;
68found_first:
69 tmp &= (~0UL << (BITS_PER_LONG - size));
70 if (!tmp) /* Are any bits set? */
71 return result + size; /* Nope. */
72found_middle:
73 return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
74}
Heiko Carstens7d7c7b22013-09-23 12:01:44 +020075EXPORT_SYMBOL(find_next_bit_inv);