MemOperand MoveEmitterARM64::toMemOperand(const MoveOperand& operand) const { MOZ_ASSERT(operand.isMemory()); ARMRegister base(operand.base(), 64); if (operand.base() == masm.getStackPointer()) { return MemOperand(base, operand.disp() + (masm.framePushed() - pushedAtStart_)); } return MemOperand(base, operand.disp()); }
Address MoveEmitterX86::toAddress(const MoveOperand& operand) const { if (operand.base() != StackPointer) return Address(operand.base(), operand.disp()); MOZ_ASSERT(operand.disp() >= 0); // Otherwise, the stack offset may need to be adjusted. return Address(StackPointer, operand.disp() + (masm.framePushed() - pushedAtStart_)); }
Address MoveEmitterARM::toAddress(const MoveOperand& operand) const { MOZ_ASSERT(operand.isMemoryOrEffectiveAddress()); if (operand.base() != StackPointer) { MOZ_ASSERT(operand.disp() < 1024 && operand.disp() > -1024); return Operand(operand.base(), operand.disp()).toAddress(); } MOZ_ASSERT(operand.disp() >= 0); // Otherwise, the stack offset may need to be adjusted. return Address(StackPointer, operand.disp() + (masm.framePushed() - pushedAtStart_)); }
void MoveEmitterARM::emitMove(const MoveOperand &from, const MoveOperand &to) { if (to.isGeneralReg() && to.reg() == spilledReg_) { // If the destination is the spilled register, make sure we // don't re-clobber its value. spilledReg_ = InvalidReg; } if (from.isGeneralReg()) { if (from.reg() == spilledReg_) { // If the source is a register that has been spilled, make sure // to load the source back into that register. masm.ma_ldr(spillSlot(), spilledReg_); spilledReg_ = InvalidReg; } switch (toOperand(to, false).getTag()) { case Operand::OP2: // secretly must be a register masm.ma_mov(from.reg(), to.reg()); break; case Operand::MEM: masm.ma_str(from.reg(), toOperand(to, false)); break; default: MOZ_ASSUME_UNREACHABLE("strange move!"); } } else if (to.isGeneralReg()) { JS_ASSERT(from.isMemory() || from.isEffectiveAddress()); if (from.isMemory()) masm.ma_ldr(toOperand(from, false), to.reg()); else masm.ma_add(from.base(), Imm32(from.disp()), to.reg()); } else { // Memory to memory gpr move. Register reg = tempReg(); JS_ASSERT(from.isMemory() || from.isEffectiveAddress()); if (from.isMemory()) masm.ma_ldr(toOperand(from, false), reg); else masm.ma_add(from.base(), Imm32(from.disp()), reg); JS_ASSERT(to.base() != reg); masm.ma_str(reg, toOperand(to, false)); } }
// Warning, do not use the resulting operand with pop instructions, since they // compute the effective destination address after altering the stack pointer. // Use toPopOperand if an Operand is needed for a pop. Operand MoveEmitterX86::toOperand(const MoveOperand &operand) const { if (operand.isMemory() || operand.isEffectiveAddress() || operand.isFloatAddress()) { if (operand.base() != StackPointer) return Operand(operand.base(), operand.disp()); JS_ASSERT(operand.disp() >= 0); // Otherwise, the stack offset may need to be adjusted. return Operand(StackPointer, operand.disp() + (masm.framePushed() - pushedAtStart_)); } if (operand.isGeneralReg()) return Operand(operand.reg()); JS_ASSERT(operand.isFloatReg()); return Operand(operand.floatReg()); }
int32_t MoveEmitterMIPS::getAdjustedOffset(const MoveOperand &operand) { MOZ_ASSERT(operand.isMemoryOrEffectiveAddress()); if (operand.base() != StackPointer) return operand.disp(); // Adjust offset if stack pointer has been moved. return operand.disp() + masm.framePushed() - pushedAtStart_; }
void MoveEmitterARM::emitMove(const MoveOperand& from, const MoveOperand& to) { // Register pairs are used to store Double values during calls. MOZ_ASSERT(!from.isGeneralRegPair()); MOZ_ASSERT(!to.isGeneralRegPair()); if (to.isGeneralReg() && to.reg() == spilledReg_) { // If the destination is the spilled register, make sure we // don't re-clobber its value. spilledReg_ = InvalidReg; } if (from.isGeneralReg()) { if (from.reg() == spilledReg_) { // If the source is a register that has been spilled, make sure // to load the source back into that register. masm.ma_ldr(spillSlot(), spilledReg_); spilledReg_ = InvalidReg; } if (to.isMemoryOrEffectiveAddress()) masm.ma_str(from.reg(), toAddress(to)); else masm.ma_mov(from.reg(), to.reg()); } else if (to.isGeneralReg()) { MOZ_ASSERT(from.isMemoryOrEffectiveAddress()); if (from.isMemory()) masm.ma_ldr(toAddress(from), to.reg()); else masm.ma_add(from.base(), Imm32(from.disp()), to.reg()); } else { // Memory to memory gpr move. Register reg = tempReg(); MOZ_ASSERT(from.isMemoryOrEffectiveAddress()); if (from.isMemory()) masm.ma_ldr(toAddress(from), reg); else masm.ma_add(from.base(), Imm32(from.disp()), reg); MOZ_ASSERT(to.base() != reg); masm.ma_str(reg, toAddress(to)); } }
// This is the same as toOperand except that it computes an Operand suitable for // use in a pop. Operand MoveEmitterX86::toPopOperand(const MoveOperand& operand) const { if (operand.isMemory()) { if (operand.base() != StackPointer) return Operand(operand.base(), operand.disp()); MOZ_ASSERT(operand.disp() >= 0); // Otherwise, the stack offset may need to be adjusted. // Note the adjustment by the stack slot here, to offset for the fact that pop // computes its effective address after incrementing the stack pointer. return Operand(StackPointer, operand.disp() + (masm.framePushed() - sizeof(void*) - pushedAtStart_)); } if (operand.isGeneralReg()) return Operand(operand.reg()); MOZ_ASSERT(operand.isFloatReg()); return Operand(operand.floatReg()); }
void MoveEmitterMIPS::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()) { // Used for passing double parameter in a2,a3 register pair. // Two moves are added for one double parameter by // MacroAssemblerMIPSCompat::passABIArg if(to.reg() == a2) masm.moveFromDoubleLo(from.floatReg(), a2); else if(to.reg() == a3) masm.moveFromDoubleHi(from.floatReg(), a3); else MOZ_CRASH("Invalid emitDoubleMove arguments."); } 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.isGeneralReg()) { // Used for passing double parameter in a2,a3 register pair. // Two moves are added for one double parameter by // MacroAssemblerMIPSCompat::passABIArg if (from.isMemory()) { if(to.reg() == a2) masm.loadPtr(getAdjustedAddress(from), a2); else if(to.reg() == a3) masm.loadPtr(Address(from.base(), getAdjustedOffset(from) + sizeof(uint32_t)), a3); else MOZ_CRASH("Invalid emitDoubleMove arguments."); } else { // Used for moving a double parameter from the same source. See Bug 1123874. if(to.reg() == a2 || to.reg() == a3) masm.ma_move(to.reg(), from.reg()); else MOZ_CRASH("Invalid emitDoubleMove arguments."); } } else { MOZ_ASSERT(from.isMemory()); MOZ_ASSERT(to.isMemory()); masm.loadDouble(getAdjustedAddress(from), ScratchDoubleReg); masm.storeDouble(ScratchDoubleReg, getAdjustedAddress(to)); } }
void MoveEmitterMIPS::emitMove(const MoveOperand &from, const MoveOperand &to) { if (to.isGeneralReg() && to.reg() == spilledReg_) { // If the destination is the spilled register, make sure we // don't re-clobber its value. spilledReg_ = InvalidReg; } if (from.isGeneralReg()) { if (from.reg() == spilledReg_) { // If the source is a register that has been spilled, make sure // to load the source back into that register. masm.mov(spillSlot(), spilledReg_); spilledReg_ = InvalidReg; } masm.mov(from.reg(), toOperand(to)); } else if (to.isGeneralReg()) { JS_ASSERT(from.isMemory() || from.isEffectiveAddress()); if (from.isMemory()) masm.mov(toOperand(from), to.reg()); else masm.lea(toOperand(from), to.reg()); } else { // Memory to memory gpr move. Register reg = tempReg(); // Reload its previous value from the stack. if (reg == from.base()) masm.mov(spillSlot(), from.base()); JS_ASSERT(from.isMemory() || from.isEffectiveAddress()); if (from.isMemory()) masm.mov(toOperand(from), reg); else masm.lea(toOperand(from), reg); JS_ASSERT(to.base() != reg); masm.mov(reg, toOperand(to)); } }
void MoveEmitterMIPS::emitDoubleMove(const MoveOperand &from, const MoveOperand &to) { // Ensure that we can use ScratchFloatReg in memory move. MOZ_ASSERT_IF(from.isFloatReg(), from.floatReg() != ScratchFloatReg); MOZ_ASSERT_IF(to.isFloatReg(), to.floatReg() != ScratchFloatReg); if (from.isFloatReg()) { if (to.isFloatReg()) { masm.moveDouble(from.floatReg(), to.floatReg()); } else if (to.isGeneralReg()) { // Used for passing double parameter in a2,a3 register pair. // Two moves are added for one double parameter by // MacroAssemblerMIPSCompat::passABIArg if(to.reg() == a2) masm.as_mfc1(a2, from.floatReg()); else if(to.reg() == a3) masm.as_mfc1_Odd(a3, from.floatReg()); else MOZ_ASSUME_UNREACHABLE("Invalid emitDoubleMove arguments."); } 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.isGeneralReg()) { MOZ_ASSERT(from.isMemory()); // Used for passing double parameter in a2,a3 register pair. // Two moves are added for one double parameter by // MacroAssemblerMIPSCompat::passABIArg if(to.reg() == a2) masm.loadPtr(getAdjustedAddress(from), a2); else if(to.reg() == a3) masm.loadPtr(Address(from.base(), getAdjustedOffset(from) + sizeof(uint32_t)), a3); else MOZ_ASSUME_UNREACHABLE("Invalid emitDoubleMove arguments."); } else { MOZ_ASSERT(from.isMemory()); MOZ_ASSERT(to.isMemory()); masm.loadDouble(getAdjustedAddress(from), ScratchFloatReg); masm.storeDouble(ScratchFloatReg, getAdjustedAddress(to)); } }
void MoveEmitterX86::emitGeneralMove(const MoveOperand& from, const MoveOperand& to) { if (from.isGeneralReg()) { masm.mov(from.reg(), toOperand(to)); } else if (to.isGeneralReg()) { MOZ_ASSERT(from.isMemoryOrEffectiveAddress()); if (from.isMemory()) masm.loadPtr(toAddress(from), to.reg()); else masm.lea(toOperand(from), to.reg()); } else if (from.isMemory()) { // Memory to memory gpr move. if (hasScratchRegister()) { Register reg = scratchRegister(); masm.loadPtr(toAddress(from), reg); masm.mov(reg, toOperand(to)); } else { // No scratch register available; bounce it off the stack. masm.Push(toOperand(from)); masm.Pop(toPopOperand(to)); } } else { // Effective address to memory move. MOZ_ASSERT(from.isEffectiveAddress()); if (hasScratchRegister()) { Register reg = scratchRegister(); masm.lea(toOperand(from), reg); masm.mov(reg, toOperand(to)); } else { // This is tricky without a scratch reg. We can't do an lea. Bounce the // base register off the stack, then add the offset in place. Note that // this clobbers FLAGS! masm.Push(from.base()); masm.Pop(toPopOperand(to)); masm.addPtr(Imm32(from.disp()), toOperand(to)); } } }
void MoveEmitterX86::emitGeneralMove(const MoveOperand &from, const MoveOperand &to) { if (from.isGeneralReg()) { masm.mov(from.reg(), toOperand(to)); } else if (to.isGeneralReg()) { JS_ASSERT(from.isMemoryOrEffectiveAddress()); if (from.isMemory()) masm.loadPtr(toAddress(from), to.reg()); else masm.lea(toOperand(from), to.reg()); } else if (from.isMemory()) { // Memory to memory gpr move. #ifdef JS_CODEGEN_X64 // x64 has a ScratchReg. Use it. masm.loadPtr(toAddress(from), ScratchReg); masm.mov(ScratchReg, toOperand(to)); #else // No ScratchReg; bounce it off the stack. masm.Push(toOperand(from)); masm.Pop(toPopOperand(to)); #endif } else { // Effective address to memory move. JS_ASSERT(from.isEffectiveAddress()); #ifdef JS_CODEGEN_X64 // x64 has a ScratchReg. Use it. masm.lea(toOperand(from), ScratchReg); masm.mov(ScratchReg, toOperand(to)); #else // This is tricky without a ScratchReg. We can't do an lea. Bounce the // base register off the stack, then add the offset in place. Note that // this clobbers FLAGS! masm.Push(from.base()); masm.Pop(toPopOperand(to)); masm.addPtr(Imm32(from.disp()), toOperand(to)); #endif } }
Address MoveEmitterMIPS::getAdjustedAddress(const MoveOperand &operand) { return Address(operand.base(), getAdjustedOffset(operand)); }