private static void EmitVectorAddv(AILEmitterCtx Context) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int Bytes = Context.CurrOp.GetBitsCount() >> 3; EmitVectorZeroLower(Context, Op.Rd); EmitVectorZeroUpper(Context, Op.Rd); Context.EmitLdvec(Op.Rd); Context.EmitLdc_I4(0); Context.EmitLdc_I4(Op.Size); EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size); for (int Index = 1; Index < (Bytes >> Op.Size); Index++) { EmitVectorExtractZx(Context, Op.Rn, Op.Size, Index); Context.Emit(OpCodes.Add); } ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec)); Context.EmitStvec(Op.Rd); }
private static void EmitVectorImmBinaryOp(AILEmitterCtx Context, Action Emit, long Imm, bool Signed) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; int Bytes = Context.CurrOp.GetBitsCount() >> 3; for (int Index = 0; Index < (Bytes >> Op.Size); Index++) { Context.EmitLdvec(Op.Rd); Context.EmitLdc_I4(Index); Context.EmitLdc_I4(Op.Size); EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed); Context.EmitLdc_I8(Imm); Emit(); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec)); Context.EmitStvec(Op.Rd); } if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } }
private static void EmitCcmp(AILEmitterCtx Context, CcmpOp CmpOp) { AOpCodeCcmp Op = (AOpCodeCcmp)Context.CurrOp; AILLabel LblTrue = new AILLabel(); AILLabel LblEnd = new AILLabel(); Context.EmitCondBranch(LblTrue, Op.Cond); Context.EmitLdc_I4((Op.NZCV >> 0) & 1); Context.EmitStflg((int)APState.VBit); Context.EmitLdc_I4((Op.NZCV >> 1) & 1); Context.EmitStflg((int)APState.CBit); Context.EmitLdc_I4((Op.NZCV >> 2) & 1); Context.EmitStflg((int)APState.ZBit); Context.EmitLdc_I4((Op.NZCV >> 3) & 1); Context.EmitStflg((int)APState.NBit); Context.Emit(OpCodes.Br_S, LblEnd); Context.MarkLabel(LblTrue); EmitDataLoadOpers(Context); if (CmpOp == CcmpOp.Cmp) { Context.Emit(OpCodes.Sub); Context.EmitZNFlagCheck(); EmitSubsCCheck(Context); EmitSubsVCheck(Context); } else if (CmpOp == CcmpOp.Cmn) { Context.Emit(OpCodes.Add); Context.EmitZNFlagCheck(); EmitAddsCCheck(Context); EmitAddsVCheck(Context); } else { throw new ArgumentException(nameof(CmpOp)); } Context.Emit(OpCodes.Pop); Context.MarkLabel(LblEnd); }
private static void EmitZeroCVFlags(AILEmitterCtx Context) { Context.EmitLdc_I4(0); Context.EmitStflg((int)APState.VBit); Context.EmitLdc_I4(0); Context.EmitStflg((int)APState.CBit); }
private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size) { Context.EmitLdvec(Reg); Context.EmitLdc_I4(Index); Context.EmitLdc_I4(Size); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertInt)); Context.EmitStvec(Reg); }
public static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, int Size, bool Signed) { ThrowIfInvalid(Index, Size); Context.EmitLdvec(Reg); Context.EmitLdc_I4(Index); Context.EmitLdc_I4(Size); AVectorHelper.EmitCall(Context, Signed ? nameof(AVectorHelper.VectorExtractIntSx) : nameof(AVectorHelper.VectorExtractIntZx)); }
public static void Dup_S(AILEmitterCtx Context) { AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp; Context.EmitLdvec(Op.Rn); Context.EmitLdc_I4(Op.DstIndex); Context.EmitLdc_I4(Op.Size); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Dup_S)); Context.EmitStvec(Op.Rd); }
private static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, bool Signed) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; Context.EmitLdvec(Reg); Context.EmitLdc_I4(Index); Context.EmitLdc_I4(Op.Size); ASoftFallback.EmitCall(Context, Signed ? nameof(ASoftFallback.ExtractSVec) : nameof(ASoftFallback.ExtractVec)); }
private static void EmitVectorShl(AILEmitterCtx Context, bool Signed) { //This instruction shifts the value on vector A by the number of bits //specified on the signed, lower 8 bits of vector B. If the shift value //is greater or equal to the data size of each lane, then the result is zero. //Additionally, negative shifts produces right shifts by the negated shift value. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int MaxShift = 8 << Op.Size; EmitVectorBinaryZx(Context, () => { AILLabel LblShl = new AILLabel(); AILLabel LblZero = new AILLabel(); AILLabel LblEnd = new AILLabel(); void EmitShift(OpCode ILOp) { Context.Emit(OpCodes.Dup); Context.EmitLdc_I4(MaxShift); Context.Emit(OpCodes.Bge_S, LblZero); Context.Emit(ILOp); Context.Emit(OpCodes.Br_S, LblEnd); } Context.Emit(OpCodes.Conv_I1); Context.Emit(OpCodes.Dup); Context.EmitLdc_I4(0); Context.Emit(OpCodes.Bge_S, LblShl); Context.Emit(OpCodes.Neg); EmitShift(Signed ? OpCodes.Shr : OpCodes.Shr_Un); Context.MarkLabel(LblShl); EmitShift(OpCodes.Shl); Context.MarkLabel(LblZero); Context.Emit(OpCodes.Pop); Context.Emit(OpCodes.Pop); Context.EmitLdc_I8(0); Context.MarkLabel(LblEnd); }); }
public static void Fmov_S(AILEmitterCtx Context) { AOpCodeSimdFmov Op = (AOpCodeSimdFmov)Context.CurrOp; Context.EmitLdc_I8(Op.Imm); Context.EmitLdc_I4(0); Context.EmitLdc_I4(Op.Size + 2); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Fmov_S)); Context.EmitStvec(Op.Rd); }
public static void Fmov_Ftoi1(AILEmitterCtx Context) { AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; Context.EmitLdvec(Op.Rn); Context.EmitLdc_I4(1); Context.EmitLdc_I4(3); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ExtractVec)); Context.EmitStintzr(Op.Rd); }
public static void Fmov_Itof1(AILEmitterCtx Context) { AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; Context.EmitLdintzr(Op.Rn); Context.EmitLdc_I4(1); Context.EmitLdc_I4(3); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Fmov_S)); Context.EmitStvec(Op.Rd); }
public static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size) { ThrowIfInvalid(Index, Size); Context.EmitLdvectmp(); Context.EmitLdc_I4(Index); Context.EmitLdc_I4(Size); AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt)); Context.EmitStvectmp(); }
public static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size, long Value) { ThrowIfInvalid(Index, Size); Context.EmitLdc_I8(Value); Context.EmitLdvec(Reg); Context.EmitLdc_I4(Index); Context.EmitLdc_I4(Size); AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt)); Context.EmitStvec(Reg); }
public static void Fcvtzu_V_Fix(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; Context.EmitLdvec(Op.Rn); Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm); Context.EmitLdc_I4(Op.Size - 2); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Fcvtzu_V_64), nameof(ASoftFallback.Fcvtzu_V_128)); Context.EmitStvec(Op.Rd); }
public static void Fcvtzu_V(AILEmitterCtx Context) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; Context.EmitLdvec(Op.Rn); Context.EmitLdc_I4(0); Context.EmitLdc_I4(Op.SizeF); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Fcvtzu_V_64), nameof(ASoftFallback.Fcvtzu_V_128)); Context.EmitStvec(Op.Rd); }
public static void Ushll_V(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; Context.EmitLdvec(Op.Rn); Context.EmitLdc_I4(Op.Imm - (8 << Op.Size)); Context.EmitLdc_I4(Op.Size); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Ushll), nameof(ASoftFallback.Ushll2)); Context.EmitStvec(Op.Rd); }
public static void Ushr_V(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; Context.EmitLdvec(Op.Rn); Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm); Context.EmitLdc_I4(Op.Size); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Ushr64), nameof(ASoftFallback.Ushr128)); Context.EmitStvec(Op.Rd); }
public static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, int Size, bool Signed) { ThrowIfInvalid(Index, Size); IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp; Context.EmitLdvec(Reg); Context.EmitLdc_I4(Index); Context.EmitLdc_I4(Size); ASoftFallback.EmitCall(Context, Signed ? nameof(ASoftFallback.VectorExtractIntSx) : nameof(ASoftFallback.VectorExtractIntZx)); }
public static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size) { if (Size < 0 || Size > 3) { throw new ArgumentOutOfRangeException(nameof(Size)); } Context.EmitLdvectmp(); Context.EmitLdc_I4(Index); Context.EmitLdc_I4(Size); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertInt)); Context.EmitStvectmp(); }
public static void Fmul_Vs(AILEmitterCtx Context) { AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; Context.EmitLdvec(Op.Rn); Context.EmitLdvec(Op.Rm); Context.EmitLdc_I4(Op.Index); Context.EmitLdc_I4(Op.SizeF); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Fmul_Ve64), nameof(ASoftFallback.Fmul_Ve128)); Context.EmitStvec(Op.Rd); }
public static void Sshr_V(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; if (AOptimizations.UseSse2 && Op.Size > 0 && Op.Size < 3) { Type[] TypesSra = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) }; EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size); Context.EmitLdc_I4(GetImmShr(Op)); Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesSra)); EmitStvecWithSignedCast(Context, Op.Rd, Op.Size); if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } } else { EmitShrImmOp(Context, ShrImmFlags.VectorSx); } }
public static void EmitRoundMathCall(AILEmitterCtx Context, MidpointRounding RoundMode) { IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp; int SizeF = Op.Size & 1; Context.EmitLdc_I4((int)RoundMode); MethodInfo MthdInfo; Type[] Types = new Type[] { null, typeof(MidpointRounding) }; Types[0] = SizeF == 0 ? typeof(float) : typeof(double); if (SizeF == 0) { MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types); } else /* if (SizeF == 1) */ { MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types); } Context.EmitCall(MthdInfo); }
private static void EmitSbc(AILEmitterCtx Context, bool SetFlags) { EmitDataLoadOpers(Context); Context.Emit(OpCodes.Sub); Context.EmitLdflg((int)APState.CBit); Type[] MthdTypes = new Type[] { typeof(bool) }; MethodInfo MthdInfo = typeof(Convert).GetMethod(nameof(Convert.ToInt32), MthdTypes); Context.EmitCall(MthdInfo); Context.EmitLdc_I4(1); Context.Emit(OpCodes.Xor); if (Context.CurrOp.RegisterSize != ARegisterSize.Int32) { Context.Emit(OpCodes.Conv_U8); } Context.Emit(OpCodes.Sub); if (SetFlags) { Context.EmitZNFlagCheck(); EmitSbcsCCheck(Context); EmitSubsVCheck(Context); } EmitDataStore(Context); }
private static void EmitCvtToUInt(AILEmitterCtx Context, int Size) { if (Size < 0 || Size > 1) { throw new ArgumentOutOfRangeException(nameof(Size)); } Context.EmitLdc_I4(0); if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) { if (Size == 0) { ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatSingleToUInt32)); } else /* if (Size == 1) */ { ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatDoubleToUInt32)); } } else { if (Size == 0) { ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatSingleToUInt64)); } else /* if (Size == 1) */ { ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatDoubleToUInt64)); } } }
public static void Frinta_S(AILEmitterCtx Context) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; Context.EmitLdvecsf(Op.Rn); Context.EmitLdc_I4((int)MidpointRounding.AwayFromZero); MethodInfo MthdInfo; if (Op.Size == 0) { Type[] Types = new Type[] { typeof(float), typeof(MidpointRounding) }; MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types); } else if (Op.Size == 1) { Type[] Types = new Type[] { typeof(double), typeof(MidpointRounding) }; MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types); } else { throw new InvalidOperationException(); } Context.EmitCall(MthdInfo); Context.EmitStvecsf(Op.Rd); }
// TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned). public static void EmitSatQ( AILEmitterCtx Context, int SizeDst, bool SignedSrc, bool SignedDst) { if (SizeDst > 2) { throw new ArgumentOutOfRangeException(nameof(SizeDst)); } Context.EmitLdc_I4(SizeDst); Context.EmitLdarg(ATranslatedSub.StateArgIdx); if (SignedSrc) { ASoftFallback.EmitCall(Context, SignedDst ? nameof(ASoftFallback.SignedSrcSignedDstSatQ) : nameof(ASoftFallback.SignedSrcUnsignedDstSatQ)); } else { ASoftFallback.EmitCall(Context, SignedDst ? nameof(ASoftFallback.UnsignedSrcSignedDstSatQ) : nameof(ASoftFallback.UnsignedSrcUnsignedDstSatQ)); } }
public static void Sli_V(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; int Bytes = Op.GetBitsCount() >> 3; int Elems = Bytes >> Op.Size; int Shift = GetImmShl(Op); ulong Mask = Shift != 0 ? ulong.MaxValue >> (64 - Shift) : 0; for (int Index = 0; Index < Elems; Index++) { EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size); Context.EmitLdc_I4(Shift); Context.Emit(OpCodes.Shl); EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size); Context.EmitLdc_I8((long)Mask); Context.Emit(OpCodes.And); Context.Emit(OpCodes.Or); EmitVectorInsert(Context, Op.Rd, Index, Op.Size); } if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } }
private static void EmitCountLeadingBits(AILEmitterCtx Context, Action Emit) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int Bytes = Op.GetBitsCount() >> 3; int Elems = Bytes >> Op.Size; int ESize = 8 << Op.Size; for (int Index = 0; Index < Elems; Index++) { EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size); Context.EmitLdc_I4(ESize); Emit(); EmitVectorInsert(Context, Op.Rd, Index, Op.Size); } if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } }
public static void Usra_V(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; if (AOptimizations.UseSse2 && Op.Size > 0) { Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) }; Type[] TypesAdd = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] }; EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size); EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size); Context.EmitLdc_I4(GetImmShr(Op)); Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesSrl)); Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd)); EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size); if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } } else { EmitVectorShrImmOpZx(Context, ShrImmFlags.Accumulate); } }