diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs index 47caef156a..e66dae022b 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs @@ -826,8 +826,6 @@ namespace ChocolArm64.Instruction int Bytes = Op.GetBitsCount() >> 3; int Elems = !Scalar ? Bytes >> Op.Size : 1; - EmitResetSaturatedFlag(Context); - if (Scalar) { EmitVectorZeroLowerTmp(Context); @@ -851,8 +849,6 @@ namespace ChocolArm64.Instruction { EmitVectorZeroUpper(Context, Op.Rd); } - - EmitUpdateFpsrQCFlag(Context); } public static void EmitScalarSaturatingBinaryOpSx(AILEmitterCtx Context, SaturatingFlags Flags) @@ -890,8 +886,6 @@ namespace ChocolArm64.Instruction int Bytes = Op.GetBitsCount() >> 3; int Elems = !Scalar ? Bytes >> Op.Size : 1; - EmitResetSaturatedFlag(Context); - if (Scalar) { EmitVectorZeroLowerTmp(Context); @@ -901,11 +895,11 @@ namespace ChocolArm64.Instruction { if (Add || Sub) { + EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed); + EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed); + if (Op.Size <= 2) { - EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed); - EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed); - Context.Emit(Add ? OpCodes.Add : OpCodes.Sub); EmitSatQ(Context, Op.Size, true, Signed); @@ -914,29 +908,29 @@ namespace ChocolArm64.Instruction { if (Add) { - EmitBinarySatQAdd(Context, Index, Signed); + EmitBinarySatQAdd(Context, Signed); } else /* if (Sub) */ { - EmitBinarySatQSub(Context, Index, Signed); + EmitBinarySatQSub(Context, Signed); } } } if (Accumulate) { + EmitVectorExtract(Context, Op.Rn, Index, Op.Size, !Signed); + EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed); + if (Op.Size <= 2) { - EmitVectorExtract(Context, Op.Rn, Index, Op.Size, !Signed); - EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed); - Context.Emit(OpCodes.Add); EmitSatQ(Context, Op.Size, true, Signed); } else /* if (Op.Size == 3) */ { - EmitBinarySatQAccumulate(Context, Index, Signed); + EmitBinarySatQAccumulate(Context, Signed); } } @@ -950,8 +944,6 @@ namespace ChocolArm64.Instruction { EmitVectorZeroUpper(Context, Op.Rd); } - - EmitUpdateFpsrQCFlag(Context); } [Flags] @@ -963,10 +955,12 @@ namespace ChocolArm64.Instruction ScalarSxSx = Scalar | SignedSrc | SignedDst, ScalarSxZx = Scalar | SignedSrc, + ScalarZxSx = Scalar | SignedDst, ScalarZxZx = Scalar, VectorSxSx = SignedSrc | SignedDst, VectorSxZx = SignedSrc, + VectorZxSx = SignedDst, VectorZxZx = 0 } @@ -980,6 +974,11 @@ namespace ChocolArm64.Instruction 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); @@ -995,6 +994,11 @@ namespace ChocolArm64.Instruction 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); @@ -1012,8 +1016,6 @@ namespace ChocolArm64.Instruction int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0; - EmitResetSaturatedFlag(Context); - if (Scalar) { EmitVectorZeroLowerTmp(Context); @@ -1043,11 +1045,9 @@ namespace ChocolArm64.Instruction { EmitVectorZeroUpper(Context, Op.Rd); } - - EmitUpdateFpsrQCFlag(Context); } - // TSrc (16bit, 32bit, 64bit) > TDst (8bit, 16bit, 32bit); signed, unsigned. + // TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned). public static void EmitSatQ( AILEmitterCtx Context, int SizeDst, @@ -1059,39 +1059,21 @@ namespace ChocolArm64.Instruction throw new ArgumentOutOfRangeException(nameof(SizeDst)); } - int ESize = 8 << SizeDst; + Context.EmitLdc_I4(SizeDst); + Context.EmitLdarg(ATranslatedSub.StateArgIdx); - long TMaxValue = SignedDst ? (1 << (ESize - 1)) - 1 : (1L << ESize) - 1L; - long TMinValue = SignedDst ? -(1 << (ESize - 1)) : 0L; - - AILLabel LblLe = new AILLabel(); - AILLabel LblGeEnd = new AILLabel(); - - Context.Emit(OpCodes.Dup); - Context.EmitLdc_I8(TMaxValue); - Context.Emit(SignedSrc ? OpCodes.Ble_S : OpCodes.Ble_Un_S, LblLe); - - Context.Emit(OpCodes.Pop); - - EmitSetSaturatedFlag(Context); - - Context.EmitLdc_I8(TMaxValue); - - Context.Emit(OpCodes.Br_S, LblGeEnd); - - Context.MarkLabel(LblLe); - - Context.Emit(OpCodes.Dup); - Context.EmitLdc_I8(TMinValue); - Context.Emit(SignedSrc ? OpCodes.Bge_S : OpCodes.Bge_Un_S, LblGeEnd); - - Context.Emit(OpCodes.Pop); - - EmitSetSaturatedFlag(Context); - - Context.EmitLdc_I8(TMinValue); - - Context.MarkLabel(LblGeEnd); + if (SignedSrc) + { + ASoftFallback.EmitCall(Context, SignedDst + ? nameof(ASoftFallback.SignedSrcSignedDstSatQ) + : nameof(ASoftFallback.SignedSrcUnsignedDstSatQ)); + } + else + { + ASoftFallback.EmitCall(Context, SignedDst + ? nameof(ASoftFallback.UnsignedSrcSignedDstSatQ) + : nameof(ASoftFallback.UnsignedSrcUnsignedDstSatQ)); + } } // TSrc (8bit, 16bit, 32bit, 64bit) == TDst (8bit, 16bit, 32bit, 64bit); signed. @@ -1112,7 +1094,7 @@ namespace ChocolArm64.Instruction Context.Emit(OpCodes.Pop); - EmitSetSaturatedFlag(Context); + EmitSetFpsrQCFlag(Context); Context.EmitLdc_I8(TMaxValue); @@ -1120,17 +1102,13 @@ namespace ChocolArm64.Instruction } // TSrcs (64bit) == TDst (64bit); signed, unsigned. - public static void EmitBinarySatQAdd(AILEmitterCtx Context, int Index, bool Signed) + public static void EmitBinarySatQAdd(AILEmitterCtx Context, bool Signed) { - AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; - - if (Op.Size < 3) + if (((AOpCodeSimdReg)Context.CurrOp).Size < 3) { throw new InvalidOperationException(); } - EmitVectorExtract(Context, Op.Rn, Index, 3, Signed); - EmitVectorExtract(Context, Op.Rm, Index, 3, Signed); Context.EmitLdarg(ATranslatedSub.StateArgIdx); ASoftFallback.EmitCall(Context, Signed @@ -1139,17 +1117,13 @@ namespace ChocolArm64.Instruction } // TSrcs (64bit) == TDst (64bit); signed, unsigned. - public static void EmitBinarySatQSub(AILEmitterCtx Context, int Index, bool Signed) + public static void EmitBinarySatQSub(AILEmitterCtx Context, bool Signed) { - AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; - - if (Op.Size < 3) + if (((AOpCodeSimdReg)Context.CurrOp).Size < 3) { throw new InvalidOperationException(); } - EmitVectorExtract(Context, Op.Rn, Index, 3, Signed); - EmitVectorExtract(Context, Op.Rm, Index, 3, Signed); Context.EmitLdarg(ATranslatedSub.StateArgIdx); ASoftFallback.EmitCall(Context, Signed @@ -1158,17 +1132,13 @@ namespace ChocolArm64.Instruction } // TSrcs (64bit) == TDst (64bit); signed, unsigned. - public static void EmitBinarySatQAccumulate(AILEmitterCtx Context, int Index, bool Signed) + public static void EmitBinarySatQAccumulate(AILEmitterCtx Context, bool Signed) { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - if (Op.Size < 3) + if (((AOpCodeSimd)Context.CurrOp).Size < 3) { throw new InvalidOperationException(); } - EmitVectorExtract(Context, Op.Rn, Index, 3, !Signed); - EmitVectorExtract(Context, Op.Rd, Index, 3, Signed); Context.EmitLdarg(ATranslatedSub.StateArgIdx); ASoftFallback.EmitCall(Context, Signed @@ -1176,19 +1146,7 @@ namespace ChocolArm64.Instruction : nameof(ASoftFallback.BinaryUnsignedSatQAcc)); } - public static void EmitResetSaturatedFlag(AILEmitterCtx Context) - { - Context.EmitLdc_I8(0L); - Context.EmitSttmp(); // Saturated = 0 - } - - public static void EmitSetSaturatedFlag(AILEmitterCtx Context) - { - Context.EmitLdc_I8(1L); - Context.EmitSttmp(); // Saturated = 1 - } - - public static void EmitUpdateFpsrQCFlag(AILEmitterCtx Context) + public static void EmitSetFpsrQCFlag(AILEmitterCtx Context) { const int QCFlagBit = 27; @@ -1197,9 +1155,7 @@ namespace ChocolArm64.Instruction Context.EmitLdarg(ATranslatedSub.StateArgIdx); Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpsr)); - Context.EmitLdtmp(); // Saturated == 0 || Saturated == 1 - Context.Emit(OpCodes.Conv_I4); - Context.EmitLsl(QCFlagBit); + Context.EmitLdc_I4(1 << QCFlagBit); Context.Emit(OpCodes.Or);