aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs')
-rw-r--r--src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs101
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);
+ }
+ }
+ }
+}