Allow loops inside basic blocks
This commit is contained in:
parent
51605fafc0
commit
08047ad5c9
3 changed files with 58 additions and 12 deletions
|
@ -117,13 +117,11 @@ namespace ChocolArm64
|
|||
|
||||
private ATranslatedSub TranslateTier0(AThreadState State, AMemory Memory, long Position)
|
||||
{
|
||||
ABlock Block = ADecoder.DecodeBasicBlock(State, this, Memory, Position);
|
||||
|
||||
ABlock[] Graph = new ABlock[] { Block };
|
||||
(ABlock[] Graph, ABlock Root) = ADecoder.DecodeBasicBlock(State, this, Memory, Position);
|
||||
|
||||
string SubName = GetSubName(Position);
|
||||
|
||||
AILEmitterCtx Context = new AILEmitterCtx(this, Graph, Block, SubName);
|
||||
AILEmitterCtx Context = new AILEmitterCtx(this, Graph, Root, SubName);
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -137,8 +135,6 @@ namespace ChocolArm64
|
|||
|
||||
CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine);
|
||||
|
||||
AOpCode LastOp = Block.GetLastOp();
|
||||
|
||||
return Subroutine;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace ChocolArm64.Decoder
|
|||
OpActivators = new ConcurrentDictionary<Type, OpActivator>();
|
||||
}
|
||||
|
||||
public static ABlock DecodeBasicBlock(
|
||||
public static (ABlock[] Graph, ABlock Root) DecodeBasicBlock(
|
||||
AThreadState State,
|
||||
ATranslator Translator,
|
||||
AMemory Memory,
|
||||
|
@ -29,7 +29,41 @@ namespace ChocolArm64.Decoder
|
|||
|
||||
FillBlock(State, Memory, Block);
|
||||
|
||||
return Block;
|
||||
AOpCode LastOp = Block.GetLastOp();
|
||||
|
||||
if (LastOp is AOpCodeBImm Op && Op.Emitter != AInstEmit.Bl)
|
||||
{
|
||||
if (Op.Imm == Start)
|
||||
{
|
||||
Block.Branch = Block;
|
||||
}
|
||||
else if ((ulong)Op.Imm > (ulong)Start &&
|
||||
(ulong)Op.Imm < (ulong)Block.EndPosition)
|
||||
{
|
||||
int NewBlockIndex = (int)((Op.Imm - Start) / 4);
|
||||
|
||||
ABlock NewBlock = new ABlock(Op.Imm);
|
||||
|
||||
for (int Index = NewBlockIndex; Index < Block.OpCodes.Count; Index++)
|
||||
{
|
||||
NewBlock.OpCodes.Add(Block.OpCodes[Index]);
|
||||
}
|
||||
|
||||
Block.OpCodes.RemoveRange(NewBlockIndex, Block.OpCodes.Count - NewBlockIndex);
|
||||
|
||||
NewBlock.EndPosition = Block.EndPosition;
|
||||
|
||||
NewBlock.Branch = NewBlock;
|
||||
|
||||
Block.EndPosition = Op.Imm;
|
||||
|
||||
Block.Next = NewBlock;
|
||||
|
||||
return (new ABlock[] { Block, NewBlock }, Block);
|
||||
}
|
||||
}
|
||||
|
||||
return (new ABlock[] { Block }, Block);
|
||||
}
|
||||
|
||||
public static (ABlock[] Graph, ABlock Root) DecodeSubroutine(
|
||||
|
|
|
@ -163,10 +163,18 @@ namespace ChocolArm64.Instruction
|
|||
{
|
||||
AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp;
|
||||
|
||||
if (Context.CurrBlock.Next != null &&
|
||||
Context.CurrBlock.Branch != null)
|
||||
if (Context.CurrBlock.Branch != null)
|
||||
{
|
||||
Context.EmitCondBranch(Context.GetLabel(Op.Imm), Cond);
|
||||
|
||||
if (Context.CurrBlock.Next == null)
|
||||
{
|
||||
Context.EmitStoreState();
|
||||
|
||||
Context.EmitLdc_I8(Op.Position + 4);
|
||||
|
||||
Context.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -192,10 +200,18 @@ namespace ChocolArm64.Instruction
|
|||
{
|
||||
AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp;
|
||||
|
||||
if (Context.CurrBlock.Next != null &&
|
||||
Context.CurrBlock.Branch != null)
|
||||
if (Context.CurrBlock.Branch != null)
|
||||
{
|
||||
Context.Emit(ILOp, Context.GetLabel(Op.Imm));
|
||||
|
||||
if (Context.CurrBlock.Next == null)
|
||||
{
|
||||
Context.EmitStoreState();
|
||||
|
||||
Context.EmitLdc_I8(Op.Position + 4);
|
||||
|
||||
Context.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue