diff options
Diffstat (limited to 'js/src/jit/mips32/MoveEmitter-mips32.cpp')
-rw-r--r-- | js/src/jit/mips32/MoveEmitter-mips32.cpp | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/js/src/jit/mips32/MoveEmitter-mips32.cpp b/js/src/jit/mips32/MoveEmitter-mips32.cpp new file mode 100644 index 0000000000..2f52c73899 --- /dev/null +++ b/js/src/jit/mips32/MoveEmitter-mips32.cpp @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * 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/mips32/MoveEmitter-mips32.h" + +#include "jit/MacroAssembler-inl.h" + +using namespace js; +using namespace js::jit; + +void MoveEmitterMIPS::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); + // Since it is uncertain if the load will be aligned or not + // just fill both of them with the same value. + masm.storeFloat32(temp, cycleSlot(slotId, 0)); + masm.storeFloat32(temp, cycleSlot(slotId, 4)); + } else { + // Just always store the largest possible size. + masm.storeDouble(to.floatReg().doubleOverlay(), cycleSlot(slotId, 0)); + } + break; + case MoveOp::DOUBLE: + if (to.isMemory()) { + FloatRegister temp = ScratchDoubleReg; + masm.loadDouble(getAdjustedAddress(to), temp); + masm.storeDouble(temp, cycleSlot(slotId, 0)); + } else { + masm.storeDouble(to.floatReg(), cycleSlot(slotId, 0)); + } + break; + case MoveOp::INT32: + MOZ_ASSERT(sizeof(uintptr_t) == sizeof(int32_t)); + [[fallthrough]]; + case MoveOp::GENERAL: + if (to.isMemory()) { + Register temp = tempReg(); + masm.loadPtr(getAdjustedAddress(to), temp); + masm.storePtr(temp, cycleSlot(0, 0)); + } else { + // Second scratch register should not be moved by MoveEmitter. + MOZ_ASSERT(to.reg() != spilledReg_); + masm.storePtr(to.reg(), cycleSlot(0, 0)); + } + break; + default: + MOZ_CRASH("Unexpected move type"); + } +} + +void MoveEmitterMIPS::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, 0), temp); + masm.storeFloat32(temp, getAdjustedAddress(to)); + } else { + uint32_t offset = 0; + if (from.floatReg().numAlignedAliased() == 1) { + offset = sizeof(float); + } + masm.loadFloat32(cycleSlot(slotId, offset), to.floatReg()); + } + break; + case MoveOp::DOUBLE: + if (to.isMemory()) { + FloatRegister temp = ScratchDoubleReg; + masm.loadDouble(cycleSlot(slotId, 0), temp); + masm.storeDouble(temp, getAdjustedAddress(to)); + } else { + masm.loadDouble(cycleSlot(slotId, 0), to.floatReg()); + } + break; + case MoveOp::INT32: + MOZ_ASSERT(sizeof(uintptr_t) == sizeof(int32_t)); + [[fallthrough]]; + case MoveOp::GENERAL: + MOZ_ASSERT(slotId == 0); + if (to.isMemory()) { + Register temp = tempReg(); + masm.loadPtr(cycleSlot(0, 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, 0), to.reg()); + } + break; + default: + MOZ_CRASH("Unexpected move type"); + } +} + +void MoveEmitterMIPS::emitDoubleMove(const MoveOperand& from, + const MoveOperand& to) { + if (from.isFloatReg()) { + if (to.isFloatReg()) { + masm.moveDouble(from.floatReg(), to.floatReg()); + } else if (to.isGeneralRegPair()) { + // Used for passing double parameter in a2,a3 register pair. + // Two moves are added for one double parameter by + // MacroAssembler::passABIArg + MOZ_ASSERT(to.evenReg() == a2 && to.oddReg() == a3, + "Invalid emitDoubleMove arguments."); + masm.moveFromDoubleLo(from.floatReg(), a2); + masm.moveFromDoubleHi(from.floatReg(), a3); + } else { + MOZ_ASSERT(to.isMemory()); + masm.storeDouble(from.floatReg(), getAdjustedAddress(to)); + } + } else if (to.isFloatReg()) { + MOZ_ASSERT(from.isMemory()); + masm.loadDouble(getAdjustedAddress(from), to.floatReg()); + } else if (to.isGeneralRegPair()) { + // Used for passing double parameter in a2,a3 register pair. + // Two moves are added for one double parameter by + // MacroAssembler::passABIArg + MOZ_ASSERT(from.isMemory()); + MOZ_ASSERT(to.evenReg() == a2 && to.oddReg() == a3, + "Invalid emitDoubleMove arguments."); + masm.loadPtr(getAdjustedAddress(from), a2); + masm.loadPtr( + Address(from.base(), getAdjustedOffset(from) + sizeof(uint32_t)), a3); + } else { + MOZ_ASSERT(from.isMemory()); + MOZ_ASSERT(to.isMemory()); + masm.loadDouble(getAdjustedAddress(from), ScratchDoubleReg); + masm.storeDouble(ScratchDoubleReg, getAdjustedAddress(to)); + } +} |