void MoveEmitterARM::breakCycle(const MoveOperand& from, const MoveOperand& to, MoveOp::Type type, uint32_t slotId) { // There is some pattern: // (A -> B) // (B -> A) // // This case handles (A -> B), which we reach first. We save B, then allow // the original move to continue. switch (type) { case MoveOp::FLOAT32: if (to.isMemory()) { VFPRegister temp = ScratchFloat32Reg; masm.ma_vldr(toAddress(to), temp); // Since it is uncertain if the load will be aligned or not // just fill both of them with the same value. masm.ma_vstr(temp, cycleSlot(slotId, 0)); masm.ma_vstr(temp, cycleSlot(slotId, 4)); } else if (to.isGeneralReg()) { // Since it is uncertain if the load will be aligned or not // just fill both of them with the same value. masm.ma_str(to.reg(), cycleSlot(slotId, 0)); masm.ma_str(to.reg(), cycleSlot(slotId, 4)); } else { FloatRegister src = to.floatReg(); // Just always store the largest possible size. Currently, this is // a double. When SIMD is added, two doubles will need to be stored. masm.ma_vstr(src.doubleOverlay(), cycleSlot(slotId, 0)); } break; case MoveOp::DOUBLE: if (to.isMemory()) { ScratchDoubleScope scratch(masm); masm.ma_vldr(toAddress(to), scratch); masm.ma_vstr(scratch, cycleSlot(slotId, 0)); } else if (to.isGeneralRegPair()) { ScratchDoubleScope scratch(masm); masm.ma_vxfer(to.evenReg(), to.oddReg(), scratch); masm.ma_vstr(scratch, cycleSlot(slotId, 0)); } else { masm.ma_vstr(to.floatReg().doubleOverlay(), cycleSlot(slotId, 0)); } break; case MoveOp::INT32: case MoveOp::GENERAL: // an non-vfp value if (to.isMemory()) { Register temp = tempReg(); masm.ma_ldr(toAddress(to), temp); masm.ma_str(temp, cycleSlot(0,0)); } else { if (to.reg() == spilledReg_) { // If the destination was spilled, restore it first. masm.ma_ldr(spillSlot(), spilledReg_); spilledReg_ = InvalidReg; } masm.ma_str(to.reg(), cycleSlot(0,0)); } break; default: MOZ_CRASH("Unexpected move type"); } }