From deb5dca420a2b25c863879bc7b47b80ceb098895 Mon Sep 17 00:00:00 2001 From: LotP Date: Tue, 14 Jul 2026 10:23:16 +0000 Subject: [PATCH] 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 --- src/ARMeilleure/Common/AddressTablePresets.cs | 40 ++++++++--- .../Instructions/InstEmitFlowHelper.cs | 21 +++--- src/ARMeilleure/Translation/Cache/JitCache.cs | 2 +- src/ARMeilleure/Translation/PTC/Ptc.cs | 2 +- .../Translation/TranslatorStubs.cs | 2 +- src/Ryujinx.Cpu/AddressTable.cs | 72 +++++++------------ .../Arm32/Target/Arm64/InstEmitFlow.cs | 20 +++--- .../Arm64/Target/Arm64/InstEmitSystem.cs | 20 +++--- .../LightningJit/Cache/JitCache.cs | 8 ++- 9 files changed, 101 insertions(+), 86 deletions(-) diff --git a/src/ARMeilleure/Common/AddressTablePresets.cs b/src/ARMeilleure/Common/AddressTablePresets.cs index 375e36d7b..fd786fc7e 100644 --- a/src/ARMeilleure/Common/AddressTablePresets.cs +++ b/src/ARMeilleure/Common/AddressTablePresets.cs @@ -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 { diff --git a/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs b/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs index 792f7107f..74866f982 100644 --- a/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs @@ -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 { diff --git a/src/ARMeilleure/Translation/Cache/JitCache.cs b/src/ARMeilleure/Translation/Cache/JitCache.cs index 2a157347a..4ab8b37ee 100644 --- a/src/ARMeilleure/Translation/Cache/JitCache.cs +++ b/src/ARMeilleure/Translation/Cache/JitCache.cs @@ -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)); } diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs index 1a09fdaa7..00152f744 100644 --- a/src/ARMeilleure/Translation/PTC/Ptc.cs +++ b/src/ARMeilleure/Translation/PTC/Ptc.cs @@ -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"; diff --git a/src/ARMeilleure/Translation/TranslatorStubs.cs b/src/ARMeilleure/Translation/TranslatorStubs.cs index 1d44416d1..92fb2d2b7 100644 --- a/src/ARMeilleure/Translation/TranslatorStubs.cs +++ b/src/ARMeilleure/Translation/TranslatorStubs.cs @@ -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++) { diff --git a/src/Ryujinx.Cpu/AddressTable.cs b/src/Ryujinx.Cpu/AddressTable.cs index da58eb0c3..19e405491 100644 --- a/src/Ryujinx.Cpu/AddressTable.cs +++ b/src/Ryujinx.Cpu/AddressTable.cs @@ -81,13 +81,12 @@ namespace ARMeilleure.Common private bool _disposed; private TEntry** _table; - private TEntry* _sparseTable; private readonly List _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 _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(); } } } /// /// Constructs a new instance of the class with the specified list of - /// . + /// . /// /// Levels for the address table /// True if the bottom page should be sparsely mapped @@ -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)); } /// @@ -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]; } } diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs index 0a544d0da..943bc6897 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs @@ -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) { diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs index a963b9cae..1bd69bc4b 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs @@ -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) { diff --git a/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs b/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs index ee0710de2..e637d7f32 100644 --- a/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs +++ b/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs @@ -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)); }