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),
};
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
{

View File

@ -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
{

View File

@ -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";

View File

@ -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<AddressTablePage>(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;

View File

@ -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)
{

View File

@ -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)
{