void MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) { FloatRegisterSet fpuSet(set.fpus().reduceSetForPush()); unsigned numFpu = fpuSet.size(); int32_t diffG = set.gprs().size() * sizeof(intptr_t); int32_t diffF = fpuSet.getPushSizeInBytes(); const int32_t reservedG = diffG; const int32_t reservedF = diffF; for (FloatRegisterBackwardIterator iter(fpuSet); iter.more(); iter++) { FloatRegister reg = *iter; diffF -= reg.size(); numFpu -= 1; if (ignore.has(reg)) continue; Address spillAddress(StackPointer, diffF); if (reg.isDouble()) loadDouble(spillAddress, reg); else if (reg.isSingle()) loadFloat32(spillAddress, reg); else if (reg.isInt32x4()) loadUnalignedInt32x4(spillAddress, reg); else if (reg.isFloat32x4()) loadUnalignedFloat32x4(spillAddress, reg); else MOZ_CRASH("Unknown register type."); } freeStack(reservedF); MOZ_ASSERT(numFpu == 0); // x64 padding to keep the stack aligned on uintptr_t. Keep in sync with // GetPushBytesInSize. diffF -= diffF % sizeof(uintptr_t); MOZ_ASSERT(diffF == 0); // On x86, use pop to pop the integer registers, if we're not going to // ignore any slots, as it's fast on modern hardware and it's a small // instruction. if (ignore.emptyGeneral()) { for (GeneralRegisterForwardIterator iter(set.gprs()); iter.more(); iter++) { diffG -= sizeof(intptr_t); Pop(*iter); } } else { for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) { diffG -= sizeof(intptr_t); if (!ignore.has(*iter)) loadPtr(Address(StackPointer, diffG), *iter); } freeStack(reservedG); } MOZ_ASSERT(diffG == 0); }
void MacroAssembler::PushRegsInMask(LiveRegisterSet set) { FloatRegisterSet fpuSet(set.fpus().reduceSetForPush()); unsigned numFpu = fpuSet.size(); int32_t diffF = fpuSet.getPushSizeInBytes(); int32_t diffG = set.gprs().size() * sizeof(intptr_t); // On x86, always use push to push the integer registers, as it's fast // on modern hardware and it's a small instruction. for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) { diffG -= sizeof(intptr_t); Push(*iter); } MOZ_ASSERT(diffG == 0); reserveStack(diffF); for (FloatRegisterBackwardIterator iter(fpuSet); iter.more(); iter++) { FloatRegister reg = *iter; diffF -= reg.size(); numFpu -= 1; Address spillAddress(StackPointer, diffF); if (reg.isDouble()) storeDouble(reg, spillAddress); else if (reg.isSingle()) storeFloat32(reg, spillAddress); else if (reg.isInt32x4()) storeUnalignedInt32x4(reg, spillAddress); else if (reg.isFloat32x4()) storeUnalignedFloat32x4(reg, spillAddress); else MOZ_CRASH("Unknown register type."); } MOZ_ASSERT(numFpu == 0); // x64 padding to keep the stack aligned on uintptr_t. Keep in sync with // GetPushBytesInSize. diffF -= diffF % sizeof(uintptr_t); MOZ_ASSERT(diffF == 0); }
void MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register) { FloatRegisterSet fpuSet(set.fpus().reduceSetForPush()); unsigned numFpu = fpuSet.size(); int32_t diffF = fpuSet.getPushSizeInBytes(); int32_t diffG = set.gprs().size() * sizeof(intptr_t); MOZ_ASSERT(dest.offset >= diffG + diffF); for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) { diffG -= sizeof(intptr_t); dest.offset -= sizeof(intptr_t); storePtr(*iter, dest); } MOZ_ASSERT(diffG == 0); for (FloatRegisterBackwardIterator iter(fpuSet); iter.more(); ++iter) { FloatRegister reg = *iter; diffF -= reg.size(); numFpu -= 1; dest.offset -= reg.size(); if (reg.isDouble()) storeDouble(reg, dest); else if (reg.isSingle()) storeFloat32(reg, dest); else if (reg.isSimd128()) storeUnalignedSimd128Float(reg, dest); else MOZ_CRASH("Unknown register type."); } MOZ_ASSERT(numFpu == 0); // x64 padding to keep the stack aligned on uintptr_t. Keep in sync with // GetPushBytesInSize. diffF -= diffF % sizeof(uintptr_t); MOZ_ASSERT(diffF == 0); }
} template <class VectorT> static unsigned StackDecrementForCall(MacroAssembler& masm, uint32_t alignment, const VectorT& args, unsigned extraBytes = 0) { return StackDecrementForCall(masm, alignment, StackArgBytes(args) + extraBytes); } #if defined(JS_CODEGEN_ARM) // The ARM system ABI also includes d15 & s31 in the non volatile float registers. // Also exclude lr (a.k.a. r14) as we preserve it manually) static const LiveRegisterSet NonVolatileRegs = LiveRegisterSet(GeneralRegisterSet(Registers::NonVolatileMask& ~(uint32_t(1) << Registers::lr)), FloatRegisterSet(FloatRegisters::NonVolatileMask | (1ULL << FloatRegisters::d15) | (1ULL << FloatRegisters::s31))); #else static const LiveRegisterSet NonVolatileRegs = LiveRegisterSet(GeneralRegisterSet(Registers::NonVolatileMask), FloatRegisterSet(FloatRegisters::NonVolatileMask)); #endif #if defined(JS_CODEGEN_MIPS32) // Mips is using one more double slot due to stack alignment for double values. // Look at MacroAssembler::PushRegsInMask(RegisterSet set) static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t) + NonVolatileRegs.fpus().getPushSizeInBytes() + sizeof(double); #elif defined(JS_CODEGEN_NONE)