diff --git a/ChocolArm64/Translation/ILEmitterCtx.cs b/ChocolArm64/Translation/ILEmitterCtx.cs index 8cc0e4b2ae..778b29ade9 100644 --- a/ChocolArm64/Translation/ILEmitterCtx.cs +++ b/ChocolArm64/Translation/ILEmitterCtx.cs @@ -21,7 +21,7 @@ namespace ChocolArm64.Translation private Block _currBlock; public Block CurrBlock => _currBlock; - public OpCode64 CurrOp => _currBlock.OpCodes[_opcIndex]; + public OpCode64 CurrOp => _currBlock?.OpCodes[_opcIndex]; private Dictionary _visitedBlocks; @@ -67,7 +67,63 @@ namespace ChocolArm64.Translation AdvanceOpCode(); } - public bool AdvanceOpCode() + public ILBlock[] GetILBlocks() + { + EmitAllOpCodes(); + + return _ilBlocks.ToArray(); + } + + private void EmitAllOpCodes() + { + do + { + EmitOpCode(); + } + while (AdvanceOpCode()); + } + + private void EmitOpCode() + { + if (_currBlock == null) + { + return; + } + + if (_opcIndex == 0) + { + MarkLabel(GetLabel(_currBlock.Position)); + + EmitSynchronization(); + } + + CurrOp.Emitter(this); + + _ilBlock.Add(new ILBarrier()); + } + + private void EmitSynchronization() + { + EmitLdarg(TranslatedSub.StateArgIdx); + + EmitLdc_I4(_currBlock.OpCodes.Count); + + EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.Synchronize)); + + EmitLdc_I4(0); + + ILLabel lblContinue = new ILLabel(); + + Emit(OpCodes.Bne_Un_S, lblContinue); + + EmitLdc_I8(0); + + Emit(OpCodes.Ret); + + MarkLabel(lblContinue); + } + + private bool AdvanceOpCode() { if (_currBlock == null) { @@ -144,51 +200,6 @@ namespace ChocolArm64.Translation return new ILBlock(); } - public void EmitOpCode() - { - if (_currBlock == null) - { - return; - } - - if (_opcIndex == 0) - { - MarkLabel(GetLabel(_currBlock.Position)); - - EmitSynchronization(); - } - - CurrOp.Emitter(this); - - _ilBlock.Add(new ILBarrier()); - } - - private void EmitSynchronization() - { - EmitLdarg(TranslatedSub.StateArgIdx); - - EmitLdc_I4(_currBlock.OpCodes.Count); - - EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.Synchronize)); - - EmitLdc_I4(0); - - ILLabel lblContinue = new ILLabel(); - - Emit(OpCodes.Bne_Un_S, lblContinue); - - EmitLdc_I8(0); - - Emit(OpCodes.Ret); - - MarkLabel(lblContinue); - } - - public ILBlock[] GetILBlocks() - { - return _ilBlocks.ToArray(); - } - public bool TryOptEmitSubroutineCall() { if (_currBlock.Next == null) diff --git a/ChocolArm64/Translator.cs b/ChocolArm64/Translator.cs index 40f453745a..47a05ba2c5 100644 --- a/ChocolArm64/Translator.cs +++ b/ChocolArm64/Translator.cs @@ -85,12 +85,6 @@ namespace ChocolArm64 ILEmitterCtx context = new ILEmitterCtx(_cache, block); - do - { - context.EmitOpCode(); - } - while (context.AdvanceOpCode()); - string subName = GetSubroutineName(position); ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(context.GetILBlocks(), subName); @@ -110,34 +104,10 @@ namespace ChocolArm64 ILEmitterCtx context = new ILEmitterCtx(_cache, graph); - 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(); - } - } - } + ILBlock[] ilBlocks = context.GetILBlocks(); string subName = GetSubroutineName(position); - ILBlock[] ilBlocks = context.GetILBlocks(); - ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(ilBlocks, subName); TranslatedSub subroutine = ilMthdBuilder.GetSubroutine(); @@ -152,6 +122,19 @@ namespace ChocolArm64 } _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)