void MacroAssembler::PushRegsInMask(RegisterSet set, FloatRegisterSet simdSet) { FloatRegisterSet doubleSet(FloatRegisterSet::Subtract(set.fpus(), simdSet)); MOZ_ASSERT_IF(simdSet.empty(), doubleSet == set.fpus()); unsigned numSimd = simdSet.size(); unsigned numDouble = doubleSet.size(); int32_t diffF = numDouble * sizeof(double) + numSimd * Simd128DataSize; 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(doubleSet); iter.more(); iter++) { diffF -= sizeof(double); numDouble -= 1; storeDouble(*iter, Address(StackPointer, diffF)); } MOZ_ASSERT(numDouble == 0); for (FloatRegisterBackwardIterator iter(simdSet); iter.more(); iter++) { diffF -= Simd128DataSize; numSimd -= 1; // XXX how to choose the right move type? storeUnalignedInt32x4(*iter, Address(StackPointer, diffF)); } MOZ_ASSERT(numSimd == 0); MOZ_ASSERT(diffF == 0); }
uint32_t VFPRegister::GetPushSizeInBytes(const FloatRegisterSet& s) { FloatRegisterSet ss = s.reduceSetForPush(); uint64_t bits = ss.bits(); uint32_t ret = mozilla::CountPopulation32(bits&0xffffffff) * sizeof(float); ret += mozilla::CountPopulation32(bits >> 32) * sizeof(double); return ret; }
uint32_t FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s) { FloatRegisterSet ss = s.reduceSetForPush(); uint64_t bits = ss.bits(); // We are only pushing double registers. MOZ_ASSERT((bits & 0xffffffff) == 0); uint32_t ret = mozilla::CountPopulation32(bits >> 32) * sizeof(double); return ret; }
void MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore, FloatRegisterSet simdSet) { FloatRegisterSet doubleSet(FloatRegisterSet::Subtract(set.fpus(), simdSet)); MOZ_ASSERT_IF(simdSet.empty(), doubleSet == set.fpus()); unsigned numSimd = simdSet.size(); unsigned numDouble = doubleSet.size(); int32_t diffG = set.gprs().size() * sizeof(intptr_t); int32_t diffF = numDouble * sizeof(double) + numSimd * Simd128DataSize; const int32_t reservedG = diffG; const int32_t reservedF = diffF; for (FloatRegisterBackwardIterator iter(simdSet); iter.more(); iter++) { diffF -= Simd128DataSize; numSimd -= 1; if (!ignore.has(*iter)) // XXX how to choose the right move type? loadUnalignedInt32x4(Address(StackPointer, diffF), *iter); } MOZ_ASSERT(numSimd == 0); for (FloatRegisterBackwardIterator iter(doubleSet); iter.more(); iter++) { diffF -= sizeof(double); numDouble -= 1; if (!ignore.has(*iter)) loadDouble(Address(StackPointer, diffF), *iter); } freeStack(reservedF); MOZ_ASSERT(numDouble == 0); 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.empty(false)) { 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); }
FloatRegisterSet VFPRegister::ReduceSetForPush(const FloatRegisterSet &s) { FloatRegisterSet mod; for (TypedRegisterIterator<FloatRegister> iter(s); iter.more(); iter++) { if ((*iter).isSingle()) { // Add in just this float. mod.addUnchecked(*iter); } else if ((*iter).id() < 16) { // A double with an overlay, add in both floats. mod.addUnchecked((*iter).singleOverlay(0)); mod.addUnchecked((*iter).singleOverlay(1)); } else { // Add in the lone double in the range 16-31. mod.addUnchecked(*iter); } } return mod; }
uint32_t FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s) { return s.size() * sizeof(double); }
uint32_t FloatRegister::GetSizeInBytes(const FloatRegisterSet& s) { uint32_t ret = s.size() * sizeof(double); return ret; }