Exemplo n.º 1
0
void
CodeGeneratorX64::emitSimdLoad(LAsmJSLoadHeap *ins)
{
    MAsmJSLoadHeap *mir = ins->mir();
    Scalar::Type type = mir->accessType();
    const LAllocation *ptr = ins->ptr();
    FloatRegister out = ToFloatRegister(ins->output());
    Operand srcAddr(HeapReg);

    if (ptr->isConstant()) {
        int32_t ptrImm = ptr->toConstant()->toInt32();
        MOZ_ASSERT(ptrImm >= 0);
        srcAddr = Operand(HeapReg, ptrImm);
    } else {
        srcAddr = Operand(HeapReg, ToRegister(ptr), TimesOne);
    }

    uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck;
    if (mir->needsBoundsCheck()) {
        maybeCmpOffset = masm.cmp32WithPatch(ToRegister(ptr), Imm32(0)).offset();
        masm.j(Assembler::AboveOrEqual, mir->outOfBoundsLabel()); // Throws RangeError
    }

    unsigned numElems = mir->numSimdElems();
    if (numElems == 3) {
        MOZ_ASSERT(type == Scalar::Int32x4 || type == Scalar::Float32x4);

        Operand shiftedOffset(HeapReg);
        if (ptr->isConstant())
            shiftedOffset = Operand(HeapReg, ptr->toConstant()->toInt32() + 2 * sizeof(float));
        else
            shiftedOffset = Operand(HeapReg, ToRegister(ptr), TimesOne, 2 * sizeof(float));

        // Load XY
        uint32_t before = masm.size();
        loadSimd(type, 2, srcAddr, out);
        uint32_t after = masm.size();
        // We're noting a load of 3 elements, so that the bounds check checks
        // for 3 elements.
        masm.append(AsmJSHeapAccess(before, after, 3, type, maybeCmpOffset));

        // Load Z (W is zeroed)
        before = after;
        loadSimd(type, 1, shiftedOffset, ScratchSimdReg);
        after = masm.size();
        masm.append(AsmJSHeapAccess(before, after, 1, type));

        // Move ZW atop XY
        masm.vmovlhps(ScratchSimdReg, out, out);
        return;
    }

    uint32_t before = masm.size();
    loadSimd(type, numElems, srcAddr, out);
    uint32_t after = masm.size();
    masm.append(AsmJSHeapAccess(before, after, numElems, type, maybeCmpOffset));
}