Jit sparse continuation #250
@ -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