From d88b5c762143d42367b9cbcdb48337db482dbed3 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 12 Mar 2018 16:29:06 -0300 Subject: [PATCH 1/8] Fix GetAudioRenderersProcessMasterVolume which was totally wrong --- ChocolArm64/Instruction/AInstEmitSystem.cs | 10 ++- .../OsHle/Services/Aud/IAudioDeviceService.cs | 63 +++++++++++++++++++ .../OsHle/Services/Aud/ServiceAudRen.cs | 13 ++-- 3 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Services/Aud/IAudioDeviceService.cs diff --git a/ChocolArm64/Instruction/AInstEmitSystem.cs b/ChocolArm64/Instruction/AInstEmitSystem.cs index f9d186020..80b566049 100644 --- a/ChocolArm64/Instruction/AInstEmitSystem.cs +++ b/ChocolArm64/Instruction/AInstEmitSystem.cs @@ -89,6 +89,9 @@ namespace ChocolArm64.Instruction //We treat it as no-op here since we don't have any cache being emulated anyway. AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp; + //TODO: We should throw on unimplemented sys instructions here, + //since it causing some problems when the programs expects some values + //that never return. switch (GetPackedId(Op)) { case 0b11_011_0111_0100_001: @@ -97,7 +100,7 @@ namespace ChocolArm64.Instruction for (int Offs = 0; Offs < (4 << AThreadState.DczSizeLog2); Offs += 8) { Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); - Context.EmitLdint(Op.Rt); + Context.EmitLdintzr(Op.Rt); Context.EmitLdc_I(Offs); Context.Emit(OpCodes.Add); @@ -106,8 +109,13 @@ namespace ChocolArm64.Instruction AInstEmitMemoryHelper.EmitWriteCall(Context, 3); } + break; } + + //No-op + case 0b11_011_0111_1110_001: //DC CIVAC + break; } } diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioDeviceService.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioDeviceService.cs new file mode 100644 index 000000000..9ebf140a2 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioDeviceService.cs @@ -0,0 +1,63 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; +using System.Text; + +namespace Ryujinx.Core.OsHle.IpcServices.Aud +{ + class IAudioDevice : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IAudioDevice() + { + m_Commands = new Dictionary() + { + { 0, ListAudioDeviceName }, + { 1, SetAudioDeviceOutputVolume }, + }; + } + + public long ListAudioDeviceName(ServiceCtx Context) + { + string[] Names = new string[] { "FIXME" }; + + Context.ResponseData.Write(Names.Length); + + long Position = Context.Request.ReceiveBuff[0].Position; + long Size = Context.Request.ReceiveBuff[0].Size; + + long BasePosition = Position; + + foreach (string Name in Names) + { + byte[] Buffer = Encoding.ASCII.GetBytes(Name + '\0'); + + if ((Position - BasePosition) + Buffer.Length > Size) + { + break; + } + + AMemoryHelper.WriteBytes(Context.Memory, Position, Buffer); + + Position += Buffer.Length; + } + + return 0; + } + + public long SetAudioDeviceOutputVolume(ServiceCtx Context) + { + float Volume = Context.RequestData.ReadSingle(); + + long Position = Context.Request.SendBuff[0].Position; + long Size = Context.Request.SendBuff[0].Size; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position, (int)Size); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs index 15bda04cc..155d04254 100644 --- a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs +++ b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs @@ -1,3 +1,4 @@ +using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; @@ -15,9 +16,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud { m_Commands = new Dictionary() { - { 0, OpenAudioRenderer }, - { 1, GetAudioRendererWorkBufferSize }, - { 2, GetAudioRenderersProcessMasterVolume } + { 0, OpenAudioRenderer }, + { 1, GetAudioRendererWorkBufferSize }, + { 2, GetAudioDevice } }; } @@ -49,9 +50,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud return 0; } - public long GetAudioRenderersProcessMasterVolume(ServiceCtx Context) + public long GetAudioDevice(ServiceCtx Context) { - Context.ResponseData.Write(0); + long UserId = Context.RequestData.ReadInt64(); + + MakeObject(Context, new IAudioDevice()); return 0; } From 6f4282daf8b5bfa650dc8c43714c7955dc779cd1 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 12 Mar 2018 16:31:09 -0300 Subject: [PATCH 2/8] IAudioDeviceService -> IAudioDevice --- ChocolArm64/Instruction/AInstEmitSystem.cs | 3 --- .../Services/Aud/{IAudioDeviceService.cs => IAudioDevice.cs} | 0 Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs | 1 - 3 files changed, 4 deletions(-) rename Ryujinx.Core/OsHle/Services/Aud/{IAudioDeviceService.cs => IAudioDevice.cs} (100%) diff --git a/ChocolArm64/Instruction/AInstEmitSystem.cs b/ChocolArm64/Instruction/AInstEmitSystem.cs index 80b566049..42a62009b 100644 --- a/ChocolArm64/Instruction/AInstEmitSystem.cs +++ b/ChocolArm64/Instruction/AInstEmitSystem.cs @@ -89,9 +89,6 @@ namespace ChocolArm64.Instruction //We treat it as no-op here since we don't have any cache being emulated anyway. AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp; - //TODO: We should throw on unimplemented sys instructions here, - //since it causing some problems when the programs expects some values - //that never return. switch (GetPackedId(Op)) { case 0b11_011_0111_0100_001: diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioDeviceService.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs similarity index 100% rename from Ryujinx.Core/OsHle/Services/Aud/IAudioDeviceService.cs rename to Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs diff --git a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs index 155d04254..c3a0a8b43 100644 --- a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs +++ b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs @@ -1,4 +1,3 @@ -using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; From 4d90d60119992556b28cde119e9a94b8ac4aebf8 Mon Sep 17 00:00:00 2001 From: emmauss Date: Tue, 13 Mar 2018 23:59:17 +0200 Subject: [PATCH 3/8] stub some hid service functions (#57) --- Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs | 60 +++++++++++++++---- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs index b1f930725..d7b53fc9c 100644 --- a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs +++ b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs @@ -1,5 +1,6 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; +using Ryujinx.Core.Input; using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; @@ -15,17 +16,20 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid { m_Commands = new Dictionary() { - { 0, CreateAppletResource }, - { 11, ActivateTouchScreen }, - { 100, SetSupportedNpadStyleSet }, - { 101, GetSupportedNpadStyleSet }, - { 102, SetSupportedNpadIdType }, - { 103, ActivateNpad }, - { 120, SetNpadJoyHoldType }, - { 121, GetNpadJoyHoldType }, - { 200, GetVibrationDeviceInfo }, - { 203, CreateActiveVibrationDeviceList }, - { 206, SendVibrationValues } + { 0, CreateAppletResource }, + { 11, ActivateTouchScreen }, + { 100, SetSupportedNpadStyleSet }, + { 101, GetSupportedNpadStyleSet }, + { 102, SetSupportedNpadIdType }, + { 103, ActivateNpad }, + { 120, SetNpadJoyHoldType }, + { 122, SetNpadJoyAssignmentModeSingleByDefault }, + { 123, SetNpadJoyAssignmentModeSingle }, + { 124, SetNpadJoyAssignmentModeDual }, + { 125, MergeSingleJoyAsDualJoy }, + { 200, GetVibrationDeviceInfo }, + { 203, CreateActiveVibrationDeviceList }, + { 206, SendVibrationValues } }; } @@ -87,6 +91,40 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid return 0; } + public long SetNpadJoyAssignmentModeSingleByDefault(ServiceCtx Context) + { + HidControllerId HidControllerId = (HidControllerId)Context.RequestData.ReadInt32(); + long AppletUserResourseId = Context.RequestData.ReadInt64(); + + return 0; + } + + public long SetNpadJoyAssignmentModeSingle(ServiceCtx Context) + { + HidControllerId HidControllerId = (HidControllerId)Context.RequestData.ReadInt32(); + long AppletUserResourseId = Context.RequestData.ReadInt64(); + long NpadJoyDeviceType = Context.RequestData.ReadInt64(); + + return 0; + } + + public long SetNpadJoyAssignmentModeDual(ServiceCtx Context) + { + HidControllerId HidControllerId = (HidControllerId)Context.RequestData.ReadInt32(); + long AppletUserResourseId = Context.RequestData.ReadInt64(); + + return 0; + } + + public long MergeSingleJoyAsDualJoy(ServiceCtx Context) + { + long Unknown0 = Context.RequestData.ReadInt32(); + long Unknown8 = Context.RequestData.ReadInt32(); + long AppletUserResourseId = Context.RequestData.ReadInt64(); + + return 0; + } + public long GetVibrationDeviceInfo(ServiceCtx Context) { int VibrationDeviceHandle = Context.RequestData.ReadInt32(); From 2ed24af756f60391dade07ac371a2cf630628eb3 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 13 Mar 2018 21:24:17 -0300 Subject: [PATCH 4/8] Add pl:u stub, use higher precision on CNTPCT_EL0 register tick count --- ChocolArm64/Instruction/AInstEmitSystem.cs | 1 + ChocolArm64/State/AThreadState.cs | 26 ++++++++++++++++--- Ryujinx.Core/OsHle/Process.cs | 3 +++ Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs | 8 ++++++ .../OsHle/Services/Pl/SharedFontType.cs | 12 +++++++++ 5 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Services/Pl/SharedFontType.cs diff --git a/ChocolArm64/Instruction/AInstEmitSystem.cs b/ChocolArm64/Instruction/AInstEmitSystem.cs index 42a62009b..1c5d02634 100644 --- a/ChocolArm64/Instruction/AInstEmitSystem.cs +++ b/ChocolArm64/Instruction/AInstEmitSystem.cs @@ -30,6 +30,7 @@ namespace ChocolArm64.Instruction case 0b11_011_0100_0100_001: PropName = nameof(AThreadState.Fpsr); break; case 0b11_011_1101_0000_010: PropName = nameof(AThreadState.TpidrEl0); break; case 0b11_011_1101_0000_011: PropName = nameof(AThreadState.Tpidr); break; + case 0b11_011_1110_0000_000: PropName = nameof(AThreadState.CntfrqEl0); break; case 0b11_011_1110_0000_001: PropName = nameof(AThreadState.CntpctEl0); break; default: throw new NotImplementedException($"Unknown MRS at {Op.Position:x16}"); diff --git a/ChocolArm64/State/AThreadState.cs b/ChocolArm64/State/AThreadState.cs index ec8621b89..6f3f62f69 100644 --- a/ChocolArm64/State/AThreadState.cs +++ b/ChocolArm64/State/AThreadState.cs @@ -1,5 +1,6 @@ using ChocolArm64.Events; using System; +using System.Diagnostics; namespace ChocolArm64.State { @@ -40,15 +41,34 @@ namespace ChocolArm64.State public uint CtrEl0 => 0x8444c004; public uint DczidEl0 => 0x00000004; - private const ulong TicksPerS = 19_200_000; - private const ulong TicksPerMS = TicksPerS / 1_000; + public ulong CntfrqEl0 { get; set; } + public ulong CntpctEl0 + { + get + { + double Ticks = TickCounter.ElapsedTicks * HostTickFreq; - public ulong CntpctEl0 => (ulong)Environment.TickCount * TicksPerMS; + return (ulong)(Ticks * CntfrqEl0); + } + } public event EventHandler Break; public event EventHandler SvcCall; public event EventHandler Undefined; + private static Stopwatch TickCounter; + + private static double HostTickFreq; + + static AThreadState() + { + HostTickFreq = 1.0 / Stopwatch.Frequency; + + TickCounter = new Stopwatch(); + + TickCounter.Start(); + } + internal void OnBreak(int Imm) { Break?.Invoke(this, new AInstExceptionEventArgs(Imm)); diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index a8719e1c2..239b19803 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -17,6 +17,8 @@ namespace Ryujinx.Core.OsHle private const int TlsSize = 0x200; private const int TotalTlsSlots = 32; + private const int TickFreq = 19_200_000; + private Switch Ns; public bool NeedsHbAbi { get; private set; } @@ -197,6 +199,7 @@ namespace Ryujinx.Core.OsHle Thread.ThreadState.Undefined += UndefinedHandler; Thread.ThreadState.ProcessId = ProcessId; Thread.ThreadState.ThreadId = ThreadId; + Thread.ThreadState.CntfrqEl0 = TickFreq; Thread.ThreadState.Tpidr = Tpidr; Thread.ThreadState.X0 = (ulong)ArgsPtr; Thread.ThreadState.X1 = (ulong)Handle; diff --git a/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs b/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs index bb795f3f4..9a6177993 100644 --- a/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs +++ b/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs @@ -13,6 +13,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Pl { m_Commands = new Dictionary() { + { 0, RequestLoad }, { 1, GetLoadState }, { 2, GetFontSize }, { 3, GetSharedMemoryAddressOffset }, @@ -20,6 +21,13 @@ namespace Ryujinx.Core.OsHle.IpcServices.Pl }; } + public long RequestLoad(ServiceCtx Context) + { + SharedFontType FontType = (SharedFontType)Context.RequestData.ReadInt32(); + + return 0; + } + public long GetLoadState(ServiceCtx Context) { Context.ResponseData.Write(1); //Loaded diff --git a/Ryujinx.Core/OsHle/Services/Pl/SharedFontType.cs b/Ryujinx.Core/OsHle/Services/Pl/SharedFontType.cs new file mode 100644 index 000000000..29fe02b8a --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Pl/SharedFontType.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.Core.OsHle.IpcServices.Pl +{ + enum SharedFontType + { + JapanUsEurope = 0, + SimplifiedChinese = 1, + SimplifiedChineseEx = 2, + TraditionalChinese = 3, + Korean = 4, + NintendoEx = 5 + } +} \ No newline at end of file From 19564e570baab98754cb808c704fbd9c924abc60 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 13 Mar 2018 21:26:14 -0300 Subject: [PATCH 5/8] Stub StartSixAxisSensor --- Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs index d7b53fc9c..6735c6ad2 100644 --- a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs +++ b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs @@ -18,6 +18,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid { { 0, CreateAppletResource }, { 11, ActivateTouchScreen }, + { 66, StartSixAxisSensor }, { 100, SetSupportedNpadStyleSet }, { 101, GetSupportedNpadStyleSet }, { 102, SetSupportedNpadIdType }, @@ -47,6 +48,15 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid return 0; } + public long StartSixAxisSensor(ServiceCtx Context) + { + int Handle = Context.RequestData.ReadInt32(); + + long AppletResourceUserId = Context.RequestData.ReadInt64(); + + return 0; + } + public long GetSupportedNpadStyleSet(ServiceCtx Context) { Context.ResponseData.Write(0); From 553ba659c40013cde0198c2bdd10b31bdd6f3d97 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 14 Mar 2018 00:12:05 -0300 Subject: [PATCH 6/8] Add CRC32 instruction and SLI (vector) --- ChocolArm64/AOpCodeTable.cs | 9 +++ ChocolArm64/Instruction/AInstEmitHash.cs | 74 ++++++++++++++++++ ChocolArm64/Instruction/AInstEmitSimdShift.cs | 54 ++++++++++--- ChocolArm64/Instruction/ASoftFallback.cs | 78 +++++++++++++++++++ 4 files changed, 205 insertions(+), 10 deletions(-) create mode 100644 ChocolArm64/Instruction/AInstEmitHash.cs diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 60646d0ee..d32bd9cd2 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -42,6 +42,14 @@ namespace ChocolArm64 Set("x1111010010xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ccmp, typeof(AOpCodeCcmpReg)); Set("11010101000000110011xxxx01011111", AInstEmit.Clrex, typeof(AOpCodeSystem)); Set("x101101011000000000100xxxxxxxxxx", AInstEmit.Clz, typeof(AOpCodeAlu)); + Set("x0011010110xxxxx010000xxxxxxxxxx", AInstEmit.Crc32b, typeof(AOpCodeAluRs)); + Set("x0011010110xxxxx010001xxxxxxxxxx", AInstEmit.Crc32h, typeof(AOpCodeAluRs)); + Set("x0011010110xxxxx010010xxxxxxxxxx", AInstEmit.Crc32w, typeof(AOpCodeAluRs)); + Set("x0011010110xxxxx010011xxxxxxxxxx", AInstEmit.Crc32x, typeof(AOpCodeAluRs)); + Set("x0011010110xxxxx010100xxxxxxxxxx", AInstEmit.Crc32cb, typeof(AOpCodeAluRs)); + Set("x0011010110xxxxx010101xxxxxxxxxx", AInstEmit.Crc32ch, typeof(AOpCodeAluRs)); + Set("x0011010110xxxxx010110xxxxxxxxxx", AInstEmit.Crc32cw, typeof(AOpCodeAluRs)); + Set("x0011010110xxxxx010111xxxxxxxxxx", AInstEmit.Crc32cx, typeof(AOpCodeAluRs)); Set("x0011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csel, typeof(AOpCodeCsel)); Set("x0011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csinc, typeof(AOpCodeCsel)); Set("x1011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csinv, typeof(AOpCodeCsel)); @@ -243,6 +251,7 @@ namespace ChocolArm64 Set("0x0011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm)); Set("0x101110<<100001001110xxxxxxxxxx", AInstEmit.Shll_V, typeof(AOpCodeSimd)); Set("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm)); + Set("0x1011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Sli_V, typeof(AOpCodeSimdShImm)); Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg)); Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg)); Set("0x001110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Smlal_V, typeof(AOpCodeSimdReg)); diff --git a/ChocolArm64/Instruction/AInstEmitHash.cs b/ChocolArm64/Instruction/AInstEmitHash.cs new file mode 100644 index 000000000..fd98f5632 --- /dev/null +++ b/ChocolArm64/Instruction/AInstEmitHash.cs @@ -0,0 +1,74 @@ +using ChocolArm64.Decoder; +using ChocolArm64.State; +using ChocolArm64.Translation; +using System.Reflection.Emit; + +namespace ChocolArm64.Instruction +{ + static partial class AInstEmit + { + + public static void Crc32b(AILEmitterCtx Context) + { + EmitCrc32(Context, nameof(ASoftFallback.Crc32b)); + } + + public static void Crc32h(AILEmitterCtx Context) + { + EmitCrc32(Context, nameof(ASoftFallback.Crc32h)); + } + + public static void Crc32w(AILEmitterCtx Context) + { + EmitCrc32(Context, nameof(ASoftFallback.Crc32w)); + } + + public static void Crc32x(AILEmitterCtx Context) + { + EmitCrc32(Context, nameof(ASoftFallback.Crc32x)); + } + + public static void Crc32cb(AILEmitterCtx Context) + { + EmitCrc32(Context, nameof(ASoftFallback.Crc32cb)); + } + + public static void Crc32ch(AILEmitterCtx Context) + { + EmitCrc32(Context, nameof(ASoftFallback.Crc32ch)); + } + + public static void Crc32cw(AILEmitterCtx Context) + { + EmitCrc32(Context, nameof(ASoftFallback.Crc32cw)); + } + + public static void Crc32cx(AILEmitterCtx Context) + { + EmitCrc32(Context, nameof(ASoftFallback.Crc32cx)); + } + + private static void EmitCrc32(AILEmitterCtx Context, string Name) + { + AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp; + + Context.EmitLdintzr(Op.Rn); + + if (Op.RegisterSize != ARegisterSize.Int32) + { + Context.Emit(OpCodes.Conv_U4); + } + + Context.EmitLdintzr(Op.Rm); + + ASoftFallback.EmitCall(Context, Name); + + if (Op.RegisterSize != ARegisterSize.Int32) + { + Context.Emit(OpCodes.Conv_U8); + } + + Context.EmitStintzr(Op.Rd); + } + } +} \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs index bb8a8f178..bffed57ed 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdShift.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdShift.cs @@ -29,7 +29,7 @@ namespace ChocolArm64.Instruction int Shift = Op.Imm - (8 << Op.Size); - EmitVectorBinaryShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift); + EmitVectorShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift); } public static void Shll_V(AILEmitterCtx Context) @@ -50,6 +50,40 @@ namespace ChocolArm64.Instruction EmitVectorShImmNarrowBinaryZx(Context, () => Context.Emit(OpCodes.Shr_Un), Shift); } + public static void Sli_V(AILEmitterCtx Context) + { + AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + int Shift = Op.Imm - (8 << Op.Size); + + ulong Mask = ulong.MaxValue >> (64 - Shift); + + for (int Index = 0; Index < (Bytes >> Op.Size); Index++) + { + EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size); + + Context.EmitLdc_I4(Shift); + + Context.Emit(OpCodes.Shl); + + EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size); + + Context.EmitLdc_I8((long)Mask); + + Context.Emit(OpCodes.And); + Context.Emit(OpCodes.Or); + + EmitVectorInsert(Context, Op.Rd, Index, Op.Size); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + public static void Sshl_V(AILEmitterCtx Context) { EmitVectorShl(Context, Signed: true); @@ -83,7 +117,7 @@ namespace ChocolArm64.Instruction int Shift = (8 << (Op.Size + 1)) - Op.Imm; - EmitVectorBinaryShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift); + EmitVectorShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift); } public static void Ssra_V(AILEmitterCtx Context) @@ -98,7 +132,7 @@ namespace ChocolArm64.Instruction Context.Emit(OpCodes.Add); }; - EmitVectorTernaryShImmBinarySx(Context, Emit, Shift); + EmitVectorShImmTernarySx(Context, Emit, Shift); } public static void Ushl_V(AILEmitterCtx Context) @@ -217,22 +251,22 @@ namespace ChocolArm64.Instruction } } - private static void EmitVectorBinaryShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm) + private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm) { - EmitVectorShImmBinaryOp(Context, Emit, Imm, false, true); + EmitVectorShImmOp(Context, Emit, Imm, false, true); } - private static void EmitVectorTernaryShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm) + private static void EmitVectorShImmTernarySx(AILEmitterCtx Context, Action Emit, int Imm) { - EmitVectorShImmBinaryOp(Context, Emit, Imm, true, true); + EmitVectorShImmOp(Context, Emit, Imm, true, true); } - private static void EmitVectorBinaryShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm) + private static void EmitVectorShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm) { - EmitVectorShImmBinaryOp(Context, Emit, Imm, false, false); + EmitVectorShImmOp(Context, Emit, Imm, false, false); } - private static void EmitVectorShImmBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Ternary, bool Signed) + private static void EmitVectorShImmOp(AILEmitterCtx Context, Action Emit, int Imm, bool Ternary, bool Signed) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs index 797d81573..7e5b3dba2 100644 --- a/ChocolArm64/Instruction/ASoftFallback.cs +++ b/ChocolArm64/Instruction/ASoftFallback.cs @@ -38,6 +38,84 @@ namespace ChocolArm64.Instruction return (ulong)Size; } + private const uint Crc32RevPoly = 0xedb88320; + private const uint Crc32cRevPoly = 0x82f63b78; + + public static uint Crc32b(uint Crc, byte Val) => Crc32 (Crc, Crc32RevPoly, Val); + public static uint Crc32h(uint Crc, byte Val) => Crc32h(Crc, Crc32RevPoly, Val); + public static uint Crc32w(uint Crc, byte Val) => Crc32w(Crc, Crc32RevPoly, Val); + public static uint Crc32x(uint Crc, byte Val) => Crc32x(Crc, Crc32RevPoly, Val); + + public static uint Crc32cb(uint Crc, byte Val) => Crc32 (Crc, Crc32cRevPoly, Val); + public static uint Crc32ch(uint Crc, byte Val) => Crc32h(Crc, Crc32cRevPoly, Val); + public static uint Crc32cw(uint Crc, byte Val) => Crc32w(Crc, Crc32cRevPoly, Val); + public static uint Crc32cx(uint Crc, byte Val) => Crc32x(Crc, Crc32cRevPoly, Val); + + private static uint Crc32h(uint Crc, uint Poly, ushort Val) + { + Crc = Crc32(Crc, Poly, (byte)(Val >> 0)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 8)); + + return Crc; + } + + private static uint Crc32w(uint Crc, uint Poly, uint Val) + { + Crc = Crc32(Crc, Poly, (byte)(Val >> 0)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 8)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 16)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 24)); + + return Crc; + } + + private static uint Crc32x(uint Crc, uint Poly, ulong Val) + { + Crc = Crc32(Crc, Poly, (byte)(Val >> 0)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 8)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 16)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 24)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 32)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 40)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 48)); + Crc = Crc32(Crc, Poly, (byte)(Val >> 56)); + + return Crc; + } + + private static uint Crc32(uint Crc, uint Poly, byte Val) + { + Crc ^= Val; + + for (int Bit = 7; Bit >= 0; Bit--) + { + uint Mask = (uint)(-(int)(Crc & 1)); + + Crc = (Crc >> 1) ^ (Poly & Mask); + } + + return Crc; + } + + public static uint ReverseBits8(uint Value) + { + Value = ((Value & 0xaa) >> 1) | ((Value & 0x55) << 1); + Value = ((Value & 0xcc) >> 2) | ((Value & 0x33) << 2); + Value = ((Value & 0xf0) >> 4) | ((Value & 0x0f) << 4); + + return Value; + } + + public static uint ReverseBits16(uint Value) + { + Value = ((Value & 0xaaaa) >> 1) | ((Value & 0x5555) << 1); + Value = ((Value & 0xcccc) >> 2) | ((Value & 0x3333) << 2); + Value = ((Value & 0xf0f0) >> 4) | ((Value & 0x0f0f) << 4); + Value = ((Value & 0xff00) >> 8) | ((Value & 0x00ff) << 8); + + return Value; + } + public static uint ReverseBits32(uint Value) { Value = ((Value & 0xaaaaaaaa) >> 1) | ((Value & 0x55555555) << 1); From d067b4d5e0e7860702bb9a10c832a46d15176fd8 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 14 Mar 2018 00:57:07 -0300 Subject: [PATCH 7/8] Remove unused function from CPU --- ChocolArm64/Instruction/AInstEmitHash.cs | 1 - ChocolArm64/Instruction/ASoftFallback.cs | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/ChocolArm64/Instruction/AInstEmitHash.cs b/ChocolArm64/Instruction/AInstEmitHash.cs index fd98f5632..94e03f6c1 100644 --- a/ChocolArm64/Instruction/AInstEmitHash.cs +++ b/ChocolArm64/Instruction/AInstEmitHash.cs @@ -7,7 +7,6 @@ namespace ChocolArm64.Instruction { static partial class AInstEmit { - public static void Crc32b(AILEmitterCtx Context) { EmitCrc32(Context, nameof(ASoftFallback.Crc32b)); diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs index 7e5b3dba2..f79628ad0 100644 --- a/ChocolArm64/Instruction/ASoftFallback.cs +++ b/ChocolArm64/Instruction/ASoftFallback.cs @@ -97,25 +97,6 @@ namespace ChocolArm64.Instruction return Crc; } - public static uint ReverseBits8(uint Value) - { - Value = ((Value & 0xaa) >> 1) | ((Value & 0x55) << 1); - Value = ((Value & 0xcc) >> 2) | ((Value & 0x33) << 2); - Value = ((Value & 0xf0) >> 4) | ((Value & 0x0f) << 4); - - return Value; - } - - public static uint ReverseBits16(uint Value) - { - Value = ((Value & 0xaaaa) >> 1) | ((Value & 0x5555) << 1); - Value = ((Value & 0xcccc) >> 2) | ((Value & 0x3333) << 2); - Value = ((Value & 0xf0f0) >> 4) | ((Value & 0x0f0f) << 4); - Value = ((Value & 0xff00) >> 8) | ((Value & 0x00ff) << 8); - - return Value; - } - public static uint ReverseBits32(uint Value) { Value = ((Value & 0xaaaaaaaa) >> 1) | ((Value & 0x55555555) << 1); From b50bc46888cf9a8d94ae1590c0941be62a083533 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 14 Mar 2018 01:59:22 -0300 Subject: [PATCH 8/8] CPU fix for the cases using a Mask with shift = 0 --- ChocolArm64/Decoder/AOpCodeSimdImm.cs | 9 ++++++++- ChocolArm64/Instruction/AInstEmitSimdShift.cs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChocolArm64/Decoder/AOpCodeSimdImm.cs b/ChocolArm64/Decoder/AOpCodeSimdImm.cs index 2959aee6d..e7dfe6211 100644 --- a/ChocolArm64/Decoder/AOpCodeSimdImm.cs +++ b/ChocolArm64/Decoder/AOpCodeSimdImm.cs @@ -88,7 +88,14 @@ namespace ChocolArm64.Decoder private static long ShlOnes(long Value, int Shift) { - return Value << Shift | (long)(ulong.MaxValue >> (64 - Shift)); + if (Shift != 0) + { + return Value << Shift | (long)(ulong.MaxValue >> (64 - Shift)); + } + else + { + return Value; + } } } } \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs index bffed57ed..24d35abe4 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdShift.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdShift.cs @@ -58,7 +58,7 @@ namespace ChocolArm64.Instruction int Shift = Op.Imm - (8 << Op.Size); - ulong Mask = ulong.MaxValue >> (64 - Shift); + ulong Mask = Shift != 0 ? ulong.MaxValue >> (64 - Shift) : 0; for (int Index = 0; Index < (Bytes >> Op.Size); Index++) {