diff options
Diffstat (limited to 'src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs')
-rw-r--r-- | src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs new file mode 100644 index 00000000..4729f694 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using System.Diagnostics; + +namespace Ryujinx.Cpu.LightningJit.Arm32 +{ + class Block + { + public readonly ulong Address; + public readonly ulong EndAddress; + public readonly List<InstInfo> Instructions; + public readonly bool EndsWithBranch; + public readonly bool HasHostCall; + public readonly bool IsTruncated; + public readonly bool IsLoopEnd; + public readonly bool IsThumb; + + public Block( + ulong address, + ulong endAddress, + List<InstInfo> instructions, + bool endsWithBranch, + bool hasHostCall, + bool isTruncated, + bool isLoopEnd, + bool isThumb) + { + Debug.Assert(isThumb || (int)((endAddress - address) / 4) == instructions.Count); + + Address = address; + EndAddress = endAddress; + Instructions = instructions; + EndsWithBranch = endsWithBranch; + HasHostCall = hasHostCall; + IsTruncated = isTruncated; + IsLoopEnd = isLoopEnd; + IsThumb = isThumb; + } + + public (Block, Block) SplitAtAddress(ulong address) + { + int splitIndex = FindSplitIndex(address); + + if (splitIndex < 0) + { + return (null, null); + } + + int splitCount = Instructions.Count - splitIndex; + + // Technically those are valid, but we don't want to create empty blocks. + Debug.Assert(splitIndex != 0); + Debug.Assert(splitCount != 0); + + Block leftBlock = new( + Address, + address, + Instructions.GetRange(0, splitIndex), + false, + HasHostCall, + false, + false, + IsThumb); + + Block rightBlock = new( + address, + EndAddress, + Instructions.GetRange(splitIndex, splitCount), + EndsWithBranch, + HasHostCall, + IsTruncated, + IsLoopEnd, + IsThumb); + + return (leftBlock, rightBlock); + } + + private int FindSplitIndex(ulong address) + { + if (IsThumb) + { + ulong pc = Address; + + for (int index = 0; index < Instructions.Count; index++) + { + if (pc == address) + { + return index; + } + + pc += Instructions[index].Flags.HasFlag(InstFlags.Thumb16) ? 2UL : 4UL; + } + + return -1; + } + else + { + return (int)((address - Address) / 4); + } + } + } +} |