Allow loops inside basic blocks

This commit is contained in:
gdkchan 2018-07-29 01:31:16 -03:00
parent 51605fafc0
commit 08047ad5c9
3 changed files with 58 additions and 12 deletions

View file

@ -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;
}

View file

@ -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(

View file

@ -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
{