aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/ATranslator.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ChocolArm64/ATranslator.cs')
-rw-r--r--ChocolArm64/ATranslator.cs82
1 files changed, 61 insertions, 21 deletions
diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs
index 96bbc89e..2daf7bbc 100644
--- a/ChocolArm64/ATranslator.cs
+++ b/ChocolArm64/ATranslator.cs
@@ -1,47 +1,70 @@
using ChocolArm64.Decoder;
+using ChocolArm64.Events;
using ChocolArm64.Instruction;
+using ChocolArm64.Memory;
using ChocolArm64.Translation;
+using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection.Emit;
namespace ChocolArm64
{
- class ATranslator
+ public class ATranslator
{
- public AThread Thread { get; private set; }
+ private ConcurrentDictionary<long, ATranslatedSub> CachedSubs;
- private Dictionary<long, ATranslatedSub> CachedSubs;
+ private ConcurrentDictionary<long, string> SymbolTable;
+
+ public event EventHandler<ACpuTraceEventArgs> CpuTrace;
+
+ public bool EnableCpuTrace { get; set; }
private bool KeepRunning;
- public ATranslator(AThread Parent)
+ public ATranslator(IReadOnlyDictionary<long, string> SymbolTable = null)
{
- this.Thread = Parent;
+ CachedSubs = new ConcurrentDictionary<long, ATranslatedSub>();
- CachedSubs = new Dictionary<long, ATranslatedSub>();
+ if (SymbolTable != null)
+ {
+ this.SymbolTable = new ConcurrentDictionary<long, string>(SymbolTable);
+ }
+ else
+ {
+ this.SymbolTable = new ConcurrentDictionary<long, string>();
+ }
KeepRunning = true;
}
public void StopExecution() => KeepRunning = false;
- public void ExecuteSubroutine(long Position)
+ public void ExecuteSubroutine(AThread Thread, long Position)
{
do
{
- if (CachedSubs.TryGetValue(Position, out ATranslatedSub Sub) && !Sub.NeedsReJit)
+ if (EnableCpuTrace)
{
- Position = Sub.Execute(Thread.ThreadState, Thread.Memory);
+ if (!SymbolTable.TryGetValue(Position, out string SubName))
+ {
+ SubName = string.Empty;
+ }
+
+ CpuTrace?.Invoke(this, new ACpuTraceEventArgs(Position, SubName));
}
- else
+
+ if (!CachedSubs.TryGetValue(Position, out ATranslatedSub Sub) || Sub.NeedsReJit)
{
- Position = TranslateSubroutine(Position).Execute(Thread.ThreadState, Thread.Memory);
+ Sub = TranslateSubroutine(Thread.Memory, Position);
}
+
+ Position = Sub.Execute(Thread.ThreadState, Thread.Memory);
}
while (Position != 0 && KeepRunning);
}
- public bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub)
+ internal bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub)
{
if (OpCode.Emitter != AInstEmit.Bl)
{
@@ -53,24 +76,29 @@ namespace ChocolArm64
return TryGetCachedSub(((AOpCodeBImmAl)OpCode).Imm, out Sub);
}
- public bool TryGetCachedSub(long Position, out ATranslatedSub Sub)
+ internal bool TryGetCachedSub(long Position, out ATranslatedSub Sub)
{
return CachedSubs.TryGetValue(Position, out Sub);
}
- public bool HasCachedSub(long Position)
+ internal bool HasCachedSub(long Position)
{
return CachedSubs.ContainsKey(Position);
}
- private ATranslatedSub TranslateSubroutine(long Position)
+ private ATranslatedSub TranslateSubroutine(AMemory Memory, long Position)
{
- (ABlock[] Graph, ABlock Root) Cfg = ADecoder.DecodeSubroutine(this, Position);
+ (ABlock[] Graph, ABlock Root) Cfg = ADecoder.DecodeSubroutine(this, Memory, Position);
+
+ string SubName = SymbolTable.GetOrAdd(Position, $"Sub{Position:x16}");
+
+ PropagateName(Cfg.Graph, SubName);
AILEmitterCtx Context = new AILEmitterCtx(
this,
Cfg.Graph,
- Cfg.Root);
+ Cfg.Root,
+ SubName);
if (Context.CurrBlock.Position != Position)
{
@@ -95,12 +123,24 @@ namespace ChocolArm64
ATranslatedSub Subroutine = Context.GetSubroutine();
- if (!CachedSubs.TryAdd(Position, Subroutine))
- {
- CachedSubs[Position] = Subroutine;
- }
+ CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine);
return Subroutine;
}
+
+ private void PropagateName(ABlock[] Graph, string Name)
+ {
+ foreach (ABlock Block in Graph)
+ {
+ AOpCode LastOp = Block.GetLastOp();
+
+ if (LastOp != null &&
+ (LastOp.Emitter == AInstEmit.Bl ||
+ LastOp.Emitter == AInstEmit.Blr))
+ {
+ SymbolTable.TryAdd(LastOp.Position + 4, Name);
+ }
+ }
+ }
}
} \ No newline at end of file