diff --git a/src/ARMeilleure/State/ExecutionContext.cs b/src/ARMeilleure/State/ExecutionContext.cs index cdf6f56c5..fa1a4a032 100644 --- a/src/ARMeilleure/State/ExecutionContext.cs +++ b/src/ARMeilleure/State/ExecutionContext.cs @@ -164,11 +164,21 @@ namespace ARMeilleure.State internal void OnBreak(ulong address, int imm) { + if (Optimizations.EnableDebugging) + { + DebugPc = Pc; + } + _breakCallback?.Invoke(this, address, imm); } internal void OnSupervisorCall(ulong address, int imm) { + if (Optimizations.EnableDebugging) + { + DebugPc = Pc; + } + _supervisorCallback?.Invoke(this, address, imm); } diff --git a/src/ARMeilleure/State/NativeContext.cs b/src/ARMeilleure/State/NativeContext.cs index c90e522a9..25b5e51c3 100644 --- a/src/ARMeilleure/State/NativeContext.cs +++ b/src/ARMeilleure/State/NativeContext.cs @@ -22,6 +22,11 @@ namespace ARMeilleure.State public ulong ExclusiveValueHigh; public int Running; public long Tpidr2El0; + + /// + /// This is only set when Optimizations.EnableDebugging is true. + /// + public ulong CurrentPc; } private static NativeCtxStorage _dummyStorage = new(); @@ -39,6 +44,11 @@ namespace ARMeilleure.State public ulong GetPc() { + if (Optimizations.EnableDebugging) + { + return GetStorage().CurrentPc; + } + // TODO: More precise tracking of PC value. return GetStorage().DispatchAddress; } @@ -268,6 +278,11 @@ namespace ARMeilleure.State return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running); } + public static int GetCurrentPcOffset() + { + return StorageOffset(ref _dummyStorage, ref _dummyStorage.CurrentPc); + } + private static int StorageOffset(ref NativeCtxStorage storage, ref T target) { return (int)Unsafe.ByteOffset(ref Unsafe.As(ref storage), ref target); diff --git a/src/ARMeilleure/Translation/Translator.cs b/src/ARMeilleure/Translation/Translator.cs index 343e361a5..351ee34f1 100644 --- a/src/ARMeilleure/Translation/Translator.cs +++ b/src/ARMeilleure/Translation/Translator.cs @@ -388,6 +388,11 @@ namespace ARMeilleure.Translation // Return to managed rather than tail call. bool useReturns = Optimizations.EnableDebugging; + if (Optimizations.EnableDebugging) + { + EmitPcUpdate(context, block.Address); + } + InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns); } else @@ -410,6 +415,11 @@ namespace ARMeilleure.Translation } } + if (Optimizations.EnableDebugging) + { + EmitPcUpdate(context, opCode.Address); + } + Operand lblPredicateSkip = default; if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al) @@ -506,6 +516,14 @@ namespace ARMeilleure.Translation context.MarkLabel(lblExit); } + internal static void EmitPcUpdate(EmitterContext context, ulong address) + { + long currentPcOffs = NativeContext.GetCurrentPcOffset(); + + Operand currentPcAddr = context.Add(context.LoadArgument(OperandType.I64, 0), Const(currentPcOffs)); + context.Store(currentPcAddr, Const(address)); + } + public void InvalidateJitCacheRegion(ulong address, ulong size) { ulong[] overlapAddresses = [];