3684 masm.bind (LSuccess) ; 3685 masm.testl (boxReg, 0) ; // set ICC.ZF=1 to indicate success 3686 masm.jmp (DONE_LABEL) ; 3687 } 3688 3689 masm.bind (Stacked) ; 3690 masm.movptr(tmpReg, Address (boxReg, 0)) ; // re-fetch 3691 if (os::is_MP()) { masm.lock(); } 3692 masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box 3693 3694 if (EmitSync & 65536) { 3695 masm.bind (CheckSucc) ; 3696 } 3697 masm.bind(DONE_LABEL); 3698 if (EmitSync & 32768) { 3699 masm.nop(); // avoid branch to branch 3700 } 3701 } 3702 %} 3703 3704 enc_class enc_String_Compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, 3705 rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{ 3706 Label RCX_GOOD_LABEL, LENGTH_DIFF_LABEL, 3707 POP_LABEL, DONE_LABEL, CONT_LABEL, 3708 WHILE_HEAD_LABEL; 3709 MacroAssembler masm(&cbuf); 3710 3711 XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 3712 XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 3713 3714 // Get the first character position in both strings 3715 // [8] char array, [12] offset, [16] count 3716 int value_offset = java_lang_String::value_offset_in_bytes(); 3717 int offset_offset = java_lang_String::offset_offset_in_bytes(); 3718 int count_offset = java_lang_String::count_offset_in_bytes(); 3719 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 3720 3721 masm.load_heap_oop(rax, Address(rsi, value_offset)); 3722 masm.movl(rcx, Address(rsi, offset_offset)); 3723 masm.lea(rax, Address(rax, rcx, Address::times_2, base_offset)); 3724 masm.load_heap_oop(rbx, Address(rdi, value_offset)); 3725 masm.movl(rcx, Address(rdi, offset_offset)); 3726 masm.lea(rbx, Address(rbx, rcx, Address::times_2, base_offset)); 3727 3728 // Compute the minimum of the string lengths(rsi) and the 3729 // difference of the string lengths (stack) 3730 3731 // do the conditional move stuff 3732 masm.movl(rdi, Address(rdi, count_offset)); 3733 masm.movl(rsi, Address(rsi, count_offset)); 3734 masm.movl(rcx, rdi); 3735 masm.subl(rdi, rsi); 3736 masm.push(rdi); 3737 masm.cmov(Assembler::lessEqual, rsi, rcx); 3738 3739 // Is the minimum length zero? 3740 masm.bind(RCX_GOOD_LABEL); 3741 masm.testl(rsi, rsi); 3742 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 3743 3744 // Load first characters 3745 masm.load_unsigned_short(rcx, Address(rbx, 0)); 3746 masm.load_unsigned_short(rdi, Address(rax, 0)); 3747 3748 // Compare first characters 3749 masm.subl(rcx, rdi); 3750 masm.jcc(Assembler::notZero, POP_LABEL); 3751 masm.decrementl(rsi); 3752 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 3753 3754 { 3755 // Check after comparing first character to see if strings are equivalent 3756 Label LSkip2; 3757 // Check if the strings start at same location 3758 masm.cmpptr(rbx, rax); 3759 masm.jccb(Assembler::notEqual, LSkip2); 3760 3761 // Check if the length difference is zero (from stack) 3762 masm.cmpl(Address(rsp, 0), 0x0); 3763 masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL); 3764 3765 // Strings might not be equivalent 3766 masm.bind(LSkip2); 3767 } 3768 3769 // Advance to next character 3770 masm.addptr(rax, 2); 3771 masm.addptr(rbx, 2); 3772 3773 if (UseSSE42Intrinsics) { 3774 // With SSE4.2, use double quad vector compare 3775 Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; 3776 // Setup to compare 16-byte vectors 3777 masm.movl(rdi, rsi); 3778 masm.andl(rsi, 0xfffffff8); // rsi holds the vector count 3779 masm.andl(rdi, 0x00000007); // rdi holds the tail count 3780 masm.testl(rsi, rsi); 3781 masm.jccb(Assembler::zero, COMPARE_TAIL); 3782 3783 masm.lea(rax, Address(rax, rsi, Address::times_2)); 3784 masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 3785 masm.negptr(rsi); 3786 3787 masm.bind(COMPARE_VECTORS); 3788 masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2)); 3789 masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2)); 3790 masm.pxor(tmp1Reg, tmp2Reg); 3791 masm.ptest(tmp1Reg, tmp1Reg); 3792 masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL); 3793 masm.addptr(rsi, 8); 3794 masm.jcc(Assembler::notZero, COMPARE_VECTORS); 3795 masm.jmpb(COMPARE_TAIL); 3796 3797 // Mismatched characters in the vectors 3798 masm.bind(VECTOR_NOT_EQUAL); 3799 masm.lea(rax, Address(rax, rsi, Address::times_2)); 3800 masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 3801 masm.movl(rdi, 8); 3802 3803 // Compare tail (< 8 chars), or rescan last vectors to 3804 // find 1st mismatched characters 3805 masm.bind(COMPARE_TAIL); 3806 masm.testl(rdi, rdi); 3807 masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL); 3808 masm.movl(rsi, rdi); 3809 // Fallthru to tail compare 3810 } 3811 3812 // Shift RAX and RBX to the end of the arrays, negate min 3813 masm.lea(rax, Address(rax, rsi, Address::times_2, 0)); 3814 masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0)); 3815 masm.negptr(rsi); 3816 3817 // Compare the rest of the characters 3818 masm.bind(WHILE_HEAD_LABEL); 3819 masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0)); 3820 masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0)); 3821 masm.subl(rcx, rdi); 3822 masm.jccb(Assembler::notZero, POP_LABEL); 3823 masm.increment(rsi); 3824 masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL); 3825 3826 // Strings are equal up to min length. Return the length difference. 3827 masm.bind(LENGTH_DIFF_LABEL); 3828 masm.pop(rcx); 3829 masm.jmpb(DONE_LABEL); 3830 3831 // Discard the stored length difference 3832 masm.bind(POP_LABEL); 3833 masm.addptr(rsp, 8); 3834 3835 // That's it 3836 masm.bind(DONE_LABEL); 3837 %} 3838 3839 enc_class enc_String_IndexOf(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2, 3840 rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result) %{ 3841 // SSE4.2 version 3842 Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, 3843 SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE; 3844 MacroAssembler masm(&cbuf); 3845 3846 XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 3847 3848 // Get the first character position in both strings 3849 // [8] char array, [12] offset, [16] count 3850 int value_offset = java_lang_String::value_offset_in_bytes(); 3851 int offset_offset = java_lang_String::offset_offset_in_bytes(); 3852 int count_offset = java_lang_String::count_offset_in_bytes(); 3853 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 3854 3855 // Get counts for string and substr 3856 masm.movl(rdx, Address(rsi, count_offset)); 3857 masm.movl(rax, Address(rdi, count_offset)); 3858 // Check for substr count > string count 3859 masm.cmpl(rax, rdx); 3860 masm.jcc(Assembler::greater, RET_NEG_ONE); 3861 3862 // Start the indexOf operation 3863 // Get start addr of string 3864 masm.load_heap_oop(rbx, Address(rsi, value_offset)); 3865 masm.movl(rcx, Address(rsi, offset_offset)); 3866 masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset)); 3867 masm.push(rsi); 3868 3869 // Get start addr of substr 3870 masm.load_heap_oop(rbx, Address(rdi, value_offset)); 3871 masm.movl(rcx, Address(rdi, offset_offset)); 3872 masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset)); 3873 masm.push(rdi); 3874 masm.push(rax); 3875 masm.jmpb(PREP_FOR_SCAN); 3876 3877 // Substr count saved at sp 3878 // Substr saved at sp+8 3879 // String saved at sp+16 3880 3881 // Prep to load substr for scan 3882 masm.bind(LOAD_SUBSTR); 3883 masm.movptr(rdi, Address(rsp, 8)); 3884 masm.movl(rax, Address(rsp, 0)); 3885 3886 // Load substr 3887 masm.bind(PREP_FOR_SCAN); 3888 masm.movdqu(tmp1Reg, Address(rdi, 0)); 3889 masm.addq(rdx, 8); // prime the loop 3890 masm.subptr(rsi, 16); 3891 3892 // Scan string for substr in 16-byte vectors 3893 masm.bind(SCAN_TO_SUBSTR); 3894 masm.subq(rdx, 8); 3895 masm.addptr(rsi, 16); 3896 masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 3897 masm.jcc(Assembler::above, SCAN_TO_SUBSTR); 3898 masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); 3899 3900 // Fallthru: found a potential substr 3901 3902 //Make sure string is still long enough 3903 masm.subl(rdx, rcx); 3904 masm.cmpl(rdx, rax); 3905 masm.jccb(Assembler::negative, RET_NOT_FOUND); 3906 // Compute start addr of substr 3907 masm.lea(rsi, Address(rsi, rcx, Address::times_2)); 3908 masm.movptr(rbx, rsi); 3909 3910 // Compare potential substr 3911 masm.addq(rdx, 8); // prime the loop 3912 masm.addq(rax, 8); 3913 masm.subptr(rsi, 16); 3914 masm.subptr(rdi, 16); 3915 3916 // Scan 16-byte vectors of string and substr 3917 masm.bind(SCAN_SUBSTR); 3918 masm.subq(rax, 8); 3919 masm.subq(rdx, 8); 3920 masm.addptr(rsi, 16); 3921 masm.addptr(rdi, 16); 3922 masm.movdqu(tmp1Reg, Address(rdi, 0)); 3926 3927 // Compute substr offset 3928 masm.movptr(rsi, Address(rsp, 16)); 3929 masm.subptr(rbx, rsi); 3930 masm.shrl(rbx, 1); 3931 masm.jmpb(CLEANUP); 3932 3933 masm.bind(RET_NEG_ONE); 3934 masm.movl(rbx, -1); 3935 masm.jmpb(DONE); 3936 3937 masm.bind(RET_NOT_FOUND); 3938 masm.movl(rbx, -1); 3939 3940 masm.bind(CLEANUP); 3941 masm.addptr(rsp, 24); 3942 3943 masm.bind(DONE); 3944 %} 3945 3946 enc_class enc_String_Equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, 3947 rbx_RegI tmp3, rcx_RegI tmp2, rax_RegI result) %{ 3948 Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR; 3949 MacroAssembler masm(&cbuf); 3950 3951 XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 3952 XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 3953 3954 int value_offset = java_lang_String::value_offset_in_bytes(); 3955 int offset_offset = java_lang_String::offset_offset_in_bytes(); 3956 int count_offset = java_lang_String::count_offset_in_bytes(); 3957 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 3958 3959 // does source == target string? 3960 masm.cmpptr(rdi, rsi); 3961 masm.jcc(Assembler::equal, RET_TRUE); 3962 3963 // get and compare counts 3964 masm.movl(rcx, Address(rdi, count_offset)); 3965 masm.movl(rax, Address(rsi, count_offset)); 3966 masm.cmpl(rcx, rax); 3967 masm.jcc(Assembler::notEqual, RET_FALSE); 3968 masm.testl(rax, rax); 3969 masm.jcc(Assembler::zero, RET_TRUE); 3970 3971 // get source string offset and value 3972 masm.load_heap_oop(rbx, Address(rsi, value_offset)); 3973 masm.movl(rax, Address(rsi, offset_offset)); 3974 masm.lea(rsi, Address(rbx, rax, Address::times_2, base_offset)); 3975 3976 // get compare string offset and value 3977 masm.load_heap_oop(rbx, Address(rdi, value_offset)); 3978 masm.movl(rax, Address(rdi, offset_offset)); 3979 masm.lea(rdi, Address(rbx, rax, Address::times_2, base_offset)); 3980 3981 // Set byte count 3982 masm.shll(rcx, 1); 3983 masm.movl(rax, rcx); 3984 3985 if (UseSSE42Intrinsics) { 3986 // With SSE4.2, use double quad vector compare 3987 Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 3988 // Compare 16-byte vectors 3989 masm.andl(rcx, 0xfffffff0); // vector count (in bytes) 3990 masm.andl(rax, 0x0000000e); // tail count (in bytes) 3991 masm.testl(rcx, rcx); 3992 masm.jccb(Assembler::zero, COMPARE_TAIL); 3993 masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 3994 masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 3995 masm.negptr(rcx); 3996 3997 masm.bind(COMPARE_WIDE_VECTORS); 3998 masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1)); 3999 masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1)); 4000 masm.pxor(tmp1Reg, tmp2Reg); 12079 ins_encode( pxor(dst, dst)); 12080 ins_pipe( fpu_reg_reg ); 12081 %} 12082 12083 12084 // ======================================================================= 12085 // fast clearing of an array 12086 instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, 12087 rFlagsReg cr) 12088 %{ 12089 match(Set dummy (ClearArray cnt base)); 12090 effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); 12091 12092 format %{ "xorl rax, rax\t# ClearArray:\n\t" 12093 "rep stosq\t# Store rax to *rdi++ while rcx--" %} 12094 ins_encode(opc_reg_reg(0x33, RAX, RAX), // xorl %eax, %eax 12095 Opcode(0xF3), Opcode(0x48), Opcode(0xAB)); // rep REX_W stos 12096 ins_pipe(pipe_slow); 12097 %} 12098 12099 instruct string_compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, 12100 rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr) 12101 %{ 12102 match(Set result (StrComp str1 str2)); 12103 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 12104 //ins_cost(300); 12105 12106 format %{ "String Compare $str1, $str2 -> $result // XXX KILL RAX, RBX" %} 12107 ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 12108 ins_pipe( pipe_slow ); 12109 %} 12110 12111 instruct string_indexof(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2, 12112 rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result, rFlagsReg cr) 12113 %{ 12114 predicate(UseSSE42Intrinsics); 12115 match(Set result (StrIndexOf str1 str2)); 12116 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr); 12117 12118 format %{ "String IndexOf $str1,$str2 -> $result // KILL RAX, RCX, RDX" %} 12119 ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 12120 ins_pipe( pipe_slow ); 12121 %} 12122 12123 // fast string equals 12124 instruct string_equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, rbx_RegI tmp3, 12125 rcx_RegI tmp4, rax_RegI result, rFlagsReg cr) 12126 %{ 12127 match(Set result (StrEquals str1 str2)); 12128 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 12129 12130 format %{ "String Equals $str1,$str2 -> $result // KILL RBX, RCX" %} 12131 ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 12132 ins_pipe( pipe_slow ); 12133 %} 12134 12135 // fast array equals 12136 instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, rax_RegI tmp3, 12137 rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr) 12138 %{ 12139 match(Set result (AryEq ary1 ary2)); 12140 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); 12141 //ins_cost(300); 12142 12143 format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %} 12144 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) ); 12145 ins_pipe( pipe_slow ); 12146 %} 12147 12148 //----------Control Flow Instructions------------------------------------------ 12149 // Signed compare Instructions 12150 12151 // XXX more variants!! | 3684 masm.bind (LSuccess) ; 3685 masm.testl (boxReg, 0) ; // set ICC.ZF=1 to indicate success 3686 masm.jmp (DONE_LABEL) ; 3687 } 3688 3689 masm.bind (Stacked) ; 3690 masm.movptr(tmpReg, Address (boxReg, 0)) ; // re-fetch 3691 if (os::is_MP()) { masm.lock(); } 3692 masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box 3693 3694 if (EmitSync & 65536) { 3695 masm.bind (CheckSucc) ; 3696 } 3697 masm.bind(DONE_LABEL); 3698 if (EmitSync & 32768) { 3699 masm.nop(); // avoid branch to branch 3700 } 3701 } 3702 %} 3703 3704 enc_class enc_String_Compare(rdi_RegP str1, rsi_RegP str2, rbx_RegI cnt1, rax_RegI cnt2, 3705 regD tmp1, regD tmp2, rcx_RegI result) %{ 3706 Label RCX_GOOD_LABEL, LENGTH_DIFF_LABEL, 3707 POP_LABEL, DONE_LABEL, CONT_LABEL, 3708 WHILE_HEAD_LABEL; 3709 MacroAssembler masm(&cbuf); 3710 3711 XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 3712 XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 3713 3714 // Compute the minimum of the string lengths(rsi) and the 3715 // difference of the string lengths (stack) 3716 3717 // do the conditional move stuff 3718 masm.movl(rcx, rbx); 3719 masm.subl(rbx, rax); 3720 masm.push(rbx); 3721 masm.cmov(Assembler::lessEqual, rax, rcx); 3722 3723 // Is the minimum length zero? 3724 masm.bind(RCX_GOOD_LABEL); 3725 masm.testl(rax, rax); 3726 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 3727 3728 // Load first characters 3729 masm.load_unsigned_short(rcx, Address(rdi, 0)); 3730 masm.load_unsigned_short(rbx, Address(rsi, 0)); 3731 3732 // Compare first characters 3733 masm.subl(rcx, rbx); 3734 masm.jcc(Assembler::notZero, POP_LABEL); 3735 masm.decrementl(rax); 3736 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 3737 3738 { 3739 // Check after comparing first character to see if strings are equivalent 3740 Label LSkip2; 3741 // Check if the strings start at same location 3742 masm.cmpptr(rdi, rsi); 3743 masm.jccb(Assembler::notEqual, LSkip2); 3744 3745 // Check if the length difference is zero (from stack) 3746 masm.cmpl(Address(rsp, 0), 0x0); 3747 masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL); 3748 3749 // Strings might not be equivalent 3750 masm.bind(LSkip2); 3751 } 3752 3753 // Advance to next character 3754 masm.addptr(rsi, 2); 3755 masm.addptr(rdi, 2); 3756 3757 if (UseSSE42Intrinsics) { 3758 // With SSE4.2, use double quad vector compare 3759 Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; 3760 // Setup to compare 16-byte vectors 3761 masm.movl(rbx, rax); 3762 masm.andl(rax, 0xfffffff8); // rax holds the vector count 3763 masm.andl(rbx, 0x00000007); // rbx holds the tail count 3764 masm.testl(rax, rax); 3765 masm.jccb(Assembler::zero, COMPARE_TAIL); 3766 3767 masm.lea(rsi, Address(rsi, rax, Address::times_2)); 3768 masm.lea(rdi, Address(rdi, rax, Address::times_2)); 3769 masm.negptr(rax); 3770 3771 masm.bind(COMPARE_VECTORS); 3772 masm.movdqu(tmp1Reg, Address(rsi, rax, Address::times_2)); 3773 masm.movdqu(tmp2Reg, Address(rdi, rax, Address::times_2)); 3774 masm.pxor(tmp1Reg, tmp2Reg); 3775 masm.ptest(tmp1Reg, tmp1Reg); 3776 masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL); 3777 masm.addptr(rax, 8); 3778 masm.jcc(Assembler::notZero, COMPARE_VECTORS); 3779 masm.jmpb(COMPARE_TAIL); 3780 3781 // Mismatched characters in the vectors 3782 masm.bind(VECTOR_NOT_EQUAL); 3783 masm.lea(rsi, Address(rsi, rax, Address::times_2)); 3784 masm.lea(rdi, Address(rdi, rax, Address::times_2)); 3785 masm.movl(rbx, 8); 3786 3787 // Compare tail (< 8 chars), or rescan last vectors to 3788 // find 1st mismatched characters 3789 masm.bind(COMPARE_TAIL); 3790 masm.testl(rbx, rbx); 3791 masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL); 3792 masm.movl(rax, rbx); 3793 // Fallthru to tail compare 3794 } 3795 3796 // Shift rsi and rdi to the end of the arrays, negate min 3797 masm.lea(rsi, Address(rsi, rax, Address::times_2, 0)); 3798 masm.lea(rdi, Address(rdi, rax, Address::times_2, 0)); 3799 masm.negptr(rax); 3800 3801 // Compare the rest of the characters 3802 masm.bind(WHILE_HEAD_LABEL); 3803 masm.load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0)); 3804 masm.load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0)); 3805 masm.subl(rcx, rbx); 3806 masm.jccb(Assembler::notZero, POP_LABEL); 3807 masm.increment(rax); 3808 masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL); 3809 3810 // Strings are equal up to min length. Return the length difference. 3811 masm.bind(LENGTH_DIFF_LABEL); 3812 masm.pop(rcx); 3813 masm.jmpb(DONE_LABEL); 3814 3815 // Discard the stored length difference 3816 masm.bind(POP_LABEL); 3817 masm.addptr(rsp, 8); 3818 3819 // That's it 3820 masm.bind(DONE_LABEL); 3821 %} 3822 3823 enc_class enc_String_IndexOf(rsi_RegP str1, rdi_RegP str2, rdx_RegI cnt1, rax_RegI cnt2, 3824 regD tmp1, rcx_RegI tmp2, rbx_RegI result) %{ 3825 // SSE4.2 version 3826 Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, 3827 SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE; 3828 MacroAssembler masm(&cbuf); 3829 3830 XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 3831 3832 // Start the indexOf operation 3833 // Get start addr of string 3834 masm.push(rsi); 3835 3836 // Get start addr of substr 3837 masm.push(rdi); 3838 masm.push(rax); 3839 masm.jmpb(PREP_FOR_SCAN); 3840 3841 // Substr count saved at sp 3842 // Substr saved at sp+8 3843 // String saved at sp+16 3844 3845 // Prep to load substr for scan 3846 masm.bind(LOAD_SUBSTR); 3847 masm.movptr(rdi, Address(rsp, 8)); 3848 masm.movl(rax, Address(rsp, 0)); 3849 3850 // Load substr 3851 masm.bind(PREP_FOR_SCAN); 3852 masm.movdqu(tmp1Reg, Address(rdi, 0)); 3853 masm.addq(rdx, 8); // prime the loop 3854 masm.subptr(rsi, 16); 3855 3856 // Scan string for substr in 16-byte vectors 3857 masm.bind(SCAN_TO_SUBSTR); 3858 masm.subq(rdx, 8); 3859 masm.addptr(rsi, 16); 3860 // pcmpestri 3861 // inputs: 3862 // xmm - substring 3863 // rax - substring length (elements count) 3864 // mem - scaned string 3865 // rdx - string length (elements count) 3866 // outputs: 3867 // rcx - matched index in string 3868 masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 3869 masm.jcc(Assembler::above, SCAN_TO_SUBSTR); 3870 masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); 3871 3872 // Fallthru: found a potential substr 3873 3874 // Make sure string is still long enough 3875 masm.subl(rdx, rcx); 3876 masm.cmpl(rdx, rax); 3877 masm.jccb(Assembler::negative, RET_NOT_FOUND); 3878 // Compute start addr of substr 3879 masm.lea(rsi, Address(rsi, rcx, Address::times_2)); 3880 masm.movptr(rbx, rsi); 3881 3882 // Compare potential substr 3883 masm.addq(rdx, 8); // prime the loop 3884 masm.addq(rax, 8); 3885 masm.subptr(rsi, 16); 3886 masm.subptr(rdi, 16); 3887 3888 // Scan 16-byte vectors of string and substr 3889 masm.bind(SCAN_SUBSTR); 3890 masm.subq(rax, 8); 3891 masm.subq(rdx, 8); 3892 masm.addptr(rsi, 16); 3893 masm.addptr(rdi, 16); 3894 masm.movdqu(tmp1Reg, Address(rdi, 0)); 3898 3899 // Compute substr offset 3900 masm.movptr(rsi, Address(rsp, 16)); 3901 masm.subptr(rbx, rsi); 3902 masm.shrl(rbx, 1); 3903 masm.jmpb(CLEANUP); 3904 3905 masm.bind(RET_NEG_ONE); 3906 masm.movl(rbx, -1); 3907 masm.jmpb(DONE); 3908 3909 masm.bind(RET_NOT_FOUND); 3910 masm.movl(rbx, -1); 3911 3912 masm.bind(CLEANUP); 3913 masm.addptr(rsp, 24); 3914 3915 masm.bind(DONE); 3916 %} 3917 3918 enc_class enc_String_Equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, regD tmp1, 3919 regD tmp2, rbx_RegI tmp3, rax_RegI result) %{ 3920 Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR; 3921 MacroAssembler masm(&cbuf); 3922 3923 XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 3924 XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 3925 3926 // does source == target? 3927 masm.cmpptr(rdi, rsi); 3928 masm.jcc(Assembler::equal, RET_TRUE); 3929 3930 // count == 0 3931 masm.testl(rcx, rcx); 3932 masm.jcc(Assembler::zero, RET_TRUE); 3933 3934 // Set byte count 3935 masm.shll(rcx, 1); 3936 masm.movl(rax, rcx); 3937 3938 if (UseSSE42Intrinsics) { 3939 // With SSE4.2, use double quad vector compare 3940 Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 3941 // Compare 16-byte vectors 3942 masm.andl(rcx, 0xfffffff0); // vector count (in bytes) 3943 masm.andl(rax, 0x0000000e); // tail count (in bytes) 3944 masm.testl(rcx, rcx); 3945 masm.jccb(Assembler::zero, COMPARE_TAIL); 3946 masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 3947 masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 3948 masm.negptr(rcx); 3949 3950 masm.bind(COMPARE_WIDE_VECTORS); 3951 masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1)); 3952 masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1)); 3953 masm.pxor(tmp1Reg, tmp2Reg); 12032 ins_encode( pxor(dst, dst)); 12033 ins_pipe( fpu_reg_reg ); 12034 %} 12035 12036 12037 // ======================================================================= 12038 // fast clearing of an array 12039 instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, 12040 rFlagsReg cr) 12041 %{ 12042 match(Set dummy (ClearArray cnt base)); 12043 effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); 12044 12045 format %{ "xorl rax, rax\t# ClearArray:\n\t" 12046 "rep stosq\t# Store rax to *rdi++ while rcx--" %} 12047 ins_encode(opc_reg_reg(0x33, RAX, RAX), // xorl %eax, %eax 12048 Opcode(0xF3), Opcode(0x48), Opcode(0xAB)); // rep REX_W stos 12049 ins_pipe(pipe_slow); 12050 %} 12051 12052 instruct string_compare(rdi_RegP str1, rsi_RegP str2, rbx_RegI cnt1, rax_RegI cnt2, 12053 regD tmp1, regD tmp2, rcx_RegI result, rFlagsReg cr) 12054 %{ 12055 match(Set result (StrComp (Binary str1 str2) (Binary cnt1 cnt2))); 12056 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); 12057 //ins_cost(300); 12058 12059 format %{ "String Compare $str1,$str2,$cnt1,$cnt2 -> $result // KILL $tmp1, $tmp2" %} 12060 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, tmp1, tmp2, result) ); 12061 ins_pipe( pipe_slow ); 12062 %} 12063 12064 instruct string_indexof(rsi_RegP str1, rdi_RegP str2, rdx_RegI cnt1, rax_RegI cnt2, 12065 regD tmp1, rcx_RegI tmp2, rbx_RegI result, rFlagsReg cr) 12066 %{ 12067 predicate(UseSSE42Intrinsics); 12068 match(Set result (StrIndexOf (Binary str1 str2) (Binary cnt1 cnt2))); 12069 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp2, KILL cr); 12070 12071 format %{ "String IndexOf $str1,$str2,$cnt1,$cnt2 -> $result // KILL $tmp1, $tmp2" %} 12072 ins_encode( enc_String_IndexOf(str1, str2, cnt1, cnt2, tmp1, tmp2, result) ); 12073 ins_pipe( pipe_slow ); 12074 %} 12075 12076 // fast string equals 12077 instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, regD tmp1, regD tmp2, 12078 rbx_RegI tmp3, rax_RegI result, rFlagsReg cr) 12079 %{ 12080 match(Set result (StrEquals (Binary str1 str2) cnt)); 12081 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr); 12082 12083 format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %} 12084 ins_encode( enc_String_Equals(str1, str2, cnt, tmp1, tmp2, tmp3, result) ); 12085 ins_pipe( pipe_slow ); 12086 %} 12087 12088 // fast array equals 12089 instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, rax_RegI tmp3, 12090 rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr) 12091 %{ 12092 match(Set result (AryEq ary1 ary2)); 12093 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); 12094 //ins_cost(300); 12095 12096 format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %} 12097 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) ); 12098 ins_pipe( pipe_slow ); 12099 %} 12100 12101 //----------Control Flow Instructions------------------------------------------ 12102 // Signed compare Instructions 12103 12104 // XXX more variants!! |