aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/include/asm/bitops.h114
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 */
567static inline unsigned long __fls(unsigned long x) 565static 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 */
615static inline int fls(int word) 643static 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;
623static 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