diff options
Diffstat (limited to 'arch/mips/include/asm/bitops.h')
| -rw-r--r-- | arch/mips/include/asm/bitops.h | 114 |
1 files changed, 76 insertions, 38 deletions
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index 49df8c4c9d25..bac4a960b24c 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h | |||
| @@ -558,39 +558,67 @@ static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long * | |||
| 558 | __clear_bit(nr, addr); | 558 | __clear_bit(nr, addr); |
| 559 | } | 559 | } |
| 560 | 560 | ||
| 561 | #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) | ||
| 562 | |||
| 563 | /* | 561 | /* |
| 564 | * Return the bit position (0..63) of the most significant 1 bit in a word | 562 | * Return the bit position (0..63) of the most significant 1 bit in a word |
| 565 | * Returns -1 if no 1 bit exists | 563 | * Returns -1 if no 1 bit exists |
| 566 | */ | 564 | */ |
| 567 | static inline unsigned long __fls(unsigned long x) | 565 | static inline unsigned long __fls(unsigned long word) |
| 568 | { | 566 | { |
| 569 | int lz; | 567 | int num; |
| 570 | 568 | ||
| 571 | if (sizeof(x) == 4) { | 569 | if (BITS_PER_LONG == 32 && |
| 570 | __builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r) { | ||
| 572 | __asm__( | 571 | __asm__( |
| 573 | " .set push \n" | 572 | " .set push \n" |
| 574 | " .set mips32 \n" | 573 | " .set mips32 \n" |
| 575 | " clz %0, %1 \n" | 574 | " clz %0, %1 \n" |
| 576 | " .set pop \n" | 575 | " .set pop \n" |
| 577 | : "=r" (lz) | 576 | : "=r" (num) |
| 578 | : "r" (x)); | 577 | : "r" (word)); |
| 579 | 578 | ||
| 580 | return 31 - lz; | 579 | return 31 - num; |
| 581 | } | 580 | } |
| 582 | 581 | ||
| 583 | BUG_ON(sizeof(x) != 8); | 582 | if (BITS_PER_LONG == 64 && |
| 583 | __builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) { | ||
| 584 | __asm__( | ||
| 585 | " .set push \n" | ||
| 586 | " .set mips64 \n" | ||
| 587 | " dclz %0, %1 \n" | ||
| 588 | " .set pop \n" | ||
| 589 | : "=r" (num) | ||
| 590 | : "r" (word)); | ||
| 584 | 591 | ||
| 585 | __asm__( | 592 | return 63 - num; |
| 586 | " .set push \n" | 593 | } |
| 587 | " .set mips64 \n" | 594 | |
| 588 | " dclz %0, %1 \n" | 595 | num = BITS_PER_LONG - 1; |
| 589 | " .set pop \n" | ||
| 590 | : "=r" (lz) | ||
| 591 | : "r" (x)); | ||
| 592 | 596 | ||
| 593 | return 63 - lz; | 597 | #if BITS_PER_LONG == 64 |
| 598 | if (!(word & (~0ul << 32))) { | ||
| 599 | num -= 32; | ||
| 600 | word <<= 32; | ||
| 601 | } | ||
| 602 | #endif | ||
| 603 | if (!(word & (~0ul << (BITS_PER_LONG-16)))) { | ||
| 604 | num -= 16; | ||
| 605 | word <<= 16; | ||
| 606 | } | ||
| 607 | if (!(word & (~0ul << (BITS_PER_LONG-8)))) { | ||
| 608 | num -= 8; | ||
| 609 | word <<= 8; | ||
| 610 | } | ||
| 611 | if (!(word & (~0ul << (BITS_PER_LONG-4)))) { | ||
| 612 | num -= 4; | ||
| 613 | word <<= 4; | ||
| 614 | } | ||
| 615 | if (!(word & (~0ul << (BITS_PER_LONG-2)))) { | ||
| 616 | num -= 2; | ||
| 617 | word <<= 2; | ||
| 618 | } | ||
| 619 | if (!(word & (~0ul << (BITS_PER_LONG-1)))) | ||
| 620 | num -= 1; | ||
| 621 | return num; | ||
| 594 | } | 622 | } |
| 595 | 623 | ||
| 596 | /* | 624 | /* |
| @@ -612,23 +640,43 @@ static inline unsigned long __ffs(unsigned long word) | |||
| 612 | * This is defined the same way as ffs. | 640 | * This is defined the same way as ffs. |
| 613 | * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. | 641 | * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. |
| 614 | */ | 642 | */ |
| 615 | static inline int fls(int word) | 643 | static inline int fls(int x) |
| 616 | { | 644 | { |
| 617 | __asm__("clz %0, %1" : "=r" (word) : "r" (word)); | 645 | int r; |
| 618 | 646 | ||
| 619 | return 32 - word; | 647 | if (__builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r) { |
| 620 | } | 648 | __asm__("clz %0, %1" : "=r" (x) : "r" (x)); |
| 621 | 649 | ||
| 622 | #if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPS64) | 650 | return 32 - x; |
| 623 | static inline int fls64(__u64 word) | 651 | } |
| 624 | { | ||
| 625 | __asm__("dclz %0, %1" : "=r" (word) : "r" (word)); | ||
| 626 | 652 | ||
| 627 | return 64 - word; | 653 | r = 32; |
| 654 | if (!x) | ||
| 655 | return 0; | ||
| 656 | if (!(x & 0xffff0000u)) { | ||
| 657 | x <<= 16; | ||
| 658 | r -= 16; | ||
| 659 | } | ||
| 660 | if (!(x & 0xff000000u)) { | ||
| 661 | x <<= 8; | ||
| 662 | r -= 8; | ||
| 663 | } | ||
| 664 | if (!(x & 0xf0000000u)) { | ||
| 665 | x <<= 4; | ||
| 666 | r -= 4; | ||
| 667 | } | ||
| 668 | if (!(x & 0xc0000000u)) { | ||
| 669 | x <<= 2; | ||
| 670 | r -= 2; | ||
| 671 | } | ||
| 672 | if (!(x & 0x80000000u)) { | ||
| 673 | x <<= 1; | ||
| 674 | r -= 1; | ||
| 675 | } | ||
| 676 | return r; | ||
| 628 | } | 677 | } |
| 629 | #else | 678 | |
| 630 | #include <asm-generic/bitops/fls64.h> | 679 | #include <asm-generic/bitops/fls64.h> |
| 631 | #endif | ||
| 632 | 680 | ||
| 633 | /* | 681 | /* |
| 634 | * ffs - find first bit set. | 682 | * ffs - find first bit set. |
| @@ -646,16 +694,6 @@ static inline int ffs(int word) | |||
| 646 | return fls(word & -word); | 694 | return fls(word & -word); |
| 647 | } | 695 | } |
| 648 | 696 | ||
| 649 | #else | ||
| 650 | |||
| 651 | #include <asm-generic/bitops/__ffs.h> | ||
| 652 | #include <asm-generic/bitops/__fls.h> | ||
| 653 | #include <asm-generic/bitops/ffs.h> | ||
| 654 | #include <asm-generic/bitops/fls.h> | ||
| 655 | #include <asm-generic/bitops/fls64.h> | ||
| 656 | |||
| 657 | #endif /*defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) */ | ||
| 658 | |||
| 659 | #include <asm-generic/bitops/ffz.h> | 697 | #include <asm-generic/bitops/ffz.h> |
| 660 | #include <asm-generic/bitops/find.h> | 698 | #include <asm-generic/bitops/find.h> |
| 661 | 699 | ||
