3684 if (os::is_MP()) { masm.lock(); } 3685 masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses EAX which is box 3686 // Intention fall-thru into DONE_LABEL 3687 3688 3689 // DONE_LABEL is a hot target - we'd really like to place it at the 3690 // start of cache line by padding with NOPs. 3691 // See the AMD and Intel software optimization manuals for the 3692 // most efficient "long" NOP encodings. 3693 // Unfortunately none of our alignment mechanisms suffice. 3694 if ((EmitSync & 65536) == 0) { 3695 masm.bind (CheckSucc) ; 3696 } 3697 masm.bind(DONE_LABEL); 3698 3699 // Avoid branch to branch on AMD processors 3700 if (EmitSync & 32768) { masm.nop() ; } 3701 } 3702 %} 3703 3704 enc_class enc_String_Compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 3705 eAXRegI tmp3, eBXRegI tmp4, eCXRegI result) %{ 3706 Label ECX_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.movptr(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.movptr(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 if (VM_Version::supports_cmov()) { 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.cmovl(Assembler::lessEqual, rsi, rcx); 3738 } else { 3739 masm.movl(rdi, Address(rdi, count_offset)); 3740 masm.movl(rcx, Address(rsi, count_offset)); 3741 masm.movl(rsi, rdi); 3742 masm.subl(rdi, rcx); 3743 masm.push(rdi); 3744 masm.jccb(Assembler::lessEqual, ECX_GOOD_LABEL); 3745 masm.movl(rsi, rcx); 3746 // rsi holds min, rcx is unused 3747 } 3748 3749 // Is the minimum length zero? 3750 masm.bind(ECX_GOOD_LABEL); 3751 masm.testl(rsi, rsi); 3752 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 3753 3754 // Load first characters 3755 masm.load_unsigned_short(rcx, Address(rbx, 0)); 3756 masm.load_unsigned_short(rdi, Address(rax, 0)); 3757 3758 // Compare first characters 3759 masm.subl(rcx, rdi); 3760 masm.jcc(Assembler::notZero, POP_LABEL); 3761 masm.decrementl(rsi); 3762 masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); 3763 3764 { 3765 // Check after comparing first character to see if strings are equivalent 3766 Label LSkip2; 3767 // Check if the strings start at same location 3768 masm.cmpptr(rbx,rax); 3769 masm.jccb(Assembler::notEqual, LSkip2); 3770 3771 // Check if the length difference is zero (from stack) 3772 masm.cmpl(Address(rsp, 0), 0x0); 3773 masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL); 3774 3775 // Strings might not be equivalent 3776 masm.bind(LSkip2); 3777 } 3778 3779 // Advance to next character 3780 masm.addptr(rax, 2); 3781 masm.addptr(rbx, 2); 3782 3783 if (UseSSE42Intrinsics) { 3784 // With SSE4.2, use double quad vector compare 3785 Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; 3786 // Setup to compare 16-byte vectors 3787 masm.movl(rdi, rsi); 3788 masm.andl(rsi, 0xfffffff8); // rsi holds the vector count 3789 masm.andl(rdi, 0x00000007); // rdi holds the tail count 3790 masm.testl(rsi, rsi); 3791 masm.jccb(Assembler::zero, COMPARE_TAIL); 3792 3793 masm.lea(rax, Address(rax, rsi, Address::times_2)); 3794 masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 3795 masm.negl(rsi); 3796 3797 masm.bind(COMPARE_VECTORS); 3798 masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2)); 3799 masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2)); 3800 masm.pxor(tmp1Reg, tmp2Reg); 3801 masm.ptest(tmp1Reg, tmp1Reg); 3802 masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL); 3803 masm.addl(rsi, 8); 3804 masm.jcc(Assembler::notZero, COMPARE_VECTORS); 3805 masm.jmpb(COMPARE_TAIL); 3806 3807 // Mismatched characters in the vectors 3808 masm.bind(VECTOR_NOT_EQUAL); 3809 masm.lea(rax, Address(rax, rsi, Address::times_2)); 3810 masm.lea(rbx, Address(rbx, rsi, Address::times_2)); 3811 masm.movl(rdi, 8); 3812 3813 // Compare tail (< 8 chars), or rescan last vectors to 3814 // find 1st mismatched characters 3815 masm.bind(COMPARE_TAIL); 3816 masm.testl(rdi, rdi); 3817 masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL); 3818 masm.movl(rsi, rdi); 3819 // Fallthru to tail compare 3820 } 3821 3822 //Shift rax, and rbx, to the end of the arrays, negate min 3823 masm.lea(rax, Address(rax, rsi, Address::times_2, 0)); 3824 masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0)); 3825 masm.negl(rsi); 3826 3827 // Compare the rest of the characters 3828 masm.bind(WHILE_HEAD_LABEL); 3829 masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0)); 3830 masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0)); 3831 masm.subl(rcx, rdi); 3832 masm.jccb(Assembler::notZero, POP_LABEL); 3833 masm.incrementl(rsi); 3834 masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL); 3835 3836 // Strings are equal up to min length. Return the length difference. 3837 masm.bind(LENGTH_DIFF_LABEL); 3838 masm.pop(rcx); 3839 masm.jmpb(DONE_LABEL); 3840 3841 // Discard the stored length difference 3842 masm.bind(POP_LABEL); 3843 masm.addptr(rsp, 4); 3844 3845 // That's it 3846 masm.bind(DONE_LABEL); 3847 %} 3848 3849 enc_class enc_String_Equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 3850 eBXRegI tmp3, eCXRegI tmp4, eAXRegI result) %{ 3851 Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR; 3852 MacroAssembler masm(&cbuf); 3853 3854 XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 3855 XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 3856 3857 int value_offset = java_lang_String::value_offset_in_bytes(); 3858 int offset_offset = java_lang_String::offset_offset_in_bytes(); 3859 int count_offset = java_lang_String::count_offset_in_bytes(); 3860 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 3861 3862 // does source == target string? 3863 masm.cmpptr(rdi, rsi); 3864 masm.jcc(Assembler::equal, RET_TRUE); 3865 3866 // get and compare counts 3867 masm.movl(rcx, Address(rdi, count_offset)); 3868 masm.movl(rax, Address(rsi, count_offset)); 3869 masm.cmpl(rcx, rax); 3870 masm.jcc(Assembler::notEqual, RET_FALSE); 3871 masm.testl(rax, rax); 3872 masm.jcc(Assembler::zero, RET_TRUE); 3873 3874 // get source string offset and value 3875 masm.movptr(rbx, Address(rsi, value_offset)); 3876 masm.movl(rax, Address(rsi, offset_offset)); 3877 masm.leal(rsi, Address(rbx, rax, Address::times_2, base_offset)); 3878 3879 // get compare string offset and value 3880 masm.movptr(rbx, Address(rdi, value_offset)); 3881 masm.movl(rax, Address(rdi, offset_offset)); 3882 masm.leal(rdi, Address(rbx, rax, Address::times_2, base_offset)); 3883 3884 // Set byte count 3885 masm.shll(rcx, 1); 3886 masm.movl(rax, rcx); 3887 3888 if (UseSSE42Intrinsics) { 3889 // With SSE4.2, use double quad vector compare 3890 Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 3891 // Compare 16-byte vectors 3892 masm.andl(rcx, 0xfffffff0); // vector count (in bytes) 3893 masm.andl(rax, 0x0000000e); // tail count (in bytes) 3894 masm.testl(rcx, rcx); 3895 masm.jccb(Assembler::zero, COMPARE_TAIL); 3896 masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 3897 masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 3898 masm.negl(rcx); 3899 3900 masm.bind(COMPARE_WIDE_VECTORS); 3901 masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1)); 3902 masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1)); 3903 masm.pxor(tmp1Reg, tmp2Reg); 3904 masm.ptest(tmp1Reg, tmp1Reg); 3905 masm.jccb(Assembler::notZero, RET_FALSE); 3906 masm.addl(rcx, 16); 3907 masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 3908 masm.bind(COMPARE_TAIL); 3909 masm.movl(rcx, rax); 3910 // Fallthru to tail compare 3911 } 3912 3913 // Compare 4-byte vectors 3914 masm.andl(rcx, 0xfffffffc); // vector count (in bytes) 3915 masm.andl(rax, 0x00000002); // tail char (in bytes) 3916 masm.testl(rcx, rcx); 3917 masm.jccb(Assembler::zero, COMPARE_CHAR); 3918 masm.lea(rdi, Address(rdi, rcx, Address::times_1)); 3919 masm.lea(rsi, Address(rsi, rcx, Address::times_1)); 3920 masm.negl(rcx); 3921 3922 masm.bind(COMPARE_VECTORS); 3923 masm.movl(rbx, Address(rdi, rcx, Address::times_1)); 3924 masm.cmpl(rbx, Address(rsi, rcx, Address::times_1)); 3925 masm.jccb(Assembler::notEqual, RET_FALSE); 3926 masm.addl(rcx, 4); 3927 masm.jcc(Assembler::notZero, COMPARE_VECTORS); 3928 3929 // Compare trailing char (final 2 bytes), if any 3930 masm.bind(COMPARE_CHAR); 3931 masm.testl(rax, rax); 3932 masm.jccb(Assembler::zero, RET_TRUE); 3933 masm.load_unsigned_short(rbx, Address(rdi, 0)); 3934 masm.load_unsigned_short(rcx, Address(rsi, 0)); 3935 masm.cmpl(rbx, rcx); 3936 masm.jccb(Assembler::notEqual, RET_FALSE); 3937 3938 masm.bind(RET_TRUE); 3939 masm.movl(rax, 1); // return true 3940 masm.jmpb(DONE); 3941 3942 masm.bind(RET_FALSE); 3943 masm.xorl(rax, rax); // return false 3944 3945 masm.bind(DONE); 3946 %} 3947 3948 enc_class enc_String_IndexOf(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2, 3949 eCXRegI tmp3, eDXRegI tmp4, eBXRegI result) %{ 3950 // SSE4.2 version 3951 Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, 3952 SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE; 3953 MacroAssembler masm(&cbuf); 3954 3955 XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 3956 3957 // Get the first character position in both strings 3958 // [8] char array, [12] offset, [16] count 3959 int value_offset = java_lang_String::value_offset_in_bytes(); 3960 int offset_offset = java_lang_String::offset_offset_in_bytes(); 3961 int count_offset = java_lang_String::count_offset_in_bytes(); 3962 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 3963 3964 // Get counts for string and substr 3965 masm.movl(rdx, Address(rsi, count_offset)); 3966 masm.movl(rax, Address(rdi, count_offset)); 3967 // Check for substr count > string count 3968 masm.cmpl(rax, rdx); 3969 masm.jcc(Assembler::greater, RET_NEG_ONE); 3970 3971 // Start the indexOf operation 3972 // Get start addr of string 3973 masm.movptr(rbx, Address(rsi, value_offset)); 3974 masm.movl(rcx, Address(rsi, offset_offset)); 3975 masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset)); 3976 masm.push(rsi); 3977 3978 // Get start addr of substr 3979 masm.movptr(rbx, Address(rdi, value_offset)); 3980 masm.movl(rcx, Address(rdi, offset_offset)); 3981 masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset)); 3982 masm.push(rdi); 3983 masm.push(rax); 3984 masm.jmpb(PREP_FOR_SCAN); 3985 3986 // Substr count saved at sp 3987 // Substr saved at sp+4 3988 // String saved at sp+8 3989 3990 // Prep to load substr for scan 3991 masm.bind(LOAD_SUBSTR); 3992 masm.movptr(rdi, Address(rsp, 4)); 3993 masm.movl(rax, Address(rsp, 0)); 3994 3995 // Load substr 3996 masm.bind(PREP_FOR_SCAN); 3997 masm.movdqu(tmp1Reg, Address(rdi, 0)); 3998 masm.addl(rdx, 8); // prime the loop 3999 masm.subptr(rsi, 16); 4000 4001 // Scan string for substr in 16-byte vectors 4002 masm.bind(SCAN_TO_SUBSTR); 4003 masm.subl(rdx, 8); 4004 masm.addptr(rsi, 16); 4005 masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 4006 masm.jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0 4007 masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0 4008 4009 // Fallthru: found a potential substr 4010 4011 // Make sure string is still long enough 4012 masm.subl(rdx, rcx); 4013 masm.cmpl(rdx, rax); 4014 masm.jccb(Assembler::negative, RET_NOT_FOUND); 4015 // Compute start addr of substr 4016 masm.lea(rsi, Address(rsi, rcx, Address::times_2)); 4017 masm.movptr(rbx, rsi); 4018 4019 // Compare potential substr 4020 masm.addl(rdx, 8); // prime the loop 4021 masm.addl(rax, 8); 4022 masm.subptr(rsi, 16); 4023 masm.subptr(rdi, 16); 4024 4025 // Scan 16-byte vectors of string and substr 4026 masm.bind(SCAN_SUBSTR); 4027 masm.subl(rax, 8); 4028 masm.subl(rdx, 8); 4029 masm.addptr(rsi, 16); 4030 masm.addptr(rdi, 16); 4031 masm.movdqu(tmp1Reg, Address(rdi, 0)); 4032 masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d); 4033 masm.jcc(Assembler::noOverflow, LOAD_SUBSTR); // OF == 0 4034 masm.jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 4035 4036 // Compute substr offset 4037 masm.movptr(rsi, Address(rsp, 8)); 4038 masm.subptr(rbx, rsi); 4039 masm.shrl(rbx, 1); 4040 masm.jmpb(CLEANUP); 4041 4042 masm.bind(RET_NEG_ONE); 4043 masm.movl(rbx, -1); 4044 masm.jmpb(DONE); 4045 4046 masm.bind(RET_NOT_FOUND); 4047 masm.movl(rbx, -1); 4048 4049 masm.bind(CLEANUP); 4050 masm.addptr(rsp, 12); 4051 4052 masm.bind(DONE); 4053 %} 4054 4055 enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, 4056 eBXRegI tmp3, eDXRegI tmp4, eAXRegI result) %{ 4057 Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; 4058 MacroAssembler masm(&cbuf); 4059 4060 XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg); 4061 XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg); 4062 Register ary1Reg = as_Register($ary1$$reg); 4063 Register ary2Reg = as_Register($ary2$$reg); 4064 Register tmp3Reg = as_Register($tmp3$$reg); 4065 Register tmp4Reg = as_Register($tmp4$$reg); 4066 Register resultReg = as_Register($result$$reg); 4067 4068 int length_offset = arrayOopDesc::length_offset_in_bytes(); 4069 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 4070 4071 // Check the input args 4072 masm.cmpptr(ary1Reg, ary2Reg); 4073 masm.jcc(Assembler::equal, TRUE_LABEL); 4074 masm.testptr(ary1Reg, ary1Reg); 4075 masm.jcc(Assembler::zero, FALSE_LABEL); 4076 masm.testptr(ary2Reg, ary2Reg); 4077 masm.jcc(Assembler::zero, FALSE_LABEL); 4078 4079 // Check the lengths 4080 masm.movl(tmp4Reg, Address(ary1Reg, length_offset)); 4081 masm.movl(resultReg, Address(ary2Reg, length_offset)); 4082 masm.cmpl(tmp4Reg, resultReg); 4083 masm.jcc(Assembler::notEqual, FALSE_LABEL); 4084 masm.testl(resultReg, resultReg); 4085 masm.jcc(Assembler::zero, TRUE_LABEL); 4086 4087 // Load array addrs 4088 masm.lea(ary1Reg, Address(ary1Reg, base_offset)); 4089 masm.lea(ary2Reg, Address(ary2Reg, base_offset)); 4090 4091 // Set byte count 4092 masm.shll(tmp4Reg, 1); 4093 masm.movl(resultReg, tmp4Reg); 4094 4095 if (UseSSE42Intrinsics) { 4096 // With SSE4.2, use double quad vector compare 4097 Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; 4098 // Compare 16-byte vectors 4099 masm.andl(tmp4Reg, 0xfffffff0); // vector count (in bytes) 4100 masm.andl(resultReg, 0x0000000e); // tail count (in bytes) 4101 masm.testl(tmp4Reg, tmp4Reg); 4102 masm.jccb(Assembler::zero, COMPARE_TAIL); 4103 masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 4104 masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 4105 masm.negl(tmp4Reg); 4106 4107 masm.bind(COMPARE_WIDE_VECTORS); 4108 masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 4109 masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 4110 masm.pxor(tmp1Reg, tmp2Reg); 4111 masm.ptest(tmp1Reg, tmp1Reg); 4112 4113 masm.jccb(Assembler::notZero, FALSE_LABEL); 4114 masm.addl(tmp4Reg, 16); 4115 masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); 4116 masm.bind(COMPARE_TAIL); 4117 masm.movl(tmp4Reg, resultReg); 4118 // Fallthru to tail compare 4119 } 4120 4121 // Compare 4-byte vectors 4122 masm.andl(tmp4Reg, 0xfffffffc); // vector count (in bytes) 4123 masm.andl(resultReg, 0x00000002); // tail char (in bytes) 4124 masm.testl(tmp4Reg, tmp4Reg); 4125 masm.jccb(Assembler::zero, COMPARE_CHAR); 4126 masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 4127 masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 4128 masm.negl(tmp4Reg); 4129 4130 masm.bind(COMPARE_VECTORS); 4131 masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1)); 4132 masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1)); 4133 masm.jccb(Assembler::notEqual, FALSE_LABEL); 4134 masm.addl(tmp4Reg, 4); 4135 masm.jcc(Assembler::notZero, COMPARE_VECTORS); 4136 4137 // Compare trailing char (final 2 bytes), if any 4138 masm.bind(COMPARE_CHAR); 4139 masm.testl(resultReg, resultReg); 4140 masm.jccb(Assembler::zero, TRUE_LABEL); 4141 masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0)); 4142 masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0)); 4143 masm.cmpl(tmp3Reg, tmp4Reg); 4144 masm.jccb(Assembler::notEqual, FALSE_LABEL); 4145 4146 masm.bind(TRUE_LABEL); 4147 masm.movl(resultReg, 1); // return true 4148 masm.jmpb(DONE); 4149 4150 masm.bind(FALSE_LABEL); 4151 masm.xorl(resultReg, resultReg); // return false 4152 4153 // That's it 4154 masm.bind(DONE); 4155 %} 4156 4157 enc_class enc_pop_rdx() %{ 4158 emit_opcode(cbuf,0x5A); 4159 %} 4160 4161 enc_class enc_rethrow() %{ 4162 cbuf.set_inst_mark(); 4163 emit_opcode(cbuf, 0xE9); // jmp entry 4164 emit_d32_reloc(cbuf, (int)OptoRuntime::rethrow_stub() - ((int)cbuf.code_end())-4, 4165 runtime_call_Relocation::spec(), RELOC_IMM32 ); 4166 %} 4167 4168 4169 // Convert a double to an int. Java semantics require we do complex 4170 // manglelations in the corner cases. So we set the rounding mode to 4171 // 'zero', store the darned double down as an int, and reset the 4172 // rounding mode to 'nearest'. The hardware throws an exception which 4173 // patches up the correct value directly to the stack. 4174 enc_class D2I_encoding( regD src ) %{ 4175 // Flip to round-to-zero mode. We attempted to allow invalid-op 4176 // exceptions here, so that a NAN or other corner-case value will 12701 format %{ "PXOR $dst,$dst\t! replicate2F" %} 12702 ins_encode( pxor(dst, dst)); 12703 ins_pipe( fpu_reg_reg ); 12704 %} 12705 12706 // ======================================================================= 12707 // fast clearing of an array 12708 instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ 12709 match(Set dummy (ClearArray cnt base)); 12710 effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); 12711 format %{ "SHL ECX,1\t# Convert doublewords to words\n\t" 12712 "XOR EAX,EAX\n\t" 12713 "REP STOS\t# store EAX into [EDI++] while ECX--" %} 12714 opcode(0,0x4); 12715 ins_encode( Opcode(0xD1), RegOpc(ECX), 12716 OpcRegReg(0x33,EAX,EAX), 12717 Opcode(0xF3), Opcode(0xAB) ); 12718 ins_pipe( pipe_slow ); 12719 %} 12720 12721 instruct string_compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 12722 eAXRegI tmp3, eBXRegI tmp4, eCXRegI result, eFlagsReg cr) %{ 12723 match(Set result (StrComp str1 str2)); 12724 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 12725 //ins_cost(300); 12726 12727 format %{ "String Compare $str1,$str2 -> $result // KILL EAX, EBX" %} 12728 ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 12729 ins_pipe( pipe_slow ); 12730 %} 12731 12732 // fast string equals 12733 instruct string_equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2, 12734 eBXRegI tmp3, eCXRegI tmp4, eAXRegI result, eFlagsReg cr) %{ 12735 match(Set result (StrEquals str1 str2)); 12736 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr); 12737 12738 format %{ "String Equals $str1,$str2 -> $result // KILL EBX, ECX" %} 12739 ins_encode( enc_String_Equals(tmp1, tmp2, str1, str2, tmp3, tmp4, result) ); 12740 ins_pipe( pipe_slow ); 12741 %} 12742 12743 instruct string_indexof(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2, 12744 eCXRegI tmp3, eDXRegI tmp4, eBXRegI result, eFlagsReg cr) %{ 12745 predicate(UseSSE42Intrinsics); 12746 match(Set result (StrIndexOf str1 str2)); 12747 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr); 12748 12749 format %{ "String IndexOf $str1,$str2 -> $result // KILL EAX, ECX, EDX" %} 12750 ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) ); 12751 ins_pipe( pipe_slow ); 12752 %} 12753 12754 // fast array equals 12755 instruct array_equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, eBXRegI tmp3, 12756 eDXRegI tmp4, eAXRegI result, eFlagsReg cr) %{ 12757 match(Set result (AryEq ary1 ary2)); 12758 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); 12759 //ins_cost(300); 12760 12761 format %{ "Array Equals $ary1,$ary2 -> $result // KILL EBX, EDX" %} 12762 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) ); 12763 ins_pipe( pipe_slow ); 12764 %} 12765 12766 //----------Control Flow Instructions------------------------------------------ 12767 // Signed compare Instructions 12768 instruct compI_eReg(eFlagsReg cr, eRegI op1, eRegI op2) %{ 12769 match(Set cr (CmpI op1 op2)); 12770 effect( DEF cr, USE op1, USE op2 ); 12771 format %{ "CMP $op1,$op2" %} 12772 opcode(0x3B); /* Opcode 3B /r */ 12773 ins_encode( OpcP, RegReg( op1, op2) ); 12774 ins_pipe( ialu_cr_reg_reg ); 12775 %} 12776 12777 instruct compI_eReg_imm(eFlagsReg cr, eRegI op1, immI op2) %{ 12778 match(Set cr (CmpI op1 op2)); 12779 effect( DEF cr, USE op1 ); 12780 format %{ "CMP $op1,$op2" %} 12781 opcode(0x81,0x07); /* Opcode 81 /7 */ 12782 // ins_encode( RegImm( op1, op2) ); /* Was CmpImm */ | 3684 if (os::is_MP()) { masm.lock(); } 3685 masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses EAX which is box 3686 // Intention fall-thru into DONE_LABEL 3687 3688 3689 // DONE_LABEL is a hot target - we'd really like to place it at the 3690 // start of cache line by padding with NOPs. 3691 // See the AMD and Intel software optimization manuals for the 3692 // most efficient "long" NOP encodings. 3693 // Unfortunately none of our alignment mechanisms suffice. 3694 if ((EmitSync & 65536) == 0) { 3695 masm.bind (CheckSucc) ; 3696 } 3697 masm.bind(DONE_LABEL); 3698 3699 // Avoid branch to branch on AMD processors 3700 if (EmitSync & 32768) { masm.nop() ; } 3701 } 3702 %} 3703 3704 3705 enc_class enc_pop_rdx() %{ 3706 emit_opcode(cbuf,0x5A); 3707 %} 3708 3709 enc_class enc_rethrow() %{ 3710 cbuf.set_inst_mark(); 3711 emit_opcode(cbuf, 0xE9); // jmp entry 3712 emit_d32_reloc(cbuf, (int)OptoRuntime::rethrow_stub() - ((int)cbuf.code_end())-4, 3713 runtime_call_Relocation::spec(), RELOC_IMM32 ); 3714 %} 3715 3716 3717 // Convert a double to an int. Java semantics require we do complex 3718 // manglelations in the corner cases. So we set the rounding mode to 3719 // 'zero', store the darned double down as an int, and reset the 3720 // rounding mode to 'nearest'. The hardware throws an exception which 3721 // patches up the correct value directly to the stack. 3722 enc_class D2I_encoding( regD src ) %{ 3723 // Flip to round-to-zero mode. We attempted to allow invalid-op 3724 // exceptions here, so that a NAN or other corner-case value will 12249 format %{ "PXOR $dst,$dst\t! replicate2F" %} 12250 ins_encode( pxor(dst, dst)); 12251 ins_pipe( fpu_reg_reg ); 12252 %} 12253 12254 // ======================================================================= 12255 // fast clearing of an array 12256 instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ 12257 match(Set dummy (ClearArray cnt base)); 12258 effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); 12259 format %{ "SHL ECX,1\t# Convert doublewords to words\n\t" 12260 "XOR EAX,EAX\n\t" 12261 "REP STOS\t# store EAX into [EDI++] while ECX--" %} 12262 opcode(0,0x4); 12263 ins_encode( Opcode(0xD1), RegOpc(ECX), 12264 OpcRegReg(0x33,EAX,EAX), 12265 Opcode(0xF3), Opcode(0xAB) ); 12266 ins_pipe( pipe_slow ); 12267 %} 12268 12269 instruct string_compare(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eBXRegI cnt2, 12270 eAXRegI result, regXD tmp1, regXD tmp2, eFlagsReg cr) %{ 12271 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 12272 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); 12273 12274 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %} 12275 ins_encode %{ 12276 __ string_compare($str1$$Register, $str2$$Register, 12277 $cnt1$$Register, $cnt2$$Register, $result$$Register, 12278 $tmp1$$XMMRegister, $tmp2$$XMMRegister); 12279 %} 12280 ins_pipe( pipe_slow ); 12281 %} 12282 12283 // fast string equals 12284 instruct string_equals(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result, 12285 regXD tmp1, regXD tmp2, eBXRegI tmp3, eFlagsReg cr) %{ 12286 match(Set result (StrEquals (Binary str1 str2) cnt)); 12287 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr); 12288 12289 format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %} 12290 ins_encode %{ 12291 __ char_arrays_equals(false, $str1$$Register, $str2$$Register, 12292 $cnt$$Register, $result$$Register, $tmp3$$Register, 12293 $tmp1$$XMMRegister, $tmp2$$XMMRegister); 12294 %} 12295 ins_pipe( pipe_slow ); 12296 %} 12297 12298 instruct string_indexof(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, 12299 eBXRegI result, regXD tmp1, eCXRegI tmp2, eFlagsReg cr) %{ 12300 predicate(UseSSE42Intrinsics); 12301 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); 12302 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp2, KILL cr); 12303 12304 format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp2, $tmp1" %} 12305 ins_encode %{ 12306 __ string_indexof($str1$$Register, $str2$$Register, 12307 $cnt1$$Register, $cnt2$$Register, $result$$Register, 12308 $tmp1$$XMMRegister, $tmp2$$Register); 12309 %} 12310 ins_pipe( pipe_slow ); 12311 %} 12312 12313 // fast array equals 12314 instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI result, 12315 regXD tmp1, regXD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr) 12316 %{ 12317 match(Set result (AryEq ary1 ary2)); 12318 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr); 12319 //ins_cost(300); 12320 12321 format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %} 12322 ins_encode %{ 12323 __ char_arrays_equals(true, $ary1$$Register, $ary2$$Register, 12324 $tmp3$$Register, $result$$Register, $tmp4$$Register, 12325 $tmp1$$XMMRegister, $tmp2$$XMMRegister); 12326 %} 12327 ins_pipe( pipe_slow ); 12328 %} 12329 12330 //----------Control Flow Instructions------------------------------------------ 12331 // Signed compare Instructions 12332 instruct compI_eReg(eFlagsReg cr, eRegI op1, eRegI op2) %{ 12333 match(Set cr (CmpI op1 op2)); 12334 effect( DEF cr, USE op1, USE op2 ); 12335 format %{ "CMP $op1,$op2" %} 12336 opcode(0x3B); /* Opcode 3B /r */ 12337 ins_encode( OpcP, RegReg( op1, op2) ); 12338 ins_pipe( ialu_cr_reg_reg ); 12339 %} 12340 12341 instruct compI_eReg_imm(eFlagsReg cr, eRegI op1, immI op2) %{ 12342 match(Set cr (CmpI op1 op2)); 12343 effect( DEF cr, USE op1 ); 12344 format %{ "CMP $op1,$op2" %} 12345 opcode(0x81,0x07); /* Opcode 81 /7 */ 12346 // ins_encode( RegImm( op1, op2) ); /* Was CmpImm */ |