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:
parent
0f01b184eb
commit
aefaa9eeb8
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user