blob: d208b83a7bb45f61e8f7eb6274ed09fadfab830b [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/mips64/MoveEmitter-mips64.h"
#include "jit/MacroAssembler-inl.h"
using namespace js;
using namespace js::jit;
void
MoveEmitterMIPS64::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()) {
FloatRegister temp = ScratchFloat32Reg;
masm.loadFloat32(getAdjustedAddress(to), temp);
masm.storeFloat32(temp, cycleSlot(slotId));
} else {
masm.storeFloat32(to.floatReg(), cycleSlot(slotId));
}
break;
case MoveOp::DOUBLE:
if (to.isMemory()) {
FloatRegister temp = ScratchDoubleReg;
masm.loadDouble(getAdjustedAddress(to), temp);
masm.storeDouble(temp, cycleSlot(slotId));
} else {
masm.storeDouble(to.floatReg(), cycleSlot(slotId));
}
break;
case MoveOp::INT32:
if (to.isMemory()) {
Register temp = tempReg();
masm.load32(getAdjustedAddress(to), temp);
masm.store32(temp, cycleSlot(0));
} else {
// Second scratch register should not be moved by MoveEmitter.
MOZ_ASSERT(to.reg() != spilledReg_);
masm.store32(to.reg(), cycleSlot(0));
}
break;
case MoveOp::GENERAL:
if (to.isMemory()) {
Register temp = tempReg();
masm.loadPtr(getAdjustedAddress(to), temp);
masm.storePtr(temp, cycleSlot(0));
} else {
// Second scratch register should not be moved by MoveEmitter.
MOZ_ASSERT(to.reg() != spilledReg_);
masm.storePtr(to.reg(), cycleSlot(0));
}
break;
default:
MOZ_CRASH("Unexpected move type");
}
}
void
MoveEmitterMIPS64::completeCycle(const MoveOperand& from, const MoveOperand& to,
MoveOp::Type type, uint32_t slotId)
{
// There is some pattern:
// (A -> B)
// (B -> A)
//
// This case handles (B -> A), which we reach last. We emit a move from the
// saved value of B, to A.
switch (type) {
case MoveOp::FLOAT32:
if (to.isMemory()) {
FloatRegister temp = ScratchFloat32Reg;
masm.loadFloat32(cycleSlot(slotId), temp);
masm.storeFloat32(temp, getAdjustedAddress(to));
} else {
masm.loadFloat32(cycleSlot(slotId), to.floatReg());
}
break;
case MoveOp::DOUBLE:
if (to.isMemory()) {
FloatRegister temp = ScratchDoubleReg;
masm.loadDouble(cycleSlot(slotId), temp);
masm.storeDouble(temp, getAdjustedAddress(to));
} else {
masm.loadDouble(cycleSlot(slotId), to.floatReg());
}
break;
case MoveOp::INT32:
MOZ_ASSERT(slotId == 0);
if (to.isMemory()) {
Register temp = tempReg();
masm.load32(cycleSlot(0), temp);
masm.store32(temp, getAdjustedAddress(to));
} else {
// Second scratch register should not be moved by MoveEmitter.
MOZ_ASSERT(to.reg() != spilledReg_);
masm.load32(cycleSlot(0), to.reg());
}
break;
case MoveOp::GENERAL:
MOZ_ASSERT(slotId == 0);
if (to.isMemory()) {
Register temp = tempReg();
masm.loadPtr(cycleSlot(0), temp);
masm.storePtr(temp, getAdjustedAddress(to));
} else {
// Second scratch register should not be moved by MoveEmitter.
MOZ_ASSERT(to.reg() != spilledReg_);
masm.loadPtr(cycleSlot(0), to.reg());
}
break;
default:
MOZ_CRASH("Unexpected move type");
}
}
void
MoveEmitterMIPS64::emitDoubleMove(const MoveOperand& from, const MoveOperand& to)
{
// Ensure that we can use ScratchDoubleReg in memory move.
MOZ_ASSERT_IF(from.isFloatReg(), from.floatReg() != ScratchDoubleReg);
MOZ_ASSERT_IF(to.isFloatReg(), to.floatReg() != ScratchDoubleReg);
if (from.isFloatReg()) {
if (to.isFloatReg()) {
masm.moveDouble(from.floatReg(), to.floatReg());
} else if (to.isGeneralReg()) {
masm.moveFromDouble(from.floatReg(), to.reg());
} else {
MOZ_ASSERT(to.isMemory());
masm.storeDouble(from.floatReg(), getAdjustedAddress(to));
}
} else if (to.isFloatReg()) {
if (from.isMemory())
masm.loadDouble(getAdjustedAddress(from), to.floatReg());
else
masm.moveToDouble(from.reg(), to.floatReg());
} else {
MOZ_ASSERT(from.isMemory());
MOZ_ASSERT(to.isMemory());
masm.loadDouble(getAdjustedAddress(from), ScratchDoubleReg);
masm.storeDouble(ScratchDoubleReg, getAdjustedAddress(to));
}
}