[PATCH 445] m68k bitops

From: Geert Uytterhoeven
Date: Thu Apr 22 2004 - 06:52:10 EST


M68k bitops updates (from Roman Zippel):
- Optimize find_{first,next}_zero_bit()
- Add missing implementations of find_{first,next}_bit()

--- linux-2.6.6-rc2/include/asm-m68k/bitops.h 2004-04-05 10:41:52.000000000 +0200
+++ linux-m68k-2.6.6-rc2/include/asm-m68k/bitops.h 2004-04-21 12:56:55.000000000 +0200
@@ -175,51 +175,96 @@ static inline int test_bit(int nr, const
static inline int find_first_zero_bit(const unsigned long *vaddr,
unsigned size)
{
- const unsigned long *p = vaddr, *addr = vaddr;
- unsigned long allones = ~0UL;
- int res;
+ const unsigned long *p = vaddr;
+ int res = 32;
unsigned long num;

if (!size)
return 0;

- size = (size >> 5) + ((size & 31) > 0);
- while (*p++ == allones)
- {
- if (--size == 0)
- return (p - addr) << 5;
+ size = (size + 31) >> 5;
+ while (!(num = ~*p++)) {
+ if (!--size)
+ goto out;
}

- num = ~*--p;
__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
: "=d" (res) : "d" (num & -num));
- return ((p - addr) << 5) + (res ^ 31);
+ res ^= 31;
+out:
+ return ((long)p - (long)vaddr - 4) * 8 + res;
}

static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
int offset)
{
- const unsigned long *addr = vaddr;
- const unsigned long *p = addr + (offset >> 5);
- int set = 0, bit = offset & 31UL, res;
+ const unsigned long *p = vaddr + (offset >> 5);
+ int bit = offset & 31UL, res;

if (offset >= size)
return size;

if (bit) {
- unsigned long num = ~*p & (~0UL << bit);
+ unsigned long num = ~*p++ & (~0UL << bit);
+ offset -= bit;

/* Look for zero in first longword */
__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
: "=d" (res) : "d" (num & -num));
if (res < 32)
- return (offset & ~31UL) + (res ^ 31);
- set = 32 - bit;
- p++;
+ return offset + (res ^ 31);
+ offset += 32;
}
/* No zero yet, search remaining full bytes for a zero */
- res = find_first_zero_bit (p, size - 32 * (p - addr));
- return (offset + set + res);
+ res = find_first_zero_bit(p, size - ((long)p - (long)vaddr) * 8);
+ return offset + res;
+}
+
+static inline int find_first_bit(const unsigned long *vaddr, unsigned size)
+{
+ const unsigned long *p = vaddr;
+ int res = 32;
+ unsigned long num;
+
+ if (!size)
+ return 0;
+
+ size = (size + 31) >> 5;
+ while (!(num = *p++)) {
+ if (!--size)
+ goto out;
+ }
+
+ __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+ : "=d" (res) : "d" (num & -num));
+ res ^= 31;
+out:
+ return ((long)p - (long)vaddr - 4) * 8 + res;
+}
+
+static inline int find_next_bit(const unsigned long *vaddr, int size,
+ int offset)
+{
+ const unsigned long *p = vaddr + (offset >> 5);
+ int bit = offset & 31UL, res;
+
+ if (offset >= size)
+ return size;
+
+ if (bit) {
+ unsigned long num = *p++ & (~0UL << bit);
+ offset -= bit;
+
+ /* Look for one in first longword */
+ __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+ : "=d" (res) : "d" (num & -num));
+ if (res < 32)
+ return offset + (res ^ 31);
+ offset += 32;
+ }
+ /* No one yet, search remaining full bytes for a one */
+ res = find_first_bit(p, size - ((long)p - (long)vaddr) * 8);
+ return offset + res;
}

/*

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/