From e6a5882e2c1e7d97046aee724c3c4910a94e7261 Mon Sep 17 00:00:00 2001 From: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> Date: Wed, 31 Oct 2018 16:40:28 +0100 Subject: [PATCH] Update and rename AInstEmitSimdCvt.cs to InstEmitSimdCvt.cs --- ChocolArm64/Instruction/AInstEmitSimdCvt.cs | 697 -------------------- ChocolArm64/Instruction/InstEmitSimdCvt.cs | 697 ++++++++++++++++++++ 2 files changed, 697 insertions(+), 697 deletions(-) delete mode 100644 ChocolArm64/Instruction/AInstEmitSimdCvt.cs create mode 100644 ChocolArm64/Instruction/InstEmitSimdCvt.cs diff --git a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs deleted file mode 100644 index f277069bff..0000000000 --- a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs +++ /dev/null @@ -1,697 +0,0 @@ -using ChocolArm64.Decoder; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -using static ChocolArm64.Instruction.AInstEmitSimdHelper; - -namespace ChocolArm64.Instruction -{ - static partial class AInstEmit - { - public static void Fcvt_S(AILEmitterCtx Context) - { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - if (AOptimizations.UseSse2) - { - if (Op.Size == 1 && Op.Opc == 0) - { - //Double -> Single. - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorSingleZero)); - - EmitLdvecWithCastToDouble(Context, Op.Rn); - - Type[] Types = new Type[] { typeof(Vector128), typeof(Vector128) }; - - Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Single), Types)); - - Context.EmitStvec(Op.Rd); - } - else if (Op.Size == 0 && Op.Opc == 1) - { - //Single -> Double. - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorDoubleZero)); - - Context.EmitLdvec(Op.Rn); - - Type[] Types = new Type[] { typeof(Vector128), typeof(Vector128) }; - - Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Double), Types)); - - EmitStvecWithCastFromDouble(Context, Op.Rd); - } - else - { - //Invalid encoding. - throw new InvalidOperationException(); - } - } - else - { - EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - - EmitFloatCast(Context, Op.Opc); - - EmitScalarSetF(Context, Op.Rd, Op.Opc); - } - } - - public static void Fcvtas_Gp(AILEmitterCtx Context) - { - EmitFcvt_s_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero)); - } - - public static void Fcvtau_Gp(AILEmitterCtx Context) - { - EmitFcvt_u_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero)); - } - - public static void Fcvtl_V(AILEmitterCtx Context) - { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - int SizeF = Op.Size & 1; - - int Elems = 4 >> SizeF; - - int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; - - for (int Index = 0; Index < Elems; Index++) - { - if (SizeF == 0) - { - EmitVectorExtractZx(Context, Op.Rn, Part + Index, 1); - Context.Emit(OpCodes.Conv_U2); - - Context.EmitLdarg(ATranslatedSub.StateArgIdx); - - Context.EmitCall(typeof(ASoftFloat16_32), nameof(ASoftFloat16_32.FPConvert)); - } - else /* if (SizeF == 1) */ - { - EmitVectorExtractF(Context, Op.Rn, Part + Index, 0); - - Context.Emit(OpCodes.Conv_R8); - } - - EmitVectorInsertTmpF(Context, Index, SizeF); - } - - Context.EmitLdvectmp(); - Context.EmitStvec(Op.Rd); - } - - public static void Fcvtms_Gp(AILEmitterCtx Context) - { - EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor))); - } - - public static void Fcvtmu_Gp(AILEmitterCtx Context) - { - EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor))); - } - - public static void Fcvtn_V(AILEmitterCtx Context) - { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - int SizeF = Op.Size & 1; - - int Elems = 4 >> SizeF; - - int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; - - if (Part != 0) - { - Context.EmitLdvec(Op.Rd); - Context.EmitStvectmp(); - } - - for (int Index = 0; Index < Elems; Index++) - { - EmitVectorExtractF(Context, Op.Rn, Index, SizeF); - - if (SizeF == 0) - { - Context.EmitLdarg(ATranslatedSub.StateArgIdx); - - Context.EmitCall(typeof(ASoftFloat32_16), nameof(ASoftFloat32_16.FPConvert)); - - Context.Emit(OpCodes.Conv_U8); - EmitVectorInsertTmp(Context, Part + Index, 1); - } - else /* if (SizeF == 1) */ - { - Context.Emit(OpCodes.Conv_R4); - - EmitVectorInsertTmpF(Context, Part + Index, 0); - } - } - - Context.EmitLdvectmp(); - Context.EmitStvec(Op.Rd); - - if (Part == 0) - { - EmitVectorZeroUpper(Context, Op.Rd); - } - } - - public static void Fcvtns_S(AILEmitterCtx Context) - { - EmitFcvtn(Context, Signed: true, Scalar: true); - } - - public static void Fcvtns_V(AILEmitterCtx Context) - { - EmitFcvtn(Context, Signed: true, Scalar: false); - } - - public static void Fcvtnu_S(AILEmitterCtx Context) - { - EmitFcvtn(Context, Signed: false, Scalar: true); - } - - public static void Fcvtnu_V(AILEmitterCtx Context) - { - EmitFcvtn(Context, Signed: false, Scalar: false); - } - - public static void Fcvtps_Gp(AILEmitterCtx Context) - { - EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling))); - } - - public static void Fcvtpu_Gp(AILEmitterCtx Context) - { - EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling))); - } - - public static void Fcvtzs_Gp(AILEmitterCtx Context) - { - EmitFcvt_s_Gp(Context, () => { }); - } - - public static void Fcvtzs_Gp_Fix(AILEmitterCtx Context) - { - EmitFcvtzs_Gp_Fix(Context); - } - - public static void Fcvtzs_S(AILEmitterCtx Context) - { - EmitScalarFcvtzs(Context); - } - - public static void Fcvtzs_V(AILEmitterCtx Context) - { - EmitVectorFcvtzs(Context); - } - - public static void Fcvtzu_Gp(AILEmitterCtx Context) - { - EmitFcvt_u_Gp(Context, () => { }); - } - - public static void Fcvtzu_Gp_Fix(AILEmitterCtx Context) - { - EmitFcvtzu_Gp_Fix(Context); - } - - public static void Fcvtzu_S(AILEmitterCtx Context) - { - EmitScalarFcvtzu(Context); - } - - public static void Fcvtzu_V(AILEmitterCtx Context) - { - EmitVectorFcvtzu(Context); - } - - public static void Scvtf_Gp(AILEmitterCtx Context) - { - AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; - - Context.EmitLdintzr(Op.Rn); - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - Context.Emit(OpCodes.Conv_U4); - } - - EmitFloatCast(Context, Op.Size); - - EmitScalarSetF(Context, Op.Rd, Op.Size); - } - - public static void Scvtf_S(AILEmitterCtx Context) - { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - EmitVectorExtractSx(Context, Op.Rn, 0, Op.Size + 2); - - EmitFloatCast(Context, Op.Size); - - EmitScalarSetF(Context, Op.Rd, Op.Size); - } - - public static void Scvtf_V(AILEmitterCtx Context) - { - EmitVectorCvtf(Context, Signed: true); - } - - public static void Ucvtf_Gp(AILEmitterCtx Context) - { - AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; - - Context.EmitLdintzr(Op.Rn); - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - Context.Emit(OpCodes.Conv_U4); - } - - Context.Emit(OpCodes.Conv_R_Un); - - EmitFloatCast(Context, Op.Size); - - EmitScalarSetF(Context, Op.Rd, Op.Size); - } - - public static void Ucvtf_S(AILEmitterCtx Context) - { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size + 2); - - Context.Emit(OpCodes.Conv_R_Un); - - EmitFloatCast(Context, Op.Size); - - EmitScalarSetF(Context, Op.Rd, Op.Size); - } - - public static void Ucvtf_V(AILEmitterCtx Context) - { - EmitVectorCvtf(Context, Signed: false); - } - - private static int GetFBits(AILEmitterCtx Context) - { - if (Context.CurrOp is AOpCodeSimdShImm Op) - { - return GetImmShr(Op); - } - - return 0; - } - - private static void EmitFloatCast(AILEmitterCtx Context, int Size) - { - if (Size == 0) - { - Context.Emit(OpCodes.Conv_R4); - } - else if (Size == 1) - { - Context.Emit(OpCodes.Conv_R8); - } - else - { - throw new ArgumentOutOfRangeException(nameof(Size)); - } - } - - private static void EmitFcvtn(AILEmitterCtx Context, bool Signed, bool Scalar) - { - AOpCodeSimd Op = (AOpCodeSimd)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) - { - AVectorHelper.EmitCall(Context, Signed - ? nameof(AVectorHelper.SatF32ToS32) - : nameof(AVectorHelper.SatF32ToU32)); - - Context.Emit(OpCodes.Conv_U8); - } - else /* if (SizeF == 1) */ - { - AVectorHelper.EmitCall(Context, Signed - ? nameof(AVectorHelper.SatF64ToS64) - : nameof(AVectorHelper.SatF64ToU64)); - } - - EmitVectorInsertTmp(Context, Index, SizeI); - } - - Context.EmitLdvectmp(); - Context.EmitStvec(Op.Rd); - - if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar) - { - EmitVectorZeroUpper(Context, Op.Rd); - } - } - - private static void EmitFcvt_s_Gp(AILEmitterCtx Context, Action Emit) - { - EmitFcvt___Gp(Context, Emit, true); - } - - private static void EmitFcvt_u_Gp(AILEmitterCtx Context, Action Emit) - { - EmitFcvt___Gp(Context, Emit, false); - } - - private static void EmitFcvt___Gp(AILEmitterCtx Context, Action Emit, bool Signed) - { - AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; - - EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - - Emit(); - - if (Signed) - { - EmitScalarFcvts(Context, Op.Size, 0); - } - else - { - EmitScalarFcvtu(Context, Op.Size, 0); - } - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - Context.Emit(OpCodes.Conv_U8); - } - - Context.EmitStintzr(Op.Rd); - } - - private static void EmitFcvtzs_Gp_Fix(AILEmitterCtx Context) - { - EmitFcvtz__Gp_Fix(Context, true); - } - - private static void EmitFcvtzu_Gp_Fix(AILEmitterCtx Context) - { - EmitFcvtz__Gp_Fix(Context, false); - } - - private static void EmitFcvtz__Gp_Fix(AILEmitterCtx Context, bool Signed) - { - AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; - - EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - - if (Signed) - { - EmitScalarFcvts(Context, Op.Size, Op.FBits); - } - else - { - EmitScalarFcvtu(Context, Op.Size, Op.FBits); - } - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - Context.Emit(OpCodes.Conv_U8); - } - - Context.EmitStintzr(Op.Rd); - } - - private static void EmitVectorScvtf(AILEmitterCtx Context) - { - EmitVectorCvtf(Context, true); - } - - private static void EmitVectorUcvtf(AILEmitterCtx Context) - { - EmitVectorCvtf(Context, false); - } - - private static void EmitVectorCvtf(AILEmitterCtx Context, bool Signed) - { - AOpCodeSimd Op = (AOpCodeSimd)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); - } - - Context.Emit(SizeF == 0 - ? OpCodes.Conv_R4 - : OpCodes.Conv_R8); - - EmitI2fFBitsMul(Context, SizeF, FBits); - - EmitVectorInsertF(Context, Op.Rd, Index, SizeF); - } - - if (Op.RegisterSize == ARegisterSize.SIMD64) - { - EmitVectorZeroUpper(Context, Op.Rd); - } - } - - private static void EmitScalarFcvtzs(AILEmitterCtx Context) - { - EmitScalarFcvtz(Context, true); - } - - private static void EmitScalarFcvtzu(AILEmitterCtx Context) - { - EmitScalarFcvtz(Context, false); - } - - private static void EmitScalarFcvtz(AILEmitterCtx Context, bool Signed) - { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - int SizeF = Op.Size & 1; - int SizeI = SizeF + 2; - - int FBits = GetFBits(Context); - - EmitVectorExtractF(Context, Op.Rn, 0, SizeF); - - EmitF2iFBitsMul(Context, SizeF, FBits); - - if (SizeF == 0) - { - AVectorHelper.EmitCall(Context, Signed - ? nameof(AVectorHelper.SatF32ToS32) - : nameof(AVectorHelper.SatF32ToU32)); - } - else /* if (SizeF == 1) */ - { - AVectorHelper.EmitCall(Context, Signed - ? nameof(AVectorHelper.SatF64ToS64) - : nameof(AVectorHelper.SatF64ToU64)); - } - - if (SizeF == 0) - { - Context.Emit(OpCodes.Conv_U8); - } - - EmitScalarSet(Context, Op.Rd, SizeI); - } - - private static void EmitVectorFcvtzs(AILEmitterCtx Context) - { - EmitVectorFcvtz(Context, true); - } - - private static void EmitVectorFcvtzu(AILEmitterCtx Context) - { - EmitVectorFcvtz(Context, false); - } - - private static void EmitVectorFcvtz(AILEmitterCtx Context, bool Signed) - { - AOpCodeSimd Op = (AOpCodeSimd)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++) - { - EmitVectorExtractF(Context, Op.Rn, Index, SizeF); - - EmitF2iFBitsMul(Context, SizeF, FBits); - - if (SizeF == 0) - { - AVectorHelper.EmitCall(Context, Signed - ? nameof(AVectorHelper.SatF32ToS32) - : nameof(AVectorHelper.SatF32ToU32)); - } - else /* if (SizeF == 1) */ - { - AVectorHelper.EmitCall(Context, Signed - ? nameof(AVectorHelper.SatF64ToS64) - : nameof(AVectorHelper.SatF64ToU64)); - } - - if (SizeF == 0) - { - Context.Emit(OpCodes.Conv_U8); - } - - EmitVectorInsert(Context, Op.Rd, Index, SizeI); - } - - if (Op.RegisterSize == ARegisterSize.SIMD64) - { - EmitVectorZeroUpper(Context, Op.Rd); - } - } - - private static void EmitScalarFcvts(AILEmitterCtx Context, int Size, int FBits) - { - if (Size < 0 || Size > 1) - { - throw new ArgumentOutOfRangeException(nameof(Size)); - } - - EmitF2iFBitsMul(Context, Size, FBits); - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - if (Size == 0) - { - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToS32)); - } - else /* if (Size == 1) */ - { - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToS32)); - } - } - else - { - if (Size == 0) - { - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToS64)); - } - else /* if (Size == 1) */ - { - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToS64)); - } - } - } - - private static void EmitScalarFcvtu(AILEmitterCtx Context, int Size, int FBits) - { - if (Size < 0 || Size > 1) - { - throw new ArgumentOutOfRangeException(nameof(Size)); - } - - EmitF2iFBitsMul(Context, Size, FBits); - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - if (Size == 0) - { - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToU32)); - } - else /* if (Size == 1) */ - { - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToU32)); - } - } - else - { - if (Size == 0) - { - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF32ToU64)); - } - else /* if (Size == 1) */ - { - AVectorHelper.EmitCall(Context, nameof(AVectorHelper.SatF64ToU64)); - } - } - } - - private static void EmitF2iFBitsMul(AILEmitterCtx Context, int Size, int FBits) - { - if (FBits != 0) - { - if (Size == 0) - { - Context.EmitLdc_R4(MathF.Pow(2f, FBits)); - } - else if (Size == 1) - { - Context.EmitLdc_R8(Math.Pow(2d, FBits)); - } - else - { - throw new ArgumentOutOfRangeException(nameof(Size)); - } - - Context.Emit(OpCodes.Mul); - } - } - - private static void EmitI2fFBitsMul(AILEmitterCtx Context, int Size, int FBits) - { - if (FBits != 0) - { - if (Size == 0) - { - Context.EmitLdc_R4(1f / MathF.Pow(2f, FBits)); - } - else if (Size == 1) - { - Context.EmitLdc_R8(1d / Math.Pow(2d, FBits)); - } - else - { - throw new ArgumentOutOfRangeException(nameof(Size)); - } - - Context.Emit(OpCodes.Mul); - } - } - } -} diff --git a/ChocolArm64/Instruction/InstEmitSimdCvt.cs b/ChocolArm64/Instruction/InstEmitSimdCvt.cs new file mode 100644 index 0000000000..45f2bef25f --- /dev/null +++ b/ChocolArm64/Instruction/InstEmitSimdCvt.cs @@ -0,0 +1,697 @@ +using ChocolArm64.Decoders; +using ChocolArm64.State; +using ChocolArm64.Translation; +using System; +using System.Reflection.Emit; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; + +using static ChocolArm64.Instructions.InstEmitSimdHelper; + +namespace ChocolArm64.Instructions +{ + static partial class InstEmit + { + public static void Fcvt_S(ILEmitterCtx context) + { + OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; + + if (Optimizations.UseSse2) + { + if (op.Size == 1 && op.Opc == 0) + { + //Double -> Single. + VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); + + EmitLdvecWithCastToDouble(context, op.Rn); + + Type[] types = new Type[] { typeof(Vector128), typeof(Vector128) }; + + context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Single), types)); + + context.EmitStvec(op.Rd); + } + else if (op.Size == 0 && op.Opc == 1) + { + //Single -> Double. + VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleZero)); + + context.EmitLdvec(op.Rn); + + Type[] types = new Type[] { typeof(Vector128), typeof(Vector128) }; + + context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Double), types)); + + EmitStvecWithCastFromDouble(context, op.Rd); + } + else + { + //Invalid encoding. + throw new InvalidOperationException(); + } + } + else + { + EmitVectorExtractF(context, op.Rn, 0, op.Size); + + EmitFloatCast(context, op.Opc); + + EmitScalarSetF(context, op.Rd, op.Opc); + } + } + + public static void Fcvtas_Gp(ILEmitterCtx context) + { + EmitFcvt_s_Gp(context, () => EmitRoundMathCall(context, MidpointRounding.AwayFromZero)); + } + + public static void Fcvtau_Gp(ILEmitterCtx context) + { + EmitFcvt_u_Gp(context, () => EmitRoundMathCall(context, MidpointRounding.AwayFromZero)); + } + + public static void Fcvtl_V(ILEmitterCtx context) + { + OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; + + int sizeF = op.Size & 1; + + int elems = 4 >> sizeF; + + int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; + + for (int index = 0; index < elems; index++) + { + if (sizeF == 0) + { + EmitVectorExtractZx(context, op.Rn, part + index, 1); + context.Emit(OpCodes.Conv_U2); + + context.EmitLdarg(TranslatedSub.StateArgIdx); + + context.EmitCall(typeof(SoftFloat16_32), nameof(SoftFloat16_32.FPConvert)); + } + else /* if (sizeF == 1) */ + { + EmitVectorExtractF(context, op.Rn, part + index, 0); + + context.Emit(OpCodes.Conv_R8); + } + + EmitVectorInsertTmpF(context, index, sizeF); + } + + context.EmitLdvectmp(); + context.EmitStvec(op.Rd); + } + + public static void Fcvtms_Gp(ILEmitterCtx context) + { + EmitFcvt_s_Gp(context, () => EmitUnaryMathCall(context, nameof(Math.Floor))); + } + + public static void Fcvtmu_Gp(ILEmitterCtx context) + { + EmitFcvt_u_Gp(context, () => EmitUnaryMathCall(context, nameof(Math.Floor))); + } + + public static void Fcvtn_V(ILEmitterCtx context) + { + OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; + + int sizeF = op.Size & 1; + + int elems = 4 >> sizeF; + + int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; + + if (part != 0) + { + context.EmitLdvec(op.Rd); + context.EmitStvectmp(); + } + + for (int index = 0; index < elems; index++) + { + EmitVectorExtractF(context, op.Rn, index, sizeF); + + if (sizeF == 0) + { + context.EmitLdarg(TranslatedSub.StateArgIdx); + + context.EmitCall(typeof(SoftFloat32_16), nameof(SoftFloat32_16.FPConvert)); + + context.Emit(OpCodes.Conv_U8); + EmitVectorInsertTmp(context, part + index, 1); + } + else /* if (sizeF == 1) */ + { + context.Emit(OpCodes.Conv_R4); + + EmitVectorInsertTmpF(context, part + index, 0); + } + } + + context.EmitLdvectmp(); + context.EmitStvec(op.Rd); + + if (part == 0) + { + EmitVectorZeroUpper(context, op.Rd); + } + } + + public static void Fcvtns_S(ILEmitterCtx context) + { + EmitFcvtn(context, signed: true, scalar: true); + } + + public static void Fcvtns_V(ILEmitterCtx context) + { + EmitFcvtn(context, signed: true, scalar: false); + } + + public static void Fcvtnu_S(ILEmitterCtx context) + { + EmitFcvtn(context, signed: false, scalar: true); + } + + public static void Fcvtnu_V(ILEmitterCtx context) + { + EmitFcvtn(context, signed: false, scalar: false); + } + + public static void Fcvtps_Gp(ILEmitterCtx context) + { + EmitFcvt_s_Gp(context, () => EmitUnaryMathCall(context, nameof(Math.Ceiling))); + } + + public static void Fcvtpu_Gp(ILEmitterCtx context) + { + EmitFcvt_u_Gp(context, () => EmitUnaryMathCall(context, nameof(Math.Ceiling))); + } + + public static void Fcvtzs_Gp(ILEmitterCtx context) + { + EmitFcvt_s_Gp(context, () => { }); + } + + public static void Fcvtzs_Gp_Fix(ILEmitterCtx context) + { + EmitFcvtzs_Gp_Fix(context); + } + + public static void Fcvtzs_S(ILEmitterCtx context) + { + EmitScalarFcvtzs(context); + } + + public static void Fcvtzs_V(ILEmitterCtx context) + { + EmitVectorFcvtzs(context); + } + + public static void Fcvtzu_Gp(ILEmitterCtx context) + { + EmitFcvt_u_Gp(context, () => { }); + } + + public static void Fcvtzu_Gp_Fix(ILEmitterCtx context) + { + EmitFcvtzu_Gp_Fix(context); + } + + public static void Fcvtzu_S(ILEmitterCtx context) + { + EmitScalarFcvtzu(context); + } + + public static void Fcvtzu_V(ILEmitterCtx context) + { + EmitVectorFcvtzu(context); + } + + public static void Scvtf_Gp(ILEmitterCtx context) + { + OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; + + context.EmitLdintzr(op.Rn); + + if (context.CurrOp.RegisterSize == RegisterSize.Int32) + { + context.Emit(OpCodes.Conv_U4); + } + + EmitFloatCast(context, op.Size); + + EmitScalarSetF(context, op.Rd, op.Size); + } + + public static void Scvtf_S(ILEmitterCtx context) + { + OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; + + EmitVectorExtractSx(context, op.Rn, 0, op.Size + 2); + + EmitFloatCast(context, op.Size); + + EmitScalarSetF(context, op.Rd, op.Size); + } + + public static void Scvtf_V(ILEmitterCtx context) + { + EmitVectorCvtf(context, signed: true); + } + + public static void Ucvtf_Gp(ILEmitterCtx context) + { + OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; + + context.EmitLdintzr(op.Rn); + + if (context.CurrOp.RegisterSize == RegisterSize.Int32) + { + context.Emit(OpCodes.Conv_U4); + } + + context.Emit(OpCodes.Conv_R_Un); + + EmitFloatCast(context, op.Size); + + EmitScalarSetF(context, op.Rd, op.Size); + } + + public static void Ucvtf_S(ILEmitterCtx context) + { + OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; + + EmitVectorExtractZx(context, op.Rn, 0, op.Size + 2); + + context.Emit(OpCodes.Conv_R_Un); + + EmitFloatCast(context, op.Size); + + EmitScalarSetF(context, op.Rd, op.Size); + } + + public static void Ucvtf_V(ILEmitterCtx context) + { + EmitVectorCvtf(context, signed: false); + } + + private static int GetFBits(ILEmitterCtx context) + { + if (context.CurrOp is OpCodeSimdShImm64 op) + { + return GetImmShr(op); + } + + return 0; + } + + private static void EmitFloatCast(ILEmitterCtx context, int size) + { + if (size == 0) + { + context.Emit(OpCodes.Conv_R4); + } + else if (size == 1) + { + context.Emit(OpCodes.Conv_R8); + } + else + { + throw new ArgumentOutOfRangeException(nameof(size)); + } + } + + 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 EmitFcvt_s_Gp(ILEmitterCtx context, Action emit) + { + EmitFcvt___Gp(context, emit, true); + } + + private static void EmitFcvt_u_Gp(ILEmitterCtx context, Action emit) + { + EmitFcvt___Gp(context, emit, false); + } + + private static void EmitFcvt___Gp(ILEmitterCtx context, Action emit, bool signed) + { + OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; + + EmitVectorExtractF(context, op.Rn, 0, op.Size); + + emit(); + + if (signed) + { + EmitScalarFcvts(context, op.Size, 0); + } + else + { + EmitScalarFcvtu(context, op.Size, 0); + } + + if (context.CurrOp.RegisterSize == RegisterSize.Int32) + { + context.Emit(OpCodes.Conv_U8); + } + + context.EmitStintzr(op.Rd); + } + + private static void EmitFcvtzs_Gp_Fix(ILEmitterCtx context) + { + EmitFcvtz__Gp_Fix(context, true); + } + + private static void EmitFcvtzu_Gp_Fix(ILEmitterCtx context) + { + EmitFcvtz__Gp_Fix(context, false); + } + + private static void EmitFcvtz__Gp_Fix(ILEmitterCtx context, bool signed) + { + OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp; + + EmitVectorExtractF(context, op.Rn, 0, op.Size); + + if (signed) + { + EmitScalarFcvts(context, op.Size, op.FBits); + } + else + { + EmitScalarFcvtu(context, op.Size, op.FBits); + } + + if (context.CurrOp.RegisterSize == RegisterSize.Int32) + { + context.Emit(OpCodes.Conv_U8); + } + + context.EmitStintzr(op.Rd); + } + + private static void EmitVectorScvtf(ILEmitterCtx context) + { + EmitVectorCvtf(context, true); + } + + private static void EmitVectorUcvtf(ILEmitterCtx context) + { + EmitVectorCvtf(context, false); + } + + 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); + } + + context.Emit(sizeF == 0 + ? OpCodes.Conv_R4 + : OpCodes.Conv_R8); + + EmitI2fFBitsMul(context, sizeF, fBits); + + EmitVectorInsertF(context, op.Rd, index, sizeF); + } + + if (op.RegisterSize == RegisterSize.Simd64) + { + EmitVectorZeroUpper(context, op.Rd); + } + } + + private static void EmitScalarFcvtzs(ILEmitterCtx context) + { + EmitScalarFcvtz(context, true); + } + + private static void EmitScalarFcvtzu(ILEmitterCtx context) + { + EmitScalarFcvtz(context, false); + } + + private static void EmitScalarFcvtz(ILEmitterCtx context, bool signed) + { + OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; + + int sizeF = op.Size & 1; + int sizeI = sizeF + 2; + + int fBits = GetFBits(context); + + EmitVectorExtractF(context, op.Rn, 0, sizeF); + + EmitF2iFBitsMul(context, sizeF, fBits); + + if (sizeF == 0) + { + VectorHelper.EmitCall(context, signed + ? nameof(VectorHelper.SatF32ToS32) + : nameof(VectorHelper.SatF32ToU32)); + } + else /* if (sizeF == 1) */ + { + VectorHelper.EmitCall(context, signed + ? nameof(VectorHelper.SatF64ToS64) + : nameof(VectorHelper.SatF64ToU64)); + } + + if (sizeF == 0) + { + context.Emit(OpCodes.Conv_U8); + } + + EmitScalarSet(context, op.Rd, sizeI); + } + + private static void EmitVectorFcvtzs(ILEmitterCtx context) + { + EmitVectorFcvtz(context, true); + } + + private static void EmitVectorFcvtzu(ILEmitterCtx context) + { + EmitVectorFcvtz(context, false); + } + + private static void EmitVectorFcvtz(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++) + { + EmitVectorExtractF(context, op.Rn, index, sizeF); + + EmitF2iFBitsMul(context, sizeF, fBits); + + if (sizeF == 0) + { + VectorHelper.EmitCall(context, signed + ? nameof(VectorHelper.SatF32ToS32) + : nameof(VectorHelper.SatF32ToU32)); + } + else /* if (sizeF == 1) */ + { + VectorHelper.EmitCall(context, signed + ? nameof(VectorHelper.SatF64ToS64) + : nameof(VectorHelper.SatF64ToU64)); + } + + if (sizeF == 0) + { + context.Emit(OpCodes.Conv_U8); + } + + EmitVectorInsert(context, op.Rd, index, sizeI); + } + + if (op.RegisterSize == RegisterSize.Simd64) + { + EmitVectorZeroUpper(context, op.Rd); + } + } + + private static void EmitScalarFcvts(ILEmitterCtx context, int size, int fBits) + { + if (size < 0 || size > 1) + { + throw new ArgumentOutOfRangeException(nameof(size)); + } + + EmitF2iFBitsMul(context, size, fBits); + + if (context.CurrOp.RegisterSize == RegisterSize.Int32) + { + if (size == 0) + { + VectorHelper.EmitCall(context, nameof(VectorHelper.SatF32ToS32)); + } + else /* if (size == 1) */ + { + VectorHelper.EmitCall(context, nameof(VectorHelper.SatF64ToS32)); + } + } + else + { + if (size == 0) + { + VectorHelper.EmitCall(context, nameof(VectorHelper.SatF32ToS64)); + } + else /* if (size == 1) */ + { + VectorHelper.EmitCall(context, nameof(VectorHelper.SatF64ToS64)); + } + } + } + + private static void EmitScalarFcvtu(ILEmitterCtx context, int size, int fBits) + { + if (size < 0 || size > 1) + { + throw new ArgumentOutOfRangeException(nameof(size)); + } + + EmitF2iFBitsMul(context, size, fBits); + + if (context.CurrOp.RegisterSize == RegisterSize.Int32) + { + if (size == 0) + { + VectorHelper.EmitCall(context, nameof(VectorHelper.SatF32ToU32)); + } + else /* if (size == 1) */ + { + VectorHelper.EmitCall(context, nameof(VectorHelper.SatF64ToU32)); + } + } + else + { + if (size == 0) + { + VectorHelper.EmitCall(context, nameof(VectorHelper.SatF32ToU64)); + } + else /* if (size == 1) */ + { + VectorHelper.EmitCall(context, nameof(VectorHelper.SatF64ToU64)); + } + } + } + + private static void EmitF2iFBitsMul(ILEmitterCtx context, int size, int fBits) + { + if (fBits != 0) + { + if (size == 0) + { + context.EmitLdc_R4(MathF.Pow(2f, fBits)); + } + else if (size == 1) + { + context.EmitLdc_R8(Math.Pow(2d, fBits)); + } + else + { + throw new ArgumentOutOfRangeException(nameof(size)); + } + + context.Emit(OpCodes.Mul); + } + } + + private static void EmitI2fFBitsMul(ILEmitterCtx context, int size, int fBits) + { + if (fBits != 0) + { + if (size == 0) + { + context.EmitLdc_R4(1f / MathF.Pow(2f, fBits)); + } + else if (size == 1) + { + context.EmitLdc_R8(1d / Math.Pow(2d, fBits)); + } + else + { + throw new ArgumentOutOfRangeException(nameof(size)); + } + + context.Emit(OpCodes.Mul); + } + } + } +}