src/cpu/x86/vm/x86_64.ad
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6827605 Sdiff src/cpu/x86/vm

src/cpu/x86/vm/x86_64.ad

Print this page




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!!


src/cpu/x86/vm/x86_64.ad
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File