public static void EmitVectorPairwiseOpF(ILEmitterCtx context, Action emit) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; int sizeF = op.Size & 1; int words = op.GetBitsCount() >> 4; int pairs = words >> sizeF + 2; for (int index = 0; index < pairs; index++) { int idx = index << 1; EmitVectorExtractF(context, op.Rn, idx, sizeF); EmitVectorExtractF(context, op.Rn, idx + 1, sizeF); emit(); EmitVectorExtractF(context, op.Rm, idx, sizeF); EmitVectorExtractF(context, op.Rm, idx + 1, sizeF); emit(); EmitVectorInsertTmpF(context, pairs + index, sizeF); EmitVectorInsertTmpF(context, index, sizeF); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }
public static void EmitVectorOpByElemF(ILEmitterCtx context, Action emit, int elem, bool ternary) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; int sizeF = op.Size & 1; int bytes = op.GetBitsCount() >> 3; int elems = bytes >> sizeF + 2; for (int index = 0; index < elems; index++) { if (ternary) { EmitVectorExtractF(context, op.Rd, index, sizeF); } EmitVectorExtractF(context, op.Rn, index, sizeF); EmitVectorExtractF(context, op.Rm, elem, sizeF); emit(); EmitVectorInsertTmpF(context, index, sizeF); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }
public static void EmitVectorOpByElem(ILEmitterCtx context, Action emit, int elem, bool ternary, bool signed) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; int bytes = op.GetBitsCount() >> 3; int elems = bytes >> op.Size; EmitVectorExtract(context, op.Rm, elem, op.Size, signed); context.EmitSttmp(); for (int index = 0; index < elems; index++) { if (ternary) { EmitVectorExtract(context, op.Rd, index, op.Size, signed); } EmitVectorExtract(context, op.Rn, index, op.Size, signed); context.EmitLdtmp(); emit(); EmitVectorInsert(context, op.Rd, index, op.Size); } if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }
public static void Ushl_V(ILEmitterCtx context) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; int bytes = op.GetBitsCount() >> 3; int elems = bytes >> op.Size; for (int index = 0; index < elems; index++) { EmitVectorExtractZx(context, op.Rn, index, op.Size); EmitVectorExtractZx(context, op.Rm, index, op.Size); context.Emit(OpCodes.Ldc_I4_0); context.EmitLdc_I4(op.Size); SoftFallback.EmitCall(context, nameof(SoftFallback.UnsignedShlReg)); EmitVectorInsert(context, op.Rd, index, op.Size); } if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }
private static void EmitVectorUnzip(ILEmitterCtx context, int part) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; int words = op.GetBitsCount() >> 4; int pairs = words >> op.Size; for (int index = 0; index < pairs; index++) { int idx = index << 1; EmitVectorExtractZx(context, op.Rn, idx + part, op.Size); EmitVectorExtractZx(context, op.Rm, idx + part, op.Size); EmitVectorInsertTmp(context, pairs + index, op.Size); EmitVectorInsertTmp(context, index, op.Size); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }
private static void EmitVectorZip(ILEmitterCtx context, int part) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; if (Optimizations.UseSse2) { string nameUpk = part == 0 ? nameof(Sse2.UnpackLow) : nameof(Sse2.UnpackHigh); context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); if (op.RegisterSize == RegisterSize.Simd128) { context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(op.Size))); } else { context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), GetTypesSflUpk(op.Size))); VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(3))); } context.EmitStvec(op.Rd); } else { int words = op.GetBitsCount() >> 4; int pairs = words >> op.Size; int Base = part != 0 ? pairs : 0; for (int index = 0; index < pairs; index++) { int idx = index << 1; EmitVectorExtractZx(context, op.Rn, Base + index, op.Size); EmitVectorExtractZx(context, op.Rm, Base + index, op.Size); EmitVectorInsertTmp(context, idx + 1, op.Size); EmitVectorInsertTmp(context, idx, op.Size); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } }
private static void EmitCmtstOp(ILEmitterCtx context, bool scalar) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; int bytes = op.GetBitsCount() >> 3; int elems = !scalar ? bytes >> op.Size : 1; ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size)); for (int index = 0; index < elems; index++) { EmitVectorExtractZx(context, op.Rn, index, op.Size); EmitVectorExtractZx(context, op.Rm, index, op.Size); ILLabel lblTrue = new ILLabel(); ILLabel lblEnd = new ILLabel(); context.Emit(OpCodes.And); context.EmitLdc_I8(0L); context.Emit(OpCodes.Bne_Un_S, lblTrue); EmitVectorInsert(context, op.Rd, index, op.Size, 0); context.Emit(OpCodes.Br_S, lblEnd); context.MarkLabel(lblTrue); EmitVectorInsert(context, op.Rd, index, op.Size, (long)szMask); context.MarkLabel(lblEnd); } if ((op.RegisterSize == RegisterSize.Simd64) || scalar) { EmitVectorZeroUpper(context, op.Rd); } }
private static void EmitVectorUnzip(ILEmitterCtx context, int part) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; if (Optimizations.UseSsse3) { Type[] typesSve = new Type[] { typeof(long), typeof(long) }; string nameUpk = part == 0 ? nameof(Sse2.UnpackLow) : nameof(Sse2.UnpackHigh); if (op.RegisterSize == RegisterSize.Simd128) { context.EmitLdvec(op.Rn); // value if (op.Size < 3) { context.EmitLdc_I8(_masksE1_TrnUzp [op.Size]); // maskE1 context.EmitLdc_I8(_masksE0_TrnUzpXtn[op.Size]); // maskE0 context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0))); } context.EmitLdvec(op.Rm); // value if (op.Size < 3) { context.EmitLdc_I8(_masksE1_TrnUzp [op.Size]); // maskE1 context.EmitLdc_I8(_masksE0_TrnUzpXtn[op.Size]); // maskE0 context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0))); } context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(3))); context.EmitStvec(op.Rd); } else { context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), GetTypesSflUpk(op.Size))); // value if (op.Size < 2) { context.EmitLdc_I8(_masksE1_Uzp[op.Size]); // maskE1 context.EmitLdc_I8(_masksE0_Uzp[op.Size]); // maskE0 context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve)); context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0))); } VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(3))); context.EmitStvec(op.Rd); } } else { int words = op.GetBitsCount() >> 4; int pairs = words >> op.Size; for (int index = 0; index < pairs; index++) { int idx = index << 1; EmitVectorExtractZx(context, op.Rn, idx + part, op.Size); EmitVectorExtractZx(context, op.Rm, idx + part, op.Size); EmitVectorInsertTmp(context, pairs + index, op.Size); EmitVectorInsertTmp(context, index, op.Size); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } }
private static void EmitBitBif(ILEmitterCtx context, bool notRm) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; if (Optimizations.UseSse2) { Type[] types = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; EmitLdvecWithUnsignedCast(context, op.Rm, op.Size); EmitLdvecWithUnsignedCast(context, op.Rd, op.Size); EmitLdvecWithUnsignedCast(context, op.Rn, op.Size); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), types)); string name = notRm ? nameof(Sse2.AndNot) : nameof(Sse2.And); context.EmitCall(typeof(Sse2).GetMethod(name, types)); EmitLdvecWithUnsignedCast(context, op.Rd, op.Size); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), types)); EmitStvecWithUnsignedCast(context, op.Rd, op.Size); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } else { int bytes = op.GetBitsCount() >> 3; int elems = bytes >> op.Size; for (int index = 0; index < elems; index++) { EmitVectorExtractZx(context, op.Rd, index, op.Size); EmitVectorExtractZx(context, op.Rn, index, op.Size); context.Emit(OpCodes.Xor); EmitVectorExtractZx(context, op.Rm, index, op.Size); if (notRm) { context.Emit(OpCodes.Not); } context.Emit(OpCodes.And); EmitVectorExtractZx(context, op.Rd, index, op.Size); context.Emit(OpCodes.Xor); EmitVectorInsert(context, op.Rd, index, op.Size); } if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } }
private static void EmitVectorZip(ILEmitterCtx context, int part) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; if (Optimizations.UseSse2) { EmitLdvecWithUnsignedCast(context, op.Rn, op.Size); EmitLdvecWithUnsignedCast(context, op.Rm, op.Size); Type[] types = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; string name = part == 0 || (part != 0 && op.RegisterSize == RegisterSize.Simd64) ? nameof(Sse2.UnpackLow) : nameof(Sse2.UnpackHigh); context.EmitCall(typeof(Sse2).GetMethod(name, types)); if (op.RegisterSize == RegisterSize.Simd64 && part != 0) { context.EmitLdc_I4(8); Type[] shTypes = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), shTypes)); } EmitStvecWithUnsignedCast(context, op.Rd, op.Size); if (op.RegisterSize == RegisterSize.Simd64 && part == 0) { EmitVectorZeroUpper(context, op.Rd); } } else { int words = op.GetBitsCount() >> 4; int pairs = words >> op.Size; int Base = part != 0 ? pairs : 0; for (int index = 0; index < pairs; index++) { int idx = index << 1; EmitVectorExtractZx(context, op.Rn, Base + index, op.Size); EmitVectorExtractZx(context, op.Rm, Base + index, op.Size); EmitVectorInsertTmp(context, idx + 1, op.Size); EmitVectorInsertTmp(context, idx, op.Size); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } }