From 66dc7a93b7fa689b1e321e28d22ea2ec7a450578 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Sat, 15 Jun 2024 23:50:59 +0100 Subject: [PATCH] Avoid a copy if possible --- .../Arm32/Target/Arm64/InstEmitFlow.cs | 31 ++++++++++++++----- .../Arm64/Target/Arm64/InstEmitSystem.cs | 31 ++++++++++++++----- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs index 9d7581580..d72e039c8 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs @@ -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; + } } } diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs index 342f5c698..c157d752e 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs @@ -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; + } } }