Support multi-level page tables

This commit is contained in:
gdkchan 2019-02-20 18:39:26 -03:00
parent 4cde30e92a
commit 8e0cd3d2fd
11 changed files with 283 additions and 138 deletions

View file

@ -161,7 +161,7 @@ namespace ChocolArm64.Instructions
EmitReadIntFallback(context, size);
context.Emit(OpCodes.Br_S, lblEnd);
context.Emit(OpCodes.Br, lblEnd);
context.MarkLabel(lblFastPath);
@ -192,7 +192,7 @@ namespace ChocolArm64.Instructions
EmitReadVectorFallback(context, size);
context.Emit(OpCodes.Br_S, lblEnd);
context.Emit(OpCodes.Br, lblEnd);
context.MarkLabel(lblFastPath);
@ -217,7 +217,7 @@ namespace ChocolArm64.Instructions
EmitWriteIntFallback(context, size);
context.Emit(OpCodes.Br_S, lblEnd);
context.Emit(OpCodes.Br, lblEnd);
context.MarkLabel(lblFastPath);
@ -255,7 +255,7 @@ namespace ChocolArm64.Instructions
EmitWriteVectorFallback(context, size);
context.Emit(OpCodes.Br_S, lblEnd);
context.Emit(OpCodes.Br, lblEnd);
context.MarkLabel(lblFastPath);
@ -283,24 +283,40 @@ namespace ChocolArm64.Instructions
private static void EmitPtPointerLoad(ILEmitterCtx context, ILLabel lblFallbackPath)
{
context.EmitLdint(_tempIntAddress);
context.EmitLsr(MemoryManager.PageBits);
context.EmitLdc_I(IntPtr.Size);
context.Emit(OpCodes.Mul);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U8);
}
context.EmitLdc_I8(context.Memory.PageTable.ToInt64());
context.Emit(OpCodes.Add);
context.Emit(OpCodes.Conv_I);
context.Emit(OpCodes.Ldind_I);
int bit = MemoryManager.PageBits;
do
{
context.EmitLdint(_tempIntAddress);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U8);
}
context.EmitLsr(bit);
bit += context.Memory.PtLevelBits;
if (bit < context.Memory.AddressSpaceBits)
{
context.EmitLdc_I8(context.Memory.PtLevelMask);
context.Emit(OpCodes.And);
}
context.EmitLdc_I8(IntPtr.Size);
context.Emit(OpCodes.Mul);
context.Emit(OpCodes.Conv_I);
context.Emit(OpCodes.Add);
context.Emit(OpCodes.Ldind_I);
}
while (bit < context.Memory.AddressSpaceBits);
if (!context.Memory.HasWriteWatchSupport)
{

View file

@ -29,21 +29,46 @@ namespace ChocolArm64.Memory
internal IntPtr PageTable => _pageTable;
internal int PtLevelBits { get; }
internal int PtLevelSize { get; }
internal int PtLevelMask { get; }
public bool HasWriteWatchSupport => MemoryManagement.HasWriteWatchSupport;
public int AddressSpaceBits { get; }
public long AddressSpaceSize { get; }
public MemoryManager(IntPtr ram, long addressSpaceSize = 1L << 39)
public MemoryManager(
IntPtr ram,
int addressSpaceBits = 48,
bool useFlatPageTable = false)
{
Ram = ram;
_ramPtr = (byte*)ram;
AddressSpaceSize = addressSpaceSize;
AddressSpaceBits = addressSpaceBits;
AddressSpaceSize = 1L << addressSpaceBits;
long pageTableSize = (addressSpaceSize / PageSize) * IntPtr.Size;
//When flag page table is requested, we use a single
//array for the mappings of the entire address space.
//This has better performance, but also high RAM usage.
//The multi level page table uses 9 bits per level, so
//the RAM usage is lower, but the performance is also
//lower, because it's needed to do multiple reads per translation.
if (useFlatPageTable)
{
PtLevelBits = addressSpaceBits - PageBits;
}
else
{
PtLevelBits = 9;
}
_pageTable = Allocate((ulong)pageTableSize);
PtLevelSize = 1 << PtLevelBits;
PtLevelMask = PtLevelSize - 1;
_pageTable = Allocate((ulong)(PtLevelSize * IntPtr.Size));
}
public void Map(long va, long pa, long size)
@ -75,14 +100,10 @@ namespace ChocolArm64.Memory
return IntPtr.Zero;
}
byte* ptr = ((byte**)_pageTable)[position >> PageBits];
IntPtr* pt = (IntPtr*)_pageTable;
byte* ptr = GetPtEntry(position);
ulong ptrUlong = (ulong)ptr;
long ptrLong = (long)ptr;
if ((ptrUlong & PteFlagsMask) != 0)
{
ptrUlong &= ~(ulong)PteFlagsMask;
@ -100,7 +121,7 @@ namespace ChocolArm64.Memory
return IntPtr.Zero;
}
byte* ptr = ((byte**)_pageTable)[position >> PageBits];
byte* ptr = GetPtEntry(position);
ulong ptrUlong = (ulong)ptr;
@ -119,6 +140,11 @@ namespace ChocolArm64.Memory
return new IntPtr(ptr + (position & PageMask));
}
private byte* GetPtEntry(long position)
{
return *(byte**)GetPtPtr(position);
}
private void SetPtEntries(long va, byte* ptr, long size)
{
long endPosition = (va + size + PageMask) & ~PageMask;
@ -138,12 +164,7 @@ namespace ChocolArm64.Memory
private void SetPtEntry(long position, byte* ptr)
{
if (!IsValidPosition(position))
{
throw new ArgumentOutOfRangeException(nameof(position));
}
((byte**)_pageTable)[position >> PageBits] = ptr;
*(byte**)GetPtPtr(position) = ptr;
}
private void SetPtEntryFlag(long position, long flag)
@ -162,13 +183,22 @@ namespace ChocolArm64.Memory
while (true)
{
IntPtr old = pt[position >> PageBits];
IntPtr* ptPtr = GetPtPtr(position);
IntPtr modified = setFlag
? new IntPtr(old.ToInt64() | flag)
: new IntPtr(old.ToInt64() & ~flag);
IntPtr old = *ptPtr;
IntPtr origValue = Interlocked.CompareExchange(ref pt[position >> PageBits], modified, old);
long modified = old.ToInt64();
if (setFlag)
{
modified |= flag;
}
else
{
modified &= ~flag;
}
IntPtr origValue = Interlocked.CompareExchange(ref *ptPtr, new IntPtr(modified), old);
if (origValue == old)
{
@ -177,6 +207,57 @@ namespace ChocolArm64.Memory
}
}
private IntPtr* GetPtPtr(long position)
{
if (!IsValidPosition(position))
{
throw new ArgumentOutOfRangeException(nameof(position));
}
IntPtr nextPtr = _pageTable;
IntPtr* ptePtr = null;
int bit = PageBits;
while (true)
{
long index = (position >> bit) & PtLevelMask;
ptePtr = &((IntPtr*)nextPtr)[index];
bit += PtLevelBits;
if (bit >= AddressSpaceBits)
{
break;
}
nextPtr = *ptePtr;
if (nextPtr == IntPtr.Zero)
{
//Entry does not yet exist, allocate a new one.
IntPtr newPtr = Allocate((ulong)(PtLevelSize * IntPtr.Size));
//Try to swap the current pointer (should be zero), with the allocated one.
nextPtr = Interlocked.Exchange(ref *ptePtr, newPtr);
//If the old pointer is not null, then another thread already has set it.
if (nextPtr != IntPtr.Zero)
{
Free(newPtr);
}
else
{
nextPtr = newPtr;
}
}
}
return ptePtr;
}
public bool IsRegionModified(long position, long size)
{
if (!HasWriteWatchSupport)
@ -318,7 +399,7 @@ namespace ChocolArm64.Memory
public bool IsValidPosition(long position)
{
return (ulong)position <= (ulong)AddressSpaceSize;
return (ulong)position < (ulong)AddressSpaceSize;
}
internal bool AtomicCompareExchange2xInt32(
@ -899,8 +980,32 @@ namespace ChocolArm64.Memory
if (ptr != IntPtr.Zero)
{
Free(ptr);
FreePageTableEntry(ptr, PageBits);
}
}
private void FreePageTableEntry(IntPtr ptr, int levelBitEnd)
{
levelBitEnd += PtLevelBits;
if (levelBitEnd >= AddressSpaceBits)
{
Free(ptr);
return;
}
for (int index = 0; index < PtLevelSize; index++)
{
IntPtr ptePtr = ((IntPtr*)ptr)[index];
if (ptePtr != IntPtr.Zero)
{
FreePageTableEntry(ptePtr, levelBitEnd);
}
}
Free(ptr);
}
}
}

