Skip to content

Commit

Permalink
ARMeilleure: Move TPIDR_EL0 and TPIDRRO_EL0 to NativeContext (Ryujinx…
Browse files Browse the repository at this point in the history
…#4661)

* ARMeilleure: Move TPIDR_EL0 and TPIDRRO_EL0 to NativeContext

Some games access these system registers several tens of thousands of times in a second from many different threads. While this isn't really crippling, it is a lot of wasted time spent in a reverse pinvoke transition.

Example games are Pokemon Scarlet/Violet and BOTW. These games have a lot of different potential bottlenecks so it's unlikely you will see a consistent improvement, but it definitely disappears from the cpu profile.

* Remove unreachable code.

* Add ulong conversion for offsets

* Nit
  • Loading branch information
riperiperi committed Apr 11, 2023
1 parent 915d6d0 commit 9ef94c8
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 58 deletions.
43 changes: 36 additions & 7 deletions ARMeilleure/Instructions/InstEmitSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ public static void Mrs(ArmEmitterContext context)
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
case 0b11_011_0100_0100_000: EmitGetFpcr(context); return;
case 0b11_011_0100_0100_001: EmitGetFpsr(context); return;
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)); break;
case 0b11_011_1101_0000_011: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)); break;
case 0b11_011_1101_0000_010: EmitGetTpidrEl0(context); return;
case 0b11_011_1101_0000_011: EmitGetTpidrroEl0(context); return;
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
case 0b11_011_1110_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
case 0b11_011_1110_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)); break;
Expand All @@ -49,19 +49,15 @@ public static void Msr(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;

MethodInfo info;

switch (GetPackedId(op))
{
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
case 0b11_011_0100_0100_000: EmitSetFpcr(context); return;
case 0b11_011_0100_0100_001: EmitSetFpsr(context); return;
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)); break;
case 0b11_011_1101_0000_010: EmitSetTpidrEl0(context); return;

default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
}

context.Call(info, GetIntOrZR(context, op.Rt));
}

public static void Nop(ArmEmitterContext context)
Expand Down Expand Up @@ -165,6 +161,28 @@ private static void EmitGetFpsr(ArmEmitterContext context)
SetIntOrZR(context, op.Rt, fpsr);
}

private static void EmitGetTpidrEl0(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;

Operand nativeContext = context.LoadArgument(OperandType.I64, 0);

Operand result = context.Load(OperandType.I64, context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())));

SetIntOrZR(context, op.Rt, result);
}

private static void EmitGetTpidrroEl0(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;

Operand nativeContext = context.LoadArgument(OperandType.I64, 0);

Operand result = context.Load(OperandType.I64, context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrroEl0Offset())));

SetIntOrZR(context, op.Rt, result);
}

private static void EmitSetNzcv(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
Expand Down Expand Up @@ -215,5 +233,16 @@ private static void EmitSetFpsr(ArmEmitterContext context)

context.UpdateArmFpMode();
}

private static void EmitSetTpidrEl0(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;

Operand value = GetIntOrZR(context, op.Rt);

Operand nativeContext = context.LoadArgument(OperandType.I64, 0);

context.Store(context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())), value);
}
}
}
47 changes: 35 additions & 12 deletions ARMeilleure/Instructions/InstEmitSystem32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ public static void Mcr(ArmEmitterContext context)
return;
}

MethodInfo info;

switch (op.CRn)
{
case 13: // Process and Thread Info.
Expand All @@ -36,14 +34,12 @@ public static void Mcr(ArmEmitterContext context)
switch (op.Opc2)
{
case 2:
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032)); break;
EmitSetTpidrEl0(context); return;

default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
}

break;

case 7:
switch (op.CRm) // Cache and Memory barrier.
{
Expand All @@ -64,8 +60,6 @@ public static void Mcr(ArmEmitterContext context)
default:
throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
}

context.Call(info, GetIntA32(context, op.Rt));
}

public static void Mrc(ArmEmitterContext context)
Expand All @@ -79,7 +73,7 @@ public static void Mrc(ArmEmitterContext context)
return;
}

MethodInfo info;
Operand result;

switch (op.CRn)
{
Expand All @@ -92,10 +86,10 @@ public static void Mrc(ArmEmitterContext context)
switch (op.Opc2)
{
case 2:
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl032)); break;
result = EmitGetTpidrEl0(context); break;

case 3:
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32)); break;
result = EmitGetTpidrroEl0(context); break;

default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
Expand All @@ -110,13 +104,13 @@ public static void Mrc(ArmEmitterContext context)
if (op.Rt == RegisterAlias.Aarch32Pc)
{
// Special behavior: copy NZCV flags into APSR.
EmitSetNzcv(context, context.Call(info));
EmitSetNzcv(context, result);

return;
}
else
{
SetIntA32(context, op.Rt, context.Call(info));
SetIntA32(context, op.Rt, result);
}
}

