Commit b13496e8 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] m68k bitops

From: Geert Uytterhoeven <geert@linux-m68k.org>

M68k bitops updates (from Roman Zippel):
  - Optimize find_{first,next}_zero_bit()
  - Add missing implementations of find_{first,next}_bit()
parent 009c5ed6
...@@ -175,51 +175,96 @@ static inline int test_bit(int nr, const volatile unsigned long *vaddr) ...@@ -175,51 +175,96 @@ static inline int test_bit(int nr, const volatile unsigned long *vaddr)
static inline int find_first_zero_bit(const unsigned long *vaddr, static inline int find_first_zero_bit(const unsigned long *vaddr,
unsigned size) unsigned size)
{ {
const unsigned long *p = vaddr, *addr = vaddr; const unsigned long *p = vaddr;
unsigned long allones = ~0UL; int res = 32;
int res;
unsigned long num; unsigned long num;
if (!size) if (!size)
return 0; return 0;
size = (size >> 5) + ((size & 31) > 0); size = (size + 31) >> 5;
while (*p++ == allones) while (!(num = ~*p++)) {
{ if (!--size)
if (--size == 0) goto out;
return (p - addr) << 5;
} }
num = ~*--p;
__asm__ __volatile__ ("bfffo %1{#0,#0},%0" __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
: "=d" (res) : "d" (num & -num)); : "=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, static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
int offset) int offset)
{ {
const unsigned long *addr = vaddr; const unsigned long *p = vaddr + (offset >> 5);
const unsigned long *p = addr + (offset >> 5); int bit = offset & 31UL, res;
int set = 0, bit = offset & 31UL, res;
if (offset >= size) if (offset >= size)
return size; return size;
if (bit) { if (bit) {
unsigned long num = ~*p & (~0UL << bit); unsigned long num = ~*p++ & (~0UL << bit);
offset -= bit;
/* Look for zero in first longword */ /* Look for zero in first longword */
__asm__ __volatile__ ("bfffo %1{#0,#0},%0" __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
: "=d" (res) : "d" (num & -num)); : "=d" (res) : "d" (num & -num));
if (res < 32) if (res < 32)
return (offset & ~31UL) + (res ^ 31); return offset + (res ^ 31);
set = 32 - bit; offset += 32;
p++;
} }
/* No zero yet, search remaining full bytes for a zero */ /* No zero yet, search remaining full bytes for a zero */
res = find_first_zero_bit (p, size - 32 * (p - addr)); res = find_first_zero_bit(p, size - ((long)p - (long)vaddr) * 8);
return (offset + set + res); 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;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment