diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2005-07-12 08:50:30 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:31:43 -0400 |
commit | 6590326505e3f7b4b57793e84760e9920c3c56b4 (patch) | |
tree | 920ab56cb70895393e57b356c28d6eb37932c63f /include/asm-mips/bitops.h | |
parent | e5de3b468795e4c58a9f0702630d28707b3ae011 (diff) |
Use clz / dclz on MIPS32 / MIPS64 processors.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'include/asm-mips/bitops.h')
-rw-r--r-- | include/asm-mips/bitops.h | 137 |
1 files changed, 115 insertions, 22 deletions
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h index d9c02bd0b18e..2ba20730a3e5 100644 --- a/include/asm-mips/bitops.h +++ b/include/asm-mips/bitops.h | |||
@@ -546,17 +546,60 @@ static inline int test_bit(unsigned long nr, const volatile unsigned long *addr) | |||
546 | return 1UL & (addr[nr >> SZLONG_LOG] >> (nr & SZLONG_MASK)); | 546 | return 1UL & (addr[nr >> SZLONG_LOG] >> (nr & SZLONG_MASK)); |
547 | } | 547 | } |
548 | 548 | ||
549 | #ifdef CONFIG_CPU_MIPS32_R1 | ||
549 | /* | 550 | /* |
550 | * ffz - find first zero in word. | 551 | * Return the bit position (0..31) of the most significant 1 bit in a word |
552 | * Returns -1 if no 1 bit exists | ||
553 | */ | ||
554 | static __inline__ int __ilog2(unsigned long x) | ||
555 | { | ||
556 | int lz; | ||
557 | |||
558 | __asm__ ( | ||
559 | " .set push \n" | ||
560 | " .set mips32 \n" | ||
561 | " clz %0, %1 \n" | ||
562 | " .set pop \n" | ||
563 | : "=r" (lz) | ||
564 | : "r" (x)); | ||
565 | |||
566 | return 31 - lz; | ||
567 | } | ||
568 | #elif defined(CONFIG_CPU_MIPS64_R1) | ||
569 | /* | ||
570 | * Return the bit position (0..63) of the most significant 1 bit in a word | ||
571 | * Returns -1 if no 1 bit exists | ||
572 | */ | ||
573 | static __inline__ int __ilog2(unsigned long x) | ||
574 | { | ||
575 | int lz; | ||
576 | |||
577 | __asm__ ( | ||
578 | " .set push \n" | ||
579 | " .set mips64 \n" | ||
580 | " dclz %0, %1 \n" | ||
581 | " .set pop \n" | ||
582 | : "=r" (lz) | ||
583 | : "r" (x)); | ||
584 | |||
585 | return 63 - lz; | ||
586 | } | ||
587 | #endif | ||
588 | |||
589 | /* | ||
590 | * __ffs - find first bit in word. | ||
551 | * @word: The word to search | 591 | * @word: The word to search |
552 | * | 592 | * |
553 | * Undefined if no zero exists, so code should check against ~0UL first. | 593 | * Returns 0..SZLONG-1 |
594 | * Undefined if no bit exists, so code should check against 0 first. | ||
554 | */ | 595 | */ |
555 | static inline unsigned long ffz(unsigned long word) | 596 | static inline unsigned long __ffs(unsigned long word) |
556 | { | 597 | { |
598 | #if defined(CONFIG_CPU_MIPS32_R1) || defined(CONFIG_CPU_MIPS64_R1) | ||
599 | return __ilog2(word & -word); | ||
600 | #else | ||
557 | int b = 0, s; | 601 | int b = 0, s; |
558 | 602 | ||
559 | word = ~word; | ||
560 | #ifdef CONFIG_32BIT | 603 | #ifdef CONFIG_32BIT |
561 | s = 16; if (word << 16 != 0) s = 0; b += s; word >>= s; | 604 | s = 16; if (word << 16 != 0) s = 0; b += s; word >>= s; |
562 | s = 8; if (word << 24 != 0) s = 0; b += s; word >>= s; | 605 | s = 8; if (word << 24 != 0) s = 0; b += s; word >>= s; |
@@ -572,26 +615,87 @@ static inline unsigned long ffz(unsigned long word) | |||
572 | s = 2; if (word << 62 != 0) s = 0; b += s; word >>= s; | 615 | s = 2; if (word << 62 != 0) s = 0; b += s; word >>= s; |
573 | s = 1; if (word << 63 != 0) s = 0; b += s; | 616 | s = 1; if (word << 63 != 0) s = 0; b += s; |
574 | #endif | 617 | #endif |
575 | |||
576 | return b; | 618 | return b; |
619 | #endif | ||
577 | } | 620 | } |
578 | 621 | ||
579 | /* | 622 | /* |
580 | * __ffs - find first bit in word. | 623 | * ffs - find first bit set. |
581 | * @word: The word to search | 624 | * @word: The word to search |
582 | * | 625 | * |
583 | * Undefined if no bit exists, so code should check against 0 first. | 626 | * Returns 1..SZLONG |
627 | * Returns 0 if no bit exists | ||
584 | */ | 628 | */ |
585 | static inline unsigned long __ffs(unsigned long word) | 629 | |
630 | static inline unsigned long ffs(unsigned long word) | ||
586 | { | 631 | { |
587 | return ffz(~word); | 632 | if (!word) |
633 | return 0; | ||
634 | |||
635 | return __ffs(word) + 1; | ||
588 | } | 636 | } |
589 | 637 | ||
590 | /* | 638 | /* |
591 | * fls: find last bit set. | 639 | * ffz - find first zero in word. |
640 | * @word: The word to search | ||
641 | * | ||
642 | * Undefined if no zero exists, so code should check against ~0UL first. | ||
592 | */ | 643 | */ |
644 | static inline unsigned long ffz(unsigned long word) | ||
645 | { | ||
646 | return __ffs (~word); | ||
647 | } | ||
648 | |||
649 | /* | ||
650 | * flz - find last zero in word. | ||
651 | * @word: The word to search | ||
652 | * | ||
653 | * Returns 0..SZLONG-1 | ||
654 | * Undefined if no zero exists, so code should check against ~0UL first. | ||
655 | */ | ||
656 | static inline unsigned long flz(unsigned long word) | ||
657 | { | ||
658 | #if defined(CONFIG_CPU_MIPS32_R1) || defined(CONFIG_CPU_MIPS64_R1) | ||
659 | return __ilog2(~word); | ||
660 | #else | ||
661 | #if defined(CONFIG_32BIT) | ||
662 | int r = 31, s; | ||
663 | word = ~word; | ||
664 | s = 16; if ((word & 0xffff0000)) s = 0; r -= s; word <<= s; | ||
665 | s = 8; if ((word & 0xff000000)) s = 0; r -= s; word <<= s; | ||
666 | s = 4; if ((word & 0xf0000000)) s = 0; r -= s; word <<= s; | ||
667 | s = 2; if ((word & 0xc0000000)) s = 0; r -= s; word <<= s; | ||
668 | s = 1; if ((word & 0x80000000)) s = 0; r -= s; | ||
669 | #endif | ||
670 | #if defined(CONFIG_64BIT) | ||
671 | int r = 63, s; | ||
672 | word = ~word; | ||
673 | s = 32; if ((word & 0xffffffff00000000UL)) s = 0; r -= s; word <<= s; | ||
674 | s = 16; if ((word & 0xffff000000000000UL)) s = 0; r -= s; word <<= s; | ||
675 | s = 8; if ((word & 0xff00000000000000UL)) s = 0; r -= s; word <<= s; | ||
676 | s = 4; if ((word & 0xf000000000000000UL)) s = 0; r -= s; word <<= s; | ||
677 | s = 2; if ((word & 0xc000000000000000UL)) s = 0; r -= s; word <<= s; | ||
678 | s = 1; if ((word & 0x8000000000000000UL)) s = 0; r -= s; | ||
679 | #endif | ||
680 | return r; | ||
681 | #endif | ||
682 | } | ||
683 | |||
684 | /* | ||
685 | * fls - find last bit set. | ||
686 | * @word: The word to search | ||
687 | * | ||
688 | * Returns 1..SZLONG | ||
689 | * Returns 0 if no bit exists | ||
690 | */ | ||
691 | static inline unsigned long fls(unsigned long word) | ||
692 | { | ||
693 | if (word == 0) | ||
694 | return 0; | ||
695 | |||
696 | return flz(~word) + 1; | ||
697 | } | ||
593 | 698 | ||
594 | #define fls(x) generic_fls(x) | ||
595 | 699 | ||
596 | /* | 700 | /* |
597 | * find_next_zero_bit - find the first zero bit in a memory region | 701 | * find_next_zero_bit - find the first zero bit in a memory region |
@@ -728,17 +832,6 @@ static inline int sched_find_first_bit(const unsigned long *b) | |||
728 | } | 832 | } |
729 | 833 | ||
730 | /* | 834 | /* |
731 | * ffs - find first bit set | ||
732 | * @x: the word to search | ||
733 | * | ||
734 | * This is defined the same way as | ||
735 | * the libc and compiler builtin ffs routines, therefore | ||
736 | * differs in spirit from the above ffz (man ffs). | ||
737 | */ | ||
738 | |||
739 | #define ffs(x) generic_ffs(x) | ||
740 | |||
741 | /* | ||
742 | * hweightN - returns the hamming weight of a N-bit word | 835 | * hweightN - returns the hamming weight of a N-bit word |
743 | * @x: the word to weigh | 836 | * @x: the word to weigh |
744 | * | 837 | * |