| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- using ChocolArm64.Decoders;
- using ChocolArm64.Events;
- using ChocolArm64.Memory;
- using ChocolArm64.State;
- using ChocolArm64.Translation;
- using System;
- namespace ChocolArm64
- {
- public class Translator
- {
- private TranslatorCache _cache;
- public event EventHandler<CpuTraceEventArgs> CpuTrace;
- public bool EnableCpuTrace { get; set; }
- public Translator()
- {
- _cache = new TranslatorCache();
- }
- internal void ExecuteSubroutine(CpuThread thread, long position)
- {
- ExecuteSubroutine(thread.ThreadState, thread.Memory, position);
- }
- private void ExecuteSubroutine(CpuThreadState state, MemoryManager memory, long position)
- {
- do
- {
- if (EnableCpuTrace)
- {
- CpuTrace?.Invoke(this, new CpuTraceEventArgs(position));
- }
- if (!_cache.TryGetSubroutine(position, out TranslatedSub sub))
- {
- sub = TranslateTier0(memory, position, state.GetExecutionMode());
- }
- if (sub.ShouldReJit())
- {
- TranslateTier1(memory, position, state.GetExecutionMode());
- }
- position = sub.Execute(state, memory);
- }
- while (position != 0 && state.Running);
- }
- internal bool HasCachedSub(long position)
- {
- return _cache.HasSubroutine(position);
- }
- private TranslatedSub TranslateTier0(MemoryManager memory, long position, ExecutionMode mode)
- {
- Block block = Decoder.DecodeBasicBlock(memory, position, mode);
- ILEmitterCtx context = new ILEmitterCtx(_cache, block);
- string subName = GetSubroutineName(position);
- ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(context.GetILBlocks(), subName);
- TranslatedSub subroutine = ilMthdBuilder.GetSubroutine();
- subroutine.SetType(TranslatedSubType.SubTier0);
- _cache.AddOrUpdate(position, subroutine, block.OpCodes.Count);
- return subroutine;
- }
- private void TranslateTier1(MemoryManager memory, long position, ExecutionMode mode)
- {
- Block graph = Decoder.DecodeSubroutine(_cache, memory, position, mode);
- ILEmitterCtx context = new ILEmitterCtx(_cache, graph);
- ILBlock[] ilBlocks = context.GetILBlocks();
- string subName = GetSubroutineName(position);
- ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(ilBlocks, subName);
- TranslatedSub subroutine = ilMthdBuilder.GetSubroutine();
- subroutine.SetType(TranslatedSubType.SubTier1);
- int ilOpCount = 0;
- foreach (ILBlock ilBlock in ilBlocks)
- {
- ilOpCount += ilBlock.Count;
- }
- _cache.AddOrUpdate(position, subroutine, ilOpCount);
- //Mark all methods that calls this method for ReJiting,
- //since we can now call it directly which is faster.
- if (_cache.TryGetSubroutine(position, out TranslatedSub oldSub))
- {
- foreach (long callerPos in oldSub.GetCallerPositions())
- {
- if (_cache.TryGetSubroutine(position, out TranslatedSub callerSub))
- {
- callerSub.MarkForReJit();
- }
- }
- }
- }
- private string GetSubroutineName(long position)
- {
- return $"Sub{position:x16}";
- }
- }
- }
|