Allow loops inside basic blocks

This commit is contained in:
gdkchan 2018-07-29 01:31:16 -03:00
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) private ATranslatedSub TranslateTier0(AThreadState State, AMemory Memory, long Position)
{ {
ABlock Block = ADecoder.DecodeBasicBlock(State, this, Memory, Position); (ABlock[] Graph, ABlock Root) = ADecoder.DecodeBasicBlock(State, this, Memory, Position);
ABlock[] Graph = new ABlock[] { Block };
string SubName = GetSubName(Position); string SubName = GetSubName(Position);
AILEmitterCtx Context = new AILEmitterCtx(this, Graph, Block, SubName); AILEmitterCtx Context = new AILEmitterCtx(this, Graph, Root, SubName);
do do
{ {
@ -137,8 +135,6 @@ namespace ChocolArm64
CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine); CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine);
AOpCode LastOp = Block.GetLastOp();
return Subroutine; return Subroutine;
} }

View file

@ -19,7 +19,7 @@ namespace ChocolArm64.Decoder
OpActivators = new ConcurrentDictionary<Type, OpActivator>(); OpActivators = new ConcurrentDictionary<Type, OpActivator>();
} }
public static ABlock DecodeBasicBlock( public static (ABlock[] Graph, ABlock Root) DecodeBasicBlock(
AThreadState State, AThreadState State,
ATranslator Translator, ATranslator Translator,
AMemory Memory, AMemory Memory,
@ -29,7 +29,41 @@ namespace ChocolArm64.Decoder
FillBlock(State, Memory, Block); 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( public static (ABlock[] Graph, ABlock Root) DecodeSubroutine(

View file

@ -163,10 +163,18 @@ namespace ChocolArm64.Instruction
{ {
AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp; AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp;
if (Context.CurrBlock.Next != null && if (Context.CurrBlock.Branch != null)
Context.CurrBlock.Branch != null)
{ {
Context.EmitCondBranch(Context.GetLabel(Op.Imm), Cond); 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 else
{ {
@ -192,10 +200,18 @@ namespace ChocolArm64.Instruction
{ {
AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp; AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp;
if (Context.CurrBlock.Next != null && if (Context.CurrBlock.Branch != null)
Context.CurrBlock.Branch != null)
{ {
Context.Emit(ILOp, Context.GetLabel(Op.Imm)); 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 else
{ {