aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-s390/bitops.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-s390/bitops.h')
-rw-r--r--include/asm-s390/bitops.h440
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 */
534static 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 */
559static 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
535static inline int 586static inline int
536find_first_zero_bit(const unsigned long * addr, unsigned int size) 587find_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
576static inline int 627static inline int
577find_first_bit(const unsigned long * addr, unsigned int size) 628find_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
617static inline int
618find_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
656static inline int
657find_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 */
700static inline unsigned long 670static inline unsigned long
701find_first_zero_bit(const unsigned long * addr, unsigned long size) 671find_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
788static inline unsigned long
789find_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
832static inline unsigned long
833find_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/* 760static inline int
878 * ffz = Find First Zero in word. Undefined if no zero exists, 761find_next_zero_bit (const unsigned long * addr, unsigned long size,
879 * so code should check against ~0UL first.. 762 unsigned long offset)
880 */
881static 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/* 790static inline int
903 * __ffs = find first bit in word. Undefined if no bit exists, 791find_next_bit (const unsigned long * addr, unsigned long size,
904 * so code should check against 0UL first.. 792 unsigned long offset)
905 */
906static 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
1034static inline int
1035ext2_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
1079static inline unsigned long 929static 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
1123static inline unsigned long 973#endif /* __s390x__ */
974
975static inline int
1124ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset) 976ext2_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) \