1 /*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
6177
6178 xorptr(tmp, tmp);
6179 if (UseFastStosb) {
6180 shlptr(cnt,3); // convert to number of bytes
6181 rep_stosb();
6182 } else {
6183 NOT_LP64(shlptr(cnt,1);) // convert to number of dwords for 32-bit VM
6184 rep_stos();
6185 }
6186 }
6187
6188 // IndexOf for constant substrings with size >= 8 chars
6189 // which don't need to be loaded through stack.
6190 void MacroAssembler::string_indexofC8(Register str1, Register str2,
6191 Register cnt1, Register cnt2,
6192 int int_cnt2, Register result,
6193 XMMRegister vec, Register tmp) {
6194 ShortBranchVerifier sbv(this);
6195 assert(UseSSE42Intrinsics, "SSE4.2 is required");
6196
6197 // This method uses pcmpestri inxtruction with bound registers
6198 // inputs:
6199 // xmm - substring
6200 // rax - substring length (elements count)
6201 // mem - scanned string
6202 // rdx - string length (elements count)
6203 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
6204 // outputs:
6205 // rcx - matched index in string
6206 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
6207
6208 Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR,
6209 RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR,
6210 MATCH_SUBSTR_HEAD, RELOAD_STR, FOUND_CANDIDATE;
6211
6212 // Note, inline_string_indexOf() generates checks:
6213 // if (substr.count > string.count) return -1;
6214 // if (substr.count == 0) return 0;
6215 assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars");
6216
6217 // Load substring.
6338 } // string_indexofC8
6339
6340 // Small strings are loaded through stack if they cross page boundary.
6341 void MacroAssembler::string_indexof(Register str1, Register str2,
6342 Register cnt1, Register cnt2,
6343 int int_cnt2, Register result,
6344 XMMRegister vec, Register tmp) {
6345 ShortBranchVerifier sbv(this);
6346 assert(UseSSE42Intrinsics, "SSE4.2 is required");
6347 //
6348 // int_cnt2 is length of small (< 8 chars) constant substring
6349 // or (-1) for non constant substring in which case its length
6350 // is in cnt2 register.
6351 //
6352 // Note, inline_string_indexOf() generates checks:
6353 // if (substr.count > string.count) return -1;
6354 // if (substr.count == 0) return 0;
6355 //
6356 assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0");
6357
6358 // This method uses pcmpestri inxtruction with bound registers
6359 // inputs:
6360 // xmm - substring
6361 // rax - substring length (elements count)
6362 // mem - scanned string
6363 // rdx - string length (elements count)
6364 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
6365 // outputs:
6366 // rcx - matched index in string
6367 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
6368
6369 Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR,
6370 RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR,
6371 FOUND_CANDIDATE;
6372
6373 { //========================================================
6374 // We don't know where these strings are located
6375 // and we can't read beyond them. Load them through stack.
6376 Label BIG_STRINGS, CHECK_STR, COPY_SUBSTR, COPY_STR;
6377
6378 movptr(tmp, rsp); // save old SP
6627 cmpl(cnt2, 1);
6628 jcc(Assembler::equal, LENGTH_DIFF_LABEL);
6629
6630 // Check if the strings start at the same location.
6631 cmpptr(str1, str2);
6632 jcc(Assembler::equal, LENGTH_DIFF_LABEL);
6633
6634 Address::ScaleFactor scale = Address::times_2;
6635 int stride = 8;
6636
6637 if (UseAVX >= 2 && UseSSE42Intrinsics) {
6638 Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR;
6639 Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR;
6640 Label COMPARE_TAIL_LONG;
6641 int pcmpmask = 0x19;
6642
6643 // Setup to compare 16-chars (32-bytes) vectors,
6644 // start from first character again because it has aligned address.
6645 int stride2 = 16;
6646 int adr_stride = stride << scale;
6647 int adr_stride2 = stride2 << scale;
6648
6649 assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
6650 // rax and rdx are used by pcmpestri as elements counters
6651 movl(result, cnt2);
6652 andl(cnt2, ~(stride2-1)); // cnt2 holds the vector count
6653 jcc(Assembler::zero, COMPARE_TAIL_LONG);
6654
6655 // fast path : compare first 2 8-char vectors.
6656 bind(COMPARE_16_CHARS);
6657 movdqu(vec1, Address(str1, 0));
6658 pcmpestri(vec1, Address(str2, 0), pcmpmask);
6659 jccb(Assembler::below, COMPARE_INDEX_CHAR);
6660
6661 movdqu(vec1, Address(str1, adr_stride));
6662 pcmpestri(vec1, Address(str2, adr_stride), pcmpmask);
6663 jccb(Assembler::aboveEqual, COMPARE_WIDE_VECTORS);
6664 addl(cnt1, stride);
6665
6666 // Compare the characters at index in cnt1
6667 bind(COMPARE_INDEX_CHAR); //cnt1 has the offset of the mismatching character
6726 jmpb(WHILE_HEAD_LABEL);
6727
6728 bind(COMPARE_SMALL_STR);
6729 } else if (UseSSE42Intrinsics) {
6730 Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
6731 int pcmpmask = 0x19;
6732 // Setup to compare 8-char (16-byte) vectors,
6733 // start from first character again because it has aligned address.
6734 movl(result, cnt2);
6735 andl(cnt2, ~(stride - 1)); // cnt2 holds the vector count
6736 jccb(Assembler::zero, COMPARE_TAIL);
6737
6738 lea(str1, Address(str1, result, scale));
6739 lea(str2, Address(str2, result, scale));
6740 negptr(result);
6741
6742 // pcmpestri
6743 // inputs:
6744 // vec1- substring
6745 // rax - negative string length (elements count)
6746 // mem - scaned string
6747 // rdx - string length (elements count)
6748 // pcmpmask - cmp mode: 11000 (string compare with negated result)
6749 // + 00 (unsigned bytes) or + 01 (unsigned shorts)
6750 // outputs:
6751 // rcx - first mismatched element index
6752 assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
6753
6754 bind(COMPARE_WIDE_VECTORS);
6755 movdqu(vec1, Address(str1, result, scale));
6756 pcmpestri(vec1, Address(str2, result, scale), pcmpmask);
6757 // After pcmpestri cnt1(rcx) contains mismatched element index
6758
6759 jccb(Assembler::below, VECTOR_NOT_EQUAL); // CF==1
6760 addptr(result, stride);
6761 subptr(cnt2, stride);
6762 jccb(Assembler::notZero, COMPARE_WIDE_VECTORS);
6763
6764 // compare wide vectors tail
6765 testptr(result, result);
6766 jccb(Assembler::zero, LENGTH_DIFF_LABEL);
|
1 /*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
6177
6178 xorptr(tmp, tmp);
6179 if (UseFastStosb) {
6180 shlptr(cnt,3); // convert to number of bytes
6181 rep_stosb();
6182 } else {
6183 NOT_LP64(shlptr(cnt,1);) // convert to number of dwords for 32-bit VM
6184 rep_stos();
6185 }
6186 }
6187
6188 // IndexOf for constant substrings with size >= 8 chars
6189 // which don't need to be loaded through stack.
6190 void MacroAssembler::string_indexofC8(Register str1, Register str2,
6191 Register cnt1, Register cnt2,
6192 int int_cnt2, Register result,
6193 XMMRegister vec, Register tmp) {
6194 ShortBranchVerifier sbv(this);
6195 assert(UseSSE42Intrinsics, "SSE4.2 is required");
6196
6197 // This method uses pcmpestri instruction with bound registers
6198 // inputs:
6199 // xmm - substring
6200 // rax - substring length (elements count)
6201 // mem - scanned string
6202 // rdx - string length (elements count)
6203 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
6204 // outputs:
6205 // rcx - matched index in string
6206 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
6207
6208 Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR,
6209 RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR,
6210 MATCH_SUBSTR_HEAD, RELOAD_STR, FOUND_CANDIDATE;
6211
6212 // Note, inline_string_indexOf() generates checks:
6213 // if (substr.count > string.count) return -1;
6214 // if (substr.count == 0) return 0;
6215 assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars");
6216
6217 // Load substring.
6338 } // string_indexofC8
6339
6340 // Small strings are loaded through stack if they cross page boundary.
6341 void MacroAssembler::string_indexof(Register str1, Register str2,
6342 Register cnt1, Register cnt2,
6343 int int_cnt2, Register result,
6344 XMMRegister vec, Register tmp) {
6345 ShortBranchVerifier sbv(this);
6346 assert(UseSSE42Intrinsics, "SSE4.2 is required");
6347 //
6348 // int_cnt2 is length of small (< 8 chars) constant substring
6349 // or (-1) for non constant substring in which case its length
6350 // is in cnt2 register.
6351 //
6352 // Note, inline_string_indexOf() generates checks:
6353 // if (substr.count > string.count) return -1;
6354 // if (substr.count == 0) return 0;
6355 //
6356 assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0");
6357
6358 // This method uses pcmpestri instruction with bound registers
6359 // inputs:
6360 // xmm - substring
6361 // rax - substring length (elements count)
6362 // mem - scanned string
6363 // rdx - string length (elements count)
6364 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
6365 // outputs:
6366 // rcx - matched index in string
6367 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
6368
6369 Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR,
6370 RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR,
6371 FOUND_CANDIDATE;
6372
6373 { //========================================================
6374 // We don't know where these strings are located
6375 // and we can't read beyond them. Load them through stack.
6376 Label BIG_STRINGS, CHECK_STR, COPY_SUBSTR, COPY_STR;
6377
6378 movptr(tmp, rsp); // save old SP
6627 cmpl(cnt2, 1);
6628 jcc(Assembler::equal, LENGTH_DIFF_LABEL);
6629
6630 // Check if the strings start at the same location.
6631 cmpptr(str1, str2);
6632 jcc(Assembler::equal, LENGTH_DIFF_LABEL);
6633
6634 Address::ScaleFactor scale = Address::times_2;
6635 int stride = 8;
6636
6637 if (UseAVX >= 2 && UseSSE42Intrinsics) {
6638 Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR;
6639 Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR;
6640 Label COMPARE_TAIL_LONG;
6641 int pcmpmask = 0x19;
6642
6643 // Setup to compare 16-chars (32-bytes) vectors,
6644 // start from first character again because it has aligned address.
6645 int stride2 = 16;
6646 int adr_stride = stride << scale;
6647
6648 assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
6649 // rax and rdx are used by pcmpestri as elements counters
6650 movl(result, cnt2);
6651 andl(cnt2, ~(stride2-1)); // cnt2 holds the vector count
6652 jcc(Assembler::zero, COMPARE_TAIL_LONG);
6653
6654 // fast path : compare first 2 8-char vectors.
6655 bind(COMPARE_16_CHARS);
6656 movdqu(vec1, Address(str1, 0));
6657 pcmpestri(vec1, Address(str2, 0), pcmpmask);
6658 jccb(Assembler::below, COMPARE_INDEX_CHAR);
6659
6660 movdqu(vec1, Address(str1, adr_stride));
6661 pcmpestri(vec1, Address(str2, adr_stride), pcmpmask);
6662 jccb(Assembler::aboveEqual, COMPARE_WIDE_VECTORS);
6663 addl(cnt1, stride);
6664
6665 // Compare the characters at index in cnt1
6666 bind(COMPARE_INDEX_CHAR); //cnt1 has the offset of the mismatching character
6725 jmpb(WHILE_HEAD_LABEL);
6726
6727 bind(COMPARE_SMALL_STR);
6728 } else if (UseSSE42Intrinsics) {
6729 Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
6730 int pcmpmask = 0x19;
6731 // Setup to compare 8-char (16-byte) vectors,
6732 // start from first character again because it has aligned address.
6733 movl(result, cnt2);
6734 andl(cnt2, ~(stride - 1)); // cnt2 holds the vector count
6735 jccb(Assembler::zero, COMPARE_TAIL);
6736
6737 lea(str1, Address(str1, result, scale));
6738 lea(str2, Address(str2, result, scale));
6739 negptr(result);
6740
6741 // pcmpestri
6742 // inputs:
6743 // vec1- substring
6744 // rax - negative string length (elements count)
6745 // mem - scanned string
6746 // rdx - string length (elements count)
6747 // pcmpmask - cmp mode: 11000 (string compare with negated result)
6748 // + 00 (unsigned bytes) or + 01 (unsigned shorts)
6749 // outputs:
6750 // rcx - first mismatched element index
6751 assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
6752
6753 bind(COMPARE_WIDE_VECTORS);
6754 movdqu(vec1, Address(str1, result, scale));
6755 pcmpestri(vec1, Address(str2, result, scale), pcmpmask);
6756 // After pcmpestri cnt1(rcx) contains mismatched element index
6757
6758 jccb(Assembler::below, VECTOR_NOT_EQUAL); // CF==1
6759 addptr(result, stride);
6760 subptr(cnt2, stride);
6761 jccb(Assembler::notZero, COMPARE_WIDE_VECTORS);
6762
6763 // compare wide vectors tail
6764 testptr(result, result);
6765 jccb(Assembler::zero, LENGTH_DIFF_LABEL);
|