aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-s390/bitops.h
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2008-02-05 10:50:43 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-02-05 10:50:58 -0500
commit0abbf05cdd69d74f92628bf444cd210ba046f6eb (patch)
tree369550d01b22fc9a68d07652513e532b97ec8975 /include/asm-s390/bitops.h
parentb6b40c532a36f91df9c21caf9baba3b635e99d4e (diff)
[S390] Cleanup & optimize bitops.
The bitops header is now a bit shorter and easier to understand since it uses less inline assembly. It requires some tricks to persuade the compiler to generate decent code. The ffz/ffs functions now use the _zb_findmap/_sb_findmap table as well. With this cleanup the new bitops for ext4 can be implemented with a few lines, instead of another large inline assembly. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'include/asm-s390/bitops.h')
-rw-r--r--include/asm-s390/bitops.h515
1 files changed, 219 insertions, 296 deletions
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index dba6fecad0be..95d93955a9bb 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -440,242 +440,256 @@ __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
440 __test_bit((nr),(addr)) ) 440 __test_bit((nr),(addr)) )
441 441
442/* 442/*
443 * ffz = Find First Zero in word. Undefined if no zero exists, 443 * Optimized find bit helper functions.
444 * so code should check against ~0UL first..
445 */ 444 */
446static inline unsigned long ffz(unsigned long word) 445
446/**
447 * __ffz_word_loop - find byte offset of first long != -1UL
448 * @addr: pointer to array of unsigned long
449 * @size: size of the array in bits
450 */
451static inline unsigned long __ffz_word_loop(const unsigned long *addr,
452 unsigned long size)
453{
454 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
455 unsigned long bytes = 0;
456
457 asm volatile(
458#ifndef __s390x__
459 " ahi %1,31\n"
460 " srl %1,5\n"
461 "0: c %2,0(%0,%3)\n"
462 " jne 1f\n"
463 " la %0,4(%0)\n"
464 " brct %1,0b\n"
465 "1:\n"
466#else
467 " aghi %1,63\n"
468 " srlg %1,%1,6\n"
469 "0: cg %2,0(%0,%3)\n"
470 " jne 1f\n"
471 " la %0,8(%0)\n"
472 " brct %1,0b\n"
473 "1:\n"
474#endif
475 : "+a" (bytes), "+d" (size)
476 : "d" (-1UL), "a" (addr), "m" (*(addrtype *) addr)
477 : "cc" );
478 return bytes;
479}
480
481/**
482 * __ffs_word_loop - find byte offset of first long != 0UL
483 * @addr: pointer to array of unsigned long
484 * @size: size of the array in bits
485 */
486static inline unsigned long __ffs_word_loop(const unsigned long *addr,
487 unsigned long size)
447{ 488{
448 unsigned long bit = 0; 489 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
490 unsigned long bytes = 0;
449 491
492 asm volatile(
493#ifndef __s390x__
494 " ahi %1,31\n"
495 " srl %1,5\n"
496 "0: c %2,0(%0,%3)\n"
497 " jne 1f\n"
498 " la %0,4(%0)\n"
499 " brct %1,0b\n"
500 "1:\n"
501#else
502 " aghi %1,63\n"
503 " srlg %1,%1,6\n"
504 "0: cg %2,0(%0,%3)\n"
505 " jne 1f\n"
506 " la %0,8(%0)\n"
507 " brct %1,0b\n"
508 "1:\n"
509#endif
510 : "+a" (bytes), "+a" (size)
511 : "d" (0UL), "a" (addr), "m" (*(addrtype *) addr)
512 : "cc" );
513 return bytes;
514}
515
516/**
517 * __ffz_word - add number of the first unset bit
518 * @nr: base value the bit number is added to
519 * @word: the word that is searched for unset bits
520 */
521static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
522{
450#ifdef __s390x__ 523#ifdef __s390x__
451 if (likely((word & 0xffffffff) == 0xffffffff)) { 524 if (likely((word & 0xffffffff) == 0xffffffff)) {
452 word >>= 32; 525 word >>= 32;
453 bit += 32; 526 nr += 32;
454 } 527 }
455#endif 528#endif
456 if (likely((word & 0xffff) == 0xffff)) { 529 if (likely((word & 0xffff) == 0xffff)) {
457 word >>= 16; 530 word >>= 16;
458 bit += 16; 531 nr += 16;
459 } 532 }
460 if (likely((word & 0xff) == 0xff)) { 533 if (likely((word & 0xff) == 0xff)) {
461 word >>= 8; 534 word >>= 8;
462 bit += 8; 535 nr += 8;
463 } 536 }
464 return bit + _zb_findmap[word & 0xff]; 537 return nr + _zb_findmap[(unsigned char) word];
465} 538}
466 539
467/* 540/**
468 * __ffs = find first bit in word. Undefined if no bit exists, 541 * __ffs_word - add number of the first set bit
469 * so code should check against 0UL first.. 542 * @nr: base value the bit number is added to
543 * @word: the word that is searched for set bits
470 */ 544 */
471static inline unsigned long __ffs (unsigned long word) 545static inline unsigned long __ffs_word(unsigned long nr, unsigned long word)
472{ 546{
473 unsigned long bit = 0;
474
475#ifdef __s390x__ 547#ifdef __s390x__
476 if (likely((word & 0xffffffff) == 0)) { 548 if (likely((word & 0xffffffff) == 0)) {
477 word >>= 32; 549 word >>= 32;
478 bit += 32; 550 nr += 32;
479 } 551 }
480#endif 552#endif
481 if (likely((word & 0xffff) == 0)) { 553 if (likely((word & 0xffff) == 0)) {
482 word >>= 16; 554 word >>= 16;
483 bit += 16; 555 nr += 16;
484 } 556 }
485 if (likely((word & 0xff) == 0)) { 557 if (likely((word & 0xff) == 0)) {
486 word >>= 8; 558 word >>= 8;
487 bit += 8; 559 nr += 8;
488 } 560 }
489 return bit + _sb_findmap[word & 0xff]; 561 return nr + _sb_findmap[(unsigned char) word];
490} 562}
491 563
492/*
493 * Find-bit routines..
494 */
495 564
496#ifndef __s390x__ 565/**
566 * __load_ulong_be - load big endian unsigned long
567 * @p: pointer to array of unsigned long
568 * @offset: byte offset of source value in the array
569 */
570static inline unsigned long __load_ulong_be(const unsigned long *p,
571 unsigned long offset)
572{
573 p = (unsigned long *)((unsigned long) p + offset);
574 return *p;
575}
497 576
498static inline int 577/**
499find_first_zero_bit(const unsigned long * addr, unsigned long size) 578 * __load_ulong_le - load little endian unsigned long
579 * @p: pointer to array of unsigned long
580 * @offset: byte offset of source value in the array
581 */
582static inline unsigned long __load_ulong_le(const unsigned long *p,
583 unsigned long offset)
500{ 584{
501 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; 585 unsigned long word;
502 unsigned long cmp, count;
503 unsigned int res;
504 586
505 if (!size) 587 p = (unsigned long *)((unsigned long) p + offset);
506 return 0; 588#ifndef __s390x__
507 asm volatile( 589 asm volatile(
508 " lhi %1,-1\n" 590 " ic %0,0(%1)\n"
509 " lr %2,%3\n" 591 " icm %0,2,1(%1)\n"
510 " slr %0,%0\n" 592 " icm %0,4,2(%1)\n"
511 " ahi %2,31\n" 593 " icm %0,8,3(%1)"
512 " srl %2,5\n" 594 : "=&d" (word) : "a" (p), "m" (*p) : "cc");
513 "0: c %1,0(%0,%4)\n" 595#else
514 " jne 1f\n" 596 asm volatile(
515 " la %0,4(%0)\n" 597 " lrvg %0,%1"
516 " brct %2,0b\n" 598 : "=d" (word) : "m" (*p) );
517 " lr %0,%3\n" 599#endif
518 " j 4f\n" 600 return word;
519 "1: l %2,0(%0,%4)\n"
520 " sll %0,3\n"
521 " lhi %1,0xff\n"
522 " tml %2,0xffff\n"
523 " jno 2f\n"
524 " ahi %0,16\n"
525 " srl %2,16\n"
526 "2: tml %2,0x00ff\n"
527 " jno 3f\n"
528 " ahi %0,8\n"
529 " srl %2,8\n"
530 "3: nr %2,%1\n"
531 " ic %2,0(%2,%5)\n"
532 " alr %0,%2\n"
533 "4:"
534 : "=&a" (res), "=&d" (cmp), "=&a" (count)
535 : "a" (size), "a" (addr), "a" (&_zb_findmap),
536 "m" (*(addrtype *) addr) : "cc");
537 return (res < size) ? res : size;
538} 601}
539 602
540static inline int 603/*
541find_first_bit(const unsigned long * addr, unsigned long size) 604 * The various find bit functions.
605 */
606
607/*
608 * ffz - find first zero in word.
609 * @word: The word to search
610 *
611 * Undefined if no zero exists, so code should check against ~0UL first.
612 */
613static inline unsigned long ffz(unsigned long word)
542{ 614{
543 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; 615 return __ffz_word(0, word);
544 unsigned long cmp, count; 616}
545 unsigned int res;
546 617
547 if (!size) 618/**
548 return 0; 619 * __ffs - find first bit in word.
549 asm volatile( 620 * @word: The word to search
550 " slr %1,%1\n" 621 *
551 " lr %2,%3\n" 622 * Undefined if no bit exists, so code should check against 0 first.
552 " slr %0,%0\n" 623 */
553 " ahi %2,31\n" 624static inline unsigned long __ffs (unsigned long word)
554 " srl %2,5\n" 625{
555 "0: c %1,0(%0,%4)\n" 626 return __ffs_word(0, word);
556 " jne 1f\n"
557 " la %0,4(%0)\n"
558 " brct %2,0b\n"
559 " lr %0,%3\n"
560 " j 4f\n"
561 "1: l %2,0(%0,%4)\n"
562 " sll %0,3\n"
563 " lhi %1,0xff\n"
564 " tml %2,0xffff\n"
565 " jnz 2f\n"
566 " ahi %0,16\n"
567 " srl %2,16\n"
568 "2: tml %2,0x00ff\n"
569 " jnz 3f\n"
570 " ahi %0,8\n"
571 " srl %2,8\n"
572 "3: nr %2,%1\n"
573 " ic %2,0(%2,%5)\n"
574 " alr %0,%2\n"
575 "4:"
576 : "=&a" (res), "=&d" (cmp), "=&a" (count)
577 : "a" (size), "a" (addr), "a" (&_sb_findmap),
578 "m" (*(addrtype *) addr) : "cc");
579 return (res < size) ? res : size;
580} 627}
581 628
582#else /* __s390x__ */ 629/**
630 * ffs - find first bit set
631 * @x: the word to search
632 *
633 * This is defined the same way as
634 * the libc and compiler builtin ffs routines, therefore
635 * differs in spirit from the above ffz (man ffs).
636 */
637static inline int ffs(int x)
638{
639 if (!x)
640 return 0;
641 return __ffs_word(1, x);
642}
583 643
584static inline unsigned long 644/**
585find_first_zero_bit(const unsigned long * addr, unsigned long size) 645 * find_first_zero_bit - find the first zero bit in a memory region
646 * @addr: The address to start the search at
647 * @size: The maximum size to search
648 *
649 * Returns the bit-number of the first zero bit, not the number of the byte
650 * containing a bit.
651 */
652static inline unsigned long find_first_zero_bit(const unsigned long *addr,
653 unsigned long size)
586{ 654{
587 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; 655 unsigned long bytes, bits;
588 unsigned long res, cmp, count;
589 656
590 if (!size) 657 if (!size)
591 return 0; 658 return 0;
592 asm volatile( 659 bytes = __ffz_word_loop(addr, size);
593 " lghi %1,-1\n" 660 bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes));
594 " lgr %2,%3\n" 661 return (bits < size) ? bits : size;
595 " slgr %0,%0\n" 662}
596 " aghi %2,63\n" 663
597 " srlg %2,%2,6\n" 664/**
598 "0: cg %1,0(%0,%4)\n" 665 * find_first_bit - find the first set bit in a memory region
599 " jne 1f\n" 666 * @addr: The address to start the search at
600 " la %0,8(%0)\n" 667 * @size: The maximum size to search
601 " brct %2,0b\n" 668 *
602 " lgr %0,%3\n" 669 * Returns the bit-number of the first set bit, not the number of the byte
603 " j 5f\n" 670 * containing a bit.
604 "1: lg %2,0(%0,%4)\n" 671 */
605 " sllg %0,%0,3\n" 672static inline unsigned long find_first_bit(const unsigned long * addr,
606 " clr %2,%1\n" 673 unsigned long size)
607 " jne 2f\n"
608 " aghi %0,32\n"
609 " srlg %2,%2,32\n"
610 "2: lghi %1,0xff\n"
611 " tmll %2,0xffff\n"
612 " jno 3f\n"
613 " aghi %0,16\n"
614 " srl %2,16\n"
615 "3: tmll %2,0x00ff\n"
616 " jno 4f\n"
617 " aghi %0,8\n"
618 " srl %2,8\n"
619 "4: ngr %2,%1\n"
620 " ic %2,0(%2,%5)\n"
621 " algr %0,%2\n"
622 "5:"
623 : "=&a" (res), "=&d" (cmp), "=&a" (count)
624 : "a" (size), "a" (addr), "a" (&_zb_findmap),
625 "m" (*(addrtype *) addr) : "cc");
626 return (res < size) ? res : size;
627}
628
629static inline unsigned long
630find_first_bit(const unsigned long * addr, unsigned long size)
631{ 674{
632 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; 675 unsigned long bytes, bits;
633 unsigned long res, cmp, count;
634 676
635 if (!size) 677 if (!size)
636 return 0; 678 return 0;
637 asm volatile( 679 bytes = __ffs_word_loop(addr, size);
638 " slgr %1,%1\n" 680 bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes));
639 " lgr %2,%3\n" 681 return (bits < size) ? bits : size;
640 " slgr %0,%0\n"
641 " aghi %2,63\n"
642 " srlg %2,%2,6\n"
643 "0: cg %1,0(%0,%4)\n"
644 " jne 1f\n"
645 " aghi %0,8\n"
646 " brct %2,0b\n"
647 " lgr %0,%3\n"
648 " j 5f\n"
649 "1: lg %2,0(%0,%4)\n"
650 " sllg %0,%0,3\n"
651 " clr %2,%1\n"
652 " jne 2f\n"
653 " aghi %0,32\n"
654 " srlg %2,%2,32\n"
655 "2: lghi %1,0xff\n"
656 " tmll %2,0xffff\n"
657 " jnz 3f\n"
658 " aghi %0,16\n"
659 " srl %2,16\n"
660 "3: tmll %2,0x00ff\n"
661 " jnz 4f\n"
662 " aghi %0,8\n"
663 " srl %2,8\n"
664 "4: ngr %2,%1\n"
665 " ic %2,0(%2,%5)\n"
666 " algr %0,%2\n"
667 "5:"
668 : "=&a" (res), "=&d" (cmp), "=&a" (count)
669 : "a" (size), "a" (addr), "a" (&_sb_findmap),
670 "m" (*(addrtype *) addr) : "cc");
671 return (res < size) ? res : size;
672} 682}
673 683
674#endif /* __s390x__ */ 684/**
675 685 * find_next_zero_bit - find the first zero bit in a memory region
676static inline int 686 * @addr: The address to base the search on
677find_next_zero_bit (const unsigned long * addr, unsigned long size, 687 * @offset: The bitnumber to start searching at
678 unsigned long offset) 688 * @size: The maximum size to search
689 */
690static inline int find_next_zero_bit (const unsigned long * addr,
691 unsigned long size,
692 unsigned long offset)
679{ 693{
680 const unsigned long *p; 694 const unsigned long *p;
681 unsigned long bit, set; 695 unsigned long bit, set;
@@ -688,10 +702,10 @@ find_next_zero_bit (const unsigned long * addr, unsigned long size,
688 p = addr + offset / __BITOPS_WORDSIZE; 702 p = addr + offset / __BITOPS_WORDSIZE;
689 if (bit) { 703 if (bit) {
690 /* 704 /*
691 * s390 version of ffz returns __BITOPS_WORDSIZE 705 * __ffz_word returns __BITOPS_WORDSIZE
692 * if no zero bit is present in the word. 706 * if no zero bit is present in the word.
693 */ 707 */
694 set = ffz(*p >> bit) + bit; 708 set = __ffz_word(0, *p >> bit) + bit;
695 if (set >= size) 709 if (set >= size)
696 return size + offset; 710 return size + offset;
697 if (set < __BITOPS_WORDSIZE) 711 if (set < __BITOPS_WORDSIZE)
@@ -703,9 +717,15 @@ find_next_zero_bit (const unsigned long * addr, unsigned long size,
703 return offset + find_first_zero_bit(p, size); 717 return offset + find_first_zero_bit(p, size);
704} 718}
705 719
706static inline int 720/**
707find_next_bit (const unsigned long * addr, unsigned long size, 721 * find_next_bit - find the first set bit in a memory region
708 unsigned long offset) 722 * @addr: The address to base the search on
723 * @offset: The bitnumber to start searching at
724 * @size: The maximum size to search
725 */
726static inline int find_next_bit (const unsigned long * addr,
727 unsigned long size,
728 unsigned long offset)
709{ 729{
710 const unsigned long *p; 730 const unsigned long *p;
711 unsigned long bit, set; 731 unsigned long bit, set;
@@ -718,10 +738,10 @@ find_next_bit (const unsigned long * addr, unsigned long size,
718 p = addr + offset / __BITOPS_WORDSIZE; 738 p = addr + offset / __BITOPS_WORDSIZE;
719 if (bit) { 739 if (bit) {
720 /* 740 /*
721 * s390 version of __ffs returns __BITOPS_WORDSIZE 741 * __ffs_word returns __BITOPS_WORDSIZE
722 * if no one bit is present in the word. 742 * if no one bit is present in the word.
723 */ 743 */
724 set = __ffs(*p & (~0UL << bit)); 744 set = __ffs_word(0, *p & (~0UL << bit));
725 if (set >= size) 745 if (set >= size)
726 return size + offset; 746 return size + offset;
727 if (set < __BITOPS_WORDSIZE) 747 if (set < __BITOPS_WORDSIZE)
@@ -744,8 +764,6 @@ static inline int sched_find_first_bit(unsigned long *b)
744 return find_first_bit(b, 140); 764 return find_first_bit(b, 140);
745} 765}
746 766
747#include <asm-generic/bitops/ffs.h>
748
749#include <asm-generic/bitops/fls.h> 767#include <asm-generic/bitops/fls.h>
750#include <asm-generic/bitops/fls64.h> 768#include <asm-generic/bitops/fls64.h>
751 769
@@ -775,105 +793,22 @@ static inline int sched_find_first_bit(unsigned long *b)
775#define ext2_find_next_bit(addr, size, off) \ 793#define ext2_find_next_bit(addr, size, off) \
776 generic_find_next_le_bit((unsigned long *)(addr), (size), (off)) 794 generic_find_next_le_bit((unsigned long *)(addr), (size), (off))
777 795
778#ifndef __s390x__ 796static inline int ext2_find_first_zero_bit(void *vaddr, unsigned int size)
779
780static inline int
781ext2_find_first_zero_bit(void *vaddr, unsigned int size)
782{ 797{
783 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; 798 unsigned long bytes, bits;
784 unsigned long cmp, count;
785 unsigned int res;
786 799
787 if (!size) 800 if (!size)
788 return 0; 801 return 0;
789 asm volatile( 802 bytes = __ffz_word_loop(vaddr, size);
790 " lhi %1,-1\n" 803 bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes));
791 " lr %2,%3\n" 804 return (bits < size) ? bits : size;
792 " ahi %2,31\n"
793 " srl %2,5\n"
794 " slr %0,%0\n"
795 "0: cl %1,0(%0,%4)\n"
796 " jne 1f\n"
797 " ahi %0,4\n"
798 " brct %2,0b\n"
799 " lr %0,%3\n"
800 " j 4f\n"
801 "1: l %2,0(%0,%4)\n"
802 " sll %0,3\n"
803 " ahi %0,24\n"
804 " lhi %1,0xff\n"
805 " tmh %2,0xffff\n"
806 " jo 2f\n"
807 " ahi %0,-16\n"
808 " srl %2,16\n"
809 "2: tml %2,0xff00\n"
810 " jo 3f\n"
811 " ahi %0,-8\n"
812 " srl %2,8\n"
813 "3: nr %2,%1\n"
814 " ic %2,0(%2,%5)\n"
815 " alr %0,%2\n"
816 "4:"
817 : "=&a" (res), "=&d" (cmp), "=&a" (count)
818 : "a" (size), "a" (vaddr), "a" (&_zb_findmap),
819 "m" (*(addrtype *) vaddr) : "cc");
820 return (res < size) ? res : size;
821} 805}
822 806
823#else /* __s390x__ */ 807static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size,
824 808 unsigned long offset)
825static inline unsigned long
826ext2_find_first_zero_bit(void *vaddr, unsigned long size)
827{
828 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
829 unsigned long res, cmp, count;
830
831 if (!size)
832 return 0;
833 asm volatile(
834 " lghi %1,-1\n"
835 " lgr %2,%3\n"
836 " aghi %2,63\n"
837 " srlg %2,%2,6\n"
838 " slgr %0,%0\n"
839 "0: clg %1,0(%0,%4)\n"
840 " jne 1f\n"
841 " aghi %0,8\n"
842 " brct %2,0b\n"
843 " lgr %0,%3\n"
844 " j 5f\n"
845 "1: cl %1,0(%0,%4)\n"
846 " jne 2f\n"
847 " aghi %0,4\n"
848 "2: l %2,0(%0,%4)\n"
849 " sllg %0,%0,3\n"
850 " aghi %0,24\n"
851 " lghi %1,0xff\n"
852 " tmlh %2,0xffff\n"
853 " jo 3f\n"
854 " aghi %0,-16\n"
855 " srl %2,16\n"
856 "3: tmll %2,0xff00\n"
857 " jo 4f\n"
858 " aghi %0,-8\n"
859 " srl %2,8\n"
860 "4: ngr %2,%1\n"
861 " ic %2,0(%2,%5)\n"
862 " algr %0,%2\n"
863 "5:"
864 : "=&a" (res), "=&d" (cmp), "=&a" (count)
865 : "a" (size), "a" (vaddr), "a" (&_zb_findmap),
866 "m" (*(addrtype *) vaddr) : "cc");
867 return (res < size) ? res : size;
868}
869
870#endif /* __s390x__ */
871
872static inline int
873ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset)
874{ 809{
875 unsigned long *addr = vaddr, *p; 810 unsigned long *addr = vaddr, *p;
876 unsigned long word, bit, set; 811 unsigned long bit, set;
877 812
878 if (offset >= size) 813 if (offset >= size)
879 return size; 814 return size;
@@ -882,23 +817,11 @@ ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset)
882 size -= offset; 817 size -= offset;
883 p = addr + offset / __BITOPS_WORDSIZE; 818 p = addr + offset / __BITOPS_WORDSIZE;
884 if (bit) { 819 if (bit) {
885#ifndef __s390x__
886 asm volatile(
887 " ic %0,0(%1)\n"
888 " icm %0,2,1(%1)\n"
889 " icm %0,4,2(%1)\n"
890 " icm %0,8,3(%1)"
891 : "=&a" (word) : "a" (p), "m" (*p) : "cc");
892#else
893 asm volatile(
894 " lrvg %0,%1"
895 : "=a" (word) : "m" (*p) );
896#endif
897 /* 820 /*
898 * s390 version of ffz returns __BITOPS_WORDSIZE 821 * s390 version of ffz returns __BITOPS_WORDSIZE
899 * if no zero bit is present in the word. 822 * if no zero bit is present in the word.
900 */ 823 */
901 set = ffz(word >> bit) + bit; 824 set = ffz(__load_ulong_le(p, 0) >> bit) + bit;
902 if (set >= size) 825 if (set >= size)
903 return size + offset; 826 return size + offset;
904 if (set < __BITOPS_WORDSIZE) 827 if (set < __BITOPS_WORDSIZE)