| Index: runtime/vm/flow_graph_compiler_ia32.cc
|
| diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
|
| index 0113aeb7ec81622e6a46072ae4c2851e27cc2c54..302b8746eeb8e9af2262db8ef96069c43c3d26f3 100644
|
| --- a/runtime/vm/flow_graph_compiler_ia32.cc
|
| +++ b/runtime/vm/flow_graph_compiler_ia32.cc
|
| @@ -1596,8 +1596,7 @@ void ParallelMoveResolver::EmitMove(int index) {
|
| if (destination.IsDoubleStackSlot()) {
|
| __ movsd(destination.ToStackSlotAddress(), source.fpu_reg());
|
| } else {
|
| - ASSERT(destination.IsFloat32x4StackSlot() ||
|
| - destination.IsUint32x4StackSlot());
|
| + ASSERT(destination.IsQuadStackSlot());
|
| __ movups(destination.ToStackSlotAddress(), source.fpu_reg());
|
| }
|
| }
|
| @@ -1609,12 +1608,11 @@ void ParallelMoveResolver::EmitMove(int index) {
|
| __ movsd(XMM0, source.ToStackSlotAddress());
|
| __ movsd(destination.ToStackSlotAddress(), XMM0);
|
| }
|
| - } else if (source.IsFloat32x4StackSlot() || source.IsUint32x4StackSlot()) {
|
| + } else if (source.IsQuadStackSlot()) {
|
| if (destination.IsFpuRegister()) {
|
| __ movups(destination.fpu_reg(), source.ToStackSlotAddress());
|
| } else {
|
| - ASSERT(destination.IsFloat32x4StackSlot() ||
|
| - destination.IsUint32x4StackSlot());
|
| + ASSERT(destination.IsQuadStackSlot());
|
| __ movups(XMM0, source.ToStackSlotAddress());
|
| __ movups(destination.ToStackSlotAddress(), XMM0);
|
| }
|
| @@ -1656,11 +1654,9 @@ void ParallelMoveResolver::EmitSwap(int index) {
|
| __ movaps(destination.fpu_reg(), XMM0);
|
| } else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
|
| ASSERT(destination.IsDoubleStackSlot() ||
|
| - destination.IsFloat32x4StackSlot() ||
|
| - destination.IsUint32x4StackSlot() ||
|
| + destination.IsQuadStackSlot() ||
|
| source.IsDoubleStackSlot() ||
|
| - source.IsFloat32x4StackSlot() ||
|
| - source.IsUint32x4StackSlot());
|
| + source.IsQuadStackSlot());
|
| bool double_width = destination.IsDoubleStackSlot() ||
|
| source.IsDoubleStackSlot();
|
| XmmRegister reg = source.IsFpuRegister() ? source.fpu_reg()
|
| @@ -1677,6 +1673,24 @@ void ParallelMoveResolver::EmitSwap(int index) {
|
| __ movups(slot_address, reg);
|
| }
|
| __ movaps(reg, XMM0);
|
| + } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
|
| + const Address& source_slot_address = source.ToStackSlotAddress();
|
| + const Address& destination_slot_address = destination.ToStackSlotAddress();
|
| +
|
| + ScratchFpuRegisterScope ensure_scratch(this, XMM0);
|
| + __ movsd(XMM0, source_slot_address);
|
| + __ movsd(ensure_scratch.reg(), destination_slot_address);
|
| + __ movsd(destination_slot_address, XMM0);
|
| + __ movsd(source_slot_address, ensure_scratch.reg());
|
| + } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
|
| + const Address& source_slot_address = source.ToStackSlotAddress();
|
| + const Address& destination_slot_address = destination.ToStackSlotAddress();
|
| +
|
| + ScratchFpuRegisterScope ensure_scratch(this, XMM0);
|
| + __ movups(XMM0, source_slot_address);
|
| + __ movups(ensure_scratch.reg(), destination_slot_address);
|
| + __ movups(destination_slot_address, XMM0);
|
| + __ movups(source_slot_address, ensure_scratch.reg());
|
| } else {
|
| UNREACHABLE();
|
| }
|
| @@ -1701,48 +1715,60 @@ void ParallelMoveResolver::EmitSwap(int index) {
|
|
|
| void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
|
| const Address& src) {
|
| - // TODO(vegorov): allocate temporary register for such moves.
|
| - __ pushl(EAX);
|
| - __ movl(EAX, src);
|
| - __ movl(dst, EAX);
|
| - __ popl(EAX);
|
| + ScratchRegisterScope ensure_scratch(this, kNoRegister);
|
| + __ movl(ensure_scratch.reg(), src);
|
| + __ movl(dst, ensure_scratch.reg());
|
| }
|
|
|
|
|
| void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
|
| - // TODO(vegorov): allocate temporary register for such moves.
|
| if (obj.IsSmi() || obj.IsNull()) {
|
| __ movl(dst, Immediate(reinterpret_cast<int32_t>(obj.raw())));
|
| } else {
|
| - __ pushl(EAX);
|
| - __ LoadObject(EAX, obj);
|
| - __ movl(dst, EAX);
|
| - __ popl(EAX);
|
| + ScratchRegisterScope ensure_scratch(this, kNoRegister);
|
| + __ LoadObject(ensure_scratch.reg(), obj);
|
| + __ movl(dst, ensure_scratch.reg());
|
| }
|
| }
|
|
|
|
|
| void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
|
| - // TODO(vegorov): allocate temporary register for such moves.
|
| - Register scratch = (reg == EAX) ? ECX : EAX;
|
| - __ pushl(scratch);
|
| - __ movl(scratch, mem);
|
| - __ xchgl(scratch, reg);
|
| - __ movl(mem, scratch);
|
| - __ popl(scratch);
|
| + ScratchRegisterScope ensure_scratch(this, reg);
|
| + __ movl(ensure_scratch.reg(), mem);
|
| + __ movl(mem, reg);
|
| + __ movl(reg, ensure_scratch.reg());
|
| }
|
|
|
|
|
| void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
|
| - // TODO(vegorov): allocate temporary registers for such moves.
|
| - __ pushl(EAX);
|
| - __ pushl(ECX);
|
| - __ movl(EAX, mem1);
|
| - __ movl(ECX, mem2);
|
| - __ movl(mem1, ECX);
|
| - __ movl(mem2, EAX);
|
| - __ popl(ECX);
|
| - __ popl(EAX);
|
| + ScratchRegisterScope ensure_scratch1(this, kNoRegister);
|
| + ScratchRegisterScope ensure_scratch2(this, ensure_scratch1.reg());
|
| + __ movl(ensure_scratch1.reg(), mem1);
|
| + __ movl(ensure_scratch2.reg(), mem2);
|
| + __ movl(mem2, ensure_scratch1.reg());
|
| + __ movl(mem1, ensure_scratch2.reg());
|
| +}
|
| +
|
| +
|
| +void ParallelMoveResolver::SpillScratch(Register reg) {
|
| + __ pushl(reg);
|
| +}
|
| +
|
| +
|
| +void ParallelMoveResolver::RestoreScratch(Register reg) {
|
| + __ popl(reg);
|
| +}
|
| +
|
| +
|
| +void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
|
| + __ subl(ESP, Immediate(kFpuRegisterSize));
|
| + __ movups(Address(ESP, 0), reg);
|
| +}
|
| +
|
| +
|
| +void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
|
| + __ movups(reg, Address(ESP, 0));
|
| + __ addl(ESP, Immediate(kFpuRegisterSize));
|
| }
|
|
|
|
|
|
|