aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ChocolArm64/Instruction/AInstEmitSimdHelper.cs')
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdHelper.cs79
1 files changed, 36 insertions, 43 deletions
diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
index 161c44ea..a9af3902 100644
--- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
+++ b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
@@ -804,7 +804,7 @@ namespace ChocolArm64.Instruction
ScalarZx = Scalar,
VectorSx = Signed,
- VectorZx = 0,
+ VectorZx = 0
}
public static void EmitScalarSaturatingUnaryOpSx(AILEmitterCtx Context, Action Emit)
@@ -837,7 +837,14 @@ namespace ChocolArm64.Instruction
Emit();
- EmitUnarySignedSatQAbsOrNeg(Context, Op.Size);
+ if (Op.Size <= 2)
+ {
+ EmitSatQ(Context, Op.Size, true, true);
+ }
+ else /* if (Op.Size == 3) */
+ {
+ EmitUnarySignedSatQAbsOrNeg(Context);
+ }
EmitVectorInsertTmp(Context, Index, Op.Size);
}
@@ -853,25 +860,25 @@ namespace ChocolArm64.Instruction
public static void EmitScalarSaturatingBinaryOpSx(AILEmitterCtx Context, SaturatingFlags Flags)
{
- EmitSaturatingBinaryOp(Context, SaturatingFlags.ScalarSx | Flags);
+ EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.ScalarSx | Flags);
}
public static void EmitScalarSaturatingBinaryOpZx(AILEmitterCtx Context, SaturatingFlags Flags)
{
- EmitSaturatingBinaryOp(Context, SaturatingFlags.ScalarZx | Flags);
+ EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.ScalarZx | Flags);
}
public static void EmitVectorSaturatingBinaryOpSx(AILEmitterCtx Context, SaturatingFlags Flags)
{
- EmitSaturatingBinaryOp(Context, SaturatingFlags.VectorSx | Flags);
+ EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.VectorSx | Flags);
}
public static void EmitVectorSaturatingBinaryOpZx(AILEmitterCtx Context, SaturatingFlags Flags)
{
- EmitSaturatingBinaryOp(Context, SaturatingFlags.VectorZx | Flags);
+ EmitSaturatingBinaryOp(Context, () => { }, SaturatingFlags.VectorZx | Flags);
}
- public static void EmitSaturatingBinaryOp(AILEmitterCtx Context, SaturatingFlags Flags)
+ public static void EmitSaturatingBinaryOp(AILEmitterCtx Context, Action Emit, SaturatingFlags Flags)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
@@ -940,6 +947,20 @@ namespace ChocolArm64.Instruction
EmitVectorInsertTmp(Context, Index, Op.Size);
}
}
+ else
+ {
+ for (int Index = 0; Index < Elems; Index++)
+ {
+ EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
+ EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed);
+
+ Emit();
+
+ EmitSatQ(Context, Op.Size, true, Signed);
+
+ EmitVectorInsertTmp(Context, Index, Op.Size);
+ }
+ }
Context.EmitLdvectmp();
Context.EmitStvec(Op.Rd);
@@ -1080,29 +1101,17 @@ namespace ChocolArm64.Instruction
}
}
- // TSrc (8bit, 16bit, 32bit, 64bit) == TDst (8bit, 16bit, 32bit, 64bit); signed.
- public static void EmitUnarySignedSatQAbsOrNeg(AILEmitterCtx Context, int Size)
+ // TSrc (64bit) == TDst (64bit); signed.
+ public static void EmitUnarySignedSatQAbsOrNeg(AILEmitterCtx Context)
{
- int ESize = 8 << Size;
-
- long TMaxValue = (1L << (ESize - 1)) - 1L;
- long TMinValue = -(1L << (ESize - 1));
-
- AILLabel LblFalse = new AILLabel();
-
- Context.Emit(OpCodes.Dup);
- Context.Emit(OpCodes.Neg);
- Context.EmitLdc_I8(TMinValue);
- Context.Emit(OpCodes.Ceq);
- Context.Emit(OpCodes.Brfalse_S, LblFalse);
-
- Context.Emit(OpCodes.Pop);
-
- EmitSetFpsrQCFlag(Context);
+ if (((AOpCodeSimd)Context.CurrOp).Size < 3)
+ {
+ throw new InvalidOperationException();
+ }
- Context.EmitLdc_I8(TMaxValue);
+ Context.EmitLdarg(ATranslatedSub.StateArgIdx);
- Context.MarkLabel(LblFalse);
+ ASoftFallback.EmitCall(Context, nameof(ASoftFallback.UnarySignedSatQAbsOrNeg));
}
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
@@ -1150,22 +1159,6 @@ namespace ChocolArm64.Instruction
: nameof(ASoftFallback.BinaryUnsignedSatQAcc));
}
- public static void EmitSetFpsrQCFlag(AILEmitterCtx Context)
- {
- const int QCFlagBit = 27;
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
- Context.EmitLdarg(ATranslatedSub.StateArgIdx);
- Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpsr));
-
- Context.EmitLdc_I4(1 << QCFlagBit);
-
- Context.Emit(OpCodes.Or);
-
- Context.EmitCallPropSet(typeof(AThreadState), nameof(AThreadState.Fpsr));
- }
-
public static void EmitScalarSet(AILEmitterCtx Context, int Reg, int Size)
{
EmitVectorZeroAll(Context, Reg);