diff options
Diffstat (limited to 'ChocolArm64/Translation/Translator.cs')
| -rw-r--r-- | ChocolArm64/Translation/Translator.cs | 252 |
1 files changed, 0 insertions, 252 deletions
diff --git a/ChocolArm64/Translation/Translator.cs b/ChocolArm64/Translation/Translator.cs deleted file mode 100644 index ab8f474a..00000000 --- a/ChocolArm64/Translation/Translator.cs +++ /dev/null @@ -1,252 +0,0 @@ -using ChocolArm64.Decoders; -using ChocolArm64.Events; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.Memory; -using ChocolArm64.State; -using System; -using System.Reflection.Emit; -using System.Threading; - -namespace ChocolArm64.Translation -{ - public class Translator : ARMeilleure.Translation.ITranslator - { - private MemoryManager _memory; - - private CpuThreadState _dummyThreadState; - - private TranslatorCache _cache; - private TranslatorQueue _queue; - - private Thread _backgroundTranslator; - - public event EventHandler<CpuTraceEventArgs> CpuTrace; - - public bool EnableCpuTrace { get; set; } - - private volatile int _threadCount; - - public Translator(MemoryManager memory) - { - _memory = memory; - - _dummyThreadState = new CpuThreadState(); - - _dummyThreadState.Running = false; - - _cache = new TranslatorCache(); - _queue = new TranslatorQueue(); - } - - public void Execute(ARMeilleure.State.IExecutionContext ctx, ulong address) - { - CpuThreadState state = (CpuThreadState)ctx; - - long position = (long)address; - - if (Interlocked.Increment(ref _threadCount) == 1) - { - _backgroundTranslator = new Thread(TranslateQueuedSubs); - _backgroundTranslator.Start(); - } - - state.CurrentTranslator = this; - - do - { - if (EnableCpuTrace) - { - CpuTrace?.Invoke(this, new CpuTraceEventArgs(position)); - } - - if (!_cache.TryGetSubroutine(position, out TranslatedSub sub)) - { - sub = TranslateLowCq(position, state.GetExecutionMode()); - } - - position = sub.Execute(state, _memory); - } - while (position != 0 && state.Running); - - state.CurrentTranslator = null; - - if (Interlocked.Decrement(ref _threadCount) == 0) - { - _queue.ForceSignal(); - } - } - - internal ArmSubroutine GetOrTranslateSubroutine(CpuThreadState state, long position, CallType cs) - { - if (!_cache.TryGetSubroutine(position, out TranslatedSub sub)) - { - sub = TranslateLowCq(position, state.GetExecutionMode()); - } - - if (sub.Rejit()) - { - bool isComplete = cs == CallType.Call || - cs == CallType.VirtualCall; - - _queue.Enqueue(position, state.GetExecutionMode(), TranslationTier.Tier1, isComplete); - } - - return sub.Delegate; - } - - private void TranslateQueuedSubs() - { - while (_threadCount != 0) - { - if (_queue.TryDequeue(out TranslatorQueueItem item)) - { - bool isCached = _cache.TryGetSubroutine(item.Position, out TranslatedSub sub); - - if (isCached && item.Tier <= sub.Tier) - { - continue; - } - - if (item.Tier == TranslationTier.Tier0) - { - TranslateLowCq(item.Position, item.Mode); - } - else - { - TranslateHighCq(item.Position, item.Mode, item.IsComplete); - } - } - else - { - _queue.WaitForItems(); - } - } - } - - private TranslatedSub TranslateLowCq(long position, ExecutionMode mode) - { - Block[] blocks = Decoder.DecodeBasicBlock(_memory, (ulong)position, mode); - - ILEmitterCtx context = new ILEmitterCtx(_memory, _cache, _queue, TranslationTier.Tier0); - - BasicBlock[] bbs = EmitAndGetBlocks(context, blocks); - - TranslatedSubBuilder builder = new TranslatedSubBuilder(mode); - - string name = GetSubroutineName(position); - - TranslatedSub subroutine = builder.Build(bbs, name, TranslationTier.Tier0); - - return _cache.GetOrAdd(position, subroutine, GetOpsCount(bbs)); - } - - private TranslatedSub TranslateHighCq(long position, ExecutionMode mode, bool isComplete) - { - Block[] blocks = Decoder.DecodeSubroutine(_memory, (ulong)position, mode); - - ILEmitterCtx context = new ILEmitterCtx(_memory, _cache, _queue, TranslationTier.Tier1); - - if (blocks[0].Address != (ulong)position) - { - context.Emit(OpCodes.Br, context.GetLabel(position)); - } - - BasicBlock[] bbs = EmitAndGetBlocks(context, blocks); - - isComplete &= !context.HasIndirectJump; - - TranslatedSubBuilder builder = new TranslatedSubBuilder(mode, isComplete); - - string name = GetSubroutineName(position); - - TranslatedSub subroutine = builder.Build(bbs, name, TranslationTier.Tier1, context.HasSlowCall); - - ForceAheadOfTimeCompilation(subroutine); - - _cache.AddOrUpdate(position, subroutine, GetOpsCount(bbs)); - - return subroutine; - } - - private static BasicBlock[] EmitAndGetBlocks(ILEmitterCtx context, Block[] blocks) - { - for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) - { - Block block = blocks[blkIndex]; - - context.CurrBlock = block; - - context.MarkLabel(context.GetLabel((long)block.Address)); - - for (int opcIndex = 0; opcIndex < block.OpCodes.Count; opcIndex++) - { - OpCode64 opCode = block.OpCodes[opcIndex]; - - context.CurrOp = opCode; - - bool isLastOp = opcIndex == block.OpCodes.Count - 1; - - if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address) - { - context.EmitSynchronization(); - } - - ILLabel lblPredicateSkip = null; - - if (opCode is OpCode32 op && op.Cond < Condition.Al) - { - lblPredicateSkip = new ILLabel(); - - context.EmitCondBranch(lblPredicateSkip, op.Cond.Invert()); - } - - opCode.Emitter(context); - - if (lblPredicateSkip != null) - { - context.MarkLabel(lblPredicateSkip); - - context.ResetBlockStateForPredicatedOp(); - - // If this is the last op on the block, and there's no "next" block - // after this one, then we have to return right now, with the address - // of the next instruction to be executed (in the case that the condition - // is false, and the branch was not taken, as all basic blocks should end - // with some kind of branch). - if (isLastOp && block.Next == null) - { - context.EmitStoreContext(); - context.EmitLdc_I8(opCode.Position + opCode.OpCodeSizeInBytes); - - context.Emit(OpCodes.Ret); - } - } - } - } - - return context.GetBlocks(); - } - - private static string GetSubroutineName(long position) - { - return $"Sub{position:x16}"; - } - - private static int GetOpsCount(BasicBlock[] blocks) - { - int opCount = 0; - - foreach (BasicBlock block in blocks) - { - opCount += block.Count; - } - - return opCount; - } - - private void ForceAheadOfTimeCompilation(TranslatedSub subroutine) - { - subroutine.Execute(_dummyThreadState, null); - } - } -}
\ No newline at end of file |
