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); }