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);
}
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);
}
Example #3
0
uint32_t
FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s)
{
    return s.size() * sizeof(double);
}
Example #4
0
uint32_t
FloatRegister::GetSizeInBytes(const FloatRegisterSet& s)
{
    uint32_t ret = s.size() * sizeof(double);
    return ret;
}