View file

@ -1,6 +1,5 @@
using ChocolArm64.Memory;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE
{

View file

@ -80,12 +80,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public bool IsPaused { get; private set; }
public Translator Translator { get; private set; }
public MemoryManager CpuMemory { get; private set; }
public Translator Translator { get; private set; }
private SvcHandler _svcHandler;
private Horizon _system;
public HleProcessDebugger Debugger { get; private set; }
public KProcess(Horizon system) : base(system)
@ -93,12 +95,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_processLock = new object();
_threadingLock = new object();
CpuMemory = new MemoryManager(system.Device.Memory.RamPointer);
_system = system;
AddressArbiter = new KAddressArbiter(system);
MemoryManager = new KMemoryManager(system, CpuMemory);
_fullTlsPages = new SortedDictionary<ulong, KTlsPageInfo>();
_freeTlsPages = new SortedDictionary<ulong, KTlsPageInfo>();
@ -108,10 +108,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_threads = new LinkedList<KThread>();
Translator = new Translator(CpuMemory);
Translator.CpuTrace += CpuTraceHandler;
_svcHandler = new SvcHandler(system.Device, this);
Debugger = new HleProcessDebugger(this);
@ -129,6 +125,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7);
InitializeMemoryManager(addrSpaceType, memRegion);
bool aslrEnabled = ((creationInfo.MmuFlags >> 5) & 1) != 0;
ulong codeAddress = creationInfo.CodeAddress;
@ -236,6 +234,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7);
InitializeMemoryManager(addrSpaceType, memRegion);
bool aslrEnabled = ((creationInfo.MmuFlags >> 5) & 1) != 0;
ulong codeAddress = creationInfo.CodeAddress;
@ -403,7 +403,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
case AddressSpaceType.Addr36Bits:
case AddressSpaceType.Addr39Bits:
_memoryUsageCapacity = MemoryManager.HeapRegionEnd -
MemoryManager.HeapRegionStart;
MemoryManager.HeapRegionStart;
break;
case AddressSpaceType.Addr32BitsNoMap:
@ -1008,6 +1008,31 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
}
}
private void InitializeMemoryManager(AddressSpaceType addrSpaceType, MemoryRegion memRegion)
{
int addrSpaceBits;
switch (addrSpaceType)
{
case AddressSpaceType.Addr32Bits: addrSpaceBits = 32; break;
case AddressSpaceType.Addr36Bits: addrSpaceBits = 36; break;
case AddressSpaceType.Addr32BitsNoMap: addrSpaceBits = 32; break;
case AddressSpaceType.Addr39Bits: addrSpaceBits = 39; break;
default: throw new ArgumentException(nameof(addrSpaceType));
}
bool useFlatPageTable = memRegion == MemoryRegion.Application;
CpuMemory = new MemoryManager(_system.Device.Memory.RamPointer, addrSpaceBits, useFlatPageTable);
MemoryManager = new KMemoryManager(_system, CpuMemory);
Translator = new Translator(CpuMemory);
Translator.CpuTrace += CpuTraceHandler;
}
public void PrintCurrentThreadStackTrace()
{
System.Scheduler.GetCurrentThread().PrintGuestStackTrace();

View file

@ -1,5 +1,4 @@
using ChocolArm64.Events;
using ChocolArm64.Memory;
using ChocolArm64.State;
using Ryujinx.HLE.HOS.Kernel.Process;
using System;
@ -11,14 +10,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
private Switch _device;
private KProcess _process;
private Horizon _system;
private MemoryManager _memory;
public SvcHandler(Switch device, KProcess process)
{
_device = device;
_process = process;
_system = device.System;
_memory = process.CpuMemory;
}
public void SvcCall(object sender, InstExceptionEventArgs e)

View file

@ -93,7 +93,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
private KernelResult SendSyncRequest(ulong messagePtr, ulong size, int handle)
{
byte[] messageData = _memory.ReadBytes((long)messagePtr, (long)size);
byte[] messageData = _process.CpuMemory.ReadBytes((long)messagePtr, (long)size);
KClientSession clientSession = _process.HandleTable.GetObject<KClientSession>(handle);
@ -142,7 +142,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
ipcMessage.Thread.ObjSyncResult = IpcHandler.IpcCall(
_device,
_process,
_memory,
_process.CpuMemory,
ipcMessage.Session,
ipcMessage.Message,
ipcMessage.MessagePtr);

View file

@ -152,14 +152,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{
KMemoryInfo blkInfo = _process.MemoryManager.QueryMemory(position);
_memory.WriteUInt64((long)infoPtr + 0x00, blkInfo.Address);
_memory.WriteUInt64((long)infoPtr + 0x08, blkInfo.Size);
_memory.WriteInt32 ((long)infoPtr + 0x10, (int)blkInfo.State & 0xff);
_memory.WriteInt32 ((long)infoPtr + 0x14, (int)blkInfo.Attribute);
_memory.WriteInt32 ((long)infoPtr + 0x18, (int)blkInfo.Permission);
_memory.WriteInt32 ((long)infoPtr + 0x1c, blkInfo.IpcRefCount);
_memory.WriteInt32 ((long)infoPtr + 0x20, blkInfo.DeviceRefCount);
_memory.WriteInt32 ((long)infoPtr + 0x24, 0);
_process.CpuMemory.WriteUInt64((long)infoPtr + 0x00, blkInfo.Address);
_process.CpuMemory.WriteUInt64((long)infoPtr + 0x08, blkInfo.Size);
_process.CpuMemory.WriteInt32 ((long)infoPtr + 0x10, (int)blkInfo.State & 0xff);
_process.CpuMemory.WriteInt32 ((long)infoPtr + 0x14, (int)blkInfo.Attribute);
_process.CpuMemory.WriteInt32 ((long)infoPtr + 0x18, (int)blkInfo.Permission);
_process.CpuMemory.WriteInt32 ((long)infoPtr + 0x1c, blkInfo.IpcRefCount);
_process.CpuMemory.WriteInt32 ((long)infoPtr + 0x20, blkInfo.DeviceRefCount);
_process.CpuMemory.WriteInt32 ((long)infoPtr + 0x24, 0);
return KernelResult.Success;
}

View file

@ -201,7 +201,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
private void OutputDebugString(ulong strPtr, ulong size)
{
string str = MemoryHelper.ReadAsciiString(_memory, (long)strPtr, (long)size);
string str = MemoryHelper.ReadAsciiString(_process.CpuMemory, (long)strPtr, (long)size);
Logger.PrintWarning(LogClass.KernelSvc, str);
}

View file

@ -1,3 +1,4 @@
using ChocolArm64.Memory;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading;
@ -346,79 +347,81 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidThread;
}
_memory.WriteUInt64((long)address + 0x0, thread.Context.ThreadState.X0);
_memory.WriteUInt64((long)address + 0x8, thread.Context.ThreadState.X1);
_memory.WriteUInt64((long)address + 0x10, thread.Context.ThreadState.X2);
_memory.WriteUInt64((long)address + 0x18, thread.Context.ThreadState.X3);
_memory.WriteUInt64((long)address + 0x20, thread.Context.ThreadState.X4);
_memory.WriteUInt64((long)address + 0x28, thread.Context.ThreadState.X5);
_memory.WriteUInt64((long)address + 0x30, thread.Context.ThreadState.X6);
_memory.WriteUInt64((long)address + 0x38, thread.Context.ThreadState.X7);
_memory.WriteUInt64((long)address + 0x40, thread.Context.ThreadState.X8);
_memory.WriteUInt64((long)address + 0x48, thread.Context.ThreadState.X9);
_memory.WriteUInt64((long)address + 0x50, thread.Context.ThreadState.X10);
_memory.WriteUInt64((long)address + 0x58, thread.Context.ThreadState.X11);
_memory.WriteUInt64((long)address + 0x60, thread.Context.ThreadState.X12);
_memory.WriteUInt64((long)address + 0x68, thread.Context.ThreadState.X13);
_memory.WriteUInt64((long)address + 0x70, thread.Context.ThreadState.X14);
_memory.WriteUInt64((long)address + 0x78, thread.Context.ThreadState.X15);
_memory.WriteUInt64((long)address + 0x80, thread.Context.ThreadState.X16);
_memory.WriteUInt64((long)address + 0x88, thread.Context.ThreadState.X17);
_memory.WriteUInt64((long)address + 0x90, thread.Context.ThreadState.X18);
_memory.WriteUInt64((long)address + 0x98, thread.Context.ThreadState.X19);
_memory.WriteUInt64((long)address + 0xa0, thread.Context.ThreadState.X20);
_memory.WriteUInt64((long)address + 0xa8, thread.Context.ThreadState.X21);
_memory.WriteUInt64((long)address + 0xb0, thread.Context.ThreadState.X22);
_memory.WriteUInt64((long)address + 0xb8, thread.Context.ThreadState.X23);
_memory.WriteUInt64((long)address + 0xc0, thread.Context.ThreadState.X24);
_memory.WriteUInt64((long)address + 0xc8, thread.Context.ThreadState.X25);
_memory.WriteUInt64((long)address + 0xd0, thread.Context.ThreadState.X26);
_memory.WriteUInt64((long)address + 0xd8, thread.Context.ThreadState.X27);
_memory.WriteUInt64((long)address + 0xe0, thread.Context.ThreadState.X28);
_memory.WriteUInt64((long)address + 0xe8, thread.Context.ThreadState.X29);
_memory.WriteUInt64((long)address + 0xf0, thread.Context.ThreadState.X30);
_memory.WriteUInt64((long)address + 0xf8, thread.Context.ThreadState.X31);
MemoryManager memory = currentProcess.CpuMemory;
_memory.WriteInt64((long)address + 0x100, thread.LastPc);
memory.WriteUInt64((long)address + 0x0, thread.Context.ThreadState.X0);
memory.WriteUInt64((long)address + 0x8, thread.Context.ThreadState.X1);
memory.WriteUInt64((long)address + 0x10, thread.Context.ThreadState.X2);
memory.WriteUInt64((long)address + 0x18, thread.Context.ThreadState.X3);
memory.WriteUInt64((long)address + 0x20, thread.Context.ThreadState.X4);
memory.WriteUInt64((long)address + 0x28, thread.Context.ThreadState.X5);
memory.WriteUInt64((long)address + 0x30, thread.Context.ThreadState.X6);
memory.WriteUInt64((long)address + 0x38, thread.Context.ThreadState.X7);
memory.WriteUInt64((long)address + 0x40, thread.Context.ThreadState.X8);
memory.WriteUInt64((long)address + 0x48, thread.Context.ThreadState.X9);
memory.WriteUInt64((long)address + 0x50, thread.Context.ThreadState.X10);
memory.WriteUInt64((long)address + 0x58, thread.Context.ThreadState.X11);
memory.WriteUInt64((long)address + 0x60, thread.Context.ThreadState.X12);
memory.WriteUInt64((long)address + 0x68, thread.Context.ThreadState.X13);
memory.WriteUInt64((long)address + 0x70, thread.Context.ThreadState.X14);
memory.WriteUInt64((long)address + 0x78, thread.Context.ThreadState.X15);
memory.WriteUInt64((long)address + 0x80, thread.Context.ThreadState.X16);
memory.WriteUInt64((long)address + 0x88, thread.Context.ThreadState.X17);
memory.WriteUInt64((long)address + 0x90, thread.Context.ThreadState.X18);
memory.WriteUInt64((long)address + 0x98, thread.Context.ThreadState.X19);
memory.WriteUInt64((long)address + 0xa0, thread.Context.ThreadState.X20);
memory.WriteUInt64((long)address + 0xa8, thread.Context.ThreadState.X21);
memory.WriteUInt64((long)address + 0xb0, thread.Context.ThreadState.X22);
memory.WriteUInt64((long)address + 0xb8, thread.Context.ThreadState.X23);
memory.WriteUInt64((long)address + 0xc0, thread.Context.ThreadState.X24);
memory.WriteUInt64((long)address + 0xc8, thread.Context.ThreadState.X25);
memory.WriteUInt64((long)address + 0xd0, thread.Context.ThreadState.X26);
memory.WriteUInt64((long)address + 0xd8, thread.Context.ThreadState.X27);
memory.WriteUInt64((long)address + 0xe0, thread.Context.ThreadState.X28);
memory.WriteUInt64((long)address + 0xe8, thread.Context.ThreadState.X29);
memory.WriteUInt64((long)address + 0xf0, thread.Context.ThreadState.X30);
memory.WriteUInt64((long)address + 0xf8, thread.Context.ThreadState.X31);
_memory.WriteUInt64((long)address + 0x108, (ulong)thread.Context.ThreadState.Psr);
memory.WriteInt64((long)address + 0x100, thread.LastPc);
_memory.WriteVector128((long)address + 0x110, thread.Context.ThreadState.V0);
_memory.WriteVector128((long)address + 0x120, thread.Context.ThreadState.V1);
_memory.WriteVector128((long)address + 0x130, thread.Context.ThreadState.V2);
_memory.WriteVector128((long)address + 0x140, thread.Context.ThreadState.V3);
_memory.WriteVector128((long)address + 0x150, thread.Context.ThreadState.V4);
_memory.WriteVector128((long)address + 0x160, thread.Context.ThreadState.V5);
_memory.WriteVector128((long)address + 0x170, thread.Context.ThreadState.V6);
_memory.WriteVector128((long)address + 0x180, thread.Context.ThreadState.V7);
_memory.WriteVector128((long)address + 0x190, thread.Context.ThreadState.V8);
_memory.WriteVector128((long)address + 0x1a0, thread.Context.ThreadState.V9);
_memory.WriteVector128((long)address + 0x1b0, thread.Context.ThreadState.V10);
_memory.WriteVector128((long)address + 0x1c0, thread.Context.ThreadState.V11);
_memory.WriteVector128((long)address + 0x1d0, thread.Context.ThreadState.V12);
_memory.WriteVector128((long)address + 0x1e0, thread.Context.ThreadState.V13);
_memory.WriteVector128((long)address + 0x1f0, thread.Context.ThreadState.V14);
_memory.WriteVector128((long)address + 0x200, thread.Context.ThreadState.V15);
_memory.WriteVector128((long)address + 0x210, thread.Context.ThreadState.V16);
_memory.WriteVector128((long)address + 0x220, thread.Context.ThreadState.V17);
_memory.WriteVector128((long)address + 0x230, thread.Context.ThreadState.V18);
_memory.WriteVector128((long)address + 0x240, thread.Context.ThreadState.V19);
_memory.WriteVector128((long)address + 0x250, thread.Context.ThreadState.V20);
_memory.WriteVector128((long)address + 0x260, thread.Context.ThreadState.V21);
_memory.WriteVector128((long)address + 0x270, thread.Context.ThreadState.V22);
_memory.WriteVector128((long)address + 0x280, thread.Context.ThreadState.V23);
_memory.WriteVector128((long)address + 0x290, thread.Context.ThreadState.V24);
_memory.WriteVector128((long)address + 0x2a0, thread.Context.ThreadState.V25);
_memory.WriteVector128((long)address + 0x2b0, thread.Context.ThreadState.V26);
_memory.WriteVector128((long)address + 0x2c0, thread.Context.ThreadState.V27);
_memory.WriteVector128((long)address + 0x2d0, thread.Context.ThreadState.V28);
_memory.WriteVector128((long)address + 0x2e0, thread.Context.ThreadState.V29);
_memory.WriteVector128((long)address + 0x2f0, thread.Context.ThreadState.V30);
_memory.WriteVector128((long)address + 0x300, thread.Context.ThreadState.V31);
memory.WriteUInt64((long)address + 0x108, (ulong)thread.Context.ThreadState.Psr);
_memory.WriteInt32((long)address + 0x310, thread.Context.ThreadState.Fpcr);
_memory.WriteInt32((long)address + 0x314, thread.Context.ThreadState.Fpsr);
_memory.WriteInt64((long)address + 0x318, thread.Context.ThreadState.Tpidr);
memory.WriteVector128((long)address + 0x110, thread.Context.ThreadState.V0);
memory.WriteVector128((long)address + 0x120, thread.Context.ThreadState.V1);
memory.WriteVector128((long)address + 0x130, thread.Context.ThreadState.V2);
memory.WriteVector128((long)address + 0x140, thread.Context.ThreadState.V3);
memory.WriteVector128((long)address + 0x150, thread.Context.ThreadState.V4);
memory.WriteVector128((long)address + 0x160, thread.Context.ThreadState.V5);
memory.WriteVector128((long)address + 0x170, thread.Context.ThreadState.V6);
memory.WriteVector128((long)address + 0x180, thread.Context.ThreadState.V7);
memory.WriteVector128((long)address + 0x190, thread.Context.ThreadState.V8);
memory.WriteVector128((long)address + 0x1a0, thread.Context.ThreadState.V9);
memory.WriteVector128((long)address + 0x1b0, thread.Context.ThreadState.V10);
memory.WriteVector128((long)address + 0x1c0, thread.Context.ThreadState.V11);
memory.WriteVector128((long)address + 0x1d0, thread.Context.ThreadState.V12);
memory.WriteVector128((long)address + 0x1e0, thread.Context.ThreadState.V13);
memory.WriteVector128((long)address + 0x1f0, thread.Context.ThreadState.V14);
memory.WriteVector128((long)address + 0x200, thread.Context.ThreadState.V15);
memory.WriteVector128((long)address + 0x210, thread.Context.ThreadState.V16);
memory.WriteVector128((long)address + 0x220, thread.Context.ThreadState.V17);
memory.WriteVector128((long)address + 0x230, thread.Context.ThreadState.V18);
memory.WriteVector128((long)address + 0x240, thread.Context.ThreadState.V19);
memory.WriteVector128((long)address + 0x250, thread.Context.ThreadState.V20);
memory.WriteVector128((long)address + 0x260, thread.Context.ThreadState.V21);
memory.WriteVector128((long)address + 0x270, thread.Context.ThreadState.V22);
memory.WriteVector128((long)address + 0x280, thread.Context.ThreadState.V23);
memory.WriteVector128((long)address + 0x290, thread.Context.ThreadState.V24);
memory.WriteVector128((long)address + 0x2a0, thread.Context.ThreadState.V25);
memory.WriteVector128((long)address + 0x2b0, thread.Context.ThreadState.V26);
memory.WriteVector128((long)address + 0x2c0, thread.Context.ThreadState.V27);
memory.WriteVector128((long)address + 0x2d0, thread.Context.ThreadState.V28);
memory.WriteVector128((long)address + 0x2e0, thread.Context.ThreadState.V29);
memory.WriteVector128((long)address + 0x2f0, thread.Context.ThreadState.V30);
memory.WriteVector128((long)address + 0x300, thread.Context.ThreadState.V31);
memory.WriteInt32((long)address + 0x310, thread.Context.ThreadState.Fpcr);
memory.WriteInt32((long)address + 0x314, thread.Context.ThreadState.Fpsr);
memory.WriteInt64((long)address + 0x318, thread.Context.ThreadState.Tpidr);
return KernelResult.Success;
}

View file

@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
for (int index = 0; index < handlesCount; index++)
{
int handle = _memory.ReadInt32((long)handlesPtr + index * 4);
int handle = _process.CpuMemory.ReadInt32((long)handlesPtr + index * 4);
KSynchronizationObject syncObj = _process.HandleTable.GetObject<KSynchronizationObject>(handle);

View file

@ -50,7 +50,7 @@ namespace Ryujinx.Tests.Cpu
_entryPoint = Position;
_ramPointer = Marshal.AllocHGlobal(new IntPtr(_size));
_memory = new MemoryManager(_ramPointer, 1L << 32);
_memory = new MemoryManager(_ramPointer);
_memory.Map(Position, 0, _size);
Translator translator = new Translator(_memory);