private static void EmitRev_V(ILEmitterCtx context, int containerSize) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; int bytes = op.GetBitsCount() >> 3; int elems = bytes >> op.Size; int containerMask = (1 << (containerSize - op.Size)) - 1; for (int index = 0; index < elems; index++) { int revIndex = index ^ containerMask; EmitVectorExtractZx(context, op.Rn, revIndex, 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 EmitVectorCvtf(ILEmitterCtx context, bool signed) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; int sizeF = op.Size & 1; int sizeI = sizeF + 2; int fBits = GetFBits(context); int bytes = op.GetBitsCount() >> 3; int elems = bytes >> sizeI; for (int index = 0; index < elems; index++) { EmitVectorExtract(context, op.Rn, index, sizeI, signed); if (!signed) { context.Emit(OpCodes.Conv_R_Un); } EmitFloatCast(context, sizeF); EmitI2fFBitsMul(context, sizeF, fBits); EmitVectorInsertF(context, op.Rd, index, sizeF); } if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }
private static void EmitCmpOpF(ILEmitterCtx context, string name, bool scalar) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; int sizeF = op.Size & 1; int bytes = op.GetBitsCount() >> 3; int elems = !scalar ? bytes >> sizeF + 2 : 1; for (int index = 0; index < elems; index++) { EmitVectorExtractF(context, op.Rn, index, sizeF); if (op is OpCodeSimdReg64 binOp) { EmitVectorExtractF(context, binOp.Rm, index, sizeF); } else { if (sizeF == 0) { context.EmitLdc_R4(0f); } else /* if (sizeF == 1) */ { context.EmitLdc_R8(0d); } } EmitSoftFloatCall(context, name); EmitVectorInsertF(context, op.Rd, index, sizeF); } if (!scalar) { if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } } else { if (sizeF == 0) { EmitVectorZero32_128(context, op.Rd); } else /* if (sizeF == 1) */ { EmitVectorZeroUpper(context, op.Rd); } } }
private static void EmitFcvtn(ILEmitterCtx context, bool signed, bool scalar) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; int sizeF = op.Size & 1; int sizeI = sizeF + 2; int bytes = op.GetBitsCount() >> 3; int elems = !scalar ? bytes >> sizeI : 1; if (scalar && (sizeF == 0)) { EmitVectorZeroLowerTmp(context); } for (int index = 0; index < elems; index++) { EmitVectorExtractF(context, op.Rn, index, sizeF); EmitRoundMathCall(context, MidpointRounding.ToEven); if (sizeF == 0) { VectorHelper.EmitCall(context, signed ? nameof(VectorHelper.SatF32ToS32) : nameof(VectorHelper.SatF32ToU32)); context.Emit(OpCodes.Conv_U8); } else /* if (sizeF == 1) */ { VectorHelper.EmitCall(context, signed ? nameof(VectorHelper.SatF64ToS64) : nameof(VectorHelper.SatF64ToU64)); } EmitVectorInsertTmp(context, index, sizeI); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); if ((op.RegisterSize == RegisterSize.Simd64) || scalar) { EmitVectorZeroUpper(context, op.Rd); } }
private static void EmitFcvtz(ILEmitterCtx context, bool signed, bool scalar) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; int sizeF = op.Size & 1; int sizeI = sizeF + 2; int fBits = GetFBits(context); int bytes = op.GetBitsCount() >> 3; int elems = !scalar ? bytes >> sizeI : 1; for (int index = 0; index < elems; index++) { EmitVectorExtractF(context, op.Rn, index, sizeF); EmitF2iFBitsMul(context, sizeF, fBits); if (sizeF == 0) { VectorHelper.EmitCall(context, signed ? nameof(VectorHelper.SatF32ToS32) : nameof(VectorHelper.SatF32ToU32)); context.Emit(OpCodes.Conv_U8); } else /* if (sizeF == 1) */ { VectorHelper.EmitCall(context, signed ? nameof(VectorHelper.SatF64ToS64) : nameof(VectorHelper.SatF64ToU64)); } if (scalar) { EmitVectorZeroAll(context, op.Rd); } EmitVectorInsert(context, op.Rd, index, sizeI); } if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }
public static void EmitVectorAcrossVectorOp(ILEmitterCtx context, Action emit, bool signed) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; int bytes = op.GetBitsCount() >> 3; int elems = bytes >> op.Size; EmitVectorExtract(context, op.Rn, 0, op.Size, signed); for (int index = 1; index < elems; index++) { EmitVectorExtract(context, op.Rn, index, op.Size, signed); emit(); } EmitScalarSet(context, op.Rd, op.Size); }
private static void EmitCmpOp(ILEmitterCtx context, OpCode ilOp, bool scalar) { OpCodeSimd64 op = (OpCodeSimd64)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++) { EmitVectorExtractSx(context, op.Rn, index, op.Size); if (op is OpCodeSimdReg64 binOp) { EmitVectorExtractSx(context, binOp.Rm, index, op.Size); } else { context.EmitLdc_I8(0L); } ILLabel lblTrue = new ILLabel(); ILLabel lblEnd = new ILLabel(); context.Emit(ilOp, 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 EmitVectorFcmp(ILEmitterCtx context, OpCode ilOp) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; int sizeF = op.Size & 1; int bytes = op.GetBitsCount() >> 3; int elems = bytes >> sizeF + 2; for (int index = 0; index < elems; index++) { EmitFcmp(context, ilOp, index, scalar: false); } if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }
public static void EmitVectorOpF(ILEmitterCtx context, Action emit, OperFlags opers) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; int sizeF = op.Size & 1; int bytes = op.GetBitsCount() >> 3; int elems = bytes >> sizeF + 2; bool rd = (opers & OperFlags.Rd) != 0; bool rn = (opers & OperFlags.Rn) != 0; bool rm = (opers & OperFlags.Rm) != 0; for (int index = 0; index < elems; index++) { if (rd) { EmitVectorExtractF(context, op.Rd, index, sizeF); } if (rn) { EmitVectorExtractF(context, op.Rn, index, sizeF); } if (rm) { EmitVectorExtractF(context, ((OpCodeSimdReg64)op).Rm, index, sizeF); } emit(); EmitVectorInsertF(context, op.Rd, index, sizeF); } if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }
public static void EmitSaturatingUnaryOpSx(ILEmitterCtx context, Action emit, SaturatingFlags flags) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; bool scalar = (flags & SaturatingFlags.Scalar) != 0; int bytes = op.GetBitsCount() >> 3; int elems = !scalar ? bytes >> op.Size : 1; if (scalar) { EmitVectorZeroLowerTmp(context); } for (int index = 0; index < elems; index++) { EmitVectorExtractSx(context, op.Rn, index, op.Size); emit(); if (op.Size <= 2) { EmitSatQ(context, op.Size, true, true); } else /* if (Op.Size == 3) */ { EmitUnarySignedSatQAbsOrNeg(context); } EmitVectorInsertTmp(context, index, op.Size); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); if ((op.RegisterSize == RegisterSize.Simd64) || scalar) { EmitVectorZeroUpper(context, op.Rd); } }
public static void EmitSaturatingBinaryOp(ILEmitterCtx context, Action emit, SaturatingFlags flags) { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; bool scalar = (flags & SaturatingFlags.Scalar) != 0; bool signed = (flags & SaturatingFlags.Signed) != 0; bool add = (flags & SaturatingFlags.Add) != 0; bool sub = (flags & SaturatingFlags.Sub) != 0; bool accumulate = (flags & SaturatingFlags.Accumulate) != 0; int bytes = op.GetBitsCount() >> 3; int elems = !scalar ? bytes >> op.Size : 1; if (add || sub) { for (int index = 0; index < elems; index++) { EmitVectorExtract(context, op.Rn, index, op.Size, signed); EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, index, op.Size, signed); if (op.Size <= 2) { context.Emit(add ? OpCodes.Add : OpCodes.Sub); EmitSatQ(context, op.Size, true, signed); } else /* if (op.Size == 3) */ { if (add) { EmitBinarySatQAdd(context, signed); } else /* if (sub) */ { EmitBinarySatQSub(context, signed); } } if (scalar) { EmitVectorZeroAll(context, op.Rd); } EmitVectorInsert(context, op.Rd, index, op.Size); } } else if (accumulate) { for (int index = 0; index < elems; index++) { EmitVectorExtract(context, op.Rn, index, op.Size, !signed); EmitVectorExtract(context, op.Rd, index, op.Size, signed); if (op.Size <= 2) { context.Emit(OpCodes.Add); EmitSatQ(context, op.Size, true, signed); } else /* if (op.Size == 3) */ { EmitBinarySatQAccumulate(context, signed); } if (scalar) { EmitVectorZeroAll(context, op.Rd); } EmitVectorInsert(context, op.Rd, index, op.Size); } } else { for (int index = 0; index < elems; index++) { EmitVectorExtract(context, op.Rn, index, op.Size, signed); EmitVectorExtract(context, ((OpCodeSimdReg64)op).Rm, index, op.Size, signed); emit(); EmitSatQ(context, op.Size, true, signed); if (scalar) { EmitVectorZeroAll(context, op.Rd); } EmitVectorInsert(context, op.Rd, index, op.Size); } } if (op.RegisterSize == RegisterSize.Simd64) { EmitVectorZeroUpper(context, op.Rd); } }