diff options
author | Nishanth Menon <x0nishan@ti.com> | 2008-08-14 20:26:49 -0500 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2008-08-15 08:47:49 +0200 |
commit | 5fc0e871d5df3ff6b2f4ed70bf19b6af457f0286 (patch) | |
tree | fd13109d728a10f028b3294b2994d2993284d46e /lib/find_next_bit.c | |
parent | aed834904a9ab4aba214dfb4405f4321833f2fe6 (diff) | |
download | barebox-5fc0e871d5df3ff6b2f4ed70bf19b6af457f0286.tar.gz |
U-Boot-V2:Bitops: asm-generic bitops
This introduces selected generic bitop files from
kernel. We don't need minix, ext2, sched or lock
based bitops. Those have been dropped.
Signed-off-by: Nishanth Menon <x0nishan@ti.com>
Diffstat (limited to 'lib/find_next_bit.c')
-rw-r--r-- | lib/find_next_bit.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c new file mode 100644 index 0000000000..01873d8884 --- /dev/null +++ b/lib/find_next_bit.c @@ -0,0 +1,109 @@ +/* find_next_bit.c: fallback find next bit implementation + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <common.h> +#include <errno.h> +#include <string.h> +#include <init.h> +#include <linux/bitops.h> +#include <asm/types.h> +#include <asm/byteorder.h> + +#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) + +#ifdef CONFIG_GENERIC_FIND_NEXT_BIT +/* + * Find the next set bit in a memory region. + */ +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp &= (~0UL << offset); + if (size < BITS_PER_LONG) + goto found_first; + if (tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG-1)) { + if ((tmp = *(p++))) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp &= (~0UL >> (BITS_PER_LONG - size)); + if (tmp == 0UL) /* Are any bits set? */ + return result + size; /* Nope. */ +found_middle: + return result + __ffs(tmp); +} +EXPORT_SYMBOL(find_next_bit); + +/* + * This implementation of find_{first,next}_zero_bit was stolen from + * Linus' asm-alpha/bitops.h. + */ +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + 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; + } + while (size & ~(BITS_PER_LONG-1)) { + if (~(tmp = *(p++))) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ffz(tmp); +} + EXPORT_SYMBOL(find_next_zero_bit); +#endif /* CONFIG_GENERIC_FIND_NEXT_BIT */ |