Browse Source

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

gdkchan 8 năm trước cách đây
mục cha
commit
2347c44bbf

+ 0 - 11
Ryujinx/Cpu/Instruction/AInstEmitAlu.cs

@@ -175,17 +175,6 @@ namespace ChocolArm64.Instruction
             Context.EmitStintzr(Op.Rd);
             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)
         public static void Rorv(AILEmitterCtx Context)
         {
         {
             EmitDataLoadRn(Context);
             EmitDataLoadRn(Context);

+ 61 - 23
Ryujinx/Cpu/Instruction/AInstEmitSystem.cs

@@ -1,6 +1,8 @@
 using ChocolArm64.Decoder;
 using ChocolArm64.Decoder;
 using ChocolArm64.State;
 using ChocolArm64.State;
 using ChocolArm64.Translation;
 using ChocolArm64.Translation;
+using System;
+using System.Reflection;
 using System.Reflection.Emit;
 using System.Reflection.Emit;
 
 
 namespace ChocolArm64.Instruction
 namespace ChocolArm64.Instruction
@@ -13,13 +15,30 @@ namespace ChocolArm64.Instruction
 
 
             Context.EmitLdarg(ATranslatedSub.RegistersArgIdx);
             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);
             Context.EmitStintzr(Op.Rt);
         }
         }
@@ -29,15 +48,28 @@ namespace ChocolArm64.Instruction
             AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
             AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
 
 
             Context.EmitLdarg(ATranslatedSub.RegistersArgIdx);
             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.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)
         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.
             //We treat it as no-op here since we don't have any cache being emulated anyway.
             AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
             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
                     //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.EmitLdarg(ATranslatedSub.MemoryArgIdx);
                         Context.EmitLdint(Op.Rt);
                         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;
+        }
     }
     }
 }
 }

+ 15 - 4
Ryujinx/Cpu/Memory/AMemory.cs

