diff --git a/rpcs3/Emu/Memory/atomic.h b/rpcs3/Emu/Memory/atomic.h index 86bd6cc741..27a5f73bef 100644 --- a/rpcs3/Emu/Memory/atomic.h +++ b/rpcs3/Emu/Memory/atomic.h @@ -61,14 +61,6 @@ template<> struct atomic_op_result_t } }; -struct break_never_t -{ - template inline bool operator()(const atomic_op_result_t&) const - { - return false; - } -}; - template union _atomic_base { using type = std::remove_cv_t; @@ -152,7 +144,7 @@ public: } // perform an atomic operation on data (callable object version, first arg is a reference to atomic type) - template auto atomic_op(F func, Args&&... args) volatile -> decltype(func(std::declval(), args...)) + template auto atomic_op(F func, Args&&... args) volatile -> decltype(func(std::declval(), args...)) { while (true) { @@ -165,16 +157,15 @@ public: // call atomic op for the local copy of the old value and save the return value of the function atomic_op_result_t> result(func, to_type(_new), args...); - // 1) check return value using callable object of Break_if type, return if condition met - // 2) atomically compare value with `old`, replace with `_new` and return on success - if (Break_if()(result) || sync_bool_compare_and_swap(&sub_data, old, _new)) return result.move(); + // atomically compare value with `old`, replace with `_new` and return on success + if (sync_bool_compare_and_swap(&sub_data, old, _new)) return result.move(); } } // perform an atomic operation on data (member function version) - template::value>> auto atomic_op(RT(CT::* func)(FArgs...), Args&&... args) volatile -> decltype((std::declval().*func)(args...)) + template::value>> auto atomic_op(RT(CT::* func)(FArgs...), Args&&... args) volatile -> decltype((std::declval().*func)(args...)) { - return atomic_op(std::mem_fn(func), std::forward(args)...); + return atomic_op(std::mem_fn(func), std::forward(args)...); } // atomic bitwise OR, returns previous data diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 6a5d66a66c..306519a079 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -28,10 +28,10 @@ s32 cellHddGameCheck(PPUThread& CPU, u32 version, vm::cptr dirName, u32 er return CELL_HDDGAME_ERROR_PARAM; } - vm::var param; - vm::var result; - vm::var get; - vm::var set; + vm::stackvar param(CPU); + vm::stackvar result(CPU); + vm::stackvar get(CPU); + vm::stackvar set(CPU); get->hddFreeSizeKB = 40 * 1024 * 1024; // 40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run. get->isNewData = CELL_HDDGAME_ISNEWDATA_EXIST; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp index 704af81681..3937e2485b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp @@ -92,26 +92,26 @@ s32 cellGifDecReadHeader( const u64& fileSize = subHandle_data->fileSize; CellGifDecInfo& current_info = subHandle_data->info; - //Write the header to buffer - vm::var buffer; // Alloc buffer for GIF header + // Write the header to buffer + u8 buffer[13]; switch(subHandle_data->src.srcSelect.value()) { case CELL_GIFDEC_BUFFER: - memmove(buffer.begin(), subHandle_data->src.streamPtr.get_ptr(), buffer.size()); + std::memcpy(buffer, subHandle_data->src.streamPtr.get_ptr(), sizeof(buffer)); break; case CELL_GIFDEC_FILE: { auto file = Emu.GetIdManager().get(fd); file->file->Seek(0); - file->file->Read(buffer.begin(), buffer.size()); + file->file->Read(buffer, sizeof(buffer)); break; } } - if (*buffer.To>(0) != 0x47494638 || - (*buffer.To(4) != 0x6139 && *buffer.To(4) != 0x6137)) // Error: The first 6 bytes are not a valid GIF signature + if (*(be_t*)buffer != 0x47494638 || + (*(le_t*)(buffer + 4) != 0x6139 && *(le_t*)(buffer + 4) != 0x6137)) // Error: The first 6 bytes are not a valid GIF signature { return CELL_GIFDEC_ERROR_STREAM_FORMAT; // Surprisingly there is no error code related with headerss } @@ -190,19 +190,19 @@ s32 cellGifDecDecodeData( const CellGifDecOutParam& current_outParam = subHandle_data->outParam; //Copy the GIF file to a buffer - vm::var gif((u32)fileSize); + std::unique_ptr gif(new u8[fileSize]); switch(subHandle_data->src.srcSelect.value()) { case CELL_GIFDEC_BUFFER: - memmove(gif.begin(), subHandle_data->src.streamPtr.get_ptr(), gif.size()); + std::memcpy(gif.get(), subHandle_data->src.streamPtr.get_ptr(), fileSize); break; case CELL_GIFDEC_FILE: { auto file = Emu.GetIdManager().get(fd); file->file->Seek(0); - file->file->Read(gif.ptr(), gif.size()); + file->file->Read(gif.get(), fileSize); break; } } @@ -211,7 +211,7 @@ s32 cellGifDecDecodeData( int width, height, actual_components; auto image = std::unique_ptr ( - stbi_load_from_memory(gif.ptr(), (s32)fileSize, &width, &height, &actual_components, 4), + stbi_load_from_memory(gif.get(), (s32)fileSize, &width, &height, &actual_components, 4), &::free ); diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp index c3a7aa162c..896e25b3c0 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp @@ -100,26 +100,26 @@ s32 cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr const u64& fileSize = subHandle_data->fileSize; CellJpgDecInfo& current_info = subHandle_data->info; - //Write the header to buffer - vm::var buffer((u32)fileSize); + // Write the header to buffer + std::unique_ptr buffer(new u8[fileSize]); switch(subHandle_data->src.srcSelect.value()) { case CELL_JPGDEC_BUFFER: - memmove(buffer.begin(), vm::get_ptr(subHandle_data->src.streamPtr), buffer.size()); + std::memcpy(buffer.get(), vm::get_ptr(subHandle_data->src.streamPtr), fileSize); break; case CELL_JPGDEC_FILE: { auto file = Emu.GetIdManager().get(fd); file->file->Seek(0); - file->file->Read(buffer.ptr(), buffer.size()); + file->file->Read(buffer.get(), fileSize); break; } } - if (*buffer.To(0) != 0xE0FFD8FF || // Error: Not a valid SOI header - *buffer.To(6) != 0x4649464A) // Error: Not a valid JFIF string + if ((le_t&)(buffer[0]) != 0xE0FFD8FF || // Error: Not a valid SOI header + (le_t&)(buffer[6]) != 0x4649464A) // Error: Not a valid JFIF string { return CELL_JPGDEC_ERROR_HEADER; } @@ -175,19 +175,19 @@ s32 cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::cp const CellJpgDecOutParam& current_outParam = subHandle_data->outParam; //Copy the JPG file to a buffer - vm::var jpg((u32)fileSize); + std::unique_ptr jpg(new u8[fileSize]); switch(subHandle_data->src.srcSelect.value()) { case CELL_JPGDEC_BUFFER: - memmove(jpg.begin(), vm::get_ptr(subHandle_data->src.streamPtr), jpg.size()); + std::memcpy(jpg.get(), vm::get_ptr(subHandle_data->src.streamPtr), fileSize); break; case CELL_JPGDEC_FILE: { auto file = Emu.GetIdManager().get(fd); file->file->Seek(0); - file->file->Read(jpg.ptr(), jpg.size()); + file->file->Read(jpg.get(), fileSize); break; } } @@ -196,7 +196,7 @@ s32 cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::cp int width, height, actual_components; auto image = std::unique_ptr ( - stbi_load_from_memory(jpg.ptr(), (s32)fileSize, &width, &height, &actual_components, 4), + stbi_load_from_memory(jpg.get(), (s32)fileSize, &width, &height, &actual_components, 4), &::free ); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index 1cd823d757..2ae0411a9e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -137,20 +137,19 @@ s32 pngReadHeader( return CELL_PNGDEC_ERROR_HEADER; // The file is smaller than the length of a PNG header } - //Write the header to buffer - vm::var buffer; // Alloc buffer for PNG header - auto buffer_32 = buffer.To>(); + // Write the header to buffer + u8 buffer[34]; be_t* buffer_32 = reinterpret_cast*>(buffer); switch (stream->src.srcSelect.value()) { case CELL_PNGDEC_BUFFER: - memmove(buffer.begin(), stream->src.streamPtr.get_ptr(), buffer.size()); + std::memcpy(buffer, stream->src.streamPtr.get_ptr(), sizeof(buffer)); break; case CELL_PNGDEC_FILE: { auto file = Emu.GetIdManager().get(stream->fd); file->file->Seek(0); - file->file->Read(buffer.begin(), buffer.size()); + file->file->Read(buffer, sizeof(buffer)); break; } } @@ -249,20 +248,20 @@ s32 pngDecodeData( const u64& fileSize = stream->fileSize; const CellPngDecOutParam& current_outParam = stream->outParam; - //Copy the PNG file to a buffer - vm::var png((u32)fileSize); + // Copy the PNG file to a buffer + std::unique_ptr png(new u8[fileSize]); switch (stream->src.srcSelect.value()) { case CELL_PNGDEC_BUFFER: - memmove(png.begin(), stream->src.streamPtr.get_ptr(), png.size()); + std::memcpy(png.get(), stream->src.streamPtr.get_ptr(), fileSize); break; case CELL_PNGDEC_FILE: { auto file = Emu.GetIdManager().get(stream->fd); file->file->Seek(0); - file->file->Read(png.ptr(), png.size()); + file->file->Read(png.get(), fileSize); break; } } @@ -271,7 +270,7 @@ s32 pngDecodeData( int width, height, actual_components; auto image = std::unique_ptr ( - stbi_load_from_memory(png.ptr(), (s32)fileSize, &width, &height, &actual_components, 4), + stbi_load_from_memory(png.get(), (s32)fileSize, &width, &height, &actual_components, 4), &::free ); if (!image) diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp index e76dccba23..2a9e157a03 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp @@ -714,7 +714,7 @@ void SetFlipHandler(vm::ptr handler) } } -int cellRescSetDisplayMode(u32 displayMode) +int cellRescSetDisplayMode(PPUThread& CPU, u32 displayMode) { cellResc.Warning("cellRescSetDisplayMode(displayMode=%d)", displayMode); @@ -765,7 +765,7 @@ int cellRescSetDisplayMode(u32 displayMode) else m_pCFragmentShader = m_pCFragmentShaderArray[RESC_SHADER_DEFAULT_BILINEAR]; }*/ - vm::var videocfg; + vm::stackvar videocfg(CPU); videocfg->resolutionId = RescBufferMode2SysutilResolutionId(s_rescInternalInstance->m_dstMode); videocfg->format = RescDstFormat2SysutilFormat(s_rescInternalInstance->m_pRescDsts->format ); videocfg->aspect = CELL_VIDEO_OUT_ASPECT_AUTO; @@ -1030,7 +1030,7 @@ int cellRescSetWaitFlip() return CELL_OK; } -int cellRescSetBufferAddress(vm::ptr colorBuffers, vm::ptr vertexArray, vm::ptr fragmentShader) +int cellRescSetBufferAddress(PPUThread& CPU, vm::ptr colorBuffers, vm::ptr vertexArray, vm::ptr fragmentShader) { cellResc.Warning("cellRescSetBufferAddress(colorBuffers_addr=0x%x, vertexArray_addr=0x%x, fragmentShader_addr=0x%x)", colorBuffers.addr(), vertexArray.addr(), fragmentShader.addr()); @@ -1050,7 +1050,7 @@ int cellRescSetBufferAddress(vm::ptr colorBuffers, vm::ptr vertexArray s_rescInternalInstance->m_vertexArrayEA = vertexArray.addr(); s_rescInternalInstance->m_fragmentUcodeEA = fragmentShader.addr(); - vm::var> dstOffset; + vm::stackvar> dstOffset(CPU); cellGcmAddressToOffset(s_rescInternalInstance->m_colorBuffersEA, dstOffset); for (int i=0; i spurs, vm::ptr taskset, vm::ptr handler, vm::ptr arg); s32 cellSpursTasksetUnsetExceptionEventHandler(vm::ptr taskset); -s32 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::pptr taskset, u32 id); +s32 cellSpursLookUpTasksetAddress(PPUThread& CPU, vm::ptr spurs, vm::pptr taskset, u32 id); s32 cellSpursTasksetGetSpursAddress(vm::cptr taskset, vm::ptr spurs); s32 cellSpursGetTasksetInfo(); s32 _cellSpursTasksetAttributeInitialize(vm::ptr attribute, u32 revision, u32 sdk_version, u64 args, vm::cptr priority, u32 max_contention); @@ -2902,7 +2902,7 @@ s32 cellSpursEventFlagSet(PPUThread& CPU, vm::ptr eventFlag, vm::stackvar> taskset(CPU); if (eventFlag->isIwl) { - cellSpursLookUpTasksetAddress(vm::ptr::make((u32)eventFlag->addr), taskset, eventFlag->waitingTaskWklId[i]); + cellSpursLookUpTasksetAddress(CPU, vm::ptr::make((u32)eventFlag->addr), taskset, eventFlag->waitingTaskWklId[i]); } else { @@ -3658,7 +3658,7 @@ s32 cellSpursCreateTask(PPUThread& CPU, vm::ptr taskset, vm::p return CELL_SPURS_TASK_ERROR_ALIGN; } - vm::var> tmpTaskId; + vm::stackvar> tmpTaskId(CPU); auto rc = spursCreateTask(taskset, tmpTaskId, vm::ptr::make(elf_addr), vm::ptr::make(context_addr), context_size, lsPattern, argument); if (rc != CELL_OK) { @@ -3990,7 +3990,7 @@ s32 cellSpursTasksetUnsetExceptionEventHandler(vm::ptr taskset return CELL_OK; } -s32 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::pptr taskset, u32 id) +s32 cellSpursLookUpTasksetAddress(PPUThread& CPU, vm::ptr spurs, vm::pptr taskset, u32 id) { cellSpurs.Warning("cellSpursLookUpTasksetAddress(spurs=*0x%x, taskset=**0x%x, id=0x%x)", spurs, taskset, id); @@ -3999,7 +3999,7 @@ s32 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::pptr> data; + vm::stackvar> data(CPU); if (s32 rc = cellSpursGetWorkloadData(spurs, data, id)) { // Convert policy module error code to a task error code diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index c424fe59b2..3568c1fe2b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -436,7 +436,7 @@ s32 cellSyncQueuePush(vm::ptr queue, vm::cptr buffer) u32 position; - g_sync_queue_wm.wait_op(queue.addr(), WRAP_EXPR(queue->ctrl.atomic_op(&sync_queue_t::try_push, depth, position))); + g_sync_queue_wm.wait_op(queue.addr(), WRAP_EXPR(queue->ctrl.atomic_op(&sync_queue_t::try_push_begin, depth, position))); // copy data from the buffer at the position std::memcpy(&queue->buffer[position * queue->size], buffer.get_ptr(), queue->size); @@ -467,7 +467,7 @@ s32 cellSyncQueueTryPush(vm::ptr queue, vm::cptr buffer) u32 position; - if (!queue->ctrl.atomic_op(&sync_queue_t::try_push, depth, position)) + if (!queue->ctrl.atomic_op(&sync_queue_t::try_push_begin, depth, position)) { return CELL_SYNC_ERROR_BUSY; } @@ -501,7 +501,7 @@ s32 cellSyncQueuePop(vm::ptr queue, vm::ptr buffer) u32 position; - g_sync_queue_wm.wait_op(queue.addr(), WRAP_EXPR(queue->ctrl.atomic_op(&sync_queue_t::try_pop, depth, position))); + g_sync_queue_wm.wait_op(queue.addr(), WRAP_EXPR(queue->ctrl.atomic_op(&sync_queue_t::try_pop_begin, depth, position))); // copy data at the position to the buffer std::memcpy(buffer.get_ptr(), &queue->buffer[position * queue->size], queue->size); @@ -532,7 +532,7 @@ s32 cellSyncQueueTryPop(vm::ptr queue, vm::ptr buffer) u32 position; - if (!queue->ctrl.atomic_op(&sync_queue_t::try_pop, depth, position)) + if (!queue->ctrl.atomic_op(&sync_queue_t::try_pop_begin, depth, position)) { return CELL_SYNC_ERROR_BUSY; } @@ -566,7 +566,7 @@ s32 cellSyncQueuePeek(vm::ptr queue, vm::ptr buffer) u32 position; - g_sync_queue_wm.wait_op(queue.addr(), WRAP_EXPR(queue->ctrl.atomic_op(&sync_queue_t::try_peek, depth, position))); + g_sync_queue_wm.wait_op(queue.addr(), WRAP_EXPR(queue->ctrl.atomic_op(&sync_queue_t::try_peek_begin, depth, position))); // copy data at the position to the buffer std::memcpy(buffer.get_ptr(), &queue->buffer[position * queue->size], queue->size); @@ -597,7 +597,7 @@ s32 cellSyncQueueTryPeek(vm::ptr queue, vm::ptr buffer) u32 position; - if (!queue->ctrl.atomic_op(&sync_queue_t::try_peek, depth, position)) + if (!queue->ctrl.atomic_op(&sync_queue_t::try_peek_begin, depth, position)) { return CELL_SYNC_ERROR_BUSY; } @@ -646,44 +646,11 @@ s32 cellSyncQueueClear(vm::ptr queue) return CELL_SYNC_ERROR_ALIGN; } - const u32 depth = queue->check_depth(); + queue->check_depth(); - // TODO: optimize if possible - g_sync_queue_wm.wait_op(queue.addr(), [queue, depth]() - { - return CELL_OK == queue->ctrl.atomic_op([depth](sync_queue_t& queue) -> s32 - { - const u32 v1 = queue.m_v1; + g_sync_queue_wm.wait_op(queue.addr(), WRAP_EXPR(queue->ctrl.atomic_op(&sync_queue_t::try_clear_begin_1))); - // extract first byte, repeat if not zero, insert 1 - if (v1 >> 24) - { - return CELL_SYNC_ERROR_BUSY; - } - - queue.m_v1 = v1 | 0x1000000; - - return CELL_OK; - }); - }); - - g_sync_queue_wm.wait_op(queue.addr(), [queue, depth]() - { - return CELL_OK == queue->ctrl.atomic_op([depth](sync_queue_t& queue) -> s32 - { - const u32 v2 = queue.m_v2; - - // extract 5th byte, repeat if not zero, insert 1 - if (v2 >> 24) - { - return CELL_SYNC_ERROR_BUSY; - } - - queue.m_v2 = v2 | 0x1000000; - - return CELL_OK; - }); - }); + g_sync_queue_wm.wait_op(queue.addr(), WRAP_EXPR(queue->ctrl.atomic_op(&sync_queue_t::try_clear_begin_2))); queue->ctrl.exchange({}); @@ -694,7 +661,7 @@ s32 cellSyncQueueClear(vm::ptr queue) // LFQueue functions -void syncLFQueueInit(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) +void syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) { queue->m_size = size; queue->m_depth = depth; @@ -734,46 +701,54 @@ void syncLFQueueInit(vm::ptr queue, vm::ptr buffer, u32 siz queue->m_eq_id = 0; } -s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) +s32 cellSyncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) { + cellSync.Warning("cellSyncLFQueueInitialize(queue=*0x%x, buffer=*0x%x, size=0x%x, depth=0x%x, direction=%d, eaSignal=*0x%x)", queue, buffer, size, depth, direction, eaSignal); + if (!queue) { return CELL_SYNC_ERROR_NULL_POINTER; } + if (size) { if (!buffer) { return CELL_SYNC_ERROR_NULL_POINTER; } + if (size > 0x4000 || size % 16) { return CELL_SYNC_ERROR_INVAL; } } + if (!depth || (depth >> 15) || direction > 3) { return CELL_SYNC_ERROR_INVAL; } + if (!queue.aligned() || buffer % 16) { return CELL_SYNC_ERROR_ALIGN; } - // prx: get sdk version of current process, return non-zero result of sys_process_get_sdk_version + // get sdk version of current process s32 sdk_ver; - s32 ret = process_get_sdk_version(process_getpid(), sdk_ver); - if (ret != CELL_OK) + + if (s32 ret = process_get_sdk_version(process_getpid(), sdk_ver)) { return ret; } + if (sdk_ver == -1) { sdk_ver = 0x460000; } - // prx: reserve u32 at 0x2c offset + // reserve `init` u32 old_value; + while (true) { const auto old = queue->init.load(); @@ -785,6 +760,7 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 { return CELL_SYNC_ERROR_STAT; } + old_value = old; } else @@ -792,6 +768,7 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 if (sdk_ver > 0x17ffff) { auto data = vm::get_ptr(queue.addr()); + for (u32 i = 0; i < sizeof(CellSyncLFQueue) / sizeof(u64); i++) { if (data[i]) @@ -800,6 +777,7 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 } } } + init = 1; old_value = 1; } @@ -813,37 +791,31 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 { return CELL_SYNC_ERROR_INVAL; } + if (sdk_ver > 0x17ffff) { - if (queue->m_eaSignal.addr() != eaSignal.addr() || queue->m_direction != direction) + if (queue->m_eaSignal != eaSignal || queue->m_direction != direction) { return CELL_SYNC_ERROR_INVAL; } } + + _mm_mfence(); } else { - // prx: call internal function with same arguments - syncLFQueueInit(queue, buffer, size, depth, direction, eaSignal); + syncLFQueueInitialize(queue, buffer, size, depth, direction, eaSignal); - // prx: sync, clear u32 at 0x2c offset queue->init.exchange({}); } - // prx: sync - _mm_mfence(); return CELL_OK; } -s32 cellSyncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) +s32 _cellSyncLFQueueGetPushPointer(PPUThread& CPU, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) { - cellSync.Warning("cellSyncLFQueueInitialize(queue=*0x%x, buffer=*0x%x, size=0x%x, depth=0x%x, direction=%d, eaSignal=*0x%x)", queue, buffer, size, depth, direction, eaSignal); + cellSync.Warning("_cellSyncLFQueueGetPushPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue); - return syncLFQueueInitialize(queue, buffer, size, depth, direction, eaSignal); -} - -s32 syncLFQueueGetPushPointer(PPUThread& CPU, vm::ptr queue, s32& pointer, u32 isBlocking, u32 useEventQueue) -{ if (queue->m_direction != CELL_SYNC_QUEUE_PPU2SPU) { return CELL_SYNC_ERROR_PERM; @@ -890,8 +862,9 @@ s32 syncLFQueueGetPushPointer(PPUThread& CPU, vm::ptr queue, s3 if (var2 < depth) { - pointer = (s16)push.m_h8; - if (pointer + 1 >= depth * 2) + const s32 _pointer = (s16)push.m_h8; + *pointer = _pointer; + if (_pointer + 1 >= depth * 2) { push.m_h8 = 0; } @@ -938,38 +911,18 @@ s32 syncLFQueueGetPushPointer(PPUThread& CPU, vm::ptr queue, s3 } } -s32 _cellSyncLFQueueGetPushPointer(PPUThread& CPU, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) -{ - cellSync.Warning("_cellSyncLFQueueGetPushPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue); - - s32 pointer_value; - s32 result = syncLFQueueGetPushPointer(CPU, queue, pointer_value, isBlocking, useEventQueue); - - *pointer = pointer_value; - - return result; -} - -s32 syncLFQueueGetPushPointer2(PPUThread& CPU, vm::ptr queue, s32& pointer, u32 isBlocking, u32 useEventQueue) -{ - throw __FUNCTION__; -} - -s32 _cellSyncLFQueueGetPushPointer2(PPUThread& CPU, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) +s32 _cellSyncLFQueueGetPushPointer2(PPUThread& CPU, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) { // arguments copied from _cellSyncLFQueueGetPushPointer cellSync.Todo("_cellSyncLFQueueGetPushPointer2(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue); - s32 pointer_value; - s32 result = syncLFQueueGetPushPointer2(CPU,queue, pointer_value, isBlocking, useEventQueue); - - *pointer = pointer_value; - - return result; + throw __FUNCTION__; } -s32 syncLFQueueCompletePushPointer(PPUThread& CPU, vm::ptr queue, s32 pointer, std::function fpSendSignal) +s32 _cellSyncLFQueueCompletePushPointer(PPUThread& CPU, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) { + cellSync.Warning("_cellSyncLFQueueCompletePushPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x)", queue, pointer, fpSendSignal); + if (queue->m_direction != CELL_SYNC_QUEUE_PPU2SPU) { return CELL_SYNC_ERROR_PERM; @@ -1008,7 +961,7 @@ s32 syncLFQueueCompletePushPointer(PPUThread& CPU, vm::ptr queu var9_ = 1 << var9_; } s32 var9 = cntlz32((u32)(u16)~(var9_ | (u16)push3.m_h6)) - 16; // count leading zeros in u16 - + s32 var5 = (s32)(u16)push3.m_h6 | var9_; if (var9 & 0x30) { @@ -1102,24 +1055,12 @@ s32 syncLFQueueCompletePushPointer(PPUThread& CPU, vm::ptr queu } } -s32 _cellSyncLFQueueCompletePushPointer(PPUThread& CPU, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) -{ - cellSync.Warning("_cellSyncLFQueueCompletePushPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x)", queue, pointer, fpSendSignal); - - return syncLFQueueCompletePushPointer(CPU, queue, pointer, fpSendSignal); -} - -s32 syncLFQueueCompletePushPointer2(PPUThread& CPU, vm::ptr queue, s32 pointer, std::function fpSendSignal) -{ - throw __FUNCTION__; -} - s32 _cellSyncLFQueueCompletePushPointer2(PPUThread& CPU, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) { // arguments copied from _cellSyncLFQueueCompletePushPointer cellSync.Todo("_cellSyncLFQueueCompletePushPointer2(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x)", queue, pointer, fpSendSignal); - return syncLFQueueCompletePushPointer2(CPU, queue, pointer, fpSendSignal); + throw __FUNCTION__; } s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr queue, vm::cptr buffer, u32 isBlocking) @@ -1131,12 +1072,13 @@ s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr queue, vm: { return CELL_SYNC_ERROR_NULL_POINTER; } + if (!queue.aligned() || buffer % 16) { return CELL_SYNC_ERROR_ALIGN; } - s32 position; + vm::stackvar> position(CPU); while (true) { @@ -1144,19 +1086,17 @@ s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr queue, vm: if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) { - res = syncLFQueueGetPushPointer(CPU, queue, position, isBlocking, 0); + res = _cellSyncLFQueueGetPushPointer(CPU, queue, position, isBlocking, 0); } else { - res = syncLFQueueGetPushPointer2(CPU, queue, position, isBlocking, 0); + res = _cellSyncLFQueueGetPushPointer2(CPU, queue, position, isBlocking, 0); } if (!isBlocking || res != CELL_SYNC_ERROR_AGAIN) { - if (res) - { - return res; - } + if (res) return res; + break; } @@ -1171,25 +1111,24 @@ s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr queue, vm: const s32 depth = queue->m_depth; const s32 size = queue->m_size; - const u32 addr = vm::cast((queue->m_buffer.addr() & ~1ull) + size * (position >= depth ? position - depth : position)); - memcpy(vm::get_ptr(addr), buffer.get_ptr(), size); - - s32 res; + const s32 pos = position.value(); + const u32 addr = vm::cast((queue->m_buffer.addr() & ~1ull) + size * (pos >= depth ? pos - depth : pos)); + std::memcpy(vm::get_ptr(addr), buffer.get_ptr(), size); if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) { - res = syncLFQueueCompletePushPointer(CPU, queue, position, nullptr); + return _cellSyncLFQueueCompletePushPointer(CPU, queue, pos, vm::null); } else { - res = syncLFQueueCompletePushPointer2(CPU, queue, position, nullptr); + return _cellSyncLFQueueCompletePushPointer2(CPU, queue, pos, vm::null); } - - return res; } -s32 syncLFQueueGetPopPointer(PPUThread& CPU, vm::ptr queue, s32& pointer, u32 isBlocking, u32, u32 useEventQueue) +s32 _cellSyncLFQueueGetPopPointer(PPUThread& CPU, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 arg4, u32 useEventQueue) { + cellSync.Warning("_cellSyncLFQueueGetPopPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, arg4=%d, useEventQueue=%d)", queue, pointer, isBlocking, arg4, useEventQueue); + if (queue->m_direction != CELL_SYNC_QUEUE_SPU2PPU) { return CELL_SYNC_ERROR_PERM; @@ -1236,8 +1175,9 @@ s32 syncLFQueueGetPopPointer(PPUThread& CPU, vm::ptr queue, s32 if (var2 > 0) { - pointer = (s16)pop.m_h4; - if (pointer + 1 >= depth * 2) + const s32 _pointer = (s16)pop.m_h4; + *pointer = _pointer; + if (_pointer + 1 >= depth * 2) { pop.m_h4 = 0; } @@ -1284,38 +1224,19 @@ s32 syncLFQueueGetPopPointer(PPUThread& CPU, vm::ptr queue, s32 } } -s32 _cellSyncLFQueueGetPopPointer(PPUThread& CPU, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 arg4, u32 useEventQueue) -{ - cellSync.Warning("_cellSyncLFQueueGetPopPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, arg4=%d, useEventQueue=%d)", queue, pointer, isBlocking, arg4, useEventQueue); - - s32 pointer_value; - s32 result = syncLFQueueGetPopPointer(CPU, queue, pointer_value, isBlocking, arg4, useEventQueue); - - *pointer = pointer_value; - - return result; -} - -s32 syncLFQueueGetPopPointer2(PPUThread& CPU, vm::ptr queue, s32& pointer, u32 isBlocking, u32 useEventQueue) -{ - throw __FUNCTION__; -} - -s32 _cellSyncLFQueueGetPopPointer2(PPUThread& CPU, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) +s32 _cellSyncLFQueueGetPopPointer2(PPUThread& CPU, vm::ptr queue, vm::ptr pointer, u32 isBlocking, u32 useEventQueue) { // arguments copied from _cellSyncLFQueueGetPopPointer cellSync.Todo("_cellSyncLFQueueGetPopPointer2(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue); - s32 pointer_value; - s32 result = syncLFQueueGetPopPointer2(CPU, queue, pointer_value, isBlocking, useEventQueue); - - *pointer = pointer_value; - - return result; + throw __FUNCTION__; } -s32 syncLFQueueCompletePopPointer(PPUThread& CPU, vm::ptr queue, s32 pointer, std::function fpSendSignal, u32 noQueueFull) +s32 _cellSyncLFQueueCompletePopPointer(PPUThread& CPU, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) { + // arguments copied from _cellSyncLFQueueCompletePushPointer + unknown argument (noQueueFull taken from LFQueue2CompletePopPointer) + cellSync.Warning("_cellSyncLFQueueCompletePopPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x, noQueueFull=%d)", queue, pointer, fpSendSignal, noQueueFull); + if (queue->m_direction != CELL_SYNC_QUEUE_SPU2PPU) { return CELL_SYNC_ERROR_PERM; @@ -1447,25 +1368,12 @@ s32 syncLFQueueCompletePopPointer(PPUThread& CPU, vm::ptr queue } } -s32 _cellSyncLFQueueCompletePopPointer(PPUThread& CPU, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) -{ - // arguments copied from _cellSyncLFQueueCompletePushPointer + unknown argument (noQueueFull taken from LFQueue2CompletePopPointer) - cellSync.Warning("_cellSyncLFQueueCompletePopPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x, noQueueFull=%d)", queue, pointer, fpSendSignal, noQueueFull); - - return syncLFQueueCompletePopPointer(CPU, queue, pointer, fpSendSignal, noQueueFull); -} - -s32 syncLFQueueCompletePopPointer2(PPUThread& CPU, vm::ptr queue, s32 pointer, std::function fpSendSignal, u32 noQueueFull) -{ - throw __FUNCTION__; -} - s32 _cellSyncLFQueueCompletePopPointer2(PPUThread& CPU, vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) { // arguments copied from _cellSyncLFQueueCompletePopPointer cellSync.Todo("_cellSyncLFQueueCompletePopPointer2(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x, noQueueFull=%d)", queue, pointer, fpSendSignal, noQueueFull); - return syncLFQueueCompletePopPointer2(CPU, queue, pointer, fpSendSignal, noQueueFull); + throw __FUNCTION__; } s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr queue, vm::ptr buffer, u32 isBlocking) @@ -1477,31 +1385,31 @@ s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr queue, vm:: { return CELL_SYNC_ERROR_NULL_POINTER; } + if (!queue.aligned() || buffer % 16) { return CELL_SYNC_ERROR_ALIGN; } - s32 position; + vm::stackvar> position(CPU); while (true) { s32 res; + if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) { - res = syncLFQueueGetPopPointer(CPU, queue, position, isBlocking, 0, 0); + res = _cellSyncLFQueueGetPopPointer(CPU, queue, position, isBlocking, 0, 0); } else { - res = syncLFQueueGetPopPointer2(CPU, queue, position, isBlocking, 0); + res = _cellSyncLFQueueGetPopPointer2(CPU, queue, position, isBlocking, 0); } if (!isBlocking || res != CELL_SYNC_ERROR_AGAIN) { - if (res) - { - return res; - } + if (res) return res; + break; } @@ -1516,21 +1424,18 @@ s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr queue, vm:: const s32 depth = queue->m_depth; const s32 size = queue->m_size; - const u32 addr = vm::cast((queue->m_buffer.addr() & ~1) + size * (position >= depth ? position - depth : position)); - memcpy(buffer.get_ptr(), vm::get_ptr(addr), size); - - s32 res; + const s32 pos = position.value(); + const u32 addr = vm::cast((queue->m_buffer.addr() & ~1) + size * (pos >= depth ? pos - depth : pos)); + std::memcpy(buffer.get_ptr(), vm::get_ptr(addr), size); if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY) { - res = syncLFQueueCompletePopPointer(CPU, queue, position, nullptr, 0); + return _cellSyncLFQueueCompletePopPointer(CPU, queue, pos, vm::null, 0); } else { - res = syncLFQueueCompletePopPointer2(CPU, queue, position, nullptr, 0); + return _cellSyncLFQueueCompletePopPointer2(CPU, queue, pos, vm::null, 0); } - - return res; } s32 cellSyncLFQueueClear(vm::ptr queue) @@ -1541,6 +1446,7 @@ s32 cellSyncLFQueueClear(vm::ptr queue) { return CELL_SYNC_ERROR_NULL_POINTER; } + if (!queue.aligned()) { return CELL_SYNC_ERROR_ALIGN; @@ -1591,6 +1497,7 @@ s32 cellSyncLFQueueSize(vm::ptr queue, vm::ptr size) { return CELL_SYNC_ERROR_NULL_POINTER; } + if (!queue.aligned()) { return CELL_SYNC_ERROR_ALIGN; @@ -1613,6 +1520,7 @@ s32 cellSyncLFQueueSize(vm::ptr queue, vm::ptr size) { *size = var2 - var1 + (u32)queue->m_depth * 2; } + return CELL_OK; } } @@ -1626,12 +1534,14 @@ s32 cellSyncLFQueueDepth(vm::ptr queue, vm::ptr depth) { return CELL_SYNC_ERROR_NULL_POINTER; } + if (!queue.aligned()) { return CELL_SYNC_ERROR_ALIGN; } *depth = queue->m_depth; + return CELL_OK; } @@ -1643,6 +1553,7 @@ s32 _cellSyncLFQueueGetSignalAddress(vm::cptr queue, vm::pptr queue, vm::ptr di { return CELL_SYNC_ERROR_NULL_POINTER; } + if (!queue.aligned()) { return CELL_SYNC_ERROR_ALIGN; } *direction = queue->m_direction; + return CELL_OK; } @@ -1678,29 +1591,21 @@ s32 cellSyncLFQueueGetEntrySize(vm::cptr queue, vm::ptr en { return CELL_SYNC_ERROR_NULL_POINTER; } + if (!queue.aligned()) { return CELL_SYNC_ERROR_ALIGN; } *entry_size = queue->m_size; - return CELL_OK; -} -s32 syncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) -{ - throw __FUNCTION__; + return CELL_OK; } s32 _cellSyncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) { cellSync.Todo("_cellSyncLFQueueAttachLv2EventQueue(spus=*0x%x, num=%d, queue=*0x%x)", spus, num, queue); - return syncLFQueueAttachLv2EventQueue(spus, num, queue); -} - -s32 syncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) -{ throw __FUNCTION__; } @@ -1708,7 +1613,7 @@ s32 _cellSyncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr m_v1; be_t m_v2; - bool try_push(u32 depth, u32& position) + bool try_push_begin(u32 depth, u32& position) { const u32 v1 = m_v1; const u32 v2 = m_v2; @@ -182,7 +182,7 @@ struct sync_queue_t // CellSyncQueue sync var return true; } - bool try_pop(u32 depth, u32& position) + bool try_pop_begin(u32 depth, u32& position) { const u32 v1 = m_v1; const u32 v2 = m_v2; @@ -204,7 +204,7 @@ struct sync_queue_t // CellSyncQueue sync var return true; } - bool try_peek(u32 depth, u32& position) + bool try_peek_begin(u32 depth, u32& position) { const u32 v1 = m_v1; const u32 v2 = m_v2; @@ -219,6 +219,30 @@ struct sync_queue_t // CellSyncQueue sync var return true; } + + bool try_clear_begin_1() + { + if (m_v1 & 0xff000000) + { + return false; + } + + m_v1 |= 0x1000000; + + return true; + } + + bool try_clear_begin_2() + { + if (m_v2 & 0xff000000) + { + return false; + } + + m_v2 |= 0x1000000; + + return true; + } }; struct set_alignment(32) CellSyncQueue @@ -311,7 +335,7 @@ struct set_alignment(128) CellSyncLFQueue u8 m_bs[4]; // 0x20 be_t m_direction; // 0x24 CellSyncQueueDirection be_t m_v1; // 0x28 - atomic_be_t init; // 0x2C + atomic_be_t init; // 0x2C atomic_be_t push2; // 0x30 be_t m_hs1[15]; // 0x32 atomic_be_t pop2; // 0x50 @@ -339,15 +363,3 @@ struct set_alignment(128) CellSyncLFQueue }; CHECK_SIZE_ALIGN(CellSyncLFQueue, 128, 128); - -s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal); -s32 syncLFQueueGetPushPointer(PPUThread& CPU, vm::ptr queue, s32& pointer, u32 isBlocking, u32 useEventQueue); -s32 syncLFQueueGetPushPointer2(PPUThread& CPU, vm::ptr queue, s32& pointer, u32 isBlocking, u32 useEventQueue); -s32 syncLFQueueCompletePushPointer(PPUThread& CPU, vm::ptr queue, s32 pointer, std::function fpSendSignal); -s32 syncLFQueueCompletePushPointer2(PPUThread& CPU, vm::ptr queue, s32 pointer, std::function fpSendSignal); -s32 syncLFQueueGetPopPointer(PPUThread& CPU, vm::ptr queue, s32& pointer, u32 isBlocking, u32, u32 useEventQueue); -s32 syncLFQueueGetPopPointer2(PPUThread& CPU, vm::ptr queue, s32& pointer, u32 isBlocking, u32 useEventQueue); -s32 syncLFQueueCompletePopPointer(PPUThread& CPU, vm::ptr queue, s32 pointer, std::function fpSendSignal, u32 noQueueFull); -s32 syncLFQueueCompletePopPointer2(PPUThread& CPU, vm::ptr queue, s32 pointer, std::function fpSendSignal, u32 noQueueFull); -s32 syncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue); -s32 syncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue);