[PATCH v3 01/11] sandbox: add generic find_next_zero_bit implementation
lukas.funke-oss at weidmueller.com
lukas.funke-oss at weidmueller.com
Wed Jan 10 10:10:27 CET 2024
From: Lukas Funke <lukas.funke at weidmueller.com>
Add generic 'find_next_zero_bit()' implementation in order to enable the
use of the 'for_each_set_bitrange' macro. The implementation is currently
missing for the sandbox-arch and using the function results in a linker
error. The implementation is copied from the 'arm' implementation.
Signed-off-by: Lukas Funke <lukas.funke at weidmueller.com>
Reviewed-by: Simon Glass <sjg at chromium.org>
---
Changes in v3:
- Use generic find_next_zero_bit() from arch/arm/include/asm/bitops.h
- Redirect sandbox ffz() implementation to generic __ffs() impl
arch/sandbox/include/asm/bitops.h | 60 +++++++++++++++++++------------
1 file changed, 38 insertions(+), 22 deletions(-)
diff --git a/arch/sandbox/include/asm/bitops.h b/arch/sandbox/include/asm/bitops.h
index f27d5e98c5..6950916962 100644
--- a/arch/sandbox/include/asm/bitops.h
+++ b/arch/sandbox/include/asm/bitops.h
@@ -104,9 +104,6 @@ static inline int __test_and_change_bit(int nr, void *addr)
return (old & mask) != 0;
}
-extern int find_first_zero_bit(void *addr, unsigned size);
-extern int find_next_zero_bit(void *addr, int size, int offset);
-
/*
* This routine doesn't need to be atomic.
*/
@@ -119,27 +116,46 @@ static inline int test_bit(int nr, const void *addr)
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
*/
-static inline unsigned long ffz(unsigned long word)
-{
- int k;
-
- word = ~word;
- k = 31;
- if (word & 0x0000ffff) {
- k -= 16; word <<= 16;
- }
- if (word & 0x00ff0000) {
- k -= 8; word <<= 8;
- }
- if (word & 0x0f000000) {
- k -= 4; word <<= 4;
+#define ffz(x) __ffs(~(x))
+
+#define find_first_zero_bit(addr, size) \
+ find_next_zero_bit((addr), (size), 0)
+
+static inline int find_next_zero_bit(const unsigned long *addr, int size,
+ int offset) {
+ unsigned long *p = ((unsigned long *)addr) + (offset / BITS_PER_LONG);
+ unsigned long result = offset & ~(BITS_PER_LONG - 1);
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= (BITS_PER_LONG - 1);
+ if (offset) {
+ tmp = *(p++);
+ tmp |= ~0UL >> (BITS_PER_LONG - offset);
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (~tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
}
- if (word & 0x30000000) {
- k -= 2; word <<= 2;
+ while (size & ~(BITS_PER_LONG - 1)) {
+ tmp = *(p++);
+ if (~tmp)
+ goto found_middle;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
}
- if (word & 0x40000000)
- k -= 1;
- return k;
+ if (!size)
+ return result;
+ tmp = *p;
+
+found_first:
+ tmp |= ~0UL << size;
+found_middle:
+ return result + ffz(tmp);
}
/*
--
2.30.2
More information about the U-Boot
mailing list