aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Translation
diff options
context:
space:
mode:
authorFicture Seven <FICTURE7@gmail.com>2020-06-18 07:37:21 +0400
committerGitHub <noreply@github.com>2020-06-18 13:37:21 +1000
commit2421186d974446ef4183420c50bc37e58d9fe213 (patch)
treee182d974bc8dde8c6dcb206936cd2c4146f2f736 /ARMeilleure/Translation
parent5e724cf24e3d696b95be859c055a617e5d37bf80 (diff)
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
Diffstat (limited to 'ARMeilleure/Translation')
-rw-r--r--ARMeilleure/Translation/Translator.cs65
1 files changed, 31 insertions, 34 deletions
diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs
index 1c2ead4f..d1404796 100644
--- a/ARMeilleure/Translation/Translator.cs
+++ b/ARMeilleure/Translation/Translator.cs
@@ -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];
+ InstEmitFlowHelper.EmitTailContinue(context, Const(block.Address), block.TailCall);
+ }
+ else
+ {
+ for (int opcIndex = 0; opcIndex < block.OpCodes.Count; opcIndex++)
+ {
+ OpCode opCode = block.OpCodes[opcIndex];
- context.CurrOp = opCode;
+ context.CurrOp = opCode;
- bool isLastOp = opcIndex == block.OpCodes.Count - 1;
+ bool isLastOp = opcIndex == block.OpCodes.Count - 1;
- if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address)
- {
- EmitSynchronization(context);
- }
+ if (isLastOp && block.Branch != null && !block.Branch.Exit && block.Branch.Address <= block.Address)
+ {
+ EmitSynchronization(context);
+ }
- Operand lblPredicateSkip = null;
+ Operand lblPredicateSkip = null;
- if (opCode is OpCode32 op && op.Cond < Condition.Al)
- {
- lblPredicateSkip = Label();
+ if (opCode is OpCode32 op && op.Cond < Condition.Al)
+ {
+ lblPredicateSkip = Label();
- InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Invert());
- }
+ 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 (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 (lblPredicateSkip != null)
{
- InstEmitFlowHelper.EmitTailContinue(context, Const(opCode.Address + (ulong)opCode.OpCodeSizeInBytes));
+ context.MarkLabel(lblPredicateSkip);
}
}
}