From 98c16ed3b0112e243a8cd4ccad4791e1240f4219 Mon Sep 17 00:00:00 2001 From: Gabriel A Date: Thu, 4 Jan 2024 17:42:33 -0300 Subject: [PATCH] Pass memory manager type around --- .../LightningJit/Arm32/CodeGenContext.cs | 6 +- .../Arm32/Target/Arm64/Compiler.cs | 9 +- .../Arm32/Target/Arm64/InstEmitMemory.cs | 91 ++++++++++--------- .../Arm32/Target/Arm64/InstEmitNeonMemory.cs | 16 ++-- .../Arm64/Target/Arm64/Compiler.cs | 4 +- .../Arm64/Target/Arm64/InstEmitMemory.cs | 90 +++++++++--------- 6 files changed, 119 insertions(+), 97 deletions(-) diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/CodeGenContext.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/CodeGenContext.cs index 70645fec4..f55e2bb99 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/CodeGenContext.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/CodeGenContext.cs @@ -1,3 +1,4 @@ +using ARMeilleure.Memory; using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; using System; using System.Collections.Generic; @@ -10,6 +11,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32 public Assembler Arm64Assembler { get; } public RegisterAllocator RegisterAllocator { get; } + public MemoryManagerType MemoryManagerType { get; } + private uint _instructionAddress; public bool IsThumb { get; } @@ -26,11 +29,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm32 private bool _nzcvModified; - public CodeGenContext(CodeWriter codeWriter, Assembler arm64Assembler, RegisterAllocator registerAllocator, bool isThumb) + public CodeGenContext(CodeWriter codeWriter, Assembler arm64Assembler, RegisterAllocator registerAllocator, MemoryManagerType mmType, bool isThumb) { CodeWriter = codeWriter; Arm64Assembler = arm64Assembler; RegisterAllocator = registerAllocator; + MemoryManagerType = mmType; _itConditions = new ArmCondition[4]; _pendingBranches = new(); IsThumb = isThumb; diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs index 653d7ee0e..1e8a89157 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs @@ -21,6 +21,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { public readonly CodeWriter Writer; public readonly RegisterAllocator RegisterAllocator; + public readonly MemoryManagerType MemoryManagerType; public readonly TailMerger TailMerger; public readonly AddressTable FuncTable; public readonly IntPtr DispatchStubPointer; @@ -31,6 +32,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public Context( CodeWriter writer, RegisterAllocator registerAllocator, + MemoryManagerType mmType, TailMerger tailMerger, AddressTable funcTable, RegisterSaveRestore registerSaveRestore, @@ -39,6 +41,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { Writer = writer; RegisterAllocator = registerAllocator; + MemoryManagerType = mmType; TailMerger = tailMerger; FuncTable = funcTable; _registerSaveRestore = registerSaveRestore; @@ -232,7 +235,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 CodeWriter writer = new(); RegisterAllocator regAlloc = new(); Assembler asm = new(writer); - CodeGenContext cgContext = new(writer, asm, regAlloc, isThumb); + CodeGenContext cgContext = new(writer, asm, regAlloc, memoryManager.Type, isThumb); ArmCondition lastCondition = ArmCondition.Al; int lastConditionIp = 0; @@ -311,7 +314,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 TailMerger tailMerger = new(); - Context context = new(writer, regAlloc, tailMerger, funcTable, rsr, dispatchStubPtr, memoryManager.PageTablePointer); + Context context = new(writer, regAlloc, memoryManager.Type, tailMerger, funcTable, rsr, dispatchStubPtr, memoryManager.PageTablePointer); InstInfo lastInstruction = multiBlock.Blocks[^1].Instructions[^1]; bool lastInstIsConditional = GetCondition(lastInstruction, isThumb) != ArmCondition.Al; @@ -635,7 +638,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 ArmShiftType.Lsl, halfword ? 1 : 0); - InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, asm, target.Operand, target.Operand); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, asm, target.Operand, target.Operand); if (halfword) { diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs index 8cf8ffc0c..534ec80a8 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs @@ -1,3 +1,4 @@ +using ARMeilleure.Memory; using Ryujinx.Cpu.LightningJit.CodeGen; using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; using System; @@ -66,7 +67,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); EmitMemoryMultipleInstructionCore( context, @@ -335,7 +336,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); EmitMemoryMultipleInstructionCore( context, @@ -477,7 +478,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 offset = InstEmitCommon.Const(BitOperations.PopCount(registerList) * 4 - 4); WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, false, ArmShiftType.Lsl, 0); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); EmitMemoryMultipleInstructionCore( context, @@ -516,12 +517,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 if (w && !writesToRn) { WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, false, ArmShiftType.Lsl, 0); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); } else { WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, false, ArmShiftType.Lsl, 0); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); } EmitMemoryMultipleInstructionCore( @@ -554,7 +555,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 Operand offset = InstEmitCommon.Const(4); WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, true, ArmShiftType.Lsl, 0); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); EmitMemoryMultipleInstructionCore( context, @@ -663,7 +664,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); action(rtOperand, tempRegister.Operand); } @@ -676,7 +677,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); action(rtOperand, rt2Operand, tempRegister.Operand); } @@ -746,17 +747,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 if (offset.Kind == OperandKind.Constant && offset.Value == 0) { - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); } - else if (offset.Kind == OperandKind.Constant && CanFoldDWordOffset(signedOffs)) + else if (offset.Kind == OperandKind.Constant && CanFoldDWordOffset(context.MemoryManagerType, signedOffs)) { - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); offs = signedOffs; } else { WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, ArmShiftType.Lsl, 0); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, tempRegister.Operand); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand); } action(rt, rt2, tempRegister.Operand, offs); @@ -767,7 +768,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); action(rt, rt2, tempRegister.Operand, 0); @@ -784,7 +785,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 // If Rt and Rn are the same register, ensure we perform the write back after the read/write. WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, ArmShiftType.Lsl, 0); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, tempRegister.Operand); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand); action(rt, rt2, tempRegister.Operand, 0); @@ -793,7 +794,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 else { WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, ArmShiftType.Lsl, 0); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); action(rt, rt2, tempRegister.Operand, 0); } @@ -808,7 +809,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); action(rdOperand, rtOperand, tempRegister.Operand); } @@ -822,7 +823,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); action(rdOperand, rtOperand, rt2Operand, tempRegister.Operand); } @@ -856,17 +857,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 if (offset.Kind == OperandKind.Constant && offset.Value == 0) { - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); } - else if (offset.Kind == OperandKind.Constant && shift == 0 && CanFoldOffset(signedOffs, scale, writeInstUnscaled != null, out unscaled)) + else if (offset.Kind == OperandKind.Constant && shift == 0 && CanFoldOffset(context.MemoryManagerType, signedOffs, scale, writeInstUnscaled != null, out unscaled)) { - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); offs = signedOffs; } else { WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, shiftType, shift); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, tempRegister.Operand); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand); } if (unscaled) @@ -891,7 +892,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, shiftType, shift); writeInst(rt, tempRegister.Operand, 0); @@ -901,7 +902,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); using ScopedRegister tempRegister2 = regAlloc.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); WriteAddShiftOffset(asm, tempRegister2.Operand, baseAddress, offset, add, shiftType, shift); writeInst(rt, tempRegister.Operand, 0); @@ -913,7 +914,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); writeInst(rt, tempRegister.Operand, 0); @@ -931,7 +932,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 // If Rt and Rn are the same register, ensure we perform the write back after the read/write. WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, shiftType, shift); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, tempRegister.Operand); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand); writeInst(rt, tempRegister.Operand, 0); @@ -940,7 +941,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 else { WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, shiftType, shift); - WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress); + WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress); writeInst(rt, tempRegister.Operand, 0); } @@ -974,7 +975,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress); action(rtOperand, tempRegister.Operand, 0); } @@ -1003,7 +1004,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress); action(rtOperand, rt2Operand, tempRegister.Operand, 0); } @@ -1020,17 +1021,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 if (imm == 0) { - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); } - else if (CanFoldOffset(signedOffs, 3, true, out unscaled)) + else if (CanFoldOffset(context.MemoryManagerType, signedOffs, 3, true, out unscaled)) { - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand); offs = signedOffs; } else { WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, rnOperand, InstEmitCommon.Const((int)imm), u, ArmShiftType.Lsl, 0); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); } if (unscaled) @@ -1051,7 +1052,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, rnOperand, rmOperand, u, (ArmShiftType)sType, (int)shift); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); context.Arm64Assembler.PrfmI(tempRegister.Operand, 0, (uint)type, 0, 0); } @@ -1071,14 +1072,19 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress); + WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress); context.Arm64Assembler.PrfmI(tempRegister.Operand, 0, (uint)type, 0, 0); } - public static bool CanFoldOffset(int offset, int scale, bool hasUnscaled, out bool unscaled) + public static bool CanFoldOffset(MemoryManagerType mmType, int offset, int scale, bool hasUnscaled, out bool unscaled) { - // TODO: Check if the memory manager mode also works with folded offsets. + if (mmType != MemoryManagerType.HostMappedUnsafe) + { + unscaled = false; + + return false; + } int mask = (1 << scale) - 1; @@ -1098,21 +1104,24 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 return unscaled; } - private static bool CanFoldDWordOffset(int offset) + private static bool CanFoldDWordOffset(MemoryManagerType mmType, int offset) { - // TODO: Check if the memory manager mode also works with folded offsets. + if (mmType != MemoryManagerType.HostMappedUnsafe) + { + return false; + } return offset >= 0 && offset < 0x40 && (offset & 3) == 0; } - private static void WriteAddressTranslation(RegisterAllocator regAlloc, in Assembler asm, Operand destination, uint guestAddress) + private static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, in Assembler asm, Operand destination, uint guestAddress) { asm.Mov(destination, guestAddress); - WriteAddressTranslation(regAlloc, asm, destination, destination); + WriteAddressTranslation(mmType, regAlloc, asm, destination, destination); } - public static void WriteAddressTranslation(RegisterAllocator regAlloc, in Assembler asm, Operand destination, Operand guestAddress) + public static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, in Assembler asm, Operand destination, Operand guestAddress) { Operand destination64 = new(destination.Kind, OperandType.I64, destination.Value); Operand basePointer = new(regAlloc.FixedPageTableRegister, RegisterType.Integer, OperandType.I64); diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs index b64165807..7f997b604 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs @@ -258,17 +258,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 if (wBack) { InstEmitMemory.WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, false, ArmShiftType.Lsl, 0); - InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); } else { InstEmitMemory.WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, false, ArmShiftType.Lsl, 0); - InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand); } } else { - InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress); } EmitMemoryMultipleInstructionCore(context, tempRegister.Operand, rd, registerCount, singleRegs, isStore); @@ -402,7 +402,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 context.Arm64Assembler.Mov(address.Operand, (context.Pc & ~3u) + (uint)offs); - InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand); offs = 0; } @@ -410,9 +410,9 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { Operand rnOperand = context.RegisterAllocator.RemapGprRegister((int)rn); - if (InstEmitMemory.CanFoldOffset(add ? offs : -offs, (int)size, true, out _)) + if (InstEmitMemory.CanFoldOffset(context.MemoryManagerType, add ? offs : -offs, (int)size, true, out _)) { - InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand); if (!add) { @@ -422,7 +422,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 else { InstEmitMemory.WriteAddShiftOffset(context.Arm64Assembler, address.Operand, rnOperand, InstEmitCommon.Const(offs), add, ArmShiftType.Lsl, 0); - InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand); offs = 0; } @@ -473,7 +473,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 using ScopedRegister address = context.RegisterAllocator.AllocateTempGprRegisterScoped(); - InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand); + InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand); callback(address.Operand); diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs index 5d2f1ea09..babe2cb41 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs @@ -350,11 +350,11 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 if (instInfo.AddressForm != AddressForm.None) { - InstEmitMemory.RewriteInstruction(writer, regAlloc, instInfo.Name, instInfo.Flags, instInfo.AddressForm, pc, encoding); + InstEmitMemory.RewriteInstruction(memoryManager.Type, writer, regAlloc, instInfo.Name, instInfo.Flags, instInfo.AddressForm, pc, encoding); } else if (instInfo.Name == InstName.Sys) { - InstEmitMemory.RewriteSysInstruction(writer, regAlloc, encoding); + InstEmitMemory.RewriteSysInstruction(memoryManager.Type, writer, regAlloc, encoding); } else if (instInfo.Name.IsSystem()) { diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs index fee737c57..fb5cd4781 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs @@ -1,3 +1,4 @@ +using ARMeilleure.Memory; using Ryujinx.Cpu.LightningJit.CodeGen; using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; using System; @@ -10,7 +11,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 private const uint XMask = 0x3f808000u; private const uint XValue = 0x8000000u; - public static void RewriteSysInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding) + public static void RewriteSysInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding) { int rtIndex = RegisterUtils.ExtractRt(encoding); if (rtIndex == RegisterUtils.ZrIndex) @@ -26,7 +27,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 Assembler asm = new(writer); - WriteAddressTranslation(regAlloc, ref asm, rt, guestAddress); + WriteAddressTranslation(mmType, regAlloc, ref asm, rt, guestAddress); encoding = RegisterUtils.ReplaceRt(encoding, tempRegister); @@ -36,6 +37,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 } public static void RewriteInstruction( + MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstName name, @@ -47,19 +49,19 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 switch (addressForm) { case AddressForm.OffsetReg: - RewriteOffsetRegMemoryInstruction(writer, regAlloc, flags, encoding); + RewriteOffsetRegMemoryInstruction(mmType, writer, regAlloc, flags, encoding); break; case AddressForm.PostIndexed: - RewritePostIndexedMemoryInstruction(writer, regAlloc, flags, encoding); + RewritePostIndexedMemoryInstruction(mmType, writer, regAlloc, flags, encoding); break; case AddressForm.PreIndexed: - RewritePreIndexedMemoryInstruction(writer, regAlloc, flags, encoding); + RewritePreIndexedMemoryInstruction(mmType, writer, regAlloc, flags, encoding); break; case AddressForm.SignedScaled: - RewriteSignedScaledMemoryInstruction(writer, regAlloc, flags, encoding); + RewriteSignedScaledMemoryInstruction(mmType, writer, regAlloc, flags, encoding); break; case AddressForm.UnsignedScaled: - RewriteUnsignedScaledMemoryInstruction(writer, regAlloc, flags, encoding); + RewriteUnsignedScaledMemoryInstruction(mmType, writer, regAlloc, flags, encoding); break; case AddressForm.BaseRegister: // Some applications uses unordered memory instructions in places where @@ -72,19 +74,19 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 encoding |= 1u << 15; } - RewriteBaseRegisterMemoryInstruction(writer, regAlloc, encoding); + RewriteBaseRegisterMemoryInstruction(mmType, writer, regAlloc, encoding); break; case AddressForm.StructNoOffset: - RewriteBaseRegisterMemoryInstruction(writer, regAlloc, encoding); + RewriteBaseRegisterMemoryInstruction(mmType, writer, regAlloc, encoding); break; case AddressForm.BasePlusOffset: - RewriteBasePlusOffsetMemoryInstruction(writer, regAlloc, encoding); + RewriteBasePlusOffsetMemoryInstruction(mmType, writer, regAlloc, encoding); break; case AddressForm.Literal: - RewriteLiteralMemoryInstruction(writer, regAlloc, name, pc, encoding); + RewriteLiteralMemoryInstruction(mmType, writer, regAlloc, name, pc, encoding); break; case AddressForm.StructPostIndexedReg: - RewriteStructPostIndexedRegMemoryInstruction(writer, regAlloc, encoding); + RewriteStructPostIndexedRegMemoryInstruction(mmType, writer, regAlloc, encoding); break; default: writer.WriteInstruction(encoding); @@ -92,7 +94,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 } } - private static void RewriteOffsetRegMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) + private static void RewriteOffsetRegMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) { // TODO: Some unallocated encoding cases. @@ -116,7 +118,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 asm.Add(rn, guestAddress, guestOffset, extensionType, shift); - WriteAddressTranslation(regAlloc, ref asm, rn, rn); + WriteAddressTranslation(mmType, regAlloc, ref asm, rn, rn); encoding = RegisterUtils.ReplaceRn(encoding, tempRegister); encoding = (encoding & ~(0xfffu << 10)) | (1u << 24); // Register -> Unsigned offset @@ -126,7 +128,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 regAlloc.FreeTempGprRegister(tempRegister); } - private static void RewritePostIndexedMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) + private static void RewritePostIndexedMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) { bool isPair = flags.HasFlag(InstFlags.Rt2); int imm = isPair ? ExtractSImm7Scaled(flags, encoding) : ExtractSImm9(encoding); @@ -137,7 +139,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 Assembler asm = new(writer); - WriteAddressTranslation(regAlloc, ref asm, rn, guestAddress); + WriteAddressTranslation(mmType, regAlloc, ref asm, rn, guestAddress); encoding = RegisterUtils.ReplaceRn(encoding, tempRegister); @@ -160,7 +162,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 regAlloc.FreeTempGprRegister(tempRegister); } - private static void RewritePreIndexedMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) + private static void RewritePreIndexedMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) { bool isPair = flags.HasFlag(InstFlags.Rt2); int imm = isPair ? ExtractSImm7Scaled(flags, encoding) : ExtractSImm9(encoding); @@ -172,7 +174,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 Assembler asm = new(writer); WriteAddConstant(ref asm, guestAddress, guestAddress, imm); - WriteAddressTranslation(regAlloc, ref asm, rn, guestAddress); + WriteAddressTranslation(mmType, regAlloc, ref asm, rn, guestAddress); encoding = RegisterUtils.ReplaceRn(encoding, tempRegister); @@ -193,27 +195,27 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 regAlloc.FreeTempGprRegister(tempRegister); } - private static void RewriteSignedScaledMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) + private static void RewriteSignedScaledMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) { - RewriteMemoryInstruction(writer, regAlloc, encoding, ExtractSImm7Scaled(flags, encoding), 0x7fu << 15); + RewriteMemoryInstruction(mmType, writer, regAlloc, encoding, ExtractSImm7Scaled(flags, encoding), 0x7fu << 15); } - private static void RewriteUnsignedScaledMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) + private static void RewriteUnsignedScaledMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding) { - RewriteMemoryInstruction(writer, regAlloc, encoding, ExtractUImm12Scaled(flags, encoding), 0xfffu << 10); + RewriteMemoryInstruction(mmType, writer, regAlloc, encoding, ExtractUImm12Scaled(flags, encoding), 0xfffu << 10); } - private static void RewriteBaseRegisterMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding) + private static void RewriteBaseRegisterMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding) { - RewriteMemoryInstruction(writer, regAlloc, encoding, 0, 0u); + RewriteMemoryInstruction(mmType, writer, regAlloc, encoding, 0, 0u); } - private static void RewriteBasePlusOffsetMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding) + private static void RewriteBasePlusOffsetMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding) { - RewriteMemoryInstruction(writer, regAlloc, encoding, ExtractSImm9(encoding), 0x1ffu << 12); + RewriteMemoryInstruction(mmType, writer, regAlloc, encoding, ExtractSImm9(encoding), 0x1ffu << 12); } - private static void RewriteMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding, int imm, uint immMask) + private static void RewriteMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding, int imm, uint immMask) { int tempRegister = regAlloc.AllocateTempGprRegister(); Operand rn = new(tempRegister, RegisterType.Integer, OperandType.I64); @@ -221,13 +223,13 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 Assembler asm = new(writer); - bool canFoldOffset = CanFoldOffset(imm); + bool canFoldOffset = CanFoldOffset(mmType, imm); if (canFoldOffset) { imm = 0; } - WriteAddressTranslation(regAlloc, ref asm, rn, guestAddress, imm); + WriteAddressTranslation(mmType, regAlloc, ref asm, rn, guestAddress, imm); encoding = RegisterUtils.ReplaceRn(encoding, tempRegister); @@ -241,7 +243,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 regAlloc.FreeTempGprRegister(tempRegister); } - private static void RewriteLiteralMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstName name, ulong pc, uint encoding) + private static void RewriteLiteralMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstName name, ulong pc, uint encoding) { Assembler asm = new(writer); @@ -306,7 +308,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 int tempRegister = regAlloc.AllocateTempGprRegister(); Operand rn = new(tempRegister, RegisterType.Integer, OperandType.I64); - WriteAddressTranslation(regAlloc, ref asm, rn, targetAddress); + WriteAddressTranslation(mmType, regAlloc, ref asm, rn, targetAddress); switch (name) { @@ -330,7 +332,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 } } - private static void RewriteStructPostIndexedRegMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding) + private static void RewriteStructPostIndexedRegMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding) { // TODO: Some unallocated encoding cases. @@ -342,7 +344,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 Assembler asm = new(writer); - WriteAddressTranslation(regAlloc, ref asm, rn, guestAddress); + WriteAddressTranslation(mmType, regAlloc, ref asm, rn, guestAddress); encoding = RegisterUtils.ReplaceRn(encoding, tempRegister); encoding &= ~((0x1fu << 16) | (1u << 23)); // Post-index -> No offset @@ -468,7 +470,13 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 regAlloc.FreeTempGprRegister(tempRegister); } - private static void WriteAddressTranslation(RegisterAllocator regAlloc, ref Assembler asm, Operand destination, Operand guestAddress, int offset) + private static void WriteAddressTranslation( + MemoryManagerType mmType, + RegisterAllocator regAlloc, + ref Assembler asm, + Operand destination, + Operand guestAddress, + int offset) { if (offset != 0) { @@ -490,17 +498,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 guestAddress = destination; } - WriteAddressTranslation(regAlloc, ref asm, destination, guestAddress); + WriteAddressTranslation(mmType, regAlloc, ref asm, destination, guestAddress); } - private static void WriteAddressTranslation(RegisterAllocator regAlloc, ref Assembler asm, Operand destination, ulong guestAddress) + private static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, ref Assembler asm, Operand destination, ulong guestAddress) { asm.Mov(destination, guestAddress); - WriteAddressTranslation(regAlloc, ref asm, destination, destination); + WriteAddressTranslation(mmType, regAlloc, ref asm, destination, destination); } - private static void WriteAddressTranslation(RegisterAllocator regAlloc, ref Assembler asm, Operand destination, Operand guestAddress) + private static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, ref Assembler asm, Operand destination, Operand guestAddress) { Operand basePointer = new(regAlloc.FixedPageTableRegister, RegisterType.Integer, OperandType.I64); @@ -519,11 +527,9 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 } } - private static bool CanFoldOffset(int offset) + private static bool CanFoldOffset(MemoryManagerType mmType, int offset) { - // TODO: Check based on the memory manager mode. - - return true; + return mmType == MemoryManagerType.HostMappedUnsafe; } private static int ExtractSImm7Scaled(InstFlags flags, uint encoding)