diff --git a/src/ARMeilleure/Common/AddressTablePresets.cs b/src/ARMeilleure/Common/AddressTablePresets.cs index e7eaf62cd..e18c6cfe4 100644 --- a/src/ARMeilleure/Common/AddressTablePresets.cs +++ b/src/ARMeilleure/Common/AddressTablePresets.cs @@ -22,25 +22,25 @@ namespace ARMeilleure.Common new( 1, 6), }; - private static readonly AddressTableLevel[] _levels64BitSparse = + private static readonly AddressTableLevel[] _levels64BitSparseTiny = new AddressTableLevel[] { - new(23, 16), - new( 2, 21), + new( 11, 28), + new( 2, 9), }; - private static readonly AddressTableLevel[] _levels32BitSparse = + private static readonly AddressTableLevel[] _levels32BitSparseTiny = new AddressTableLevel[] { - new(22, 10), - new( 1, 21), + new( 10, 22), + new( 1, 9), }; public static AddressTableLevel[] GetArmPreset(bool for64Bits, bool sparse) { if (sparse) { - return for64Bits ? _levels64BitSparse : _levels32BitSparse; + return for64Bits ? _levels64BitSparseGiant : _levels32BitSparseGiant; } else { diff --git a/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs b/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs index 8b235b81e..4693ac833 100644 --- a/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitFlowHelper.cs @@ -210,30 +210,24 @@ namespace ARMeilleure.Instructions // Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels. // Deliberately attempts to avoid branches. - var level0 = table.Levels[0]; - int clearBits0 = 64 - (level0.Index + level0.Length); - - Operand index = context.ShiftLeft( - context.ShiftRightUI(context.ShiftLeft(guestAddress, Const(clearBits0)), Const(clearBits0 + level0.Index)), - Const(3) - ); - Operand tableBase = !context.HasPtc ? Const(table.Base) : Const(table.Base, Ptc.FunctionTableSymbol); - Operand page = context.Load(OperandType.I64, context.Add(tableBase, index)); + hostAddress = tableBase; - // Second level - var level1 = table.Levels[1]; - int clearBits1 = 64 - (level1.Index + level1.Length); + for (int i = 0; i < table.Levels.Length; i++) + { + var level = table.Levels[i]; + int clearBits = 64 - (level.Index + level.Length); - Operand index2 = context.ShiftLeft( - context.ShiftRightUI(context.ShiftLeft(guestAddress, Const(clearBits1)), Const(clearBits1 + level1.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(page, index2)); + hostAddress = context.Load(OperandType.I64, context.Add(hostAddress, index)); + } } else { diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs index fbaa1cb3a..f9f0828e1 100644 --- a/src/ARMeilleure/Translation/PTC/Ptc.cs +++ b/src/ARMeilleure/Translation/PTC/Ptc.cs @@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0"; - private const uint InternalVersion = 6978; //! To be incremented manually for each change to the ARMeilleure project. + private const uint InternalVersion = 6986; //! 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/Ryujinx.Cpu/AddressTable.cs b/src/Ryujinx.Cpu/AddressTable.cs index 7b1851ed2..d8b9176ca 100644 --- a/src/Ryujinx.Cpu/AddressTable.cs +++ b/src/Ryujinx.Cpu/AddressTable.cs @@ -141,11 +141,6 @@ namespace ARMeilleure.Common { ArgumentNullException.ThrowIfNull(levels); - if (levels.Length < 2) - { - throw new ArgumentException("Table must be at least 2 levels deep.", nameof(levels)); - } - _pages = new List(capacity: 16); Levels = levels; @@ -344,7 +339,10 @@ namespace ARMeilleure.Common { if (_table == null) { - _table = (TEntry**)Allocate(1 << Levels[0].Length, GetFillValue(0), leaf: false); + if (Levels.Length == 1) + _table = (TEntry**)Allocate(1 << Levels[0].Length, Fill, leaf: true); + else + _table = (TEntry**)Allocate(1 << Levels[0].Length, GetFillValue(0), leaf: false); } return _table; diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs index beef52582..48bdbb573 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs @@ -143,8 +143,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 int tempGuestAddress = -1; bool inlineLookup = guestAddress.Kind != OperandKind.Constant && - funcTable is { Sparse: true } && - funcTable.Levels.Length == 2; + funcTable is { Sparse: true }; if (guestAddress.Kind == OperandKind.Constant) { @@ -199,28 +198,23 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 guestAddress = Register(tempGuestAddress); } - var level0 = funcTable.Levels[0]; - asm.Ubfx(indexReg, guestAddress, level0.Index, level0.Length); - asm.Lsl(indexReg, indexReg, Const(3)); - ulong tableBase = (ulong)funcTable.Base; // Index into the table. asm.Mov(rn, tableBase); - asm.Add(rn, rn, indexReg); - // Load the page address. - asm.LdrRiUn(rn, rn, 0); + for (int i = 0; i < funcTable.Levels.Length; i++) + { + var level = funcTable.Levels[i]; + asm.Ubfx(indexReg, guestAddress, level.Index, level.Length); + asm.Lsl(indexReg, indexReg, Const(3)); - var level1 = funcTable.Levels[1]; - asm.Ubfx(indexReg, guestAddress, level1.Index, level1.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 final branch 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 df54cef2a..f534e8b6e 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs @@ -308,8 +308,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 int tempGuestAddress = -1; bool inlineLookup = guestAddress.Kind != OperandKind.Constant && - funcTable is { Sparse: true } && - funcTable.Levels.Length == 2; + funcTable is { Sparse: true }; if (guestAddress.Kind == OperandKind.Constant) { @@ -364,28 +363,23 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 guestAddress = Register(tempGuestAddress); } - var level0 = funcTable.Levels[0]; - asm.Ubfx(indexReg, guestAddress, level0.Index, level0.Length); - asm.Lsl(indexReg, indexReg, Const(3)); - ulong tableBase = (ulong)funcTable.Base; // Index into the table. asm.Mov(rn, tableBase); - asm.Add(rn, rn, indexReg); - // Load the page address. - asm.LdrRiUn(rn, rn, 0); + for (int i = 0; i < funcTable.Levels.Length; i++) + { + var level = funcTable.Levels[i]; + asm.Ubfx(indexReg, guestAddress, level.Index, level.Length); + asm.Lsl(indexReg, indexReg, Const(3)); - var level1 = funcTable.Levels[1]; - asm.Ubfx(indexReg, guestAddress, level1.Index, level1.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 final branch address - asm.LdrRiUn(rn, rn, 0); + // Load the page address. + asm.LdrRiUn(rn, rn, 0); + } if (tempGuestAddress != -1) {