@@ -6,6 +6,8 @@ namespace ChocolArm64.Memory
 {
 {
     public unsafe class AMemory
     public unsafe class AMemory
     {
     {
+        private const long ErgMask = (4 << ARegisters.ErgSizeLog2) - 1;
+
         public AMemoryMgr Manager { get; private set; }
         public AMemoryMgr Manager { get; private set; }
 
 
         private struct ExMonitor
         private struct ExMonitor
@@ -52,6 +54,11 @@ namespace ChocolArm64.Memory
         {
         {
             lock (Monitors)
             lock (Monitors)
             {
             {
+                if (Monitors.TryGetValue(ThreadId, out ExMonitor Monitor))
+                {
+                    ExAddrs.Remove(Monitor.Position);
+                }
+
                 Monitors.Remove(ThreadId);
                 Monitors.Remove(ThreadId);
             }
             }
         }
         }
@@ -60,14 +67,16 @@ namespace ChocolArm64.Memory
         {
         {
             lock (Monitors)
             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))
                 if (!Monitors.TryAdd(Registers.ThreadId, Monitor))
                 {
                 {
@@ -80,6 +89,8 @@ namespace ChocolArm64.Memory
         {
         {
             lock (Monitors)
             lock (Monitors)
             {
             {
+                Position &= ~ErgMask;
+
                 if (!Monitors.TryGetValue(Registers.ThreadId, out ExMonitor Monitor))
                 if (!Monitors.TryGetValue(Registers.ThreadId, out ExMonitor Monitor))
                 {
                 {
                     return false;
                     return false;

+ 0 - 8
Ryujinx/Cpu/State/ACoreType.cs

@@ -1,8 +0,0 @@
-namespace ChocolArm64.State
-{
-    public enum ACoreType
-    {
-        CortexA53,
-        CortexA57
-    }
-}

+ 15 - 83
Ryujinx/Cpu/State/ARegisters.cs

@@ -7,6 +7,12 @@ namespace ChocolArm64.State
         internal const int LRIndex = 30;
         internal const int LRIndex = 30;
         internal const int ZRIndex = 31;
         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,
         public ulong X0,  X1,  X2,  X3,  X4,  X5,  X6,  X7,
                      X8,  X9,  X10, X11, X12, X13, X14, X15,
                      X8,  X9,  X10, X11, X12, X13, X14, X15,
                      X16, X17, X18, X19, X20, X21, X22, X23,
                      X16, X17, X18, X19, X20, X21, X22, X23,
@@ -22,97 +28,23 @@ namespace ChocolArm64.State
         public bool Zero;
         public bool Zero;
         public bool Negative;
         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<SvcEventArgs> SvcCall;
         public event EventHandler<SvcEventArgs> SvcCall;
         public event EventHandler<EventArgs>    Undefined;
         public event EventHandler<EventArgs>    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)
         public void OnSvcCall(int Imm)
         {
         {
             SvcCall?.Invoke(this, new SvcEventArgs(Imm));
             SvcCall?.Invoke(this, new SvcEventArgs(Imm));

+ 34 - 4
Ryujinx/Cpu/Translation/AILEmitterCtx.cs

@@ -467,11 +467,41 @@ namespace ChocolArm64.Translation
             throw new ArgumentOutOfRangeException(nameof(Size));
             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)
             if (MthdName == null)
@@ -479,7 +509,7 @@ namespace ChocolArm64.Translation
                 throw new ArgumentNullException(nameof(MthdName));
                 throw new ArgumentNullException(nameof(MthdName));
             }
             }
 
 
-            EmitCall(MthdType.GetMethod(MthdName));
+            EmitCall(ObjType.GetMethod(MthdName));
         }
         }
 
 
         public void EmitCall(MethodInfo MthdInfo)
         public void EmitCall(MethodInfo MthdInfo)

+ 1 - 1
Ryujinx/OsHle/Objects/AudIAudioRenderer.cs

@@ -19,7 +19,7 @@ namespace Ryujinx.OsHle.Objects
             {
             {
                 Context.Memory.WriteInt32(Position + Offset, 5);
                 Context.Memory.WriteInt32(Position + Offset, 5);
             }
             }
-            
+
             return 0;
             return 0;
         }
         }
 
 

+ 2 - 2
Ryujinx/OsHle/Process.cs

@@ -138,7 +138,7 @@ namespace Ryujinx.OsHle
             Thread.Registers.SvcCall  += SvcHandler.SvcCall;
             Thread.Registers.SvcCall  += SvcHandler.SvcCall;
             Thread.Registers.ProcessId = ProcessId;
             Thread.Registers.ProcessId = ProcessId;
             Thread.Registers.ThreadId  = Ns.Os.IdGen.GenerateId();
             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.X0        = (ulong)ArgsPtr;
             Thread.Registers.X1        = (ulong)Handle;
             Thread.Registers.X1        = (ulong)Handle;
             Thread.Registers.X31       = (ulong)StackTop;
             Thread.Registers.X31       = (ulong)StackTop;
@@ -165,7 +165,7 @@ namespace Ryujinx.OsHle
         {
         {
             if (sender is AThread Thread)
             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);
                 Ns.Os.IdGen.DeleteId(Thread.ThreadId);
             }
             }

+ 2 - 2
Ryujinx/OsHle/Svc/SvcSystem.cs

@@ -39,7 +39,7 @@ namespace Ryujinx.OsHle.Svc
 
 
         private static void SvcGetSystemTick(Switch Ns, ARegisters Registers, AMemory Memory)
         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)
         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)
         private static void SendSyncRequest(Switch Ns, ARegisters Registers, AMemory Memory, bool IsUser)
         {
         {
-            long CmdPtr = Registers.TlsAddr;
+            long CmdPtr = Registers.Tpidr;
             long Size   = 0x100;
             long Size   = 0x100;
             int  Handle = 0;
             int  Handle = 0;