ARMeilleure: Implement single stepping (#3133)

* Decoder: Implement SingleInstruction decoder mode

* Translator: Implement Step

* DecoderMode: Rename Normal to MultipleBlocks
This commit is contained in:
merry 2022-02-22 14:11:42 +00:00 committed by GitHub
parent ccf23fc629
commit dc063eac83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 7 deletions

View file

@ -18,7 +18,7 @@ namespace ARMeilleure.Decoders
// For lower code quality translation, we set a lower limit since we're blocking execution. // For lower code quality translation, we set a lower limit since we're blocking execution.
private const int MaxInstsPerFunctionLowCq = 500; 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<Block> blocks = new List<Block>(); List<Block> blocks = new List<Block>();
@ -38,7 +38,7 @@ namespace ARMeilleure.Decoders
{ {
block = new Block(blkAddress); 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.Exit = true;
block.EndAddress = blkAddress; 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); FillBlock(memory, mode, currBlock, limitAddress);
opsCount += currBlock.OpCodes.Count; 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}."); 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); return TailCallRemover.RunPass(address, blocks);
} }

View file

@ -0,0 +1,9 @@
namespace ARMeilleure.Decoders
{
enum DecoderMode
{
MultipleBlocks,
SingleBlock,
SingleInstruction,
}
}

View file

@ -209,6 +209,17 @@ namespace ARMeilleure.Translation
return nextAddr; 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) internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
{ {
if (!Functions.TryGetValue(address, out TranslatedFunction func)) 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( var context = new ArmEmitterContext(
Memory, Memory,
@ -255,7 +266,7 @@ namespace ARMeilleure.Translation
Logger.StartPass(PassName.Decoding); 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); Logger.EndPass(PassName.Decoding);
@ -285,14 +296,14 @@ namespace ARMeilleure.Translation
var options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; var options = highCq ? CompilerOptions.HighCq : CompilerOptions.None;
if (context.HasPtc) if (context.HasPtc && !singleStep)
{ {
options |= CompilerOptions.Relocatable; options |= CompilerOptions.Relocatable;
} }
CompiledFunction compiledFunc = Compiler.Compile(cfg, argTypes, retType, options); CompiledFunction compiledFunc = Compiler.Compile(cfg, argTypes, retType, options);
if (context.HasPtc) if (context.HasPtc && !singleStep)
{ {
Hash128 hash = Ptc.ComputeHash(Memory, address, funcSize); Hash128 hash = Ptc.ComputeHash(Memory, address, funcSize);