diff options
| author | LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> | 2018-09-17 06:54:05 +0200 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-09-17 01:54:05 -0300 |
| commit | c7387be0d296f54a6ad5678d25e2c0d4910b7da4 (patch) | |
| tree | 6c9374064822de8a2a40c1db94064c4023bdf059 /ChocolArm64 | |
| parent | 8a78a703f2e8e374286efaae575d87fb38242427 (diff) | |
Fix/Add 1+12 [Saturating] [Rounded] Shift Right Narrow (imm.) Instructions; add 14 Tests. Add 6 Tests for PR#405. Add 2 Tests for PR#412. (#409)
* Update AOpCodeTable.cs
* Update AInstEmitSimdShift.cs
* Update CpuTestSimdShImm.cs
* Update AInstEmitSimdArithmetic.cs
* Update AInstEmitSimdHelper.cs
* Create CpuTestSimdIns.cs
* Update CpuTest.cs
* Update CpuTestSimd.cs
* Update CpuTestSimdReg.cs
* Update CpuTest.cs
* Update CpuTestSimd.cs
* Update CpuTestSimdReg.cs
* Update CpuTestSimd.cs
* Update CpuTestSimdReg.cs
* Update CpuTest.cs
* Update CpuTestSimdReg.cs
* Update CpuTestSimd.cs
Diffstat (limited to 'ChocolArm64')
| -rw-r--r-- | ChocolArm64/AOpCodeTable.cs | 12 | ||||
| -rw-r--r-- | ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs | 12 | ||||
| -rw-r--r-- | ChocolArm64/Instruction/AInstEmitSimdHelper.cs | 46 | ||||
| -rw-r--r-- | ChocolArm64/Instruction/AInstEmitSimdShift.cs | 213 |
4 files changed, 192 insertions, 91 deletions
diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index b053334f..fe3dce41 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -364,6 +364,7 @@ namespace ChocolArm64 SetA64("0x00111000100000000110xxxxxxxxxx", AInstEmit.Rev16_V, typeof(AOpCodeSimd)); SetA64("0x1011100x100000000010xxxxxxxxxx", AInstEmit.Rev32_V, typeof(AOpCodeSimd)); SetA64("0x001110<<100000000010xxxxxxxxxx", AInstEmit.Rev64_V, typeof(AOpCodeSimd)); + SetA64("0x00111100>>>xxx100011xxxxxxxxxx", AInstEmit.Rshrn_V, typeof(AOpCodeSimdShImm)); SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", AInstEmit.Rsubhn_V, typeof(AOpCodeSimdReg)); SetA64("0x001110<<1xxxxx011111xxxxxxxxxx", AInstEmit.Saba_V, typeof(AOpCodeSimdReg)); SetA64("0x001110<<1xxxxx010100xxxxxxxxxx", AInstEmit.Sabal_V, typeof(AOpCodeSimdReg)); @@ -409,7 +410,14 @@ namespace ChocolArm64 SetA64("01111110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_S, typeof(AOpCodeSimdReg)); SetA64("0x101110011xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_V, typeof(AOpCodeSimdReg)); SetA64("0x101110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_V, typeof(AOpCodeSimdReg)); + SetA64("0101111100>>>xxx100111xxxxxxxxxx", AInstEmit.Sqrshrn_S, typeof(AOpCodeSimdShImm)); SetA64("0x00111100>>>xxx100111xxxxxxxxxx", AInstEmit.Sqrshrn_V, typeof(AOpCodeSimdShImm)); + SetA64("0111111100>>>xxx100011xxxxxxxxxx", AInstEmit.Sqrshrun_S, typeof(AOpCodeSimdShImm)); + SetA64("0x10111100>>>xxx100011xxxxxxxxxx", AInstEmit.Sqrshrun_V, typeof(AOpCodeSimdShImm)); + SetA64("0101111100>>>xxx100101xxxxxxxxxx", AInstEmit.Sqshrn_S, typeof(AOpCodeSimdShImm)); + SetA64("0x00111100>>>xxx100101xxxxxxxxxx", AInstEmit.Sqshrn_V, typeof(AOpCodeSimdShImm)); + SetA64("0111111100>>>xxx100001xxxxxxxxxx", AInstEmit.Sqshrun_S, typeof(AOpCodeSimdShImm)); + SetA64("0x10111100>>>xxx100001xxxxxxxxxx", AInstEmit.Sqshrun_V, typeof(AOpCodeSimdShImm)); SetA64("01011110xx1xxxxx001011xxxxxxxxxx", AInstEmit.Sqsub_S, typeof(AOpCodeSimdReg)); SetA64("0>001110<<1xxxxx001011xxxxxxxxxx", AInstEmit.Sqsub_V, typeof(AOpCodeSimdReg)); SetA64("01011110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_S, typeof(AOpCodeSimd)); @@ -476,6 +484,10 @@ namespace ChocolArm64 SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Umull_V, typeof(AOpCodeSimdReg)); SetA64("01111110xx1xxxxx000011xxxxxxxxxx", AInstEmit.Uqadd_S, typeof(AOpCodeSimdReg)); SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", AInstEmit.Uqadd_V, typeof(AOpCodeSimdReg)); + SetA64("0111111100>>>xxx100111xxxxxxxxxx", AInstEmit.Uqrshrn_S, typeof(AOpCodeSimdShImm)); + SetA64("0x10111100>>>xxx100111xxxxxxxxxx", AInstEmit.Uqrshrn_V, typeof(AOpCodeSimdShImm)); + SetA64("0111111100>>>xxx100101xxxxxxxxxx", AInstEmit.Uqshrn_S, typeof(AOpCodeSimdShImm)); + SetA64("0x10111100>>>xxx100101xxxxxxxxxx", AInstEmit.Uqshrn_V, typeof(AOpCodeSimdShImm)); SetA64("01111110xx1xxxxx001011xxxxxxxxxx", AInstEmit.Uqsub_S, typeof(AOpCodeSimdReg)); SetA64("0>101110<<1xxxxx001011xxxxxxxxxx", AInstEmit.Uqsub_V, typeof(AOpCodeSimdReg)); SetA64("01111110<<100001010010xxxxxxxxxx", AInstEmit.Uqxtn_S, typeof(AOpCodeSimd)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index b9aedd07..27a86d84 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -1199,22 +1199,22 @@ namespace ChocolArm64.Instruction public static void Sqxtn_S(AILEmitterCtx Context) { - EmitScalarSaturatingNarrowOpSxSx(Context, () => { }); + EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.ScalarSxSx); } public static void Sqxtn_V(AILEmitterCtx Context) { - EmitVectorSaturatingNarrowOpSxSx(Context, () => { }); + EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.VectorSxSx); } public static void Sqxtun_S(AILEmitterCtx Context) { - EmitScalarSaturatingNarrowOpSxZx(Context, () => { }); + EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.ScalarSxZx); } public static void Sqxtun_V(AILEmitterCtx Context) { - EmitVectorSaturatingNarrowOpSxZx(Context, () => { }); + EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.VectorSxZx); } public static void Srhadd_V(AILEmitterCtx Context) @@ -1455,12 +1455,12 @@ namespace ChocolArm64.Instruction public static void Uqxtn_S(AILEmitterCtx Context) { - EmitScalarSaturatingNarrowOpZxZx(Context, () => { }); + EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.ScalarZxZx); } public static void Uqxtn_V(AILEmitterCtx Context) { - EmitVectorSaturatingNarrowOpZxZx(Context, () => { }); + EmitSaturatingNarrowOp(Context, SaturatingNarrowFlags.VectorZxZx); } public static void Urhadd_V(AILEmitterCtx Context) diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs index cb884c1a..75a5a0d0 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs @@ -1004,56 +1004,14 @@ namespace ChocolArm64.Instruction ScalarSxSx = Scalar | SignedSrc | SignedDst, ScalarSxZx = Scalar | SignedSrc, - ScalarZxSx = Scalar | SignedDst, ScalarZxZx = Scalar, VectorSxSx = SignedSrc | SignedDst, VectorSxZx = SignedSrc, - VectorZxSx = SignedDst, VectorZxZx = 0 } - public static void EmitScalarSaturatingNarrowOpSxSx(AILEmitterCtx Context, Action Emit) - { - EmitSaturatingNarrowOp(Context, Emit, SaturatingNarrowFlags.ScalarSxSx); - } - - public static void EmitScalarSaturatingNarrowOpSxZx(AILEmitterCtx Context, Action Emit) - { - EmitSaturatingNarrowOp(Context, Emit, SaturatingNarrowFlags.ScalarSxZx); - } - - public static void EmitScalarSaturatingNarrowOpZxSx(AILEmitterCtx Context, Action Emit) - { - EmitSaturatingNarrowOp(Context, Emit, SaturatingNarrowFlags.ScalarZxSx); - } - - public static void EmitScalarSaturatingNarrowOpZxZx(AILEmitterCtx Context, Action Emit) - { - EmitSaturatingNarrowOp(Context, Emit, SaturatingNarrowFlags.ScalarZxZx); - } - - public static void EmitVectorSaturatingNarrowOpSxSx(AILEmitterCtx Context, Action Emit) - { - EmitSaturatingNarrowOp(Context, Emit, SaturatingNarrowFlags.VectorSxSx); - } - - public static void EmitVectorSaturatingNarrowOpSxZx(AILEmitterCtx Context, Action Emit) - { - EmitSaturatingNarrowOp(Context, Emit, SaturatingNarrowFlags.VectorSxZx); - } - - public static void EmitVectorSaturatingNarrowOpZxSx(AILEmitterCtx Context, Action Emit) - { - EmitSaturatingNarrowOp(Context, Emit, SaturatingNarrowFlags.VectorZxSx); - } - - public static void EmitVectorSaturatingNarrowOpZxZx(AILEmitterCtx Context, Action Emit) - { - EmitSaturatingNarrowOp(Context, Emit, SaturatingNarrowFlags.VectorZxZx); - } - - public static void EmitSaturatingNarrowOp(AILEmitterCtx Context, Action Emit, SaturatingNarrowFlags Flags) + public static void EmitSaturatingNarrowOp(AILEmitterCtx Context, SaturatingNarrowFlags Flags) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; @@ -1080,8 +1038,6 @@ namespace ChocolArm64.Instruction { EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc); - Emit(); - EmitSatQ(Context, Op.Size, SignedSrc, SignedDst); EmitVectorInsertTmp(Context, Part + Index, Op.Size); diff --git a/ChocolArm64/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs index 4dee53b9..127abf1d 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdShift.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdShift.cs @@ -10,6 +10,11 @@ namespace ChocolArm64.Instruction { static partial class AInstEmit { + public static void Rshrn_V(AILEmitterCtx Context) + { + EmitVectorShrImmNarrowOpZx(Context, Round: true); + } + public static void Shl_S(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; @@ -45,9 +50,7 @@ namespace ChocolArm64.Instruction public static void Shrn_V(AILEmitterCtx Context) { - AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; - - EmitVectorShImmNarrowBinaryZx(Context, () => Context.Emit(OpCodes.Shr_Un), GetImmShr(Op)); + EmitVectorShrImmNarrowOpZx(Context, Round: false); } public static void Sli_V(AILEmitterCtx Context) @@ -85,26 +88,44 @@ namespace ChocolArm64.Instruction } } - public static void Sqrshrn_V(AILEmitterCtx Context) + public static void Sqrshrn_S(AILEmitterCtx Context) { - AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxSx); + } - int Shift = GetImmShr(Op); + public static void Sqrshrn_V(AILEmitterCtx Context) + { + EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxSx); + } - long RoundConst = 1L << (Shift - 1); + public static void Sqrshrun_S(AILEmitterCtx Context) + { + EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxZx); + } - Action Emit = () => - { - Context.EmitLdc_I8(RoundConst); + public static void Sqrshrun_V(AILEmitterCtx Context) + { + EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxZx); + } - Context.Emit(OpCodes.Add); + public static void Sqshrn_S(AILEmitterCtx Context) + { + EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxSx); + } - Context.EmitLdc_I4(Shift); + public static void Sqshrn_V(AILEmitterCtx Context) + { + EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxSx); + } - Context.Emit(OpCodes.Shr); - }; + public static void Sqshrun_S(AILEmitterCtx Context) + { + EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarSxZx); + } - EmitVectorSaturatingNarrowOpSxSx(Context, Emit); + public static void Sqshrun_V(AILEmitterCtx Context) + { + EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorSxZx); } public static void Srshr_S(AILEmitterCtx Context) @@ -159,6 +180,26 @@ namespace ChocolArm64.Instruction EmitVectorShrImmOpSx(Context, ShrImmFlags.Accumulate); } + public static void Uqrshrn_S(AILEmitterCtx Context) + { + EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarZxZx); + } + + public static void Uqrshrn_V(AILEmitterCtx Context) + { + EmitRoundShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorZxZx); + } + + public static void Uqshrn_S(AILEmitterCtx Context) + { + EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.ScalarZxZx); + } + + public static void Uqshrn_V(AILEmitterCtx Context) + { + EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.VectorZxZx); + } + public static void Urshr_S(AILEmitterCtx Context) { EmitScalarShrImmOpZx(Context, ShrImmFlags.Round); @@ -367,61 +408,153 @@ namespace ChocolArm64.Instruction } } - // Dst_64 = (Int(Src_64, Signed) + RoundConst) >> Shift; - private static void EmitShrImm_64( - AILEmitterCtx Context, - bool Signed, - long RoundConst, - int Shift) + private static void EmitVectorShrImmNarrowOpZx(AILEmitterCtx Context, bool Round) { - if (((AOpCodeSimd)Context.CurrOp).Size < 3) + AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + + int Shift = GetImmShr(Op); + + long RoundConst = 1L << (Shift - 1); + + int Elems = 8 >> Op.Size; + + int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; + + if (Part != 0) { - throw new InvalidOperationException(); + Context.EmitLdvec(Op.Rd); + Context.EmitStvectmp(); } - Context.EmitLdc_I8(RoundConst); - Context.EmitLdc_I4(Shift); + for (int Index = 0; Index < Elems; Index++) + { + EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size + 1); - ASoftFallback.EmitCall(Context, Signed - ? nameof(ASoftFallback.SignedShrImm_64) - : nameof(ASoftFallback.UnsignedShrImm_64)); + if (Round) + { + Context.EmitLdc_I8(RoundConst); + + Context.Emit(OpCodes.Add); + } + + Context.EmitLdc_I4(Shift); + + Context.Emit(OpCodes.Shr_Un); + + EmitVectorInsertTmp(Context, Part + Index, Op.Size); + } + + Context.EmitLdvectmp(); + Context.EmitStvec(Op.Rd); + + if (Part == 0) + { + EmitVectorZeroUpper(Context, Op.Rd); + } } - private static void EmitVectorShImmNarrowBinarySx(AILEmitterCtx Context, Action Emit, int Imm) + [Flags] + private enum ShrImmSaturatingNarrowFlags { - EmitVectorShImmNarrowBinaryOp(Context, Emit, Imm, true); + Scalar = 1 << 0, + SignedSrc = 1 << 1, + SignedDst = 1 << 2, + + Round = 1 << 3, + + ScalarSxSx = Scalar | SignedSrc | SignedDst, + ScalarSxZx = Scalar | SignedSrc, + ScalarZxZx = Scalar, + + VectorSxSx = SignedSrc | SignedDst, + VectorSxZx = SignedSrc, + VectorZxZx = 0 } - private static void EmitVectorShImmNarrowBinaryZx(AILEmitterCtx Context, Action Emit, int Imm) + private static void EmitRoundShrImmSaturatingNarrowOp(AILEmitterCtx Context, ShrImmSaturatingNarrowFlags Flags) { - EmitVectorShImmNarrowBinaryOp(Context, Emit, Imm, false); + EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.Round | Flags); } - private static void EmitVectorShImmNarrowBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed) + private static void EmitShrImmSaturatingNarrowOp(AILEmitterCtx Context, ShrImmSaturatingNarrowFlags Flags) { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; - int Elems = 8 >> Op.Size; + bool Scalar = (Flags & ShrImmSaturatingNarrowFlags.Scalar) != 0; + bool SignedSrc = (Flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0; + bool SignedDst = (Flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0; + bool Round = (Flags & ShrImmSaturatingNarrowFlags.Round) != 0; - int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; + int Shift = GetImmShr(Op); + + long RoundConst = 1L << (Shift - 1); + + int Elems = !Scalar ? 8 >> Op.Size : 1; + + int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0; + + if (Scalar) + { + EmitVectorZeroLowerTmp(Context); + } + + if (Part != 0) + { + Context.EmitLdvec(Op.Rd); + Context.EmitStvectmp(); + } for (int Index = 0; Index < Elems; Index++) { - EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, Signed); + EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc); - Context.EmitLdc_I4(Imm); + if (Op.Size <= 1 || !Round) + { + if (Round) + { + Context.EmitLdc_I8(RoundConst); - Emit(); + Context.Emit(OpCodes.Add); + } - EmitVectorInsert(Context, Op.Rd, Part + Index, Op.Size); + Context.EmitLdc_I4(Shift); + + Context.Emit(SignedSrc ? OpCodes.Shr : OpCodes.Shr_Un); + } + else /* if (Op.Size == 2 && Round) */ + { + EmitShrImm_64(Context, SignedSrc, RoundConst, Shift); // Shift <= 32 + } + + EmitSatQ(Context, Op.Size, SignedSrc, SignedDst); + + EmitVectorInsertTmp(Context, Part + Index, Op.Size); } + Context.EmitLdvectmp(); + Context.EmitStvec(Op.Rd); + if (Part == 0) { EmitVectorZeroUpper(Context, Op.Rd); } } + // Dst_64 = (Int(Src_64, Signed) + RoundConst) >> Shift; + private static void EmitShrImm_64( + AILEmitterCtx Context, + bool Signed, + long RoundConst, + int Shift) + { + Context.EmitLdc_I8(RoundConst); + Context.EmitLdc_I4(Shift); + + ASoftFallback.EmitCall(Context, Signed + ? nameof(ASoftFallback.SignedShrImm_64) + : nameof(ASoftFallback.UnsignedShrImm_64)); + } + private static void EmitVectorShImmWidenBinarySx(AILEmitterCtx Context, Action Emit, int Imm) { EmitVectorShImmWidenBinaryOp(Context, Emit, Imm, true); |
