Avoid a copy if possible

This commit is contained in:
riperiperi 2024-06-15 23:50:59 +01:00
parent 9ef61df9b8
commit 631b3e5116
2 changed files with 48 additions and 14 deletions

View file

@ -140,7 +140,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
bool isTail = false) bool isTail = false)
{ {
int tempRegister; int tempRegister;
int tempGuestAddress = 0; int tempGuestAddress = -1;
bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable != null && funcTable.Levels.Length == 2; bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable != null && funcTable.Levels.Length == 2;
@ -157,15 +157,15 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{ {
asm.StrRiUn(guestAddress, Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset); asm.StrRiUn(guestAddress, Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset);
if (inlineLookup) if (inlineLookup && guestAddress.Value == 0)
{ {
// Might be overwritten. Move the address to a temp register. // X0 will be overwritten. Move the address to a temp register.
tempGuestAddress = regAlloc.AllocateTempGprRegister(); tempGuestAddress = regAlloc.AllocateTempGprRegister();
asm.Mov(Register(tempGuestAddress), guestAddress); asm.Mov(Register(tempGuestAddress), guestAddress);
} }
} }
tempRegister = regAlloc.FixedContextRegister == 1 ? 2 : 1; tempRegister = NextFreeRegister(1, tempGuestAddress);
if (!isTail) if (!isTail)
{ {
@ -190,8 +190,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{ {
// 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.
Operand indexReg = Register(3); Operand indexReg = Register(NextFreeRegister(tempRegister + 1, tempGuestAddress));
guestAddress = Register(tempGuestAddress);
if (tempGuestAddress != -1)
{
guestAddress = Register(tempGuestAddress);
}
var level0 = funcTable.Levels[0]; var level0 = funcTable.Levels[0];
asm.Ubfx(indexReg, guestAddress, level0.Index, level0.Length); asm.Ubfx(indexReg, guestAddress, level0.Index, level0.Length);
@ -225,7 +229,10 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
// Load the final branch address // Load the final branch address
asm.LdrRiUn(rn, rn, 0); asm.LdrRiUn(rn, rn, 0);
regAlloc.FreeTempGprRegister(tempGuestAddress); if (tempGuestAddress != -1)
{
regAlloc.FreeTempGprRegister(tempGuestAddress);
}
} }
else else
{ {
@ -308,5 +315,15 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{ {
return new Operand(type, (ulong)value); return new Operand(type, (ulong)value);
} }
private static int NextFreeRegister(int start, int avoid)
{
if (start == avoid)
{
start++;
}
return start;
}
} }
} }

View file

@ -305,7 +305,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
bool isTail = false) bool isTail = false)
{ {
int tempRegister; int tempRegister;
int tempGuestAddress = 0; int tempGuestAddress = -1;
bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable != null && funcTable.Levels.Length == 2; bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable != null && funcTable.Levels.Length == 2;
@ -322,15 +322,15 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
{ {
asm.StrRiUn(guestAddress, Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset); asm.StrRiUn(guestAddress, Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset);
if (inlineLookup) if (inlineLookup && guestAddress.Value == 0)
{ {
// Might be overwritten. Move the address to a temp register. // X0 will be overwritten. Move the address to a temp register.
tempGuestAddress = regAlloc.AllocateTempGprRegister(); tempGuestAddress = regAlloc.AllocateTempGprRegister();
asm.Mov(Register(tempGuestAddress), guestAddress); asm.Mov(Register(tempGuestAddress), guestAddress);
} }
} }
tempRegister = regAlloc.FixedContextRegister == 1 ? 2 : 1; tempRegister = NextFreeRegister(1, tempGuestAddress);
if (!isTail) if (!isTail)
{ {
@ -355,8 +355,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
{ {
// 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.
Operand indexReg = Register(3); Operand indexReg = Register(NextFreeRegister(tempRegister + 1, tempGuestAddress));
guestAddress = Register(tempGuestAddress);
if (tempGuestAddress != -1)
{
guestAddress = Register(tempGuestAddress);
}
var level0 = funcTable.Levels[0]; var level0 = funcTable.Levels[0];
asm.Ubfx(indexReg, guestAddress, level0.Index, level0.Length); asm.Ubfx(indexReg, guestAddress, level0.Index, level0.Length);
@ -390,7 +394,10 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
// Load the final branch address // Load the final branch address
asm.LdrRiUn(rn, rn, 0); asm.LdrRiUn(rn, rn, 0);
regAlloc.FreeTempGprRegister(tempGuestAddress); if (tempGuestAddress != -1)
{
regAlloc.FreeTempGprRegister(tempGuestAddress);
}
} }
else else
{ {
@ -669,5 +676,15 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
{ {
return new Operand(type, (ulong)value); return new Operand(type, (ulong)value);
} }
private static int NextFreeRegister(int start, int avoid)
{
if (start == avoid)
{
start++;
}
return start;
}
} }
} }