xref: /openbmc/linux/arch/s390/lib/find.c (revision b2441318)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2746479cdSHeiko Carstens /*
3746479cdSHeiko Carstens  * MSB0 numbered special bitops handling.
4746479cdSHeiko Carstens  *
548002bd5SHeiko Carstens  * The bits are numbered:
6746479cdSHeiko Carstens  *   |0..............63|64............127|128...........191|192...........255|
7746479cdSHeiko Carstens  *
8746479cdSHeiko Carstens  * The reason for this bit numbering is the fact that the hardware sets bits
9746479cdSHeiko Carstens  * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
10746479cdSHeiko Carstens  * from the 'wrong end'.
11746479cdSHeiko Carstens  */
12746479cdSHeiko Carstens 
13746479cdSHeiko Carstens #include <linux/compiler.h>
14746479cdSHeiko Carstens #include <linux/bitops.h>
15746479cdSHeiko Carstens #include <linux/export.h>
16746479cdSHeiko Carstens 
find_first_bit_inv(const unsigned long * addr,unsigned long size)177d7c7b24SHeiko Carstens unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size)
18746479cdSHeiko Carstens {
19746479cdSHeiko Carstens 	const unsigned long *p = addr;
20746479cdSHeiko Carstens 	unsigned long result = 0;
21746479cdSHeiko Carstens 	unsigned long tmp;
22746479cdSHeiko Carstens 
23746479cdSHeiko Carstens 	while (size & ~(BITS_PER_LONG - 1)) {
24746479cdSHeiko Carstens 		if ((tmp = *(p++)))
25746479cdSHeiko Carstens 			goto found;
26746479cdSHeiko Carstens 		result += BITS_PER_LONG;
27746479cdSHeiko Carstens 		size -= BITS_PER_LONG;
28746479cdSHeiko Carstens 	}
29746479cdSHeiko Carstens 	if (!size)
30746479cdSHeiko Carstens 		return result;
31746479cdSHeiko Carstens 	tmp = (*p) & (~0UL << (BITS_PER_LONG - size));
32746479cdSHeiko Carstens 	if (!tmp)		/* Are any bits set? */
33746479cdSHeiko Carstens 		return result + size;	/* Nope. */
34746479cdSHeiko Carstens found:
35746479cdSHeiko Carstens 	return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
36746479cdSHeiko Carstens }
377d7c7b24SHeiko Carstens EXPORT_SYMBOL(find_first_bit_inv);
38746479cdSHeiko Carstens 
find_next_bit_inv(const unsigned long * addr,unsigned long size,unsigned long offset)397d7c7b24SHeiko Carstens unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
40746479cdSHeiko Carstens 				unsigned long offset)
41746479cdSHeiko Carstens {
42746479cdSHeiko Carstens 	const unsigned long *p = addr + (offset / BITS_PER_LONG);
43746479cdSHeiko Carstens 	unsigned long result = offset & ~(BITS_PER_LONG - 1);
44746479cdSHeiko Carstens 	unsigned long tmp;
45746479cdSHeiko Carstens 
46746479cdSHeiko Carstens 	if (offset >= size)
47746479cdSHeiko Carstens 		return size;
48746479cdSHeiko Carstens 	size -= result;
49746479cdSHeiko Carstens 	offset %= BITS_PER_LONG;
50746479cdSHeiko Carstens 	if (offset) {
51746479cdSHeiko Carstens 		tmp = *(p++);
52746479cdSHeiko Carstens 		tmp &= (~0UL >> offset);
53746479cdSHeiko Carstens 		if (size < BITS_PER_LONG)
54746479cdSHeiko Carstens 			goto found_first;
55746479cdSHeiko Carstens 		if (tmp)
56746479cdSHeiko Carstens 			goto found_middle;
57746479cdSHeiko Carstens 		size -= BITS_PER_LONG;
58746479cdSHeiko Carstens 		result += BITS_PER_LONG;
59746479cdSHeiko Carstens 	}
60746479cdSHeiko Carstens 	while (size & ~(BITS_PER_LONG-1)) {
61746479cdSHeiko Carstens 		if ((tmp = *(p++)))
62746479cdSHeiko Carstens 			goto found_middle;
63746479cdSHeiko Carstens 		result += BITS_PER_LONG;
64746479cdSHeiko Carstens 		size -= BITS_PER_LONG;
65746479cdSHeiko Carstens 	}
66746479cdSHeiko Carstens 	if (!size)
67746479cdSHeiko Carstens 		return result;
68746479cdSHeiko Carstens 	tmp = *p;
69746479cdSHeiko Carstens found_first:
70746479cdSHeiko Carstens 	tmp &= (~0UL << (BITS_PER_LONG - size));
71746479cdSHeiko Carstens 	if (!tmp)		/* Are any bits set? */
72746479cdSHeiko Carstens 		return result + size;	/* Nope. */
73746479cdSHeiko Carstens found_middle:
74746479cdSHeiko Carstens 	return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
75746479cdSHeiko Carstens }
767d7c7b24SHeiko Carstens EXPORT_SYMBOL(find_next_bit_inv);
77