Implement TinyBlock

Updated the Branch to use TinyBlock by default.
In the next commit GiantBlock will be default with TinyBlock being used instead of LowPowerPTC is enabled.
This commit is contained in:
LotP1 2024-11-16 17:37:12 +01:00 committed by LotP1
parent 0f01b184eb
commit aefaa9eeb8
6 changed files with 45 additions and 65 deletions

View File

@ -22,25 +22,25 @@ namespace ARMeilleure.Common
new( 1, 6), new( 1, 6),
}; };
private static readonly AddressTableLevel[] _levels64BitSparse = private static readonly AddressTableLevel[] _levels64BitSparseTiny =
new AddressTableLevel[] new AddressTableLevel[]
{ {
new(23, 16), new( 11, 28),
new( 2, 21), new( 2, 9),
}; };
private static readonly AddressTableLevel[] _levels32BitSparse = private static readonly AddressTableLevel[] _levels32BitSparseTiny =
new AddressTableLevel[] new AddressTableLevel[]
{ {
new(22, 10), new( 10, 22),
new( 1, 21), new( 1, 9),
}; };
public static AddressTableLevel[] GetArmPreset(bool for64Bits, bool sparse) public static AddressTableLevel[] GetArmPreset(bool for64Bits, bool sparse)
{ {
if (sparse) if (sparse)
{ {
return for64Bits ? _levels64BitSparse : _levels32BitSparse; return for64Bits ? _levels64BitSparseGiant : _levels32BitSparseGiant;
} }
else else
{ {

View File

@ -210,30 +210,24 @@ namespace ARMeilleure.Instructions
// Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels. // Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels.
// Deliberately attempts to avoid branches. // 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 ? Operand tableBase = !context.HasPtc ?
Const(table.Base) : Const(table.Base) :
Const(table.Base, Ptc.FunctionTableSymbol); Const(table.Base, Ptc.FunctionTableSymbol);
Operand page = context.Load(OperandType.I64, context.Add(tableBase, index)); hostAddress = tableBase;
// Second level for (int i = 0; i < table.Levels.Length; i++)
var level1 = table.Levels[1]; {
int clearBits1 = 64 - (level1.Index + level1.Length); var level = table.Levels[i];
int clearBits = 64 - (level.Index + level.Length);
Operand index2 = context.ShiftLeft( Operand index = context.ShiftLeft(
context.ShiftRightUI(context.ShiftLeft(guestAddress, Const(clearBits1)), Const(clearBits1 + level1.Index)), context.ShiftRightUI(context.ShiftLeft(guestAddress, Const(clearBits)), Const(clearBits + level.Index)),
Const(3) Const(3)
); );
hostAddress = context.Load(OperandType.I64, context.Add(page, index2)); hostAddress = context.Load(OperandType.I64, context.Add(hostAddress, index));
}
} }
else else
{ {

View File

@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\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 ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";

View File

@ -141,11 +141,6 @@ namespace ARMeilleure.Common
{ {
ArgumentNullException.ThrowIfNull(levels); ArgumentNullException.ThrowIfNull(levels);
if (levels.Length < 2)
{
throw new ArgumentException("Table must be at least 2 levels deep.", nameof(levels));
}
_pages = new List<AddressTablePage>(capacity: 16); _pages = new List<AddressTablePage>(capacity: 16);
Levels = levels; Levels = levels;
@ -344,6 +339,9 @@ namespace ARMeilleure.Common
{ {
if (_table == null) if (_table == null)
{ {
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); _table = (TEntry**)Allocate(1 << Levels[0].Length, GetFillValue(0), leaf: false);
} }

View File

@ -143,8 +143,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
int tempGuestAddress = -1; int tempGuestAddress = -1;
bool inlineLookup = guestAddress.Kind != OperandKind.Constant && bool inlineLookup = guestAddress.Kind != OperandKind.Constant &&
funcTable is { Sparse: true } && funcTable is { Sparse: true };
funcTable.Levels.Length == 2;
if (guestAddress.Kind == OperandKind.Constant) if (guestAddress.Kind == OperandKind.Constant)
{ {
@ -199,28 +198,23 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
guestAddress = Register(tempGuestAddress); 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; ulong tableBase = (ulong)funcTable.Base;
// Index into the table. // Index into the table.
asm.Mov(rn, tableBase); asm.Mov(rn, tableBase);
asm.Add(rn, rn, indexReg);
// Load the page address. for (int i = 0; i < funcTable.Levels.Length; i++)
asm.LdrRiUn(rn, rn, 0); {
var level = funcTable.Levels[i];
var level1 = funcTable.Levels[1]; asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Ubfx(indexReg, guestAddress, level1.Index, level1.Length);
asm.Lsl(indexReg, indexReg, Const(3)); asm.Lsl(indexReg, indexReg, Const(3));
// Index into the page. // Index into the page.
asm.Add(rn, rn, indexReg); asm.Add(rn, rn, indexReg);
// Load the final branch address // Load the page address.
asm.LdrRiUn(rn, rn, 0); asm.LdrRiUn(rn, rn, 0);
}
if (tempGuestAddress != -1) if (tempGuestAddress != -1)
{ {

View File

@ -308,8 +308,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
int tempGuestAddress = -1; int tempGuestAddress = -1;
bool inlineLookup = guestAddress.Kind != OperandKind.Constant && bool inlineLookup = guestAddress.Kind != OperandKind.Constant &&
funcTable is { Sparse: true } && funcTable is { Sparse: true };
funcTable.Levels.Length == 2;
if (guestAddress.Kind == OperandKind.Constant) if (guestAddress.Kind == OperandKind.Constant)
{ {
@ -364,28 +363,23 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
guestAddress = Register(tempGuestAddress); 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; ulong tableBase = (ulong)funcTable.Base;
// Index into the table. // Index into the table.
asm.Mov(rn, tableBase); asm.Mov(rn, tableBase);
asm.Add(rn, rn, indexReg);
// Load the page address. for (int i = 0; i < funcTable.Levels.Length; i++)
asm.LdrRiUn(rn, rn, 0); {
var level = funcTable.Levels[i];
var level1 = funcTable.Levels[1]; asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Ubfx(indexReg, guestAddress, level1.Index, level1.Length);
asm.Lsl(indexReg, indexReg, Const(3)); asm.Lsl(indexReg, indexReg, Const(3));
// Index into the page. // Index into the page.
asm.Add(rn, rn, indexReg); asm.Add(rn, rn, indexReg);
// Load the final branch address // Load the page address.
asm.LdrRiUn(rn, rn, 0); asm.LdrRiUn(rn, rn, 0);
}
if (tempGuestAddress != -1) if (tempGuestAddress != -1)
{ {