Revert "mono-jit (#167)" (#172)

This reverts the mono jit PR.
It had several issues that i haven't had time to fix yet.
Expect mono jit v2 in the future with said fixes.

JitCache alignement fixes are still included/fixed.

Co-authored-by: LotP1 <68976644+LotP1@users.noreply.github.com>
Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/172
This commit is contained in:
LotP
2026-07-14 10:23:16 +00:00
co-authored by LotP1
parent 97738fdc51
commit deb5dca420
9 changed files with 101 additions and 86 deletions
+32 -8
View File
@@ -19,22 +19,46 @@ namespace ARMeilleure.Common
new( 7, 8),
new( 1, 6)
];
private static readonly AddressTableLevel[] _monoSparse64Bit =
private static readonly AddressTableLevel[] _levels64BitSparseTiny =
[
new( 2, 37)
new( 11, 28),
new( 2, 9)
];
private static readonly AddressTableLevel[] _monoSparse32Bit =
private static readonly AddressTableLevel[] _levels32BitSparseTiny =
[
new( 1, 31)
new( 10, 22),
new( 1, 9)
];
public static AddressTableLevel[] GetArmPreset(bool for64Bits, bool sparse)
private static readonly AddressTableLevel[] _levels64BitSparseGiant =
[
new( 38, 1),
new( 2, 36)
];
private static readonly AddressTableLevel[] _levels32BitSparseGiant =
[
new( 31, 1),
new( 1, 30)
];
//high power will run worse on DDR3 systems and some DDR4 systems due to the higher ram utilization
//low power will never run worse than non-sparse, but for most systems it won't be necessary
//high power is always used, but I've left low power in here for future reference
public static AddressTableLevel[] GetArmPreset(bool for64Bits, bool sparse, bool lowPower = false)
{
if (sparse)
{
return for64Bits ? _monoSparse64Bit : _monoSparse32Bit;
if (lowPower)
{
return for64Bits ? _levels64BitSparseTiny : _levels32BitSparseTiny;
}
else
{
return for64Bits ? _levels64BitSparseGiant : _levels32BitSparseGiant;
}
}
else
{
@@ -5,7 +5,7 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using ARMeilleure.Translation.PTC;
using System.Linq;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@@ -238,7 +238,7 @@ namespace ARMeilleure.Instructions
}
else if (table.Sparse)
{
// Inline table lookup. Only enabled when the sparse function table is enabled with 1 level.
// Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels.
// Deliberately attempts to avoid branches.
Operand tableBase = !context.HasPtc ?
@@ -247,15 +247,18 @@ namespace ARMeilleure.Instructions
hostAddress = tableBase;
AddressTableLevel level = table.Levels.Last();
int clearBits = 64 - (level.Index + level.Length);
for (int i = 0; i < table.Levels.Length; i++)
{
AddressTableLevel level = table.Levels[i];
int clearBits = 64 - (level.Index + level.Length);
Operand index = context.ShiftLeft(
context.ShiftRightUI(context.ShiftLeft(guestAddress, Const(clearBits)), Const(clearBits + level.Index)),
Const(3)
);
Operand index = context.ShiftLeft(
context.ShiftRightUI(context.ShiftLeft(guestAddress, Const(clearBits)), Const(clearBits + level.Index)),
Const(3)
);
hostAddress = context.Load(OperandType.I64, context.Add(hostAddress, index));
hostAddress = context.Load(OperandType.I64, context.Add(hostAddress, index));
}
}
else
{
@@ -132,7 +132,7 @@ namespace ARMeilleure.Translation.Cache
int regionEnd = endOffs % (int)CacheSize == 0
? (((int)CacheSize) + _pageMask) & ~_pageMask
: ((endOffs % (int)CacheSize) + _pageMask) & ~_pageMask;
GetRegion(offset).Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
}
+1 -1
View File
@@ -34,7 +34,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 7018; //! To be incremented manually for each change to the ARMeilleure project.
private const uint InternalVersion = 7019; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
@@ -161,7 +161,7 @@ namespace ARMeilleure.Translation
context.BranchIfTrue(lblFallback, masked);
Operand index = default;
Operand page = Const(_functionTable.Base);
Operand page = Const((long)_functionTable.Base);
for (int i = 0; i < _functionTable.Levels.Length; i++)
{
+26 -46
View File
@@ -81,13 +81,12 @@ namespace ARMeilleure.Common
private bool _disposed;
private TEntry** _table;
private TEntry* _sparseTable;
private readonly List<AddressTablePage> _pages;
private TEntry _fill;
private MemoryBlock _sparseFill;
private SparseMemoryBlock _fillBottomLevel;
private TEntry* _fillBottomLevelPtr;
private readonly MemoryBlock _sparseFill;
private readonly SparseMemoryBlock _fillBottomLevel;
private readonly TEntry* _fillBottomLevelPtr;
private readonly List<TableSparseBlock> _sparseReserved;
private readonly ReaderWriterLockSlim _sparseLock;
@@ -123,23 +122,16 @@ namespace ARMeilleure.Common
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (Sparse)
lock (_pages)
{
return (nint)_sparseTable;
}
else
{
lock (_pages)
{
return (nint)GetRootPage();
}
return (nint)GetRootPage();
}
}
}
/// <summary>
/// Constructs a new instance of the <see cref="AddressTable{TEntry}"/> class with the specified list of
/// <see cref="AddressTableLevel"/>.
/// <see cref="Level"/>.
/// </summary>
/// <param name="levels">Levels for the address table</param>
/// <param name="sparse">True if the bottom page should be sparsely mapped</param>
@@ -164,8 +156,18 @@ namespace ARMeilleure.Common
if (sparse)
{
// If the address table is sparse, allocate a fill block
_sparseFill = new MemoryBlock(268435456ul, MemoryAllocationFlags.Mirrorable); //low Power TC uses size: 65536ul
ulong bottomLevelSize = (1ul << levels.Last().Length) * (ulong)sizeof(TEntry);
_fillBottomLevel = new SparseMemoryBlock(bottomLevelSize, null, _sparseFill);
_fillBottomLevelPtr = (TEntry*)_fillBottomLevel.Block.Pointer;
_sparseReserved = [];
_sparseLock = new ReaderWriterLockSlim();
_sparseBlockSize = bottomLevelSize;
}
}
@@ -207,24 +209,13 @@ namespace ARMeilleure.Common
public void SignalCodeRange(ulong address, ulong size)
{
AddressTableLevel bottom = Levels.Last();
ulong bottomLevelEntries = 1ul << bottom.Length;
ulong entryIndex = address >> bottom.Index;
ulong entries = size >> bottom.Index;
if (Sparse)
{
ulong bottomLevelSize = (ulong)BitUtils.Pow2RoundUp((int)entries) * (ulong)sizeof(TEntry);
_sparseFill = new MemoryBlock(bottomLevelSize, MemoryAllocationFlags.Mirrorable);
entries += entryIndex - BitUtils.AlignDown(entryIndex, bottomLevelEntries);
_fillBottomLevel = new SparseMemoryBlock(bottomLevelSize, null, _sparseFill);
_fillBottomLevelPtr = (TEntry*)_fillBottomLevel.Block.Pointer;
_sparseBlockSize = bottomLevelSize;
_sparseTable = (TEntry*)Allocate((int)entries, Fill, leaf: true);
_sparseTable -= Levels.Last().GetValue(address);
}
_sparseBlockSize = Math.Max(_sparseBlockSize, BitUtils.AlignUp(entries, bottomLevelEntries) * (ulong)sizeof(TEntry));
}
/// <inheritdoc/>
@@ -243,26 +234,15 @@ namespace ARMeilleure.Common
throw new ArgumentException($"Address 0x{address:X} is not mapped onto the table.", nameof(address));
}
if (Sparse)
lock (_pages)
{
long index = Levels.Last().GetValue(address);
EnsureMapped((nint)(_sparseTable + index));
return ref _sparseTable[index];
}
else
{
lock (_pages)
{
TEntry* page = GetPage(address);
TEntry* page = GetPage(address);
long index = Levels.Last().GetValue(address);
long index = Levels[^1].GetValue(address);
EnsureMapped((nint)(page + index));
EnsureMapped((nint)(page + index));
return ref page[index];
}
return ref page[index];
}
}
@@ -3,7 +3,6 @@ using Ryujinx.Cpu.LightningJit.CodeGen;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using System;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
@@ -190,7 +189,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
}
else if (inlineLookup)
{
// Inline table lookup. Only enabled when the sparse function table is enabled with 1 level.
// Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels.
Operand indexReg = Register(NextFreeRegister(tempRegister + 1, tempGuestAddress));
@@ -204,15 +203,18 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
// Index into the table.
asm.Mov(rn, tableBase);
AddressTableLevel level = funcTable.Levels.Last();
asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Lsl(indexReg, indexReg, Const(3));
for (int i = 0; i < funcTable.Levels.Length; i++)
{
AddressTableLevel level = funcTable.Levels[i];
asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Lsl(indexReg, indexReg, Const(3));
// Index into the page.
asm.Add(rn, rn, indexReg);
// Index into the page.
asm.Add(rn, rn, indexReg);
// Load the page address.
asm.LdrRiUn(rn, rn, 0);
// Load the page address.
asm.LdrRiUn(rn, rn, 0);
}
if (tempGuestAddress != -1)
{
@@ -3,7 +3,6 @@ using Ryujinx.Cpu.LightningJit.CodeGen;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using System;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -356,7 +355,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
}
else if (inlineLookup)
{
// Inline table lookup. Only enabled when the sparse function table is enabled with 1 level.
// Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels.
Operand indexReg = Register(NextFreeRegister(tempRegister + 1, tempGuestAddress));
@@ -370,15 +369,18 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
// Index into the table.
asm.Mov(rn, tableBase);
AddressTableLevel level = funcTable.Levels.Last();
asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Lsl(indexReg, indexReg, Const(3));
for (int i = 0; i < funcTable.Levels.Length; i++)
{
AddressTableLevel level = funcTable.Levels[i];
asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Lsl(indexReg, indexReg, Const(3));
// Index into the page.
asm.Add(rn, rn, indexReg);
// Index into the page.
asm.Add(rn, rn, indexReg);
// Load the page address.
asm.LdrRiUn(rn, rn, 0);
// Load the page address.
asm.LdrRiUn(rn, rn, 0);
}
if (tempGuestAddress != -1)
{
@@ -106,7 +106,9 @@ namespace Ryujinx.Cpu.LightningJit.Cache
{
int endOffs = offset + size;
int regionStart = (offset % (int)CacheSize) & ~_pageMask;
int regionEnd = ((endOffs % (int)CacheSize) + _pageMask) & ~_pageMask;
int regionEnd = endOffs % (int)CacheSize == 0
? (((int)CacheSize) + _pageMask) & ~_pageMask
: ((endOffs % (int)CacheSize) + _pageMask) & ~_pageMask;
GetRegion(offset).Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
}
@@ -115,7 +117,9 @@ namespace Ryujinx.Cpu.LightningJit.Cache
{
int endOffs = offset + size;
int regionStart = (offset % (int)CacheSize) & ~_pageMask;
int regionEnd = ((endOffs % (int)CacheSize) + _pageMask) & ~_pageMask;
int regionEnd = endOffs % (int)CacheSize == 0
? (((int)CacheSize) + _pageMask) & ~_pageMask
: ((endOffs % (int)CacheSize) + _pageMask) & ~_pageMask;
GetRegion(offset).Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
}