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