From 2347c44bbf3aec7300da51161b07220c8ab3922b Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 6 Feb 2018 12:15:08 -0300 Subject: [PATCH] Improve access to system registers by using properties, also use exclusive region granularity on exclusive load/stores, and ensure that acquires without releases won't hold the address forever, remove unused ALU rev method --- Ryujinx/Cpu/Instruction/AInstEmitAlu.cs | 11 --- Ryujinx/Cpu/Instruction/AInstEmitSystem.cs | 84 ++++++++++++++----- Ryujinx/Cpu/Memory/AMemory.cs | 19 ++++- Ryujinx/Cpu/State/ACoreType.cs | 8 -- Ryujinx/Cpu/State/ARegisters.cs | 98 ++++------------------ Ryujinx/Cpu/Translation/AILEmitterCtx.cs | 38 ++++++++- Ryujinx/OsHle/Objects/AudIAudioRenderer.cs | 2 +- Ryujinx/OsHle/Process.cs | 4 +- Ryujinx/OsHle/Svc/SvcSystem.cs | 4 +- 9 files changed, 130 insertions(+), 138 deletions(-) delete mode 100644 Ryujinx/Cpu/State/ACoreType.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs index c09b18632..f963f6f7d 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs @@ -175,17 +175,6 @@ namespace ChocolArm64.Instruction Context.EmitStintzr(Op.Rd); } - private static void EmitRev(AILEmitterCtx Context, string Name) - { - AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp; - - Context.EmitLdintzr(Op.Rn); - - ASoftFallback.EmitCall(Context, Name); - - Context.EmitStintzr(Op.Rd); - } - public static void Rorv(AILEmitterCtx Context) { EmitDataLoadRn(Context); diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSystem.cs b/Ryujinx/Cpu/Instruction/AInstEmitSystem.cs index 23a0b6b2d..9a6333cd9 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSystem.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSystem.cs @@ -1,6 +1,8 @@ using ChocolArm64.Decoder; using ChocolArm64.State; using ChocolArm64.Translation; +using System; +using System.Reflection; using System.Reflection.Emit; namespace ChocolArm64.Instruction @@ -13,13 +15,30 @@ namespace ChocolArm64.Instruction Context.EmitLdarg(ATranslatedSub.RegistersArgIdx); - Context.EmitLdc_I4(Op.Op0); - Context.EmitLdc_I4(Op.Op1); - Context.EmitLdc_I4(Op.CRn); - Context.EmitLdc_I4(Op.CRm); - Context.EmitLdc_I4(Op.Op2); + string PropName; - Context.EmitCall(typeof(ARegisters), nameof(ARegisters.GetSystemReg)); + switch (GetPackedId(Op)) + { + case 0b11_011_0000_0000_001: PropName = nameof(ARegisters.CtrEl0); break; + case 0b11_011_0000_0000_111: PropName = nameof(ARegisters.DczidEl0); break; + case 0b11_011_0100_0100_000: PropName = nameof(ARegisters.Fpcr); break; + case 0b11_011_0100_0100_001: PropName = nameof(ARegisters.Fpsr); break; + case 0b11_011_1101_0000_010: PropName = nameof(ARegisters.TpidrEl0); break; + case 0b11_011_1101_0000_011: PropName = nameof(ARegisters.Tpidr); break; + case 0b11_011_1110_0000_001: PropName = nameof(ARegisters.CntpctEl0); break; + + default: throw new NotImplementedException($"Unknown MRS at {Op.Position:x16}"); + } + + Context.EmitCallPropGet(typeof(ARegisters), PropName); + + PropertyInfo PropInfo = typeof(ARegisters).GetProperty(PropName); + + if (PropInfo.PropertyType != typeof(long) && + PropInfo.PropertyType != typeof(ulong)) + { + Context.Emit(OpCodes.Conv_U8); + } Context.EmitStintzr(Op.Rt); } @@ -29,15 +48,28 @@ namespace ChocolArm64.Instruction AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp; Context.EmitLdarg(ATranslatedSub.RegistersArgIdx); - - Context.EmitLdc_I4(Op.Op0); - Context.EmitLdc_I4(Op.Op1); - Context.EmitLdc_I4(Op.CRn); - Context.EmitLdc_I4(Op.CRm); - Context.EmitLdc_I4(Op.Op2); Context.EmitLdintzr(Op.Rt); - Context.EmitCall(typeof(ARegisters), nameof(ARegisters.SetSystemReg)); + string PropName; + + switch (GetPackedId(Op)) + { + case 0b11_011_0100_0100_000: PropName = nameof(ARegisters.Fpcr); break; + case 0b11_011_0100_0100_001: PropName = nameof(ARegisters.Fpsr); break; + case 0b11_011_1101_0000_010: PropName = nameof(ARegisters.TpidrEl0); break; + + default: throw new NotImplementedException($"Unknown MSR at {Op.Position:x16}"); + } + + PropertyInfo PropInfo = typeof(ARegisters).GetProperty(PropName); + + if (PropInfo.PropertyType != typeof(long) && + PropInfo.PropertyType != typeof(ulong)) + { + Context.Emit(OpCodes.Conv_U4); + } + + Context.EmitCallPropSet(typeof(ARegisters), PropName); } public static void Nop(AILEmitterCtx Context) @@ -52,19 +84,12 @@ 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; - int Id; - - Id = Op.Op2 << 0; - Id |= Op.CRm << 3; - Id |= Op.CRn << 7; - Id |= Op.Op1 << 11; - - switch (Id) + switch (GetPackedId(Op)) { - case 0b011_0111_0100_001: + case 0b11_011_0111_0100_001: { //DC ZVA - for (int Offs = 0; Offs < 64; Offs += 8) + for (int Offs = 0; Offs < (4 << ARegisters.DczSizeLog2); Offs += 8) { Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); Context.EmitLdint(Op.Rt); @@ -80,5 +105,18 @@ namespace ChocolArm64.Instruction } } } + + private static int GetPackedId(AOpCodeSystem Op) + { + int Id; + + Id = Op.Op2 << 0; + Id |= Op.CRm << 3; + Id |= Op.CRn << 7; + Id |= Op.Op1 << 11; + Id |= Op.Op0 << 14; + + return Id; + } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/Memory/AMemory.cs b/Ryujinx/Cpu/Memory/AMemory.cs index 4e9bd53fc..af1c75bf0 100644 --- a/Ryujinx/Cpu/Memory/AMemory.cs +++ b/Ryujinx/Cpu/Memory/AMemory.cs @@ -6,6 +6,8 @@ namespace ChocolArm64.Memory { public unsafe class AMemory { + private const long ErgMask = (4 << ARegisters.ErgSizeLog2) - 1; + public AMemoryMgr Manager { get; private set; } private struct ExMonitor @@ -52,6 +54,11 @@ namespace ChocolArm64.Memory { lock (Monitors) { + if (Monitors.TryGetValue(ThreadId, out ExMonitor Monitor)) + { + ExAddrs.Remove(Monitor.Position); + } + Monitors.Remove(ThreadId); } } @@ -60,14 +67,16 @@ namespace ChocolArm64.Memory { lock (Monitors) { - bool ExState = !ExAddrs.Contains(Position); + Position &= ~ErgMask; - if (ExState) + if (Monitors.TryGetValue(Registers.ThreadId, out ExMonitor Monitor)) { - ExAddrs.Add(Position); + ExAddrs.Remove(Monitor.Position); } - ExMonitor Monitor = new ExMonitor(Position, ExState); + bool ExState = ExAddrs.Add(Position); + + Monitor = new ExMonitor(Position, ExState); if (!Monitors.TryAdd(Registers.ThreadId, Monitor)) { @@ -80,6 +89,8 @@ namespace ChocolArm64.Memory { lock (Monitors) { + Position &= ~ErgMask; + if (!Monitors.TryGetValue(Registers.ThreadId, out ExMonitor Monitor)) { return false; diff --git a/Ryujinx/Cpu/State/ACoreType.cs b/Ryujinx/Cpu/State/ACoreType.cs deleted file mode 100644 index 3fed78cf6..000000000 --- a/Ryujinx/Cpu/State/ACoreType.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace ChocolArm64.State -{ - public enum ACoreType - { - CortexA53, - CortexA57 - } -} \ No newline at end of file diff --git a/Ryujinx/Cpu/State/ARegisters.cs b/Ryujinx/Cpu/State/ARegisters.cs index 3a424a7f9..76b8f9b3a 100644 --- a/Ryujinx/Cpu/State/ARegisters.cs +++ b/Ryujinx/Cpu/State/ARegisters.cs @@ -7,6 +7,12 @@ namespace ChocolArm64.State internal const int LRIndex = 30; internal const int ZRIndex = 31; + internal const int ErgSizeLog2 = 4; + internal const int DczSizeLog2 = 4; + + private const long TicksPerS = 19_200_000; + private const long TicksPerMS = TicksPerS / 1_000; + public ulong X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, @@ -22,97 +28,23 @@ namespace ChocolArm64.State public bool Zero; public bool Negative; - public int ProcessId; - public int ThreadId; - public long TlsAddrEl0; - public long TlsAddr; + public int ProcessId; + public int ThreadId; - private int FPCR; - private int FPSR; + public long TpidrEl0 { get; set; } + public long Tpidr { get; set; } - public ACoreType CoreType; + public int Fpcr { get; set; } + public int Fpsr { get; set; } - private const ulong A53DczidEl0 = 4; - private const ulong A53CtrEl0 = 0x84448004; - private const ulong A57CtrEl0 = 0x8444c004; + public uint CtrEl0 => 0x8444c004; + public uint DczidEl0 => 0x00000004; - private const ulong TicksPerS = 19_200_000; - private const ulong TicksPerMS = TicksPerS / 1_000; + public long CntpctEl0 => Environment.TickCount * TicksPerMS; public event EventHandler SvcCall; public event EventHandler Undefined; - public ulong GetSystemReg(int Op0, int Op1, int CRn, int CRm, int Op2) - { - switch (PackRegId(Op0, Op1, CRn, CRm, Op2)) - { - case 0b11_011_0000_0000_001: return GetCtrEl0(); - case 0b11_011_0000_0000_111: return GetDczidEl0(); - case 0b11_011_0100_0100_000: return (ulong)PackFPCR(); - case 0b11_011_0100_0100_001: return (ulong)PackFPSR(); - case 0b11_011_1101_0000_010: return (ulong)TlsAddrEl0; - case 0b11_011_1101_0000_011: return (ulong)TlsAddr; - case 0b11_011_1110_0000_001: return (ulong)Environment.TickCount * TicksPerMS; - - default: throw new ArgumentException(); - } - } - - public void SetSystemReg(int Op0, int Op1, int CRn, int CRm, int Op2, ulong Value) - { - switch (PackRegId(Op0, Op1, CRn, CRm, Op2)) - { - case 0b11_011_0100_0100_000: UnpackFPCR((int)Value); break; - case 0b11_011_0100_0100_001: UnpackFPSR((int)Value); break; - case 0b11_011_1101_0000_010: TlsAddrEl0 = (long)Value; break; - - default: throw new ArgumentException(); - } - } - - private int PackRegId(int Op0, int Op1, int CRn, int CRm, int Op2) - { - int Id; - - Id = Op2 << 0; - Id |= CRm << 3; - Id |= CRn << 7; - Id |= Op1 << 11; - Id |= Op0 << 14; - - return Id; - } - - public ulong GetCtrEl0() - { - return CoreType == ACoreType.CortexA53 ? A53CtrEl0 : A57CtrEl0; - } - - public ulong GetDczidEl0() - { - return A53DczidEl0; - } - - public int PackFPCR() - { - return FPCR; //TODO - } - - public int PackFPSR() - { - return FPSR; //TODO - } - - public void UnpackFPCR(int Value) - { - FPCR = Value; - } - - public void UnpackFPSR(int Value) - { - FPSR = Value; - } - public void OnSvcCall(int Imm) { SvcCall?.Invoke(this, new SvcEventArgs(Imm)); diff --git a/Ryujinx/Cpu/Translation/AILEmitterCtx.cs b/Ryujinx/Cpu/Translation/AILEmitterCtx.cs index 88841db77..bf56db212 100644 --- a/Ryujinx/Cpu/Translation/AILEmitterCtx.cs +++ b/Ryujinx/Cpu/Translation/AILEmitterCtx.cs @@ -467,11 +467,41 @@ namespace ChocolArm64.Translation throw new ArgumentOutOfRangeException(nameof(Size)); } - public void EmitCall(Type MthdType, string MthdName) + public void EmitCallPropGet(Type ObjType, string PropName) { - if (MthdType == null) + if (ObjType == null) { - throw new ArgumentNullException(nameof(MthdType)); + throw new ArgumentNullException(nameof(ObjType)); + } + + if (PropName == null) + { + throw new ArgumentNullException(nameof(PropName)); + } + + EmitCall(ObjType.GetMethod($"get_{PropName}")); + } + + public void EmitCallPropSet(Type ObjType, string PropName) + { + if (ObjType == null) + { + throw new ArgumentNullException(nameof(ObjType)); + } + + if (PropName == null) + { + throw new ArgumentNullException(nameof(PropName)); + } + + EmitCall(ObjType.GetMethod($"set_{PropName}")); + } + + public void EmitCall(Type ObjType, string MthdName) + { + if (ObjType == null) + { + throw new ArgumentNullException(nameof(ObjType)); } if (MthdName == null) @@ -479,7 +509,7 @@ namespace ChocolArm64.Translation throw new ArgumentNullException(nameof(MthdName)); } - EmitCall(MthdType.GetMethod(MthdName)); + EmitCall(ObjType.GetMethod(MthdName)); } public void EmitCall(MethodInfo MthdInfo) diff --git a/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs b/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs index b451d07ba..84ac4e04b 100644 --- a/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs +++ b/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs @@ -19,7 +19,7 @@ namespace Ryujinx.OsHle.Objects { Context.Memory.WriteInt32(Position + Offset, 5); } - + return 0; } diff --git a/Ryujinx/OsHle/Process.cs b/Ryujinx/OsHle/Process.cs index 1cfae9293..3f72527e6 100644 --- a/Ryujinx/OsHle/Process.cs +++ b/Ryujinx/OsHle/Process.cs @@ -138,7 +138,7 @@ namespace Ryujinx.OsHle Thread.Registers.SvcCall += SvcHandler.SvcCall; Thread.Registers.ProcessId = ProcessId; Thread.Registers.ThreadId = Ns.Os.IdGen.GenerateId(); - Thread.Registers.TlsAddr = TlsPageAddr + TlsSlot * TlsSize; + Thread.Registers.Tpidr = TlsPageAddr + TlsSlot * TlsSize; Thread.Registers.X0 = (ulong)ArgsPtr; Thread.Registers.X1 = (ulong)Handle; Thread.Registers.X31 = (ulong)StackTop; @@ -165,7 +165,7 @@ namespace Ryujinx.OsHle { if (sender is AThread Thread) { - TlsSlots.TryRemove(GetTlsSlot(Thread.Registers.TlsAddr), out _); + TlsSlots.TryRemove(GetTlsSlot(Thread.Registers.Tpidr), out _); Ns.Os.IdGen.DeleteId(Thread.ThreadId); } diff --git a/Ryujinx/OsHle/Svc/SvcSystem.cs b/Ryujinx/OsHle/Svc/SvcSystem.cs index 6f614d162..75d04830a 100644 --- a/Ryujinx/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx/OsHle/Svc/SvcSystem.cs @@ -39,7 +39,7 @@ namespace Ryujinx.OsHle.Svc private static void SvcGetSystemTick(Switch Ns, ARegisters Registers, AMemory Memory) { - Registers.X0 = (ulong)Registers.GetSystemReg(3, 3, 14, 0, 1); + Registers.X0 = (ulong)Registers.CntpctEl0; } private static void SvcConnectToNamedPort(Switch Ns, ARegisters Registers, AMemory Memory) @@ -70,7 +70,7 @@ namespace Ryujinx.OsHle.Svc private static void SendSyncRequest(Switch Ns, ARegisters Registers, AMemory Memory, bool IsUser) { - long CmdPtr = Registers.TlsAddr; + long CmdPtr = Registers.Tpidr; long Size = 0x100; int Handle = 0;