diff --git a/ARMeilleure/Decoders/Decoder.cs b/ARMeilleure/Decoders/Decoder.cs index 46774f416..e4839bf7b 100644 --- a/ARMeilleure/Decoders/Decoder.cs +++ b/ARMeilleure/Decoders/Decoder.cs @@ -18,7 +18,7 @@ namespace ARMeilleure.Decoders // For lower code quality translation, we set a lower limit since we're blocking execution. private const int MaxInstsPerFunctionLowCq = 500; - public static Block[] Decode(IMemoryManager memory, ulong address, ExecutionMode mode, bool highCq, bool singleBlock) + public static Block[] Decode(IMemoryManager memory, ulong address, ExecutionMode mode, bool highCq, DecoderMode dMode) { List blocks = new List(); @@ -38,7 +38,7 @@ namespace ARMeilleure.Decoders { block = new Block(blkAddress); - if ((singleBlock && visited.Count >= 1) || opsCount > instructionLimit || !memory.IsMapped(blkAddress)) + if ((dMode != DecoderMode.MultipleBlocks && visited.Count >= 1) || opsCount > instructionLimit || !memory.IsMapped(blkAddress)) { block.Exit = true; block.EndAddress = blkAddress; @@ -96,6 +96,12 @@ namespace ARMeilleure.Decoders } } + if (dMode == DecoderMode.SingleInstruction) + { + // Only read at most one instruction + limitAddress = currBlock.Address + 1; + } + FillBlock(memory, mode, currBlock, limitAddress); opsCount += currBlock.OpCodes.Count; @@ -143,7 +149,7 @@ namespace ARMeilleure.Decoders throw new InvalidOperationException($"Decoded a single empty exit block. Entry point = 0x{address:X}."); } - if (!singleBlock) + if (dMode == DecoderMode.MultipleBlocks) { return TailCallRemover.RunPass(address, blocks); } diff --git a/ARMeilleure/Decoders/DecoderMode.cs b/ARMeilleure/Decoders/DecoderMode.cs new file mode 100644 index 000000000..553620847 --- /dev/null +++ b/ARMeilleure/Decoders/DecoderMode.cs @@ -0,0 +1,9 @@ +namespace ARMeilleure.Decoders +{ + enum DecoderMode + { + MultipleBlocks, + SingleBlock, + SingleInstruction, + } +} \ No newline at end of file diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs index 611716e22..389adf292 100644 --- a/ARMeilleure/Translation/Translator.cs +++ b/ARMeilleure/Translation/Translator.cs @@ -209,6 +209,17 @@ namespace ARMeilleure.Translation return nextAddr; } + public ulong Step(State.ExecutionContext context, ulong address) + { + TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true); + + address = func.Execute(context); + + EnqueueForDeletion(address, func); + + return address; + } + internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode) { if (!Functions.TryGetValue(address, out TranslatedFunction func)) @@ -242,7 +253,7 @@ namespace ARMeilleure.Translation } } - internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq) + internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false) { var context = new ArmEmitterContext( Memory, @@ -255,7 +266,7 @@ namespace ARMeilleure.Translation Logger.StartPass(PassName.Decoding); - Block[] blocks = Decoder.Decode(Memory, address, mode, highCq, singleBlock: false); + Block[] blocks = Decoder.Decode(Memory, address, mode, highCq, singleStep ? DecoderMode.SingleInstruction : DecoderMode.MultipleBlocks); Logger.EndPass(PassName.Decoding); @@ -285,14 +296,14 @@ namespace ARMeilleure.Translation var options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; - if (context.HasPtc) + if (context.HasPtc && !singleStep) { options |= CompilerOptions.Relocatable; } CompiledFunction compiledFunc = Compiler.Compile(cfg, argTypes, retType, options); - if (context.HasPtc) + if (context.HasPtc && !singleStep) { Hash128 hash = Ptc.ComputeHash(Memory, address, funcSize);