From d77d691381ffa79b18a0df1b898b20b3a098ca1a Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 7 Feb 2018 09:38:43 -0300 Subject: [PATCH 1/3] Implement SSHL instruction, fix exception on FMAX/FMIN, and use a better exception message for undefined/unimplemented instructions --- Ryujinx/Cpu/AOpCodeTable.cs | 1 + Ryujinx/Cpu/Instruction/AInstEmitException.cs | 2 +- Ryujinx/Cpu/Instruction/AInstEmitScalar.cs | 17 ++++++++++++++++- Ryujinx/Cpu/Instruction/AInstEmitSimd.cs | 11 +++++++++-- Ryujinx/Loaders/Executable.cs | 2 -- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs index d15d2e123..1f770c6a1 100644 --- a/Ryujinx/Cpu/AOpCodeTable.cs +++ b/Ryujinx/Cpu/AOpCodeTable.cs @@ -208,6 +208,7 @@ namespace ChocolArm64 Set("0x0011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm)); Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg)); Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg)); + Set("0x001110xx1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg)); Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm)); Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm)); Set("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm)); diff --git a/Ryujinx/Cpu/Instruction/AInstEmitException.cs b/Ryujinx/Cpu/Instruction/AInstEmitException.cs index 6e5665fbc..2f1edf781 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitException.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitException.cs @@ -27,7 +27,7 @@ namespace ChocolArm64.Instruction public static void Und(AILEmitterCtx Context) { - throw new Exception("und inst! " + Context.CurrOp.Position.ToString("x8")); + throw new NotImplementedException($"Undefined instruction at {Context.CurrOp.Position:x16}"); } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs b/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs index fcddb0c98..5085c224e 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs @@ -498,7 +498,22 @@ namespace ChocolArm64.Instruction Context.EmitLdvecsf(Op.Rn); Context.EmitLdvecsf(Op.Rm); - EmitMathOpCall(Context, Name); + MethodInfo MthdInfo; + + if (Op.Size == 0) + { + MthdInfo = typeof(MathF).GetMethod(Name, new Type[] { typeof(float), typeof(float) }); + } + else if (Op.Size == 1) + { + MthdInfo = typeof(Math).GetMethod(Name, new Type[] { typeof(double), typeof(double) }); + } + else + { + throw new InvalidOperationException(); + } + + Context.EmitCall(MthdInfo); Context.EmitStvecsf(Op.Rd); } diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs index 0801716ad..c41703bfb 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs @@ -375,6 +375,8 @@ namespace ChocolArm64.Instruction public static void Smax_V(AILEmitterCtx Context) => EmitVectorSmax(Context); public static void Smin_V(AILEmitterCtx Context) => EmitVectorSmin(Context); + public static void Sshl_V(AILEmitterCtx Context) => EmitVectorSshl(Context); + public static void Sshll_V(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; @@ -737,7 +739,10 @@ namespace ChocolArm64.Instruction EmitVectorBinarySx(Context, () => Context.EmitCall(MthdInfo)); } - private static void EmitVectorUshl(AILEmitterCtx Context) + private static void EmitVectorSshl(AILEmitterCtx Context) => EmitVectorShl(Context, true); + private static void EmitVectorUshl(AILEmitterCtx Context) => EmitVectorShl(Context, false); + + private static void EmitVectorShl(AILEmitterCtx Context, bool Signed) { //This instruction shifts the value on vector A by the number of bits //specified on the signed, lower 8 bits of vector B. If the shift value @@ -772,7 +777,9 @@ namespace ChocolArm64.Instruction Context.Emit(OpCodes.Bge_S, LblShl); Context.Emit(OpCodes.Neg); - EmitShift(OpCodes.Shr_Un); + EmitShift(Signed + ? OpCodes.Shr + : OpCodes.Shr_Un); Context.MarkLabel(LblShl); diff --git a/Ryujinx/Loaders/Executable.cs b/Ryujinx/Loaders/Executable.cs index 4a3d36f57..785a8c723 100644 --- a/Ryujinx/Loaders/Executable.cs +++ b/Ryujinx/Loaders/Executable.cs @@ -7,7 +7,6 @@ namespace Ryujinx.Loaders { class Executable { - private IExecutable NsoData; private AMemory Memory; private ElfDyn[] Dynamic; @@ -17,7 +16,6 @@ namespace Ryujinx.Loaders public Executable(IExecutable Exe, AMemory Memory, long ImageBase) { - this.NsoData = Exe; this.Memory = Memory; this.ImageBase = ImageBase; this.ImageEnd = ImageBase; From 768b5737722280c57c86364c1503ab923203da38 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 7 Feb 2018 19:43:52 -0300 Subject: [PATCH 2/3] Add FMOV (scalar, register) and FCMPE instructions --- Ryujinx/Cpu/AOpCodeTable.cs | 4 +++- Ryujinx/Cpu/Instruction/AInstEmitScalar.cs | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs index 1f770c6a1..344911bce 100644 --- a/Ryujinx/Cpu/AOpCodeTable.cs +++ b/Ryujinx/Cpu/AOpCodeTable.cs @@ -144,6 +144,7 @@ namespace ChocolArm64 Set("0x0011100x1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond)); Set("00011110xx1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg)); + Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond)); Set("00011110xx10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd)); Set("x0011110xx110000000000xxxxxxxxxx", AInstEmit.Fcvtms_S, typeof(AOpCodeSimdCvt)); @@ -162,7 +163,8 @@ namespace ChocolArm64 Set("00011110xx1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg)); Set("0x0011100x1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg)); Set("0x0011111< EmitMathOp3(Context, nameof(Math.Min)); public static void Fmov_S(AILEmitterCtx Context) + { + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + + Context.EmitLdvecsf(Op.Rn); + Context.EmitStvecsf(Op.Rd); + } + + public static void Fmov_Si(AILEmitterCtx Context) { AOpCodeSimdFmov Op = (AOpCodeSimdFmov)Context.CurrOp; From 79f028e410b29a3f808580fcbdc28d87e98daa57 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 7 Feb 2018 20:07:16 -0300 Subject: [PATCH 3/3] Add FMADD and FMSUB instructions --- Ryujinx/Cpu/AOpCodeTable.cs | 2 ++ Ryujinx/Cpu/Decoder/AOpCodeSimdReg.cs | 6 +++-- Ryujinx/Cpu/Instruction/AInstEmitScalar.cs | 31 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs index 344911bce..cf3d11c79 100644 --- a/Ryujinx/Cpu/AOpCodeTable.cs +++ b/Ryujinx/Cpu/AOpCodeTable.cs @@ -157,6 +157,7 @@ namespace ChocolArm64 Set("x0011110xx011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Fix, typeof(AOpCodeSimdCvt)); Set("x0011110xx011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Fix, typeof(AOpCodeSimdCvt)); Set("00011110xx1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg)); + Set("00011111xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg)); @@ -170,6 +171,7 @@ namespace ChocolArm64 Set("x0011110xx100111000000xxxxxxxxxx", AInstEmit.Fmov_Itof, typeof(AOpCodeSimdCvt)); Set("x0011110xx101110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi1, typeof(AOpCodeSimdCvt)); Set("x0011110xx101111000000xxxxxxxxxx", AInstEmit.Fmov_Itof1, typeof(AOpCodeSimdCvt)); + Set("00011111xx0xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fmsub_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx000010xxxxxxxxxx", AInstEmit.Fmul_S, typeof(AOpCodeSimdReg)); Set("0x1011100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); Set("0x0011111<> 16) & 0x1f; Bit3 = ((OpCode >> 3) & 0x1) != 0; + Ra = (OpCode >> 10) & 0x1f; + Rm = (OpCode >> 16) & 0x1f; } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs b/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs index 8822d69e7..ab4c2fd22 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitScalar.cs @@ -258,6 +258,20 @@ namespace ChocolArm64.Instruction public static void Fdiv_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Div); + public static void Fmadd_S(AILEmitterCtx Context) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + Context.EmitLdvecsf(Op.Ra); + Context.EmitLdvecsf(Op.Rn); + Context.EmitLdvecsf(Op.Rm); + + Context.Emit(OpCodes.Mul); + Context.Emit(OpCodes.Add); + + Context.EmitStvecsf(Op.Rd); + } + public static void Fmax_S(AILEmitterCtx Context) => EmitMathOp3(Context, nameof(Math.Max)); public static void Fmin_S(AILEmitterCtx Context) => EmitMathOp3(Context, nameof(Math.Min)); @@ -327,6 +341,23 @@ namespace ChocolArm64.Instruction Context.EmitStvec(Op.Rd); } + public static void Fmsub_S(AILEmitterCtx Context) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + Context.EmitLdvecsf(Op.Ra); + Context.EmitLdvecsf(Op.Rn); + + Context.Emit(OpCodes.Neg); + + Context.EmitLdvecsf(Op.Rm); + + Context.Emit(OpCodes.Mul); + Context.Emit(OpCodes.Sub); + + Context.EmitStvecsf(Op.Rd); + } + public static void Fmul_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Mul); public static void Fneg_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Neg);