Ryujinx/src/Ryujinx.Cpu/LightningJit/Arm32/Block.cs
gdkchan 427b7d06b5
Implement a new JIT for Arm devices (#6057)
* Implement a new JIT for Arm devices

* Auto-format

* Make a lot of Assembler members read-only

* More read-only

* Fix more warnings

* ObjectDisposedException.ThrowIf

* New JIT cache for platforms that enforce W^X, currently unused

* Remove unused using

* Fix assert

* Pass memory manager type around

* Safe memory manager mode support + other improvements

* Actual safe memory manager mode masking support

* PR feedback
2024-01-20 11:11:28 -03:00

101 lines
2.8 KiB
C#

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