diff options
author | riperiperi <rhy3756547@hotmail.com> | 2023-04-11 07:55:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-11 08:55:04 +0200 |
commit | 9ef94c8292beda825fa76e05ad2e561c6d571c95 (patch) | |
tree | e535eef49837759f9947bac48a8cbf0b91512d9e /ARMeilleure/Instructions/InstEmitSystem.cs | |
parent | 915d6d044cbf8c89935f14b8c7e085ad729f0e28 (diff) |
ARMeilleure: Move TPIDR_EL0 and TPIDRRO_EL0 to NativeContext (#4661)1.1.705
* 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
Diffstat (limited to 'ARMeilleure/Instructions/InstEmitSystem.cs')
-rw-r--r-- | ARMeilleure/Instructions/InstEmitSystem.cs | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/ARMeilleure/Instructions/InstEmitSystem.cs b/ARMeilleure/Instructions/InstEmitSystem.cs index f668b83b..f84829aa 100644 --- a/ARMeilleure/Instructions/InstEmitSystem.cs +++ b/ARMeilleure/Instructions/InstEmitSystem.cs @@ -33,8 +33,8 @@ namespace ARMeilleure.Instructions 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; @@ -49,19 +49,15 @@ namespace ARMeilleure.Instructions { 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) @@ -165,6 +161,28 @@ namespace ARMeilleure.Instructions 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; @@ -215,5 +233,16 @@ namespace ARMeilleure.Instructions 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); + } } } |