From 1dac13be16c83f5762eba8d4b4080907d531f517 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 10 Oct 2014 01:26:04 +0400 Subject: [PATCH] RSXIO memory mapping with strict ordering (draft) --- rpcs3/Emu/RSX/RSXThread.cpp | 36 +++++++++++++--- rpcs3/Emu/RSX/RSXThread.h | 1 + rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 52 ++++++++++++++--------- rpcs3/Emu/SysCalls/Modules/cellGcmSys.h | 4 +- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 2 +- 5 files changed, 66 insertions(+), 29 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 509ff8b303..52c2d01890 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -3,6 +3,7 @@ #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" +#include "Emu/RSX/GSManager.h" #include "RSXThread.h" #include "Emu/SysCalls/Callback.h" @@ -45,15 +46,40 @@ void RSXThread::nativeRescale(float width, float height) u32 GetAddress(u32 offset, u32 location) { + u32 res = 0; + switch(location) { - case CELL_GCM_LOCATION_LOCAL: return (u32)Memory.RSXFBMem.GetStartAddr() + offset; - case CELL_GCM_LOCATION_MAIN: return (u32)Memory.RSXIOMem.RealAddr(offset); // TODO: Error Check? + case CELL_GCM_LOCATION_LOCAL: + { + res = (u32)Memory.RSXFBMem.GetStartAddr() + offset; + break; + } + case CELL_GCM_LOCATION_MAIN: + { + res = (u32)Memory.RSXIOMem.RealAddr(offset); // TODO: Error Check? + if (res == 0) + { + LOG_ERROR(RSX, "GetAddress(offset=0x%x): RSXIO memory not mapped", offset); + Emu.Pause(); + break; + } + + if (Emu.GetGSManager().GetRender().m_strict_ordering[offset >> 20]) + { + _mm_mfence(); // probably doesn't have any effect on current implementation + } + break; + } + default: + { + LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x): invalid location", offset, location); + Emu.Pause(); + break; + } } - LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x)", location); - assert(0); - return 0; + return res; } RSXVertexData::RSXVertexData() diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index f6763e2e80..2ad4dfe254 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -134,6 +134,7 @@ public: u32 m_report_main_addr; u32 m_local_mem_addr, m_main_mem_addr; + bool m_strict_ordering[0x1000]; public: uint m_draw_mode; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 1200f9408b..ce69c39c23 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -61,11 +61,11 @@ CellGcmOffsetTable offsetTable; void InitOffsetTable() { - offsetTable.ioAddress = (u32)Memory.Alloc(3072 * sizeof(u16), 1); - offsetTable.eaAddress = (u32)Memory.Alloc(512 * sizeof(u16), 1); + offsetTable.ioAddress.set(be_t::make((u32)Memory.Alloc(3072 * sizeof(u16), 1))); + offsetTable.eaAddress.set(be_t::make((u32)Memory.Alloc(512 * sizeof(u16), 1))); - memset(vm::get_ptr(offsetTable.ioAddress), 0xFF, 3072 * sizeof(u16)); - memset(vm::get_ptr(offsetTable.eaAddress), 0xFF, 512 * sizeof(u16)); + memset(offsetTable.ioAddress.get_ptr(), 0xFF, 3072 * sizeof(u16)); + memset(offsetTable.eaAddress.get_ptr(), 0xFF, 512 * sizeof(u16)); } //---------------------------------------------------------------------------- @@ -129,7 +129,7 @@ u32 cellGcmGetNotifyDataAddress(u32 index) cellGcmGetOffsetTable(table); // If entry not in use, return NULL - u16 entry = vm::read16(table->eaAddress + 241 * sizeof(u16)); + u16 entry = table->eaAddress[241]; if (entry == 0xFFFF) { return 0; } @@ -814,7 +814,7 @@ s32 cellGcmAddressToOffset(u64 address, vm::ptr> offset) // Address in main memory else check else { - u16 upper12Bits = vm::read16(offsetTable.ioAddress + sizeof(u16)*(address >> 20)); + u16 upper12Bits = offsetTable.ioAddress[address >> 20]; // If the address is mapped in IO if (upper12Bits != 0xFFFF) { @@ -858,10 +858,8 @@ s32 cellGcmIoOffsetToAddress(u32 ioOffset, u64 address) return CELL_OK; } -s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size) +s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict) { - cellGcmSys->Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size); - if ((ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE; // Check if the mapping was successfull @@ -870,8 +868,9 @@ s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size) // Fill the offset table for (u32 i = 0; i<(size >> 20); i++) { - vm::write16(offsetTable.ioAddress + ((ea >> 20) + i)*sizeof(u16), (io >> 20) + i); - vm::write16(offsetTable.eaAddress + ((io >> 20) + i)*sizeof(u16), (ea >> 20) + i); + offsetTable.ioAddress[(ea >> 20) + i] = (io >> 20) + i; + offsetTable.eaAddress[(io >> 20) + i] = (ea >> 20) + i; + Emu.GetGSManager().GetRender().m_strict_ordering[(io >> 20) + i] = is_strict; } } else @@ -883,10 +882,20 @@ s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size) return CELL_OK; } +s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size) +{ + cellGcmSys->Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size); + + return gcmMapEaIoAddress(ea, io, size, false); +} + s32 cellGcmMapEaIoAddressWithFlags(u32 ea, u32 io, u32 size, u32 flags) { cellGcmSys->Warning("cellGcmMapEaIoAddressWithFlags(ea=0x%x, io=0x%x, size=0x%x, flags=0x%x)", ea, io, size, flags); - return cellGcmMapEaIoAddress(ea, io, size); // TODO: strict ordering + + assert(flags == 2 /*CELL_GCM_IOMAP_FLAG_STRICT_ORDERING*/); + + return gcmMapEaIoAddress(ea, io, size, true); } s32 cellGcmMapLocalMemory(u64 address, u64 size) @@ -919,13 +928,14 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr> offset) u32 io = Memory.RSXIOMem.Map(ea, size); //check if the mapping was successfull - if (Memory.RSXIOMem.Write32(io, 0)) + if (Memory.RSXIOMem.RealAddr(io) == ea) { //fill the offset table for (u32 i = 0; i<(size >> 20); i++) { - vm::write16(offsetTable.ioAddress + ((ea >> 20) + i) * sizeof(u16), (u16)(io >> 20) + i); - vm::write16(offsetTable.eaAddress + ((io >> 20) + i) * sizeof(u16), (u16)(ea >> 20) + i); + offsetTable.ioAddress[(ea >> 20) + i] = (u16)(io >> 20) + i; + offsetTable.eaAddress[(io >> 20) + i] = (u16)(ea >> 20) + i; + Emu.GetGSManager().GetRender().m_strict_ordering[(io >> 20) + i] = false; } *offset = io; @@ -970,12 +980,12 @@ s32 cellGcmUnmapEaIoAddress(u64 ea) { u64 io; ea = ea >> 20; - io = vm::read16(offsetTable.ioAddress + (ea*sizeof(u16))); + io = offsetTable.ioAddress[ea]; for (u32 i = 0; i> 20; - ea = vm::read16(offsetTable.eaAddress + (io*sizeof(u16))); + ea = offsetTable.eaAddress[io]; for (u32 i = 0; i ioAddress; // u16* - be_t eaAddress; // u16* + vm::bptr ioAddress; + vm::bptr eaAddress; }; // Auxiliary functions diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index f9e931ad60..bb7f9fc910 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -34,7 +34,7 @@ void sys_ppu_thread_exit(PPUThread& CPU, u64 errorcode) void sys_internal_ppu_thread_exit(PPUThread& CPU, u64 errorcode) { - sys_ppu_thread.Log("sys_internal_ppu_thread_exit(0x%llx)", errorcode); + sys_ppu_thread.Warning("sys_internal_ppu_thread_exit(0x%llx)", errorcode); ppu_thread_exit(CPU, errorcode); }