public static void Bic_V(ILEmitterCtx context) { if (Optimizations.UseSse2) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; Type[] typesAnt = new Type[] { typeof(Vector128 <byte>), typeof(Vector128 <byte>) }; context.EmitLdvec(op.Rm); context.EmitLdvec(op.Rn); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } else { EmitVectorBinaryOpZx(context, () => { context.Emit(OpCodes.Not); context.Emit(OpCodes.And); }); } }
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 EmitVectorWidenOpByElem(ILEmitterCtx context, Action emit, int elem, bool ternary, bool signed) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; int elems = 8 >> op.Size; int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; 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 + 1, signed); } EmitVectorExtract(context, op.Rn, part + index, op.Size, signed); context.EmitLdtmp(); emit(); EmitVectorInsertTmp(context, index, op.Size + 1); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); }
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 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); } }
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 Cmhs_V(ILEmitterCtx context) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; if (Optimizations.UseSse41 && op.Size < 3) { Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] }; Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax)); context.EmitLdvec(op.Rn); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqual), typesCmp)); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } else { EmitCmpOp(context, OpCodes.Bge_Un_S, scalar: false); } }
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); } }
public static void Orn_V(ILEmitterCtx context) { if (Optimizations.UseSse2) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; Type[] typesSav = new Type[] { typeof(long) }; Type[] typesAntOr = new Type[] { typeof(Vector128 <long>), typeof(Vector128 <long>) }; context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); context.EmitLdc_I8(-1L); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAntOr)); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAntOr)); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } else { EmitVectorBinaryOpZx(context, () => { context.Emit(OpCodes.Not); context.Emit(OpCodes.Or); }); } }
private static void EmitBifBit(ILEmitterCtx context, bool notRm) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; if (Optimizations.UseSse2) { Type[] typesXorAndNot = new Type[] { typeof(Vector128 <byte>), typeof(Vector128 <byte>) }; string nameAndNot = notRm ? nameof(Sse2.AndNot) : nameof(Sse2.And); context.EmitLdvec(op.Rd); context.EmitLdvec(op.Rm); context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rd); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXorAndNot)); context.EmitCall(typeof(Sse2).GetMethod(nameAndNot, typesXorAndNot)); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXorAndNot)); context.EmitStvec(op.Rd); if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } else { int elems = op.RegisterSize == RegisterSize.Simd128 ? 2 : 1; for (int index = 0; index < elems; index++) { EmitVectorExtractZx(context, op.Rd, index, 3); context.Emit(OpCodes.Dup); EmitVectorExtractZx(context, op.Rn, index, 3); context.Emit(OpCodes.Xor); EmitVectorExtractZx(context, op.Rm, index, 3); if (notRm) { context.Emit(OpCodes.Not); } context.Emit(OpCodes.And); context.Emit(OpCodes.Xor); EmitVectorInsert(context, op.Rd, index, 3); } 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); } } }
public static void Sha1su0_V(ILEmitterCtx context) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; context.EmitLdvec(op.Rd); context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); SoftFallback.EmitCall(context, nameof(SoftFallback.Sha1SchedulePart1)); context.EmitStvec(op.Rd); }
public static void Sha256h_V(ILEmitterCtx context) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; context.EmitLdvec(op.Rd); context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); SoftFallback.EmitCall(context, nameof(SoftFallback.HashLower)); context.EmitStvec(op.Rd); }
public static void Sha1p_V(ILEmitterCtx context) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; context.EmitLdvec(op.Rd); EmitVectorExtractZx(context, op.Rn, 0, 2); context.EmitLdvec(op.Rm); SoftFallback.EmitCall(context, nameof(SoftFallback.HashParity)); context.EmitStvec(op.Rd); }
public static void Bsl_V(ILEmitterCtx context) { if (Optimizations.UseSse2) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; Type[] types = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; EmitLdvecWithUnsignedCast(context, op.Rn, op.Size); EmitLdvecWithUnsignedCast(context, op.Rm, op.Size); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), types)); EmitLdvecWithUnsignedCast(context, op.Rd, op.Size); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), types)); EmitLdvecWithUnsignedCast(context, op.Rm, 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 { EmitVectorTernaryOpZx(context, () => { context.EmitSttmp(); context.EmitLdtmp(); context.Emit(OpCodes.Xor); context.Emit(OpCodes.And); context.EmitLdtmp(); context.Emit(OpCodes.Xor); }); } }
public static void EmitScalarOpByElemF(ILEmitterCtx context, Action emit, int elem, bool ternary) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; int sizeF = op.Size & 1; if (ternary) { EmitVectorExtractF(context, op.Rd, 0, sizeF); } EmitVectorExtractF(context, op.Rn, 0, sizeF); EmitVectorExtractF(context, op.Rm, elem, sizeF); emit(); EmitScalarSetF(context, op.Rd, sizeF); }
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); } }
public static void EmitVectorPairwiseSseOrSse2OpF(ILEmitterCtx context, string name) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; int sizeF = op.Size & 1; if (sizeF == 0) { if (op.RegisterSize == RegisterSize.Simd64) { Type[] types = new Type[] { typeof(Vector128 <float>), typeof(Vector128 <float>) }; context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.UnpackLow), types)); context.EmitStvectmp(); context.EmitLdvectmp(); VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh), types)); VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); context.EmitLdvectmp(); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveHighToLow), types)); context.EmitCall(typeof(Sse).GetMethod(name, types)); context.EmitStvec(op.Rd); } else /* if (op.RegisterSize == RegisterSize.Simd128) */ { Type[] typesSfl = new Type[] { typeof(Vector128 <float>), typeof(Vector128 <float>), typeof(byte) }; Type[] types = new Type[] { typeof(Vector128 <float>), typeof(Vector128 <float>) }; context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); context.EmitLdc_I4(2 << 6 | 0 << 4 | 2 << 2 | 0 << 0); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); context.EmitLdc_I4(3 << 6 | 1 << 4 | 3 << 2 | 1 << 0); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); context.EmitCall(typeof(Sse).GetMethod(name, types)); context.EmitStvec(op.Rd); } } else /* if (sizeF == 1) */ { Type[] types = new Type[] { typeof(Vector128 <double>), typeof(Vector128 <double>) }; context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), types)); context.EmitLdvec(op.Rn); context.EmitLdvec(op.Rm); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackHigh), types)); context.EmitCall(typeof(Sse2).GetMethod(name, types)); context.EmitStvec(op.Rd); } }
private static void EmitFcmpOrFcmpe(ILEmitterCtx context, bool signalNaNs) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; bool cmpWithZero = !(op is OpCodeSimdFcond64) ? op.Bit3 : false; if (Optimizations.FastFP && Optimizations.UseSse2) { if (op.Size == 0) { Type[] typesCmp = new Type[] { typeof(Vector128 <float>), typeof(Vector128 <float>) }; ILLabel lblNaN = new ILLabel(); ILLabel lblEnd = new ILLabel(); context.EmitLdvec(op.Rn); context.Emit(OpCodes.Dup); context.EmitStvectmp(); if (cmpWithZero) { VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); } else { context.EmitLdvec(op.Rm); } context.Emit(OpCodes.Dup); context.EmitStvectmp2(); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareOrderedScalar), typesCmp)); VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareEqualOrderedScalar), typesCmp)); context.Emit(OpCodes.Brtrue_S, lblNaN); context.EmitLdc_I4(0); context.EmitLdvectmp(); context.EmitLdvectmp2(); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualOrderedScalar), typesCmp)); context.EmitLdvectmp(); context.EmitLdvectmp2(); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareEqualOrderedScalar), typesCmp)); context.EmitLdvectmp(); context.EmitLdvectmp2(); context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrderedScalar), typesCmp)); context.EmitStflg((int)PState.NBit); context.EmitStflg((int)PState.ZBit); context.EmitStflg((int)PState.CBit); context.EmitStflg((int)PState.VBit); context.Emit(OpCodes.Br_S, lblEnd); context.MarkLabel(lblNaN); context.EmitLdc_I4(1); context.Emit(OpCodes.Dup); context.EmitLdc_I4(0); context.Emit(OpCodes.Dup); context.EmitStflg((int)PState.NBit); context.EmitStflg((int)PState.ZBit); context.EmitStflg((int)PState.CBit); context.EmitStflg((int)PState.VBit); context.MarkLabel(lblEnd); } else /* if (op.Size == 1) */ { Type[] typesCmp = new Type[] { typeof(Vector128 <double>), typeof(Vector128 <double>) }; ILLabel lblNaN = new ILLabel(); ILLabel lblEnd = new ILLabel(); context.EmitLdvec(op.Rn); context.Emit(OpCodes.Dup); context.EmitStvectmp(); if (cmpWithZero) { VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleZero)); } else { context.EmitLdvec(op.Rm); } context.Emit(OpCodes.Dup); context.EmitStvectmp2(); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareOrderedScalar), typesCmp)); VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleZero)); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualOrderedScalar), typesCmp)); context.Emit(OpCodes.Brtrue_S, lblNaN); context.EmitLdc_I4(0); context.EmitLdvectmp(); context.EmitLdvectmp2(); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualOrderedScalar), typesCmp)); context.EmitLdvectmp(); context.EmitLdvectmp2(); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualOrderedScalar), typesCmp)); context.EmitLdvectmp(); context.EmitLdvectmp2(); context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrderedScalar), typesCmp)); context.EmitStflg((int)PState.NBit); context.EmitStflg((int)PState.ZBit); context.EmitStflg((int)PState.CBit); context.EmitStflg((int)PState.VBit); context.Emit(OpCodes.Br_S, lblEnd); context.MarkLabel(lblNaN); context.EmitLdc_I4(1); context.Emit(OpCodes.Dup); context.EmitLdc_I4(0); context.Emit(OpCodes.Dup); context.EmitStflg((int)PState.NBit); context.EmitStflg((int)PState.ZBit); context.EmitStflg((int)PState.CBit); context.EmitStflg((int)PState.VBit); context.MarkLabel(lblEnd); } } else { EmitVectorExtractF(context, op.Rn, 0, op.Size); if (cmpWithZero) { if (op.Size == 0) { context.EmitLdc_R4(0f); } else /* if (op.Size == 1) */ { context.EmitLdc_R8(0d); } } else { EmitVectorExtractF(context, op.Rm, 0, op.Size); } context.EmitLdc_I4(!signalNaNs ? 0 : 1); EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare)); EmitSetNzcv(context); } }
public static void Fcmp_S(ILEmitterCtx context) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; bool cmpWithZero = !(op is OpCodeSimdFcond64) ? op.Bit3 : false; //Handle NaN case. //If any number is NaN, then NZCV = 0011. if (cmpWithZero) { EmitNaNCheck(context, op.Rn); } else { EmitNaNCheck(context, op.Rn); EmitNaNCheck(context, op.Rm); context.Emit(OpCodes.Or); } ILLabel lblNaN = new ILLabel(); ILLabel lblEnd = new ILLabel(); context.Emit(OpCodes.Brtrue_S, lblNaN); void EmitLoadOpers() { EmitVectorExtractF(context, op.Rn, 0, op.Size); if (cmpWithZero) { if (op.Size == 0) { context.EmitLdc_R4(0f); } else /* if (Op.Size == 1) */ { context.EmitLdc_R8(0d); } } else { EmitVectorExtractF(context, op.Rm, 0, op.Size); } } //Z = Rn == Rm EmitLoadOpers(); context.Emit(OpCodes.Ceq); context.Emit(OpCodes.Dup); context.EmitStflg((int)PState.ZBit); //C = Rn >= Rm EmitLoadOpers(); context.Emit(OpCodes.Cgt); context.Emit(OpCodes.Or); context.EmitStflg((int)PState.CBit); //N = Rn < Rm EmitLoadOpers(); context.Emit(OpCodes.Clt); context.EmitStflg((int)PState.NBit); //V = 0 context.EmitLdc_I4(0); context.EmitStflg((int)PState.VBit); context.Emit(OpCodes.Br_S, lblEnd); context.MarkLabel(lblNaN); EmitSetNzcv(context, 0b0011); context.MarkLabel(lblEnd); }
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 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); } } }
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); } } }