diff options
Diffstat (limited to 'arch/m68k/include/asm/bitops_mm.h')
| -rw-r--r-- | arch/m68k/include/asm/bitops_mm.h | 87 | 
1 files changed, 57 insertions, 30 deletions
diff --git a/arch/m68k/include/asm/bitops_mm.h b/arch/m68k/include/asm/bitops_mm.h index 9d69f6e6236..e9020f88a74 100644 --- a/arch/m68k/include/asm/bitops_mm.h +++ b/arch/m68k/include/asm/bitops_mm.h @@ -181,14 +181,15 @@ static inline int find_first_zero_bit(const unsigned long *vaddr,  {  	const unsigned long *p = vaddr;  	int res = 32; +	unsigned int words;  	unsigned long num;  	if (!size)  		return 0; -	size = (size + 31) >> 5; +	words = (size + 31) >> 5;  	while (!(num = ~*p++)) { -		if (!--size) +		if (!--words)  			goto out;  	} @@ -196,7 +197,8 @@ static inline int find_first_zero_bit(const unsigned long *vaddr,  			      : "=d" (res) : "d" (num & -num));  	res ^= 31;  out: -	return ((long)p - (long)vaddr - 4) * 8 + res; +	res += ((long)p - (long)vaddr - 4) * 8; +	return res < size ? res : size;  }  static inline int find_next_zero_bit(const unsigned long *vaddr, int size, @@ -215,27 +217,32 @@ static inline int find_next_zero_bit(const unsigned long *vaddr, int size,  		/* Look for zero in first longword */  		__asm__ __volatile__ ("bfffo %1{#0,#0},%0"  				      : "=d" (res) : "d" (num & -num)); -		if (res < 32) -			return offset + (res ^ 31); +		if (res < 32) { +			offset += res ^ 31; +			return offset < size ? offset : size; +		}  		offset += 32; + +		if (offset >= size) +			return size;  	}  	/* No zero yet, search remaining full bytes for a zero */ -	res = find_first_zero_bit(p, size - ((long)p - (long)vaddr) * 8); -	return offset + res; +	return offset + find_first_zero_bit(p, size - offset);  }  static inline int find_first_bit(const unsigned long *vaddr, unsigned size)  {  	const unsigned long *p = vaddr;  	int res = 32; +	unsigned int words;  	unsigned long num;  	if (!size)  		return 0; -	size = (size + 31) >> 5; +	words = (size + 31) >> 5;  	while (!(num = *p++)) { -		if (!--size) +		if (!--words)  			goto out;  	} @@ -243,7 +250,8 @@ static inline int find_first_bit(const unsigned long *vaddr, unsigned size)  			      : "=d" (res) : "d" (num & -num));  	res ^= 31;  out: -	return ((long)p - (long)vaddr - 4) * 8 + res; +	res += ((long)p - (long)vaddr - 4) * 8; +	return res < size ? res : size;  }  static inline int find_next_bit(const unsigned long *vaddr, int size, @@ -262,13 +270,17 @@ static inline int find_next_bit(const unsigned long *vaddr, int size,  		/* 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); +		if (res < 32) { +			offset += res ^ 31; +			return offset < size ? offset : size; +		}  		offset += 32; + +		if (offset >= size) +			return size;  	}  	/* No one yet, search remaining full bytes for a one */ -	res = find_first_bit(p, size - ((long)p - (long)vaddr) * 8); -	return offset + res; +	return offset + find_first_bit(p, size - offset);  }  /* @@ -366,23 +378,25 @@ static inline int test_bit_le(int nr, const void *vaddr)  static inline int find_first_zero_bit_le(const void *vaddr, unsigned size)  {  	const unsigned long *p = vaddr, *addr = vaddr; -	int res; +	int res = 0; +	unsigned int words;  	if (!size)  		return 0; -	size = (size >> 5) + ((size & 31) > 0); -	while (*p++ == ~0UL) -	{ -		if (--size == 0) -			return (p - addr) << 5; +	words = (size >> 5) + ((size & 31) > 0); +	while (*p++ == ~0UL) { +		if (--words == 0) +			goto out;  	}  	--p;  	for (res = 0; res < 32; res++)  		if (!test_bit_le(res, p))  			break; -	return (p - addr) * 32 + res; +out: +	res += (p - addr) * 32; +	return res < size ? res : size;  }  static inline unsigned long find_next_zero_bit_le(const void *addr, @@ -400,10 +414,15 @@ static inline unsigned long find_next_zero_bit_le(const void *addr,  		offset -= bit;  		/* Look for zero in first longword */  		for (res = bit; res < 32; res++) -			if (!test_bit_le(res, p)) -				return offset + res; +			if (!test_bit_le(res, p)) { +				offset += res; +				return offset < size ? offset : size; +			}  		p++;  		offset += 32; + +		if (offset >= size) +			return size;  	}  	/* No zero yet, search remaining full bytes for a zero */  	return offset + find_first_zero_bit_le(p, size - offset); @@ -412,22 +431,25 @@ static inline unsigned long find_next_zero_bit_le(const void *addr,  static inline int find_first_bit_le(const void *vaddr, unsigned size)  {  	const unsigned long *p = vaddr, *addr = vaddr; -	int res; +	int res = 0; +	unsigned int words;  	if (!size)  		return 0; -	size = (size >> 5) + ((size & 31) > 0); +	words = (size >> 5) + ((size & 31) > 0);  	while (*p++ == 0UL) { -		if (--size == 0) -			return (p - addr) << 5; +		if (--words == 0) +			goto out;  	}  	--p;  	for (res = 0; res < 32; res++)  		if (test_bit_le(res, p))  			break; -	return (p - addr) * 32 + res; +out: +	res += (p - addr) * 32; +	return res < size ? res : size;  }  static inline unsigned long find_next_bit_le(const void *addr, @@ -445,10 +467,15 @@ static inline unsigned long find_next_bit_le(const void *addr,  		offset -= bit;  		/* Look for one in first longword */  		for (res = bit; res < 32; res++) -			if (test_bit_le(res, p)) -				return offset + res; +			if (test_bit_le(res, p)) { +				offset += res; +				return offset < size ? offset : size; +			}  		p++;  		offset += 32; + +		if (offset >= size) +			return size;  	}  	/* No set bit yet, search remaining full bytes for a set bit */  	return offset + find_first_bit_le(p, size - offset);  |