diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index dbac50e797..6379fabb02 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -1,5 +1,7 @@ #include "stdafx.h" #include "Memory.h" +#include "Emu/CPU/CPUThread.h" +#include "Emu/Cell/PPUThread.h" namespace vm { @@ -143,4 +145,84 @@ namespace vm { Memory.Close(); } + + u32 stack_push(CPUThread& CPU, u32 size, u32 align_v, u32& old_pos) + { + switch (CPU.GetType()) + { + case CPU_THREAD_PPU: + { + PPUThread& PPU = static_cast(CPU); + + assert(align_v); + old_pos = (u32)PPU.GPR[1]; + PPU.GPR[1] -= align(size, 8); // room minimal possible size + PPU.GPR[1] &= ~(align_v - 1); // fix stack alignment + + if (PPU.GPR[1] < CPU.GetStackAddr()) + { + // stack overflow + PPU.GPR[1] = old_pos; + return 0; + } + else + { + return (u32)PPU.GPR[1]; + } + } + + case CPU_THREAD_SPU: + case CPU_THREAD_RAW_SPU: + { + assert(!"stack_push(): SPU not supported"); + return 0; + } + + case CPU_THREAD_ARMv7: + { + assert(!"stack_push(): ARMv7 not supported"); + return 0; + } + + default: + { + assert(!"stack_push(): invalid thread type"); + return 0; + } + } + } + + void stack_pop(CPUThread& CPU, u32 addr, u32 old_pos) + { + switch (CPU.GetType()) + { + case CPU_THREAD_PPU: + { + PPUThread& PPU = static_cast(CPU); + + assert(PPU.GPR[1] == addr); + PPU.GPR[1] = old_pos; + return; + } + + case CPU_THREAD_SPU: + case CPU_THREAD_RAW_SPU: + { + assert(!"stack_pop(): SPU not supported"); + return; + } + + case CPU_THREAD_ARMv7: + { + assert(!"stack_pop(): ARMv7 not supported"); + return; + } + + default: + { + assert(!"stack_pop(): invalid thread type"); + return; + } + } + } } \ No newline at end of file diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index c3d637abda..9a1862de96 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -1,5 +1,10 @@ #pragma once +class CPUThread; +class PPUThread; +class SPUThread; +class ARMv7Thread; + namespace vm { template @@ -495,4 +500,152 @@ namespace vm return (NT*)(m_ptr + offset); } }; + + u32 stack_push(CPUThread& CPU, u32 size, u32 align, u32& old_pos); + void stack_pop(CPUThread& CPU, u32 addr, u32 old_pos); + + template + class stackvar + { + T* m_ptr; + u32 m_addr; + u32 m_size; + u32 m_align; + u32 m_old_pos; + CPUThread& m_thread; + + void alloc() + { + m_addr = stack_push(m_thread, m_size, m_align, m_old_pos); + m_ptr = vm::get_ptr(m_addr); + } + + void dealloc() + { + if (m_addr) + { + stack_pop(m_thread, m_addr, m_old_pos); + m_addr = 0; + m_ptr = vm::get_ptr(0u); + } + } + + public: + stackvar(PPUThread& CPU, u32 size = sizeof(T), u32 align = __alignof(T)) + : m_size(size) + , m_align(align) + , m_thread(CPU) + { + alloc(); + } + + stackvar(SPUThread& CPU, u32 size = sizeof(T), u32 align = __alignof(T)) + : m_size(size) + , m_align(align) + , m_thread(CPU) + { + alloc(); + } + + stackvar(ARMv7Thread& CPU, u32 size = sizeof(T), u32 align = __alignof(T)) + : m_size(size) + , m_align(align) + , m_thread(CPU) + { + alloc(); + } + + stackvar(const stackvar& r) + : m_size(r.m_size) + , m_align(r.m_align) + , m_thread(r.m_thread) + { + alloc(); + *m_ptr = *r.m_ptr; + } + + stackvar(stackvar&& r) + : m_ptr(r.m_ptr) + , m_addr(r.m_addr) + , m_size(r.m_size) + , m_align(r.m_align) + , m_old_pos(r.m_old_pos) + , m_thread(r.m_thread) + { + r.m_addr = 0; + r.m_ptr = vm::get_ptr(0u); + } + + ~stackvar() + { + dealloc(); + } + + T* operator -> () + { + return m_ptr; + } + + const T* operator -> () const + { + return m_ptr; + } + + T* get_ptr() + { + return m_ptr; + } + + const T* get_ptr() const + { + return m_ptr; + } + + T& value() + { + return *m_ptr; + } + + const T& value() const + { + return *m_ptr; + } + + u32 addr() const + { + return m_addr; + } + + u32 size() const + { + return m_size; + } + + /* + operator const ref() const + { + return addr(); + } + */ + + template operator const ps3::ptr() const + { + return ps3::ptr::make(m_addr); + } + + template operator const ps3::ptr() const + { + return ps3::ptr::make(m_addr); + } + + operator T&() + { + return *m_ptr; + } + + operator const T&() const + { + return *m_ptr; + } + }; } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellFont.cpp b/rpcs3/Emu/SysCalls/Modules/cellFont.cpp index 0d709d6d39..69199e2f2c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFont.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellFont.cpp @@ -36,11 +36,11 @@ int cellFontGetRevisionFlags(vm::ptr> revisionFlags) return CELL_FONT_OK; } -int cellFontInit(vm::ptr config) +int cellFontInit(PPUThread& CPU, vm::ptr config) { cellFont->Log("cellFontInit(config=0x%x)", config.addr()); - vm::var> revisionFlags; + vm::stackvar> revisionFlags(CPU); revisionFlags.value() = 0; cellFontGetRevisionFlags(revisionFlags); return cellFontInitializeWithRevision(revisionFlags.value(), config); @@ -101,7 +101,7 @@ int cellFontOpenFontFile(vm::ptr library, vm::ptr f return ret; } -int cellFontOpenFontset(vm::ptr library, vm::ptr fontType, vm::ptr font) +int cellFontOpenFontset(PPUThread& CPU, vm::ptr library, vm::ptr fontType, vm::ptr font) { cellFont->Log("cellFontOpenFontset(library_addr=0x%x, fontType_addr=0x%x, font_addr=0x%x)", library.addr(), fontType.addr(), font.addr()); @@ -177,7 +177,7 @@ int cellFontOpenFontset(vm::ptr library, vm::ptr return CELL_FONT_ERROR_NO_SUPPORT_FONTSET; } - vm::var f((u32)file.length() + 1, 1); + vm::stackvar f(CPU, (u32)file.length() + 1, 1); memcpy(f.get_ptr(), file.c_str(), file.size() + 1); int ret = cellFontOpenFontFile(library, f, 0, 0, font); //TODO: Find the correct values of subNum, uniqueId font->origin = CELL_FONT_OPEN_FONTSET; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 227d43ca96..e2a82abf0f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -201,7 +201,7 @@ int cellGameContentPermit(vm::ptr contentInfoPath, vm: return CELL_GAME_RET_OK; } -int cellGameDataCheckCreate2(u32 version, vm::ptr dirName, u32 errDialog, +int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container) { cellGame->Warning("cellGameDataCheckCreate(2)(version=0x%x, dirName_addr=0x%x, errDialog=0x%x, funcStat_addr=0x%x, container=%d)", @@ -238,10 +238,9 @@ int cellGameDataCheckCreate2(u32 version, vm::ptr dirName, u32 errDi return CELL_GAMEDATA_ERROR_BROKEN; } - // TODO: use memory container - vm::var cbResult; - vm::var cbGet; - vm::var cbSet; + vm::stackvar cbResult(CPU); + vm::stackvar cbGet(CPU); + vm::stackvar cbSet(CPU); cbGet.value() = {}; @@ -307,11 +306,11 @@ int cellGameDataCheckCreate2(u32 version, vm::ptr dirName, u32 errDi } } -int cellGameDataCheckCreate(u32 version, vm::ptr dirName, u32 errDialog, +int cellGameDataCheckCreate(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container) { // TODO: almost identical, the only difference is that this function will always calculate the size of game data - return cellGameDataCheckCreate2(version, dirName, errDialog, funcStat, container); + return cellGameDataCheckCreate2(CPU, version, dirName, errDialog, funcStat, container); } int cellGameCreateGameData(vm::ptr init, vm::ptr tmp_contentInfoPath, vm::ptr tmp_usrdirPath) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.h b/rpcs3/Emu/SysCalls/Modules/cellGame.h index 0e7f6e3e95..1ccda34eb1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.h +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.h @@ -199,4 +199,4 @@ struct CellGameDataStatSet { vm::bptr setParam; be_t reserved; -}; \ No newline at end of file +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index fca2ca40f7..a557d3abd8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -1287,7 +1287,7 @@ s32 _cellSyncLFQueueCompletePushPointer2(vm::ptr queue, s32 poi return syncLFQueueCompletePushPointer2(queue, pointer, fpSendSignal); } -s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr buffer, u32 isBlocking) +s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr queue, vm::ptr buffer, u32 isBlocking) { // cellSyncLFQueuePush has 1 in isBlocking param, cellSyncLFQueueTryPush has 0 cellSync->Warning("_cellSyncLFQueuePushBody(queue_addr=0x%x, buffer_addr=0x%x, isBlocking=%d)", queue.addr(), buffer.addr(), isBlocking); @@ -1302,10 +1302,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr } s32 position; - //syncLFQueueDump(queue); - #ifdef PRX_DEBUG - vm::var> position_v; + vm::stackvar> position_v(CPU); #endif while (true) { @@ -1314,7 +1312,7 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) { #ifdef PRX_DEBUG_XXX - res = cb_caller, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x24B0, libsre_rtoc, + res = cb_call, u32, u32, u64>(CPU, libsre + 0x24B0, libsre_rtoc, queue, position_v.addr(), isBlocking, 0); position = position_v->ToLE(); #else @@ -1324,7 +1322,7 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr else { #ifdef PRX_DEBUG - res = cb_call, u32, u32, u64>(GetCurrentPPUThread(), libsre + 0x3050, libsre_rtoc, + res = cb_call, u32, u32, u64>(CPU, libsre + 0x3050, libsre_rtoc, queue, position_v.addr(), isBlocking, 0); position = position_v->ToLE(); #else @@ -1332,9 +1330,6 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr #endif } - //LOG_NOTICE(HLE, "... position = %d", position); - //syncLFQueueDump(queue); - if (!isBlocking || res != CELL_SYNC_ERROR_AGAIN) { if (res) @@ -1360,7 +1355,7 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) { #ifdef PRX_DEBUG_XXX - res = cb_caller, s32, u64>::call(GetCurrentPPUThread(), libsre + 0x26C0, libsre_rtoc, + res = cb_call, s32, u64>(CPU, libsre + 0x26C0, libsre_rtoc, queue, position, 0); #else res = syncLFQueueCompletePushPointer(queue, position, nullptr); @@ -1369,14 +1364,13 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr else { #ifdef PRX_DEBUG - res = cb_call, s32, u64>(GetCurrentPPUThread(), libsre + 0x355C, libsre_rtoc, + res = cb_call, s32, u64>(CPU, libsre + 0x355C, libsre_rtoc, queue, position, 0); #else res = syncLFQueueCompletePushPointer2(queue, position, nullptr); #endif } - //syncLFQueueDump(queue); return res; } @@ -1669,7 +1663,7 @@ s32 _cellSyncLFQueueCompletePopPointer2(vm::ptr queue, s32 poin return syncLFQueueCompletePopPointer2(queue, pointer, fpSendSignal, noQueueFull); } -s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer, u32 isBlocking) +s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr queue, vm::ptr buffer, u32 isBlocking) { // cellSyncLFQueuePop has 1 in isBlocking param, cellSyncLFQueueTryPop has 0 cellSync->Warning("_cellSyncLFQueuePopBody(queue_addr=0x%x, buffer_addr=0x%x, isBlocking=%d)", queue.addr(), buffer.addr(), isBlocking); @@ -1685,7 +1679,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer s32 position; #ifdef PRX_DEBUG - vm::var> position_v; + vm::stackvar> position_v(CPU); #endif while (true) { @@ -1693,7 +1687,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) { #ifdef PRX_DEBUG_XXX - res = cb_caller, u32, u32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x2A90, libsre_rtoc, + res = cb_call, u32, u32, u64, u64>(CPU, libsre + 0x2A90, libsre_rtoc, queue, position_v.addr(), isBlocking, 0, 0); position = position_v->ToLE(); #else @@ -1703,7 +1697,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer else { #ifdef PRX_DEBUG - res = cb_call, u32, u32, u64>(GetCurrentPPUThread(), libsre + 0x39AC, libsre_rtoc, + res = cb_call, u32, u32, u64>(CPU, libsre + 0x39AC, libsre_rtoc, queue, position_v.addr(), isBlocking, 0); position = position_v->ToLE(); #else @@ -1736,7 +1730,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) { #ifdef PRX_DEBUG_XXX - res = cb_caller, s32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x2CA8, libsre_rtoc, + res = cb_call, s32, u64, u64>(CPU, libsre + 0x2CA8, libsre_rtoc, queue, position, 0, 0); #else res = syncLFQueueCompletePopPointer(queue, position, nullptr, 0); @@ -1745,7 +1739,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer else { #ifdef PRX_DEBUG - res = cb_call, s32, u64, u64>(GetCurrentPPUThread(), libsre + 0x3EB8, libsre_rtoc, + res = cb_call, s32, u64, u64>(CPU, libsre + 0x3EB8, libsre_rtoc, queue, position, 0, 0); #else res = syncLFQueueCompletePopPointer2(queue, position, nullptr, 0); @@ -1926,10 +1920,10 @@ s32 _cellSyncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr spus, u32 num, vm::ptr queue) +s32 syncLFQueueDetachLv2EventQueue(PPUThread& CPU, vm::ptr spus, u32 num, vm::ptr queue) { #ifdef PRX_DEBUG - return cb_call, u32, vm::ptr>(GetCurrentPPUThread(), libsre + 0x1DA0, libsre_rtoc, + return cb_call, u32, vm::ptr>(CPU, libsre + 0x1DA0, libsre_rtoc, spus, num, queue); #endif diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 44458c905c..06c419b4b8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -835,10 +835,10 @@ int cellWebBrowserEstimate2(const vm::ptr config, v return CELL_OK; } -extern int cellGameDataCheckCreate2(u32 version, vm::ptr dirName, u32 errDialog, +extern int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container); -extern int cellGameDataCheckCreate(u32 version, vm::ptr dirName, u32 errDialog, +extern int cellGameDataCheckCreate(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container); extern void cellSysutil_SaveData_init(); diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index faf91a529f..767c3c04da 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -286,7 +286,7 @@ s32 _sys_spu_printf_finalize() return CELL_OK; } -s64 _sys_spu_printf_attach_group(u32 group) +s32 _sys_spu_printf_attach_group(PPUThread& CPU, u32 group) { sysPrxForUser->Warning("_sys_spu_printf_attach_group(group=%d)", group); @@ -295,10 +295,10 @@ s64 _sys_spu_printf_attach_group(u32 group) return CELL_ESTAT; } - return spu_printf_agcb(group); + return spu_printf_agcb.call(CPU, group); } -s64 _sys_spu_printf_detach_group(u32 group) +s32 _sys_spu_printf_detach_group(PPUThread& CPU, u32 group) { sysPrxForUser->Warning("_sys_spu_printf_detach_group(group=%d)", group); @@ -307,10 +307,10 @@ s64 _sys_spu_printf_detach_group(u32 group) return CELL_ESTAT; } - return spu_printf_dgcb(group); + return spu_printf_dgcb.call(CPU, group); } -s64 _sys_spu_printf_attach_thread(u32 thread) +s32 _sys_spu_printf_attach_thread(PPUThread& CPU, u32 thread) { sysPrxForUser->Warning("_sys_spu_printf_attach_thread(thread=%d)", thread); @@ -319,10 +319,10 @@ s64 _sys_spu_printf_attach_thread(u32 thread) return CELL_ESTAT; } - return spu_printf_atcb(thread); + return spu_printf_atcb.call(CPU, thread); } -s64 _sys_spu_printf_detach_thread(u32 thread) +s32 _sys_spu_printf_detach_thread(PPUThread& CPU, u32 thread) { sysPrxForUser->Warning("_sys_spu_printf_detach_thread(thread=%d)", thread); @@ -331,7 +331,7 @@ s64 _sys_spu_printf_detach_thread(u32 thread) return CELL_ESTAT; } - return spu_printf_dtcb(thread); + return spu_printf_dtcb.call(CPU, thread); } s32 _sys_snprintf(vm::ptr dst, u32 count, vm::ptr fmt) // va_args... diff --git a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp index 60e09c82fc..ec5e07daed 100644 --- a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp @@ -1000,13 +1000,13 @@ int cellFsAioFinish(vm::ptr mount_point) return CELL_OK; } -int cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr buf, u64 buffer_size, vm::ptr> nread) +int cellFsReadWithOffset(PPUThread& CPU, u32 fd, u64 offset, vm::ptr buf, u64 buffer_size, vm::ptr> nread) { sys_fs->Warning("cellFsReadWithOffset(fd=%d, offset=0x%llx, buf_addr=0x%x, buffer_size=%lld nread=0x%llx)", fd, offset, buf.addr(), buffer_size, nread.addr()); int ret; - vm::var> oldPos, newPos; + vm::stackvar> oldPos(CPU), newPos(CPU); ret = cellFsLseek(fd, 0, CELL_SEEK_CUR, oldPos); // Save the current position if (ret) return ret; ret = cellFsLseek(fd, offset, CELL_SEEK_SET, newPos); // Move to the specified offset