From 98c16ed3b0112e243a8cd4ccad4791e1240f4219 Mon Sep 17 00:00:00 2001
From: Gabriel A <gab.dark.100@gmail.com>
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<ulong> 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<ulong> 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)