8402 movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); |
8402 movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); |
8403 } |
8403 } |
8404 } |
8404 } |
8405 #endif // _LP64 |
8405 #endif // _LP64 |
8406 |
8406 |
|
8407 // IndexOf substring. |
|
8408 void MacroAssembler::string_indexof(Register str1, Register str2, |
|
8409 Register cnt1, Register cnt2, Register result, |
|
8410 XMMRegister vec, Register tmp) { |
|
8411 assert(UseSSE42Intrinsics, "SSE4.2 is required"); |
|
8412 |
|
8413 Label RELOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, |
|
8414 SCAN_SUBSTR, RET_NOT_FOUND, CLEANUP; |
|
8415 |
|
8416 push(str1); // string addr |
|
8417 push(str2); // substr addr |
|
8418 push(cnt2); // substr count |
|
8419 jmpb(PREP_FOR_SCAN); |
|
8420 |
|
8421 // Substr count saved at sp |
|
8422 // Substr saved at sp+1*wordSize |
|
8423 // String saved at sp+2*wordSize |
|
8424 |
|
8425 // Reload substr for rescan |
|
8426 bind(RELOAD_SUBSTR); |
|
8427 movl(cnt2, Address(rsp, 0)); |
|
8428 movptr(str2, Address(rsp, wordSize)); |
|
8429 // We came here after the beginninig of the substring was |
|
8430 // matched but the rest of it was not so we need to search |
|
8431 // again. Start from the next element after the previous match. |
|
8432 subptr(str1, result); // Restore counter |
|
8433 shrl(str1, 1); |
|
8434 addl(cnt1, str1); |
|
8435 lea(str1, Address(result, 2)); // Reload string |
|
8436 |
|
8437 // Load substr |
|
8438 bind(PREP_FOR_SCAN); |
|
8439 movdqu(vec, Address(str2, 0)); |
|
8440 addl(cnt1, 8); // prime the loop |
|
8441 subptr(str1, 16); |
|
8442 |
|
8443 // Scan string for substr in 16-byte vectors |
|
8444 bind(SCAN_TO_SUBSTR); |
|
8445 subl(cnt1, 8); |
|
8446 addptr(str1, 16); |
|
8447 |
|
8448 // pcmpestri |
|
8449 // inputs: |
|
8450 // xmm - substring |
|
8451 // rax - substring length (elements count) |
|
8452 // mem - scaned string |
|
8453 // rdx - string length (elements count) |
|
8454 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) |
|
8455 // outputs: |
|
8456 // rcx - matched index in string |
|
8457 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); |
|
8458 |
|
8459 pcmpestri(vec, Address(str1, 0), 0x0d); |
|
8460 jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0 |
|
8461 jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0 |
|
8462 |
|
8463 // Fallthrough: found a potential substr |
|
8464 |
|
8465 // Make sure string is still long enough |
|
8466 subl(cnt1, tmp); |
|
8467 cmpl(cnt1, cnt2); |
|
8468 jccb(Assembler::negative, RET_NOT_FOUND); |
|
8469 // Compute start addr of substr |
|
8470 lea(str1, Address(str1, tmp, Address::times_2)); |
|
8471 movptr(result, str1); // save |
|
8472 |
|
8473 // Compare potential substr |
|
8474 addl(cnt1, 8); // prime the loop |
|
8475 addl(cnt2, 8); |
|
8476 subptr(str1, 16); |
|
8477 subptr(str2, 16); |
|
8478 |
|
8479 // Scan 16-byte vectors of string and substr |
|
8480 bind(SCAN_SUBSTR); |
|
8481 subl(cnt1, 8); |
|
8482 subl(cnt2, 8); |
|
8483 addptr(str1, 16); |
|
8484 addptr(str2, 16); |
|
8485 movdqu(vec, Address(str2, 0)); |
|
8486 pcmpestri(vec, Address(str1, 0), 0x0d); |
|
8487 jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 |
|
8488 jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 |
|
8489 |
|
8490 // Compute substr offset |
|
8491 subptr(result, Address(rsp, 2*wordSize)); |
|
8492 shrl(result, 1); // index |
|
8493 jmpb(CLEANUP); |
|
8494 |
|
8495 bind(RET_NOT_FOUND); |
|
8496 movl(result, -1); |
|
8497 |
|
8498 bind(CLEANUP); |
|
8499 addptr(rsp, 3*wordSize); |
|
8500 } |
|
8501 |
|
8502 // Compare strings. |
|
8503 void MacroAssembler::string_compare(Register str1, Register str2, |
|
8504 Register cnt1, Register cnt2, Register result, |
|
8505 XMMRegister vec1, XMMRegister vec2) { |
|
8506 Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL; |
|
8507 |
|
8508 // Compute the minimum of the string lengths and the |
|
8509 // difference of the string lengths (stack). |
|
8510 // Do the conditional move stuff |
|
8511 movl(result, cnt1); |
|
8512 subl(cnt1, cnt2); |
|
8513 push(cnt1); |
|
8514 if (VM_Version::supports_cmov()) { |
|
8515 cmovl(Assembler::lessEqual, cnt2, result); |
|
8516 } else { |
|
8517 Label GT_LABEL; |
|
8518 jccb(Assembler::greater, GT_LABEL); |
|
8519 movl(cnt2, result); |
|
8520 bind(GT_LABEL); |
|
8521 } |
|
8522 |
|
8523 // Is the minimum length zero? |
|
8524 testl(cnt2, cnt2); |
|
8525 jcc(Assembler::zero, LENGTH_DIFF_LABEL); |
|
8526 |
|
8527 // Load first characters |
|
8528 load_unsigned_short(result, Address(str1, 0)); |
|
8529 load_unsigned_short(cnt1, Address(str2, 0)); |
|
8530 |
|
8531 // Compare first characters |
|
8532 subl(result, cnt1); |
|
8533 jcc(Assembler::notZero, POP_LABEL); |
|
8534 decrementl(cnt2); |
|
8535 jcc(Assembler::zero, LENGTH_DIFF_LABEL); |
|
8536 |
|
8537 { |
|
8538 // Check after comparing first character to see if strings are equivalent |
|
8539 Label LSkip2; |
|
8540 // Check if the strings start at same location |
|
8541 cmpptr(str1, str2); |
|
8542 jccb(Assembler::notEqual, LSkip2); |
|
8543 |
|
8544 // Check if the length difference is zero (from stack) |
|
8545 cmpl(Address(rsp, 0), 0x0); |
|
8546 jcc(Assembler::equal, LENGTH_DIFF_LABEL); |
|
8547 |
|
8548 // Strings might not be equivalent |
|
8549 bind(LSkip2); |
|
8550 } |
|
8551 |
|
8552 // Advance to next character |
|
8553 addptr(str1, 2); |
|
8554 addptr(str2, 2); |
|
8555 |
|
8556 if (UseSSE42Intrinsics) { |
|
8557 // With SSE4.2, use double quad vector compare |
|
8558 Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; |
|
8559 // Setup to compare 16-byte vectors |
|
8560 movl(cnt1, cnt2); |
|
8561 andl(cnt2, 0xfffffff8); // cnt2 holds the vector count |
|
8562 andl(cnt1, 0x00000007); // cnt1 holds the tail count |
|
8563 testl(cnt2, cnt2); |
|
8564 jccb(Assembler::zero, COMPARE_TAIL); |
|
8565 |
|
8566 lea(str2, Address(str2, cnt2, Address::times_2)); |
|
8567 lea(str1, Address(str1, cnt2, Address::times_2)); |
|
8568 negptr(cnt2); |
|
8569 |
|
8570 bind(COMPARE_VECTORS); |
|
8571 movdqu(vec1, Address(str1, cnt2, Address::times_2)); |
|
8572 movdqu(vec2, Address(str2, cnt2, Address::times_2)); |
|
8573 pxor(vec1, vec2); |
|
8574 ptest(vec1, vec1); |
|
8575 jccb(Assembler::notZero, VECTOR_NOT_EQUAL); |
|
8576 addptr(cnt2, 8); |
|
8577 jcc(Assembler::notZero, COMPARE_VECTORS); |
|
8578 jmpb(COMPARE_TAIL); |
|
8579 |
|
8580 // Mismatched characters in the vectors |
|
8581 bind(VECTOR_NOT_EQUAL); |
|
8582 lea(str1, Address(str1, cnt2, Address::times_2)); |
|
8583 lea(str2, Address(str2, cnt2, Address::times_2)); |
|
8584 movl(cnt1, 8); |
|
8585 |
|
8586 // Compare tail (< 8 chars), or rescan last vectors to |
|
8587 // find 1st mismatched characters |
|
8588 bind(COMPARE_TAIL); |
|
8589 testl(cnt1, cnt1); |
|
8590 jccb(Assembler::zero, LENGTH_DIFF_LABEL); |
|
8591 movl(cnt2, cnt1); |
|
8592 // Fallthru to tail compare |
|
8593 } |
|
8594 |
|
8595 // Shift str2 and str1 to the end of the arrays, negate min |
|
8596 lea(str1, Address(str1, cnt2, Address::times_2, 0)); |
|
8597 lea(str2, Address(str2, cnt2, Address::times_2, 0)); |
|
8598 negptr(cnt2); |
|
8599 |
|
8600 // Compare the rest of the characters |
|
8601 bind(WHILE_HEAD_LABEL); |
|
8602 load_unsigned_short(result, Address(str1, cnt2, Address::times_2, 0)); |
|
8603 load_unsigned_short(cnt1, Address(str2, cnt2, Address::times_2, 0)); |
|
8604 subl(result, cnt1); |
|
8605 jccb(Assembler::notZero, POP_LABEL); |
|
8606 increment(cnt2); |
|
8607 jcc(Assembler::notZero, WHILE_HEAD_LABEL); |
|
8608 |
|
8609 // Strings are equal up to min length. Return the length difference. |
|
8610 bind(LENGTH_DIFF_LABEL); |
|
8611 pop(result); |
|
8612 jmpb(DONE_LABEL); |
|
8613 |
|
8614 // Discard the stored length difference |
|
8615 bind(POP_LABEL); |
|
8616 addptr(rsp, wordSize); |
|
8617 |
|
8618 // That's it |
|
8619 bind(DONE_LABEL); |
|
8620 } |
|
8621 |
|
8622 // Compare char[] arrays aligned to 4 bytes or substrings. |
|
8623 void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, |
|
8624 Register limit, Register result, Register chr, |
|
8625 XMMRegister vec1, XMMRegister vec2) { |
|
8626 Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; |
|
8627 |
|
8628 int length_offset = arrayOopDesc::length_offset_in_bytes(); |
|
8629 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); |
|
8630 |
|
8631 // Check the input args |
|
8632 cmpptr(ary1, ary2); |
|
8633 jcc(Assembler::equal, TRUE_LABEL); |
|
8634 |
|
8635 if (is_array_equ) { |
|
8636 // Need additional checks for arrays_equals. |
|
8637 andptr(ary1, ary2); |
|
8638 jcc(Assembler::zero, FALSE_LABEL); // One pointer is NULL |
|
8639 |
|
8640 // Check the lengths |
|
8641 movl(limit, Address(ary1, length_offset)); |
|
8642 cmpl(limit, Address(ary2, length_offset)); |
|
8643 jcc(Assembler::notEqual, FALSE_LABEL); |
|
8644 } |
|
8645 |
|
8646 // count == 0 |
|
8647 testl(limit, limit); |
|
8648 jcc(Assembler::zero, TRUE_LABEL); |
|
8649 |
|
8650 if (is_array_equ) { |
|
8651 // Load array address |
|
8652 lea(ary1, Address(ary1, base_offset)); |
|
8653 lea(ary2, Address(ary2, base_offset)); |
|
8654 } |
|
8655 |
|
8656 shll(limit, 1); // byte count != 0 |
|
8657 movl(result, limit); // copy |
|
8658 |
|
8659 if (UseSSE42Intrinsics) { |
|
8660 // With SSE4.2, use double quad vector compare |
|
8661 Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; |
|
8662 // Compare 16-byte vectors |
|
8663 andl(result, 0x0000000e); // tail count (in bytes) |
|
8664 andl(limit, 0xfffffff0); // vector count (in bytes) |
|
8665 jccb(Assembler::zero, COMPARE_TAIL); |
|
8666 |
|
8667 lea(ary1, Address(ary1, limit, Address::times_1)); |
|
8668 lea(ary2, Address(ary2, limit, Address::times_1)); |
|
8669 negptr(limit); |
|
8670 |
|
8671 bind(COMPARE_WIDE_VECTORS); |
|
8672 movdqu(vec1, Address(ary1, limit, Address::times_1)); |
|
8673 movdqu(vec2, Address(ary2, limit, Address::times_1)); |
|
8674 pxor(vec1, vec2); |
|
8675 ptest(vec1, vec1); |
|
8676 jccb(Assembler::notZero, FALSE_LABEL); |
|
8677 addptr(limit, 16); |
|
8678 jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); |
|
8679 |
|
8680 bind(COMPARE_TAIL); // limit is zero |
|
8681 movl(limit, result); |
|
8682 // Fallthru to tail compare |
|
8683 } |
|
8684 |
|
8685 // Compare 4-byte vectors |
|
8686 andl(limit, 0xfffffffc); // vector count (in bytes) |
|
8687 jccb(Assembler::zero, COMPARE_CHAR); |
|
8688 |
|
8689 lea(ary1, Address(ary1, limit, Address::times_1)); |
|
8690 lea(ary2, Address(ary2, limit, Address::times_1)); |
|
8691 negptr(limit); |
|
8692 |
|
8693 bind(COMPARE_VECTORS); |
|
8694 movl(chr, Address(ary1, limit, Address::times_1)); |
|
8695 cmpl(chr, Address(ary2, limit, Address::times_1)); |
|
8696 jccb(Assembler::notEqual, FALSE_LABEL); |
|
8697 addptr(limit, 4); |
|
8698 jcc(Assembler::notZero, COMPARE_VECTORS); |
|
8699 |
|
8700 // Compare trailing char (final 2 bytes), if any |
|
8701 bind(COMPARE_CHAR); |
|
8702 testl(result, 0x2); // tail char |
|
8703 jccb(Assembler::zero, TRUE_LABEL); |
|
8704 load_unsigned_short(chr, Address(ary1, 0)); |
|
8705 load_unsigned_short(limit, Address(ary2, 0)); |
|
8706 cmpl(chr, limit); |
|
8707 jccb(Assembler::notEqual, FALSE_LABEL); |
|
8708 |
|
8709 bind(TRUE_LABEL); |
|
8710 movl(result, 1); // return true |
|
8711 jmpb(DONE); |
|
8712 |
|
8713 bind(FALSE_LABEL); |
|
8714 xorl(result, result); // return false |
|
8715 |
|
8716 // That's it |
|
8717 bind(DONE); |
|
8718 } |
|
8719 |
8407 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { |
8720 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { |
8408 switch (cond) { |
8721 switch (cond) { |
8409 // Note some conditions are synonyms for others |
8722 // Note some conditions are synonyms for others |
8410 case Assembler::zero: return Assembler::notZero; |
8723 case Assembler::zero: return Assembler::notZero; |
8411 case Assembler::notZero: return Assembler::zero; |
8724 case Assembler::notZero: return Assembler::zero; |