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 9d69f6e62365..e9020f88a748 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, | |||
181 | { | 181 | { |
182 | const unsigned long *p = vaddr; | 182 | const unsigned long *p = vaddr; |
183 | int res = 32; | 183 | int res = 32; |
184 | unsigned int words; | ||
184 | unsigned long num; | 185 | unsigned long num; |
185 | 186 | ||
186 | if (!size) | 187 | if (!size) |
187 | return 0; | 188 | return 0; |
188 | 189 | ||
189 | size = (size + 31) >> 5; | 190 | words = (size + 31) >> 5; |
190 | while (!(num = ~*p++)) { | 191 | while (!(num = ~*p++)) { |
191 | if (!--size) | 192 | if (!--words) |
192 | goto out; | 193 | goto out; |
193 | } | 194 | } |
194 | 195 | ||
@@ -196,7 +197,8 @@ static inline int find_first_zero_bit(const unsigned long *vaddr, | |||
196 | : "=d" (res) : "d" (num & -num)); | 197 | : "=d" (res) : "d" (num & -num)); |
197 | res ^= 31; | 198 | res ^= 31; |
198 | out: | 199 | out: |
199 | return ((long)p - (long)vaddr - 4) * 8 + res; | 200 | res += ((long)p - (long)vaddr - 4) * 8; |
201 | return res < size ? res : size; | ||
200 | } | 202 | } |
201 | 203 | ||
202 | static inline int find_next_zero_bit(const unsigned long *vaddr, int size, | 204 | 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, | |||
215 | /* Look for zero in first longword */ | 217 | /* Look for zero in first longword */ |
216 | __asm__ __volatile__ ("bfffo %1{#0,#0},%0" | 218 | __asm__ __volatile__ ("bfffo %1{#0,#0},%0" |
217 | : "=d" (res) : "d" (num & -num)); | 219 | : "=d" (res) : "d" (num & -num)); |
218 | if (res < 32) | 220 | if (res < 32) { |
219 | return offset + (res ^ 31); | 221 | offset += res ^ 31; |
222 | return offset < size ? offset : size; | ||
223 | } | ||
220 | offset += 32; | 224 | offset += 32; |
225 | |||
226 | if (offset >= size) | ||
227 | return size; | ||
221 | } | 228 | } |
222 | /* No zero yet, search remaining full bytes for a zero */ | 229 | /* No zero yet, search remaining full bytes for a zero */ |
223 | res = find_first_zero_bit(p, size - ((long)p - (long)vaddr) * 8); | 230 | return offset + find_first_zero_bit(p, size - offset); |
224 | return offset + res; | ||
225 | } | 231 | } |
226 | 232 | ||
227 | static inline int find_first_bit(const unsigned long *vaddr, unsigned size) | 233 | static inline int find_first_bit(const unsigned long *vaddr, unsigned size) |
228 | { | 234 | { |
229 | const unsigned long *p = vaddr; | 235 | const unsigned long *p = vaddr; |
230 | int res = 32; | 236 | int res = 32; |
237 | unsigned int words; | ||
231 | unsigned long num; | 238 | unsigned long num; |
232 | 239 | ||
233 | if (!size) | 240 | if (!size) |
234 | return 0; | 241 | return 0; |
235 | 242 | ||
236 | size = (size + 31) >> 5; | 243 | words = (size + 31) >> 5; |
237 | while (!(num = *p++)) { | 244 | while (!(num = *p++)) { |
238 | if (!--size) | 245 | if (!--words) |
239 | goto out; | 246 | goto out; |
240 | } | 247 | } |
241 | 248 | ||
@@ -243,7 +250,8 @@ static inline int find_first_bit(const unsigned long *vaddr, unsigned size) | |||
243 | : "=d" (res) : "d" (num & -num)); | 250 | : "=d" (res) : "d" (num & -num)); |
244 | res ^= 31; | 251 | res ^= 31; |
245 | out: | 252 | out: |
246 | return ((long)p - (long)vaddr - 4) * 8 + res; | 253 | res += ((long)p - (long)vaddr - 4) * 8; |
254 | return res < size ? res : size; | ||
247 | } | 255 | } |
248 | 256 | ||
249 | static inline int find_next_bit(const unsigned long *vaddr, int size, | 257 | 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, | |||
262 | /* Look for one in first longword */ | 270 | /* Look for one in first longword */ |
263 | __asm__ __volatile__ ("bfffo %1{#0,#0},%0" | 271 | __asm__ __volatile__ ("bfffo %1{#0,#0},%0" |
264 | : "=d" (res) : "d" (num & -num)); | 272 | : "=d" (res) : "d" (num & -num)); |
265 | if (res < 32) | 273 | if (res < 32) { |
266 | return offset + (res ^ 31); | 274 | offset += res ^ 31; |
275 | return offset < size ? offset : size; | ||
276 | } | ||
267 | offset += 32; | 277 | offset += 32; |
278 | |||
279 | if (offset >= size) | ||
280 | return size; | ||
268 | } | 281 | } |
269 | /* No one yet, search remaining full bytes for a one */ | 282 | /* No one yet, search remaining full bytes for a one */ |
270 | res = find_first_bit(p, size - ((long)p - (long)vaddr) * 8); | 283 | return offset + find_first_bit(p, size - offset); |
271 | return offset + res; | ||
272 | } | 284 | } |
273 | 285 | ||
274 | /* | 286 | /* |
@@ -366,23 +378,25 @@ static inline int test_bit_le(int nr, const void *vaddr) | |||
366 | static inline int find_first_zero_bit_le(const void *vaddr, unsigned size) | 378 | static inline int find_first_zero_bit_le(const void *vaddr, unsigned size) |
367 | { | 379 | { |
368 | const unsigned long *p = vaddr, *addr = vaddr; | 380 | const unsigned long *p = vaddr, *addr = vaddr; |
369 | int res; | 381 | int res = 0; |
382 | unsigned int words; | ||
370 | 383 | ||
371 | if (!size) | 384 | if (!size) |
372 | return 0; | 385 | return 0; |
373 | 386 | ||
374 | size = (size >> 5) + ((size & 31) > 0); | 387 | words = (size >> 5) + ((size & 31) > 0); |
375 | while (*p++ == ~0UL) | 388 | while (*p++ == ~0UL) { |
376 | { | 389 | if (--words == 0) |
377 | if (--size == 0) | 390 | goto out; |
378 | return (p - addr) << 5; | ||
379 | } | 391 | } |
380 | 392 | ||
381 | --p; | 393 | --p; |
382 | for (res = 0; res < 32; res++) | 394 | for (res = 0; res < 32; res++) |
383 | if (!test_bit_le(res, p)) | 395 | if (!test_bit_le(res, p)) |
384 | break; | 396 | break; |
385 | return (p - addr) * 32 + res; | 397 | out: |
398 | res += (p - addr) * 32; | ||
399 | return res < size ? res : size; | ||
386 | } | 400 | } |
387 | 401 | ||
388 | static inline unsigned long find_next_zero_bit_le(const void *addr, | 402 | 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, | |||
400 | offset -= bit; | 414 | offset -= bit; |
401 | /* Look for zero in first longword */ | 415 | /* Look for zero in first longword */ |
402 | for (res = bit; res < 32; res++) | 416 | for (res = bit; res < 32; res++) |
403 | if (!test_bit_le(res, p)) | 417 | if (!test_bit_le(res, p)) { |
404 | return offset + res; | 418 | offset += res; |
419 | return offset < size ? offset : size; | ||
420 | } | ||
405 | p++; | 421 | p++; |
406 | offset += 32; | 422 | offset += 32; |
423 | |||
424 | if (offset >= size) | ||
425 | return size; | ||
407 | } | 426 | } |
408 | /* No zero yet, search remaining full bytes for a zero */ | 427 | /* No zero yet, search remaining full bytes for a zero */ |
409 | return offset + find_first_zero_bit_le(p, size - offset); | 428 | 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, | |||
412 | static inline int find_first_bit_le(const void *vaddr, unsigned size) | 431 | static inline int find_first_bit_le(const void *vaddr, unsigned size) |
413 | { | 432 | { |
414 | const unsigned long *p = vaddr, *addr = vaddr; | 433 | const unsigned long *p = vaddr, *addr = vaddr; |
415 | int res; | 434 | int res = 0; |
435 | unsigned int words; | ||
416 | 436 | ||
417 | if (!size) | 437 | if (!size) |
418 | return 0; | 438 | return 0; |
419 | 439 | ||
420 | size = (size >> 5) + ((size & 31) > 0); | 440 | words = (size >> 5) + ((size & 31) > 0); |
421 | while (*p++ == 0UL) { | 441 | while (*p++ == 0UL) { |
422 | if (--size == 0) | 442 | if (--words == 0) |
423 | return (p - addr) << 5; | 443 | goto out; |
424 | } | 444 | } |
425 | 445 | ||
426 | --p; | 446 | --p; |
427 | for (res = 0; res < 32; res++) | 447 | for (res = 0; res < 32; res++) |
428 | if (test_bit_le(res, p)) | 448 | if (test_bit_le(res, p)) |
429 | break; | 449 | break; |
430 | return (p - addr) * 32 + res; | 450 | out: |
451 | res += (p - addr) * 32; | ||
452 | return res < size ? res : size; | ||
431 | } | 453 | } |
432 | 454 | ||
433 | static inline unsigned long find_next_bit_le(const void *addr, | 455 | 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, | |||
445 | offset -= bit; | 467 | offset -= bit; |
446 | /* Look for one in first longword */ | 468 | /* Look for one in first longword */ |
447 | for (res = bit; res < 32; res++) | 469 | for (res = bit; res < 32; res++) |
448 | if (test_bit_le(res, p)) | 470 | if (test_bit_le(res, p)) { |
449 | return offset + res; | 471 | offset += res; |
472 | return offset < size ? offset : size; | ||
473 | } | ||
450 | p++; | 474 | p++; |
451 | offset += 32; | 475 | offset += 32; |
476 | |||
477 | if (offset >= size) | ||
478 | return size; | ||
452 | } | 479 | } |
453 | /* No set bit yet, search remaining full bytes for a set bit */ | 480 | /* No set bit yet, search remaining full bytes for a set bit */ |
454 | return offset + find_first_bit_le(p, size - offset); | 481 | return offset + find_first_bit_le(p, size - offset); |