1
0
Fork 0
mirror of https://github.com/Ryujinx/Ryujinx.git synced 2024-12-27 02:06:01 +00:00

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
src/Ryujinx.Cpu/LightningJit
Arm32/Target/Arm64
Arm64/Target/Arm64

View file

@ -140,7 +140,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
bool isTail = false)
{
int tempRegister;
int tempGuestAddress = 0;
int tempGuestAddress = -1;
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);
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();
asm.Mov(Register(tempGuestAddress), guestAddress);
}
}
tempRegister = regAlloc.FixedContextRegister == 1 ? 2 : 1;
tempRegister = NextFreeRegister(1, tempGuestAddress);
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.
Operand indexReg = Register(3);
guestAddress = Register(tempGuestAddress);
Operand indexReg = Register(NextFreeRegister(tempRegister + 1, tempGuestAddress));
if (tempGuestAddress != -1)
{
guestAddress = Register(tempGuestAddress);
}
var level0 = funcTable.Levels[0];
asm.Ubfx(indexReg, guestAddress, level0.Index, level0.Length);
@ -225,7 +229,10 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
// Load the final branch address
asm.LdrRiUn(rn, rn, 0);
regAlloc.FreeTempGprRegister(tempGuestAddress);
if (tempGuestAddress != -1)
{
regAlloc.FreeTempGprRegister(tempGuestAddress);
}
}
else
{
@ -308,5 +315,15 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{
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)
{
int tempRegister;
int tempGuestAddress = 0;
int tempGuestAddress = -1;
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);
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();
asm.Mov(Register(tempGuestAddress), guestAddress);
}
}
tempRegister = regAlloc.FixedContextRegister == 1 ? 2 : 1;
tempRegister = NextFreeRegister(1, tempGuestAddress);
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.
Operand indexReg = Register(3);
guestAddress = Register(tempGuestAddress);
Operand indexReg = Register(NextFreeRegister(tempRegister + 1, tempGuestAddress));
if (tempGuestAddress != -1)
{
guestAddress = Register(tempGuestAddress);
}
var level0 = funcTable.Levels[0];
asm.Ubfx(indexReg, guestAddress, level0.Index, level0.Length);
@ -390,7 +394,10 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
// Load the final branch address
asm.LdrRiUn(rn, rn, 0);
regAlloc.FreeTempGprRegister(tempGuestAddress);
if (tempGuestAddress != -1)
{
regAlloc.FreeTempGprRegister(tempGuestAddress);
}
}
else
{
@ -669,5 +676,15 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
{
return new Operand(type, (ulong)value);
}
private static int NextFreeRegister(int start, int avoid)
{
if (start == avoid)
{
start++;
}
return start;
}
}
}