aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-02-20 14:39:03 -0300
committergdkchan <gab.dark.100@gmail.com>2018-02-20 14:39:03 -0300
commitb4a1cfde107d6201e549c7493ed5bd794cf2cd62 (patch)
tree0e6d99bc6f67db736a145d817add99609f8cbef7
parent01b753856011540fc7ab247401b6bd49532e8c01 (diff)
Add SMULL (vector), USHR (scalar), FCCMPE, FNMSUB, fixed a some instructions
-rw-r--r--Ryujinx/Cpu/AOpCodeTable.cs5
-rw-r--r--Ryujinx/Cpu/Instruction/AInstEmitAlu.cs10
-rw-r--r--Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs19
-rw-r--r--Ryujinx/Cpu/Instruction/AInstEmitBfm.cs29
-rw-r--r--Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs27
-rw-r--r--Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs71
-rw-r--r--Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs2
-rw-r--r--Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs46
-rw-r--r--Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs71
-rw-r--r--Ryujinx/Cpu/Instruction/ASoftFallback.cs51
10 files changed, 203 insertions, 128 deletions
diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs
index 43a0e63b..01134ee3 100644
--- a/Ryujinx/Cpu/AOpCodeTable.cs
+++ b/Ryujinx/Cpu/AOpCodeTable.cs
@@ -47,6 +47,7 @@ namespace ChocolArm64
Set("x1011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csneg, typeof(AOpCodeCsel));
Set("11010101000000110011xxxx10111111", AInstEmit.Dmb, typeof(AOpCodeSystem));
Set("11010101000000110011xxxx10011111", AInstEmit.Dsb, typeof(AOpCodeSystem));
+ Set("x1001010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eon, typeof(AOpCodeAluRs));
Set("x10100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
Set("x1001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
Set("x00100111x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
@@ -147,6 +148,7 @@ namespace ChocolArm64
Set("00011110xx1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg));
Set("0x0011100x1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg));
Set("00011110xx1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond));
+ Set("00011110xx1xxxxxxxxx01xxxxx1xxxx", AInstEmit.Fccmpe_S, typeof(AOpCodeSimdFcond));
Set("00011110xx1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg));
Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg));
Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond));
@@ -183,6 +185,7 @@ namespace ChocolArm64
Set("0x1011100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg));
Set("0x0011111<<xxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Ve, typeof(AOpCodeSimdRegElem));
Set("00011110xx100001010000xxxxxxxxxx", AInstEmit.Fneg_S, typeof(AOpCodeSimdReg));
+ Set("00011111xx1xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fnmsub_S, typeof(AOpCodeSimdReg));
Set("00011110xx1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg));
Set("00011110xx100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
Set("00011110xx100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd));
@@ -225,6 +228,7 @@ namespace ChocolArm64
Set("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm));
Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg));
Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
+ Set("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg));
Set("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg));
Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
@@ -251,6 +255,7 @@ namespace ChocolArm64
Set("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns));
Set("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
Set("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
+ Set("011111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_S, typeof(AOpCodeSimdShImm));
Set("0x1011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
Set("0x1011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
Set("0x001110xx0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg));
diff --git a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs
index 073a45e7..72903f5b 100644
--- a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs
+++ b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs
@@ -107,6 +107,16 @@ namespace ChocolArm64.Instruction
Context.EmitStintzr(Op.Rd);
}
+ public static void Eon(AILEmitterCtx Context)
+ {
+ EmitDataLoadOpers(Context);
+
+ Context.Emit(OpCodes.Not);
+ Context.Emit(OpCodes.Xor);
+
+ EmitDataStore(Context);
+ }
+
public static void Eor(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Xor);
public static void Extr(AILEmitterCtx Context)
diff --git a/Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs b/Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs
index 57ec25dd..e848742d 100644
--- a/Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs
+++ b/Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs
@@ -145,5 +145,24 @@ namespace ChocolArm64.Instruction
Context.EmitStint(Op.Rd);
}
}
+
+ public static void EmitSetNZCV(AILEmitterCtx Context, int NZCV)
+ {
+ Context.EmitLdc_I4((NZCV >> 0) & 1);
+
+ Context.EmitStflg((int)APState.VBit);
+
+ Context.EmitLdc_I4((NZCV >> 1) & 1);
+
+ Context.EmitStflg((int)APState.CBit);
+
+ Context.EmitLdc_I4((NZCV >> 2) & 1);
+
+ Context.EmitStflg((int)APState.ZBit);
+
+ Context.EmitLdc_I4((NZCV >> 3) & 1);
+
+ Context.EmitStflg((int)APState.NBit);
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx/Cpu/Instruction/AInstEmitBfm.cs b/Ryujinx/Cpu/Instruction/AInstEmitBfm.cs
index 4eff013d..823af738 100644
--- a/Ryujinx/Cpu/Instruction/AInstEmitBfm.cs
+++ b/Ryujinx/Cpu/Instruction/AInstEmitBfm.cs
@@ -36,7 +36,7 @@ namespace ChocolArm64.Instruction
if (Op.Pos + 1 == BitsCount)
{
- EmitBfmShift(Context, OpCodes.Shr);
+ EmitSbfmShift(Context);
}
else if (Op.Pos < Op.Shift)
{
@@ -87,7 +87,7 @@ namespace ChocolArm64.Instruction
if (Op.Pos + 1 == Op.GetBitsCount())
{
- EmitBfmShift(Context, OpCodes.Shr_Un);
+ EmitUbfmShift(Context);
}
else if (Op.Pos < Op.Shift)
{
@@ -166,19 +166,28 @@ namespace ChocolArm64.Instruction
Context.EmitStintzr(Op.Rd);
}
- private static void EmitBfmShift(AILEmitterCtx Context, OpCode ILOp)
+ private static void EmitSbfmShift(AILEmitterCtx Context)
+ {
+ EmitBfmShift(Context, true);
+ }
+
+ private static void EmitUbfmShift(AILEmitterCtx Context)
+ {
+ EmitBfmShift(Context, false);
+ }
+
+ private static void EmitBfmShift(AILEmitterCtx Context, bool Signed)
{
AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
- if (Op.Shift > 0)
- {
- Context.EmitLdintzr(Op.Rn);
- Context.EmitLdc_I4(Op.Shift);
+ Context.EmitLdintzr(Op.Rn);
+ Context.EmitLdc_I4(Op.Shift);
- Context.Emit(ILOp);
+ Context.Emit(Signed
+ ? OpCodes.Shr
+ : OpCodes.Shr_Un);
- Context.EmitStintzr(Op.Rd);
- }
+ Context.EmitStintzr(Op.Rd);
}
private static void EmitBfmLsl(AILEmitterCtx Context)
diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs
index d6ebcc3f..08991a90 100644
--- a/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs
+++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs
@@ -215,6 +215,24 @@ namespace ChocolArm64.Instruction
});
}
+ public static void Fnmsub_S(AILEmitterCtx Context)
+ {
+ AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
+
+ int SizeF = Op.Size & 1;
+
+ EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
+ EmitVectorExtractF(Context, Op.Rm, 0, SizeF);
+
+ Context.Emit(OpCodes.Mul);
+
+ EmitVectorExtractF(Context, Op.Ra, 0, SizeF);
+
+ Context.Emit(OpCodes.Sub);
+
+ EmitScalarSetF(Context, Op.Rd, SizeF);
+ }
+
public static void Frinta_S(AILEmitterCtx Context)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
@@ -282,7 +300,7 @@ namespace ChocolArm64.Instruction
public static void Saddw_V(AILEmitterCtx Context)
{
- EmitVectorWidenBinaryOpSx(Context, () => Context.Emit(OpCodes.Add));
+ EmitVectorWidenRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Add));
}
public static void Smax_V(AILEmitterCtx Context)
@@ -303,6 +321,11 @@ namespace ChocolArm64.Instruction
EmitVectorBinaryOpSx(Context, () => Context.EmitCall(MthdInfo));
}
+ public static void Smull_V(AILEmitterCtx Context)
+ {
+ EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
+ }
+
public static void Sub_S(AILEmitterCtx Context)
{
EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
@@ -333,7 +356,7 @@ namespace ChocolArm64.Instruction
public static void Uaddw_V(AILEmitterCtx Context)
{
- EmitVectorWidenBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
+ EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
}
}
} \ No newline at end of file
diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs
index 92361fbd..97ccf0ab 100644
--- a/Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs
+++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs
@@ -4,6 +4,7 @@ using ChocolArm64.Translation;
using System;
using System.Reflection.Emit;
+using static ChocolArm64.Instruction.AInstEmitAluHelper;
using static ChocolArm64.Instruction.AInstEmitSimdHelper;
namespace ChocolArm64.Instruction
@@ -54,24 +55,9 @@ namespace ChocolArm64.Instruction
Context.EmitCondBranch(LblTrue, Op.Cond);
- //TODO: Share this logic with Ccmp.
- Context.EmitLdc_I4((Op.NZCV >> 0) & 1);
+ EmitSetNZCV(Context, Op.NZCV);
- Context.EmitStflg((int)APState.VBit);
-
- Context.EmitLdc_I4((Op.NZCV >> 1) & 1);
-
- Context.EmitStflg((int)APState.CBit);
-
- Context.EmitLdc_I4((Op.NZCV >> 2) & 1);
-
- Context.EmitStflg((int)APState.ZBit);
-
- Context.EmitLdc_I4((Op.NZCV >> 3) & 1);
-
- Context.EmitStflg((int)APState.NBit);
-
- Context.Emit(OpCodes.Br_S, LblEnd);
+ Context.Emit(OpCodes.Br, LblEnd);
Context.MarkLabel(LblTrue);
@@ -80,12 +66,35 @@ namespace ChocolArm64.Instruction
Context.MarkLabel(LblEnd);
}
+ public static void Fccmpe_S(AILEmitterCtx Context)
+ {
+ Fccmp_S(Context);
+ }
+
public static void Fcmp_S(AILEmitterCtx Context)
{
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false;
+ //Handle NaN case. If any number is NaN, then NZCV = 0011.
+ if (CmpWithZero)
+ {
+ EmitNaNCheck(Context, Op.Rn);
+ }
+ else
+ {
+ EmitNaNCheck(Context, Op.Rn);
+ EmitNaNCheck(Context, Op.Rm);
+
+ Context.Emit(OpCodes.Or);
+ }
+
+ AILLabel LblNaN = new AILLabel();
+ AILLabel LblEnd = new AILLabel();
+
+ Context.Emit(OpCodes.Brtrue_S, LblNaN);
+
void EmitLoadOpers()
{
EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
@@ -102,7 +111,7 @@ namespace ChocolArm64.Instruction
//Z = Rn == Rm
EmitLoadOpers();
-
+
Context.Emit(OpCodes.Ceq);
Context.Emit(OpCodes.Dup);
@@ -123,30 +132,18 @@ namespace ChocolArm64.Instruction
Context.EmitStflg((int)APState.NBit);
- //Handle NaN case. If any number is NaN, then NZCV = 0011.
- AILLabel LblNotNaN = new AILLabel();
-
- if (CmpWithZero)
- {
- EmitNaNCheck(Context, Op.Rn);
- }
- else
- {
- EmitNaNCheck(Context, Op.Rn);
- EmitNaNCheck(Context, Op.Rm);
+ //V = 0
+ Context.EmitLdc_I4(0);
- Context.Emit(OpCodes.Or);
- }
+ Context.EmitStflg((int)APState.VBit);
- Context.Emit(OpCodes.Brfalse_S, LblNotNaN);
+ Context.Emit(OpCodes.Br_S, LblEnd);
- Context.EmitLdc_I4(1);
- Context.EmitLdc_I4(1);
+ Context.MarkLabel(LblNaN);
- Context.EmitStflg((int)APState.CBit);
- Context.EmitStflg((int)APState.VBit);
+ EmitSetNZCV(Context, 0b0011);
- Context.MarkLabel(LblNotNaN);
+ Context.MarkLabel(LblEnd);
}
public static void Fcmpe_S(AILEmitterCtx Context)
diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs
index fbb0dfda..00c2fe9b 100644
--- a/Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs
+++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs
@@ -91,7 +91,7 @@ namespace ChocolArm64.Instruction
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
- EmitVectorExtractSx(Context, Op.Rd, 0, Op.Size + 2);
+ EmitVectorExtractSx(Context, Op.Rn, 0, Op.Size + 2);
EmitFloatCast(Context, Op.Size);
diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs
index 97f28816..20c8be26 100644
--- a/Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs
+++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs
@@ -133,7 +133,7 @@ namespace ChocolArm64.Instruction
public static void EmitScalarOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed)
{
- AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
+ AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
if (Opers.HasFlag(OperFlags.Rd))
{
@@ -147,7 +147,7 @@ namespace ChocolArm64.Instruction
if (Opers.HasFlag(OperFlags.Rm))
{
- EmitVectorExtract(Context, Op.Rm, 0, Op.Size, Signed);
+ EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, 0, Op.Size, Signed);
}
Emit();
@@ -383,17 +383,17 @@ namespace ChocolArm64.Instruction
}
}
- public static void EmitVectorWidenBinaryOpSx(AILEmitterCtx Context, Action Emit)
+ public static void EmitVectorWidenRmBinaryOpSx(AILEmitterCtx Context, Action Emit)
{
- EmitVectorWidenBinaryOp(Context, Emit, true);
+ EmitVectorWidenRmBinaryOp(Context, Emit, true);
}
- public static void EmitVectorWidenBinaryOpZx(AILEmitterCtx Context, Action Emit)
+ public static void EmitVectorWidenRmBinaryOpZx(AILEmitterCtx Context, Action Emit)
{
- EmitVectorWidenBinaryOp(Context, Emit, false);
+ EmitVectorWidenRmBinaryOp(Context, Emit, false);
}
- public static void EmitVectorWidenBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed)
+ public static void EmitVectorWidenRmBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed)
{
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
@@ -415,6 +415,38 @@ namespace ChocolArm64.Instruction
Context.EmitStvec(Op.Rd);
}
+ public static void EmitVectorWidenRnRmBinaryOpSx(AILEmitterCtx Context, Action Emit)
+ {
+ EmitVectorWidenRnRmBinaryOp(Context, Emit, true);
+ }
+
+ public static void EmitVectorWidenRnRmBinaryOpZx(AILEmitterCtx Context, Action Emit)
+ {
+ EmitVectorWidenRnRmBinaryOp(Context, Emit, false);
+ }
+
+ public static void EmitVectorWidenRnRmBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed)
+ {
+ AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
+
+ int Elems = 8 >> Op.Size;
+
+ int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
+
+ for (int Index = 0; Index < Elems; Index++)
+ {
+ EmitVectorExtract(Context, Op.Rn, Part + Index, Op.Size, Signed);
+ EmitVectorExtract(Context, Op.Rm, Part + Index, Op.Size, Signed);
+
+ Emit();
+
+ EmitVectorInsertTmp(Context, Index, Op.Size + 1);
+ }
+
+ Context.EmitLdvectmp();
+ Context.EmitStvec(Op.Rd);
+ }
+
public static void EmitScalarSet(AILEmitterCtx Context, int Reg, int Size)
{
EmitVectorZeroAll(Context, Reg);
diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs
index 16564234..8740ba4d 100644
--- a/Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs
+++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs
@@ -10,15 +10,6 @@ namespace ChocolArm64.Instruction
{
static partial class AInstEmit
{
- [Flags]
- private enum ShrFlags
- {
- None = 0,
- Signed = 1 << 0,
- Rounding = 1 << 1,
- Accumulate = 1 << 2
- }
-
public static void Shl_S(AILEmitterCtx Context)
{
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
@@ -100,14 +91,43 @@ namespace ChocolArm64.Instruction
EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
}
+ public static void Ushr_S(AILEmitterCtx Context)
+ {
+ AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
+
+ EmitScalarUnaryOpZx(Context, () =>
+ {
+ Context.EmitLdc_I4(GetImmShr(Op));
+
+ Context.Emit(OpCodes.Shr_Un);
+ });
+ }
+
public static void Ushr_V(AILEmitterCtx Context)
{
- EmitVectorShr(Context, ShrFlags.None);
+ AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
+
+ EmitVectorUnaryOpZx(Context, () =>
+ {
+ Context.EmitLdc_I4(GetImmShr(Op));
+
+ Context.Emit(OpCodes.Shr_Un);
+ });
}
public static void Usra_V(AILEmitterCtx Context)
{
- EmitVectorShr(Context, ShrFlags.Accumulate);
+ AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
+
+ Action Emit = () =>
+ {
+ Context.EmitLdc_I4(GetImmShr(Op));
+
+ Context.Emit(OpCodes.Shr_Un);
+ Context.Emit(OpCodes.Add);
+ };
+
+ EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false);
}
private static void EmitVectorShl(AILEmitterCtx Context, bool Signed)
@@ -173,35 +193,6 @@ namespace ChocolArm64.Instruction
}
}
- private static void EmitVectorShr(AILEmitterCtx Context, ShrFlags Flags)
- {
- AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
-
- int Shift = (8 << (Op.Size + 1)) - Op.Imm;
-
- if (Flags.HasFlag(ShrFlags.Accumulate))
- {
- Action Emit = () =>
- {
- Context.EmitLdc_I4(Shift);
-
- Context.Emit(OpCodes.Shr_Un);
- Context.Emit(OpCodes.Add);
- };
-
- EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false);
- }
- else
- {
- EmitVectorUnaryOpZx(Context, () =>
- {
- Context.EmitLdc_I4(Shift);
-
- Context.Emit(OpCodes.Shr_Un);
- });
- }
- }
-
private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
{
EmitVectorShImmBinaryOp(Context, Emit, Imm, true);
diff --git a/Ryujinx/Cpu/Instruction/ASoftFallback.cs b/Ryujinx/Cpu/Instruction/ASoftFallback.cs
index b70d0b4f..a57966ba 100644
--- a/Ryujinx/Cpu/Instruction/ASoftFallback.cs
+++ b/Ryujinx/Cpu/Instruction/ASoftFallback.cs
@@ -1,6 +1,7 @@
using ChocolArm64.State;
using ChocolArm64.Translation;
using System;
+using System.Numerics;
using System.Runtime.CompilerServices;
namespace ChocolArm64.Instruction
@@ -101,6 +102,8 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SatF32ToS32(float Value)
{
+ if (float.IsNaN(Value)) return 0;
+
return Value > int.MaxValue ? int.MaxValue :
Value < int.MinValue ? int.MinValue : (int)Value;
}
@@ -108,6 +111,8 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long SatF32ToS64(float Value)
{
+ if (float.IsNaN(Value)) return 0;
+
return Value > long.MaxValue ? long.MaxValue :
Value < long.MinValue ? long.MinValue : (long)Value;
}
@@ -115,6 +120,8 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint SatF32ToU32(float Value)
{
+ if (float.IsNaN(Value)) return 0;
+
return Value > uint.MaxValue ? uint.MaxValue :
Value < uint.MinValue ? uint.MinValue : (uint)Value;
}
@@ -122,6 +129,8 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong SatF32ToU64(float Value)
{
+ if (float.IsNaN(Value)) return 0;
+
return Value > ulong.MaxValue ? ulong.MaxValue :
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
}
@@ -129,6 +138,8 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SatF64ToS32(double Value)
{
+ if (double.IsNaN(Value)) return 0;
+
return Value > int.MaxValue ? int.MaxValue :
Value < int.MinValue ? int.MinValue : (int)Value;
}
@@ -136,6 +147,8 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long SatF64ToS64(double Value)
{
+ if (double.IsNaN(Value)) return 0;
+
return Value > long.MaxValue ? long.MaxValue :
Value < long.MinValue ? long.MinValue : (long)Value;
}
@@ -143,6 +156,8 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint SatF64ToU32(double Value)
{
+ if (double.IsNaN(Value)) return 0;
+
return Value > uint.MaxValue ? uint.MaxValue :
Value < uint.MinValue ? uint.MinValue : (uint)Value;
}
@@ -150,46 +165,20 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong SatF64ToU64(double Value)
{
+ if (double.IsNaN(Value)) return 0;
+
return Value > ulong.MaxValue ? ulong.MaxValue :
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
}
- public static ulong SMulHi128(ulong LHS, ulong RHS)
+ public static long SMulHi128(long LHS, long RHS)
{
- long LLo = (uint)(LHS >> 0);
- long LHi = (int)(LHS >> 32);
- long RLo = (uint)(RHS >> 0);
- long RHi = (int)(RHS >> 32);
-
- long LHiRHi = LHi * RHi;
- long LHiRLo = LHi * RLo;
- long LLoRHi = LLo * RHi;
- long LLoRLo = LLo * RLo;
-
- long Carry = ((uint)LHiRLo + ((uint)LLoRHi + (LLoRLo >> 32))) >> 32;
-
- long ResHi = LHiRHi + (LHiRLo >> 32) + (LLoRHi >> 32) + Carry;
-
- return (ulong)ResHi;
+ return (long)(BigInteger.Multiply(LHS, RHS) >> 64);
}
public static ulong UMulHi128(ulong LHS, ulong RHS)
{
- ulong LLo = (uint)(LHS >> 0);
- ulong LHi = (uint)(LHS >> 32);
- ulong RLo = (uint)(RHS >> 0);
- ulong RHi = (uint)(RHS >> 32);
-
- ulong LHiRHi = LHi * RHi;
- ulong LHiRLo = LHi * RLo;
- ulong LLoRHi = LLo * RHi;
- ulong LLoRLo = LLo * RLo;
-
- ulong Carry = ((uint)LHiRLo + ((uint)LLoRHi + (LLoRLo >> 32))) >> 32;
-
- ulong ResHi = LHiRHi + (LHiRLo >> 32) + (LLoRHi >> 32) + Carry;
-
- return ResHi;
+ return (ulong)(BigInteger.Multiply(LHS, RHS) >> 64);
}
public static int CountSetBits8(byte Value)