diff options
| author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-02-05 10:50:43 -0500 | 
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-02-05 10:50:58 -0500 | 
| commit | 0abbf05cdd69d74f92628bf444cd210ba046f6eb (patch) | |
| tree | 369550d01b22fc9a68d07652513e532b97ec8975 | |
| parent | b6b40c532a36f91df9c21caf9baba3b635e99d4e (diff) | |
[S390] Cleanup & optimize bitops.
The bitops header is now a bit shorter and easier to understand since
it uses less inline assembly. It requires some tricks to persuade the
compiler to generate decent code. The ffz/ffs functions now use the
_zb_findmap/_sb_findmap table as well.
With this cleanup the new bitops for ext4 can be implemented with a
few lines, instead of another large inline assembly.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
| -rw-r--r-- | include/asm-s390/bitops.h | 515 | 
1 files changed, 219 insertions, 296 deletions
| diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index dba6fecad0be..95d93955a9bb 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h | |||
| @@ -440,242 +440,256 @@ __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) { | |||
| 440 | __test_bit((nr),(addr)) ) | 440 | __test_bit((nr),(addr)) ) | 
| 441 | 441 | ||
| 442 | /* | 442 | /* | 
| 443 | * ffz = Find First Zero in word. Undefined if no zero exists, | 443 | * Optimized find bit helper functions. | 
| 444 | * so code should check against ~0UL first.. | ||
| 445 | */ | 444 | */ | 
| 446 | static inline unsigned long ffz(unsigned long word) | 445 | |
| 446 | /** | ||
| 447 | * __ffz_word_loop - find byte offset of first long != -1UL | ||
| 448 | * @addr: pointer to array of unsigned long | ||
| 449 | * @size: size of the array in bits | ||
| 450 | */ | ||
| 451 | static inline unsigned long __ffz_word_loop(const unsigned long *addr, | ||
| 452 | unsigned long size) | ||
| 453 | { | ||
| 454 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | ||
| 455 | unsigned long bytes = 0; | ||
| 456 | |||
| 457 | asm volatile( | ||
| 458 | #ifndef __s390x__ | ||
| 459 | " ahi %1,31\n" | ||
| 460 | " srl %1,5\n" | ||
| 461 | "0: c %2,0(%0,%3)\n" | ||
| 462 | " jne 1f\n" | ||
| 463 | " la %0,4(%0)\n" | ||
| 464 | " brct %1,0b\n" | ||
| 465 | "1:\n" | ||
| 466 | #else | ||
| 467 | " aghi %1,63\n" | ||
| 468 | " srlg %1,%1,6\n" | ||
| 469 | "0: cg %2,0(%0,%3)\n" | ||
| 470 | " jne 1f\n" | ||
| 471 | " la %0,8(%0)\n" | ||
| 472 | " brct %1,0b\n" | ||
| 473 | "1:\n" | ||
| 474 | #endif | ||
| 475 | : "+a" (bytes), "+d" (size) | ||
| 476 | : "d" (-1UL), "a" (addr), "m" (*(addrtype *) addr) | ||
| 477 | : "cc" ); | ||
| 478 | return bytes; | ||
| 479 | } | ||
| 480 | |||
| 481 | /** | ||
| 482 | * __ffs_word_loop - find byte offset of first long != 0UL | ||
| 483 | * @addr: pointer to array of unsigned long | ||
| 484 | * @size: size of the array in bits | ||
| 485 | */ | ||
| 486 | static inline unsigned long __ffs_word_loop(const unsigned long *addr, | ||
| 487 | unsigned long size) | ||
| 447 | { | 488 | { | 
| 448 | unsigned long bit = 0; | 489 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | 
| 490 | unsigned long bytes = 0; | ||
| 449 | 491 | ||
| 492 | asm volatile( | ||
| 493 | #ifndef __s390x__ | ||
| 494 | " ahi %1,31\n" | ||
| 495 | " srl %1,5\n" | ||
| 496 | "0: c %2,0(%0,%3)\n" | ||
| 497 | " jne 1f\n" | ||
| 498 | " la %0,4(%0)\n" | ||
| 499 | " brct %1,0b\n" | ||
| 500 | "1:\n" | ||
| 501 | #else | ||
| 502 | " aghi %1,63\n" | ||
| 503 | " srlg %1,%1,6\n" | ||
| 504 | "0: cg %2,0(%0,%3)\n" | ||
| 505 | " jne 1f\n" | ||
| 506 | " la %0,8(%0)\n" | ||
| 507 | " brct %1,0b\n" | ||
| 508 | "1:\n" | ||
| 509 | #endif | ||
| 510 | : "+a" (bytes), "+a" (size) | ||
| 511 | : "d" (0UL), "a" (addr), "m" (*(addrtype *) addr) | ||
| 512 | : "cc" ); | ||
| 513 | return bytes; | ||
| 514 | } | ||
| 515 | |||
| 516 | /** | ||
| 517 | * __ffz_word - add number of the first unset bit | ||
| 518 | * @nr: base value the bit number is added to | ||
| 519 | * @word: the word that is searched for unset bits | ||
| 520 | */ | ||
| 521 | static inline unsigned long __ffz_word(unsigned long nr, unsigned long word) | ||
| 522 | { | ||
| 450 | #ifdef __s390x__ | 523 | #ifdef __s390x__ | 
| 451 | if (likely((word & 0xffffffff) == 0xffffffff)) { | 524 | if (likely((word & 0xffffffff) == 0xffffffff)) { | 
| 452 | word >>= 32; | 525 | word >>= 32; | 
| 453 | bit += 32; | 526 | nr += 32; | 
| 454 | } | 527 | } | 
| 455 | #endif | 528 | #endif | 
| 456 | if (likely((word & 0xffff) == 0xffff)) { | 529 | if (likely((word & 0xffff) == 0xffff)) { | 
| 457 | word >>= 16; | 530 | word >>= 16; | 
| 458 | bit += 16; | 531 | nr += 16; | 
| 459 | } | 532 | } | 
| 460 | if (likely((word & 0xff) == 0xff)) { | 533 | if (likely((word & 0xff) == 0xff)) { | 
| 461 | word >>= 8; | 534 | word >>= 8; | 
| 462 | bit += 8; | 535 | nr += 8; | 
| 463 | } | 536 | } | 
| 464 | return bit + _zb_findmap[word & 0xff]; | 537 | return nr + _zb_findmap[(unsigned char) word]; | 
| 465 | } | 538 | } | 
| 466 | 539 | ||
| 467 | /* | 540 | /** | 
| 468 | * __ffs = find first bit in word. Undefined if no bit exists, | 541 | * __ffs_word - add number of the first set bit | 
| 469 | * so code should check against 0UL first.. | 542 | * @nr: base value the bit number is added to | 
| 543 | * @word: the word that is searched for set bits | ||
| 470 | */ | 544 | */ | 
| 471 | static inline unsigned long __ffs (unsigned long word) | 545 | static inline unsigned long __ffs_word(unsigned long nr, unsigned long word) | 
| 472 | { | 546 | { | 
| 473 | unsigned long bit = 0; | ||
| 474 | |||
| 475 | #ifdef __s390x__ | 547 | #ifdef __s390x__ | 
| 476 | if (likely((word & 0xffffffff) == 0)) { | 548 | if (likely((word & 0xffffffff) == 0)) { | 
| 477 | word >>= 32; | 549 | word >>= 32; | 
| 478 | bit += 32; | 550 | nr += 32; | 
| 479 | } | 551 | } | 
| 480 | #endif | 552 | #endif | 
| 481 | if (likely((word & 0xffff) == 0)) { | 553 | if (likely((word & 0xffff) == 0)) { | 
| 482 | word >>= 16; | 554 | word >>= 16; | 
| 483 | bit += 16; | 555 | nr += 16; | 
| 484 | } | 556 | } | 
| 485 | if (likely((word & 0xff) == 0)) { | 557 | if (likely((word & 0xff) == 0)) { | 
| 486 | word >>= 8; | 558 | word >>= 8; | 
| 487 | bit += 8; | 559 | nr += 8; | 
| 488 | } | 560 | } | 
| 489 | return bit + _sb_findmap[word & 0xff]; | 561 | return nr + _sb_findmap[(unsigned char) word]; | 
| 490 | } | 562 | } | 
| 491 | 563 | ||
| 492 | /* | ||
| 493 | * Find-bit routines.. | ||
| 494 | */ | ||
| 495 | 564 | ||
| 496 | #ifndef __s390x__ | 565 | /** | 
| 566 | * __load_ulong_be - load big endian unsigned long | ||
| 567 | * @p: pointer to array of unsigned long | ||
| 568 | * @offset: byte offset of source value in the array | ||
| 569 | */ | ||
| 570 | static inline unsigned long __load_ulong_be(const unsigned long *p, | ||
| 571 | unsigned long offset) | ||
| 572 | { | ||
| 573 | p = (unsigned long *)((unsigned long) p + offset); | ||
| 574 | return *p; | ||
| 575 | } | ||
| 497 | 576 | ||
| 498 | static inline int | 577 | /** | 
| 499 | find_first_zero_bit(const unsigned long * addr, unsigned long size) | 578 | * __load_ulong_le - load little endian unsigned long | 
| 579 | * @p: pointer to array of unsigned long | ||
| 580 | * @offset: byte offset of source value in the array | ||
| 581 | */ | ||
| 582 | static inline unsigned long __load_ulong_le(const unsigned long *p, | ||
| 583 | unsigned long offset) | ||
| 500 | { | 584 | { | 
| 501 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | 585 | unsigned long word; | 
| 502 | unsigned long cmp, count; | ||
| 503 | unsigned int res; | ||
| 504 | 586 | ||
| 505 | if (!size) | 587 | p = (unsigned long *)((unsigned long) p + offset); | 
| 506 | return 0; | 588 | #ifndef __s390x__ | 
| 507 | asm volatile( | 589 | asm volatile( | 
| 508 | " lhi %1,-1\n" | 590 | " ic %0,0(%1)\n" | 
| 509 | " lr %2,%3\n" | 591 | " icm %0,2,1(%1)\n" | 
| 510 | " slr %0,%0\n" | 592 | " icm %0,4,2(%1)\n" | 
| 511 | " ahi %2,31\n" | 593 | " icm %0,8,3(%1)" | 
| 512 | " srl %2,5\n" | 594 | : "=&d" (word) : "a" (p), "m" (*p) : "cc"); | 
| 513 | "0: c %1,0(%0,%4)\n" | 595 | #else | 
| 514 | " jne 1f\n" | 596 | asm volatile( | 
| 515 | " la %0,4(%0)\n" | 597 | " lrvg %0,%1" | 
| 516 | " brct %2,0b\n" | 598 | : "=d" (word) : "m" (*p) ); | 
| 517 | " lr %0,%3\n" | 599 | #endif | 
| 518 | " j 4f\n" | 600 | return word; | 
| 519 | "1: l %2,0(%0,%4)\n" | ||
| 520 | " sll %0,3\n" | ||
| 521 | " lhi %1,0xff\n" | ||
| 522 | " tml %2,0xffff\n" | ||
| 523 | " jno 2f\n" | ||
| 524 | " ahi %0,16\n" | ||
| 525 | " srl %2,16\n" | ||
| 526 | "2: tml %2,0x00ff\n" | ||
| 527 | " jno 3f\n" | ||
| 528 | " ahi %0,8\n" | ||
| 529 | " srl %2,8\n" | ||
| 530 | "3: nr %2,%1\n" | ||
| 531 | " ic %2,0(%2,%5)\n" | ||
| 532 | " alr %0,%2\n" | ||
| 533 | "4:" | ||
| 534 | : "=&a" (res), "=&d" (cmp), "=&a" (count) | ||
| 535 | : "a" (size), "a" (addr), "a" (&_zb_findmap), | ||
| 536 | "m" (*(addrtype *) addr) : "cc"); | ||
| 537 | return (res < size) ? res : size; | ||
| 538 | } | 601 | } | 
| 539 | 602 | ||
| 540 | static inline int | 603 | /* | 
| 541 | find_first_bit(const unsigned long * addr, unsigned long size) | 604 | * The various find bit functions. | 
| 605 | */ | ||
| 606 | |||
| 607 | /* | ||
| 608 | * ffz - find first zero in word. | ||
| 609 | * @word: The word to search | ||
| 610 | * | ||
| 611 | * Undefined if no zero exists, so code should check against ~0UL first. | ||
| 612 | */ | ||
| 613 | static inline unsigned long ffz(unsigned long word) | ||
| 542 | { | 614 | { | 
| 543 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | 615 | return __ffz_word(0, word); | 
| 544 | unsigned long cmp, count; | 616 | } | 
| 545 | unsigned int res; | ||
| 546 | 617 | ||
| 547 | if (!size) | 618 | /** | 
| 548 | return 0; | 619 | * __ffs - find first bit in word. | 
| 549 | asm volatile( | 620 | * @word: The word to search | 
| 550 | " slr %1,%1\n" | 621 | * | 
| 551 | " lr %2,%3\n" | 622 | * Undefined if no bit exists, so code should check against 0 first. | 
| 552 | " slr %0,%0\n" | 623 | */ | 
| 553 | " ahi %2,31\n" | 624 | static inline unsigned long __ffs (unsigned long word) | 
| 554 | " srl %2,5\n" | 625 | { | 
| 555 | "0: c %1,0(%0,%4)\n" | 626 | return __ffs_word(0, word); | 
| 556 | " jne 1f\n" | ||
| 557 | " la %0,4(%0)\n" | ||
| 558 | " brct %2,0b\n" | ||
| 559 | " lr %0,%3\n" | ||
| 560 | " j 4f\n" | ||
| 561 | "1: l %2,0(%0,%4)\n" | ||
| 562 | " sll %0,3\n" | ||
| 563 | " lhi %1,0xff\n" | ||
| 564 | " tml %2,0xffff\n" | ||
| 565 | " jnz 2f\n" | ||
| 566 | " ahi %0,16\n" | ||
| 567 | " srl %2,16\n" | ||
| 568 | "2: tml %2,0x00ff\n" | ||
| 569 | " jnz 3f\n" | ||
| 570 | " ahi %0,8\n" | ||
| 571 | " srl %2,8\n" | ||
| 572 | "3: nr %2,%1\n" | ||
| 573 | " ic %2,0(%2,%5)\n" | ||
| 574 | " alr %0,%2\n" | ||
| 575 | "4:" | ||
| 576 | : "=&a" (res), "=&d" (cmp), "=&a" (count) | ||
| 577 | : "a" (size), "a" (addr), "a" (&_sb_findmap), | ||
| 578 | "m" (*(addrtype *) addr) : "cc"); | ||
| 579 | return (res < size) ? res : size; | ||
| 580 | } | 627 | } | 
| 581 | 628 | ||
| 582 | #else /* __s390x__ */ | 629 | /** | 
| 630 | * ffs - find first bit set | ||
| 631 | * @x: the word to search | ||
| 632 | * | ||
| 633 | * This is defined the same way as | ||
| 634 | * the libc and compiler builtin ffs routines, therefore | ||
| 635 | * differs in spirit from the above ffz (man ffs). | ||
| 636 | */ | ||
| 637 | static inline int ffs(int x) | ||
| 638 | { | ||
| 639 | if (!x) | ||
| 640 | return 0; | ||
| 641 | return __ffs_word(1, x); | ||
| 642 | } | ||
| 583 | 643 | ||
| 584 | static inline unsigned long | 644 | /** | 
| 585 | find_first_zero_bit(const unsigned long * addr, unsigned long size) | 645 | * find_first_zero_bit - find the first zero bit in a memory region | 
| 646 | * @addr: The address to start the search at | ||
| 647 | * @size: The maximum size to search | ||
| 648 | * | ||
| 649 | * Returns the bit-number of the first zero bit, not the number of the byte | ||
| 650 | * containing a bit. | ||
| 651 | */ | ||
| 652 | static inline unsigned long find_first_zero_bit(const unsigned long *addr, | ||
| 653 | unsigned long size) | ||
| 586 | { | 654 | { | 
| 587 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | 655 | unsigned long bytes, bits; | 
| 588 | unsigned long res, cmp, count; | ||
| 589 | 656 | ||
| 590 | if (!size) | 657 | if (!size) | 
| 591 | return 0; | 658 | return 0; | 
| 592 | asm volatile( | 659 | bytes = __ffz_word_loop(addr, size); | 
| 593 | " lghi %1,-1\n" | 660 | bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes)); | 
| 594 | " lgr %2,%3\n" | 661 | return (bits < size) ? bits : size; | 
| 595 | " slgr %0,%0\n" | 662 | } | 
| 596 | " aghi %2,63\n" | 663 | |
| 597 | " srlg %2,%2,6\n" | 664 | /** | 
| 598 | "0: cg %1,0(%0,%4)\n" | 665 | * find_first_bit - find the first set bit in a memory region | 
| 599 | " jne 1f\n" | 666 | * @addr: The address to start the search at | 
| 600 | " la %0,8(%0)\n" | 667 | * @size: The maximum size to search | 
| 601 | " brct %2,0b\n" | 668 | * | 
| 602 | " lgr %0,%3\n" | 669 | * Returns the bit-number of the first set bit, not the number of the byte | 
| 603 | " j 5f\n" | 670 | * containing a bit. | 
| 604 | "1: lg %2,0(%0,%4)\n" | 671 | */ | 
| 605 | " sllg %0,%0,3\n" | 672 | static inline unsigned long find_first_bit(const unsigned long * addr, | 
| 606 | " clr %2,%1\n" | 673 | unsigned long size) | 
| 607 | " jne 2f\n" | ||
| 608 | " aghi %0,32\n" | ||
| 609 | " srlg %2,%2,32\n" | ||
| 610 | "2: lghi %1,0xff\n" | ||
| 611 | " tmll %2,0xffff\n" | ||
| 612 | " jno 3f\n" | ||
| 613 | " aghi %0,16\n" | ||
| 614 | " srl %2,16\n" | ||
| 615 | "3: tmll %2,0x00ff\n" | ||
| 616 | " jno 4f\n" | ||
| 617 | " aghi %0,8\n" | ||
| 618 | " srl %2,8\n" | ||
| 619 | "4: ngr %2,%1\n" | ||
| 620 | " ic %2,0(%2,%5)\n" | ||
| 621 | " algr %0,%2\n" | ||
| 622 | "5:" | ||
| 623 | : "=&a" (res), "=&d" (cmp), "=&a" (count) | ||
| 624 | : "a" (size), "a" (addr), "a" (&_zb_findmap), | ||
| 625 | "m" (*(addrtype *) addr) : "cc"); | ||
| 626 | return (res < size) ? res : size; | ||
| 627 | } | ||
| 628 | |||
| 629 | static inline unsigned long | ||
| 630 | find_first_bit(const unsigned long * addr, unsigned long size) | ||
| 631 | { | 674 | { | 
| 632 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | 675 | unsigned long bytes, bits; | 
| 633 | unsigned long res, cmp, count; | ||
| 634 | 676 | ||
| 635 | if (!size) | 677 | if (!size) | 
| 636 | return 0; | 678 | return 0; | 
| 637 | asm volatile( | 679 | bytes = __ffs_word_loop(addr, size); | 
| 638 | " slgr %1,%1\n" | 680 | bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes)); | 
| 639 | " lgr %2,%3\n" | 681 | return (bits < size) ? bits : size; | 
| 640 | " slgr %0,%0\n" | ||
| 641 | " aghi %2,63\n" | ||
| 642 | " srlg %2,%2,6\n" | ||
| 643 | "0: cg %1,0(%0,%4)\n" | ||
| 644 | " jne 1f\n" | ||
| 645 | " aghi %0,8\n" | ||
| 646 | " brct %2,0b\n" | ||
| 647 | " lgr %0,%3\n" | ||
| 648 | " j 5f\n" | ||
| 649 | "1: lg %2,0(%0,%4)\n" | ||
| 650 | " sllg %0,%0,3\n" | ||
| 651 | " clr %2,%1\n" | ||
| 652 | " jne 2f\n" | ||
| 653 | " aghi %0,32\n" | ||
| 654 | " srlg %2,%2,32\n" | ||
| 655 | "2: lghi %1,0xff\n" | ||
| 656 | " tmll %2,0xffff\n" | ||
| 657 | " jnz 3f\n" | ||
| 658 | " aghi %0,16\n" | ||
| 659 | " srl %2,16\n" | ||
| 660 | "3: tmll %2,0x00ff\n" | ||
| 661 | " jnz 4f\n" | ||
| 662 | " aghi %0,8\n" | ||
| 663 | " srl %2,8\n" | ||
| 664 | "4: ngr %2,%1\n" | ||
| 665 | " ic %2,0(%2,%5)\n" | ||
| 666 | " algr %0,%2\n" | ||
| 667 | "5:" | ||
| 668 | : "=&a" (res), "=&d" (cmp), "=&a" (count) | ||
| 669 | : "a" (size), "a" (addr), "a" (&_sb_findmap), | ||
| 670 | "m" (*(addrtype *) addr) : "cc"); | ||
| 671 | return (res < size) ? res : size; | ||
| 672 | } | 682 | } | 
| 673 | 683 | ||
| 674 | #endif /* __s390x__ */ | 684 | /** | 
| 675 | 685 | * find_next_zero_bit - find the first zero bit in a memory region | |
| 676 | static inline int | 686 | * @addr: The address to base the search on | 
| 677 | find_next_zero_bit (const unsigned long * addr, unsigned long size, | 687 | * @offset: The bitnumber to start searching at | 
| 678 | unsigned long offset) | 688 | * @size: The maximum size to search | 
| 689 | */ | ||
| 690 | static inline int find_next_zero_bit (const unsigned long * addr, | ||
| 691 | unsigned long size, | ||
| 692 | unsigned long offset) | ||
| 679 | { | 693 | { | 
| 680 | const unsigned long *p; | 694 | const unsigned long *p; | 
| 681 | unsigned long bit, set; | 695 | unsigned long bit, set; | 
| @@ -688,10 +702,10 @@ find_next_zero_bit (const unsigned long * addr, unsigned long size, | |||
| 688 | p = addr + offset / __BITOPS_WORDSIZE; | 702 | p = addr + offset / __BITOPS_WORDSIZE; | 
| 689 | if (bit) { | 703 | if (bit) { | 
| 690 | /* | 704 | /* | 
| 691 | * s390 version of ffz returns __BITOPS_WORDSIZE | 705 | * __ffz_word returns __BITOPS_WORDSIZE | 
| 692 | * if no zero bit is present in the word. | 706 | * if no zero bit is present in the word. | 
| 693 | */ | 707 | */ | 
| 694 | set = ffz(*p >> bit) + bit; | 708 | set = __ffz_word(0, *p >> bit) + bit; | 
| 695 | if (set >= size) | 709 | if (set >= size) | 
| 696 | return size + offset; | 710 | return size + offset; | 
| 697 | if (set < __BITOPS_WORDSIZE) | 711 | if (set < __BITOPS_WORDSIZE) | 
| @@ -703,9 +717,15 @@ find_next_zero_bit (const unsigned long * addr, unsigned long size, | |||
| 703 | return offset + find_first_zero_bit(p, size); | 717 | return offset + find_first_zero_bit(p, size); | 
| 704 | } | 718 | } | 
| 705 | 719 | ||
| 706 | static inline int | 720 | /** | 
| 707 | find_next_bit (const unsigned long * addr, unsigned long size, | 721 | * find_next_bit - find the first set bit in a memory region | 
| 708 | unsigned long offset) | 722 | * @addr: The address to base the search on | 
| 723 | * @offset: The bitnumber to start searching at | ||
| 724 | * @size: The maximum size to search | ||
| 725 | */ | ||
| 726 | static inline int find_next_bit (const unsigned long * addr, | ||
| 727 | unsigned long size, | ||
| 728 | unsigned long offset) | ||
| 709 | { | 729 | { | 
| 710 | const unsigned long *p; | 730 | const unsigned long *p; | 
| 711 | unsigned long bit, set; | 731 | unsigned long bit, set; | 
| @@ -718,10 +738,10 @@ find_next_bit (const unsigned long * addr, unsigned long size, | |||
| 718 | p = addr + offset / __BITOPS_WORDSIZE; | 738 | p = addr + offset / __BITOPS_WORDSIZE; | 
| 719 | if (bit) { | 739 | if (bit) { | 
| 720 | /* | 740 | /* | 
| 721 | * s390 version of __ffs returns __BITOPS_WORDSIZE | 741 | * __ffs_word returns __BITOPS_WORDSIZE | 
| 722 | * if no one bit is present in the word. | 742 | * if no one bit is present in the word. | 
| 723 | */ | 743 | */ | 
| 724 | set = __ffs(*p & (~0UL << bit)); | 744 | set = __ffs_word(0, *p & (~0UL << bit)); | 
| 725 | if (set >= size) | 745 | if (set >= size) | 
| 726 | return size + offset; | 746 | return size + offset; | 
| 727 | if (set < __BITOPS_WORDSIZE) | 747 | if (set < __BITOPS_WORDSIZE) | 
| @@ -744,8 +764,6 @@ static inline int sched_find_first_bit(unsigned long *b) | |||
| 744 | return find_first_bit(b, 140); | 764 | return find_first_bit(b, 140); | 
| 745 | } | 765 | } | 
| 746 | 766 | ||
| 747 | #include <asm-generic/bitops/ffs.h> | ||
| 748 | |||
| 749 | #include <asm-generic/bitops/fls.h> | 767 | #include <asm-generic/bitops/fls.h> | 
| 750 | #include <asm-generic/bitops/fls64.h> | 768 | #include <asm-generic/bitops/fls64.h> | 
| 751 | 769 | ||
| @@ -775,105 +793,22 @@ static inline int sched_find_first_bit(unsigned long *b) | |||
| 775 | #define ext2_find_next_bit(addr, size, off) \ | 793 | #define ext2_find_next_bit(addr, size, off) \ | 
| 776 | generic_find_next_le_bit((unsigned long *)(addr), (size), (off)) | 794 | generic_find_next_le_bit((unsigned long *)(addr), (size), (off)) | 
| 777 | 795 | ||
| 778 | #ifndef __s390x__ | 796 | static inline int ext2_find_first_zero_bit(void *vaddr, unsigned int size) | 
| 779 | |||
| 780 | static inline int | ||
| 781 | ext2_find_first_zero_bit(void *vaddr, unsigned int size) | ||
| 782 | { | 797 | { | 
| 783 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | 798 | unsigned long bytes, bits; | 
| 784 | unsigned long cmp, count; | ||
| 785 | unsigned int res; | ||
| 786 | 799 | ||
| 787 | if (!size) | 800 | if (!size) | 
| 788 | return 0; | 801 | return 0; | 
| 789 | asm volatile( | 802 | bytes = __ffz_word_loop(vaddr, size); | 
| 790 | " lhi %1,-1\n" | 803 | bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes)); | 
| 791 | " lr %2,%3\n" | 804 | return (bits < size) ? bits : size; | 
| 792 | " ahi %2,31\n" | ||
| 793 | " srl %2,5\n" | ||
| 794 | " slr %0,%0\n" | ||
| 795 | "0: cl %1,0(%0,%4)\n" | ||
| 796 | " jne 1f\n" | ||
| 797 | " ahi %0,4\n" | ||
| 798 | " brct %2,0b\n" | ||
| 799 | " lr %0,%3\n" | ||
| 800 | " j 4f\n" | ||
| 801 | "1: l %2,0(%0,%4)\n" | ||
| 802 | " sll %0,3\n" | ||
| 803 | " ahi %0,24\n" | ||
| 804 | " lhi %1,0xff\n" | ||
| 805 | " tmh %2,0xffff\n" | ||
| 806 | " jo 2f\n" | ||
| 807 | " ahi %0,-16\n" | ||
| 808 | " srl %2,16\n" | ||
| 809 | "2: tml %2,0xff00\n" | ||
| 810 | " jo 3f\n" | ||
| 811 | " ahi %0,-8\n" | ||
| 812 | " srl %2,8\n" | ||
| 813 | "3: nr %2,%1\n" | ||
| 814 | " ic %2,0(%2,%5)\n" | ||
| 815 | " alr %0,%2\n" | ||
| 816 | "4:" | ||
| 817 | : "=&a" (res), "=&d" (cmp), "=&a" (count) | ||
| 818 | : "a" (size), "a" (vaddr), "a" (&_zb_findmap), | ||
| 819 | "m" (*(addrtype *) vaddr) : "cc"); | ||
| 820 | return (res < size) ? res : size; | ||
| 821 | } | 805 | } | 
| 822 | 806 | ||
| 823 | #else /* __s390x__ */ | 807 | static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size, | 
| 824 | 808 | unsigned long offset) | |
| 825 | static inline unsigned long | ||
| 826 | ext2_find_first_zero_bit(void *vaddr, unsigned long size) | ||
| 827 | { | ||
| 828 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | ||
| 829 | unsigned long res, cmp, count; | ||
| 830 | |||
| 831 | if (!size) | ||
| 832 | return 0; | ||
| 833 | asm volatile( | ||
| 834 | " lghi %1,-1\n" | ||
| 835 | " lgr %2,%3\n" | ||
| 836 | " aghi %2,63\n" | ||
| 837 | " srlg %2,%2,6\n" | ||
| 838 | " slgr %0,%0\n" | ||
| 839 | "0: clg %1,0(%0,%4)\n" | ||
| 840 | " jne 1f\n" | ||
| 841 | " aghi %0,8\n" | ||
| 842 | " brct %2,0b\n" | ||
| 843 | " lgr %0,%3\n" | ||
| 844 | " j 5f\n" | ||
| 845 | "1: cl %1,0(%0,%4)\n" | ||
| 846 | " jne 2f\n" | ||
| 847 | " aghi %0,4\n" | ||
| 848 | "2: l %2,0(%0,%4)\n" | ||
| 849 | " sllg %0,%0,3\n" | ||
| 850 | " aghi %0,24\n" | ||
| 851 | " lghi %1,0xff\n" | ||
| 852 | " tmlh %2,0xffff\n" | ||
| 853 | " jo 3f\n" | ||
| 854 | " aghi %0,-16\n" | ||
| 855 | " srl %2,16\n" | ||
| 856 | "3: tmll %2,0xff00\n" | ||
| 857 | " jo 4f\n" | ||
| 858 | " aghi %0,-8\n" | ||
| 859 | " srl %2,8\n" | ||
| 860 | "4: ngr %2,%1\n" | ||
| 861 | " ic %2,0(%2,%5)\n" | ||
| 862 | " algr %0,%2\n" | ||
| 863 | "5:" | ||
| 864 | : "=&a" (res), "=&d" (cmp), "=&a" (count) | ||
| 865 | : "a" (size), "a" (vaddr), "a" (&_zb_findmap), | ||
| 866 | "m" (*(addrtype *) vaddr) : "cc"); | ||
| 867 | return (res < size) ? res : size; | ||
| 868 | } | ||
| 869 | |||
| 870 | #endif /* __s390x__ */ | ||
| 871 | |||
| 872 | static inline int | ||
| 873 | ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset) | ||
| 874 | { | 809 | { | 
| 875 | unsigned long *addr = vaddr, *p; | 810 | unsigned long *addr = vaddr, *p; | 
| 876 | unsigned long word, bit, set; | 811 | unsigned long bit, set; | 
| 877 | 812 | ||
| 878 | if (offset >= size) | 813 | if (offset >= size) | 
| 879 | return size; | 814 | return size; | 
| @@ -882,23 +817,11 @@ ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset) | |||
| 882 | size -= offset; | 817 | size -= offset; | 
| 883 | p = addr + offset / __BITOPS_WORDSIZE; | 818 | p = addr + offset / __BITOPS_WORDSIZE; | 
| 884 | if (bit) { | 819 | if (bit) { | 
| 885 | #ifndef __s390x__ | ||
| 886 | asm volatile( | ||
| 887 | " ic %0,0(%1)\n" | ||
| 888 | " icm %0,2,1(%1)\n" | ||
| 889 | " icm %0,4,2(%1)\n" | ||
| 890 | " icm %0,8,3(%1)" | ||
| 891 | : "=&a" (word) : "a" (p), "m" (*p) : "cc"); | ||
| 892 | #else | ||
| 893 | asm volatile( | ||
| 894 | " lrvg %0,%1" | ||
| 895 | : "=a" (word) : "m" (*p) ); | ||
| 896 | #endif | ||
| 897 | /* | 820 | /* | 
| 898 | * s390 version of ffz returns __BITOPS_WORDSIZE | 821 | * s390 version of ffz returns __BITOPS_WORDSIZE | 
| 899 | * if no zero bit is present in the word. | 822 | * if no zero bit is present in the word. | 
| 900 | */ | 823 | */ | 
| 901 | set = ffz(word >> bit) + bit; | 824 | set = ffz(__load_ulong_le(p, 0) >> bit) + bit; | 
| 902 | if (set >= size) | 825 | if (set >= size) | 
| 903 | return size + offset; | 826 | return size + offset; | 
| 904 | if (set < __BITOPS_WORDSIZE) | 827 | if (set < __BITOPS_WORDSIZE) | 
