diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2005-07-27 14:44:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-27 19:26:04 -0400 |
commit | afff7e2b3b13dbd26a2b9991d3d571df111d92e8 (patch) | |
tree | 51142ff8f5160bcd317120ffba604653c9e34455 /include/asm-s390 | |
parent | 951f22d5b1f0eaae35dafc669e3774a0c2084d10 (diff) |
[PATCH] s390: find_next_{zero}_bit fixes
The find_next_{zero}_bit primitives on s390* should never return a bit number
bigger then the bit field size. In the case of a bitfield that doesn't end on
a word boundary, an offset that makes the search start at the last word of the
bit field and the last word doesn't contain any zero/one bits the search is
continued with a call to find_first_bit with a negative size. The search
normally ends pretty quickly because the words following the bit field contain
a mix of zeros and ones. But the bit number that is returned in this case is
too big.
To fix this and additional if to check for this case is needed. To make the
code easier to read I removed the assembler parts from the
find_next_{zero}_bit functions, the C-ified code is as good.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/asm-s390')
-rw-r--r-- | include/asm-s390/bitops.h | 440 |
1 files changed, 140 insertions, 300 deletions
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index 16bb08499c7f..8651524217fd 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h | |||
@@ -527,13 +527,64 @@ __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) { | |||
527 | __constant_test_bit((nr),(addr)) : \ | 527 | __constant_test_bit((nr),(addr)) : \ |
528 | __test_bit((nr),(addr)) ) | 528 | __test_bit((nr),(addr)) ) |
529 | 529 | ||
530 | #ifndef __s390x__ | 530 | /* |
531 | * ffz = Find First Zero in word. Undefined if no zero exists, | ||
532 | * so code should check against ~0UL first.. | ||
533 | */ | ||
534 | static inline unsigned long ffz(unsigned long word) | ||
535 | { | ||
536 | unsigned long bit = 0; | ||
537 | |||
538 | #ifdef __s390x__ | ||
539 | if (likely((word & 0xffffffff) == 0xffffffff)) { | ||
540 | word >>= 32; | ||
541 | bit += 32; | ||
542 | } | ||
543 | #endif | ||
544 | if (likely((word & 0xffff) == 0xffff)) { | ||
545 | word >>= 16; | ||
546 | bit += 16; | ||
547 | } | ||
548 | if (likely((word & 0xff) == 0xff)) { | ||
549 | word >>= 8; | ||
550 | bit += 8; | ||
551 | } | ||
552 | return bit + _zb_findmap[word & 0xff]; | ||
553 | } | ||
554 | |||
555 | /* | ||
556 | * __ffs = find first bit in word. Undefined if no bit exists, | ||
557 | * so code should check against 0UL first.. | ||
558 | */ | ||
559 | static inline unsigned long __ffs (unsigned long word) | ||
560 | { | ||
561 | unsigned long bit = 0; | ||
562 | |||
563 | #ifdef __s390x__ | ||
564 | if (likely((word & 0xffffffff) == 0)) { | ||
565 | word >>= 32; | ||
566 | bit += 32; | ||
567 | } | ||
568 | #endif | ||
569 | if (likely((word & 0xffff) == 0)) { | ||
570 | word >>= 16; | ||
571 | bit += 16; | ||
572 | } | ||
573 | if (likely((word & 0xff) == 0)) { | ||
574 | word >>= 8; | ||
575 | bit += 8; | ||
576 | } | ||
577 | return bit + _sb_findmap[word & 0xff]; | ||
578 | } | ||
531 | 579 | ||
532 | /* | 580 | /* |
533 | * Find-bit routines.. | 581 | * Find-bit routines.. |
534 | */ | 582 | */ |
583 | |||
584 | #ifndef __s390x__ | ||
585 | |||
535 | static inline int | 586 | static inline int |
536 | find_first_zero_bit(const unsigned long * addr, unsigned int size) | 587 | find_first_zero_bit(const unsigned long * addr, unsigned long size) |
537 | { | 588 | { |
538 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | 589 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; |
539 | unsigned long cmp, count; | 590 | unsigned long cmp, count; |
@@ -548,7 +599,7 @@ find_first_zero_bit(const unsigned long * addr, unsigned int size) | |||
548 | " srl %2,5\n" | 599 | " srl %2,5\n" |
549 | "0: c %1,0(%0,%4)\n" | 600 | "0: c %1,0(%0,%4)\n" |
550 | " jne 1f\n" | 601 | " jne 1f\n" |
551 | " ahi %0,4\n" | 602 | " la %0,4(%0)\n" |
552 | " brct %2,0b\n" | 603 | " brct %2,0b\n" |
553 | " lr %0,%3\n" | 604 | " lr %0,%3\n" |
554 | " j 4f\n" | 605 | " j 4f\n" |
@@ -574,7 +625,7 @@ find_first_zero_bit(const unsigned long * addr, unsigned int size) | |||
574 | } | 625 | } |
575 | 626 | ||
576 | static inline int | 627 | static inline int |
577 | find_first_bit(const unsigned long * addr, unsigned int size) | 628 | find_first_bit(const unsigned long * addr, unsigned long size) |
578 | { | 629 | { |
579 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; | 630 | typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; |
580 | unsigned long cmp, count; | 631 | unsigned long cmp, count; |
@@ -589,7 +640,7 @@ find_first_bit(const unsigned long * addr, unsigned int size) | |||
589 | " srl %2,5\n" | 640 | " srl %2,5\n" |
590 | "0: c %1,0(%0,%4)\n" | 641 | "0: c %1,0(%0,%4)\n" |
591 | " jne 1f\n" | 642 | " jne 1f\n" |
592 | " ahi %0,4\n" | 643 | " la %0,4(%0)\n" |
593 | " brct %2,0b\n" | 644 | " brct %2,0b\n" |
594 | " lr %0,%3\n" | 645 | " lr %0,%3\n" |
595 | " j 4f\n" | 646 | " j 4f\n" |
@@ -614,89 +665,8 @@ find_first_bit(const unsigned long * addr, unsigned int size) | |||
614 | return (res < size) ? res : size; | 665 | return (res < size) ? res : size; |
615 | } | 666 | } |
616 | 667 | ||
617 | static inline int | ||
618 | find_next_zero_bit (const unsigned long * addr, int size, int offset) | ||
619 | { | ||
620 | unsigned long * p = ((unsigned long *) addr) + (offset >> 5); | ||
621 | unsigned long bitvec, reg; | ||
622 | int set, bit = offset & 31, res; | ||
623 | |||
624 | if (bit) { | ||
625 | /* | ||
626 | * Look for zero in first word | ||
627 | */ | ||
628 | bitvec = (*p) >> bit; | ||
629 | __asm__(" slr %0,%0\n" | ||
630 | " lhi %2,0xff\n" | ||
631 | " tml %1,0xffff\n" | ||
632 | " jno 0f\n" | ||
633 | " ahi %0,16\n" | ||
634 | " srl %1,16\n" | ||
635 | "0: tml %1,0x00ff\n" | ||
636 | " jno 1f\n" | ||
637 | " ahi %0,8\n" | ||
638 | " srl %1,8\n" | ||
639 | "1: nr %1,%2\n" | ||
640 | " ic %1,0(%1,%3)\n" | ||
641 | " alr %0,%1" | ||
642 | : "=&d" (set), "+a" (bitvec), "=&d" (reg) | ||
643 | : "a" (&_zb_findmap) : "cc" ); | ||
644 | if (set < (32 - bit)) | ||
645 | return set + offset; | ||
646 | offset += 32 - bit; | ||
647 | p++; | ||
648 | } | ||
649 | /* | ||
650 | * No zero yet, search remaining full words for a zero | ||
651 | */ | ||
652 | res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); | ||
653 | return (offset + res); | ||
654 | } | ||
655 | |||
656 | static inline int | ||
657 | find_next_bit (const unsigned long * addr, int size, int offset) | ||
658 | { | ||
659 | unsigned long * p = ((unsigned long *) addr) + (offset >> 5); | ||
660 | unsigned long bitvec, reg; | ||
661 | int set, bit = offset & 31, res; | ||
662 | |||
663 | if (bit) { | ||
664 | /* | ||
665 | * Look for set bit in first word | ||
666 | */ | ||
667 | bitvec = (*p) >> bit; | ||
668 | __asm__(" slr %0,%0\n" | ||
669 | " lhi %2,0xff\n" | ||
670 | " tml %1,0xffff\n" | ||
671 | " jnz 0f\n" | ||
672 | " ahi %0,16\n" | ||
673 | " srl %1,16\n" | ||
674 | "0: tml %1,0x00ff\n" | ||
675 | " jnz 1f\n" | ||
676 | " ahi %0,8\n" | ||
677 | " srl %1,8\n" | ||
678 | "1: nr %1,%2\n" | ||
679 | " ic %1,0(%1,%3)\n" | ||
680 | " alr %0,%1" | ||
681 | : "=&d" (set), "+a" (bitvec), "=&d" (reg) | ||
682 | : "a" (&_sb_findmap) : "cc" ); | ||
683 | if (set < (32 - bit)) | ||
684 | return set + offset; | ||
685 | offset += 32 - bit; | ||
686 | p++; | ||
687 | } | ||
688 | /* | ||
689 | * No set bit yet, search remaining full words for a bit | ||
690 | */ | ||
691 | res = find_first_bit (p, size - 32 * (p - (unsigned long *) addr)); | ||
692 | return (offset + res); | ||
693 | } | ||
694 | |||
695 | #else /* __s390x__ */ | 668 | #else /* __s390x__ */ |
696 | 669 | ||
697 | /* | ||
698 | * Find-bit routines.. | ||
699 | */ | ||
700 | static inline unsigned long | 670 | static inline unsigned long |
701 | find_first_zero_bit(const unsigned long * addr, unsigned long size) | 671 | find_first_zero_bit(const unsigned long * addr, unsigned long size) |
702 | { | 672 | { |
@@ -712,7 +682,7 @@ find_first_zero_bit(const unsigned long * addr, unsigned long size) | |||
712 | " srlg %2,%2,6\n" | 682 | " srlg %2,%2,6\n" |
713 | "0: cg %1,0(%0,%4)\n" | 683 | "0: cg %1,0(%0,%4)\n" |
714 | " jne 1f\n" | 684 | " jne 1f\n" |
715 | " aghi %0,8\n" | 685 | " la %0,8(%0)\n" |
716 | " brct %2,0b\n" | 686 | " brct %2,0b\n" |
717 | " lgr %0,%3\n" | 687 | " lgr %0,%3\n" |
718 | " j 5f\n" | 688 | " j 5f\n" |
@@ -785,143 +755,66 @@ find_first_bit(const unsigned long * addr, unsigned long size) | |||
785 | return (res < size) ? res : size; | 755 | return (res < size) ? res : size; |
786 | } | 756 | } |
787 | 757 | ||
788 | static inline unsigned long | ||
789 | find_next_zero_bit (const unsigned long * addr, unsigned long size, unsigned long offset) | ||
790 | { | ||
791 | unsigned long * p = ((unsigned long *) addr) + (offset >> 6); | ||
792 | unsigned long bitvec, reg; | ||
793 | unsigned long set, bit = offset & 63, res; | ||
794 | |||
795 | if (bit) { | ||
796 | /* | ||
797 | * Look for zero in first word | ||
798 | */ | ||
799 | bitvec = (*p) >> bit; | ||
800 | __asm__(" lhi %2,-1\n" | ||
801 | " slgr %0,%0\n" | ||
802 | " clr %1,%2\n" | ||
803 | " jne 0f\n" | ||
804 | " aghi %0,32\n" | ||
805 | " srlg %1,%1,32\n" | ||
806 | "0: lghi %2,0xff\n" | ||
807 | " tmll %1,0xffff\n" | ||
808 | " jno 1f\n" | ||
809 | " aghi %0,16\n" | ||
810 | " srlg %1,%1,16\n" | ||
811 | "1: tmll %1,0x00ff\n" | ||
812 | " jno 2f\n" | ||
813 | " aghi %0,8\n" | ||
814 | " srlg %1,%1,8\n" | ||
815 | "2: ngr %1,%2\n" | ||
816 | " ic %1,0(%1,%3)\n" | ||
817 | " algr %0,%1" | ||
818 | : "=&d" (set), "+a" (bitvec), "=&d" (reg) | ||
819 | : "a" (&_zb_findmap) : "cc" ); | ||
820 | if (set < (64 - bit)) | ||
821 | return set + offset; | ||
822 | offset += 64 - bit; | ||
823 | p++; | ||
824 | } | ||
825 | /* | ||
826 | * No zero yet, search remaining full words for a zero | ||
827 | */ | ||
828 | res = find_first_zero_bit (p, size - 64 * (p - (unsigned long *) addr)); | ||
829 | return (offset + res); | ||
830 | } | ||
831 | |||
832 | static inline unsigned long | ||
833 | find_next_bit (const unsigned long * addr, unsigned long size, unsigned long offset) | ||
834 | { | ||
835 | unsigned long * p = ((unsigned long *) addr) + (offset >> 6); | ||
836 | unsigned long bitvec, reg; | ||
837 | unsigned long set, bit = offset & 63, res; | ||
838 | |||
839 | if (bit) { | ||
840 | /* | ||
841 | * Look for zero in first word | ||
842 | */ | ||
843 | bitvec = (*p) >> bit; | ||
844 | __asm__(" slgr %0,%0\n" | ||
845 | " ltr %1,%1\n" | ||
846 | " jnz 0f\n" | ||
847 | " aghi %0,32\n" | ||
848 | " srlg %1,%1,32\n" | ||
849 | "0: lghi %2,0xff\n" | ||
850 | " tmll %1,0xffff\n" | ||
851 | " jnz 1f\n" | ||
852 | " aghi %0,16\n" | ||
853 | " srlg %1,%1,16\n" | ||
854 | "1: tmll %1,0x00ff\n" | ||
855 | " jnz 2f\n" | ||
856 | " aghi %0,8\n" | ||
857 | " srlg %1,%1,8\n" | ||
858 | "2: ngr %1,%2\n" | ||
859 | " ic %1,0(%1,%3)\n" | ||
860 | " algr %0,%1" | ||
861 | : "=&d" (set), "+a" (bitvec), "=&d" (reg) | ||
862 | : "a" (&_sb_findmap) : "cc" ); | ||
863 | if (set < (64 - bit)) | ||
864 | return set + offset; | ||
865 | offset += 64 - bit; | ||
866 | p++; | ||
867 | } | ||
868 | /* | ||
869 | * No set bit yet, search remaining full words for a bit | ||
870 | */ | ||
871 | res = find_first_bit (p, size - 64 * (p - (unsigned long *) addr)); | ||
872 | return (offset + res); | ||
873 | } | ||
874 | |||
875 | #endif /* __s390x__ */ | 758 | #endif /* __s390x__ */ |
876 | 759 | ||
877 | /* | 760 | static inline int |
878 | * ffz = Find First Zero in word. Undefined if no zero exists, | 761 | find_next_zero_bit (const unsigned long * addr, unsigned long size, |
879 | * so code should check against ~0UL first.. | 762 | unsigned long offset) |
880 | */ | ||
881 | static inline unsigned long ffz(unsigned long word) | ||
882 | { | 763 | { |
883 | unsigned long bit = 0; | 764 | const unsigned long *p; |
884 | 765 | unsigned long bit, set; | |
885 | #ifdef __s390x__ | 766 | |
886 | if (likely((word & 0xffffffff) == 0xffffffff)) { | 767 | if (offset >= size) |
887 | word >>= 32; | 768 | return size; |
888 | bit += 32; | 769 | bit = offset & (__BITOPS_WORDSIZE - 1); |
889 | } | 770 | offset -= bit; |
890 | #endif | 771 | size -= offset; |
891 | if (likely((word & 0xffff) == 0xffff)) { | 772 | p = addr + offset / __BITOPS_WORDSIZE; |
892 | word >>= 16; | 773 | if (bit) { |
893 | bit += 16; | 774 | /* |
775 | * s390 version of ffz returns __BITOPS_WORDSIZE | ||
776 | * if no zero bit is present in the word. | ||
777 | */ | ||
778 | set = ffz(*p >> bit) + bit; | ||
779 | if (set >= size) | ||
780 | return size + offset; | ||
781 | if (set < __BITOPS_WORDSIZE) | ||
782 | return set + offset; | ||
783 | offset += __BITOPS_WORDSIZE; | ||
784 | size -= __BITOPS_WORDSIZE; | ||
785 | p++; | ||
894 | } | 786 | } |
895 | if (likely((word & 0xff) == 0xff)) { | 787 | return offset + find_first_zero_bit(p, size); |
896 | word >>= 8; | ||
897 | bit += 8; | ||
898 | } | ||
899 | return bit + _zb_findmap[word & 0xff]; | ||
900 | } | 788 | } |
901 | 789 | ||
902 | /* | 790 | static inline int |
903 | * __ffs = find first bit in word. Undefined if no bit exists, | 791 | find_next_bit (const unsigned long * addr, unsigned long size, |
904 | * so code should check against 0UL first.. | 792 | unsigned long offset) |
905 | */ | ||
906 | static inline unsigned long __ffs (unsigned long word) | ||
907 | { | 793 | { |
908 | unsigned long bit = 0; | 794 | const unsigned long *p; |
909 | 795 | unsigned long bit, set; | |
910 | #ifdef __s390x__ | 796 | |
911 | if (likely((word & 0xffffffff) == 0)) { | 797 | if (offset >= size) |
912 | word >>= 32; | 798 | return size; |
913 | bit += 32; | 799 | bit = offset & (__BITOPS_WORDSIZE - 1); |
800 | offset -= bit; | ||
801 | size -= offset; | ||
802 | p = addr + offset / __BITOPS_WORDSIZE; | ||
803 | if (bit) { | ||
804 | /* | ||
805 | * s390 version of __ffs returns __BITOPS_WORDSIZE | ||
806 | * if no one bit is present in the word. | ||
807 | */ | ||
808 | set = __ffs(*p & (~0UL << bit)); | ||
809 | if (set >= size) | ||
810 | return size + offset; | ||
811 | if (set < __BITOPS_WORDSIZE) | ||
812 | return set + offset; | ||
813 | offset += __BITOPS_WORDSIZE; | ||
814 | size -= __BITOPS_WORDSIZE; | ||
815 | p++; | ||
914 | } | 816 | } |
915 | #endif | 817 | return offset + find_first_bit(p, size); |
916 | if (likely((word & 0xffff) == 0)) { | ||
917 | word >>= 16; | ||
918 | bit += 16; | ||
919 | } | ||
920 | if (likely((word & 0xff) == 0)) { | ||
921 | word >>= 8; | ||
922 | bit += 8; | ||
923 | } | ||
924 | return bit + _sb_findmap[word & 0xff]; | ||
925 | } | 818 | } |
926 | 819 | ||
927 | /* | 820 | /* |
@@ -1031,49 +924,6 @@ ext2_find_first_zero_bit(void *vaddr, unsigned int size) | |||
1031 | return (res < size) ? res : size; | 924 | return (res < size) ? res : size; |
1032 | } | 925 | } |
1033 | 926 | ||
1034 | static inline int | ||
1035 | ext2_find_next_zero_bit(void *vaddr, unsigned int size, unsigned offset) | ||
1036 | { | ||
1037 | unsigned long *addr = vaddr; | ||
1038 | unsigned long *p = addr + (offset >> 5); | ||
1039 | unsigned long word, reg; | ||
1040 | unsigned int bit = offset & 31UL, res; | ||
1041 | |||
1042 | if (offset >= size) | ||
1043 | return size; | ||
1044 | |||
1045 | if (bit) { | ||
1046 | __asm__(" ic %0,0(%1)\n" | ||
1047 | " icm %0,2,1(%1)\n" | ||
1048 | " icm %0,4,2(%1)\n" | ||
1049 | " icm %0,8,3(%1)" | ||
1050 | : "=&a" (word) : "a" (p) : "cc" ); | ||
1051 | word >>= bit; | ||
1052 | res = bit; | ||
1053 | /* Look for zero in first longword */ | ||
1054 | __asm__(" lhi %2,0xff\n" | ||
1055 | " tml %1,0xffff\n" | ||
1056 | " jno 0f\n" | ||
1057 | " ahi %0,16\n" | ||
1058 | " srl %1,16\n" | ||
1059 | "0: tml %1,0x00ff\n" | ||
1060 | " jno 1f\n" | ||
1061 | " ahi %0,8\n" | ||
1062 | " srl %1,8\n" | ||
1063 | "1: nr %1,%2\n" | ||
1064 | " ic %1,0(%1,%3)\n" | ||
1065 | " alr %0,%1" | ||
1066 | : "+&d" (res), "+&a" (word), "=&d" (reg) | ||
1067 | : "a" (&_zb_findmap) : "cc" ); | ||
1068 | if (res < 32) | ||
1069 | return (p - addr)*32 + res; | ||
1070 | p++; | ||
1071 | } | ||
1072 | /* No zero yet, search remaining full bytes for a zero */ | ||
1073 | res = ext2_find_first_zero_bit (p, size - 32 * (p - addr)); | ||
1074 | return (p - addr) * 32 + res; | ||
1075 | } | ||
1076 | |||
1077 | #else /* __s390x__ */ | 927 | #else /* __s390x__ */ |
1078 | 928 | ||
1079 | static inline unsigned long | 929 | static inline unsigned long |
@@ -1120,56 +970,46 @@ ext2_find_first_zero_bit(void *vaddr, unsigned long size) | |||
1120 | return (res < size) ? res : size; | 970 | return (res < size) ? res : size; |
1121 | } | 971 | } |
1122 | 972 | ||
1123 | static inline unsigned long | 973 | #endif /* __s390x__ */ |
974 | |||
975 | static inline int | ||
1124 | ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset) | 976 | ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset) |
1125 | { | 977 | { |
1126 | unsigned long *addr = vaddr; | 978 | unsigned long *addr = vaddr, *p; |
1127 | unsigned long *p = addr + (offset >> 6); | 979 | unsigned long word, bit, set; |
1128 | unsigned long word, reg; | ||
1129 | unsigned long bit = offset & 63UL, res; | ||
1130 | 980 | ||
1131 | if (offset >= size) | 981 | if (offset >= size) |
1132 | return size; | 982 | return size; |
1133 | 983 | bit = offset & (__BITOPS_WORDSIZE - 1); | |
984 | offset -= bit; | ||
985 | size -= offset; | ||
986 | p = addr + offset / __BITOPS_WORDSIZE; | ||
1134 | if (bit) { | 987 | if (bit) { |
1135 | __asm__(" lrvg %0,%1" /* load reversed, neat instruction */ | 988 | #ifndef __s390x__ |
1136 | : "=a" (word) : "m" (*p) ); | 989 | asm(" ic %0,0(%1)\n" |
1137 | word >>= bit; | 990 | " icm %0,2,1(%1)\n" |
1138 | res = bit; | 991 | " icm %0,4,2(%1)\n" |
1139 | /* Look for zero in first 8 byte word */ | 992 | " icm %0,8,3(%1)" |
1140 | __asm__(" lghi %2,0xff\n" | 993 | : "=&a" (word) : "a" (p), "m" (*p) : "cc" ); |
1141 | " tmll %1,0xffff\n" | 994 | #else |
1142 | " jno 2f\n" | 995 | asm(" lrvg %0,%1" : "=a" (word) : "m" (*p) ); |
1143 | " ahi %0,16\n" | 996 | #endif |
1144 | " srlg %1,%1,16\n" | 997 | /* |
1145 | "0: tmll %1,0xffff\n" | 998 | * s390 version of ffz returns __BITOPS_WORDSIZE |
1146 | " jno 2f\n" | 999 | * if no zero bit is present in the word. |
1147 | " ahi %0,16\n" | 1000 | */ |
1148 | " srlg %1,%1,16\n" | 1001 | set = ffz(word >> bit) + bit; |
1149 | "1: tmll %1,0xffff\n" | 1002 | if (set >= size) |
1150 | " jno 2f\n" | 1003 | return size + offset; |
1151 | " ahi %0,16\n" | 1004 | if (set < __BITOPS_WORDSIZE) |
1152 | " srl %1,16\n" | 1005 | return set + offset; |
1153 | "2: tmll %1,0x00ff\n" | 1006 | offset += __BITOPS_WORDSIZE; |
1154 | " jno 3f\n" | 1007 | size -= __BITOPS_WORDSIZE; |
1155 | " ahi %0,8\n" | 1008 | p++; |
1156 | " srl %1,8\n" | ||
1157 | "3: ngr %1,%2\n" | ||
1158 | " ic %1,0(%1,%3)\n" | ||
1159 | " alr %0,%1" | ||
1160 | : "+&d" (res), "+a" (word), "=&d" (reg) | ||
1161 | : "a" (&_zb_findmap) : "cc" ); | ||
1162 | if (res < 64) | ||
1163 | return (p - addr)*64 + res; | ||
1164 | p++; | ||
1165 | } | 1009 | } |
1166 | /* No zero yet, search remaining full bytes for a zero */ | 1010 | return offset + ext2_find_first_zero_bit(p, size); |
1167 | res = ext2_find_first_zero_bit (p, size - 64 * (p - addr)); | ||
1168 | return (p - addr) * 64 + res; | ||
1169 | } | 1011 | } |
1170 | 1012 | ||
1171 | #endif /* __s390x__ */ | ||
1172 | |||
1173 | /* Bitmap functions for the minix filesystem. */ | 1013 | /* Bitmap functions for the minix filesystem. */ |
1174 | /* FIXME !!! */ | 1014 | /* FIXME !!! */ |
1175 | #define minix_test_and_set_bit(nr,addr) \ | 1015 | #define minix_test_and_set_bit(nr,addr) \ |