2901 FloatRegister Fsrc2 = $primary ? reg_to_SingleFloatRegister_object($src2$$reg) |
2901 FloatRegister Fsrc2 = $primary ? reg_to_SingleFloatRegister_object($src2$$reg) |
2902 : reg_to_DoubleFloatRegister_object($src2$$reg); |
2902 : reg_to_DoubleFloatRegister_object($src2$$reg); |
2903 |
2903 |
2904 // Convert condition code fcc0 into -1,0,1; unordered reports less-than (-1) |
2904 // Convert condition code fcc0 into -1,0,1; unordered reports less-than (-1) |
2905 __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst); |
2905 __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst); |
2906 %} |
|
2907 |
|
2908 |
|
2909 enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{ |
|
2910 Label Ldone, Lloop; |
|
2911 MacroAssembler _masm(&cbuf); |
|
2912 |
|
2913 Register str1_reg = reg_to_register_object($str1$$reg); |
|
2914 Register str2_reg = reg_to_register_object($str2$$reg); |
|
2915 Register cnt1_reg = reg_to_register_object($cnt1$$reg); |
|
2916 Register cnt2_reg = reg_to_register_object($cnt2$$reg); |
|
2917 Register result_reg = reg_to_register_object($result$$reg); |
|
2918 |
|
2919 assert(result_reg != str1_reg && |
|
2920 result_reg != str2_reg && |
|
2921 result_reg != cnt1_reg && |
|
2922 result_reg != cnt2_reg , |
|
2923 "need different registers"); |
|
2924 |
|
2925 // Compute the minimum of the string lengths(str1_reg) and the |
|
2926 // difference of the string lengths (stack) |
|
2927 |
|
2928 // See if the lengths are different, and calculate min in str1_reg. |
|
2929 // Stash diff in O7 in case we need it for a tie-breaker. |
|
2930 Label Lskip; |
|
2931 __ subcc(cnt1_reg, cnt2_reg, O7); |
|
2932 __ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit |
|
2933 __ br(Assembler::greater, true, Assembler::pt, Lskip); |
|
2934 // cnt2 is shorter, so use its count: |
|
2935 __ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit |
|
2936 __ bind(Lskip); |
|
2937 |
|
2938 // reallocate cnt1_reg, cnt2_reg, result_reg |
|
2939 // Note: limit_reg holds the string length pre-scaled by 2 |
|
2940 Register limit_reg = cnt1_reg; |
|
2941 Register chr2_reg = cnt2_reg; |
|
2942 Register chr1_reg = result_reg; |
|
2943 // str{12} are the base pointers |
|
2944 |
|
2945 // Is the minimum length zero? |
|
2946 __ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity |
|
2947 __ br(Assembler::equal, true, Assembler::pn, Ldone); |
|
2948 __ delayed()->mov(O7, result_reg); // result is difference in lengths |
|
2949 |
|
2950 // Load first characters |
|
2951 __ lduh(str1_reg, 0, chr1_reg); |
|
2952 __ lduh(str2_reg, 0, chr2_reg); |
|
2953 |
|
2954 // Compare first characters |
|
2955 __ subcc(chr1_reg, chr2_reg, chr1_reg); |
|
2956 __ br(Assembler::notZero, false, Assembler::pt, Ldone); |
|
2957 assert(chr1_reg == result_reg, "result must be pre-placed"); |
|
2958 __ delayed()->nop(); |
|
2959 |
|
2960 { |
|
2961 // Check after comparing first character to see if strings are equivalent |
|
2962 Label LSkip2; |
|
2963 // Check if the strings start at same location |
|
2964 __ cmp(str1_reg, str2_reg); |
|
2965 __ brx(Assembler::notEqual, true, Assembler::pt, LSkip2); |
|
2966 __ delayed()->nop(); |
|
2967 |
|
2968 // Check if the length difference is zero (in O7) |
|
2969 __ cmp(G0, O7); |
|
2970 __ br(Assembler::equal, true, Assembler::pn, Ldone); |
|
2971 __ delayed()->mov(G0, result_reg); // result is zero |
|
2972 |
|
2973 // Strings might not be equal |
|
2974 __ bind(LSkip2); |
|
2975 } |
|
2976 |
|
2977 // We have no guarantee that on 64 bit the higher half of limit_reg is 0 |
|
2978 __ signx(limit_reg); |
|
2979 |
|
2980 __ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg); |
|
2981 __ br(Assembler::equal, true, Assembler::pn, Ldone); |
|
2982 __ delayed()->mov(O7, result_reg); // result is difference in lengths |
|
2983 |
|
2984 // Shift str1_reg and str2_reg to the end of the arrays, negate limit |
|
2985 __ add(str1_reg, limit_reg, str1_reg); |
|
2986 __ add(str2_reg, limit_reg, str2_reg); |
|
2987 __ neg(chr1_reg, limit_reg); // limit = -(limit-2) |
|
2988 |
|
2989 // Compare the rest of the characters |
|
2990 __ lduh(str1_reg, limit_reg, chr1_reg); |
|
2991 __ bind(Lloop); |
|
2992 // __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted |
|
2993 __ lduh(str2_reg, limit_reg, chr2_reg); |
|
2994 __ subcc(chr1_reg, chr2_reg, chr1_reg); |
|
2995 __ br(Assembler::notZero, false, Assembler::pt, Ldone); |
|
2996 assert(chr1_reg == result_reg, "result must be pre-placed"); |
|
2997 __ delayed()->inccc(limit_reg, sizeof(jchar)); |
|
2998 // annul LDUH if branch is not taken to prevent access past end of string |
|
2999 __ br(Assembler::notZero, true, Assembler::pt, Lloop); |
|
3000 __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted |
|
3001 |
|
3002 // If strings are equal up to min length, return the length difference. |
|
3003 __ mov(O7, result_reg); |
|
3004 |
|
3005 // Otherwise, return the difference between the first mismatched chars. |
|
3006 __ bind(Ldone); |
|
3007 %} |
|
3008 |
|
3009 enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{ |
|
3010 Label Lchar, Lchar_loop, Ldone; |
|
3011 MacroAssembler _masm(&cbuf); |
|
3012 |
|
3013 Register str1_reg = reg_to_register_object($str1$$reg); |
|
3014 Register str2_reg = reg_to_register_object($str2$$reg); |
|
3015 Register cnt_reg = reg_to_register_object($cnt$$reg); |
|
3016 Register tmp1_reg = O7; |
|
3017 Register result_reg = reg_to_register_object($result$$reg); |
|
3018 |
|
3019 assert(result_reg != str1_reg && |
|
3020 result_reg != str2_reg && |
|
3021 result_reg != cnt_reg && |
|
3022 result_reg != tmp1_reg , |
|
3023 "need different registers"); |
|
3024 |
|
3025 __ cmp(str1_reg, str2_reg); //same char[] ? |
|
3026 __ brx(Assembler::equal, true, Assembler::pn, Ldone); |
|
3027 __ delayed()->add(G0, 1, result_reg); |
|
3028 |
|
3029 __ cmp_zero_and_br(Assembler::zero, cnt_reg, Ldone, true, Assembler::pn); |
|
3030 __ delayed()->add(G0, 1, result_reg); // count == 0 |
|
3031 |
|
3032 //rename registers |
|
3033 Register limit_reg = cnt_reg; |
|
3034 Register chr1_reg = result_reg; |
|
3035 Register chr2_reg = tmp1_reg; |
|
3036 |
|
3037 // We have no guarantee that on 64 bit the higher half of limit_reg is 0 |
|
3038 __ signx(limit_reg); |
|
3039 |
|
3040 //check for alignment and position the pointers to the ends |
|
3041 __ or3(str1_reg, str2_reg, chr1_reg); |
|
3042 __ andcc(chr1_reg, 0x3, chr1_reg); |
|
3043 // notZero means at least one not 4-byte aligned. |
|
3044 // We could optimize the case when both arrays are not aligned |
|
3045 // but it is not frequent case and it requires additional checks. |
|
3046 __ br(Assembler::notZero, false, Assembler::pn, Lchar); // char by char compare |
|
3047 __ delayed()->sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); // set byte count |
|
3048 |
|
3049 // Compare char[] arrays aligned to 4 bytes. |
|
3050 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, |
|
3051 chr1_reg, chr2_reg, Ldone); |
|
3052 __ ba(Ldone); |
|
3053 __ delayed()->add(G0, 1, result_reg); |
|
3054 |
|
3055 // char by char compare |
|
3056 __ bind(Lchar); |
|
3057 __ add(str1_reg, limit_reg, str1_reg); |
|
3058 __ add(str2_reg, limit_reg, str2_reg); |
|
3059 __ neg(limit_reg); //negate count |
|
3060 |
|
3061 __ lduh(str1_reg, limit_reg, chr1_reg); |
|
3062 // Lchar_loop |
|
3063 __ bind(Lchar_loop); |
|
3064 __ lduh(str2_reg, limit_reg, chr2_reg); |
|
3065 __ cmp(chr1_reg, chr2_reg); |
|
3066 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); |
|
3067 __ delayed()->mov(G0, result_reg); //not equal |
|
3068 __ inccc(limit_reg, sizeof(jchar)); |
|
3069 // annul LDUH if branch is not taken to prevent access past end of string |
|
3070 __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); |
|
3071 __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted |
|
3072 |
|
3073 __ add(G0, 1, result_reg); //equal |
|
3074 |
|
3075 __ bind(Ldone); |
|
3076 %} |
|
3077 |
|
3078 enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, notemp_iRegI result) %{ |
|
3079 Label Lvector, Ldone, Lloop; |
|
3080 MacroAssembler _masm(&cbuf); |
|
3081 |
|
3082 Register ary1_reg = reg_to_register_object($ary1$$reg); |
|
3083 Register ary2_reg = reg_to_register_object($ary2$$reg); |
|
3084 Register tmp1_reg = reg_to_register_object($tmp1$$reg); |
|
3085 Register tmp2_reg = O7; |
|
3086 Register result_reg = reg_to_register_object($result$$reg); |
|
3087 |
|
3088 int length_offset = arrayOopDesc::length_offset_in_bytes(); |
|
3089 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); |
|
3090 |
|
3091 // return true if the same array |
|
3092 __ cmp(ary1_reg, ary2_reg); |
|
3093 __ brx(Assembler::equal, true, Assembler::pn, Ldone); |
|
3094 __ delayed()->add(G0, 1, result_reg); // equal |
|
3095 |
|
3096 __ br_null(ary1_reg, true, Assembler::pn, Ldone); |
|
3097 __ delayed()->mov(G0, result_reg); // not equal |
|
3098 |
|
3099 __ br_null(ary2_reg, true, Assembler::pn, Ldone); |
|
3100 __ delayed()->mov(G0, result_reg); // not equal |
|
3101 |
|
3102 //load the lengths of arrays |
|
3103 __ ld(Address(ary1_reg, length_offset), tmp1_reg); |
|
3104 __ ld(Address(ary2_reg, length_offset), tmp2_reg); |
|
3105 |
|
3106 // return false if the two arrays are not equal length |
|
3107 __ cmp(tmp1_reg, tmp2_reg); |
|
3108 __ br(Assembler::notEqual, true, Assembler::pn, Ldone); |
|
3109 __ delayed()->mov(G0, result_reg); // not equal |
|
3110 |
|
3111 __ cmp_zero_and_br(Assembler::zero, tmp1_reg, Ldone, true, Assembler::pn); |
|
3112 __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal |
|
3113 |
|
3114 // load array addresses |
|
3115 __ add(ary1_reg, base_offset, ary1_reg); |
|
3116 __ add(ary2_reg, base_offset, ary2_reg); |
|
3117 |
|
3118 // renaming registers |
|
3119 Register chr1_reg = result_reg; // for characters in ary1 |
|
3120 Register chr2_reg = tmp2_reg; // for characters in ary2 |
|
3121 Register limit_reg = tmp1_reg; // length |
|
3122 |
|
3123 // set byte count |
|
3124 __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); |
|
3125 |
|
3126 // Compare char[] arrays aligned to 4 bytes. |
|
3127 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, |
|
3128 chr1_reg, chr2_reg, Ldone); |
|
3129 __ add(G0, 1, result_reg); // equals |
|
3130 |
|
3131 __ bind(Ldone); |
|
3132 %} |
2906 %} |
3133 |
2907 |
3134 enc_class enc_rethrow() %{ |
2908 enc_class enc_rethrow() %{ |
3135 cbuf.set_insts_mark(); |
2909 cbuf.set_insts_mark(); |
3136 Register temp_reg = G3; |
2910 Register temp_reg = G3; |
10273 |
10047 |
10274 %} |
10048 %} |
10275 ins_pipe(long_memory_op); |
10049 ins_pipe(long_memory_op); |
10276 %} |
10050 %} |
10277 |
10051 |
10278 instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, |
10052 instruct string_compareL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, |
10279 o7RegI tmp, flagsReg ccr) %{ |
10053 o7RegI tmp, flagsReg ccr) %{ |
|
10054 predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL); |
10280 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); |
10055 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); |
10281 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp); |
10056 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp); |
10282 ins_cost(300); |
10057 ins_cost(300); |
10283 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} |
10058 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} |
10284 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) ); |
10059 ins_encode %{ |
|
10060 __ string_compare($str1$$Register, $str2$$Register, |
|
10061 $cnt1$$Register, $cnt2$$Register, |
|
10062 $tmp$$Register, $tmp$$Register, |
|
10063 $result$$Register, StrIntrinsicNode::LL); |
|
10064 %} |
10285 ins_pipe(long_memory_op); |
10065 ins_pipe(long_memory_op); |
10286 %} |
10066 %} |
10287 |
10067 |
10288 instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, |
10068 instruct string_compareU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, |
10289 o7RegI tmp, flagsReg ccr) %{ |
10069 o7RegI tmp, flagsReg ccr) %{ |
|
10070 predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU); |
|
10071 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); |
|
10072 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp); |
|
10073 ins_cost(300); |
|
10074 format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} |
|
10075 ins_encode %{ |
|
10076 __ string_compare($str1$$Register, $str2$$Register, |
|
10077 $cnt1$$Register, $cnt2$$Register, |
|
10078 $tmp$$Register, $tmp$$Register, |
|
10079 $result$$Register, StrIntrinsicNode::UU); |
|
10080 %} |
|
10081 ins_pipe(long_memory_op); |
|
10082 %} |
|
10083 |
|
10084 instruct string_compareLU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, |
|
10085 o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{ |
|
10086 predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU); |
|
10087 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); |
|
10088 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2); |
|
10089 ins_cost(300); |
|
10090 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1,$tmp2" %} |
|
10091 ins_encode %{ |
|
10092 __ string_compare($str1$$Register, $str2$$Register, |
|
10093 $cnt1$$Register, $cnt2$$Register, |
|
10094 $tmp1$$Register, $tmp2$$Register, |
|
10095 $result$$Register, StrIntrinsicNode::LU); |
|
10096 %} |
|
10097 ins_pipe(long_memory_op); |
|
10098 %} |
|
10099 |
|
10100 instruct string_compareUL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, |
|
10101 o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{ |
|
10102 predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL); |
|
10103 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); |
|
10104 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2); |
|
10105 ins_cost(300); |
|
10106 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1,$tmp2" %} |
|
10107 ins_encode %{ |
|
10108 __ string_compare($str2$$Register, $str1$$Register, |
|
10109 $cnt2$$Register, $cnt1$$Register, |
|
10110 $tmp1$$Register, $tmp2$$Register, |
|
10111 $result$$Register, StrIntrinsicNode::UL); |
|
10112 %} |
|
10113 ins_pipe(long_memory_op); |
|
10114 %} |
|
10115 |
|
10116 instruct string_equalsL(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, |
|
10117 o7RegI tmp, flagsReg ccr) %{ |
|
10118 predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); |
10290 match(Set result (StrEquals (Binary str1 str2) cnt)); |
10119 match(Set result (StrEquals (Binary str1 str2) cnt)); |
10291 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr); |
10120 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr); |
10292 ins_cost(300); |
10121 ins_cost(300); |
10293 format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %} |
10122 format %{ "String Equals byte[] $str1,$str2,$cnt -> $result // KILL $tmp" %} |
10294 ins_encode( enc_String_Equals(str1, str2, cnt, result) ); |
10123 ins_encode %{ |
|
10124 __ array_equals(false, $str1$$Register, $str2$$Register, |
|
10125 $cnt$$Register, $tmp$$Register, |
|
10126 $result$$Register, true /* byte */); |
|
10127 %} |
10295 ins_pipe(long_memory_op); |
10128 ins_pipe(long_memory_op); |
10296 %} |
10129 %} |
10297 |
10130 |
10298 instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, |
10131 instruct string_equalsU(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, |
10299 o7RegI tmp2, flagsReg ccr) %{ |
10132 o7RegI tmp, flagsReg ccr) %{ |
|
10133 predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); |
|
10134 match(Set result (StrEquals (Binary str1 str2) cnt)); |
|
10135 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr); |
|
10136 ins_cost(300); |
|
10137 format %{ "String Equals char[] $str1,$str2,$cnt -> $result // KILL $tmp" %} |
|
10138 ins_encode %{ |
|
10139 __ array_equals(false, $str1$$Register, $str2$$Register, |
|
10140 $cnt$$Register, $tmp$$Register, |
|
10141 $result$$Register, false /* byte */); |
|
10142 %} |
|
10143 ins_pipe(long_memory_op); |
|
10144 %} |
|
10145 |
|
10146 instruct array_equalsB(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, |
|
10147 o7RegI tmp2, flagsReg ccr) %{ |
|
10148 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); |
10300 match(Set result (AryEq ary1 ary2)); |
10149 match(Set result (AryEq ary1 ary2)); |
10301 effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); |
10150 effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); |
10302 ins_cost(300); |
10151 ins_cost(300); |
10303 format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %} |
10152 format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %} |
10304 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, result)); |
10153 ins_encode %{ |
|
10154 __ array_equals(true, $ary1$$Register, $ary2$$Register, |
|
10155 $tmp1$$Register, $tmp2$$Register, |
|
10156 $result$$Register, true /* byte */); |
|
10157 %} |
|
10158 ins_pipe(long_memory_op); |
|
10159 %} |
|
10160 |
|
10161 instruct array_equalsC(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, |
|
10162 o7RegI tmp2, flagsReg ccr) %{ |
|
10163 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); |
|
10164 match(Set result (AryEq ary1 ary2)); |
|
10165 effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); |
|
10166 ins_cost(300); |
|
10167 format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %} |
|
10168 ins_encode %{ |
|
10169 __ array_equals(true, $ary1$$Register, $ary2$$Register, |
|
10170 $tmp1$$Register, $tmp2$$Register, |
|
10171 $result$$Register, false /* byte */); |
|
10172 %} |
|
10173 ins_pipe(long_memory_op); |
|
10174 %} |
|
10175 |
|
10176 // char[] to byte[] compression |
|
10177 instruct string_compress(o0RegP src, o1RegP dst, g3RegI len, notemp_iRegI result, iRegL tmp, flagsReg ccr) %{ |
|
10178 predicate(UseVIS < 3); |
|
10179 match(Set result (StrCompressedCopy src (Binary dst len))); |
|
10180 effect(TEMP result, TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr); |
|
10181 ins_cost(300); |
|
10182 format %{ "String Compress $src,$dst,$len -> $result // KILL $tmp" %} |
|
10183 ins_encode %{ |
|
10184 Label Ldone; |
|
10185 __ signx($len$$Register); |
|
10186 __ cmp_zero_and_br(Assembler::zero, $len$$Register, Ldone, false, Assembler::pn); |
|
10187 __ delayed()->mov($len$$Register, $result$$Register); // copy count |
|
10188 __ string_compress($src$$Register, $dst$$Register, $len$$Register, $result$$Register, $tmp$$Register, Ldone); |
|
10189 __ bind(Ldone); |
|
10190 %} |
|
10191 ins_pipe(long_memory_op); |
|
10192 %} |
|
10193 |
|
10194 // fast char[] to byte[] compression using VIS instructions |
|
10195 instruct string_compress_fast(o0RegP src, o1RegP dst, g3RegI len, notemp_iRegI result, |
|
10196 iRegL tmp1, iRegL tmp2, iRegL tmp3, iRegL tmp4, |
|
10197 regD ftmp1, regD ftmp2, regD ftmp3, flagsReg ccr) %{ |
|
10198 predicate(UseVIS >= 3); |
|
10199 match(Set result (StrCompressedCopy src (Binary dst len))); |
|
10200 effect(TEMP result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ftmp1, TEMP ftmp2, TEMP ftmp3, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr); |
|
10201 ins_cost(300); |
|
10202 format %{ "String Compress Fast $src,$dst,$len -> $result // KILL $tmp1,$tmp2,$tmp3,$tmp4,$ftmp1,$ftmp2,$ftmp3" %} |
|
10203 ins_encode %{ |
|
10204 Label Ldone; |
|
10205 __ signx($len$$Register); |
|
10206 __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $result$$Register, |
|
10207 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, |
|
10208 $ftmp1$$FloatRegister, $ftmp2$$FloatRegister, $ftmp3$$FloatRegister, Ldone); |
|
10209 __ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone); |
|
10210 __ string_compress($src$$Register, $dst$$Register, $len$$Register, $result$$Register, $tmp1$$Register, Ldone); |
|
10211 __ bind(Ldone); |
|
10212 %} |
|
10213 ins_pipe(long_memory_op); |
|
10214 %} |
|
10215 |
|
10216 // byte[] to char[] inflation |
|
10217 instruct string_inflate(Universe dummy, o0RegP src, o1RegP dst, g3RegI len, |
|
10218 iRegL tmp, flagsReg ccr) %{ |
|
10219 match(Set dummy (StrInflatedCopy src (Binary dst len))); |
|
10220 effect(TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr); |
|
10221 ins_cost(300); |
|
10222 format %{ "String Inflate $src,$dst,$len // KILL $tmp" %} |
|
10223 ins_encode %{ |
|
10224 Label Ldone; |
|
10225 __ signx($len$$Register); |
|
10226 __ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone); |
|
10227 __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, Ldone); |
|
10228 __ bind(Ldone); |
|
10229 %} |
|
10230 ins_pipe(long_memory_op); |
|
10231 %} |
|
10232 |
|
10233 // fast byte[] to char[] inflation using VIS instructions |
|
10234 instruct string_inflate_fast(Universe dummy, o0RegP src, o1RegP dst, g3RegI len, |
|
10235 iRegL tmp, regD ftmp1, regD ftmp2, regD ftmp3, regD ftmp4, flagsReg ccr) %{ |
|
10236 predicate(UseVIS >= 3); |
|
10237 match(Set dummy (StrInflatedCopy src (Binary dst len))); |
|
10238 effect(TEMP tmp, TEMP ftmp1, TEMP ftmp2, TEMP ftmp3, TEMP ftmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr); |
|
10239 ins_cost(300); |
|
10240 format %{ "String Inflate Fast $src,$dst,$len // KILL $tmp,$ftmp1,$ftmp2,$ftmp3,$ftmp4" %} |
|
10241 ins_encode %{ |
|
10242 Label Ldone; |
|
10243 __ signx($len$$Register); |
|
10244 __ string_inflate_16($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, |
|
10245 $ftmp1$$FloatRegister, $ftmp2$$FloatRegister, $ftmp3$$FloatRegister, $ftmp4$$FloatRegister, Ldone); |
|
10246 __ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone); |
|
10247 __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, Ldone); |
|
10248 __ bind(Ldone); |
|
10249 %} |
10305 ins_pipe(long_memory_op); |
10250 ins_pipe(long_memory_op); |
10306 %} |
10251 %} |
10307 |
10252 |
10308 |
10253 |
10309 //---------- Zeros Count Instructions ------------------------------------------ |
10254 //---------- Zeros Count Instructions ------------------------------------------ |