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 8253b34248613cd9d38221917692475a0d7ebc8f..24bdb8168c3251ebad563e594697f5aa0e953b3b 100644 |
--- a/runtime/vm/flow_graph_compiler_ia32.cc |
+++ b/runtime/vm/flow_graph_compiler_ia32.cc |
@@ -880,6 +880,7 @@ void FlowGraphCompiler::GenerateInlinedMathSqrt(Label* done) { |
AssemblerMacros::TryAllocate(assembler_, |
double_class_, |
&call_method, |
+ Assembler::kNearJump, |
EAX); // Result register. |
__ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
__ Drop(1); |
@@ -1106,12 +1107,56 @@ void FlowGraphCompiler::LoadDoubleOrSmiToXmm(XmmRegister result, |
} |
+void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
+ // TODO(vegorov): consider saving only caller save (volatile) registers. |
+ const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
+ if (xmm_regs_count > 0) { |
+ intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
+ for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
+ XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
+ if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
+ __ movsd(Address(EBP, -stack_offs), xmm_reg); |
+ stack_offs += kDoubleSize; |
+ } |
+ } |
+ } |
+ |
+ for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) { |
+ Register reg = static_cast<Register>(reg_idx); |
+ if (locs->live_registers()->ContainsRegister(reg)) { |
+ __ pushl(reg); |
+ } |
+ } |
+} |
+ |
+ |
+void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { |
+ for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { |
+ Register reg = static_cast<Register>(reg_idx); |
+ if (locs->live_registers()->ContainsRegister(reg)) { |
+ __ popl(reg); |
+ } |
+ } |
+ |
+ const intptr_t xmm_regs_count = locs->live_registers()->xmm_regs_count(); |
+ if (xmm_regs_count > 0) { |
+ intptr_t stack_offs = (StackSize() + 1) * kWordSize; |
+ for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
+ XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
+ if (locs->live_registers()->ContainsXmmRegister(xmm_reg)) { |
+ __ movsd(xmm_reg, Address(EBP, -stack_offs)); |
+ stack_offs += kDoubleSize; |
+ } |
+ } |
+ } |
+} |
+ |
+ |
#undef __ |
#define __ compiler_->assembler()-> |
static Address ToStackSlotAddress(Location loc) { |
- ASSERT(loc.IsStackSlot()); |
const intptr_t index = loc.stack_index(); |
if (index < 0) { |
const intptr_t offset = (1 - index) * kWordSize; |
@@ -1144,6 +1189,23 @@ void ParallelMoveResolver::EmitMove(int index) { |
MoveMemoryToMemory(ToStackSlotAddress(destination), |
ToStackSlotAddress(source)); |
} |
+ } else if (source.IsXmmRegister()) { |
+ if (destination.IsXmmRegister()) { |
+ // Optimization manual recommends using MOVAPS for register |
+ // to register moves. |
+ __ movaps(destination.xmm_reg(), source.xmm_reg()); |
+ } else { |
+ ASSERT(destination.IsDoubleStackSlot()); |
+ __ movsd(ToStackSlotAddress(destination), source.xmm_reg()); |
+ } |
+ } else if (source.IsDoubleStackSlot()) { |
+ if (destination.IsXmmRegister()) { |
+ __ movsd(destination.xmm_reg(), ToStackSlotAddress(source)); |
+ } else { |
+ ASSERT(destination.IsDoubleStackSlot()); |
+ __ movsd(XMM0, ToStackSlotAddress(source)); |
+ __ movsd(ToStackSlotAddress(destination), XMM0); |
+ } |
} else { |
ASSERT(source.IsConstant()); |
if (destination.IsRegister()) { |
@@ -1171,6 +1233,20 @@ void ParallelMoveResolver::EmitSwap(int index) { |
Exchange(destination.reg(), ToStackSlotAddress(source)); |
} else if (source.IsStackSlot() && destination.IsStackSlot()) { |
Exchange(ToStackSlotAddress(destination), ToStackSlotAddress(source)); |
+ } else if (source.IsXmmRegister() && destination.IsXmmRegister()) { |
+ __ movaps(XMM0, source.xmm_reg()); |
+ __ movaps(source.xmm_reg(), destination.xmm_reg()); |
+ __ movaps(destination.xmm_reg(), XMM0); |
+ } else if (source.IsXmmRegister() || destination.IsXmmRegister()) { |
+ ASSERT(destination.IsDoubleStackSlot() || source.IsDoubleStackSlot()); |
+ XmmRegister reg = source.IsXmmRegister() ? source.xmm_reg() |
+ : destination.xmm_reg(); |
+ Address slot_address = |
+ ToStackSlotAddress(source.IsXmmRegister() ? destination : source); |
+ |
+ __ movsd(XMM0, slot_address); |
+ __ movsd(slot_address, reg); |
+ __ movaps(reg, XMM0); |
} else { |
UNREACHABLE(); |
} |