2836 __ delayed()-> stx(G0, base_pointer_arg, nof_bytes_tmp); |
2836 __ delayed()-> stx(G0, base_pointer_arg, nof_bytes_tmp); |
2837 // %%%% this mini-loop must not cross a cache boundary! |
2837 // %%%% this mini-loop must not cross a cache boundary! |
2838 %} |
2838 %} |
2839 |
2839 |
2840 |
2840 |
2841 enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ |
2841 enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{ |
2842 Label Ldone, Lloop; |
2842 Label Ldone, Lloop; |
2843 MacroAssembler _masm(&cbuf); |
2843 MacroAssembler _masm(&cbuf); |
2844 |
2844 |
2845 Register str1_reg = reg_to_register_object($str1$$reg); |
2845 Register str1_reg = reg_to_register_object($str1$$reg); |
2846 Register str2_reg = reg_to_register_object($str2$$reg); |
2846 Register str2_reg = reg_to_register_object($str2$$reg); |
2847 Register tmp1_reg = reg_to_register_object($tmp1$$reg); |
2847 Register cnt1_reg = reg_to_register_object($cnt1$$reg); |
2848 Register tmp2_reg = reg_to_register_object($tmp2$$reg); |
2848 Register cnt2_reg = reg_to_register_object($cnt2$$reg); |
2849 Register result_reg = reg_to_register_object($result$$reg); |
2849 Register result_reg = reg_to_register_object($result$$reg); |
2850 |
2850 |
2851 // Get the first character position in both strings |
2851 assert(result_reg != str1_reg && |
2852 // [8] char array, [12] offset, [16] count |
2852 result_reg != str2_reg && |
2853 int value_offset = java_lang_String:: value_offset_in_bytes(); |
2853 result_reg != cnt1_reg && |
2854 int offset_offset = java_lang_String::offset_offset_in_bytes(); |
2854 result_reg != cnt2_reg , |
2855 int count_offset = java_lang_String:: count_offset_in_bytes(); |
2855 "need different registers"); |
2856 |
|
2857 // load str1 (jchar*) base address into tmp1_reg |
|
2858 __ load_heap_oop(str1_reg, value_offset, tmp1_reg); |
|
2859 __ ld(str1_reg, offset_offset, result_reg); |
|
2860 __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg); |
|
2861 __ ld(str1_reg, count_offset, str1_reg); // hoisted |
|
2862 __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); |
|
2863 __ load_heap_oop(str2_reg, value_offset, tmp2_reg); // hoisted |
|
2864 __ add(result_reg, tmp1_reg, tmp1_reg); |
|
2865 |
|
2866 // load str2 (jchar*) base address into tmp2_reg |
|
2867 // __ ld_ptr(str2_reg, value_offset, tmp2_reg); // hoisted |
|
2868 __ ld(str2_reg, offset_offset, result_reg); |
|
2869 __ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg); |
|
2870 __ ld(str2_reg, count_offset, str2_reg); // hoisted |
|
2871 __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); |
|
2872 __ subcc(str1_reg, str2_reg, O7); // hoisted |
|
2873 __ add(result_reg, tmp2_reg, tmp2_reg); |
|
2874 |
2856 |
2875 // Compute the minimum of the string lengths(str1_reg) and the |
2857 // Compute the minimum of the string lengths(str1_reg) and the |
2876 // difference of the string lengths (stack) |
2858 // difference of the string lengths (stack) |
2877 |
|
2878 // discard string base pointers, after loading up the lengths |
|
2879 // __ ld(str1_reg, count_offset, str1_reg); // hoisted |
|
2880 // __ ld(str2_reg, count_offset, str2_reg); // hoisted |
|
2881 |
2859 |
2882 // See if the lengths are different, and calculate min in str1_reg. |
2860 // See if the lengths are different, and calculate min in str1_reg. |
2883 // Stash diff in O7 in case we need it for a tie-breaker. |
2861 // Stash diff in O7 in case we need it for a tie-breaker. |
2884 Label Lskip; |
2862 Label Lskip; |
2885 // __ subcc(str1_reg, str2_reg, O7); // hoisted |
2863 __ subcc(cnt1_reg, cnt2_reg, O7); |
2886 __ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit |
2864 __ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit |
2887 __ br(Assembler::greater, true, Assembler::pt, Lskip); |
2865 __ br(Assembler::greater, true, Assembler::pt, Lskip); |
2888 // str2 is shorter, so use its count: |
2866 // cnt2 is shorter, so use its count: |
2889 __ delayed()->sll(str2_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit |
2867 __ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit |
2890 __ bind(Lskip); |
2868 __ bind(Lskip); |
2891 |
2869 |
2892 // reallocate str1_reg, str2_reg, result_reg |
2870 // reallocate cnt1_reg, cnt2_reg, result_reg |
2893 // Note: limit_reg holds the string length pre-scaled by 2 |
2871 // Note: limit_reg holds the string length pre-scaled by 2 |
2894 Register limit_reg = str1_reg; |
2872 Register limit_reg = cnt1_reg; |
2895 Register chr2_reg = str2_reg; |
2873 Register chr2_reg = cnt2_reg; |
2896 Register chr1_reg = result_reg; |
2874 Register chr1_reg = result_reg; |
2897 // tmp{12} are the base pointers |
2875 // str{12} are the base pointers |
2898 |
2876 |
2899 // Is the minimum length zero? |
2877 // Is the minimum length zero? |
2900 __ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity |
2878 __ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity |
2901 __ br(Assembler::equal, true, Assembler::pn, Ldone); |
2879 __ br(Assembler::equal, true, Assembler::pn, Ldone); |
2902 __ delayed()->mov(O7, result_reg); // result is difference in lengths |
2880 __ delayed()->mov(O7, result_reg); // result is difference in lengths |
2903 |
2881 |
2904 // Load first characters |
2882 // Load first characters |
2905 __ lduh(tmp1_reg, 0, chr1_reg); |
2883 __ lduh(str1_reg, 0, chr1_reg); |
2906 __ lduh(tmp2_reg, 0, chr2_reg); |
2884 __ lduh(str2_reg, 0, chr2_reg); |
2907 |
2885 |
2908 // Compare first characters |
2886 // Compare first characters |
2909 __ subcc(chr1_reg, chr2_reg, chr1_reg); |
2887 __ subcc(chr1_reg, chr2_reg, chr1_reg); |
2910 __ br(Assembler::notZero, false, Assembler::pt, Ldone); |
2888 __ br(Assembler::notZero, false, Assembler::pt, Ldone); |
2911 assert(chr1_reg == result_reg, "result must be pre-placed"); |
2889 assert(chr1_reg == result_reg, "result must be pre-placed"); |
2930 |
2908 |
2931 __ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg); |
2909 __ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg); |
2932 __ br(Assembler::equal, true, Assembler::pn, Ldone); |
2910 __ br(Assembler::equal, true, Assembler::pn, Ldone); |
2933 __ delayed()->mov(O7, result_reg); // result is difference in lengths |
2911 __ delayed()->mov(O7, result_reg); // result is difference in lengths |
2934 |
2912 |
2935 // Shift tmp1_reg and tmp2_reg to the end of the arrays, negate limit |
2913 // Shift str1_reg and str2_reg to the end of the arrays, negate limit |
2936 __ add(tmp1_reg, limit_reg, tmp1_reg); |
2914 __ add(str1_reg, limit_reg, str1_reg); |
2937 __ add(tmp2_reg, limit_reg, tmp2_reg); |
2915 __ add(str2_reg, limit_reg, str2_reg); |
2938 __ neg(chr1_reg, limit_reg); // limit = -(limit-2) |
2916 __ neg(chr1_reg, limit_reg); // limit = -(limit-2) |
2939 |
2917 |
2940 // Compare the rest of the characters |
2918 // Compare the rest of the characters |
2941 __ lduh(tmp1_reg, limit_reg, chr1_reg); |
2919 __ lduh(str1_reg, limit_reg, chr1_reg); |
2942 __ bind(Lloop); |
2920 __ bind(Lloop); |
2943 // __ lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted |
2921 // __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted |
2944 __ lduh(tmp2_reg, limit_reg, chr2_reg); |
2922 __ lduh(str2_reg, limit_reg, chr2_reg); |
2945 __ subcc(chr1_reg, chr2_reg, chr1_reg); |
2923 __ subcc(chr1_reg, chr2_reg, chr1_reg); |
2946 __ br(Assembler::notZero, false, Assembler::pt, Ldone); |
2924 __ br(Assembler::notZero, false, Assembler::pt, Ldone); |
2947 assert(chr1_reg == result_reg, "result must be pre-placed"); |
2925 assert(chr1_reg == result_reg, "result must be pre-placed"); |
2948 __ delayed()->inccc(limit_reg, sizeof(jchar)); |
2926 __ delayed()->inccc(limit_reg, sizeof(jchar)); |
2949 // annul LDUH if branch is not taken to prevent access past end of string |
2927 // annul LDUH if branch is not taken to prevent access past end of string |
2950 __ br(Assembler::notZero, true, Assembler::pt, Lloop); |
2928 __ br(Assembler::notZero, true, Assembler::pt, Lloop); |
2951 __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted |
2929 __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted |
2952 |
2930 |
2953 // If strings are equal up to min length, return the length difference. |
2931 // If strings are equal up to min length, return the length difference. |
2954 __ mov(O7, result_reg); |
2932 __ mov(O7, result_reg); |
2955 |
2933 |
2956 // Otherwise, return the difference between the first mismatched chars. |
2934 // Otherwise, return the difference between the first mismatched chars. |
2957 __ bind(Ldone); |
2935 __ bind(Ldone); |
2958 %} |
2936 %} |
2959 |
2937 |
2960 enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ |
2938 enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{ |
2961 Label Lword, Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone; |
2939 Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone; |
2962 MacroAssembler _masm(&cbuf); |
2940 MacroAssembler _masm(&cbuf); |
2963 |
2941 |
2964 Register str1_reg = reg_to_register_object($str1$$reg); |
2942 Register str1_reg = reg_to_register_object($str1$$reg); |
2965 Register str2_reg = reg_to_register_object($str2$$reg); |
2943 Register str2_reg = reg_to_register_object($str2$$reg); |
2966 Register tmp1_reg = reg_to_register_object($tmp1$$reg); |
2944 Register cnt_reg = reg_to_register_object($cnt$$reg); |
2967 Register tmp2_reg = reg_to_register_object($tmp2$$reg); |
2945 Register tmp1_reg = O7; |
2968 Register result_reg = reg_to_register_object($result$$reg); |
2946 Register result_reg = reg_to_register_object($result$$reg); |
2969 |
2947 |
2970 // Get the first character position in both strings |
2948 assert(result_reg != str1_reg && |
2971 // [8] char array, [12] offset, [16] count |
2949 result_reg != str2_reg && |
2972 int value_offset = java_lang_String:: value_offset_in_bytes(); |
2950 result_reg != cnt_reg && |
2973 int offset_offset = java_lang_String::offset_offset_in_bytes(); |
2951 result_reg != tmp1_reg , |
2974 int count_offset = java_lang_String:: count_offset_in_bytes(); |
2952 "need different registers"); |
2975 |
2953 |
2976 // load str1 (jchar*) base address into tmp1_reg |
2954 __ cmp(str1_reg, str2_reg); //same char[] ? |
2977 __ load_heap_oop(Address(str1_reg, value_offset), tmp1_reg); |
|
2978 __ ld(Address(str1_reg, offset_offset), result_reg); |
|
2979 __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg); |
|
2980 __ ld(Address(str1_reg, count_offset), str1_reg); // hoisted |
|
2981 __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); |
|
2982 __ load_heap_oop(Address(str2_reg, value_offset), tmp2_reg); // hoisted |
|
2983 __ add(result_reg, tmp1_reg, tmp1_reg); |
|
2984 |
|
2985 // load str2 (jchar*) base address into tmp2_reg |
|
2986 // __ ld_ptr(Address(str2_reg, value_offset), tmp2_reg); // hoisted |
|
2987 __ ld(Address(str2_reg, offset_offset), result_reg); |
|
2988 __ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg); |
|
2989 __ ld(Address(str2_reg, count_offset), str2_reg); // hoisted |
|
2990 __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); |
|
2991 __ cmp(str1_reg, str2_reg); // hoisted |
|
2992 __ add(result_reg, tmp2_reg, tmp2_reg); |
|
2993 |
|
2994 __ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); |
|
2995 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); |
|
2996 __ delayed()->mov(G0, result_reg); // not equal |
|
2997 |
|
2998 __ br_zero(Assembler::equal, true, Assembler::pn, str1_reg, Ldone); |
|
2999 __ delayed()->add(G0, 1, result_reg); //equals |
|
3000 |
|
3001 __ cmp(tmp1_reg, tmp2_reg); //same string ? |
|
3002 __ brx(Assembler::equal, true, Assembler::pn, Ldone); |
2955 __ brx(Assembler::equal, true, Assembler::pn, Ldone); |
3003 __ delayed()->add(G0, 1, result_reg); |
2956 __ delayed()->add(G0, 1, result_reg); |
3004 |
2957 |
|
2958 __ br_on_reg_cond(Assembler::rc_z, true, Assembler::pn, cnt_reg, Ldone); |
|
2959 __ delayed()->add(G0, 1, result_reg); // count == 0 |
|
2960 |
3005 //rename registers |
2961 //rename registers |
3006 Register limit_reg = str1_reg; |
2962 Register limit_reg = cnt_reg; |
3007 Register chr2_reg = str2_reg; |
|
3008 Register chr1_reg = result_reg; |
2963 Register chr1_reg = result_reg; |
3009 // tmp{12} are the base pointers |
2964 Register chr2_reg = tmp1_reg; |
3010 |
2965 |
3011 //check for alignment and position the pointers to the ends |
2966 //check for alignment and position the pointers to the ends |
3012 __ or3(tmp1_reg, tmp2_reg, chr1_reg); |
2967 __ or3(str1_reg, str2_reg, chr1_reg); |
3013 __ andcc(chr1_reg, 0x3, chr1_reg); // notZero means at least one not 4-byte aligned |
2968 __ andcc(chr1_reg, 0x3, chr1_reg); |
3014 __ br(Assembler::notZero, false, Assembler::pn, Lchar); |
2969 // notZero means at least one not 4-byte aligned. |
3015 __ delayed()->nop(); |
2970 // We could optimize the case when both arrays are not aligned |
3016 |
2971 // but it is not frequent case and it requires additional checks. |
3017 __ bind(Lword); |
2972 __ br(Assembler::notZero, false, Assembler::pn, Lchar); // char by char compare |
3018 __ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2) |
2973 __ delayed()->sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); // set byte count |
3019 __ andn(limit_reg, 0x3, limit_reg); |
2974 |
3020 __ br_zero(Assembler::zero, false, Assembler::pn, limit_reg, Lpost_word); |
2975 // Compare char[] arrays aligned to 4 bytes. |
3021 __ delayed()->nop(); |
2976 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, |
3022 |
2977 chr1_reg, chr2_reg, Ldone); |
3023 __ add(tmp1_reg, limit_reg, tmp1_reg); |
|
3024 __ add(tmp2_reg, limit_reg, tmp2_reg); |
|
3025 __ neg(limit_reg); |
|
3026 |
|
3027 __ lduw(tmp1_reg, limit_reg, chr1_reg); |
|
3028 __ bind(Lword_loop); |
|
3029 __ lduw(tmp2_reg, limit_reg, chr2_reg); |
|
3030 __ cmp(chr1_reg, chr2_reg); |
|
3031 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); |
|
3032 __ delayed()->mov(G0, result_reg); |
|
3033 __ inccc(limit_reg, 2*sizeof(jchar)); |
|
3034 // annul LDUW if branch i s not taken to prevent access past end of string |
|
3035 __ br(Assembler::notZero, true, Assembler::pt, Lword_loop); //annul on taken |
|
3036 __ delayed()->lduw(tmp1_reg, limit_reg, chr1_reg); // hoisted |
|
3037 |
|
3038 __ bind(Lpost_word); |
|
3039 __ br_zero(Assembler::zero, true, Assembler::pt, O7, Ldone); |
|
3040 __ delayed()->add(G0, 1, result_reg); |
|
3041 |
|
3042 __ lduh(tmp1_reg, 0, chr1_reg); |
|
3043 __ lduh(tmp2_reg, 0, chr2_reg); |
|
3044 __ cmp (chr1_reg, chr2_reg); |
|
3045 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); |
|
3046 __ delayed()->mov(G0, result_reg); |
|
3047 __ ba(false,Ldone); |
2978 __ ba(false,Ldone); |
3048 __ delayed()->add(G0, 1, result_reg); |
2979 __ delayed()->add(G0, 1, result_reg); |
3049 |
2980 |
|
2981 // char by char compare |
3050 __ bind(Lchar); |
2982 __ bind(Lchar); |
3051 __ add(tmp1_reg, limit_reg, tmp1_reg); |
2983 __ add(str1_reg, limit_reg, str1_reg); |
3052 __ add(tmp2_reg, limit_reg, tmp2_reg); |
2984 __ add(str2_reg, limit_reg, str2_reg); |
3053 __ neg(limit_reg); //negate count |
2985 __ neg(limit_reg); //negate count |
3054 |
2986 |
3055 __ lduh(tmp1_reg, limit_reg, chr1_reg); |
2987 __ lduh(str1_reg, limit_reg, chr1_reg); |
|
2988 // Lchar_loop |
3056 __ bind(Lchar_loop); |
2989 __ bind(Lchar_loop); |
3057 __ lduh(tmp2_reg, limit_reg, chr2_reg); |
2990 __ lduh(str2_reg, limit_reg, chr2_reg); |
3058 __ cmp(chr1_reg, chr2_reg); |
2991 __ cmp(chr1_reg, chr2_reg); |
3059 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); |
2992 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); |
3060 __ delayed()->mov(G0, result_reg); //not equal |
2993 __ delayed()->mov(G0, result_reg); //not equal |
3061 __ inccc(limit_reg, sizeof(jchar)); |
2994 __ inccc(limit_reg, sizeof(jchar)); |
3062 // annul LDUH if branch is not taken to prevent access past end of string |
2995 // annul LDUH if branch is not taken to prevent access past end of string |
3063 __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); //annul on taken |
2996 __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); |
3064 __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted |
2997 __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted |
3065 |
2998 |
3066 __ add(G0, 1, result_reg); //equal |
2999 __ add(G0, 1, result_reg); //equal |
3067 |
3000 |
3068 __ bind(Ldone); |
3001 __ bind(Ldone); |
3069 %} |
3002 %} |
3070 |
3003 |
3071 enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ |
3004 enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, notemp_iRegI result) %{ |
3072 Label Lvector, Ldone, Lloop; |
3005 Label Lvector, Ldone, Lloop; |
3073 MacroAssembler _masm(&cbuf); |
3006 MacroAssembler _masm(&cbuf); |
3074 |
3007 |
3075 Register ary1_reg = reg_to_register_object($ary1$$reg); |
3008 Register ary1_reg = reg_to_register_object($ary1$$reg); |
3076 Register ary2_reg = reg_to_register_object($ary2$$reg); |
3009 Register ary2_reg = reg_to_register_object($ary2$$reg); |
3077 Register tmp1_reg = reg_to_register_object($tmp1$$reg); |
3010 Register tmp1_reg = reg_to_register_object($tmp1$$reg); |
3078 Register tmp2_reg = reg_to_register_object($tmp2$$reg); |
3011 Register tmp2_reg = O7; |
3079 Register result_reg = reg_to_register_object($result$$reg); |
3012 Register result_reg = reg_to_register_object($result$$reg); |
3080 |
3013 |
3081 int length_offset = arrayOopDesc::length_offset_in_bytes(); |
3014 int length_offset = arrayOopDesc::length_offset_in_bytes(); |
3082 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); |
3015 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); |
3083 |
3016 |
3099 // return false if the two arrays are not equal length |
3032 // return false if the two arrays are not equal length |
3100 __ cmp(tmp1_reg, tmp2_reg); |
3033 __ cmp(tmp1_reg, tmp2_reg); |
3101 __ br(Assembler::notEqual, true, Assembler::pn, Ldone); |
3034 __ br(Assembler::notEqual, true, Assembler::pn, Ldone); |
3102 __ delayed()->mov(G0, result_reg); // not equal |
3035 __ delayed()->mov(G0, result_reg); // not equal |
3103 |
3036 |
3104 __ br_zero(Assembler::zero, true, Assembler::pn, tmp1_reg, Ldone); |
3037 __ br_on_reg_cond(Assembler::rc_z, true, Assembler::pn, tmp1_reg, Ldone); |
3105 __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal |
3038 __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal |
3106 |
3039 |
3107 // load array addresses |
3040 // load array addresses |
3108 __ add(ary1_reg, base_offset, ary1_reg); |
3041 __ add(ary1_reg, base_offset, ary1_reg); |
3109 __ add(ary2_reg, base_offset, ary2_reg); |
3042 __ add(ary2_reg, base_offset, ary2_reg); |
3110 |
3043 |
3111 // renaming registers |
3044 // renaming registers |
3112 Register chr1_reg = tmp2_reg; // for characters in ary1 |
3045 Register chr1_reg = result_reg; // for characters in ary1 |
3113 Register chr2_reg = result_reg; // for characters in ary2 |
3046 Register chr2_reg = tmp2_reg; // for characters in ary2 |
3114 Register limit_reg = tmp1_reg; // length |
3047 Register limit_reg = tmp1_reg; // length |
3115 |
3048 |
3116 // set byte count |
3049 // set byte count |
3117 __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); |
3050 __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); |
3118 __ andcc(limit_reg, 0x2, chr1_reg); //trailing character ? |
3051 |
3119 __ br(Assembler::zero, false, Assembler::pt, Lvector); |
3052 // Compare char[] arrays aligned to 4 bytes. |
3120 __ delayed()->nop(); |
3053 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, |
3121 |
3054 chr1_reg, chr2_reg, Ldone); |
3122 //compare the trailing char |
|
3123 __ sub(limit_reg, sizeof(jchar), limit_reg); |
|
3124 __ lduh(ary1_reg, limit_reg, chr1_reg); |
|
3125 __ lduh(ary2_reg, limit_reg, chr2_reg); |
|
3126 __ cmp(chr1_reg, chr2_reg); |
|
3127 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); |
|
3128 __ delayed()->mov(G0, result_reg); // not equal |
|
3129 |
|
3130 // only one char ? |
|
3131 __ br_zero(Assembler::zero, true, Assembler::pn, limit_reg, Ldone); |
|
3132 __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal |
|
3133 |
|
3134 __ bind(Lvector); |
|
3135 // Shift ary1_reg and ary2_reg to the end of the arrays, negate limit |
|
3136 __ add(ary1_reg, limit_reg, ary1_reg); |
|
3137 __ add(ary2_reg, limit_reg, ary2_reg); |
|
3138 __ neg(limit_reg, limit_reg); |
|
3139 |
|
3140 __ lduw(ary1_reg, limit_reg, chr1_reg); |
|
3141 __ bind(Lloop); |
|
3142 __ lduw(ary2_reg, limit_reg, chr2_reg); |
|
3143 __ cmp(chr1_reg, chr2_reg); |
|
3144 __ br(Assembler::notEqual, false, Assembler::pt, Ldone); |
|
3145 __ delayed()->mov(G0, result_reg); // not equal |
|
3146 __ inccc(limit_reg, 2*sizeof(jchar)); |
|
3147 // annul LDUW if branch is not taken to prevent access past end of string |
|
3148 __ br(Assembler::notZero, true, Assembler::pt, Lloop); //annul on taken |
|
3149 __ delayed()->lduw(ary1_reg, limit_reg, chr1_reg); // hoisted |
|
3150 |
|
3151 __ add(G0, 1, result_reg); // equals |
3055 __ add(G0, 1, result_reg); // equals |
3152 |
3056 |
3153 __ bind(Ldone); |
3057 __ bind(Ldone); |
3154 %} |
3058 %} |
3155 |
3059 |
9469 " STX G0,[$base+$temp]\t! delay slot" %} |
9373 " STX G0,[$base+$temp]\t! delay slot" %} |
9470 ins_encode( enc_Clear_Array(cnt, base, temp) ); |
9374 ins_encode( enc_Clear_Array(cnt, base, temp) ); |
9471 ins_pipe(long_memory_op); |
9375 ins_pipe(long_memory_op); |
9472 %} |
9376 %} |
9473 |
9377 |
9474 instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, |
9378 instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, |
9475 o7RegI tmp3, flagsReg ccr) %{ |
9379 o7RegI tmp, flagsReg ccr) %{ |
9476 match(Set result (StrComp str1 str2)); |
9380 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); |
9477 effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3); |
9381 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp); |
9478 ins_cost(300); |
9382 ins_cost(300); |
9479 format %{ "String Compare $str1,$str2 -> $result" %} |
9383 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} |
9480 ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, result) ); |
9384 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) ); |
9481 ins_pipe(long_memory_op); |
9385 ins_pipe(long_memory_op); |
9482 %} |
9386 %} |
9483 |
9387 |
9484 instruct string_equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, |
9388 instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, |
9485 o7RegI tmp3, flagsReg ccr) %{ |
9389 o7RegI tmp, flagsReg ccr) %{ |
9486 match(Set result (StrEquals str1 str2)); |
9390 match(Set result (StrEquals (Binary str1 str2) cnt)); |
9487 effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3); |
9391 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr); |
9488 ins_cost(300); |
9392 ins_cost(300); |
9489 format %{ "String Equals $str1,$str2 -> $result" %} |
9393 format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %} |
9490 ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, result) ); |
9394 ins_encode( enc_String_Equals(str1, str2, cnt, result) ); |
9491 ins_pipe(long_memory_op); |
9395 ins_pipe(long_memory_op); |
9492 %} |
9396 %} |
9493 |
9397 |
9494 instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, |
9398 instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, |
9495 flagsReg ccr) %{ |
9399 o7RegI tmp2, flagsReg ccr) %{ |
9496 match(Set result (AryEq ary1 ary2)); |
9400 match(Set result (AryEq ary1 ary2)); |
9497 effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); |
9401 effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); |
9498 ins_cost(300); |
9402 ins_cost(300); |
9499 format %{ "Array Equals $ary1,$ary2 -> $result" %} |
9403 format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %} |
9500 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result)); |
9404 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, result)); |
9501 ins_pipe(long_memory_op); |
9405 ins_pipe(long_memory_op); |
9502 %} |
9406 %} |
9503 |
9407 |
9504 |
9408 |
9505 //---------- Zeros Count Instructions ------------------------------------------ |
9409 //---------- Zeros Count Instructions ------------------------------------------ |