Expand Down Expand Up @@ -324,5 +318,34 @@ private static void EmitSetFpscr(ArmEmitterContext context)

context.UpdateArmFpMode();
}

private static Operand EmitGetTpidrEl0(ArmEmitterContext context)
{
OpCode32System op = (OpCode32System)context.CurrOp;

Operand nativeContext = context.LoadArgument(OperandType.I64, 0);

return context.Load(OperandType.I64, context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())));
}

private static Operand EmitGetTpidrroEl0(ArmEmitterContext context)
{
OpCode32System op = (OpCode32System)context.CurrOp;

Operand nativeContext = context.LoadArgument(OperandType.I64, 0);

return context.Load(OperandType.I64, context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrroEl0Offset())));
}

private static void EmitSetTpidrEl0(ArmEmitterContext context)
{
OpCode32System op = (OpCode32System)context.CurrOp;

Operand value = GetIntA32(context, op.Rt);

Operand nativeContext = context.LoadArgument(OperandType.I64, 0);

context.Store(context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())), context.ZeroExtend32(OperandType.I64, value));
}
}
}
30 changes: 0 additions & 30 deletions ARMeilleure/Instructions/NativeInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,26 +72,6 @@ public static ulong GetDczidEl0()
return (ulong)GetContext().DczidEl0;
}

public static ulong GetTpidrEl0()
{
return (ulong)GetContext().TpidrEl0;
}

public static uint GetTpidrEl032()
{
return (uint)GetContext().TpidrEl0;
}

public static ulong GetTpidrroEl0()
{
return (ulong)GetContext().TpidrroEl0;
}

public static uint GetTpidr32()
{
return (uint)GetContext().TpidrroEl0;
}

public static ulong GetCntfrqEl0()
{
return GetContext().CntfrqEl0;
Expand All @@ -106,16 +86,6 @@ public static ulong GetCntvctEl0()
{
return GetContext().CntvctEl0;
}

public static void SetTpidrEl0(ulong value)
{
GetContext().TpidrEl0 = (long)value;
}

public static void SetTpidrEl032(uint value)
{
GetContext().TpidrEl0 = (long)value;
}
#endregion

#region "Read"
Expand Down
13 changes: 11 additions & 2 deletions ARMeilleure/State/ExecutionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,17 @@ public class ExecutionContext
// Since EL2 isn't implemented, CNTVOFF_EL2 = 0
public ulong CntvctEl0 => CntpctEl0;

public long TpidrEl0 { get; set; }
public long TpidrroEl0 { get; set; }
public long TpidrEl0
{
get => _nativeContext.GetTpidrEl0();
set => _nativeContext.SetTpidrEl0(value);
}

public long TpidrroEl0
{
get => _nativeContext.GetTpidrroEl0();
set => _nativeContext.SetTpidrroEl0(value);
}

public uint Pstate
{
Expand Down
18 changes: 18 additions & 0 deletions ARMeilleure/State/NativeContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ private unsafe struct NativeCtxStorage
public fixed ulong V[RegisterConsts.VecRegsCount * 2];
public fixed uint Flags[RegisterConsts.FlagsCount];
public fixed uint FpFlags[RegisterConsts.FpFlagsCount];
public long TpidrEl0;
public long TpidrroEl0;
public int Counter;
public ulong DispatchAddress;
public ulong ExclusiveAddress;
Expand Down Expand Up @@ -168,6 +170,12 @@ public unsafe void SetFPState(uint value, uint mask = uint.MaxValue)
}
}

public long GetTpidrEl0() => GetStorage().TpidrEl0;
public void SetTpidrEl0(long value) => GetStorage().TpidrEl0 = value;

public long GetTpidrroEl0() => GetStorage().TpidrroEl0;
public void SetTpidrroEl0(long value) => GetStorage().TpidrroEl0 = value;

public int GetCounter() => GetStorage().Counter;
public void SetCounter(int value) => GetStorage().Counter = value;

Expand Down Expand Up @@ -214,6 +222,16 @@ public unsafe static int GetRegisterOffset(Register reg)
}
}

public static int GetTpidrEl0Offset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.TpidrEl0);
}

public static int GetTpidrroEl0Offset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.TpidrroEl0);
}

public static int GetCounterOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Counter);
Expand Down
6 changes: 0 additions & 6 deletions ARMeilleure/Translation/Delegates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,11 @@ static Delegates()
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl032))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SupervisorCall)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ThrowInvalidMemoryAccess)));
Expand Down
2 changes: 1 addition & 1 deletion ARMeilleure/Translation/PTC/Ptc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Ptc : IPtcLoadState
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";

private const uint InternalVersion = 4626; //! To be incremented manually for each change to the ARMeilleure project.
private const uint InternalVersion = 4661; //! To be incremented manually for each change to the ARMeilleure project.

private const string ActualDir = "0";
private const string BackupDir = "1";
Expand Down

0 comments on commit 9ef94c8

Please sign in to comment.