< prev index next >
src/cpu/sparc/vm/macroAssembler_sparc.cpp
Print this page
*** 4514,4535 ****
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
neg(chr2, limit2); // limit2 = -(limit2-stride2)
}
// Compare the rest of the characters
! if (ae == StrIntrinsicNode::UU) {
! lduh(str1, limit1, chr1);
! } else {
! ldub(str1, limit1, chr1);
! }
bind(Lloop);
! if (ae == StrIntrinsicNode::LL) {
! ldub(str2, limit2, chr2);
! } else {
! lduh(str2, limit2, chr2);
! }
subcc(chr1, chr2, chr1);
br(Assembler::notZero, false, Assembler::pt, Ldone);
assert(chr1 == result, "result must be pre-placed");
delayed()->inccc(limit1, stride1);
--- 4514,4527 ----
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
neg(chr2, limit2); // limit2 = -(limit2-stride2)
}
// Compare the rest of the characters
! load_sized_value(Address(str1, limit1), chr1, (ae == StrIntrinsicNode::UU) ? 2 : 1, false);
bind(Lloop);
! load_sized_value(Address(str2, limit2), chr2, (ae == StrIntrinsicNode::LL) ? 1 : 2, false);
subcc(chr1, chr2, chr1);
br(Assembler::notZero, false, Assembler::pt, Ldone);
assert(chr1 == result, "result must be pre-placed");
delayed()->inccc(limit1, stride1);
*** 4537,4551 ****
inccc(limit2, stride2);
}
// annul LDUB if branch is not taken to prevent access past end of string
br(Assembler::notZero, true, Assembler::pt, Lloop);
! if (ae == StrIntrinsicNode::UU) {
! delayed()->lduh(str1, limit2, chr1);
! } else {
! delayed()->ldub(str1, limit1, chr1);
! }
// If strings are equal up to min length, return the length difference.
if (ae == StrIntrinsicNode::UU) {
// Divide by 2 to get number of chars
sra(diff, 1, result);
--- 4529,4539 ----
inccc(limit2, stride2);
}
// annul LDUB if branch is not taken to prevent access past end of string
br(Assembler::notZero, true, Assembler::pt, Lloop);
! delayed()->load_sized_value(Address(str1, limit1), chr1, (ae == StrIntrinsicNode::UU) ? 2 : 1, false);
// If strings are equal up to min length, return the length difference.
if (ae == StrIntrinsicNode::UU) {
// Divide by 2 to get number of chars
sra(diff, 1, result);
*** 4561,4671 ****
}
}
void MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2,
Register limit, Register tmp, Register result, bool is_byte) {
! Label Ldone, Lvector, Lloop;
assert_different_registers(ary1, ary2, limit, tmp, result);
int length_offset = arrayOopDesc::length_offset_in_bytes();
int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR);
if (is_array_equ) {
// return true if the same array
cmp(ary1, ary2);
brx(Assembler::equal, true, Assembler::pn, Ldone);
! delayed()->add(G0, 1, result); // equal
br_null(ary1, true, Assembler::pn, Ldone);
! delayed()->mov(G0, result); // not equal
br_null(ary2, true, Assembler::pn, Ldone);
! delayed()->mov(G0, result); // not equal
// load the lengths of arrays
ld(Address(ary1, length_offset), limit);
ld(Address(ary2, length_offset), tmp);
// return false if the two arrays are not equal length
cmp(limit, tmp);
br(Assembler::notEqual, true, Assembler::pn, Ldone);
! delayed()->mov(G0, result); // not equal
}
cmp_zero_and_br(Assembler::zero, limit, Ldone, true, Assembler::pn);
! delayed()->add(G0, 1, result); // zero-length arrays are equal
if (is_array_equ) {
// load array addresses
add(ary1, base_offset, ary1);
add(ary2, base_offset, ary2);
} else {
// We have no guarantee that on 64 bit the higher half of limit is 0
signx(limit);
}
! if (is_byte) {
! Label Lskip;
! // check for trailing byte
! andcc(limit, 0x1, tmp);
! br(Assembler::zero, false, Assembler::pt, Lskip);
! delayed()->nop();
!
! // compare the trailing byte
! sub(limit, sizeof(jbyte), limit);
! ldub(ary1, limit, result);
! ldub(ary2, limit, tmp);
! cmp(result, tmp);
! br(Assembler::notEqual, true, Assembler::pt, Ldone);
! delayed()->mov(G0, result); // not equal
!
! // only one byte?
! cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn);
! delayed()->add(G0, 1, result); // zero-length arrays are equal
! bind(Lskip);
! } else if (is_array_equ) {
! // set byte count
! sll(limit, exact_log2(sizeof(jchar)), limit);
! }
! // check for trailing character
! andcc(limit, 0x2, tmp);
! br(Assembler::zero, false, Assembler::pt, Lvector);
! delayed()->nop();
!
! // compare the trailing char
! sub(limit, sizeof(jchar), limit);
! lduh(ary1, limit, result);
! lduh(ary2, limit, tmp);
! cmp(result, tmp);
! br(Assembler::notEqual, true, Assembler::pt, Ldone);
! delayed()->mov(G0, result); // not equal
!
! // only one char?
! cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn);
! delayed()->add(G0, 1, result); // zero-length arrays are equal
- // word by word compare, dont't need alignment check
- bind(Lvector);
// Shift ary1 and ary2 to the end of the arrays, negate limit
add(ary1, limit, ary1);
add(ary2, limit, ary2);
neg(limit, limit);
! lduw(ary1, limit, result);
bind(Lloop);
! lduw(ary2, limit, tmp);
! cmp(result, tmp);
! br(Assembler::notEqual, true, Assembler::pt, Ldone);
! delayed()->mov(G0, result); // not equal
! inccc(limit, 2*sizeof(jchar));
! // annul LDUW if branch is not taken to prevent access past end of array
! br(Assembler::notZero, true, Assembler::pt, Lloop);
! delayed()->lduw(ary1, limit, result); // hoisted
! add(G0, 1, result); // equals
! bind(Ldone);
}
void MacroAssembler::has_negatives(Register inp, Register size, Register result, Register t2, Register t3, Register t4, Register t5) {
// test for negative bytes in input string of a given size
--- 4549,4677 ----
}
}
void MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2,
Register limit, Register tmp, Register result, bool is_byte) {
! Label Ldone, Lunaligned;
assert_different_registers(ary1, ary2, limit, tmp, result);
int length_offset = arrayOopDesc::length_offset_in_bytes();
int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR);
if (is_array_equ) {
// return true if the same array
cmp(ary1, ary2);
brx(Assembler::equal, true, Assembler::pn, Ldone);
! delayed()->mov(1, result); // equal
br_null(ary1, true, Assembler::pn, Ldone);
! delayed()->clr(result); // not equal
br_null(ary2, true, Assembler::pn, Ldone);
! delayed()->clr(result); // not equal
// load the lengths of arrays
ld(Address(ary1, length_offset), limit);
ld(Address(ary2, length_offset), tmp);
// return false if the two arrays are not equal length
cmp(limit, tmp);
br(Assembler::notEqual, true, Assembler::pn, Ldone);
! delayed()->clr(result); // not equal
}
cmp_zero_and_br(Assembler::zero, limit, Ldone, true, Assembler::pn);
! delayed()->mov(1, result); // zero-length arrays are equal
if (is_array_equ) {
// load array addresses
add(ary1, base_offset, ary1);
add(ary2, base_offset, ary2);
+ // set byte count
+ if (!is_byte) {
+ sll(limit, exact_log2(sizeof(jchar)), limit);
+ }
} else {
// We have no guarantee that on 64 bit the higher half of limit is 0
signx(limit);
}
! // Check for doubleword (8 byte) alignment of ary1 and ary2
! or3(ary1, ary2, tmp);
! and3(tmp, 7, tmp);
! br_notnull_short(tmp, Assembler::pn, Lunaligned);
!
! // Aligned, perform doubleword comparison
! array_equals_loop(ary1, ary2, limit, tmp, result, 8, &Ldone);
!
! // Misaligned, perform word comparison (word alignment is guaranteed)
! bind(Lunaligned);
! array_equals_loop(ary1, ary2, limit, tmp, result, 4, NULL /* fall through */);
!
! bind(Ldone);
! }
!
! // Compares two arrays in chunks of size 'byte_width'. The addresses must be aligned accordingly.
! void MacroAssembler::array_equals_loop(Register ary1, Register ary2, Register limit, Register tmp,
! Register result, size_t byte_width, Label* Ldone_or_null) {
! Label Lloop, Lremaining, Lfallthrough;
! // Fall through if the given label is NULL
! Label& Ldone = (Ldone_or_null != NULL) ? *Ldone_or_null : Lfallthrough;
! // Use appropriate CC register depending on byte_width
! Assembler::CC cc = (byte_width == 8) ? xcc : icc;
// Shift ary1 and ary2 to the end of the arrays, negate limit
add(ary1, limit, ary1);
add(ary2, limit, ary2);
neg(limit, limit);
! // MAIN LOOP
! // Load and compare array elements of size 'byte_width' until the elements are not
! // equal or we reached the end of the arrays. If the size of the arrays is not a
! // multiple of 'byte_width', we simply read over the end of the array, bail out and
! // compare the remaining bytes below by skipping the garbage bytes.
! load_sized_value(Address(ary1, limit), result, byte_width, false);
bind(Lloop);
! load_sized_value(Address(ary2, limit), tmp, byte_width, false);
! inccc(limit, byte_width);
! // Bail out if we reached the end (but still do the comparison)
! br(Assembler::positive, false, Assembler::pn, Lremaining);
! delayed()->xorcc(tmp, result, tmp);
! // Check equality of elements
! bp(Assembler::equal, false, cc, Assembler::pt, target(Lloop));
! delayed()->load_sized_value(Address(ary1, limit), result, byte_width, false);
!
! ba(Ldone);
! delayed()->clr(result); // not equal
!
! // TAIL COMPARISON
! // We got here because we reached the end of the arrays. 'limit' is the number of
! // garbage bytes we may have compared by reading over the end of the arrays. Shift
! // out the garbage and compare the remaining elements. A 'limit' value of 0 means
! // "preserve all bits". The elements are pre-compared bitwise, in that result has
! // been xored into tmp.
! bind(Lremaining);
! // Optimistic shortcut: elements potentially including garbage are equal
! bp(Assembler::equal, true, cc, Assembler::pt, target(Ldone));
! delayed()->mov(1, result); // equal
! sll(limit, 3, limit); // bytes to bits
! clr(result);
! // Shift 'limit' bytes to the right and compare
! if (cc == icc) {
! srl(tmp, limit, tmp);
! } else {
! srlx(tmp, limit, tmp);
! }
! // Fall through if we are at the end of the intrinsic
! if (Ldone_or_null != NULL) {
! ba(Ldone);
! delayed(); // ->movr(...)
! }
! movr(Assembler::rc_z, tmp, 1, result); // may be a delay slot instruction
! bind(Lfallthrough);
}
void MacroAssembler::has_negatives(Register inp, Register size, Register result, Register t2, Register t3, Register t4, Register t5) {
// test for negative bytes in input string of a given size
< prev index next >