Chromium Code Reviews| Index: runtime/vm/assembler_x64.cc |
| =================================================================== |
| --- runtime/vm/assembler_x64.cc (revision 28057) |
| +++ runtime/vm/assembler_x64.cc (working copy) |
| @@ -204,6 +204,16 @@ |
| } |
| +void Assembler::PushImmediate(const Immediate& imm, Register pp) { |
| + if (imm.is_int32()) { |
| + pushq(imm); |
| + } else { |
| + LoadImmediate(TMP, imm, pp); |
| + pushq(TMP); |
| + } |
| +} |
| + |
| + |
| void Assembler::popq(Register reg) { |
| AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| EmitRegisterREX(reg, REX_NONE); |
| @@ -813,7 +823,8 @@ |
| uint32_t d; |
| } float_not_constant = |
| { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; |
| - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant))); |
| + LoadImmediate( |
| + TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant)), PP); |
| xorps(dst, Address(TMP, 0)); |
| } |
| @@ -826,7 +837,8 @@ |
| uint32_t d; |
| } float_negate_constant = |
| { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; |
| - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant))); |
| + LoadImmediate( |
| + TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant)), PP); |
| xorps(dst, Address(TMP, 0)); |
| } |
| @@ -839,7 +851,8 @@ |
| uint32_t d; |
| } float_absolute_constant = |
| { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; |
| - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant))); |
| + LoadImmediate( |
| + TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant)), PP); |
| andps(dst, Address(TMP, 0)); |
| } |
| @@ -852,7 +865,8 @@ |
| uint32_t d; |
| } float_zerow_constant = |
| { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }; |
| - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant))); |
| + LoadImmediate( |
| + TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant)), PP); |
| andps(dst, Address(TMP, 0)); |
| } |
| @@ -1342,6 +1356,28 @@ |
| } |
| +void Assembler::CompareImmediate(Register reg, const Immediate& imm, |
| + Register pp) { |
| + if (imm.is_int32()) { |
| + cmpq(reg, imm); |
| + } else { |
| + LoadImmediate(TMP, imm, pp); |
| + cmpq(reg, TMP); |
| + } |
| +} |
| + |
| + |
| +void Assembler::CompareImmediate(const Address& address, const Immediate& imm, |
| + Register pp) { |
| + if (imm.is_int32()) { |
| + cmpq(address, imm); |
| + } else { |
| + LoadImmediate(TMP, imm, pp); |
| + cmpq(address, TMP); |
| + } |
| +} |
| + |
| + |
| void Assembler::testl(Register reg1, Register reg2) { |
| AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| Operand operand(reg2); |
| @@ -1492,6 +1528,17 @@ |
| } |
| +void Assembler::AndImmediate(Register dst, const Immediate& imm, Register pp) { |
| + if (imm.is_int32()) { |
| + andq(dst, imm); |
| + } else { |
| + ASSERT(dst != TMP); |
| + LoadImmediate(TMP, imm, pp); |
| + andq(dst, TMP); |
| + } |
| +} |
| + |
| + |
| void Assembler::orq(Register dst, Register src) { |
| AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| Operand operand(src); |
| @@ -1521,6 +1568,17 @@ |
| } |
| +void Assembler::OrImmediate(Register dst, const Immediate& imm, Register pp) { |
| + if (imm.is_int32()) { |
| + orq(dst, imm); |
| + } else { |
| + ASSERT(dst != TMP); |
| + LoadImmediate(TMP, imm, pp); |
| + orq(dst, TMP); |
| + } |
| +} |
| + |
| + |
| void Assembler::xorq(Register dst, Register src) { |
| AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| Operand operand(src); |
| @@ -1558,6 +1616,17 @@ |
| } |
| +void Assembler::XorImmediate(Register dst, const Immediate& imm, Register pp) { |
| + if (imm.is_int32()) { |
| + xorq(dst, imm); |
| + } else { |
| + ASSERT(dst != TMP); |
| + LoadImmediate(TMP, imm, pp); |
| + xorq(dst, TMP); |
| + } |
| +} |
| + |
| + |
| void Assembler::addl(Register dst, Register src) { |
| AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| Operand operand(src); |
| @@ -1708,6 +1777,17 @@ |
| } |
| +void Assembler::MulImmediate(Register reg, const Immediate& imm, Register pp) { |
| + if (imm.is_int32()) { |
| + imulq(reg, imm); |
| + } else { |
| + ASSERT(reg != TMP); |
| + LoadImmediate(TMP, imm, pp); |
| + imulq(reg, TMP); |
| + } |
| +} |
| + |
| + |
| void Assembler::imulq(Register dst, const Address& address) { |
| AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| EmitOperandREX(dst, address, REX_W); |
| @@ -1746,6 +1826,21 @@ |
| } |
| +void Assembler::subq(const Address& address, Register reg) { |
| + AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| + EmitOperandREX(reg, address, REX_W); |
| + EmitUint8(0x29); |
| + EmitOperand(reg & 7, address); |
| +} |
| + |
| + |
| +void Assembler::subq(const Address& address, const Immediate& imm) { |
| + // TODO(srdjan): Implement shorter version for imm32. |
| + movq(TMP, imm); |
| + subq(address, TMP); |
| +} |
| + |
| + |
| void Assembler::shll(Register reg, const Immediate& imm) { |
| EmitGenericShift(false, 4, reg, imm); |
| } |
| @@ -2138,25 +2233,69 @@ |
| } |
| -void Assembler::AddImmediate(Register reg, const Immediate& imm) { |
| +void Assembler::AddImmediate(Register reg, const Immediate& imm, Register pp) { |
| int64_t value = imm.value(); |
| if (value > 0) { |
| if (value == 1) { |
| incq(reg); |
| } else if (value != 0) { |
| - addq(reg, imm); |
| + if (imm.is_int32()) { |
| + addq(reg, imm); |
| + } else { |
| + ASSERT(reg != TMP); |
| + LoadImmediate(TMP, imm, pp); |
| + addq(reg, TMP); |
| + } |
| } |
| } else if (value < 0) { |
| value = -value; |
| if (value == 1) { |
| decq(reg); |
| } else if (value != 0) { |
| - subq(reg, Immediate(value)); |
| + const Immediate& s = Immediate(value); |
| + if (s.is_int32()) { |
| + subq(reg, Immediate(value)); |
| + } else { |
| + ASSERT(reg != TMP); |
| + LoadImmediate(TMP, s, pp); |
| + subq(reg, TMP); |
| + } |
| } |
| } |
| } |
| +void Assembler::AddImmediate(const Address& address, const Immediate& imm, |
| + Register pp) { |
| + int64_t value = imm.value(); |
| + if (value > 0) { |
| + if (value == 1) { |
| + incq(address); |
| + } else if (value != 0) { |
| + if (imm.is_int32()) { |
| + addq(address, imm); |
| + } else { |
| + LoadImmediate(TMP, imm, pp); |
| + addq(address, TMP); |
| + } |
| + } |
| + } else if (value < 0) { |
| + value = -value; |
| + if (value == 1) { |
| + decq(address); |
| + } else if (value != 0) { |
| + const Immediate& s = Immediate(value); |
| + if (s.is_int32()) { |
| + subq(address, s); |
| + } else { |
| + LoadImmediate(TMP, s, pp); |
| + subq(address, TMP); |
| + } |
| + } |
| + } |
| +} |
| + |
| + |
| void Assembler::Drop(intptr_t stack_elements) { |
| ASSERT(stack_elements >= 0); |
| if (stack_elements <= 4) { |
| @@ -2261,42 +2400,87 @@ |
| ASSERT((Isolate::Current() == Dart::vm_isolate()) || |
| object.IsSmi() || |
| object.InVMHeap()); |
| - movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
| + LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
| } |
| } |
| -void Assembler::StoreObject(const Address& dst, const Object& object) { |
| +void Assembler::StoreObject(const Address& dst, const Object& object, |
| + Register pp) { |
| if (CanLoadFromObjectPool(object)) { |
| - LoadObject(TMP, object, PP); |
| + LoadObject(TMP, object, pp); |
| movq(dst, TMP); |
| } else { |
| - movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
| + LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
| } |
| } |
| -void Assembler::PushObject(const Object& object) { |
| +void Assembler::PushObject(const Object& object, Register pp) { |
| if (CanLoadFromObjectPool(object)) { |
| - LoadObject(TMP, object, PP); |
| + LoadObject(TMP, object, pp); |
| pushq(TMP); |
| } else { |
| - pushq(Immediate(reinterpret_cast<int64_t>(object.raw()))); |
| + PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
| } |
| } |
| -void Assembler::CompareObject(Register reg, const Object& object) { |
| +void Assembler::CompareObject(Register reg, const Object& object, Register pp) { |
| if (CanLoadFromObjectPool(object)) { |
| ASSERT(reg != TMP); |
| - LoadObject(TMP, object, PP); |
| + LoadObject(TMP, object, pp); |
| cmpq(reg, TMP); |
| } else { |
| - cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); |
| + CompareImmediate( |
| + reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
| } |
| } |
| +intptr_t Assembler::FindImmediate(int64_t imm) { |
| + ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| + ASSERT(!object_pool_.IsNull()); |
| + const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); |
| + return FindObject(smi, kNotPatchable); |
| +} |
| + |
| + |
| +void Assembler::LoadImmediate(Register reg, const Immediate& imm, Register pp) { |
| + if (imm.is_int32() || |
| + (pp == kNoRegister) || |
| + (Isolate::Current() == Dart::vm_isolate())) { |
| + movq(reg, imm); |
| + } else { |
| + // It's a 64-bit constant and we're not in the VM isolate, so load from |
| + // object pool. |
| + int64_t val = imm.value(); |
| + // Save the bits that must be masked-off for the SmiTag |
| + int64_t val_smi_tag = val & kSmiTagMask; |
| + val &= ~kSmiTagMask; // Mask off the tag bits. |
| + const int32_t offset = Array::element_offset(FindImmediate(val)); |
| + LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag); |
| + if (val_smi_tag != 0) { |
| + // Add back the tag bits. |
| + orq(reg, Immediate(val_smi_tag)); |
| + } |
| + } |
| +} |
| + |
| + |
| +void Assembler::LoadImmediate(const Address& dst, const Immediate& imm, |
| + Register pp) { |
| + if (imm.is_int32() || |
| + (pp == kNoRegister) || |
| + (Isolate::Current() == Dart::vm_isolate())) { |
|
Florian Schneider
2013/09/30 18:43:35
These 3 conditions seem to be repeated a couple of
zra
2013/09/30 19:59:31
Done.
|
| + movq(dst, imm); |
| + } else { |
| + LoadImmediate(TMP, imm, pp); |
| + movq(dst, TMP); |
| + } |
| +} |
| + |
| + |
| // Destroys the value register. |
| void Assembler::StoreIntoObjectFilterNoSmi(Register object, |
| Register value, |
| @@ -2383,7 +2567,8 @@ |
| uint64_t b; |
| } double_negate_constant = |
| {0x8000000000000000LL, 0x8000000000000000LL}; |
| - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant))); |
| + LoadImmediate( |
| + TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP); |
| xorpd(d, Address(TMP, 0)); |
| } |
| @@ -2394,7 +2579,8 @@ |
| uint64_t b; |
| } double_abs_constant = |
| {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; |
| - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&double_abs_constant))); |
| + LoadImmediate(TMP, |
| + Immediate(reinterpret_cast<intptr_t>(&double_abs_constant)), PP); |
| andpd(reg, Address(TMP, 0)); |
| } |
| @@ -2404,7 +2590,7 @@ |
| if (FLAG_print_stop_message) { |
| pushq(TMP); // Preserve TMP register. |
| pushq(RDI); // Preserve RDI register. |
| - movq(RDI, Immediate(message_address)); |
| + LoadImmediate(RDI, Immediate(message_address), PP); |
| call(&StubCode::PrintStopMessageLabel()); |
| popq(RDI); // Restore RDI register. |
| popq(TMP); // Restore TMP register. |
| @@ -2477,7 +2663,9 @@ |
| void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { |
| // Reserve space for arguments and align frame before entering |
| // the C++ world. |
| - AddImmediate(RSP, Immediate(-frame_space)); |
| + if (frame_space != 0) { |
| + subq(RSP, Immediate(frame_space)); |
| + } |
| if (OS::ActivationFrameAlignment() > 1) { |
| andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
| } |
| @@ -2667,29 +2855,31 @@ |
| void Assembler::TryAllocate(const Class& cls, |
| Label* failure, |
| bool near_jump, |
| - Register instance_reg) { |
| + Register instance_reg, |
| + Register pp) { |
| ASSERT(failure != NULL); |
| if (FLAG_inline_alloc) { |
| Heap* heap = Isolate::Current()->heap(); |
| const intptr_t instance_size = cls.instance_size(); |
| - movq(TMP, Immediate(heap->TopAddress())); |
| + LoadImmediate(TMP, Immediate(heap->TopAddress()), pp); |
| movq(instance_reg, Address(TMP, 0)); |
| - addq(instance_reg, Immediate(instance_size)); |
| + AddImmediate(instance_reg, Immediate(instance_size), pp); |
| // instance_reg: potential next object start. |
| - movq(TMP, Immediate(heap->EndAddress())); |
| + LoadImmediate(TMP, Immediate(heap->EndAddress()), pp); |
| cmpq(instance_reg, Address(TMP, 0)); |
| j(ABOVE_EQUAL, failure, near_jump); |
| // Successfully allocated the object, now update top to point to |
| // next object start and store the class in the class field of object. |
| - movq(TMP, Immediate(heap->TopAddress())); |
| + LoadImmediate(TMP, Immediate(heap->TopAddress()), pp); |
| movq(Address(TMP, 0), instance_reg); |
| ASSERT(instance_size >= kHeapObjectTag); |
| - subq(instance_reg, Immediate(instance_size - kHeapObjectTag)); |
| + AddImmediate(instance_reg, Immediate(kHeapObjectTag - instance_size), pp); |
| uword tags = 0; |
| tags = RawObject::SizeTag::update(instance_size, tags); |
| ASSERT(cls.id() != kIllegalCid); |
| tags = RawObject::ClassIdTag::update(cls.id(), tags); |
| - movq(FieldAddress(instance_reg, Object::tags_offset()), Immediate(tags)); |
| + LoadImmediate(FieldAddress(instance_reg, Object::tags_offset()), |
| + Immediate(tags), pp); |
| } else { |
| jmp(failure); |
| } |