1 /*
2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
4844 b(MATCH);
4845
4846 BIND(DO1_SHORT);
4847 mov(result_tmp, cnt1);
4848 lea(str1, Address(str1, cnt1, Address::uxtw(1)));
4849 sub(cnt1_neg, zr, cnt1, LSL, 1);
4850 BIND(DO1_LOOP);
4851 ldrh(ch1, Address(str1, cnt1_neg));
4852 cmpw(ch, ch1);
4853 br(EQ, MATCH);
4854 adds(cnt1_neg, cnt1_neg, 2);
4855 br(LT, DO1_LOOP);
4856 BIND(NOMATCH);
4857 mov(result, -1);
4858 b(DONE);
4859 BIND(MATCH);
4860 add(result, result_tmp, cnt1_neg, ASR, 1);
4861 BIND(DONE);
4862 }
4863
4864 // Compare strings.
4865 void MacroAssembler::string_compare(Register str1, Register str2,
4866 Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2,
4867 FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, int ae) {
4868 Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB,
4869 DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT,
4870 SHORT_LOOP_START, TAIL_CHECK;
4871
4872 const u1 STUB_THRESHOLD = 64 + 8;
4873 bool isLL = ae == StrIntrinsicNode::LL;
4874 bool isLU = ae == StrIntrinsicNode::LU;
4875 bool isUL = ae == StrIntrinsicNode::UL;
4876
4877 bool str1_isL = isLL || isLU;
4878 bool str2_isL = isLL || isUL;
4879
4880 int str1_chr_shift = str1_isL ? 0 : 1;
4881 int str2_chr_shift = str2_isL ? 0 : 1;
4882 int str1_chr_size = str1_isL ? 1 : 2;
4883 int str2_chr_size = str2_isL ? 1 : 2;
4884 int minCharsInWord = isLL ? wordSize : wordSize/2;
|
1 /*
2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
4844 b(MATCH);
4845
4846 BIND(DO1_SHORT);
4847 mov(result_tmp, cnt1);
4848 lea(str1, Address(str1, cnt1, Address::uxtw(1)));
4849 sub(cnt1_neg, zr, cnt1, LSL, 1);
4850 BIND(DO1_LOOP);
4851 ldrh(ch1, Address(str1, cnt1_neg));
4852 cmpw(ch, ch1);
4853 br(EQ, MATCH);
4854 adds(cnt1_neg, cnt1_neg, 2);
4855 br(LT, DO1_LOOP);
4856 BIND(NOMATCH);
4857 mov(result, -1);
4858 b(DONE);
4859 BIND(MATCH);
4860 add(result, result_tmp, cnt1_neg, ASR, 1);
4861 BIND(DONE);
4862 }
4863
4864 // Summary: Compare strings intrinsic implementation. All combinations of UTF-16
4865 // and Latin1 encodings for both strings are considered. Comparison
4866 // is performed in lexical order.
4867 //
4868 // Input: str1: pointer to 1st string
4869 // str2: pointer to 2nd string
4870 // cnt1: number of bytes in 1st string
4871 // cnt2: number of bytes in 2nd string
4872 //
4873 // Algorithm parameter:
4874 // ae: encodings used in 1st and 2nd strings
4875 //
4876 // Temporary registers:
4877 // tmp1, tmp2, rscratch1, rscratch2: always used
4878 // vtmp1, vtmp2, vtmp3: used in case encodings are different
4879 //
4880 // Output: result - return 0 if strings are equal. Returns positive value
4881 // if 1st string > 2nd string in lexical order. Returns
4882 // negative value if 1st string < 2nd string.
4883 //
4884 // Side effects: str1, str2, cnt1, cnt2, tmp1, tmp2, rscratch1, rscratch2: clobbered.
4885 // vtmp1, vtmp2, vtmp2: clobbered if encodings are different
4886 //
4887 // Additional data: boolean values: isLL, isLU, isUL, str1_isL, str2_isL and
4888 // int minCharInWords are derived from ae parameter based on encodings used
4889 // in strings. Different code is generated depending of these values:
4890 //
4891 // isLL = both strings are Latin1
4892 // isLU = 1st string is Latin1, 2nd string is UTF-16
4893 // isUL = 1st string is UTF-16, 2nd string is Latin1
4894 // str1_isL = 1st string is Latin1
4895 // str2_isL = 2nd string is Latin1
4896 // str1_chr_shift = shift value to convert between characters counter to byte counter for 1st string
4897 // str2_chr_shift = shift value to convert between characters counter to byte counter for 2nd string
4898 // minCharInWords = minimum number of characters that fit in register (8 for LL case, 4 otherwise)
4899 //
4900 //
4901 // PSEUDO CODE:
4902 //
4903 // // N.B.: this pseudo-code doesn't strictly follow implementation details.
4904 // // It is here to help understand the basics. Detailed implementation
4905 // // description is listed after this code.
4906 //
4907 // <convert byte counters cnt1, cnt2 into character counters if UTF-16 encoding is used>;
4908 // result = cnt1 - cnt2; // length difference. Used in if all min(cnt1, cnt2) characters are same
4909 // cnt2 = min(cnt1, cnt2); // amount of characters to check
4910 // if (result <= minCharInWords) { // <= wordSize bytes should be loaded for comparison
4911 // if (cnt2 == 0) return result;
4912 // while (cnt2 != 0) {
4913 // char str1char = str1[0];
4914 // char str2char = str2[0];
4915 // str1 += 1 << str1_chr_shift; // advance pointer by size of str1 character
4916 // str2 += 1 << str2_chr_shift; // advance pointer by size of str2 character
4917 // if (str1[0] != str2[0]) return str1[0] - str2[0];
4918 // cnt2--;
4919 // }
4920 // } else { // > wordSize bytes should be loaded for comparison
4921 // // This code checks string in 8-byte blocks. If encodings are
4922 // // different, Latin1 string will be loaded via 4-byte blocks and then
4923 // // each block will be converted to 8-byte UTF-16 equivalent. Then 8 byte
4924 // // blocks are compared. Each load is 8 characters for LL case and 4
4925 // // characters for LU/UL/UU.
4926 // // This set of instructions (load 8 Latin1 character OR load 4 Latin1
4927 // // characters and convert it to 4 UTF-16 character OR load 4 UTF-16
4928 // // character) is referred as <load-and-probably-convert ...> below.
4929 //
4930 // // First iteration in the loop is unrolled to add initialization.
4931 //
4932 // // The code below calculates addresses of each string last load: addresses
4933 // // of last 8 characters for LL case and last 4 characters otherwise.
4934 // // Then offsets from the addresses to the beginning of the strings are
4935 // // calculated. Offset is then use as loop counter. When offset is >= 0, then
4936 // // only last loads (possible overlapped) are left to be checked.
4937 // // N.B.: in case of same encodings, offsets are the same for both strings.
4938 // // Then offset for 2nd string is used for both strings.
4939 //
4940 // tmp1 = <load-and-probably-convert str1>;
4941 // if (str1 == str2) return result;
4942 // tmp2 = <load-and-probably-convert str2>;
4943 //
4944 // // use special implementation optimized for large strings. See detailed code and stub comments.
4945 // if (cnt2 >= 72) return compare_long_string_implementation(<args>);
4946 //
4947 // cnt2 -= <amount of loaded characters>; // 8 for isLL case. 4 otherwise.
4948 //
4949 // if (str1_isL == str2_isL) {
4950 // // Optional optimization for same encoding cases. Can be applied for all
4951 // // cases, but is faster in same encoding cases only. Without this branch
4952 // // smallest string (8 character for LL and 4 characters for others) would
4953 // // be checked twice.
4954 // if (cnt2 == 0) goto TAIL_CHECK; // no more characters to be loaded. Just check already loaded data.
4955 // }
4956 //
4957 // // calculate addresses of last loads. use str1 and str2 pointers for that
4958 // str1 = str1 + cnt2 << str1_chr_shift;
4959 // str2 = str2 + cnt2 << str2_chr_shift;
4960 //
4961 // // calculate offsets for both strings. cnt1 and cnt2 can be reused
4962 // if (str1_isL != str2_isL) cnt1 = - (cnt2 << str1_chr_shift);
4963 // cnt2 = - (cnt2 << str2_chr_shift);
4964 //
4965 // // increment calculated offsets by the number of already loaded bytes
4966 // if (isLU) cnt1 += 4;
4967 // if (isUL) cnt1 += 8;
4968 // cnt2 += isUL ? 4 : 8;
4969 //
4970 // if (cnt2 >= 0) goto TAIL; // only last loads remains. Still need to check currently loaded data.
4971 //
4972 // rscratch2 = tmp1 BIT_XOR tmp2;
4973 // if (rscratch2 != 0) goto DIFFERENCE;
4974 //
4975 // // main loop. Label = NEXT_WORD
4976 // do {
4977 // tmp1 = <load-and-probably-convert str1 at offset of (str1_isL == str2_isL ? cnt2 : cnt1)>;
4978 // tmp2 = <load-and-probably-convert str2 at offset of cnt2>;
4979 //
4980 // // update offsets by the number of loaded bytes
4981 // cnt2 += isUL ? 4 : 8;
4982 // if (isLU) cnt1 += 4;
4983 // if (isUL) cnt1 += 8;
4984 //
4985 // if (cnt2 >= 0) goto TAIL; // last block left to be loaded. Still need to check currently loaded block.
4986 // rscratch2 = tmp1 BIT_XOR tmp2;
4987 // } while (rscratch2 == 0);
4988 // goto DIFFERENCE:
4989 //
4990 // TAIL: // last block left to be loaded. Still need to check currently loaded block.
4991 // rscratch2 = tmp1 BIT_XOR tmp2;
4992 // if (rscratch2 != 0) goto DIFFERENCE;
4993 // tmp1 = <load-and-probably-convert str1>;
4994 // tmp2 = <load-and-probably-convert str2>;
4995 // // fallthrough to TAIL_CHECK
4996 // TAIL_CHECK:
4997 // rscratch2 = tmp1 BIT_XOR tmp2;
4998 // if (rscratch2 == 0) return result;
4999 // DIFFERENCE: // different character found. Find it and compute difference
5000 // // tmp1 and tmp2 have current data with at least 1 different character.
5001 // // Find index of first such character.
5002 // rscratch2 = REVERSE_BITS(rscratch2);
5003 // rscratch2 = COUNT_LEADING_ZEROES(rscratch2); // position of different bit in current 8 bytes
5004 // rscratch2 = rscratch2 & (isLL ? -8 : -16); // number of bits until (possibly converted) different characters in tmp1 and tmp2
5005 // tmp1 = tmp1 >> rscratch2; // now first character in tmp1 is the one sought for
5006 // tmp1 = tmp1 & (isLL ? 0xFF : 0xFFFF); // only first different character left
5007 // tmp2 = tmp2 >> rscratch2; // now first character in tmp2 is the one sought for
5008 // tmp2 = tmp2 & (isLL ? 0xFF : 0xFFFF); // only first different character left
5009 // result = tmp1 - tmp2;
5010 // }
5011 // return result;
5012 //
5013 //
5014 //
5015 // DETAILED CODE:
5016 //
5017 // if (!str1_isL) cnt1 = cnt1 >> 1; // counter for 1st string (in characters)
5018 // if (!str2_isL) cnt2 = cnt2 >> 1; // counter for 2nd string (in characters)
5019 // result = cnt1 - cnt2; // keep in flags the result of operation
5020 // cnt2 = min(cnt1, cnt2); // implemented as csel instruction using stored flag value above
5021 // bool shortStringsCase = cnt2 <= minCharInWords; // kept in flag
5022 // if (shortStringsCase) goto SHORT_STRING; // separate code for short strings
5023 // if (str1_isL == str2_isL) { // same encoding case
5024 // tmp1 = LOAD8BYTES(str1);
5025 // bool sameString = str1 == str2; // kept in flags
5026 // if (sameString) goto DONE; // the string is the same, return
5027 // tmp2 = LOAD8BYTES(str2);
5028 // bool largeStrings = cnt2 >= 72; // kept in flags
5029 // if (largeStrings) goto STUB; // handled in separate stub implementation for large strings
5030 // cnt2 = cnt2 - minCharsInWord; // decrement counter by the number of loaded characters
5031 // bool noMoreLoadsAvailable = cnt2 == 0; // kept in flags
5032 // if (noMoreLoadsAvailable) goto TAIL_CHECK;
5033 // str2 = str2 + cnt2 << str2_chr_shift; // address of str2 last load
5034 // str1 = str1 + cnt2 << str1_chr_shift; // address of str1 last load
5035 // cnt2 = -(cnt2 << str2_chr_shift); // byte offset to 1st character in each string
5036 // } else if (isLU) {
5037 // vtmp = LOAD4BYTES(str1);
5038 // bool sameString = str1 == str2; // kept in flags
5039 // if (sameString) goto DONE; // return
5040 // tmp2 = LOAD8BYTES(str2);
5041 // bool largeStrings = cnt2 >= 72; // kept in flags
5042 // if (largeStrings) goto STUB; // handled in separate stub implementation for large strings
5043 // cnt2 = cnt2 - 4; // decrement counter by the number of loaded characters
5044 // vtmpz = 0; // implemented as eor
5045 // str1 = str1 + cnt2 << str1_chr_shift; // address of str1 last load
5046 // str2 = str2 + cnt2 << str2_chr_shift; // address of str2 last load
5047 // vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz); // convert Latin1 to UTF16 because it'll be compared with UTF16. Implemented as zip instruction
5048 // cnt1 = -(cnt2 << str1_chr_shift); // byte offset to 1st character in 1st string
5049 // cnt2 = -(cnt2 << str2_chr_shift); // byte offset to 1st character in 2nd string
5050 // cnt1 = cnt1 + 4; // advance 1st string offset by the number of loaded bytes
5051 // tmp1 = vtmp; // move converted characters from FPU register to GPR
5052 // } else { // UL
5053 // tmp1 = LOAD8BYTES(str1);
5054 // bool sameString = str1 == str2; // kept in flags
5055 // if (sameString) goto DONE; // return
5056 // vtmp = LOAD4BYTES(str2);
5057 // bool largeStrings = cnt2 >= 72; // kept in flags
5058 // if (largeStrings) goto STUB; // separate stub implementation for large strings
5059 // cnt2 = cnt2 - 4; // update counter by the number of loaded characters
5060 // str1 = str1 + cnt2 << str1_chr_shift; // address of str1 last load
5061 // vtmpz = 0; // implemented as eor
5062 // str2 = str2 + cnt2 << str2_chr_shift; // address of str2 last load
5063 // cnt1 = -(cnt2 << str1_chr_shift); // byte offset to 1st character in 1st string
5064 // vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz); // convert Latin1 to UTF16 because it'll be compared with UTF16. implemented as zip instruction
5065 // cnt2 = -(cnt2 << str2_chr_shift); // byte offset to 1st character in 2nd string
5066 // cnt1 = cnt1 + 8; // advance 1st string offset by the number of loaded bytes
5067 // tmp2 = vtmp; // move converted characters from FPU register to GPR
5068 // }
5069 // cnt2 = cnt2 + (isUL ? 4 : 8); // update offset by the number of loaded bytes
5070 // bool onlyLastLoadRemains = cnt2 >= 0; // kept in flags
5071 // if (onlyLastLoadRemains) goto TAIL;
5072 // rscratch2 = BIT_XOR(tmp1, tmp2); // current block comparison result
5073 // if (rscratch2 != 0) goto DIFFERENCE; // found different characters in current block
5074 // NEXT_WORD: // main loop
5075 // // implementation for each encoding loads 4 or 8 characters at calculated
5076 // // offsets from each string and convert encodings if necessary. Then offsets
5077 // // are updated.
5078 // if (str1_isL == str2_isL) {
5079 // tmp1 = LOAD8BYTES(str1, cnt2);
5080 // tmp2 = LOAD8BYTES(str2, cnt2);
5081 // cnt2 = cnt2 + 8; // update counter by the number of loaded bytes
5082 // onlyLastLoadRemains = cnt2 >= 0; // kept in flags
5083 // } else if (isLU) {
5084 // vtmp = LOAD4BYTES(str1, cnt1);
5085 // tmp2 = LOAD8BYTES(str2, cnt2);
5086 // cnt1 = cnt1 + 4;
5087 // vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);
5088 // tmp1 = vtmp;
5089 // cnt2 = cnt2 + 8;
5090 // onlyLastLoadRemains = cnt2 >= 0; // kept in flags
5091 // } else { // UL
5092 // vtmp = LOAD4BYTES(str2, cnt2);
5093 // tmp1 = LOAD8BYTES(str1, cnt1);
5094 // vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);
5095 // cnt1 = cnt1 + 8;
5096 // tmp2 = vtmp;
5097 // cnt2 = cnt2 + 4;
5098 // onlyLastLoadRemains = cnt2 >= 0; // kept in flags
5099 // }
5100 // if (onlyLastLoadRemains) goto TAIL;
5101 // rscratch2 = BIT_XOR(tmp1, tmp2); // current block comparison result
5102 // if (rscratch2 == 0) goto NEXT_WORD;
5103 // goto DIFFERENCE;
5104 // TAIL: // check already loaded data and last load
5105 // rscratch2 = BIT_XOR(tmp1, tmp2); // current block comparison result
5106 // if (rscratch2 != 0) goto DIFFERENCE;
5107 //
5108 // // last load (and convert if needed) from each string
5109 // if (str1_isL == str2_isL) {
5110 // tmp1 = LOAD8BYTES(str1);
5111 // tmp2 = LOAD8BYTES(str2);
5112 // } else if (isLU) {
5113 // vtmp = LOAD4BYTES(str1);
5114 // tmp2 = LOAD8BYTES(str2);
5115 // vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);
5116 // tmp1 = vtmp;
5117 // } else { // UL
5118 // vtmp = LOAD4BYTES(str2);
5119 // tmp1 = LOAD8BYTES(str1);
5120 // vtmp = CONVERT_LATIN1_TO_UTF16(vtmp, vtmpz);
5121 // tmp2 = vtmp;
5122 // }
5123 // TAIL_CHECK: // last check
5124 // rscratch2 = BIT_XOR(tmp1, tmp2); // current block comparison result
5125 // if (rscratch2 == 0) goto DONE; // return
5126 // DIFFERENCE:
5127 // rscratch2 = REVERSE_BITS(rscratch2); // It's not possible to count trailing zeroes. Reverse bits and then count leading zeroes instead.
5128 // rscratch2 = COUNT_LEADING_ZEROES(rscratch2); // position of different bit in current 8 bytes
5129 // rscratch2 = rscratch2 & (isLL ? -8 : -16); // number of bits until (possibly converted) different characters in tmp1 and tmp2
5130 // tmp1 = tmp1 >> rscratch2; // first character in tmp1 is the one sought for
5131 // tmp1 = isLL ? UNSIGNED_EXTEND_BYTE2INT(tmp1) : UNSIGNED_EXTEND_SHORT2INT(tmp1); // only first different character left
5132 // tmp2 = tmp2 >> rscratch2; // first character in tmp2 is the one sought for
5133 // tmp2 = isLL ? UNSIGNED_EXTEND_BYTE2INT(tmp2) : UNSIGNED_EXTEND_SHORT2INT(tmp1); // only first different character left
5134 // result = tmp1 - tmp2;
5135 // goto DONE;
5136 // }
5137 //
5138 // STUB:
5139 // <get address of compare_long_string_[LL|UU|LU|UL] stub routine and call it>
5140 // goto DONE;
5141 //
5142 // // Short strings comparison code. Instead of simple per-character loop with
5143 // // load-and-compare code it uses loop than issues 2 per-character loads from
5144 // // each string per iteration. Different registers are used for that to
5145 // // remove dependencies: (tmp1, cnt1) and (tmp2, rscratch1) pairs.
5146 // // First characters loads are issued in pre-loop.
5147 // SHORT_STRING:
5148 // if (cnt2 == 0) goto DONE; // no characters to compare. Length difference (already calculated) should be used as result
5149 // tmp1 = LOAD_STR1_CHAR(str1);
5150 // str1 = str1 + str1_chr_size); // merged with load above as post-increment
5151 // cnt2 = cnt2 - 1; // calculate remaining length after first character is loaded
5152 // bool endReached = cnt2 == 0; // kept in flags
5153 // if (endReached) goto SHORT_LAST_INIT; // load 1 character to complete from 2nd string to complete init and compare it with 1st string character
5154 // cnt1 = LOAD_STR2_CHAR(str2);
5155 // str2 = str2 + str2_chr_size; // merged with load above as post-increment
5156 // goto SHORT_LOOP_START; // per-character loop entry point
5157 // SHORT_LOOP: // per-character loop
5158 // cnt2 = cnt2 - 1; // calculate remaining length
5159 // endReached = cnt2 == 0;
5160 // if (endReached) goto SHORT_LAST_INIT;
5161 // SHORT_LOOP_START: // per-character loop entry point
5162 // tmp2 = LOAD_STR1_CHAR(str1);
5163 // rscratch1 = LOAD_STR2_CHAR(str2);
5164 // bool differentResult = tmp1 != cnt1; // check difference of previously loaded pair of registers while last pair is still loading. Kept in flags
5165 // if (differentResult) goto SHORT_LOOP_TAIL; // calculate character difference and return
5166 // cnt2 = cnt2 - 1; // calculate remaining length
5167 // endReached = cnt2 == 0;
5168 // if (endReached) goto SHORT_LAST2; // last comparison of second pair of registers (tmp2, rscratch1) is left
5169 // tmp1 = LOAD_STR1_CHAR(str1);
5170 // cnt1 = LOAD_STR2_CHAR(str2);
5171 // bool sameResult = tmp2 == rscratch1; // check difference of previously loaded pair of registers while last pair is still loading. Kept in flags
5172 // if (sameResult) goto SHORT_LOOP;
5173 // result = tmp2 - rscratch1;
5174 // goto DONE;
5175 // SHORT_LAST2: // last comparison is left: (tmp2, rscratch1)
5176 // sameResult = tmp2 == rscratch1;
5177 // if (sameResult) goto DONE;
5178 // result = tmp2 - rscratch1;
5179 // goto DONE;
5180 // SHORT_LAST_INIT:
5181 // cnt1 = LOAD_STR2_CHAR(str2);
5182 // SHORT_LAST: // last comparison of second pair of registers (tmp1, cnt1) is left
5183 // sameResult = tmp1 == cnt1;
5184 // if (sameResult) goto DONE;
5185 // result = tmp1 - cnt1;
5186 // DONE:
5187 // return; // result
5188
5189 void MacroAssembler::string_compare(Register str1, Register str2,
5190 Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2,
5191 FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, int ae) {
5192 Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB,
5193 DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT,
5194 SHORT_LOOP_START, TAIL_CHECK;
5195
5196 const u1 STUB_THRESHOLD = 64 + 8;
5197 bool isLL = ae == StrIntrinsicNode::LL;
5198 bool isLU = ae == StrIntrinsicNode::LU;
5199 bool isUL = ae == StrIntrinsicNode::UL;
5200
5201 bool str1_isL = isLL || isLU;
5202 bool str2_isL = isLL || isUL;
5203
5204 int str1_chr_shift = str1_isL ? 0 : 1;
5205 int str2_chr_shift = str2_isL ? 0 : 1;
5206 int str1_chr_size = str1_isL ? 1 : 2;
5207 int str2_chr_size = str2_isL ? 1 : 2;
5208 int minCharsInWord = isLL ? wordSize : wordSize/2;
|