Mercurial > hg > graal-compiler
comparison src/cpu/x86/vm/assembler_x86.cpp @ 1930:2d26b0046e0d
Merge.
author | Thomas Wuerthinger <wuerthinger@ssw.jku.at> |
---|---|
date | Tue, 30 Nov 2010 14:53:30 +0100 |
parents | 3483ec571caf 2fe998383789 |
children | 06f017f7daa7 |
comparison
equal
deleted
inserted
replaced
1484:6b7001391c97 | 1930:2d26b0046e0d |
---|---|
1 /* | 1 /* |
2 * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. | 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
14 * | 14 * |
15 * You should have received a copy of the GNU General Public License version | 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, | 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. | 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 * | 18 * |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | 20 * or visit www.oracle.com if you need additional information or have any |
21 * have any questions. | 21 * questions. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 #include "incls/_precompiled.incl" | 25 #include "incls/_precompiled.incl" |
26 #include "incls/_assembler_x86.cpp.incl" | 26 #include "incls/_assembler_x86.cpp.incl" |
1273 int encode = prefix_and_encode(src->encoding()); | 1273 int encode = prefix_and_encode(src->encoding()); |
1274 emit_byte(0xF7); | 1274 emit_byte(0xF7); |
1275 emit_byte(0xF8 | encode); | 1275 emit_byte(0xF8 | encode); |
1276 } | 1276 } |
1277 | 1277 |
1278 void Assembler::divl(Register src) { // Unsigned | |
1279 int encode = prefix_and_encode(src->encoding()); | |
1280 emit_byte(0xF7); | |
1281 emit_byte(0xF0 | encode); | |
1282 } | |
1283 | |
1278 void Assembler::imull(Register dst, Register src) { | 1284 void Assembler::imull(Register dst, Register src) { |
1279 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | 1285 int encode = prefix_and_encode(dst->encoding(), src->encoding()); |
1280 emit_byte(0x0F); | 1286 emit_byte(0x0F); |
1281 emit_byte(0xAF); | 1287 emit_byte(0xAF); |
1282 emit_byte(0xC0 | encode); | 1288 emit_byte(0xC0 | encode); |
1286 void Assembler::imull(Register dst, Register src, int value) { | 1292 void Assembler::imull(Register dst, Register src, int value) { |
1287 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | 1293 int encode = prefix_and_encode(dst->encoding(), src->encoding()); |
1288 if (is8bit(value)) { | 1294 if (is8bit(value)) { |
1289 emit_byte(0x6B); | 1295 emit_byte(0x6B); |
1290 emit_byte(0xC0 | encode); | 1296 emit_byte(0xC0 | encode); |
1291 emit_byte(value); | 1297 emit_byte(value & 0xFF); |
1292 } else { | 1298 } else { |
1293 emit_byte(0x69); | 1299 emit_byte(0x69); |
1294 emit_byte(0xC0 | encode); | 1300 emit_byte(0xC0 | encode); |
1295 emit_long(value); | 1301 emit_long(value); |
1296 } | 1302 } |
3901 void Assembler::imulq(Register dst, Register src, int value) { | 3907 void Assembler::imulq(Register dst, Register src, int value) { |
3902 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | 3908 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); |
3903 if (is8bit(value)) { | 3909 if (is8bit(value)) { |
3904 emit_byte(0x6B); | 3910 emit_byte(0x6B); |
3905 emit_byte(0xC0 | encode); | 3911 emit_byte(0xC0 | encode); |
3906 emit_byte(value); | 3912 emit_byte(value & 0xFF); |
3907 } else { | 3913 } else { |
3908 emit_byte(0x69); | 3914 emit_byte(0x69); |
3909 emit_byte(0xC0 | encode); | 3915 emit_byte(0xC0 | encode); |
3910 emit_long(value); | 3916 emit_long(value); |
3911 } | 3917 } |
4991 // This is the value of eip which points to where verify_oop will return. | 4997 // This is the value of eip which points to where verify_oop will return. |
4992 if (os::message_box(msg, "Execution stopped, print registers?")) { | 4998 if (os::message_box(msg, "Execution stopped, print registers?")) { |
4993 ttyLocker ttyl; | 4999 ttyLocker ttyl; |
4994 tty->print_cr("eip = 0x%08x", eip); | 5000 tty->print_cr("eip = 0x%08x", eip); |
4995 #ifndef PRODUCT | 5001 #ifndef PRODUCT |
4996 tty->cr(); | 5002 if ((WizardMode || Verbose) && PrintMiscellaneous) { |
4997 findpc(eip); | 5003 tty->cr(); |
4998 tty->cr(); | 5004 findpc(eip); |
5005 tty->cr(); | |
5006 } | |
4999 #endif | 5007 #endif |
5000 tty->print_cr("rax, = 0x%08x", rax); | 5008 tty->print_cr("rax = 0x%08x", rax); |
5001 tty->print_cr("rbx, = 0x%08x", rbx); | 5009 tty->print_cr("rbx = 0x%08x", rbx); |
5002 tty->print_cr("rcx = 0x%08x", rcx); | 5010 tty->print_cr("rcx = 0x%08x", rcx); |
5003 tty->print_cr("rdx = 0x%08x", rdx); | 5011 tty->print_cr("rdx = 0x%08x", rdx); |
5004 tty->print_cr("rdi = 0x%08x", rdi); | 5012 tty->print_cr("rdi = 0x%08x", rdi); |
5005 tty->print_cr("rsi = 0x%08x", rsi); | 5013 tty->print_cr("rsi = 0x%08x", rsi); |
5006 tty->print_cr("rbp, = 0x%08x", rbp); | 5014 tty->print_cr("rbp = 0x%08x", rbp); |
5007 tty->print_cr("rsp = 0x%08x", rsp); | 5015 tty->print_cr("rsp = 0x%08x", rsp); |
5008 BREAKPOINT; | 5016 BREAKPOINT; |
5017 assert(false, "start up GDB"); | |
5009 } | 5018 } |
5010 } else { | 5019 } else { |
5011 ttyLocker ttyl; | 5020 ttyLocker ttyl; |
5012 ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); | 5021 ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); |
5013 assert(false, "DEBUG MESSAGE"); | 5022 assert(false, "DEBUG MESSAGE"); |
6492 } | 6501 } |
6493 return off; | 6502 return off; |
6494 } | 6503 } |
6495 | 6504 |
6496 void MacroAssembler::load_sized_value(Register dst, Address src, | 6505 void MacroAssembler::load_sized_value(Register dst, Address src, |
6497 int size_in_bytes, bool is_signed) { | 6506 size_t size_in_bytes, bool is_signed) { |
6498 switch (size_in_bytes ^ (is_signed ? -1 : 0)) { | 6507 switch (size_in_bytes) { |
6499 #ifndef _LP64 | 6508 #ifndef _LP64 |
6500 // For case 8, caller is responsible for manually loading | 6509 // For case 8, caller is responsible for manually loading |
6501 // the second word into another register. | 6510 // the second word into another register. |
6502 case ~8: // fall through: | 6511 case 8: movl(dst, src); break; |
6503 case 8: movl( dst, src ); break; | |
6504 #else | 6512 #else |
6505 case ~8: // fall through: | 6513 case 8: movq(dst, src); break; |
6506 case 8: movq( dst, src ); break; | |
6507 #endif | 6514 #endif |
6508 case ~4: // fall through: | 6515 case 4: movl(dst, src); break; |
6509 case 4: movl( dst, src ); break; | 6516 case 2: is_signed ? load_signed_short(dst, src) : load_unsigned_short(dst, src); break; |
6510 case ~2: load_signed_short( dst, src ); break; | 6517 case 1: is_signed ? load_signed_byte( dst, src) : load_unsigned_byte( dst, src); break; |
6511 case 2: load_unsigned_short( dst, src ); break; | 6518 default: ShouldNotReachHere(); |
6512 case ~1: load_signed_byte( dst, src ); break; | |
6513 case 1: load_unsigned_byte( dst, src ); break; | |
6514 default: ShouldNotReachHere(); | |
6515 } | 6519 } |
6516 } | 6520 } |
6517 | 6521 |
6518 void MacroAssembler::mov32(AddressLiteral dst, Register src) { | 6522 void MacroAssembler::mov32(AddressLiteral dst, Register src) { |
6519 if (reachable(dst)) { | 6523 if (reachable(dst)) { |
7156 movptr(Address(top, oopDesc::mark_offset_in_bytes()), (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); | 7160 movptr(Address(top, oopDesc::mark_offset_in_bytes()), (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); |
7157 // set the length to the remaining space | 7161 // set the length to the remaining space |
7158 subptr(t1, typeArrayOopDesc::header_size(T_INT)); | 7162 subptr(t1, typeArrayOopDesc::header_size(T_INT)); |
7159 addptr(t1, (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); | 7163 addptr(t1, (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); |
7160 shlptr(t1, log2_intptr(HeapWordSize/sizeof(jint))); | 7164 shlptr(t1, log2_intptr(HeapWordSize/sizeof(jint))); |
7161 movptr(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); | 7165 movl(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); |
7162 // set klass to intArrayKlass | 7166 // set klass to intArrayKlass |
7163 // dubious reloc why not an oop reloc? | 7167 // dubious reloc why not an oop reloc? |
7164 movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr())); | 7168 movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr())); |
7165 // store klass last. concurrent gcs assumes klass length is valid if | 7169 // store klass last. concurrent gcs assumes klass length is valid if |
7166 // klass field is not null. | 7170 // klass field is not null. |
7573 // Skip to start of data. | 7577 // Skip to start of data. |
7574 addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); | 7578 addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); |
7575 | 7579 |
7576 // Scan RCX words at [RDI] for an occurrence of RAX. | 7580 // Scan RCX words at [RDI] for an occurrence of RAX. |
7577 // Set NZ/Z based on last compare. | 7581 // Set NZ/Z based on last compare. |
7582 // Z flag value will not be set by 'repne' if RCX == 0 since 'repne' does | |
7583 // not change flags (only scas instruction which is repeated sets flags). | |
7584 // Set Z = 0 (not equal) before 'repne' to indicate that class was not found. | |
7578 #ifdef _LP64 | 7585 #ifdef _LP64 |
7579 // This part is tricky, as values in supers array could be 32 or 64 bit wide | 7586 // This part is tricky, as values in supers array could be 32 or 64 bit wide |
7580 // and we store values in objArrays always encoded, thus we need to encode | 7587 // and we store values in objArrays always encoded, thus we need to encode |
7581 // the value of rax before repne. Note that rax is dead after the repne. | 7588 // the value of rax before repne. Note that rax is dead after the repne. |
7582 if (UseCompressedOops) { | 7589 if (UseCompressedOops) { |
7583 encode_heap_oop_not_null(rax); | 7590 encode_heap_oop_not_null(rax); // Changes flags. |
7584 // The superclass is never null; it would be a basic system error if a null | 7591 // The superclass is never null; it would be a basic system error if a null |
7585 // pointer were to sneak in here. Note that we have already loaded the | 7592 // pointer were to sneak in here. Note that we have already loaded the |
7586 // Klass::super_check_offset from the super_klass in the fast path, | 7593 // Klass::super_check_offset from the super_klass in the fast path, |
7587 // so if there is a null in that register, we are already in the afterlife. | 7594 // so if there is a null in that register, we are already in the afterlife. |
7595 testl(rax,rax); // Set Z = 0 | |
7588 repne_scanl(); | 7596 repne_scanl(); |
7589 } else | 7597 } else |
7590 #endif // _LP64 | 7598 #endif // _LP64 |
7599 { | |
7600 testptr(rax,rax); // Set Z = 0 | |
7591 repne_scan(); | 7601 repne_scan(); |
7592 | 7602 } |
7593 // Unspill the temp. registers: | 7603 // Unspill the temp. registers: |
7594 if (pushed_rdi) pop(rdi); | 7604 if (pushed_rdi) pop(rdi); |
7595 if (pushed_rcx) pop(rcx); | 7605 if (pushed_rcx) pop(rcx); |
7596 if (pushed_rax) pop(rax); | 7606 if (pushed_rax) pop(rax); |
7597 | 7607 |
7648 if (!VerifyOops) return; | 7658 if (!VerifyOops) return; |
7649 | 7659 |
7650 // Pass register number to verify_oop_subroutine | 7660 // Pass register number to verify_oop_subroutine |
7651 char* b = new char[strlen(s) + 50]; | 7661 char* b = new char[strlen(s) + 50]; |
7652 sprintf(b, "verify_oop: %s: %s", reg->name(), s); | 7662 sprintf(b, "verify_oop: %s: %s", reg->name(), s); |
7663 #ifdef _LP64 | |
7664 push(rscratch1); // save r10, trashed by movptr() | |
7665 #endif | |
7653 push(rax); // save rax, | 7666 push(rax); // save rax, |
7654 push(reg); // pass register argument | 7667 push(reg); // pass register argument |
7655 ExternalAddress buffer((address) b); | 7668 ExternalAddress buffer((address) b); |
7656 // avoid using pushptr, as it modifies scratch registers | 7669 // avoid using pushptr, as it modifies scratch registers |
7657 // and our contract is not to modify anything | 7670 // and our contract is not to modify anything |
7658 movptr(rax, buffer.addr()); | 7671 movptr(rax, buffer.addr()); |
7659 push(rax); | 7672 push(rax); |
7660 // call indirectly to solve generation ordering problem | 7673 // call indirectly to solve generation ordering problem |
7661 movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); | 7674 movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); |
7662 call(rax); | 7675 call(rax); |
7676 // Caller pops the arguments (oop, message) and restores rax, r10 | |
7663 } | 7677 } |
7664 | 7678 |
7665 | 7679 |
7666 RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, | 7680 RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, |
7667 Register tmp, | 7681 Register tmp, |
7672 | 7686 |
7673 // load indirectly to solve generation ordering problem | 7687 // load indirectly to solve generation ordering problem |
7674 movptr(tmp, ExternalAddress((address) delayed_value_addr)); | 7688 movptr(tmp, ExternalAddress((address) delayed_value_addr)); |
7675 | 7689 |
7676 #ifdef ASSERT | 7690 #ifdef ASSERT |
7677 Label L; | 7691 { Label L; |
7678 testptr(tmp, tmp); | 7692 testptr(tmp, tmp); |
7679 jccb(Assembler::notZero, L); | 7693 if (WizardMode) { |
7680 hlt(); | 7694 jcc(Assembler::notZero, L); |
7681 bind(L); | 7695 char* buf = new char[40]; |
7696 sprintf(buf, "DelayedValue="INTPTR_FORMAT, delayed_value_addr[1]); | |
7697 stop(buf); | |
7698 } else { | |
7699 jccb(Assembler::notZero, L); | |
7700 hlt(); | |
7701 } | |
7702 bind(L); | |
7703 } | |
7682 #endif | 7704 #endif |
7683 | 7705 |
7684 if (offset != 0) | 7706 if (offset != 0) |
7685 addptr(tmp, offset); | 7707 addptr(tmp, offset); |
7686 | 7708 |
7693 // - rcx: method handle | 7715 // - rcx: method handle |
7694 // - rdx, rsi, or ?: killable temp | 7716 // - rdx, rsi, or ?: killable temp |
7695 void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, | 7717 void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, |
7696 Register temp_reg, | 7718 Register temp_reg, |
7697 Label& wrong_method_type) { | 7719 Label& wrong_method_type) { |
7698 if (UseCompressedOops) unimplemented(); // field accesses must decode | 7720 Address type_addr(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)); |
7699 // compare method type against that of the receiver | 7721 // compare method type against that of the receiver |
7700 cmpptr(mtype_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg))); | 7722 if (UseCompressedOops) { |
7723 load_heap_oop(temp_reg, type_addr); | |
7724 cmpptr(mtype_reg, temp_reg); | |
7725 } else { | |
7726 cmpptr(mtype_reg, type_addr); | |
7727 } | |
7701 jcc(Assembler::notEqual, wrong_method_type); | 7728 jcc(Assembler::notEqual, wrong_method_type); |
7702 } | 7729 } |
7703 | 7730 |
7704 | 7731 |
7705 // A method handle has a "vmslots" field which gives the size of its | 7732 // A method handle has a "vmslots" field which gives the size of its |
7706 // argument list in JVM stack slots. This field is either located directly | 7733 // argument list in JVM stack slots. This field is either located directly |
7707 // in every method handle, or else is indirectly accessed through the | 7734 // in every method handle, or else is indirectly accessed through the |
7708 // method handle's MethodType. This macro hides the distinction. | 7735 // method handle's MethodType. This macro hides the distinction. |
7709 void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, | 7736 void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, |
7710 Register temp_reg) { | 7737 Register temp_reg) { |
7711 if (UseCompressedOops) unimplemented(); // field accesses must decode | 7738 assert_different_registers(vmslots_reg, mh_reg, temp_reg); |
7712 // load mh.type.form.vmslots | 7739 // load mh.type.form.vmslots |
7713 if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { | 7740 if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { |
7714 // hoist vmslots into every mh to avoid dependent load chain | 7741 // hoist vmslots into every mh to avoid dependent load chain |
7715 movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg))); | 7742 movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg))); |
7716 } else { | 7743 } else { |
7717 Register temp2_reg = vmslots_reg; | 7744 Register temp2_reg = vmslots_reg; |
7718 movptr(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg))); | 7745 load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg))); |
7719 movptr(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg))); | 7746 load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg))); |
7720 movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); | 7747 movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); |
7721 } | 7748 } |
7722 } | 7749 } |
7723 | 7750 |
7724 | 7751 |
7728 // - rax: killable temp (compiled only) | 7755 // - rax: killable temp (compiled only) |
7729 void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { | 7756 void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { |
7730 assert(mh_reg == rcx, "caller must put MH object in rcx"); | 7757 assert(mh_reg == rcx, "caller must put MH object in rcx"); |
7731 assert_different_registers(mh_reg, temp_reg); | 7758 assert_different_registers(mh_reg, temp_reg); |
7732 | 7759 |
7733 if (UseCompressedOops) unimplemented(); // field accesses must decode | |
7734 | |
7735 // pick out the interpreted side of the handler | 7760 // pick out the interpreted side of the handler |
7761 // NOTE: vmentry is not an oop! | |
7736 movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg))); | 7762 movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg))); |
7737 | 7763 |
7738 // off we go... | 7764 // off we go... |
7739 jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); | 7765 jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); |
7740 | 7766 |
7744 | 7770 |
7745 | 7771 |
7746 Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, | 7772 Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, |
7747 int extra_slot_offset) { | 7773 int extra_slot_offset) { |
7748 // cf. TemplateTable::prepare_invoke(), if (load_receiver). | 7774 // cf. TemplateTable::prepare_invoke(), if (load_receiver). |
7749 int stackElementSize = Interpreter::stackElementSize(); | 7775 int stackElementSize = Interpreter::stackElementSize; |
7750 int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); | 7776 int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); |
7751 #ifdef ASSERT | 7777 #ifdef ASSERT |
7752 int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); | 7778 int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); |
7753 assert(offset1 - offset == stackElementSize, "correct arithmetic"); | 7779 assert(offset1 - offset == stackElementSize, "correct arithmetic"); |
7754 #endif | 7780 #endif |
7771 // Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord); | 7797 // Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord); |
7772 // Pass register number to verify_oop_subroutine | 7798 // Pass register number to verify_oop_subroutine |
7773 char* b = new char[strlen(s) + 50]; | 7799 char* b = new char[strlen(s) + 50]; |
7774 sprintf(b, "verify_oop_addr: %s", s); | 7800 sprintf(b, "verify_oop_addr: %s", s); |
7775 | 7801 |
7802 #ifdef _LP64 | |
7803 push(rscratch1); // save r10, trashed by movptr() | |
7804 #endif | |
7776 push(rax); // save rax, | 7805 push(rax); // save rax, |
7777 // addr may contain rsp so we will have to adjust it based on the push | 7806 // addr may contain rsp so we will have to adjust it based on the push |
7778 // we just did | 7807 // we just did |
7779 // NOTE: 64bit seemed to have had a bug in that it did movq(addr, rax); which | 7808 // NOTE: 64bit seemed to have had a bug in that it did movq(addr, rax); which |
7780 // stores rax into addr which is backwards of what was intended. | 7809 // stores rax into addr which is backwards of what was intended. |
7793 push(rax); | 7822 push(rax); |
7794 | 7823 |
7795 // call indirectly to solve generation ordering problem | 7824 // call indirectly to solve generation ordering problem |
7796 movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); | 7825 movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); |
7797 call(rax); | 7826 call(rax); |
7798 // Caller pops the arguments and restores rax, from the stack | 7827 // Caller pops the arguments (addr, message) and restores rax, r10. |
7799 } | 7828 } |
7800 | 7829 |
7801 void MacroAssembler::verify_tlab() { | 7830 void MacroAssembler::verify_tlab() { |
7802 #ifdef ASSERT | 7831 #ifdef ASSERT |
7803 if (UseTLAB && VerifyOops) { | 7832 if (UseTLAB && VerifyOops) { |
7975 case 0: return "valid"; | 8004 case 0: return "valid"; |
7976 case 1: return "zero"; | 8005 case 1: return "zero"; |
7977 case 2: return "special"; | 8006 case 2: return "special"; |
7978 case 3: return "empty"; | 8007 case 3: return "empty"; |
7979 } | 8008 } |
7980 ShouldNotReachHere() | 8009 ShouldNotReachHere(); |
7981 return NULL; | 8010 return NULL; |
7982 } | 8011 } |
7983 | 8012 |
7984 void print() const { | 8013 void print() const { |
7985 // print computation registers | 8014 // print computation registers |
8189 #ifdef _LP64 | 8218 #ifdef _LP64 |
8190 if (UseCompressedOops) { | 8219 if (UseCompressedOops) { |
8191 assert (Universe::heap() != NULL, "java heap should be initialized"); | 8220 assert (Universe::heap() != NULL, "java heap should be initialized"); |
8192 movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); | 8221 movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); |
8193 if (Universe::narrow_oop_shift() != 0) { | 8222 if (Universe::narrow_oop_shift() != 0) { |
8194 assert(Address::times_8 == LogMinObjAlignmentInBytes && | 8223 assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
8195 Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong"); | 8224 if (LogMinObjAlignmentInBytes == Address::times_8) { |
8196 movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | 8225 movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); |
8226 } else { | |
8227 // OK to use shift since we don't need to preserve flags. | |
8228 shlq(dst, LogMinObjAlignmentInBytes); | |
8229 movq(dst, Address(r12_heapbase, dst, Address::times_1, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | |
8230 } | |
8197 } else { | 8231 } else { |
8198 movq(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | 8232 movq(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); |
8199 } | 8233 } |
8200 } else | 8234 } else |
8201 #endif | 8235 #endif |
8213 } else | 8247 } else |
8214 #endif | 8248 #endif |
8215 movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src); | 8249 movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src); |
8216 } | 8250 } |
8217 | 8251 |
8252 void MacroAssembler::load_heap_oop(Register dst, Address src) { | |
8253 #ifdef _LP64 | |
8254 if (UseCompressedOops) { | |
8255 movl(dst, src); | |
8256 decode_heap_oop(dst); | |
8257 } else | |
8258 #endif | |
8259 movptr(dst, src); | |
8260 } | |
8261 | |
8262 void MacroAssembler::store_heap_oop(Address dst, Register src) { | |
8263 #ifdef _LP64 | |
8264 if (UseCompressedOops) { | |
8265 assert(!dst.uses(src), "not enough registers"); | |
8266 encode_heap_oop(src); | |
8267 movl(dst, src); | |
8268 } else | |
8269 #endif | |
8270 movptr(dst, src); | |
8271 } | |
8272 | |
8273 // Used for storing NULLs. | |
8274 void MacroAssembler::store_heap_oop_null(Address dst) { | |
8275 #ifdef _LP64 | |
8276 if (UseCompressedOops) { | |
8277 movl(dst, (int32_t)NULL_WORD); | |
8278 } else { | |
8279 movslq(dst, (int32_t)NULL_WORD); | |
8280 } | |
8281 #else | |
8282 movl(dst, (int32_t)NULL_WORD); | |
8283 #endif | |
8284 } | |
8285 | |
8218 #ifdef _LP64 | 8286 #ifdef _LP64 |
8219 void MacroAssembler::store_klass_gap(Register dst, Register src) { | 8287 void MacroAssembler::store_klass_gap(Register dst, Register src) { |
8220 if (UseCompressedOops) { | 8288 if (UseCompressedOops) { |
8221 // Store to klass gap in destination | 8289 // Store to klass gap in destination |
8222 movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src); | 8290 movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src); |
8223 } | 8291 } |
8224 } | 8292 } |
8225 | 8293 |
8226 void MacroAssembler::load_heap_oop(Register dst, Address src) { | 8294 #ifdef ASSERT |
8227 if (UseCompressedOops) { | 8295 void MacroAssembler::verify_heapbase(const char* msg) { |
8228 movl(dst, src); | 8296 assert (UseCompressedOops, "should be compressed"); |
8229 decode_heap_oop(dst); | 8297 assert (Universe::heap() != NULL, "java heap should be initialized"); |
8230 } else { | 8298 if (CheckCompressedOops) { |
8231 movq(dst, src); | 8299 Label ok; |
8232 } | 8300 push(rscratch1); // cmpptr trashes rscratch1 |
8233 } | 8301 cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); |
8234 | 8302 jcc(Assembler::equal, ok); |
8235 void MacroAssembler::store_heap_oop(Address dst, Register src) { | 8303 stop(msg); |
8236 if (UseCompressedOops) { | 8304 bind(ok); |
8237 assert(!dst.uses(src), "not enough registers"); | 8305 pop(rscratch1); |
8238 encode_heap_oop(src); | 8306 } |
8239 movl(dst, src); | 8307 } |
8240 } else { | 8308 #endif |
8241 movq(dst, src); | |
8242 } | |
8243 } | |
8244 | |
8245 // Used for storing NULLs. | |
8246 void MacroAssembler::store_heap_oop_null(Address dst) { | |
8247 if (UseCompressedOops) { | |
8248 movl(dst, (int32_t)NULL_WORD); | |
8249 } else { | |
8250 movslq(dst, (int32_t)NULL_WORD); | |
8251 } | |
8252 } | |
8253 | 8309 |
8254 // Algorithm must match oop.inline.hpp encode_heap_oop. | 8310 // Algorithm must match oop.inline.hpp encode_heap_oop. |
8255 void MacroAssembler::encode_heap_oop(Register r) { | 8311 void MacroAssembler::encode_heap_oop(Register r) { |
8256 assert (UseCompressedOops, "should be compressed"); | 8312 #ifdef ASSERT |
8257 assert (Universe::heap() != NULL, "java heap should be initialized"); | 8313 verify_heapbase("MacroAssembler::encode_heap_oop: heap base corrupted?"); |
8314 #endif | |
8315 verify_oop(r, "broken oop in encode_heap_oop"); | |
8258 if (Universe::narrow_oop_base() == NULL) { | 8316 if (Universe::narrow_oop_base() == NULL) { |
8259 verify_oop(r, "broken oop in encode_heap_oop"); | |
8260 if (Universe::narrow_oop_shift() != 0) { | 8317 if (Universe::narrow_oop_shift() != 0) { |
8261 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); | 8318 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
8262 shrq(r, LogMinObjAlignmentInBytes); | 8319 shrq(r, LogMinObjAlignmentInBytes); |
8263 } | 8320 } |
8264 return; | 8321 return; |
8265 } | 8322 } |
8266 #ifdef ASSERT | |
8267 if (CheckCompressedOops) { | |
8268 Label ok; | |
8269 push(rscratch1); // cmpptr trashes rscratch1 | |
8270 cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); | |
8271 jcc(Assembler::equal, ok); | |
8272 stop("MacroAssembler::encode_heap_oop: heap base corrupted?"); | |
8273 bind(ok); | |
8274 pop(rscratch1); | |
8275 } | |
8276 #endif | |
8277 verify_oop(r, "broken oop in encode_heap_oop"); | |
8278 testq(r, r); | 8323 testq(r, r); |
8279 cmovq(Assembler::equal, r, r12_heapbase); | 8324 cmovq(Assembler::equal, r, r12_heapbase); |
8280 subq(r, r12_heapbase); | 8325 subq(r, r12_heapbase); |
8281 shrq(r, LogMinObjAlignmentInBytes); | 8326 shrq(r, LogMinObjAlignmentInBytes); |
8282 } | 8327 } |
8283 | 8328 |
8284 void MacroAssembler::encode_heap_oop_not_null(Register r) { | 8329 void MacroAssembler::encode_heap_oop_not_null(Register r) { |
8285 assert (UseCompressedOops, "should be compressed"); | |
8286 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
8287 #ifdef ASSERT | 8330 #ifdef ASSERT |
8331 verify_heapbase("MacroAssembler::encode_heap_oop_not_null: heap base corrupted?"); | |
8288 if (CheckCompressedOops) { | 8332 if (CheckCompressedOops) { |
8289 Label ok; | 8333 Label ok; |
8290 testq(r, r); | 8334 testq(r, r); |
8291 jcc(Assembler::notEqual, ok); | 8335 jcc(Assembler::notEqual, ok); |
8292 stop("null oop passed to encode_heap_oop_not_null"); | 8336 stop("null oop passed to encode_heap_oop_not_null"); |
8302 shrq(r, LogMinObjAlignmentInBytes); | 8346 shrq(r, LogMinObjAlignmentInBytes); |
8303 } | 8347 } |
8304 } | 8348 } |
8305 | 8349 |
8306 void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { | 8350 void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { |
8307 assert (UseCompressedOops, "should be compressed"); | |
8308 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
8309 #ifdef ASSERT | 8351 #ifdef ASSERT |
8352 verify_heapbase("MacroAssembler::encode_heap_oop_not_null2: heap base corrupted?"); | |
8310 if (CheckCompressedOops) { | 8353 if (CheckCompressedOops) { |
8311 Label ok; | 8354 Label ok; |
8312 testq(src, src); | 8355 testq(src, src); |
8313 jcc(Assembler::notEqual, ok); | 8356 jcc(Assembler::notEqual, ok); |
8314 stop("null oop passed to encode_heap_oop_not_null2"); | 8357 stop("null oop passed to encode_heap_oop_not_null2"); |
8327 shrq(dst, LogMinObjAlignmentInBytes); | 8370 shrq(dst, LogMinObjAlignmentInBytes); |
8328 } | 8371 } |
8329 } | 8372 } |
8330 | 8373 |
8331 void MacroAssembler::decode_heap_oop(Register r) { | 8374 void MacroAssembler::decode_heap_oop(Register r) { |
8332 assert (UseCompressedOops, "should be compressed"); | 8375 #ifdef ASSERT |
8333 assert (Universe::heap() != NULL, "java heap should be initialized"); | 8376 verify_heapbase("MacroAssembler::decode_heap_oop: heap base corrupted?"); |
8377 #endif | |
8334 if (Universe::narrow_oop_base() == NULL) { | 8378 if (Universe::narrow_oop_base() == NULL) { |
8335 if (Universe::narrow_oop_shift() != 0) { | 8379 if (Universe::narrow_oop_shift() != 0) { |
8336 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); | 8380 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
8337 shlq(r, LogMinObjAlignmentInBytes); | 8381 shlq(r, LogMinObjAlignmentInBytes); |
8338 } | 8382 } |
8339 verify_oop(r, "broken oop in decode_heap_oop"); | 8383 } else { |
8340 return; | 8384 Label done; |
8341 } | 8385 shlq(r, LogMinObjAlignmentInBytes); |
8342 #ifdef ASSERT | 8386 jccb(Assembler::equal, done); |
8343 if (CheckCompressedOops) { | 8387 addq(r, r12_heapbase); |
8344 Label ok; | 8388 bind(done); |
8345 push(rscratch1); | 8389 } |
8346 cmpptr(r12_heapbase, | |
8347 ExternalAddress((address)Universe::narrow_oop_base_addr())); | |
8348 jcc(Assembler::equal, ok); | |
8349 stop("MacroAssembler::decode_heap_oop: heap base corrupted?"); | |
8350 bind(ok); | |
8351 pop(rscratch1); | |
8352 } | |
8353 #endif | |
8354 | |
8355 Label done; | |
8356 shlq(r, LogMinObjAlignmentInBytes); | |
8357 jccb(Assembler::equal, done); | |
8358 addq(r, r12_heapbase); | |
8359 #if 0 | |
8360 // alternate decoding probably a wash. | |
8361 testq(r, r); | |
8362 jccb(Assembler::equal, done); | |
8363 leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); | |
8364 #endif | |
8365 bind(done); | |
8366 verify_oop(r, "broken oop in decode_heap_oop"); | 8390 verify_oop(r, "broken oop in decode_heap_oop"); |
8367 } | 8391 } |
8368 | 8392 |
8369 void MacroAssembler::decode_heap_oop_not_null(Register r) { | 8393 void MacroAssembler::decode_heap_oop_not_null(Register r) { |
8394 // Note: it will change flags | |
8370 assert (UseCompressedOops, "should only be used for compressed headers"); | 8395 assert (UseCompressedOops, "should only be used for compressed headers"); |
8371 assert (Universe::heap() != NULL, "java heap should be initialized"); | 8396 assert (Universe::heap() != NULL, "java heap should be initialized"); |
8372 // Cannot assert, unverified entry point counts instructions (see .ad file) | 8397 // Cannot assert, unverified entry point counts instructions (see .ad file) |
8373 // vtableStubs also counts instructions in pd_code_size_limit. | 8398 // vtableStubs also counts instructions in pd_code_size_limit. |
8374 // Also do not verify_oop as this is called by verify_oop. | 8399 // Also do not verify_oop as this is called by verify_oop. |
8375 if (Universe::narrow_oop_shift() != 0) { | 8400 if (Universe::narrow_oop_shift() != 0) { |
8376 assert (Address::times_8 == LogMinObjAlignmentInBytes && | 8401 assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
8377 Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong"); | 8402 shlq(r, LogMinObjAlignmentInBytes); |
8378 // Don't use Shift since it modifies flags. | 8403 if (Universe::narrow_oop_base() != NULL) { |
8379 leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); | 8404 addq(r, r12_heapbase); |
8405 } | |
8380 } else { | 8406 } else { |
8381 assert (Universe::narrow_oop_base() == NULL, "sanity"); | 8407 assert (Universe::narrow_oop_base() == NULL, "sanity"); |
8382 } | 8408 } |
8383 } | 8409 } |
8384 | 8410 |
8385 void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { | 8411 void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { |
8412 // Note: it will change flags | |
8386 assert (UseCompressedOops, "should only be used for compressed headers"); | 8413 assert (UseCompressedOops, "should only be used for compressed headers"); |
8387 assert (Universe::heap() != NULL, "java heap should be initialized"); | 8414 assert (Universe::heap() != NULL, "java heap should be initialized"); |
8388 // Cannot assert, unverified entry point counts instructions (see .ad file) | 8415 // Cannot assert, unverified entry point counts instructions (see .ad file) |
8389 // vtableStubs also counts instructions in pd_code_size_limit. | 8416 // vtableStubs also counts instructions in pd_code_size_limit. |
8390 // Also do not verify_oop as this is called by verify_oop. | 8417 // Also do not verify_oop as this is called by verify_oop. |
8391 if (Universe::narrow_oop_shift() != 0) { | 8418 if (Universe::narrow_oop_shift() != 0) { |
8392 assert (Address::times_8 == LogMinObjAlignmentInBytes && | 8419 assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
8393 Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong"); | 8420 if (LogMinObjAlignmentInBytes == Address::times_8) { |
8394 leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); | 8421 leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); |
8395 } else if (dst != src) { | 8422 } else { |
8423 if (dst != src) { | |
8424 movq(dst, src); | |
8425 } | |
8426 shlq(dst, LogMinObjAlignmentInBytes); | |
8427 if (Universe::narrow_oop_base() != NULL) { | |
8428 addq(dst, r12_heapbase); | |
8429 } | |
8430 } | |
8431 } else { | |
8396 assert (Universe::narrow_oop_base() == NULL, "sanity"); | 8432 assert (Universe::narrow_oop_base() == NULL, "sanity"); |
8397 movq(dst, src); | 8433 if (dst != src) { |
8434 movq(dst, src); | |
8435 } | |
8398 } | 8436 } |
8399 } | 8437 } |
8400 | 8438 |
8401 void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { | 8439 void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { |
8402 assert (UseCompressedOops, "should only be used for compressed headers"); | 8440 assert (UseCompressedOops, "should only be used for compressed headers"); |
8754 xorl(result, result); // return false | 8792 xorl(result, result); // return false |
8755 | 8793 |
8756 // That's it | 8794 // That's it |
8757 bind(DONE); | 8795 bind(DONE); |
8758 } | 8796 } |
8797 | |
8798 #ifdef PRODUCT | |
8799 #define BLOCK_COMMENT(str) /* nothing */ | |
8800 #else | |
8801 #define BLOCK_COMMENT(str) block_comment(str) | |
8802 #endif | |
8803 | |
8804 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") | |
8805 void MacroAssembler::generate_fill(BasicType t, bool aligned, | |
8806 Register to, Register value, Register count, | |
8807 Register rtmp, XMMRegister xtmp) { | |
8808 assert_different_registers(to, value, count, rtmp); | |
8809 Label L_exit, L_skip_align1, L_skip_align2, L_fill_byte; | |
8810 Label L_fill_2_bytes, L_fill_4_bytes; | |
8811 | |
8812 int shift = -1; | |
8813 switch (t) { | |
8814 case T_BYTE: | |
8815 shift = 2; | |
8816 break; | |
8817 case T_SHORT: | |
8818 shift = 1; | |
8819 break; | |
8820 case T_INT: | |
8821 shift = 0; | |
8822 break; | |
8823 default: ShouldNotReachHere(); | |
8824 } | |
8825 | |
8826 if (t == T_BYTE) { | |
8827 andl(value, 0xff); | |
8828 movl(rtmp, value); | |
8829 shll(rtmp, 8); | |
8830 orl(value, rtmp); | |
8831 } | |
8832 if (t == T_SHORT) { | |
8833 andl(value, 0xffff); | |
8834 } | |
8835 if (t == T_BYTE || t == T_SHORT) { | |
8836 movl(rtmp, value); | |
8837 shll(rtmp, 16); | |
8838 orl(value, rtmp); | |
8839 } | |
8840 | |
8841 cmpl(count, 2<<shift); // Short arrays (< 8 bytes) fill by element | |
8842 jcc(Assembler::below, L_fill_4_bytes); // use unsigned cmp | |
8843 if (!UseUnalignedLoadStores && !aligned && (t == T_BYTE || t == T_SHORT)) { | |
8844 // align source address at 4 bytes address boundary | |
8845 if (t == T_BYTE) { | |
8846 // One byte misalignment happens only for byte arrays | |
8847 testptr(to, 1); | |
8848 jccb(Assembler::zero, L_skip_align1); | |
8849 movb(Address(to, 0), value); | |
8850 increment(to); | |
8851 decrement(count); | |
8852 BIND(L_skip_align1); | |
8853 } | |
8854 // Two bytes misalignment happens only for byte and short (char) arrays | |
8855 testptr(to, 2); | |
8856 jccb(Assembler::zero, L_skip_align2); | |
8857 movw(Address(to, 0), value); | |
8858 addptr(to, 2); | |
8859 subl(count, 1<<(shift-1)); | |
8860 BIND(L_skip_align2); | |
8861 } | |
8862 if (UseSSE < 2) { | |
8863 Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes; | |
8864 // Fill 32-byte chunks | |
8865 subl(count, 8 << shift); | |
8866 jcc(Assembler::less, L_check_fill_8_bytes); | |
8867 align(16); | |
8868 | |
8869 BIND(L_fill_32_bytes_loop); | |
8870 | |
8871 for (int i = 0; i < 32; i += 4) { | |
8872 movl(Address(to, i), value); | |
8873 } | |
8874 | |
8875 addptr(to, 32); | |
8876 subl(count, 8 << shift); | |
8877 jcc(Assembler::greaterEqual, L_fill_32_bytes_loop); | |
8878 BIND(L_check_fill_8_bytes); | |
8879 addl(count, 8 << shift); | |
8880 jccb(Assembler::zero, L_exit); | |
8881 jmpb(L_fill_8_bytes); | |
8882 | |
8883 // | |
8884 // length is too short, just fill qwords | |
8885 // | |
8886 BIND(L_fill_8_bytes_loop); | |
8887 movl(Address(to, 0), value); | |
8888 movl(Address(to, 4), value); | |
8889 addptr(to, 8); | |
8890 BIND(L_fill_8_bytes); | |
8891 subl(count, 1 << (shift + 1)); | |
8892 jcc(Assembler::greaterEqual, L_fill_8_bytes_loop); | |
8893 // fall through to fill 4 bytes | |
8894 } else { | |
8895 Label L_fill_32_bytes; | |
8896 if (!UseUnalignedLoadStores) { | |
8897 // align to 8 bytes, we know we are 4 byte aligned to start | |
8898 testptr(to, 4); | |
8899 jccb(Assembler::zero, L_fill_32_bytes); | |
8900 movl(Address(to, 0), value); | |
8901 addptr(to, 4); | |
8902 subl(count, 1<<shift); | |
8903 } | |
8904 BIND(L_fill_32_bytes); | |
8905 { | |
8906 assert( UseSSE >= 2, "supported cpu only" ); | |
8907 Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes; | |
8908 // Fill 32-byte chunks | |
8909 movdl(xtmp, value); | |
8910 pshufd(xtmp, xtmp, 0); | |
8911 | |
8912 subl(count, 8 << shift); | |
8913 jcc(Assembler::less, L_check_fill_8_bytes); | |
8914 align(16); | |
8915 | |
8916 BIND(L_fill_32_bytes_loop); | |
8917 | |
8918 if (UseUnalignedLoadStores) { | |
8919 movdqu(Address(to, 0), xtmp); | |
8920 movdqu(Address(to, 16), xtmp); | |
8921 } else { | |
8922 movq(Address(to, 0), xtmp); | |
8923 movq(Address(to, 8), xtmp); | |
8924 movq(Address(to, 16), xtmp); | |
8925 movq(Address(to, 24), xtmp); | |
8926 } | |
8927 | |
8928 addptr(to, 32); | |
8929 subl(count, 8 << shift); | |
8930 jcc(Assembler::greaterEqual, L_fill_32_bytes_loop); | |
8931 BIND(L_check_fill_8_bytes); | |
8932 addl(count, 8 << shift); | |
8933 jccb(Assembler::zero, L_exit); | |
8934 jmpb(L_fill_8_bytes); | |
8935 | |
8936 // | |
8937 // length is too short, just fill qwords | |
8938 // | |
8939 BIND(L_fill_8_bytes_loop); | |
8940 movq(Address(to, 0), xtmp); | |
8941 addptr(to, 8); | |
8942 BIND(L_fill_8_bytes); | |
8943 subl(count, 1 << (shift + 1)); | |
8944 jcc(Assembler::greaterEqual, L_fill_8_bytes_loop); | |
8945 } | |
8946 } | |
8947 // fill trailing 4 bytes | |
8948 BIND(L_fill_4_bytes); | |
8949 testl(count, 1<<shift); | |
8950 jccb(Assembler::zero, L_fill_2_bytes); | |
8951 movl(Address(to, 0), value); | |
8952 if (t == T_BYTE || t == T_SHORT) { | |
8953 addptr(to, 4); | |
8954 BIND(L_fill_2_bytes); | |
8955 // fill trailing 2 bytes | |
8956 testl(count, 1<<(shift-1)); | |
8957 jccb(Assembler::zero, L_fill_byte); | |
8958 movw(Address(to, 0), value); | |
8959 if (t == T_BYTE) { | |
8960 addptr(to, 2); | |
8961 BIND(L_fill_byte); | |
8962 // fill trailing byte | |
8963 testl(count, 1); | |
8964 jccb(Assembler::zero, L_exit); | |
8965 movb(Address(to, 0), value); | |
8966 } else { | |
8967 BIND(L_fill_byte); | |
8968 } | |
8969 } else { | |
8970 BIND(L_fill_2_bytes); | |
8971 } | |
8972 BIND(L_exit); | |
8973 } | |
8974 #undef BIND | |
8975 #undef BLOCK_COMMENT | |
8976 | |
8759 | 8977 |
8760 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { | 8978 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { |
8761 switch (cond) { | 8979 switch (cond) { |
8762 // Note some conditions are synonyms for others | 8980 // Note some conditions are synonyms for others |
8763 case Assembler::zero: return Assembler::notZero; | 8981 case Assembler::zero: return Assembler::notZero; |