| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- using ChocolArm64.Decoders;
- using ChocolArm64.Events;
- using ChocolArm64.Memory;
- using ChocolArm64.State;
- using ChocolArm64.Translation;
- using System;
- using System.Reflection.Emit;
- 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)
- {
- //TODO: Both the execute A32/A64 methods should be merged on the future,
- //when both ISAs are implemented with the interpreter and JIT.
- //As of now, A32 only has a interpreter and A64 a JIT.
- CpuThreadState state = thread.ThreadState;
- MemoryManager memory = thread.Memory;
- if (state.ExecutionMode == ExecutionMode.AArch32)
- {
- ExecuteSubroutineA32(state, memory);
- }
- else
- {
- ExecuteSubroutineA64(state, memory, position);
- }
- }
- private void ExecuteSubroutineA32(CpuThreadState state, MemoryManager memory)
- {
- do
- {
- OpCode64 opCode = Decoder.DecodeOpCode(state, memory, state.R15);
- opCode.Interpreter(state, memory, opCode);
- }
- while (state.R15 != 0 && state.Running);
- }
- private void ExecuteSubroutineA64(CpuThreadState state, MemoryManager memory, long position)
- {
- do
- {
- if (EnableCpuTrace)
- {
- CpuTrace?.Invoke(this, new CpuTraceEventArgs(position));
- }
- if (!_cache.TryGetSubroutine(position, out TranslatedSub sub))
- {
- sub = TranslateTier0(state, memory, position);
- }
- if (sub.ShouldReJit())
- {
- TranslateTier1(state, memory, position);
- }
- position = sub.Execute(state, memory);
- }
- while (position != 0 && state.Running);
- }
- internal bool HasCachedSub(long position)
- {
- return _cache.HasSubroutine(position);
- }
- private TranslatedSub TranslateTier0(CpuThreadState state, MemoryManager memory, long position)
- {
- Block block = Decoder.DecodeBasicBlock(state, memory, position);
- Block[] graph = new Block[] { block };
- string subName = GetSubroutineName(position);
- ILEmitterCtx context = new ILEmitterCtx(_cache, graph, block, subName);
- do
- {
- context.EmitOpCode();
- }
- while (context.AdvanceOpCode());
- TranslatedSub subroutine = context.GetSubroutine();
- subroutine.SetType(TranslatedSubType.SubTier0);
- _cache.AddOrUpdate(position, subroutine, block.OpCodes.Count);
- OpCode64 lastOp = block.GetLastOp();
- return subroutine;
- }
- private void TranslateTier1(CpuThreadState state, MemoryManager memory, long position)
- {
- (Block[] graph, Block root) = Decoder.DecodeSubroutine(_cache, state, memory, position);
- string subName = GetSubroutineName(position);
- ILEmitterCtx context = new ILEmitterCtx(_cache, graph, root, subName);
- if (context.CurrBlock.Position != position)
- {
- context.Emit(OpCodes.Br, context.GetLabel(position));
- }
- do
- {
- context.EmitOpCode();
- }
- while (context.AdvanceOpCode());
- //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();
- }
- }
- }
- TranslatedSub subroutine = context.GetSubroutine();
- subroutine.SetType(TranslatedSubType.SubTier1);
- _cache.AddOrUpdate(position, subroutine, GetGraphInstCount(graph));
- }
- private string GetSubroutineName(long position)
- {
- return $"Sub{position:x16}";
- }
- private int GetGraphInstCount(Block[] graph)
- {
- int size = 0;
- foreach (Block block in graph)
- {
- size += block.OpCodes.Count;
- }
- return size;
- }
- }
- }
|