aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64
diff options
context:
space:
mode:
Diffstat (limited to 'ChocolArm64')
-rw-r--r--ChocolArm64/AOpCodeTable.cs7
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs110
2 files changed, 117 insertions, 0 deletions
diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs
index c28abe5c..ea16ec00 100644
--- a/ChocolArm64/AOpCodeTable.cs
+++ b/ChocolArm64/AOpCodeTable.cs
@@ -208,10 +208,17 @@ namespace ChocolArm64
Set("000111110x1xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fnmsub_S, typeof(AOpCodeSimdReg));
Set("000111100x1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg));
Set("000111100x100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
+ Set("0>1011100<100001100010xxxxxxxxxx", AInstEmit.Frinta_V, typeof(AOpCodeSimd));
+ Set("000111100x100111110000xxxxxxxxxx", AInstEmit.Frinti_S, typeof(AOpCodeSimd));
+ Set("0>1011101<100001100110xxxxxxxxxx", AInstEmit.Frinti_V, typeof(AOpCodeSimd));
Set("000111100x100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd));
Set("0>0011100<100001100110xxxxxxxxxx", AInstEmit.Frintm_V, typeof(AOpCodeSimd));
+ Set("000111100x100100010000xxxxxxxxxx", AInstEmit.Frintn_S, typeof(AOpCodeSimd));
+ Set("0>0011100<100001100010xxxxxxxxxx", AInstEmit.Frintn_V, typeof(AOpCodeSimd));
Set("000111100x100100110000xxxxxxxxxx", AInstEmit.Frintp_S, typeof(AOpCodeSimd));
+ Set("0>0011101<100001100010xxxxxxxxxx", AInstEmit.Frintp_V, typeof(AOpCodeSimd));
Set("000111100x100111010000xxxxxxxxxx", AInstEmit.Frintx_S, typeof(AOpCodeSimd));
+ Set("0>1011100<100001100110xxxxxxxxxx", AInstEmit.Frintx_V, typeof(AOpCodeSimd));
Set("000111100x100001110000xxxxxxxxxx", AInstEmit.Fsqrt_S, typeof(AOpCodeSimd));
Set("000111100x1xxxxx001110xxxxxxxxxx", AInstEmit.Fsub_S, typeof(AOpCodeSimdReg));
Set("0>0011101<1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
index 989b470e..abe47d74 100644
--- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
+++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
@@ -248,6 +248,56 @@ namespace ChocolArm64.Instruction
EmitScalarSetF(Context, Op.Rd, SizeF);
}
+ public static void Frinti_S(AILEmitterCtx Context)
+ {
+ AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
+
+ EmitScalarUnaryOpF(Context, () =>
+ {
+ Context.EmitLdarg(ATranslatedSub.StateArgIdx);
+
+ Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
+
+ if (Op.Size == 0)
+ {
+ ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
+ }
+ else if (Op.Size == 1)
+ {
+ ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ });
+ }
+
+ public static void Frinti_V(AILEmitterCtx Context)
+ {
+ AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
+
+ EmitVectorUnaryOpF(Context, () =>
+ {
+ Context.EmitLdarg(ATranslatedSub.StateArgIdx);
+
+ Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
+
+ if (Op.Size == 2)
+ {
+ ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
+ }
+ else if (Op.Size == 3)
+ {
+ ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ });
+ }
+
public static void Frinta_S(AILEmitterCtx Context)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
@@ -259,6 +309,14 @@ namespace ChocolArm64.Instruction
EmitScalarSetF(Context, Op.Rd, Op.Size);
}
+ public static void Frinta_V(AILEmitterCtx Context)
+ {
+ EmitVectorUnaryOpF(Context, () =>
+ {
+ EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
+ });
+ }
+
public static void Frintm_S(AILEmitterCtx Context)
{
EmitScalarUnaryOpF(Context, () =>
@@ -275,6 +333,25 @@ namespace ChocolArm64.Instruction
});
}
+ public static void Frintn_S(AILEmitterCtx Context)
+ {
+ AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
+
+ EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
+
+ EmitRoundMathCall(Context, MidpointRounding.ToEven);
+
+ EmitScalarSetF(Context, Op.Rd, Op.Size);
+ }
+
+ public static void Frintn_V(AILEmitterCtx Context)
+ {
+ EmitVectorUnaryOpF(Context, () =>
+ {
+ EmitRoundMathCall(Context, MidpointRounding.ToEven);
+ });
+ }
+
public static void Frintp_S(AILEmitterCtx Context)
{
EmitScalarUnaryOpF(Context, () =>
@@ -283,6 +360,14 @@ namespace ChocolArm64.Instruction
});
}
+ public static void Frintp_V(AILEmitterCtx Context)
+ {
+ EmitVectorUnaryOpF(Context, () =>
+ {
+ EmitUnaryMathCall(Context, nameof(Math.Ceiling));
+ });
+ }
+
public static void Frintx_S(AILEmitterCtx Context)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
@@ -308,6 +393,31 @@ namespace ChocolArm64.Instruction
});
}
+ public static void Frintx_V(AILEmitterCtx Context)
+ {
+ AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
+
+ EmitVectorUnaryOpF(Context, () =>
+ {
+ Context.EmitLdarg(ATranslatedSub.StateArgIdx);
+
+ Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
+
+ if (Op.Size == 0)
+ {
+ ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
+ }
+ else if (Op.Size == 1)
+ {
+ ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ });
+ }
+
public static void Fsqrt_S(AILEmitterCtx Context)
{
EmitScalarUnaryOpF(Context, () =>