526 sub(cnt1_neg, zr, cnt1, LSL, 1);
527 BIND(DO1_LOOP);
528 ldrh(ch1, Address(str1, cnt1_neg));
529 cmpw(ch, ch1);
530 br(EQ, MATCH);
531 adds(cnt1_neg, cnt1_neg, 2);
532 br(LT, DO1_LOOP);
533 BIND(NOMATCH);
534 mov(result, -1);
535 b(DONE);
536 BIND(MATCH);
537 add(result, result_tmp, cnt1_neg, ASR, 1);
538 BIND(DONE);
539 }
540
541 // Compare strings.
542 void C2_MacroAssembler::string_compare(Register str1, Register str2,
543 Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2,
544 FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, int ae) {
545 Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB,
546 DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT,
547 SHORT_LOOP_START, TAIL_CHECK;
548
549 bool isLL = ae == StrIntrinsicNode::LL;
550 bool isLU = ae == StrIntrinsicNode::LU;
551 bool isUL = ae == StrIntrinsicNode::UL;
552
553 // The stub threshold for LL strings is: 72 (64 + 8) chars
554 // UU: 36 chars, or 72 bytes (valid for the 64-byte large loop with prefetch)
555 // LU/UL: 24 chars, or 48 bytes (valid for the 16-character loop at least)
556 const u1 stub_threshold = isLL ? 72 : ((isLU || isUL) ? 24 : 36);
557
558 bool str1_isL = isLL || isLU;
559 bool str2_isL = isLL || isUL;
560
561 int str1_chr_shift = str1_isL ? 0 : 1;
562 int str2_chr_shift = str2_isL ? 0 : 1;
563 int str1_chr_size = str1_isL ? 1 : 2;
564 int str2_chr_size = str2_isL ? 1 : 2;
565 int minCharsInWord = isLL ? wordSize : wordSize/2;
566
617 add(cnt1, cnt1, 4);
618 fmovd(tmp1, vtmp);
619 } else { // UL case
620 ldr(tmp1, Address(str1));
621 ldrs(vtmp, Address(str2));
622 cmp(cnt2, stub_threshold);
623 br(GE, STUB);
624 subw(cnt2, cnt2, 4);
625 lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
626 eor(vtmpZ, T16B, vtmpZ, vtmpZ);
627 lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
628 sub(cnt1, zr, cnt2, LSL, str1_chr_shift);
629 zip1(vtmp, T8B, vtmp, vtmpZ);
630 sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
631 add(cnt1, cnt1, 8);
632 fmovd(tmp2, vtmp);
633 }
634 adds(cnt2, cnt2, isUL ? 4 : 8);
635 br(GE, TAIL);
636 eor(rscratch2, tmp1, tmp2);
637 cbnz(rscratch2, DIFFERENCE);
638 // main loop
639 bind(NEXT_WORD);
640 if (str1_isL == str2_isL) {
641 ldr(tmp1, Address(str1, cnt2));
642 ldr(tmp2, Address(str2, cnt2));
643 adds(cnt2, cnt2, 8);
644 } else if (isLU) {
645 ldrs(vtmp, Address(str1, cnt1));
646 ldr(tmp2, Address(str2, cnt2));
647 add(cnt1, cnt1, 4);
648 zip1(vtmp, T8B, vtmp, vtmpZ);
649 fmovd(tmp1, vtmp);
650 adds(cnt2, cnt2, 8);
651 } else { // UL
652 ldrs(vtmp, Address(str2, cnt2));
653 ldr(tmp1, Address(str1, cnt1));
654 zip1(vtmp, T8B, vtmp, vtmpZ);
655 add(cnt1, cnt1, 8);
656 fmovd(tmp2, vtmp);
657 adds(cnt2, cnt2, 4);
658 }
659 br(GE, TAIL);
660
661 eor(rscratch2, tmp1, tmp2);
662 cbz(rscratch2, NEXT_WORD);
663 b(DIFFERENCE);
664 bind(TAIL);
665 eor(rscratch2, tmp1, tmp2);
666 cbnz(rscratch2, DIFFERENCE);
667 // Last longword. In the case where length == 4 we compare the
668 // same longword twice, but that's still faster than another
669 // conditional branch.
670 if (str1_isL == str2_isL) {
671 ldr(tmp1, Address(str1));
672 ldr(tmp2, Address(str2));
673 } else if (isLU) {
674 ldrs(vtmp, Address(str1));
675 ldr(tmp2, Address(str2));
676 zip1(vtmp, T8B, vtmp, vtmpZ);
677 fmovd(tmp1, vtmp);
678 } else { // UL
679 ldrs(vtmp, Address(str2));
680 ldr(tmp1, Address(str1));
681 zip1(vtmp, T8B, vtmp, vtmpZ);
682 fmovd(tmp2, vtmp);
683 }
684 bind(TAIL_CHECK);
685 eor(rscratch2, tmp1, tmp2);
686 cbz(rscratch2, DONE);
687
688 // Find the first different characters in the longwords and
689 // compute their difference.
690 bind(DIFFERENCE);
691 rev(rscratch2, rscratch2);
692 clz(rscratch2, rscratch2);
693 andr(rscratch2, rscratch2, isLL ? -8 : -16);
694 lsrv(tmp1, tmp1, rscratch2);
695 (this->*ext_chr)(tmp1, tmp1);
696 lsrv(tmp2, tmp2, rscratch2);
697 (this->*ext_chr)(tmp2, tmp2);
698 subw(result, tmp1, tmp2);
699 b(DONE);
700 }
701
702 bind(STUB);
703 RuntimeAddress stub = NULL;
704 switch(ae) {
705 case StrIntrinsicNode::LL:
706 stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_LL());
707 break;
708 case StrIntrinsicNode::UU:
709 stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_UU());
710 break;
|
526 sub(cnt1_neg, zr, cnt1, LSL, 1);
527 BIND(DO1_LOOP);
528 ldrh(ch1, Address(str1, cnt1_neg));
529 cmpw(ch, ch1);
530 br(EQ, MATCH);
531 adds(cnt1_neg, cnt1_neg, 2);
532 br(LT, DO1_LOOP);
533 BIND(NOMATCH);
534 mov(result, -1);
535 b(DONE);
536 BIND(MATCH);
537 add(result, result_tmp, cnt1_neg, ASR, 1);
538 BIND(DONE);
539 }
540
541 // Compare strings.
542 void C2_MacroAssembler::string_compare(Register str1, Register str2,
543 Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2,
544 FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, int ae) {
545 Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB,
546 DIFF, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT,
547 SHORT_LOOP_START, TAIL_CHECK;
548
549 bool isLL = ae == StrIntrinsicNode::LL;
550 bool isLU = ae == StrIntrinsicNode::LU;
551 bool isUL = ae == StrIntrinsicNode::UL;
552
553 // The stub threshold for LL strings is: 72 (64 + 8) chars
554 // UU: 36 chars, or 72 bytes (valid for the 64-byte large loop with prefetch)
555 // LU/UL: 24 chars, or 48 bytes (valid for the 16-character loop at least)
556 const u1 stub_threshold = isLL ? 72 : ((isLU || isUL) ? 24 : 36);
557
558 bool str1_isL = isLL || isLU;
559 bool str2_isL = isLL || isUL;
560
561 int str1_chr_shift = str1_isL ? 0 : 1;
562 int str2_chr_shift = str2_isL ? 0 : 1;
563 int str1_chr_size = str1_isL ? 1 : 2;
564 int str2_chr_size = str2_isL ? 1 : 2;
565 int minCharsInWord = isLL ? wordSize : wordSize/2;
566
617 add(cnt1, cnt1, 4);
618 fmovd(tmp1, vtmp);
619 } else { // UL case
620 ldr(tmp1, Address(str1));
621 ldrs(vtmp, Address(str2));
622 cmp(cnt2, stub_threshold);
623 br(GE, STUB);
624 subw(cnt2, cnt2, 4);
625 lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
626 eor(vtmpZ, T16B, vtmpZ, vtmpZ);
627 lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
628 sub(cnt1, zr, cnt2, LSL, str1_chr_shift);
629 zip1(vtmp, T8B, vtmp, vtmpZ);
630 sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
631 add(cnt1, cnt1, 8);
632 fmovd(tmp2, vtmp);
633 }
634 adds(cnt2, cnt2, isUL ? 4 : 8);
635 br(GE, TAIL);
636 eor(rscratch2, tmp1, tmp2);
637 cbnz(rscratch2, DIFF);
638 // main loop
639 bind(NEXT_WORD);
640 if (str1_isL == str2_isL) {
641 ldr(tmp1, Address(str1, cnt2));
642 ldr(tmp2, Address(str2, cnt2));
643 adds(cnt2, cnt2, 8);
644 } else if (isLU) {
645 ldrs(vtmp, Address(str1, cnt1));
646 ldr(tmp2, Address(str2, cnt2));
647 add(cnt1, cnt1, 4);
648 zip1(vtmp, T8B, vtmp, vtmpZ);
649 fmovd(tmp1, vtmp);
650 adds(cnt2, cnt2, 8);
651 } else { // UL
652 ldrs(vtmp, Address(str2, cnt2));
653 ldr(tmp1, Address(str1, cnt1));
654 zip1(vtmp, T8B, vtmp, vtmpZ);
655 add(cnt1, cnt1, 8);
656 fmovd(tmp2, vtmp);
657 adds(cnt2, cnt2, 4);
658 }
659 br(GE, TAIL);
660
661 eor(rscratch2, tmp1, tmp2);
662 cbz(rscratch2, NEXT_WORD);
663 b(DIFF);
664 bind(TAIL);
665 eor(rscratch2, tmp1, tmp2);
666 cbnz(rscratch2, DIFF);
667 // Last longword. In the case where length == 4 we compare the
668 // same longword twice, but that's still faster than another
669 // conditional branch.
670 if (str1_isL == str2_isL) {
671 ldr(tmp1, Address(str1));
672 ldr(tmp2, Address(str2));
673 } else if (isLU) {
674 ldrs(vtmp, Address(str1));
675 ldr(tmp2, Address(str2));
676 zip1(vtmp, T8B, vtmp, vtmpZ);
677 fmovd(tmp1, vtmp);
678 } else { // UL
679 ldrs(vtmp, Address(str2));
680 ldr(tmp1, Address(str1));
681 zip1(vtmp, T8B, vtmp, vtmpZ);
682 fmovd(tmp2, vtmp);
683 }
684 bind(TAIL_CHECK);
685 eor(rscratch2, tmp1, tmp2);
686 cbz(rscratch2, DONE);
687
688 // Find the first different characters in the longwords and
689 // compute their difference.
690 bind(DIFF);
691 rev(rscratch2, rscratch2);
692 clz(rscratch2, rscratch2);
693 andr(rscratch2, rscratch2, isLL ? -8 : -16);
694 lsrv(tmp1, tmp1, rscratch2);
695 (this->*ext_chr)(tmp1, tmp1);
696 lsrv(tmp2, tmp2, rscratch2);
697 (this->*ext_chr)(tmp2, tmp2);
698 subw(result, tmp1, tmp2);
699 b(DONE);
700 }
701
702 bind(STUB);
703 RuntimeAddress stub = NULL;
704 switch(ae) {
705 case StrIntrinsicNode::LL:
706 stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_LL());
707 break;
708 case StrIntrinsicNode::UU:
709 stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_UU());
710 break;
|