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
This commit is contained in:
parent
331c07807f
commit
427b7d06b5
135 changed files with 43322 additions and 24 deletions
138
src/Ryujinx.Cpu/LightningJit/Arm64/Block.cs
Normal file
138
src/Ryujinx.Cpu/LightningJit/Arm64/Block.cs
Normal file
|
@ -0,0 +1,138 @@
|
|||
using Ryujinx.Cpu.LightningJit.Graph;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Cpu.LightningJit.Arm64
|
||||
{
|
||||
class Block : IBlock
|
||||
{
|
||||
public int Index { get; private set; }
|
||||
|
||||
private readonly List<Block> _predecessors;
|
||||
private readonly List<Block> _successors;
|
||||
|
||||
public int PredecessorsCount => _predecessors.Count;
|
||||
public int SuccessorsCount => _successors.Count;
|
||||
|
||||
public readonly ulong Address;
|
||||
public readonly ulong EndAddress;
|
||||
public readonly List<InstInfo> Instructions;
|
||||
public readonly bool EndsWithBranch;
|
||||
public readonly bool IsTruncated;
|
||||
public readonly bool IsLoopEnd;
|
||||
|
||||
public Block(ulong address, ulong endAddress, List<InstInfo> instructions, bool endsWithBranch, bool isTruncated, bool isLoopEnd)
|
||||
{
|
||||
Debug.Assert((int)((endAddress - address) / 4) == instructions.Count);
|
||||
|
||||
_predecessors = new();
|
||||
_successors = new();
|
||||
Address = address;
|
||||
EndAddress = endAddress;
|
||||
Instructions = instructions;
|
||||
EndsWithBranch = endsWithBranch;
|
||||
IsTruncated = isTruncated;
|
||||
IsLoopEnd = isLoopEnd;
|
||||
}
|
||||
|
||||
public (Block, Block) SplitAtAddress(ulong address)
|
||||
{
|
||||
int splitIndex = (int)((address - Address) / 4);
|
||||
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,
|
||||
false,
|
||||
false);
|
||||
|
||||
Block rightBlock = new(
|
||||
address,
|
||||
EndAddress,
|
||||
Instructions.GetRange(splitIndex, splitCount),
|
||||
EndsWithBranch,
|
||||
IsTruncated,
|
||||
IsLoopEnd);
|
||||
|
||||
return (leftBlock, rightBlock);
|
||||
}
|
||||
|
||||
public void Number(int index)
|
||||
{
|
||||
Index = index;
|
||||
}
|
||||
|
||||
public void AddSuccessor(Block block)
|
||||
{
|
||||
if (!_successors.Contains(block))
|
||||
{
|
||||
_successors.Add(block);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPredecessor(Block block)
|
||||
{
|
||||
if (!_predecessors.Contains(block))
|
||||
{
|
||||
_predecessors.Add(block);
|
||||
}
|
||||
}
|
||||
|
||||
public IBlock GetSuccessor(int index)
|
||||
{
|
||||
return _successors[index];
|
||||
}
|
||||
|
||||
public IBlock GetPredecessor(int index)
|
||||
{
|
||||
return _predecessors[index];
|
||||
}
|
||||
|
||||
public RegisterUse ComputeUseMasks()
|
||||
{
|
||||
if (Instructions.Count == 0)
|
||||
{
|
||||
return new(0u, 0u, 0u, 0u, 0u, 0u);
|
||||
}
|
||||
|
||||
RegisterUse use = Instructions[0].RegisterUse;
|
||||
|
||||
for (int index = 1; index < Instructions.Count; index++)
|
||||
{
|
||||
RegisterUse currentUse = Instructions[index].RegisterUse;
|
||||
|
||||
use = new(use.Read | (currentUse.Read & ~use.Write), use.Write | currentUse.Write);
|
||||
}
|
||||
|
||||
return use;
|
||||
}
|
||||
|
||||
public bool EndsWithContextLoad()
|
||||
{
|
||||
return !IsTruncated && EndsWithContextStoreAndLoad();
|
||||
}
|
||||
|
||||
public bool EndsWithContextStore()
|
||||
{
|
||||
return EndsWithContextStoreAndLoad();
|
||||
}
|
||||
|
||||
private bool EndsWithContextStoreAndLoad()
|
||||
{
|
||||
if (Instructions.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
InstName lastInstructionName = Instructions[^1].Name;
|
||||
|
||||
return lastInstructionName.IsCall() || lastInstructionName.IsException();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue