Generalize tail continues (#1298)
* Generalize tail continues * Fix DecodeBasicBlock `Next` and `Branch` would be null, which is not the state expected by the branch instructions. They end up branching or falling into a block which is never populated by the `Translator`. This causes an assert to be fired when building the CFG. * Clean up Decode overloads * Do not synchronize when branching into exit block If we're branching into an exit block, that exit block will tail continue into another translation which already has a synchronization. * Remove A32 predicate tail continue If `block` is not an exit block then the `block.Next` must exist (as per the last instruction of `block`). * Throw if decoded 0 blocks Address gdkchan's feedback * Rebuild block list instead of setting to null Address gdkchan's feedback
This commit is contained in:
parent
5e724cf24e
commit
2421186d97
9 changed files with 178 additions and 240 deletions
|
@ -183,7 +183,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
Logger.StartPass(PassName.Decoding);
|
||||
|
||||
Block[] blocks = Decoder.DecodeFunction(memory, address, mode, highCq);
|
||||
Block[] blocks = Decoder.Decode(memory, address, mode, highCq, singleBlock: false);
|
||||
|
||||
Logger.EndPass(PassName.Decoding);
|
||||
|
||||
|
@ -242,49 +242,46 @@ namespace ARMeilleure.Translation
|
|||
|
||||
context.MarkLabel(context.GetLabel(block.Address));
|
||||
|
||||
for (int opcIndex = 0; opcIndex < block.OpCodes.Count; opcIndex++)
|
||||
if (block.Exit)
|
||||
{
|
||||
OpCode opCode = block.OpCodes[opcIndex];
|
||||
|
||||
context.CurrOp = opCode;
|
||||
|
||||
bool isLastOp = opcIndex == block.OpCodes.Count - 1;
|
||||
|
||||
if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address)
|
||||
InstEmitFlowHelper.EmitTailContinue(context, Const(block.Address), block.TailCall);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int opcIndex = 0; opcIndex < block.OpCodes.Count; opcIndex++)
|
||||
{
|
||||
EmitSynchronization(context);
|
||||
}
|
||||
OpCode opCode = block.OpCodes[opcIndex];
|
||||
|
||||
Operand lblPredicateSkip = null;
|
||||
context.CurrOp = opCode;
|
||||
|
||||
if (opCode is OpCode32 op && op.Cond < Condition.Al)
|
||||
{
|
||||
lblPredicateSkip = Label();
|
||||
bool isLastOp = opcIndex == block.OpCodes.Count - 1;
|
||||
|
||||
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Invert());
|
||||
}
|
||||
|
||||
if (opCode.Instruction.Emitter != null)
|
||||
{
|
||||
opCode.Instruction.Emitter(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid instruction \"{opCode.Instruction.Name}\".");
|
||||
}
|
||||
|
||||
if (lblPredicateSkip != null)
|
||||
{
|
||||
context.MarkLabel(lblPredicateSkip);
|
||||
|
||||
// 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)
|
||||
if (isLastOp && block.Branch != null && !block.Branch.Exit && block.Branch.Address <= block.Address)
|
||||
{
|
||||
InstEmitFlowHelper.EmitTailContinue(context, Const(opCode.Address + (ulong)opCode.OpCodeSizeInBytes));
|
||||
EmitSynchronization(context);
|
||||
}
|
||||
|
||||
Operand lblPredicateSkip = null;
|
||||
|
||||
if (opCode is OpCode32 op && op.Cond < Condition.Al)
|
||||
{
|
||||
lblPredicateSkip = Label();
|
||||
|
||||
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Invert());
|
||||
}
|
||||
|
||||
if (opCode.Instruction.Emitter != null)
|
||||
{
|
||||
opCode.Instruction.Emitter(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid instruction \"{opCode.Instruction.Name}\".");
|
||||
}
|
||||
|
||||
if (lblPredicateSkip != null)
|
||||
{
|
||||
context.MarkLabel(lblPredicateSkip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue