From bb77249ac889bcf108deac06ca28f51e9501b59e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 19 Sep 2014 04:19:22 +0400 Subject: [PATCH 01/24] CellSpurs initialization --- Utilities/BEType.h | 2 +- Utilities/GNU.h | 10 +- Utilities/SMutex.h | 15 +- rpcs3/Emu/Cell/PPUInterpreter.h | 12 -- rpcs3/Emu/Cell/SPUThread.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 192 +++++++++++++++++-- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 107 +++++++++-- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 53 ++--- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h | 10 +- rpcs3/Emu/SysCalls/lv2/sys_cond.h | 1 + rpcs3/Emu/SysCalls/lv2/sys_event.cpp | 56 ++++-- rpcs3/Emu/SysCalls/lv2/sys_event.h | 15 +- rpcs3/Emu/SysCalls/lv2/sys_event_flag.h | 2 + rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp | 34 ++-- rpcs3/Emu/SysCalls/lv2/sys_lwcond.h | 8 +- rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp | 46 ++--- rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h | 17 +- rpcs3/Emu/SysCalls/lv2/sys_mutex.h | 1 + rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp | 28 +-- rpcs3/Emu/SysCalls/lv2/sys_semaphore.h | 15 +- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 156 ++++++++------- rpcs3/Emu/SysCalls/lv2/sys_spu.h | 87 ++++++--- 22 files changed, 599 insertions(+), 272 deletions(-) diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 3c6d0b74ec..4e3da154c5 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -153,7 +153,7 @@ union u128 std::string to_hex() const { - return fmt::Format("%16llx%16llx", _u64[1], _u64[0]); + return fmt::Format("%016llx%016llx", _u64[1], _u64[0]); } std::string to_xyzw() const diff --git a/Utilities/GNU.h b/Utilities/GNU.h index 43b00feafc..9b5d40ec6b 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -13,13 +13,21 @@ #endif template -void strcpy_trunc(char (&dst)[size], const std::string& src) +void strcpy_trunc(char(&dst)[size], const std::string& src) { const size_t count = (src.size() >= size) ? size - 1 /* truncation */ : src.size(); memcpy(dst, src.c_str(), count); dst[count] = 0; } +template +void strcpy_trunc(char(&dst)[size], const char(&src)[rsize]) +{ + const size_t count = (rsize >= size) ? size - 1 /* truncation */ : rsize; + memcpy(dst, src, count); + dst[count] = 0; +} + #if defined(__GNUG__) #include #include diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index 8acc971894..ebab2f0cff 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -25,7 +25,8 @@ template class SMutexBase { static_assert(sizeof(T) == sizeof(std::atomic), "Invalid SMutexBase type"); - std::atomic owner; + T owner; + typedef std::atomic AT; public: static const T GetFreeValue() @@ -45,10 +46,10 @@ public: owner = GetFreeValue(); } - SMutexBase() - { - initialize(); - } + //SMutexBase() + //{ + // initialize(); + //} void finalize() { @@ -68,7 +69,7 @@ public: } T old = GetFreeValue(); - if (!owner.compare_exchange_strong(old, tid)) + if (!reinterpret_cast(owner).compare_exchange_strong(old, tid)) { if (old == tid) { @@ -92,7 +93,7 @@ public: } T old = tid; - if (!owner.compare_exchange_strong(old, to)) + if (!reinterpret_cast(owner).compare_exchange_strong(old, to)) { if (old == GetFreeValue()) { diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 26352c1c4d..3ad8ba2eea 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2464,8 +2464,6 @@ private: } void DCBST(u32 ra, u32 rb) { - //UNK("dcbst", false); - _mm_mfence(); } void LWZUX(u32 rd, u32 ra, u32 rb) { @@ -2521,8 +2519,6 @@ private: } void DCBF(u32 ra, u32 rb) { - //UNK("dcbf", false); - _mm_mfence(); } void LBZX(u32 rd, u32 ra, u32 rb) { @@ -2739,8 +2735,6 @@ private: } void DCBTST(u32 ra, u32 rb, u32 th) { - //UNK("dcbtst", false); - _mm_mfence(); } void STBUX(u32 rs, u32 ra, u32 rb) { @@ -2758,8 +2752,6 @@ private: } void DCBT(u32 ra, u32 rb, u32 th) { - //UNK("dcbt", false); - _mm_mfence(); } void LHZX(u32 rd, u32 ra, u32 rb) { @@ -2796,7 +2788,6 @@ private: } void DST(u32 ra, u32 rb, u32 strm, u32 t) { - _mm_mfence(); } void LHAX(u32 rd, u32 ra, u32 rb) { @@ -2825,7 +2816,6 @@ private: } void DSTST(u32 ra, u32 rb, u32 strm, u32 t) { - _mm_mfence(); } void LHAUX(u32 rd, u32 ra, u32 rb) { @@ -3166,7 +3156,6 @@ private: } void DSS(u32 strm, u32 a) { - _mm_mfence(); } void SRAWI(u32 ra, u32 rs, u32 sh, bool rc) { @@ -3239,7 +3228,6 @@ private: auto const cache_line = vm::get_ptr(addr & ~127); if (cache_line) memset(cache_line, 0, 128); - _mm_mfence(); } void LWZ(u32 rd, u32 ra, s32 d) { diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 63e8c77f9b..f7dc30ca73 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -175,16 +175,16 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) return; } + SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]); + u32 addr = (ea & SYS_SPU_THREAD_BASE_MASK) % SYS_SPU_THREAD_OFFSET; if ((addr <= 0x3ffff) && (addr + size <= 0x40000)) { - SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]); // LS access ea = spu->dmac.ls_offset + addr; } else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2)) { - SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]); spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(dmac.ls_offset + lsa)); return; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 7d6a2d4721..056f453f88 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -3,8 +3,13 @@ #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Callback.h" -#include "Emu/SysCalls/lv2/sys_spu.h" +#include "Emu/Cell/SPUThread.h" +#include "Emu/SysCalls/lv2/sys_memory.h" +#include "Emu/SysCalls/lv2/sys_process.h" +#include "Emu/SysCalls/lv2/sys_semaphore.h" +#include "Emu/SysCalls/lv2/sys_event.h" #include "Emu/Cell/SPURSManager.h" +#include "sysPrxForUser.h" #include "cellSpurs.h" Module *cellSpurs = nullptr; @@ -14,27 +19,176 @@ extern u32 libsre; extern u32 libsre_rtoc; #endif +s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, u32 arg3, u32 arg4) +{ +#ifdef PRX_DEBUG + vm::var> queue; + s32 res = cb_call, vm::ptr>, u32, u32>(GetCurrentPPUThread(), libsre + 0xB14C, libsre_rtoc, + spurs, queue, arg3, arg4); + queue_id = queue->ToLE(); + return res; +#else + // TODO + queue_id = event_queue_create(SYS_SYNC_PRIORITY, SYS_PPU_QUEUE, *(u64*)"+QUEUE+", 0, 1); + return CELL_OK; +#endif +} + s64 spursInit( - vm::ptr spurs, - u32 revision, - u32 sdkVersion, - s32 nSpus, - s32 spuPriority, - s32 ppuPriority, + vm::ptr spurs, + const u32 revision, + const u32 sdkVersion, + const s32 nSpus, + const s32 spuPriority, + const s32 ppuPriority, u32 flags, // SpursAttrFlags const char prefix[], - u32 prefixSize, - u32 container, + const u32 prefixSize, + const u32 container, const u8 swlPriority[], - u32 swlMaxSpu, - u32 swlIsPreem) + const u32 swlMaxSpu, + const u32 swlIsPreem) { - // internal function -#ifdef PRX_DEBUG - return cb_call, u32, u32, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc, +#ifdef PRX_DEBUG_XXX + return cb_call, u32, u32, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc, spurs, revision, sdkVersion, nSpus, spuPriority, ppuPriority, flags, Memory.RealToVirtualAddr(prefix), prefixSize, container, Memory.RealToVirtualAddr(swlPriority), swlMaxSpu, swlIsPreem); #else - //spurs->spurs = new SPURSManager(attr); + // SPURS initialization (asserts should actually rollback and return the error instead) + + if (!spurs) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + if (prefixSize > CELL_SPURS_NAME_MAX_LENGTH) + { + return CELL_SPURS_CORE_ERROR_INVAL; + } + if (process_is_spu_lock_line_reservation_address(spurs.addr(), SYS_MEMORY_ACCESS_RIGHT_SPU_THR) != CELL_OK) + { + return CELL_SPURS_CORE_ERROR_PERM; + } + + const bool isSecond = flags & SAF_SECOND_VERSION; + memset(spurs.get_ptr(), 0, CellSpurs::size1 + isSecond * CellSpurs::size2); + spurs->m.revision = revision; + spurs->m.sdkVersion = sdkVersion; + spurs->m.unk1 = 0xffffffffull; + spurs->m.unk2 = 0xffffffffull; + spurs->m.flags = flags; + memcpy(spurs->m.prefix, prefix, prefixSize); + spurs->m.prefixSize = (u8)prefixSize; + + std::string name(prefix, prefixSize); // initialize name string + + if (!isSecond) + { + spurs->m.unk0 = 0xffff; + } + spurs->m.unk6[0xC] = 0; + spurs->m.unk6[0xD] = 0; + spurs->m.unk6[0xE] = 0; + for (u32 i = 0; i < 8; i++) + { + spurs->m.unk6[i] = -1; + } +#ifdef PRX_DEBUG + spurs->m.unk7 = vm::read32(libsre_rtoc - 0x7EA4); // write 64-bit pointer to unknown data +#else + spurs->m.unk7 = 0x7ull << 48 | 0x7; // wrong 64-bit address +#endif + spurs->m.unk8 = 0ull; + spurs->m.unk9 = 0x2200; + spurs->m.unk10 = -1; + u32 sem; + for (u32 i = 0; i < 0x10; i++) + { + sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl"); + assert(sem && ~sem); // should rollback if semaphore creating failed and return the error + spurs->m.sub1[i].sem = sem; + } + if (isSecond) + { + for (u32 i = 0; i < 0x10; i++) + { + sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl"); + assert(sem && ~sem); + spurs->m.sub2[i].sem = sem; + } + } + sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuPrv"); + assert(sem && ~sem); + spurs->m.semPrv = sem; + spurs->m.unk11 = -1; + spurs->m.unk12 = -1; + spurs->m.unk13 = 0; + spurs->m.nSpus = nSpus; + spurs->m.spuPriority = spuPriority; +#ifdef PRX_DEBUG + assert(spu_image_import(spurs->m.spuImg, vm::read32(libsre_rtoc - (isSecond ? 0x7E94 : 0x7E98)), 1) == CELL_OK); +#endif + //char str1[0x80]; + //memcpy(str1, prefix, prefixSize); // strcpy + //memcpy(str1 + prefixSize, "CellSpursKernelGroup", 21); // strcat + + s32 tgt = SYS_SPU_THREAD_GROUP_TYPE_NORMAL; + if (flags & SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT) + { + tgt = SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT; + } + else if (flags & SAF_UNKNOWN_FLAG_0) + { + tgt = 0xC02; + } + if (flags & SAF_SPU_MEMORY_CONTAINER_SET) tgt |= SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER; + if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) tgt |= SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM; + if (flags & SAF_UNKNOWN_FLAG_7) tgt |= 0x102; + if (flags & SAF_UNKNOWN_FLAG_8) tgt |= 0xC02; + if (flags & SAF_UNKNOWN_FLAG_9) tgt |= 0x800; + auto tg = spu_thread_group_create(name + "CellSpursKernelGroup", nSpus, spuPriority, tgt, container); + spurs->m.spuTG = tg->m_id; + + name += "CellSpursKernel0"; + for (s32 i = 0; i < nSpus; i++, name[name.size() - 1]++) + { + auto spu = spu_thread_initialize(tg, i, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, u64(i) << 32, spurs.addr(), 0, 0); + spurs->m.spus[i] = spu->GetId(); + } + + if (flags & SAF_SPU_PRINTF_ENABLED) + { + // spu_printf: attach group + if (!spu_printf_agcb || spu_printf_agcb(tg->m_id) != CELL_OK) + { + // remove flag if failed + spurs->m.flags &= ~SAF_SPU_PRINTF_ENABLED; + } + } + + assert(lwmutex_create(spurs->m.mutex, SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, *(u64*)"_spuPrv") == CELL_OK); + assert(lwcond_create(spurs->m.cond, spurs->m.mutex, *(u64*)"_spuPrv") == CELL_OK); + + spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK) << 7 | (isSecond ? 0x40 : 0); + spurs->m.unk15 = -1; + spurs->m.unk18 = -1; + spurs->_u8[0xD64] = 0; + spurs->_u8[0xD65] = 0; + spurs->_u8[0xD66] = 0; + spurs->m.ppuPriority = ppuPriority; + + u32 queue; + assert(spursCreateLv2EventQueue(spurs, queue, spurs.addr() + 0xc9, 0x2a) == CELL_OK); + spurs->m.queue = queue; + + u32 port = event_port_create(0); + assert(port && ~port); + spurs->m.port = port; + + assert(sys_event_port_connect_local(port, queue) == CELL_OK); + return CELL_OK; #endif } @@ -48,7 +202,7 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 return GetCurrentPPUThread().FastCall2(libsre + 0x8480, libsre_rtoc); #else return spursInit( - vm::ptr::make(spurs.addr()), + spurs, 0, 0, nSpus, @@ -85,7 +239,7 @@ s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptr::make(spurs.addr()), + spurs, attr->m.revision, attr->m.sdkVersion, attr->m.nSpus, @@ -101,7 +255,7 @@ s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptr spurs, vm::ptr attr) +s64 cellSpursInitializeWithAttribute2(vm::ptr spurs, vm::ptr attr) { cellSpurs->Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, attr_addr=0x%x)", spurs.addr(), attr.addr()); @@ -128,7 +282,7 @@ s64 cellSpursInitializeWithAttribute2(vm::ptr spurs, vm::ptrm.nSpus, attr->m.spuPriority, attr->m.ppuPriority, - attr->m.flags.ToLE() | (attr->m.exitIfNoWork ? SAF_EXIT_IF_NO_WORK : 0) | 4, // +add unknown flag + attr->m.flags.ToLE() | (attr->m.exitIfNoWork ? SAF_EXIT_IF_NO_WORK : 0) | SAF_SECOND_VERSION, attr->m.prefix, attr->m.prefixSize, attr->m.container, diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index c01d38c5c3..a01e1591de 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -1,4 +1,7 @@ #pragma once +#include "Emu/SysCalls/lv2/sys_lwmutex.h" +#include "Emu/SysCalls/lv2/sys_lwcond.h" +#include "Emu/SysCalls/lv2/sys_spu.h" // Core return codes. enum @@ -80,26 +83,20 @@ class SPURSManager; class SPURSManagerEventFlag; class SPURSManagerTaskset; -// Core CellSpurs structures. -struct CellSpurs -{ - SPURSManager *spurs; -}; - -struct CellSpurs2 -{ - SPURSManager *spurs; -}; - enum SpursAttrFlags : u32 { - SAF_NONE = 0x0, + SAF_NONE = 0x0, SAF_EXIT_IF_NO_WORK = 0x1, + SAF_SECOND_VERSION = 0x4, + SAF_UNKNOWN_FLAG_9 = 0x00400000, + SAF_UNKNOWN_FLAG_8 = 0x00800000, + SAF_UNKNOWN_FLAG_7 = 0x01000000, SAF_SYSTEM_WORKLOAD_ENABLED = 0x02000000, SAF_SPU_PRINTF_ENABLED = 0x10000000, SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT = 0x20000000, SAF_SPU_MEMORY_CONTAINER_SET = 0x40000000, + SAF_UNKNOWN_FLAG_0 = 0x80000000, }; struct CellSpursAttribute @@ -113,7 +110,7 @@ struct CellSpursAttribute u8 _u8[size]; struct { be_t _u32[size / sizeof(u32)]; }; - // real structure + // real data struct { be_t revision; // 0x0 @@ -140,6 +137,90 @@ struct CellSpursAttribute }; }; +// Core CellSpurs structures +struct CellSpurs +{ + static const uint align = 128; + static const uint size = 0x2000; // size of CellSpurs2 + static const uint size1 = 0x1000; // size of CellSpurs + static const uint size2 = 0x1000; + + struct _sub_str1 + { + static const uint size = 0x80; + + be_t sem; + u8 unk_[0x78]; + }; + + union + { + // raw data + u8 _u8[size]; + std::array, size / sizeof(u32)> _u32; + + // real data + struct + { + u8 unknown[0x6C]; + be_t unk18; // 0x6C + u8 unk17[4]; // 0x70 + u8 flags1; // 0x74 + u8 unk16; // 0x75 + u8 nSpus; // 0x76 + u8 unk15; // 0x77 + u8 unknown0[0xB0 - 0x78]; + be_t unk0; // 0x0B0 + u8 unknown2[0xC0 - 0xB4]; + u8 unk6[0x10]; // 0x0C0 + u8 unknown1[0x120 - 0x0D0]; + _sub_str1 sub1[0x10]; // 0x120 + u8 unknown7[0x980 - 0x920]; + be_t semPrv; // 0x980 + be_t unk11; // 0x988 + be_t unk12; // 0x98C + be_t unk13; // 0x990 + u8 unknown4[0xD00 - 0x998]; + be_t unk7; // 0xD00 + be_t unk8; // 0xD08 + be_t unk9; // 0xD10 + u8 unk10; // 0xD14 + u8 unknown5[0xD20 - 0xD15]; + be_t unk1; // 0xD20 + be_t unk2; // 0xD28 + be_t spuTG; // 0xD30 + be_t spus[8]; // 0xD34 + u8 unknown3[0xD5C - 0xD54]; + be_t queue; // 0xD5C + be_t port; // 0xD60 + u8 unk19[0xC]; // 0xD64 + sys_spu_image spuImg; // 0xD70 + be_t flags; // 0xD80 + be_t spuPriority;// 0xD84 + be_t ppuPriority;// 0xD88 + char prefix[0x0f]; // 0xD8C + u8 prefixSize; // 0xD9B + be_t unk5; // 0xD9C + be_t revision; // 0xDA0 + be_t sdkVersion; // 0xDA4 + u8 unknown8[0xDB0 - 0xDA8]; + sys_lwmutex_t mutex; // 0xDB0 + sys_lwcond_t cond; // 0xDC8 + u8 unknown6[0x1220 - 0xDD0]; + _sub_str1 sub2[0x10]; // 0x1220 + // ... + } m; + + // alternative implementation + struct + { + SPURSManager *spurs; + } c; + }; +}; + +typedef CellSpurs CellSpurs2; + struct CellSpursEventFlag { SPURSManagerEventFlag *eventFlag; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 8730463aff..b32ad1286e 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -5,7 +5,6 @@ #include "Emu/SysCalls/Callback.h" #include "Emu/FS/vfsFile.h" -#include "Emu/FS/vfsStreamMemory.h" #include "Emu/SysCalls/lv2/sys_spu.h" #include "Emu/SysCalls/lv2/sys_lwmutex.h" #include "Emu/SysCalls/lv2/sys_spinlock.h" @@ -21,8 +20,6 @@ Module *sysPrxForUser = nullptr; -extern u32 LoadSpuImage(vfsStream& stream, u32& spu_ep); - int _sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size) { sysPrxForUser->Warning("_sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size); @@ -97,18 +94,9 @@ int sys_spu_elf_get_segments(u32 elf_img, vm::ptr segments, int int sys_spu_image_import(vm::ptr img, u32 src, u32 type) { - sysPrxForUser->Warning("sys_spu_image_import(img=0x%x, src=0x%x, type=0x%x)", img.addr(), src, type); + sysPrxForUser->Warning("sys_spu_image_import(img=0x%x, src=0x%x, type=%d)", img.addr(), src, type); - vfsStreamMemory f(src); - u32 entry; - u32 offset = LoadSpuImage(f, entry); - - img->type = type; - img->entry_point = entry; - img->segs_addr = offset; - img->nsegs = 0; - - return CELL_OK; + return spu_image_import(*img, src, type); } int sys_spu_image_close(vm::ptr img) @@ -143,7 +131,7 @@ int sys_raw_spu_image_load(int id, vm::ptr img) sysPrxForUser->Warning("sys_raw_spu_image_load(id=0x%x, img_addr=0x%x)", id, img.addr()); // TODO: use segment info - memcpy(vm::get_ptr(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id), vm::get_ptr(img->segs_addr), 256 * 1024); + memcpy(vm::get_ptr(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id), vm::get_ptr(img->addr), 256 * 1024); vm::write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, (u32)img->entry_point); return CELL_OK; @@ -235,8 +223,6 @@ vm::ptr _sys_strncpy(vm::ptr dest, vm::ptr source, u32 l return dest; } -typedef s32(*spu_printf_cb_t)(u32 arg); - vm::ptr spu_printf_agcb; vm::ptr spu_printf_dgcb; vm::ptr spu_printf_atcb; @@ -270,68 +256,63 @@ s32 _sys_spu_printf_finalize() return CELL_OK; } -s64 _sys_spu_printf_attach_group(u32 arg) +s64 _sys_spu_printf_attach_group(u32 group) { - sysPrxForUser->Warning("_sys_spu_printf_attach_group(arg=0x%x)", arg); + sysPrxForUser->Warning("_sys_spu_printf_attach_group(group=%d)", group); if (!spu_printf_agcb) { return CELL_ESTAT; } - return spu_printf_agcb(arg); + return spu_printf_agcb(group); } -s64 _sys_spu_printf_detach_group(u32 arg) +s64 _sys_spu_printf_detach_group(u32 group) { - sysPrxForUser->Warning("_sys_spu_printf_detach_group(arg=0x%x)", arg); + sysPrxForUser->Warning("_sys_spu_printf_detach_group(group=%d)", group); if (!spu_printf_dgcb) { return CELL_ESTAT; } - return spu_printf_dgcb(arg); + return spu_printf_dgcb(group); } -s64 _sys_spu_printf_attach_thread(u32 arg) +s64 _sys_spu_printf_attach_thread(u32 thread) { - sysPrxForUser->Warning("_sys_spu_printf_attach_thread(arg=0x%x)", arg); + sysPrxForUser->Warning("_sys_spu_printf_attach_thread(thread=%d)", thread); if (!spu_printf_atcb) { return CELL_ESTAT; } - return spu_printf_atcb(arg); + return spu_printf_atcb(thread); } -s64 _sys_spu_printf_detach_thread(u32 arg) +s64 _sys_spu_printf_detach_thread(u32 thread) { - sysPrxForUser->Warning("_sys_spu_printf_detach_thread(arg=0x%x)", arg); + sysPrxForUser->Warning("_sys_spu_printf_detach_thread(thread=%d)", thread); if (!spu_printf_dtcb) { return CELL_ESTAT; } - return spu_printf_dtcb(arg); + return spu_printf_dtcb(thread); } -s32 _sys_snprintf(vm::ptr dst, u32 count, vm::ptr fmt, u32 a1, u32 a2) // va_args... +s32 _sys_snprintf(vm::ptr dst, u32 count, vm::ptr fmt) // va_args... { sysPrxForUser->Todo("_sys_snprintf(dst_addr=0x%x, count=%d, fmt_addr=0x%x['%s'], ...)", dst.addr(), count, fmt.addr(), fmt.get_ptr()); - if (std::string(fmt.get_ptr()) == "%s_%08x") - { - return snprintf(dst.get_ptr(), count, fmt.get_ptr(), vm::get_ptr(a1), a2); - } - Emu.Pause(); return 0; } -s32 _sys_printf(vm::ptr fmt) +s32 _sys_printf(vm::ptr fmt) // va_args... { sysPrxForUser->Todo("_sys_printf(fmt_addr=0x%x, ...)", fmt.addr()); diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h index 6fa65c5d69..8c020f3ecc 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h @@ -1,4 +1,4 @@ -# pragma once +#pragma once struct HeapInfo { @@ -14,5 +14,13 @@ struct HeapInfo } }; +typedef s32(*spu_printf_cb_t)(u32 arg); + +// Aux +extern vm::ptr spu_printf_agcb; +extern vm::ptr spu_printf_dgcb; +extern vm::ptr spu_printf_atcb; +extern vm::ptr spu_printf_dtcb; + // SysCalls vm::ptr _sys_memset(vm::ptr dst, s32 value, u32 size); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.h b/rpcs3/Emu/SysCalls/lv2/sys_cond.h index 3ed2c93eca..c6ea124172 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.h @@ -27,6 +27,7 @@ struct Cond , m_queue(name) , signaler(0) { + signal.initialize(); } }; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp index 76a73b0f26..d34acadf30 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp @@ -10,7 +10,24 @@ SysCallBase sys_event("sys_event"); -s32 sys_event_queue_create(vm::ptr> equeue_id, vm::ptr attr, u64 event_queue_key, int size) +u32 event_queue_create(u32 protocol, s32 type, u64 name_u64, u64 event_queue_key, s32 size) +{ + EventQueue* eq = new EventQueue(protocol, type, name_u64, event_queue_key, size); + + if (event_queue_key && !Emu.GetEventManager().RegisterKey(eq, event_queue_key)) + { + delete eq; + return 0; + } + + std::string name((const char*)&name_u64, 8); + u32 id = sys_event.GetNewId(eq, TYPE_EVENT_QUEUE); + sys_event.Warning("*** event_queue created [%s] (protocol=0x%x, type=0x%x, key=0x%llx, size=0x%x): id = %d", + name.c_str(), protocol, type, event_queue_key, size, id); + return id; +} + +s32 sys_event_queue_create(vm::ptr> equeue_id, vm::ptr attr, u64 event_queue_key, s32 size) { sys_event.Warning("sys_event_queue_create(equeue_id_addr=0x%x, attr_addr=0x%x, event_queue_key=0x%llx, size=%d)", equeue_id.addr(), attr.addr(), event_queue_key, size); @@ -33,7 +50,7 @@ s32 sys_event_queue_create(vm::ptr> equeue_id, vm::ptrtype); return CELL_EINVAL; + default: sys_event.Error("Unknown 0x%x type attr", (s32)attr->type); return CELL_EINVAL; } if (event_queue_key && Emu.GetEventManager().CheckKey(event_queue_key)) @@ -41,20 +58,13 @@ s32 sys_event_queue_create(vm::ptr> equeue_id, vm::ptrprotocol, (int)attr->type, attr->name_u64, event_queue_key, size); - - if (event_queue_key && !Emu.GetEventManager().RegisterKey(eq, event_queue_key)) + if (u32 id = event_queue_create(attr->protocol, attr->type, attr->name_u64, event_queue_key, size)) { - delete eq; - return CELL_EAGAIN; + *equeue_id = id; + return CELL_OK; } - u32 id = sys_event.GetNewId(eq, TYPE_EVENT_QUEUE); - *equeue_id = id; - sys_event.Warning("*** event_queue created [%s] (protocol=0x%x, type=0x%x): id = %d", - std::string(attr->name, 8).c_str(), (u32)attr->protocol, (int)attr->type, id); - - return CELL_OK; + return CELL_EAGAIN; } s32 sys_event_queue_destroy(u32 equeue_id, int mode) @@ -102,7 +112,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, int mode) return CELL_OK; } -s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_array, int size, vm::ptr> number) +s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_array, s32 size, vm::ptr> number) { sys_event.Todo("sys_event_queue_tryreceive(equeue_id=%d, event_array_addr=0x%x, size=%d, number_addr=0x%x)", equeue_id, event_array.addr(), size, number.addr()); @@ -225,7 +235,16 @@ s32 sys_event_queue_drain(u32 equeue_id) return CELL_OK; } -s32 sys_event_port_create(vm::ptr> eport_id, int port_type, u64 name) +u32 event_port_create(u64 name) +{ + EventPort* eport = new EventPort(); + u32 id = sys_event.GetNewId(eport, TYPE_EVENT_PORT); + eport->name = name ? name : ((u64)process_getpid() << 32) | (u64)id; + sys_event.Warning("*** sys_event_port created: id = %d", id); + return id; +} + +s32 sys_event_port_create(vm::ptr> eport_id, s32 port_type, u64 name) { sys_event.Warning("sys_event_port_create(eport_id_addr=0x%x, port_type=0x%x, name=0x%llx)", eport_id.addr(), port_type, name); @@ -236,12 +255,7 @@ s32 sys_event_port_create(vm::ptr> eport_id, int port_type, u64 name) return CELL_EINVAL; } - EventPort* eport = new EventPort(); - u32 id = sys_event.GetNewId(eport, TYPE_EVENT_PORT); - eport->name = name ? name : ((u64)process_getpid() << 32) | (u64)id; - *eport_id = id; - sys_event.Warning("*** sys_event_port created: id = %d", id); - + *eport_id = event_port_create(name); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.h b/rpcs3/Emu/SysCalls/lv2/sys_event.h index c379370d45..59d2796e0b 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.h @@ -37,7 +37,7 @@ enum EventSourceKey : u64 struct sys_event_queue_attr { be_t protocol; // SYS_SYNC_PRIORITY or SYS_SYNC_FIFO - be_t type; // SYS_PPU_QUEUE or SYS_SPU_QUEUE + be_t type; // SYS_PPU_QUEUE or SYS_SPU_QUEUE union { char name[8]; @@ -212,17 +212,22 @@ struct EventQueue , key(key) , events(size) // size: max event count this queue can hold { + owner.initialize(); } }; +// Aux +u32 event_port_create(u64 name); +u32 event_queue_create(u32 protocol, s32 type, u64 name_u64, u64 event_queue_key, s32 size); + // SysCalls -s32 sys_event_queue_create(vm::ptr> equeue_id, vm::ptr attr, u64 event_queue_key, int size); -s32 sys_event_queue_destroy(u32 equeue_id, int mode); +s32 sys_event_queue_create(vm::ptr> equeue_id, vm::ptr attr, u64 event_queue_key, s32 size); +s32 sys_event_queue_destroy(u32 equeue_id, s32 mode); s32 sys_event_queue_receive(u32 equeue_id, vm::ptr event, u64 timeout); -s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_array, int size, vm::ptr> number); +s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_array, s32 size, vm::ptr> number); s32 sys_event_queue_drain(u32 event_queue_id); -s32 sys_event_port_create(vm::ptr> eport_id, int port_type, u64 name); +s32 sys_event_port_create(vm::ptr> eport_id, s32 port_type, u64 name); s32 sys_event_port_destroy(u32 eport_id); s32 sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id); s32 sys_event_port_disconnect(u32 eport_id); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h index 90a4fc7a54..b3c12f18de 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h @@ -45,6 +45,8 @@ struct EventFlag , m_protocol(protocol) , m_type(type) { + m_mutex.initialize(); + signal.initialize(); } u32 check(); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp index e7c1527d38..f819a76818 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp @@ -9,21 +9,29 @@ SysCallBase sys_lwcond("sys_lwcond"); +s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64) +{ + u32 id = sys_lwcond.GetNewId(new Lwcond(name_u64), TYPE_LWCOND); + u32 addr = Memory.RealToVirtualAddr(&lwmutex); + lwcond.lwmutex.set(be_t::MakeFromLE(addr)); + lwcond.lwcond_queue = id; + + std::string name((const char*)&name_u64, 8); + + sys_lwcond.Warning("*** lwcond created [%s] (lwmutex_addr=0x%x): id = %d", + name.c_str(), addr, id); + + Emu.GetSyncPrimManager().AddSyncPrimData(TYPE_LWCOND, id, name); + + return CELL_OK; +} + s32 sys_lwcond_create(vm::ptr lwcond, vm::ptr lwmutex, vm::ptr attr) { sys_lwcond.Log("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)", lwcond.addr(), lwmutex.addr(), attr.addr()); - u32 id = sys_lwcond.GetNewId(new Lwcond(attr->name_u64), TYPE_LWCOND); - lwcond->lwmutex = lwmutex.addr(); - lwcond->lwcond_queue = id; - - sys_lwcond.Warning("*** lwcond created [%s] (lwmutex_addr=0x%x): id = %d", - std::string(attr->name, 8).c_str(), lwmutex.addr(), (u32) lwcond->lwcond_queue); - - Emu.GetSyncPrimManager().AddSyncPrimData(TYPE_LWCOND, id, std::string(attr->name, 8)); - - return CELL_OK; + return lwcond_create(*lwcond, *lwmutex, attr->name_u64); } s32 sys_lwcond_destroy(vm::ptr lwcond) @@ -58,7 +66,7 @@ s32 sys_lwcond_signal(vm::ptr lwcond) return CELL_ESRCH; } - auto mutex = vm::ptr::make(lwcond->lwmutex); + auto mutex = vm::ptr::make(lwcond->lwmutex.addr()); if (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop())) { @@ -84,7 +92,7 @@ s32 sys_lwcond_signal_all(vm::ptr lwcond) return CELL_ESRCH; } - auto mutex = vm::ptr::make(lwcond->lwmutex); + auto mutex = vm::ptr::make(lwcond->lwmutex.addr()); while (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop())) { @@ -144,7 +152,7 @@ s32 sys_lwcond_wait(vm::ptr lwcond, u64 timeout) return CELL_ESRCH; } - auto mutex = vm::ptr::make(lwcond->lwmutex); + auto mutex = vm::ptr::make(lwcond->lwmutex.addr()); u32 tid_le = GetCurrentPPUThread().GetId(); be_t tid = be_t::MakeFromLE(tid_le); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h index 8331fc00db..5c34190776 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h @@ -1,5 +1,7 @@ #pragma once +struct sys_lwmutex_t; + struct sys_lwcond_attribute_t { union @@ -11,7 +13,7 @@ struct sys_lwcond_attribute_t struct sys_lwcond_t { - be_t lwmutex; + vm::bptr lwmutex; be_t lwcond_queue; }; @@ -23,9 +25,13 @@ struct Lwcond Lwcond(u64 name) : m_queue(name) { + signal.initialize(); } }; +// Aux +s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64); + // SysCalls s32 sys_lwcond_create(vm::ptr lwcond, vm::ptr lwmutex, vm::ptr attr); s32 sys_lwcond_destroy(vm::ptr lwcond); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp index df9829a02d..4a0702623f 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp @@ -11,43 +11,45 @@ SysCallBase sys_lwmutex("sys_lwmutex"); // TODO: move SleepQueue somewhere +s32 lwmutex_create(sys_lwmutex_t& lwmutex, u32 protocol, u32 recursive, u64 name_u64) +{ + LV2_LOCK(0); + + lwmutex.all_info() = 0; + lwmutex.attribute = protocol | recursive; + lwmutex.recursive_count = 0; + u32 sq_id = sys_lwmutex.GetNewId(new SleepQueue(name_u64), TYPE_LWMUTEX); + lwmutex.sleep_queue = sq_id; + + std::string name((const char*)&name_u64, 8); + sys_lwmutex.Notice("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d", name.c_str(), protocol | recursive, sq_id); + + Emu.GetSyncPrimManager().AddLwMutexData(sq_id, name, GetCurrentPPUThread().GetId()); + + return CELL_OK; +} + s32 sys_lwmutex_create(vm::ptr lwmutex, vm::ptr attr) { - sys_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)", - lwmutex.addr(), attr.addr()); + sys_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr=0x%x, attr_addr=0x%x)", lwmutex.addr(), attr.addr()); - switch (attr->attr_recursive.ToBE()) + switch (attr->recursive.ToBE()) { case se32(SYS_SYNC_RECURSIVE): break; case se32(SYS_SYNC_NOT_RECURSIVE): break; - default: sys_lwmutex.Error("Unknown recursive attribute(0x%x)", (u32)attr->attr_recursive); return CELL_EINVAL; + default: sys_lwmutex.Error("Unknown recursive attribute(0x%x)", (u32)attr->recursive); return CELL_EINVAL; } - switch (attr->attr_protocol.ToBE()) + switch (attr->protocol.ToBE()) { case se32(SYS_SYNC_PRIORITY): break; case se32(SYS_SYNC_RETRY): break; case se32(SYS_SYNC_PRIORITY_INHERIT): sys_lwmutex.Error("Invalid SYS_SYNC_PRIORITY_INHERIT protocol attr"); return CELL_EINVAL; case se32(SYS_SYNC_FIFO): break; - default: sys_lwmutex.Error("Unknown protocol attribute(0x%x)", (u32)attr->attr_protocol); return CELL_EINVAL; + default: sys_lwmutex.Error("Unknown protocol attribute(0x%x)", (u32)attr->protocol); return CELL_EINVAL; } - lwmutex->attribute = attr->attr_protocol | attr->attr_recursive; - lwmutex->waiter = 0; - lwmutex->mutex.initialize(); - //lwmutex->waiter = lwmutex->owner.GetOwner(); - lwmutex->pad = 0; - lwmutex->recursive_count = 0; - - u32 sq_id = sys_lwmutex.GetNewId(new SleepQueue(attr->name_u64), TYPE_LWMUTEX); - lwmutex->sleep_queue = sq_id; - - sys_lwmutex.Warning("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d", - std::string(attr->name, 8).c_str(), (u32) lwmutex->attribute, sq_id); - - Emu.GetSyncPrimManager().AddLwMutexData(sq_id, std::string(attr->name, 8), GetCurrentPPUThread().GetId()); - - return CELL_OK; + return lwmutex_create(*lwmutex, attr->protocol, attr->recursive, attr->name_u64); } s32 sys_lwmutex_destroy(vm::ptr lwmutex) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h index 067a317e1b..16a2381f60 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h @@ -29,8 +29,8 @@ enum struct sys_lwmutex_attribute_t { - be_t attr_protocol; - be_t attr_recursive; + be_t protocol; + be_t recursive; union { char name[8]; @@ -66,19 +66,26 @@ struct SleepQueue struct sys_lwmutex_t { - /* volatile */ SMutexBase> mutex; - /* volatile */ be_t waiter; // not used - u64 &all_info(){return *(reinterpret_cast(this));} + SMutexBase> mutex; + be_t waiter; // currently not used be_t attribute; be_t recursive_count; be_t sleep_queue; be_t pad; + u64& all_info() + { + return *(reinterpret_cast(this)); + } + int trylock(be_t tid); int unlock(be_t tid); int lock(be_t tid, u64 timeout); }; +// Aux +s32 lwmutex_create(sys_lwmutex_t& lwmutex, u32 protocol, u32 recursive, u64 name_u64); + // SysCalls s32 sys_lwmutex_create(vm::ptr lwmutex, vm::ptr attr); s32 sys_lwmutex_destroy(vm::ptr lwmutex); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h index a94ce37eaf..d3d261138e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h @@ -34,6 +34,7 @@ struct Mutex , m_queue(name) , cond_count(0) { + m_mutex.initialize(); } ~Mutex(); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp index a7ddb0468e..6b2c7d594a 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp @@ -5,13 +5,23 @@ #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/PPUThread.h" -#include "sys_semaphore.h" #include "sys_time.h" -//#include "Utilities/SMutex.h" +#include "sys_semaphore.h" SysCallBase sys_semaphore("sys_semaphore"); -s32 sys_semaphore_create(vm::ptr> sem, vm::ptr attr, int initial_count, int max_count) +u32 semaphore_create(s32 initial_count, s32 max_count, u32 protocol, u64 name_u64) +{ + LV2_LOCK(0); + + const std::string name((const char*)&name_u64, 8); + const u32 id = sys_semaphore.GetNewId(new Semaphore(initial_count, max_count, protocol, name_u64), TYPE_SEMAPHORE); + sys_semaphore.Notice("*** semaphore created [%s] (protocol=0x%x): id = %d", name.c_str(), protocol, id); + Emu.GetSyncPrimManager().AddSemaphoreData(id, name, initial_count, max_count); + return id; +} + +s32 sys_semaphore_create(vm::ptr> sem, vm::ptr attr, s32 initial_count, s32 max_count) { sys_semaphore.Warning("sys_semaphore_create(sem_addr=0x%x, attr_addr=0x%x, initial_count=%d, max_count=%d)", sem.addr(), attr.addr(), initial_count, max_count); @@ -37,13 +47,7 @@ s32 sys_semaphore_create(vm::ptr> sem, vm::ptrprotocol); return CELL_EINVAL; } - u32 id = sys_semaphore.GetNewId(new Semaphore(initial_count, max_count, attr->protocol, attr->name_u64), TYPE_SEMAPHORE); - *sem = id; - sys_semaphore.Notice("*** semaphore created [%s] (protocol=0x%x): id = %d", - std::string(attr->name, 8).c_str(), (u32)attr->protocol, id); - - Emu.GetSyncPrimManager().AddSemaphoreData(id, std::string(attr->name, 8), initial_count, max_count); - + *sem = semaphore_create(initial_count, max_count, attr->protocol, attr->name_u64); return CELL_OK; } @@ -144,7 +148,7 @@ s32 sys_semaphore_trywait(u32 sem_id) } } -s32 sys_semaphore_post(u32 sem_id, int count) +s32 sys_semaphore_post(u32 sem_id, s32 count) { sys_semaphore.Log("sys_semaphore_post(sem_id=%d, count=%d)", sem_id, count); @@ -159,7 +163,7 @@ s32 sys_semaphore_post(u32 sem_id, int count) return CELL_EINVAL; } - if (count + sem->m_value - (int)sem->m_queue.count() > sem->max) + if (count + sem->m_value - (s32)sem->m_queue.count() > sem->max) { return CELL_EBUSY; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h index 6ce29cf398..d0deccb14e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h @@ -7,7 +7,7 @@ struct sys_semaphore_attribute be_t protocol; be_t pshared; // undefined be_t ipc_key; // undefined - be_t flags; // undefined + be_t flags; // undefined be_t pad; // not used union { @@ -20,14 +20,14 @@ struct Semaphore { std::mutex m_mutex; SleepQueue m_queue; - int m_value; + s32 m_value; u32 signal; - const int max; + const s32 max; const u32 protocol; const u64 name; - Semaphore(int initial_count, int max_count, u32 protocol, u64 name) + Semaphore(s32 initial_count, s32 max_count, u32 protocol, u64 name) : m_value(initial_count) , signal(0) , max(max_count) @@ -37,10 +37,13 @@ struct Semaphore } }; +// Aux +u32 semaphore_create(s32 initial_count, s32 max_count, u32 protocol, u64 name_u64); + // SysCalls -s32 sys_semaphore_create(vm::ptr> sem, vm::ptr attr, int initial_count, int max_count); +s32 sys_semaphore_create(vm::ptr> sem, vm::ptr attr, s32 initial_count, s32 max_count); s32 sys_semaphore_destroy(u32 sem_id); s32 sys_semaphore_wait(u32 sem_id, u64 timeout); s32 sys_semaphore_trywait(u32 sem_id); -s32 sys_semaphore_post(u32 sem_id, int count); +s32 sys_semaphore_post(u32 sem_id, s32 count); s32 sys_semaphore_get_value(u32 sem_id, vm::ptr> count); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index e2f7c19b12..26909c9408 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -5,6 +5,7 @@ #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/RawSPUThread.h" +#include "Emu/FS/vfsStreamMemory.h" #include "Emu/FS/vfsFile.h" #include "Loader/ELF.h" #include "sys_spu.h" @@ -22,7 +23,20 @@ u32 LoadSpuImage(vfsStream& stream, u32& spu_ep) return spu_offset; } -//156 +s32 spu_image_import(sys_spu_image& img, u32 src, u32 type) +{ + vfsStreamMemory f(src); + u32 entry; + u32 offset = LoadSpuImage(f, entry); + + img.type = SYS_SPU_IMAGE_TYPE_USER; + img.entry_point = entry; + img.addr = offset; // TODO: writing actual segment info + img.nsegs = 1; // wrong value + + return CELL_OK; +} + s32 sys_spu_image_open(vm::ptr img, vm::ptr path) { sys_spu.Warning("sys_spu_image_open(img_addr=0x%x, path_addr=0x%x [%s])", img.addr(), path.addr(), path.get_ptr()); @@ -37,15 +51,47 @@ s32 sys_spu_image_open(vm::ptr img, vm::ptr path) u32 entry; u32 offset = LoadSpuImage(f, entry); - img->type = 1; + img->type = SYS_SPU_IMAGE_TYPE_USER; img->entry_point = entry; - img->segs_addr = offset; - img->nsegs = 0; + img->addr = offset; // TODO: writing actual segment info + img->nsegs = 1; // wrong value return CELL_OK; } -//172 +SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4) +{ + if (option) + { + sys_spu.Todo("Unsupported SPU Thread options (0x%x)", option); + } + + u32 spu_ep = (u32)img.entry_point; + // Copy SPU image: + // TODO: use segment info + u32 spu_offset = (u32)Memory.Alloc(256 * 1024, 4096); + memcpy(vm::get_ptr(spu_offset), vm::get_ptr(img.addr), 256 * 1024); + + SPUThread& new_thread = static_cast(Emu.GetCPU().AddThread(CPU_THREAD_SPU)); + //initialize from new place: + new_thread.SetOffset(spu_offset); + new_thread.SetEntry(spu_ep); + new_thread.SetName(name); + new_thread.Run(); + new_thread.GPR[3] = u128::from64(0, a1); + new_thread.GPR[4] = u128::from64(0, a2); + new_thread.GPR[5] = u128::from64(0, a3); + new_thread.GPR[6] = u128::from64(0, a4); + + const u32 id = new_thread.GetId(); + if (group) group->list[spu_num] = id; + new_thread.group = group; + + sys_spu.Warning("*** New SPU Thread [%s] (ep=0x%x, opt=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d", + name.c_str(), spu_ep, option, a1, a2, a3, a4, id); + return &new_thread; +} + s32 sys_spu_thread_initialize(vm::ptr> thread, u32 group, u32 spu_num, vm::ptr img, vm::ptr attr, vm::ptr arg) { sys_spu.Warning("sys_spu_thread_initialize(thread_addr=0x%x, group=0x%x, spu_num=%d, img_addr=0x%x, attr_addr=0x%x, arg_addr=0x%x)", @@ -67,49 +113,23 @@ s32 sys_spu_thread_initialize(vm::ptr> thread, u32 group, u32 spu_num, return CELL_EBUSY; } - u32 spu_ep = (u32)img->entry_point; - - std::string name = "SPUThread"; - if (attr->name) - { - name = std::string(attr->name.get_ptr(), attr->name_len); - } - - u64 a1 = arg->arg1; - u64 a2 = arg->arg2; - u64 a3 = arg->arg3; - u64 a4 = arg->arg4; - - // Copy SPU image: - // TODO: use correct segment info - u32 spu_offset = (u32)Memory.Alloc(256 * 1024, 4096); - memcpy(vm::get_ptr(spu_offset), vm::get_ptr(img->segs_addr), 256 * 1024); - - CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU); - //initialize from new place: - new_thread.SetOffset(spu_offset); - new_thread.SetEntry(spu_ep); - new_thread.SetName(name); - new_thread.Run(); - static_cast(new_thread).GPR[3] = u128::from64(0, a1); - static_cast(new_thread).GPR[4] = u128::from64(0, a2); - static_cast(new_thread).GPR[5] = u128::from64(0, a3); - static_cast(new_thread).GPR[6] = u128::from64(0, a4); - - u32 id = new_thread.GetId(); - *thread = group_info->list[spu_num] = id; - static_cast(new_thread).group = group_info; - - sys_spu.Warning("*** New SPU Thread [%s] (img_offset=0x%x, ls_offset=0x%x, ep=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d", - (attr->name ? attr->name.get_ptr() : ""), (u32)img->segs_addr, ((SPUThread&)new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, id); - + *thread = spu_thread_initialize( + group_info, + spu_num, + *img, + attr->name ? std::string(attr->name.get_ptr(), attr->name_len) : "SPUThread", + attr->option, + arg->arg1, + arg->arg2, + arg->arg3, + arg->arg4)->GetId(); return CELL_OK; } -//166 s32 sys_spu_thread_set_argument(u32 id, vm::ptr arg) { sys_spu.Warning("sys_spu_thread_set_argument(id=%d, arg_addr=0x%x)", id, arg.addr()); + CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || thr->GetType() != CPU_THREAD_SPU) @@ -127,7 +147,6 @@ s32 sys_spu_thread_set_argument(u32 id, vm::ptr arg) return CELL_OK; } -//165 s32 sys_spu_thread_get_exit_status(u32 id, vm::ptr> status) { sys_spu.Warning("sys_spu_thread_get_exit_status(id=%d, status_addr=0x%x)", id, status.addr()); @@ -149,7 +168,6 @@ s32 sys_spu_thread_get_exit_status(u32 id, vm::ptr> status) return CELL_OK; } -//171 s32 sys_spu_thread_group_destroy(u32 id) { sys_spu.Warning("sys_spu_thread_group_destroy(id=%d)", id); @@ -192,7 +210,6 @@ s32 sys_spu_thread_group_destroy(u32 id) return CELL_OK; } -//173 s32 sys_spu_thread_group_start(u32 id) { sys_spu.Warning("sys_spu_thread_group_start(id=%d)", id); @@ -228,7 +245,6 @@ s32 sys_spu_thread_group_start(u32 id) return CELL_OK; } -//174 s32 sys_spu_thread_group_suspend(u32 id) { sys_spu.Log("sys_spu_thread_group_suspend(id=%d)", id); @@ -275,7 +291,6 @@ s32 sys_spu_thread_group_suspend(u32 id) return CELL_OK; } -//175 s32 sys_spu_thread_group_resume(u32 id) { sys_spu.Log("sys_spu_thread_group_resume(id=%d)", id); @@ -323,7 +338,6 @@ s32 sys_spu_thread_group_resume(u32 id) return CELL_OK; } -//176: Left doing nothing, indeed s32 sys_spu_thread_group_yield(u32 id) { sys_spu.Error("sys_spu_thread_group_yield(id=%d)", id); @@ -366,7 +380,6 @@ s32 sys_spu_thread_group_yield(u32 id) return CELL_OK; } -//177: Left omit the EPERM check. s32 sys_spu_thread_group_terminate(u32 id, int value) { sys_spu.Error("sys_spu_thread_group_terminate(id=%d, value=%d)", id, value); @@ -406,27 +419,37 @@ s32 sys_spu_thread_group_terminate(u32 id, int value) return CELL_OK; } -//170 -s32 sys_spu_thread_group_create(vm::ptr> id, u32 num, int prio, vm::ptr attr) +SpuGroupInfo* spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container) +{ + LV2_LOCK(0); + + if (type) + { + sys_spu.Todo("Unsupported SPU Thread Group type (0x%x)", type); + } + + auto group = new SpuGroupInfo(name, num, prio, type, container); + const u32 _id = sys_spu.GetNewId(group); + group->m_id = _id; + sys_spu.Notice("*** SPU Thread Group created [%s] (num=%d, prio=%d, type=0x%x, container=%d): id=%d", + name.c_str(), num, prio, type, container, _id); + return group; +} + +s32 sys_spu_thread_group_create(vm::ptr> id, u32 num, s32 prio, vm::ptr attr) { sys_spu.Warning("sys_spu_thread_group_create(id_addr=0x%x, num=%d, prio=%d, attr_addr=0x%x)", id.addr(), num, prio, attr.addr()); - if (num > 256) return CELL_EINVAL; - - if (prio < 16 || prio > 255) return CELL_EINVAL; - - const std::string name(attr->name.get_ptr(), attr->nsize); - - *id = sys_spu.GetNewId(new SpuGroupInfo(name, num, prio, attr->type, attr->ct)); - - sys_spu.Warning("*** SPU Thread Group created [%s] (type=0x%x, option.ct=0x%x): id=%d", - name.c_str(), (int)attr->type, (u32)attr->ct, (u32)*id); + if (!num || num > 6 || prio < 16 || prio > 255) + { + return CELL_EINVAL; + } + *id = spu_thread_group_create(std::string(attr->name.get_ptr(), attr->nsize - 1), num, prio, attr->type, attr->ct)->m_id; return CELL_OK; } -//178 s32 sys_spu_thread_group_join(u32 id, vm::ptr> cause, vm::ptr> status) { sys_spu.Warning("sys_spu_thread_group_join(id=%d, cause_addr=0x%x, status_addr=0x%x)", id, cause.addr(), status.addr()); @@ -487,7 +510,6 @@ s32 sys_spu_thread_create(vm::ptr> thread_id, vm::ptr> entry return CELL_OK; } -//169 s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu) { sys_spu.Warning("sys_spu_initialize(max_usable_spu=%d, max_raw_spu=%d)", max_usable_spu, max_raw_spu); @@ -500,7 +522,6 @@ s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu) return CELL_OK; } -//181 s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type) { sys_spu.Log("sys_spu_thread_write_ls(id=%d, address=0x%x, value=0x%llx, type=0x%x)", @@ -533,7 +554,6 @@ s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type) } } -//182 s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr> value, u32 type) { sys_spu.Log("sys_spu_thread_read_ls(id=%d, address=0x%x, value_addr=0x%x, type=0x%x)", @@ -566,7 +586,6 @@ s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr> value, u32 ty } } -//190 s32 sys_spu_thread_write_spu_mb(u32 id, u32 value) { sys_spu.Log("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value); @@ -583,7 +602,6 @@ s32 sys_spu_thread_write_spu_mb(u32 id, u32 value) return CELL_OK; } -//187 s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value) { sys_spu.Warning("sys_spu_thread_set_spu_cfg(id=%d, value=0x%x)", id, value); @@ -605,7 +623,6 @@ s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value) return CELL_OK; } -//188 s32 sys_spu_thread_get_spu_cfg(u32 id, vm::ptr> value) { sys_spu.Warning("sys_spu_thread_get_spu_cfg(id=%d, value_addr=0x%x)", id, value.addr()); @@ -622,7 +639,6 @@ s32 sys_spu_thread_get_spu_cfg(u32 id, vm::ptr> value) return CELL_OK; } -//184 s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value) { sys_spu.Log("sys_spu_thread_write_snr(id=%d, number=%d, value=0x%x)", id, number, value); @@ -713,7 +729,6 @@ s32 sys_spu_thread_connect_event(u32 id, u32 eq_id, u32 et, u8 spup) return CELL_OK; } -// s32 sys_spu_thread_disconnect_event(u32 id, u32 et, u8 spup) { sys_spu.Warning("sys_spu_thread_disconnect_event(id=%d, event_type=0x%x, spup=%d)", id, et, spup); @@ -884,7 +899,6 @@ s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup) return CELL_OK; } -//160 s32 sys_raw_spu_create(vm::ptr> id, u32 attr_addr) { sys_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id.addr(), attr_addr); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.h b/rpcs3/Emu/SysCalls/lv2/sys_spu.h index 5888aabfdd..53edee68bc 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.h @@ -1,6 +1,6 @@ #pragma once -enum +enum : s32 { SYS_SPU_THREAD_GROUP_TYPE_NORMAL = 0x00, SYS_SPU_THREAD_GROUP_TYPE_SEQUENTIAL = 0x01, @@ -8,7 +8,7 @@ enum SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER = 0x04, SYS_SPU_THREAD_GROUP_TYPE_NON_CONTEXT = 0x08, SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT = 0x18, - SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM = 0x20 + SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM = 0x20, }; enum @@ -18,7 +18,8 @@ enum SYS_SPU_THREAD_GROUP_JOIN_TERMINATED = 0x0004 }; -enum { +enum +{ SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED, SPU_THREAD_GROUP_STATUS_INITIALIZED, SPU_THREAD_GROUP_STATUS_READY, @@ -30,11 +31,11 @@ enum { SPU_THREAD_GROUP_STATUS_UNKNOWN }; -enum +enum : s32 { - SYS_SPU_SEGMENT_TYPE_COPY = 0x0001, - SYS_SPU_SEGMENT_TYPE_FILL = 0x0002, - SYS_SPU_SEGMENT_TYPE_INFO = 0x0004, + SYS_SPU_SEGMENT_TYPE_COPY = 1, + SYS_SPU_SEGMENT_TYPE_FILL = 2, + SYS_SPU_SEGMENT_TYPE_INFO = 4, }; struct sys_spu_thread_group_attribute @@ -45,6 +46,13 @@ struct sys_spu_thread_group_attribute be_t ct; // memory container id }; +enum : u32 +{ + SYS_SPU_THREAD_OPTION_NONE = 0, + SYS_SPU_THREAD_OPTION_ASYNC_INTR_ENABLE = 1, + SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE = 2, +}; + struct sys_spu_thread_attribute { vm::bptr name; @@ -60,20 +68,43 @@ struct sys_spu_thread_argument be_t arg4; }; -struct sys_spu_image -{ - be_t type; - be_t entry_point; - be_t segs_addr; //temporarily used as offset of LS image after elf loading - be_t nsegs; -}; - struct sys_spu_segment { - be_t type; - be_t ls_start; - be_t size; - be_t src; + be_t type; // copy, fill, info + be_t ls; // local storage address + be_t size; + + union + { + be_t addr; // address or fill value + u64 pad; + }; +}; + +static_assert(sizeof(sys_spu_segment) == 0x18, "Wrong sys_spu_segment size"); + +enum : u32 +{ + SYS_SPU_IMAGE_TYPE_USER = 0, + SYS_SPU_IMAGE_TYPE_KERNEL = 1, +}; + +struct sys_spu_image +{ + be_t type; // user, kernel + be_t entry_point; + union + { + be_t addr; // temporarily used as offset of the whole LS image (should be removed) + vm::bptr segs; + }; + be_t nsegs; +}; + +enum : u32 +{ + SYS_SPU_IMAGE_PROTECT = 0, + SYS_SPU_IMAGE_DIRECT = 1, }; struct SpuGroupInfo @@ -81,15 +112,16 @@ struct SpuGroupInfo std::vector list; std::atomic lock; std::string m_name; - int m_prio; - int m_type; - int m_ct; + u32 m_id; + s32 m_prio; + s32 m_type; + u32 m_ct; u32 m_count; - int m_state; //SPU Thread Group State. + s32 m_state; //SPU Thread Group State. u32 m_exit_status; bool m_group_exit; - SpuGroupInfo(const std::string& name, u32 num, int prio, int type, u32 ct) + SpuGroupInfo(const std::string& name, u32 num, s32 prio, s32 type, u32 ct) : m_name(name) , m_prio(prio) , m_type(type) @@ -107,6 +139,13 @@ struct SpuGroupInfo } }; +class SPUThread; + +// Aux +s32 spu_image_import(sys_spu_image& img, u32 src, u32 type); +SpuGroupInfo* spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container); +SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4); + // SysCalls s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu); s32 sys_spu_image_open(vm::ptr img, vm::ptr path); From 5ad68cfe300414cb46d80d8a0dceba7572b99378 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 19 Sep 2014 04:24:06 +0400 Subject: [PATCH 02/24] Compilation fix --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 056f453f88..92737bae4a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -497,8 +497,6 @@ s64 cellSpursFinalize(vm::ptr spurs) #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x8568, libsre_rtoc); #else - spurs->spurs->Finalize(); - return CELL_OK; #endif } From dbd49a55c6fbd28fc8286a85246ccb59dc6ddf91 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 19 Sep 2014 15:27:51 +0400 Subject: [PATCH 03/24] CellSpurs initialization --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 22 ++++++++- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 4 +- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 60 +++++++++++++---------- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h | 5 ++ 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 92737bae4a..7562cd0806 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -4,6 +4,7 @@ #include "Emu/SysCalls/Callback.h" #include "Emu/Cell/SPUThread.h" +#include "Emu/SysCalls/lv2/sys_ppu_thread.h" #include "Emu/SysCalls/lv2/sys_memory.h" #include "Emu/SysCalls/lv2/sys_process.h" #include "Emu/SysCalls/lv2/sys_semaphore.h" @@ -76,8 +77,8 @@ s64 spursInit( memset(spurs.get_ptr(), 0, CellSpurs::size1 + isSecond * CellSpurs::size2); spurs->m.revision = revision; spurs->m.sdkVersion = sdkVersion; - spurs->m.unk1 = 0xffffffffull; - spurs->m.unk2 = 0xffffffffull; + spurs->m.ppu0 = 0xffffffffull; + spurs->m.ppu1 = 0xffffffffull; spurs->m.flags = flags; memcpy(spurs->m.prefix, prefix, prefixSize); spurs->m.prefixSize = (u8)prefixSize; @@ -149,6 +150,7 @@ s64 spursInit( if (flags & SAF_UNKNOWN_FLAG_8) tgt |= 0xC02; if (flags & SAF_UNKNOWN_FLAG_9) tgt |= 0x800; auto tg = spu_thread_group_create(name + "CellSpursKernelGroup", nSpus, spuPriority, tgt, container); + assert(tg); spurs->m.spuTG = tg->m_id; name += "CellSpursKernel0"; @@ -189,6 +191,22 @@ s64 spursInit( assert(sys_event_port_connect_local(port, queue) == CELL_OK); + name = std::string(prefix, prefixSize); + + PPUThread* ppu0 = nullptr; +#ifdef PRX_DEBUG + ppu0 = ppu_thread_create(vm::read32(libsre_rtoc - 0x7E60), spurs.addr(), ppuPriority, 0x4000, true, false, name + "SpursHdlr0"); +#endif + assert(ppu0); + spurs->m.ppu0 = ppu0->GetId(); + + PPUThread* ppu1 = nullptr; +#ifdef PRX_DEBUG + ppu1 = ppu_thread_create(vm::read32(libsre_rtoc - 0x7E24), spurs.addr(), ppuPriority, 0x8000, true, false, name + "SpursHdlr1"); +#endif + assert(ppu1); + spurs->m.ppu1 = ppu1->GetId(); + return CELL_OK; #endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index a01e1591de..a85c4c928d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -186,8 +186,8 @@ struct CellSpurs be_t unk9; // 0xD10 u8 unk10; // 0xD14 u8 unknown5[0xD20 - 0xD15]; - be_t unk1; // 0xD20 - be_t unk2; // 0xD28 + be_t ppu0; // 0xD20 + be_t ppu1; // 0xD28 be_t spuTG; // 0xD30 be_t spus[8]; // 0xD34 u8 unknown3[0xD5C - 0xD54]; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index c63b93bcfd..f9cd0f3ec2 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -147,6 +147,39 @@ s32 sys_ppu_thread_restart(u64 thread_id) return CELL_OK; } +PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, const std::string& name) +{ + PPUThread& new_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); + + u32 id = new_thread.GetId(); + new_thread.SetEntry(entry); + new_thread.SetPrio(prio); + new_thread.SetStackSize(stacksize); + //new_thread.flags = flags; + new_thread.m_has_interrupt = false; + new_thread.m_is_interrupt = is_interrupt; + new_thread.SetName(name); + + sys_ppu_thread.Notice("*** New PPU Thread [%s] (%s, entry=0x%x): id = %d", name.c_str(), + is_interrupt ? "interrupt" : + (is_joinable ? "joinable" : "non-joinable"), entry, id); + + if (!is_interrupt) + { + new_thread.Run(); + new_thread.GPR[3] = arg; + new_thread.Exec(); + } + else + { + new_thread.InitStack(); + new_thread.InitRegs(); + new_thread.DoRun(); + } + + return &new_thread; +} + s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::ptr threadname) { sys_ppu_thread.Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))", @@ -171,32 +204,9 @@ s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 default: sys_ppu_thread.Error("sys_ppu_thread_create(): unknown flags value (0x%llx)", flags); return CELL_EPERM; } - PPUThread& new_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); - - *thread_id = new_thread.GetId(); - new_thread.SetEntry(entry); - new_thread.SetPrio(prio); - new_thread.SetStackSize(stacksize); - //new_thread.flags = flags; - new_thread.m_has_interrupt = false; - new_thread.m_is_interrupt = is_interrupt; - new_thread.SetName(threadname ? threadname.get_ptr() : ""); - - sys_ppu_thread.Notice("*** New PPU Thread [%s] (flags=0x%llx, entry=0x%x): id = %d", new_thread.GetName().c_str(), flags, entry, new_thread.GetId()); - - if (!is_interrupt) - { - new_thread.Run(); - new_thread.GPR[3] = arg; - new_thread.Exec(); - } - else - { - new_thread.InitStack(); - new_thread.InitRegs(); - new_thread.DoRun(); - } + std::string name = threadname ? threadname.get_ptr() : ""; + *thread_id = ppu_thread_create(entry, arg, prio, stacksize, is_joinable, is_interrupt, name)->GetId(); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h index 0bbe4aabc3..4b79c4f7e9 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h @@ -1,5 +1,7 @@ #pragma once +class PPUThread; + enum { SYS_PPU_THREAD_ONCE_INIT, @@ -12,6 +14,9 @@ enum ppu_thread_flags : u64 SYS_PPU_THREAD_CREATE_INTERRUPT = 0x2, }; +// Aux +PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, const std::string& name); + // SysCalls void sys_ppu_thread_exit(PPUThread& CPU, u64 errorcode); void sys_internal_ppu_thread_exit(PPUThread& CPU, u64 errorcode); From b6f8700b8b111808b8dcd1e1dbe5ed443752c253 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 19 Sep 2014 23:11:43 +0400 Subject: [PATCH 04/24] vm::atomic initial structure --- Utilities/SMutex.h | 21 +++----- rpcs3/Emu/Memory/vm.h | 3 +- rpcs3/Emu/Memory/vm_atomic.h | 63 +++++++++++++++++++++++ rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 33 +++++++++++- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 34 +++++++++--- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 6 +-- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h | 8 +-- rpcs3/Emu/SysCalls/lv2/sys_spu.h | 14 +++++ rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 ++ 10 files changed, 156 insertions(+), 30 deletions(-) create mode 100644 rpcs3/Emu/Memory/vm_atomic.h diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index ebab2f0cff..e62361b304 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -1,4 +1,5 @@ #pragma once +#include "Emu/Memory/vm_atomic.h" bool SM_IsAborted(); void SM_Sleep(); @@ -24,9 +25,9 @@ template > class SMutexBase { - static_assert(sizeof(T) == sizeof(std::atomic), "Invalid SMutexBase type"); + static_assert(sizeof(T) == sizeof(vm::atomic_le), "Invalid SMutexBase type"); T owner; - typedef std::atomic AT; + typedef vm::atomic_le AT; public: static const T GetFreeValue() @@ -46,11 +47,6 @@ public: owner = GetFreeValue(); } - //SMutexBase() - //{ - // initialize(); - //} - void finalize() { owner = GetDeadValue(); @@ -67,9 +63,9 @@ public: { return SMR_ABORT; } - T old = GetFreeValue(); + T old = reinterpret_cast(owner).compare_and_swap(GetFreeValue(), tid); - if (!reinterpret_cast(owner).compare_exchange_strong(old, tid)) + if (old != GetFreeValue()) { if (old == tid) { @@ -91,9 +87,9 @@ public: { return SMR_ABORT; } - T old = tid; + T old = reinterpret_cast(owner).compare_and_swap(tid, to); - if (!reinterpret_cast(owner).compare_exchange_strong(old, to)) + if (old != tid) { if (old == GetFreeValue()) { @@ -132,5 +128,4 @@ public: } }; -typedef SMutexBase - SMutex; +typedef SMutexBase SMutex; diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index fd3ab07d38..af24ccf86e 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -204,4 +204,5 @@ namespace vm #include "vm_ref.h" #include "vm_ptr.h" -#include "vm_var.h" \ No newline at end of file +#include "vm_var.h" +#include "vm_atomic.h" diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h new file mode 100644 index 0000000000..c292f1a7ed --- /dev/null +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -0,0 +1,63 @@ +#pragma once + +namespace vm +{ + template + struct _to_atomic + { + static_assert(size == 4 || size == 8, "Invalid atomic type"); + + typedef T type; + }; + + template + struct _to_atomic + { + typedef uint32_t type; + }; + + template + struct _to_atomic + { + typedef uint64_t type; + }; + + template + class _atomic_base + { + T data; + typedef typename _to_atomic::type atomic_type; + + public: + T compare_and_swap(T cmp, T exch) + { + const atomic_type res = InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp); + return (T&)res; + } + + }; + + template struct atomic_le : public _atomic_base + { + }; + + template struct atomic_be : public _atomic_base::type> + { + }; + + namespace ps3 + { + template struct atomic : public atomic_be + { + }; + } + + namespace psv + { + template struct atomic : public atomic_le + { + }; + } + + using namespace ps3; +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 7562cd0806..4a2e215efa 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -207,6 +207,37 @@ s64 spursInit( assert(ppu1); spurs->m.ppu1 = ppu1->GetId(); + // enable exception event handler + if (spurs->m.enableEH.compare_and_swap(be_t::MakeFromBE(0), be_t::MakeFromBE(se32(1))).ToBE() != 0) + { + assert(sys_spu_thread_group_connect_event(spurs->m.spuTG, spurs->m.queue, SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION) == CELL_OK); + } + + spurs->m.unk22 = 0; + // can also use cellLibprof if available (omitted) + + // some unknown subroutine + spurs->m.sub3.unk1 = spurs.addr() + 0xc9; + spurs->m.sub3.unk2 = 3; // unknown const + spurs->m.sub3.port = (u64)spurs->m.port; + + if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) // initialize system workload + { + s32 res; +#ifdef PRX_DEBUG + res = cb_call, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x10428, libsre_rtoc, + spurs, Memory.RealToVirtualAddr(swlPriority), swlMaxSpu, swlIsPreem); +#else + res = -1; +#endif + assert(res == CELL_OK); + } + else if (flags & SAF_EXIT_IF_NO_WORK) // wakeup + { +#ifdef PRX_DEBUG + return cb_call>(GetCurrentPPUThread(), libsre + 0x84D8, libsre_rtoc, spurs); +#endif + } return CELL_OK; #endif } @@ -1657,7 +1688,7 @@ s64 cellSpursAddWorkload() #endif } -s64 cellSpursWakeUp() +s64 cellSpursWakeUp(vm::ptr spurs) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index a85c4c928d..717e9afe94 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -149,8 +149,21 @@ struct CellSpurs { static const uint size = 0x80; - be_t sem; - u8 unk_[0x78]; + u8 unk0[0x20]; + be_t sem; // 0x20 + u8 unk_[0x58]; + }; + + struct _sub_str2 + { + static const uint size = 0x80; + + be_t unk0; + be_t unk1; + be_t unk2; + be_t unk3; + be_t port; // 0x10 + u8 unk_[0x68]; }; union @@ -173,9 +186,10 @@ struct CellSpurs be_t unk0; // 0x0B0 u8 unknown2[0xC0 - 0xB4]; u8 unk6[0x10]; // 0x0C0 - u8 unknown1[0x120 - 0x0D0]; - _sub_str1 sub1[0x10]; // 0x120 - u8 unknown7[0x980 - 0x920]; + u8 unknown1[0x100 - 0x0D0]; + _sub_str1 sub1[0x10]; // 0x100 + be_t unk22; // 0x900 + u8 unknown7[0x980 - 0x908]; be_t semPrv; // 0x980 be_t unk11; // 0x988 be_t unk12; // 0x98C @@ -193,7 +207,9 @@ struct CellSpurs u8 unknown3[0xD5C - 0xD54]; be_t queue; // 0xD5C be_t port; // 0xD60 - u8 unk19[0xC]; // 0xD64 + be_t unk19; // 0xD64 + vm::atomic enableEH; // 0xD68 + be_t unk21; // 0xD6C sys_spu_image spuImg; // 0xD70 be_t flags; // 0xD80 be_t spuPriority;// 0xD84 @@ -206,8 +222,10 @@ struct CellSpurs u8 unknown8[0xDB0 - 0xDA8]; sys_lwmutex_t mutex; // 0xDB0 sys_lwcond_t cond; // 0xDC8 - u8 unknown6[0x1220 - 0xDD0]; - _sub_str1 sub2[0x10]; // 0x1220 + u8 unknown9[0xF00 - 0xDD0]; + _sub_str2 sub3; // 0xF00 + u8 unknown6[0x1200 - 0xF80]; + _sub_str1 sub2[0x10]; // 0x1200 // ... } m; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index f9cd0f3ec2..385115d47f 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -210,12 +210,12 @@ s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 return CELL_OK; } -void sys_ppu_thread_once(PPUThread& CPU, vm::ptr>> once_ctrl, vm::ptr init) +void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init) { sys_ppu_thread.Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, init_addr=0x%x)", once_ctrl.addr(), init.addr()); - be_t old = be_t::MakeFromBE(se32(SYS_PPU_THREAD_ONCE_INIT)); - if (once_ctrl->compare_exchange_weak(old, be_t::MakeFromBE(se32(SYS_PPU_THREAD_DONE_INIT)))) + auto cmp = to_be(SYS_PPU_THREAD_ONCE_INIT); + if (once_ctrl->compare_and_swap(cmp, to_be(SYS_PPU_THREAD_DONE_INIT)) == cmp) { init.call(CPU); } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h index 4b79c4f7e9..b5d8540d32 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h @@ -2,10 +2,10 @@ class PPUThread; -enum +enum : u32 { - SYS_PPU_THREAD_ONCE_INIT, - SYS_PPU_THREAD_DONE_INIT, + SYS_PPU_THREAD_ONCE_INIT = 0, + SYS_PPU_THREAD_DONE_INIT = 1, }; enum ppu_thread_flags : u64 @@ -30,6 +30,6 @@ s32 sys_ppu_thread_get_stack_information(PPUThread& CPU, u32 info_addr); s32 sys_ppu_thread_stop(u64 thread_id); s32 sys_ppu_thread_restart(u64 thread_id); s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::ptr threadname); -void sys_ppu_thread_once(PPUThread& CPU, vm::ptr>> once_ctrl, vm::ptr init); +void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init); s32 sys_ppu_thread_get_id(PPUThread& CPU, vm::ptr> thread_id); s32 sys_ppu_thread_rename(u64 thread_id, vm::ptr name); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.h b/rpcs3/Emu/SysCalls/lv2/sys_spu.h index 53edee68bc..526334fe36 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.h @@ -18,6 +18,20 @@ enum SYS_SPU_THREAD_GROUP_JOIN_TERMINATED = 0x0004 }; +enum +{ + SYS_SPU_THREAD_GROUP_EVENT_RUN = 1, + SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION = 2, + SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE = 4, +}; + +enum : u64 +{ + SYS_SPU_THREAD_GROUP_EVENT_RUN_KEY = 0xFFFFFFFF53505500ull, + SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION_KEY = 0xFFFFFFFF53505503ull, + SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE_KEY = 0xFFFFFFFF53505504ull, +}; + enum { SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED, diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index f09d6a99d5..e46932a9d3 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -311,6 +311,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 038502f880..573ebd2fed 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1219,5 +1219,8 @@ Emu\SysCalls + + Emu\Memory + \ No newline at end of file From 0baf295c1be88444fa2e1eb4d3771cd0640c4593 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 19 Sep 2014 23:12:31 +0400 Subject: [PATCH 05/24] to_be() --- Utilities/BEType.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 4e3da154c5..148b5a4e25 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -540,6 +540,12 @@ template struct _se, T1, value> : pub #define se32(x) _se::value #define se64(x) _se::value +template +__forceinline static const be_t to_be(const T value) +{ + return be_t::MakeFromLE(value); +} + template __forceinline static u8 Read8(T& f) { u8 ret; From 66000240ac5bf9aea8e6e4d58af448c7bdac960d Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 20 Sep 2014 03:16:11 +0400 Subject: [PATCH 06/24] vm::atomic update, be_t update 1) MakeFromLE replaced with make(), MakeFromBE removed. Compiler seems to be able to optimize it anyway. 2) be_t<> conversion operator temporarily replaced with conversion through LE because it can't work with all possible numeric conversions (float<>int for example) --- Utilities/BEType.h | 39 +++------------------ Utilities/GNU.h | 17 +++++++-- rpcs3/Crypto/unpkg.cpp | 4 +-- rpcs3/Emu/CPU/CPUThread.h | 2 +- rpcs3/Emu/Memory/vm_atomic.h | 15 ++++++-- rpcs3/Emu/RSX/sysutil_video.h | 18 +++++----- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 7 ++-- rpcs3/Emu/SysCalls/Modules/cellSync.h | 2 +- rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp | 6 ++-- rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp | 8 ++--- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 4 +-- rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp | 18 +++++----- rpcs3/Emu/SysCalls/lv2/sys_spinlock.h | 8 ++--- rpcs3/Loader/TROPUSR.cpp | 35 +++++++++++++----- 16 files changed, 98 insertions(+), 89 deletions(-) diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 148b5a4e25..ee5989f100 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -306,17 +306,12 @@ public: m_data = se_t::func(value); } - static be_t MakeFromLE(const T value) + static be_t make(const T value) { T data = se_t::func(value); return (be_t&)data; } - static be_t MakeFromBE(const T value) - { - return (be_t&)value; - } - //template operator const T() const { @@ -335,7 +330,8 @@ public: template operator const be_t() const { - return _convert sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data); + return be_t::make(ToLE()); + //return _convert sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data); } template be_t& operator += (T1 right) { return *this = T(*this) + right; } @@ -401,17 +397,12 @@ public: return se_t::func(m_data); } - static be_t MakeFromLE(const T value) + static be_t make(const T value) { const T data = se_t::func(value); return (be_t&)data; } - static be_t MakeFromBE(const T value) - { - return (be_t&)value; - } - //template operator const T() const { @@ -421,21 +412,7 @@ public: template operator const be_t() const { - if (sizeof(T1) > sizeof(T) || std::is_floating_point::value || std::is_floating_point::value) - { - T1 res = se_t::func(ToLE()); - return (be_t&)res; - } - else if (sizeof(T1) < sizeof(T)) - { - T1 res = ToBE() >> ((sizeof(T) - sizeof(T1)) * 8); - return (be_t&)res; - } - else - { - T1 res = ToBE(); - return (be_t&)res; - } + return be_t::make(ToLE()); } template be_t operator & (const be_t& right) const { const T res = ToBE() & right.ToBE(); return (be_t&)res; } @@ -540,12 +517,6 @@ template struct _se, T1, value> : pub #define se32(x) _se::value #define se64(x) _se::value -template -__forceinline static const be_t to_be(const T value) -{ - return be_t::MakeFromLE(value); -} - template __forceinline static u8 Read8(T& f) { u8 ret; diff --git a/Utilities/GNU.h b/Utilities/GNU.h index 9b5d40ec6b..d4eb6cb103 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -45,7 +45,7 @@ void strcpy_trunc(char(&dst)[size], const char(&src)[rsize]) #define INFINITE 0xFFFFFFFF #define _CRT_ALIGN(x) __attribute__((aligned(x))) #define InterlockedCompareExchange(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val) -#define InterlockedCompareExchange64(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val) +#define InterlockedExchange(ptr, value) __sync_lock_test_and_set(ptr, value) inline int64_t InterlockedOr64(volatile int64_t *dest, int64_t val) { @@ -54,7 +54,7 @@ inline int64_t InterlockedOr64(volatile int64_t *dest, int64_t val) do { olderval = oldval; - oldval = InterlockedCompareExchange64(dest, olderval | val, olderval); + oldval = __sync_val_compare_and_swap(dest, olderval | val, olderval); } while (olderval != oldval); return oldval; } @@ -100,4 +100,15 @@ static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest { return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp); } -#endif \ No newline at end of file +#endif + +#ifndef InterlockedExchange +static __forceinline uint32_t InterlockedExchange(volatile uint32_t* dest, uint32_t value) +{ + return _InterlockedExchange((volatile long*)dest, value); +} +static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint64_t value) +{ + return _InterlockedExchange64((volatile long long*)dest, value); +} +#endif diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index caae7fb9f7..39f4bf99a8 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -120,8 +120,8 @@ int Decrypt(rFile& pkg_f, rFile& dec_pkg_f, PKGHeader* m_header) { aes_crypt_ecb(&c, AES_ENCRYPT, iv, ctr+j*HASH_LEN); - be_t hi = be_t::MakeFromBE(*(u64*)&iv[0]); - be_t lo = be_t::MakeFromBE(*(u64*)&iv[8]); + be_t hi = *(be_t*)&iv[0]; + be_t lo = *(be_t*)&iv[8]; lo++; if (lo == 0) diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 65b5c7afdc..e70007773c 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -109,7 +109,7 @@ public: virtual std::string GetThreadName() const { - std::string temp = (GetFName() + fmt::Format("[0x%08llx]", PC)); + std::string temp = (GetFName() + fmt::Format("[0x%08x]", PC)); return temp; } diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h index c292f1a7ed..9019f0407f 100644 --- a/rpcs3/Emu/Memory/vm_atomic.h +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -25,16 +25,27 @@ namespace vm template class _atomic_base { - T data; + volatile T data; typedef typename _to_atomic::type atomic_type; public: - T compare_and_swap(T cmp, T exch) + __forceinline const T compare_and_swap(const T cmp, const T exch) volatile { const atomic_type res = InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp); return (T&)res; } + __forceinline const T exchange(const T value) volatile + { + const atomic_type res = InterlockedExchange((volatile atomic_type*)&data, (atomic_type&)value); + return (T&)res; + } + + __forceinline const T read_relaxed() const volatile + { + return (T&)data; + } + }; template struct atomic_le : public _atomic_base diff --git a/rpcs3/Emu/RSX/sysutil_video.h b/rpcs3/Emu/RSX/sysutil_video.h index 36bda57b4e..c5bf9426cd 100644 --- a/rpcs3/Emu/RSX/sysutil_video.h +++ b/rpcs3/Emu/RSX/sysutil_video.h @@ -228,15 +228,15 @@ enum CellVideoOutRGBOutputRange static const CellVideoOutResolution ResolutionTable[] = { - { be_t::MakeFromBE(se16(0xffff)), be_t::MakeFromBE(se16(0xffff)) }, //0 - 0 - { be_t::MakeFromBE(se16(1920)), be_t::MakeFromBE(se16(1080)) }, //1 - 1 - { be_t::MakeFromBE(se16(1280)), be_t::MakeFromBE(se16(720)) }, //2 - 2 - { be_t::MakeFromBE(se16(720)), be_t::MakeFromBE(se16(480)) }, //4 - 3 - { be_t::MakeFromBE(se16(720)), be_t::MakeFromBE(se16(576)) }, //5 - 4 - { be_t::MakeFromBE(se16(1600)), be_t::MakeFromBE(se16(1080)) }, //10 - 5 - { be_t::MakeFromBE(se16(1440)), be_t::MakeFromBE(se16(1080)) }, //11 - 6 - { be_t::MakeFromBE(se16(1280)), be_t::MakeFromBE(se16(1080)) }, //12 - 7 - { be_t::MakeFromBE(se16(960)), be_t::MakeFromBE(se16(1080)) }, //13 - 8 + { be_t::make(0xffff), be_t::make(0xffff) }, //0 - 0 + { be_t::make(1920), be_t::make(1080) }, //1 - 1 + { be_t::make(1280), be_t::make(720) }, //2 - 2 + { be_t::make(720), be_t::make(480) }, //4 - 3 + { be_t::make(720), be_t::make(576) }, //5 - 4 + { be_t::make(1600), be_t::make(1080) }, //10 - 5 + { be_t::make(1440), be_t::make(1080) }, //11 - 6 + { be_t::make(1280), be_t::make(1080) }, //12 - 7 + { be_t::make(960), be_t::make(1080) }, //13 - 8 }; inline static u32 ResolutionIdToNum(u32 id) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 61dad6c763..ecc5bf8625 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -210,7 +210,7 @@ void getSaveDataStat(SaveDataEntry entry, vm::ptr statGet) } } - statGet->fileList = vm::bptr::make(be_t::MakeFromLE((u32)Memory.Alloc(sizeof(CellSaveDataFileStat) * (u32)fileEntries.size(), sizeof(CellSaveDataFileStat)))); + statGet->fileList = vm::bptr::make(be_t::make((u32)Memory.Alloc(sizeof(CellSaveDataFileStat) * (u32)fileEntries.size(), sizeof(CellSaveDataFileStat)))); for (u32 i=0; ifileList[i], &fileEntries[i], sizeof(CellSaveDataFileStat)); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 4a2e215efa..c43826648a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -208,7 +208,7 @@ s64 spursInit( spurs->m.ppu1 = ppu1->GetId(); // enable exception event handler - if (spurs->m.enableEH.compare_and_swap(be_t::MakeFromBE(0), be_t::MakeFromBE(se32(1))).ToBE() != 0) + if (spurs->m.enableEH.compare_and_swap(be_t::make(0), be_t::make(1)).ToBE() == 0) { assert(sys_spu_thread_group_connect_event(spurs->m.spuTG, spurs->m.queue, SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION) == CELL_OK); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 43df317feb..112ea57f5e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -16,7 +16,7 @@ u32 libsre; u32 libsre_rtoc; #endif -s32 syncMutexInitialize(vm::ptr mutex) +s32 syncMutexInitialize(vm::ptr> mutex) { if (!mutex) { @@ -28,12 +28,11 @@ s32 syncMutexInitialize(vm::ptr mutex) } // prx: set zero and sync - mutex->m_data() = 0; - InterlockedCompareExchange(&mutex->m_data(), 0, 0); + mutex->exchange({}); return CELL_OK; } -s32 cellSyncMutexInitialize(vm::ptr mutex) +s32 cellSyncMutexInitialize(vm::ptr> mutex) { cellSync->Log("cellSyncMutexInitialize(mutex_addr=0x%x)", mutex.addr()); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index 5e282cec50..dbcdc00586 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -155,7 +155,7 @@ struct CellSyncLFQueue static_assert(sizeof(CellSyncLFQueue) == 128, "CellSyncLFQueue: wrong size"); -s32 syncMutexInitialize(vm::ptr mutex); +s32 syncMutexInitialize(vm::ptr> mutex); s32 syncBarrierInitialize(vm::ptr barrier, u16 total_count); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp index f819a76818..1f71d0fb30 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp @@ -13,7 +13,7 @@ s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64) { u32 id = sys_lwcond.GetNewId(new Lwcond(name_u64), TYPE_LWCOND); u32 addr = Memory.RealToVirtualAddr(&lwmutex); - lwcond.lwmutex.set(be_t::MakeFromLE(addr)); + lwcond.lwmutex.set(be_t::make(addr)); lwcond.lwcond_queue = id; std::string name((const char*)&name_u64, 8); @@ -154,7 +154,7 @@ s32 sys_lwcond_wait(vm::ptr lwcond, u64 timeout) auto mutex = vm::ptr::make(lwcond->lwmutex.addr()); u32 tid_le = GetCurrentPPUThread().GetId(); - be_t tid = be_t::MakeFromLE(tid_le); + be_t tid = be_t::make(tid_le); SleepQueue* sq = nullptr; Emu.GetIdManager().GetIDData((u32)mutex->sleep_queue, sq); @@ -176,7 +176,7 @@ s32 sys_lwcond_wait(vm::ptr lwcond, u64 timeout) if (sq) { - mutex->mutex.unlock(tid, be_t::MakeFromLE(mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())); + mutex->mutex.unlock(tid, be_t::make(mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())); } else if (mutex->attribute.ToBE() == se32(SYS_SYNC_RETRY)) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp index 4a0702623f..d4fb074429 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp @@ -79,14 +79,14 @@ s32 sys_lwmutex_lock(vm::ptr lwmutex, u64 timeout) //ConLog.Write("*** lock mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)", //lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter); - return lwmutex->lock(be_t::MakeFromLE(GetCurrentPPUThread().GetId()), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0); + return lwmutex->lock(be_t::make(GetCurrentPPUThread().GetId()), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0); } s32 sys_lwmutex_trylock(vm::ptr lwmutex) { sys_lwmutex.Log("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.addr()); - return lwmutex->trylock(be_t::MakeFromLE(GetCurrentPPUThread().GetId())); + return lwmutex->trylock(be_t::make(GetCurrentPPUThread().GetId())); } s32 sys_lwmutex_unlock(vm::ptr lwmutex) @@ -96,7 +96,7 @@ s32 sys_lwmutex_unlock(vm::ptr lwmutex) //ConLog.Write("*** unlocking mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)", //lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, (u32)lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter); - return lwmutex->unlock(be_t::MakeFromLE(GetCurrentPPUThread().GetId())); + return lwmutex->unlock(be_t::make(GetCurrentPPUThread().GetId())); } void SleepQueue::push(u32 tid) @@ -292,7 +292,7 @@ int sys_lwmutex_t::unlock(be_t tid) recursive_count -= 1; if (!recursive_count.ToBE()) { - be_t target = be_t::MakeFromBE(se32(0)); + be_t target = be_t::make(0); switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) { case se32(SYS_SYNC_FIFO): diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index 385115d47f..3e504cffc9 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -214,8 +214,8 @@ void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm: { sys_ppu_thread.Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, init_addr=0x%x)", once_ctrl.addr(), init.addr()); - auto cmp = to_be(SYS_PPU_THREAD_ONCE_INIT); - if (once_ctrl->compare_and_swap(cmp, to_be(SYS_PPU_THREAD_DONE_INIT)) == cmp) + be_t cmp = be_t::make(SYS_PPU_THREAD_ONCE_INIT); + if (once_ctrl->compare_and_swap(cmp, be_t::make(SYS_PPU_THREAD_DONE_INIT)) == cmp) { init.call(CPU); } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp index 5c6c3d9f27..0598dcc654 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp @@ -7,22 +7,22 @@ SysCallBase sys_spinlock("sys_spinlock"); -void sys_spinlock_initialize(vm::ptr>> lock) +void sys_spinlock_initialize(vm::ptr> lock) { sys_spinlock.Log("sys_spinlock_initialize(lock_addr=0x%x)", lock.addr()); // prx: set 0 and sync - *lock = be_t::MakeFromBE(0); + lock->exchange(be_t::make(0)); } -void sys_spinlock_lock(vm::ptr>> lock) +void sys_spinlock_lock(vm::ptr> lock) { sys_spinlock.Log("sys_spinlock_lock(lock_addr=0x%x)", lock.addr()); // prx: exchange with 0xabadcafe, repeat until exchanged with 0 - while (lock->exchange(be_t::MakeFromBE(se32(0xabadcafe))).ToBE()) + while (lock->exchange(be_t::make(0xabadcafe)).ToBE()) { - while (lock->load(std::memory_order_relaxed).ToBE()) + while (lock->read_relaxed().ToBE()) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack if (Emu.IsStopped()) @@ -39,12 +39,12 @@ void sys_spinlock_lock(vm::ptr>> lock) } } -s32 sys_spinlock_trylock(vm::ptr>> lock) +s32 sys_spinlock_trylock(vm::ptr> lock) { sys_spinlock.Log("sys_spinlock_trylock(lock_addr=0x%x)", lock.addr()); // prx: exchange with 0xabadcafe, translate exchanged value - if (lock->exchange(be_t::MakeFromBE(se32(0xabadcafe))).ToBE()) + if (lock->exchange(be_t::make(0xabadcafe)).ToBE()) { return CELL_EBUSY; } @@ -52,10 +52,10 @@ s32 sys_spinlock_trylock(vm::ptr>> lock) return CELL_OK; } -void sys_spinlock_unlock(vm::ptr>> lock) +void sys_spinlock_unlock(vm::ptr> lock) { sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.addr()); // prx: sync and set 0 - *lock = be_t::MakeFromBE(0); + lock->exchange(be_t::make(0)); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h index 9bab9011a1..5102d7d588 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h @@ -1,7 +1,7 @@ #pragma once // SysCalls -void sys_spinlock_initialize(vm::ptr>> lock); -void sys_spinlock_lock(vm::ptr>> lock); -s32 sys_spinlock_trylock(vm::ptr>> lock); -void sys_spinlock_unlock(vm::ptr>> lock); +void sys_spinlock_initialize(vm::ptr> lock); +void sys_spinlock_lock(vm::ptr> lock); +s32 sys_spinlock_trylock(vm::ptr> lock); +void sys_spinlock_unlock(vm::ptr> lock); diff --git a/rpcs3/Loader/TROPUSR.cpp b/rpcs3/Loader/TROPUSR.cpp index e6a15fb59f..6569ae3fd3 100644 --- a/rpcs3/Loader/TROPUSR.cpp +++ b/rpcs3/Loader/TROPUSR.cpp @@ -144,11 +144,20 @@ bool TROPUSRLoader::Generate(const std::string& filepath, const std::string& con default: trophy_grade = 0; } - TROPUSREntry4 entry4 = { be_t::MakeFromBE(se32(4)), be_t::MakeFromBE(se32(sizeof(TROPUSREntry4) - 0x10)), - be_t::MakeFromLE((u32)m_table4.size()), be_t::MakeFromBE(se32(0)), be_t::MakeFromLE(trophy_id), - be_t::MakeFromLE(trophy_grade), be_t::MakeFromBE(se32(0xFFFFFFFF)) }; - TROPUSREntry6 entry6 = { be_t::MakeFromBE(se32(6)), be_t::MakeFromBE(se32(sizeof(TROPUSREntry6) - 0x10)), - be_t::MakeFromLE((u32)m_table6.size()), be_t::MakeFromBE(0), be_t::MakeFromLE(trophy_id) }; + TROPUSREntry4 entry4 = { + be_t::make(4), + be_t::make(sizeof(TROPUSREntry4) - 0x10), + be_t::make((u32)m_table4.size()), + be_t::make(0), + be_t::make(trophy_id), + be_t::make(trophy_grade), + be_t::make(0xFFFFFFFF) }; + TROPUSREntry6 entry6 = { + be_t::make(6), + be_t::make(sizeof(TROPUSREntry6) - 0x10), + be_t::make((u32)m_table6.size()), + be_t::make(0), + be_t::make(trophy_id) }; m_table4.push_back(entry4); m_table6.push_back(entry6); @@ -156,11 +165,19 @@ bool TROPUSRLoader::Generate(const std::string& filepath, const std::string& con } u64 offset = sizeof(TROPUSRHeader) + 2 * sizeof(TROPUSRTableHeader); - TROPUSRTableHeader table4header = { be_t::MakeFromBE(se32(4)), be_t::MakeFromBE(se32(sizeof(TROPUSREntry4)-0x10)), - be_t::MakeFromBE(se32(1)), be_t::MakeFromLE((u32)m_table4.size()), be_t::MakeFromLE(offset) }; + TROPUSRTableHeader table4header = { + be_t::make(4), + be_t::make(sizeof(TROPUSREntry4) - 0x10), + be_t::make(1), + be_t::make((u32)m_table4.size()), + be_t::make(offset) }; offset += m_table4.size() * sizeof(TROPUSREntry4); - TROPUSRTableHeader table6header = { be_t::MakeFromBE(se32(6)), be_t::MakeFromBE(se32(sizeof(TROPUSREntry6)-0x10)), - be_t::MakeFromBE(se32(1)), be_t::MakeFromLE((u32)m_table6.size()), be_t::MakeFromLE(offset) }; + TROPUSRTableHeader table6header = { + be_t::make(6), + be_t::make(sizeof(TROPUSREntry6) - 0x10), + be_t::make(1), + be_t::make((u32)m_table6.size()), + be_t::make(offset) }; offset += m_table6.size() * sizeof(TROPUSREntry6); m_tableHeaders.clear(); From 89da242cd2cfd411010bb63e78ba9de21412b81f Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 20 Sep 2014 04:08:12 +0400 Subject: [PATCH 07/24] Warning fix --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 2 +- rpcs3/Emu/SysCalls/SyncPrimitivesManager.h | 7 ++++++- rpcs3/Emu/SysCalls/lv2/sys_cond.cpp | 4 ++++ rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp | 4 ++++ rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp | 2 ++ rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp | 4 ++++ rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp | 2 ++ 7 files changed, 23 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index c43826648a..c8505e036b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -219,7 +219,7 @@ s64 spursInit( // some unknown subroutine spurs->m.sub3.unk1 = spurs.addr() + 0xc9; spurs->m.sub3.unk2 = 3; // unknown const - spurs->m.sub3.port = (u64)spurs->m.port; + spurs->m.sub3.port = spurs->m.port; if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) // initialize system workload { diff --git a/rpcs3/Emu/SysCalls/SyncPrimitivesManager.h b/rpcs3/Emu/SysCalls/SyncPrimitivesManager.h index 07293bbd96..97110e2a50 100644 --- a/rpcs3/Emu/SysCalls/SyncPrimitivesManager.h +++ b/rpcs3/Emu/SysCalls/SyncPrimitivesManager.h @@ -78,6 +78,7 @@ public: case TYPE_MUTEX: m_mutex_name[id] = name; break; case TYPE_COND: m_cond_name[id] = name; break; + default: LOG_ERROR(GENERAL, "Unknown IDType = %d", type); } } @@ -93,13 +94,17 @@ public: } } - std::string& GetSyncPrimName(const IDType type, const u32 id) + const std::string& GetSyncPrimName(const IDType type, const u32 id) { + static const std::string empty = ""; + switch (type) { case TYPE_LWCOND: return m_lw_cond_name[id]; case TYPE_MUTEX: return m_mutex_name[id]; case TYPE_COND: return m_cond_name[id]; + + default: LOG_ERROR(GENERAL, "Unknown IDType = %d", type); return empty; } } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp index 7f21a920e7..a51b9f977a 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp @@ -14,6 +14,8 @@ s32 sys_cond_create(vm::ptr> cond_id, u32 mutex_id, vm::ptrpshared.ToBE() != se32(0x200)) { sys_cond.Error("Invalid pshared attribute(0x%x)", (u32)attr->pshared); @@ -45,6 +47,8 @@ s32 sys_cond_destroy(u32 cond_id) { sys_cond.Warning("sys_cond_destroy(cond_id=%d)", cond_id); + LV2_LOCK(0); + Cond* cond; if (!Emu.GetIdManager().GetIDData(cond_id, cond)) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp index 1f71d0fb30..9c709ba37f 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp @@ -11,6 +11,8 @@ SysCallBase sys_lwcond("sys_lwcond"); s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64) { + LV2_LOCK(0); + u32 id = sys_lwcond.GetNewId(new Lwcond(name_u64), TYPE_LWCOND); u32 addr = Memory.RealToVirtualAddr(&lwmutex); lwcond.lwmutex.set(be_t::make(addr)); @@ -38,6 +40,8 @@ s32 sys_lwcond_destroy(vm::ptr lwcond) { sys_lwcond.Warning("sys_lwcond_destroy(lwcond_addr=0x%x)", lwcond.addr()); + LV2_LOCK(0); + u32 id = lwcond->lwcond_queue; Lwcond* lw; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp index d4fb074429..9e3c9f9483 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp @@ -56,6 +56,8 @@ s32 sys_lwmutex_destroy(vm::ptr lwmutex) { sys_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.addr()); + LV2_LOCK(0); + u32 sq_id = lwmutex->sleep_queue; if (!Emu.GetIdManager().CheckID(sq_id)) return CELL_ESRCH; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp index 63d4263552..75a23f43cc 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp @@ -30,6 +30,8 @@ s32 sys_mutex_create(vm::ptr> mutex_id, vm::ptr a { sys_mutex.Log("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)", mutex_id.addr(), attr.addr()); + LV2_LOCK(0); + switch (attr->protocol.ToBE()) { case se32(SYS_SYNC_FIFO): break; @@ -73,6 +75,8 @@ s32 sys_mutex_destroy(u32 mutex_id) { sys_mutex.Warning("sys_mutex_destroy(mutex_id=%d)", mutex_id); + LV2_LOCK(0); + Mutex* mutex; if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp index 6b2c7d594a..7d26df4c05 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp @@ -55,6 +55,8 @@ s32 sys_semaphore_destroy(u32 sem_id) { sys_semaphore.Warning("sys_semaphore_destroy(sem_id=%d)", sem_id); + LV2_LOCK(0); + Semaphore* sem; if (!Emu.GetIdManager().GetIDData(sem_id, sem)) { From 169c8c47c09812b3acd8b10914ab8ae0c35263a9 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 21 Sep 2014 01:00:55 +0400 Subject: [PATCH 08/24] vm::atomic update --- rpcs3/Emu/Memory/vm_atomic.h | 51 ++++++++- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 125 +++++++++-------------- rpcs3/Emu/SysCalls/Modules/cellSync.h | 20 ++-- 4 files changed, 109 insertions(+), 91 deletions(-) diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h index 9019f0407f..dba8a6af84 100644 --- a/rpcs3/Emu/Memory/vm_atomic.h +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -29,23 +29,70 @@ namespace vm typedef typename _to_atomic::type atomic_type; public: + // atomically compare data with cmp, replace with exch if equal, return previous data value anyway __forceinline const T compare_and_swap(const T cmp, const T exch) volatile { const atomic_type res = InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp); return (T&)res; } - __forceinline const T exchange(const T value) volatile + // atomically compare data with cmp, replace with exch if equal, return true if data was replaced + __forceinline bool compare_and_swap_test(const T cmp, const T exch) volatile { - const atomic_type res = InterlockedExchange((volatile atomic_type*)&data, (atomic_type&)value); + return InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp) == (atomic_type&)cmp; + } + + // read data with memory barrier + __forceinline const T read_sync() const volatile + { + const atomic_type res = InterlockedCompareExchange((volatile atomic_type*)&data, 0, 0); return (T&)res; } + // atomically replace data with exch, return previous data value + __forceinline const T exchange(const T exch) volatile + { + const atomic_type res = InterlockedExchange((volatile atomic_type*)&data, (atomic_type&)exch); + return (T&)res; + } + + // read data without memory barrier __forceinline const T read_relaxed() const volatile { return (T&)data; } + // write data without memory barrier + __forceinline void write_relaxed(const T value) volatile + { + (T&)data = value; + } + + // perform atomic operation on data + template __forceinline void atomic_op(const FT atomic_proc) volatile + { + while (true) + { + const T old = read_relaxed(); + T _new = old; + atomic_proc(_new); // function should accept reference to T type + if (compare_and_swap_test(old, _new)) return; + } + } + + // perform atomic operation on data with special exit condition (if intermediate result != proceed_value) + template __forceinline RT atomic_op(const RT proceed_value, const FT atomic_proc) volatile + { + while (true) + { + const T old = read_relaxed(); + T _new = old; + RT res = (RT)atomic_proc(_new); // function should accept reference to T type and return some value + if (res != proceed_value) return res; + if (compare_and_swap_test(old, _new)) return proceed_value; + } + } + }; template struct atomic_le : public _atomic_base diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index c8505e036b..26dd568e54 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -219,7 +219,7 @@ s64 spursInit( // some unknown subroutine spurs->m.sub3.unk1 = spurs.addr() + 0xc9; spurs->m.sub3.unk2 = 3; // unknown const - spurs->m.sub3.port = spurs->m.port; + spurs->m.sub3.port = (u64)spurs->m.port; if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) // initialize system workload { @@ -247,7 +247,7 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 cellSpurs->Warning("cellSpursInitialize(spurs_addr=0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)", spurs.addr(), nSpus, spuPriority, ppuPriority, exitIfNoWork ? 1 : 0); -#ifdef PRX_DEBUG_XXX +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x8480, libsre_rtoc); #else return spursInit( diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 112ea57f5e..a832c15dfa 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -16,7 +16,7 @@ u32 libsre; u32 libsre_rtoc; #endif -s32 syncMutexInitialize(vm::ptr> mutex) +s32 syncMutexInitialize(vm::ptr mutex) { if (!mutex) { @@ -28,11 +28,11 @@ s32 syncMutexInitialize(vm::ptr> mutex) } // prx: set zero and sync - mutex->exchange({}); + mutex->data.exchange({}); return CELL_OK; } -s32 cellSyncMutexInitialize(vm::ptr> mutex) +s32 cellSyncMutexInitialize(vm::ptr mutex) { cellSync->Log("cellSyncMutexInitialize(mutex_addr=0x%x)", mutex.addr()); @@ -52,21 +52,15 @@ s32 cellSyncMutexLock(vm::ptr mutex) return CELL_SYNC_ERROR_ALIGN; } - // prx: increase u16 and remember its old value - be_t old_order; - while (true) + // prx: increase m_acq and remember its old value + be_t order; + mutex->data.atomic_op([&order](CellSyncMutex::data_t& _mutex) { - const u32 old_data = mutex->m_data(); - CellSyncMutex new_mutex; - new_mutex.m_data() = old_data; + order = _mutex.m_acq++; + }); - old_order = new_mutex.m_order; - new_mutex.m_order++; // increase m_order - if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break; - } - - // prx: wait until another u16 value == old value - while (old_order != mutex->m_freed) + // prx: wait until this old value is equal to m_rel + while (order != mutex->data.read_relaxed().m_rel) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack if (Emu.IsStopped()) @@ -77,7 +71,7 @@ s32 cellSyncMutexLock(vm::ptr mutex) } // prx: sync - InterlockedCompareExchange(&mutex->m_data(), 0, 0); + mutex->data.read_sync(); return CELL_OK; } @@ -94,25 +88,15 @@ s32 cellSyncMutexTryLock(vm::ptr mutex) return CELL_SYNC_ERROR_ALIGN; } - while (true) + // prx: exit if m_acq and m_rel are not equal, increase m_acq + return mutex->data.atomic_op(CELL_OK, [](CellSyncMutex::data_t& _mutex) -> s32 { - const u32 old_data = mutex->m_data(); - CellSyncMutex new_mutex; - new_mutex.m_data() = old_data; - - // prx: compare two u16 values and exit if not equal - if (new_mutex.m_order != new_mutex.m_freed) + if (_mutex.m_acq++ != _mutex.m_rel) { return CELL_SYNC_ERROR_BUSY; } - else - { - new_mutex.m_order++; - } - if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break; - } - - return CELL_OK; + return CELL_OK; + }); } s32 cellSyncMutexUnlock(vm::ptr mutex) @@ -128,18 +112,11 @@ s32 cellSyncMutexUnlock(vm::ptr mutex) return CELL_SYNC_ERROR_ALIGN; } - InterlockedCompareExchange(&mutex->m_data(), 0, 0); - - while (true) + mutex->data.read_sync(); + mutex->data.atomic_op([](CellSyncMutex::data_t& _mutex) { - const u32 old_data = mutex->m_data(); - CellSyncMutex new_mutex; - new_mutex.m_data() = old_data; - - new_mutex.m_freed++; - if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break; - } - + _mutex.m_rel++; + }); return CELL_OK; } @@ -159,9 +136,7 @@ s32 syncBarrierInitialize(vm::ptr barrier, u16 total_count) } // prx: zeroize first u16, write total_count in second u16 and sync - barrier->m_value = 0; - barrier->m_count = total_count; - InterlockedCompareExchange(&barrier->m_data(), 0, 0); + barrier->data.exchange({ be_t::make(0), be_t::make(total_count) }); return CELL_OK; } @@ -186,15 +161,14 @@ s32 cellSyncBarrierNotify(vm::ptr barrier) } // prx: sync, extract m_value, repeat if < 0, increase, compare with second s16, set sign bit if equal, insert it back - InterlockedCompareExchange(&barrier->m_data(), 0, 0); + barrier->data.read_sync(); while (true) { - const u32 old_data = barrier->m_data(); - CellSyncBarrier new_barrier; - new_barrier.m_data() = old_data; + const auto old = barrier->data.read_relaxed(); + auto _barrier = old; - s16 value = (s16)new_barrier.m_value; + s16 value = (s16)_barrier.m_value; if (value < 0) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack @@ -207,12 +181,12 @@ s32 cellSyncBarrierNotify(vm::ptr barrier) } value++; - if (value == (s16)new_barrier.m_count) + if (value == (s16)_barrier.m_count) { value |= 0x8000; } - new_barrier.m_value = value; - if (InterlockedCompareExchange(&barrier->m_data(), new_barrier.m_data(), old_data) == old_data) break; + _barrier.m_value = value; + if (barrier->data.compare_and_swap_test(old, _barrier)) break; } return CELL_OK; @@ -231,28 +205,27 @@ s32 cellSyncBarrierTryNotify(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - InterlockedCompareExchange(&barrier->m_data(), 0, 0); + barrier->data.read_sync(); while (true) { - const u32 old_data = barrier->m_data(); - CellSyncBarrier new_barrier; - new_barrier.m_data() = old_data; + const auto old = barrier->data.read_relaxed(); + auto _barrier = old; - s16 value = (s16)new_barrier.m_value; + s16 value = (s16)_barrier.m_value; if (value >= 0) { value++; - if (value == (s16)new_barrier.m_count) + if (value == (s16)_barrier.m_count) { value |= 0x8000; } - new_barrier.m_value = value; - if (InterlockedCompareExchange(&barrier->m_data(), new_barrier.m_data(), old_data) == old_data) break; + _barrier.m_value = value; + if (barrier->data.compare_and_swap_test(old, _barrier)) break; } else { - if (InterlockedCompareExchange(&barrier->m_data(), new_barrier.m_data(), old_data) == old_data) return CELL_SYNC_ERROR_BUSY; + if (barrier->data.compare_and_swap_test(old, _barrier)) return CELL_SYNC_ERROR_BUSY; } } @@ -273,15 +246,14 @@ s32 cellSyncBarrierWait(vm::ptr barrier) } // prx: sync, extract m_value (repeat if >= 0), decrease it, set 0 if == 0x8000, insert it back - InterlockedCompareExchange(&barrier->m_data(), 0, 0); + barrier->data.read_sync(); while (true) { - const u32 old_data = barrier->m_data(); - CellSyncBarrier new_barrier; - new_barrier.m_data() = old_data; + const auto old = barrier->data.read_relaxed(); + auto _barrier = old; - s16 value = (s16)new_barrier.m_value; + s16 value = (s16)_barrier.m_value; if (value >= 0) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack @@ -298,8 +270,8 @@ s32 cellSyncBarrierWait(vm::ptr barrier) { value = 0; } - new_barrier.m_value = value; - if (InterlockedCompareExchange(&barrier->m_data(), new_barrier.m_data(), old_data) == old_data) break; + _barrier.m_value = value; + if (barrier->data.compare_and_swap_test(old, _barrier)) break; } return CELL_OK; @@ -318,15 +290,14 @@ s32 cellSyncBarrierTryWait(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - InterlockedCompareExchange(&barrier->m_data(), 0, 0); + barrier->data.read_sync(); while (true) { - const u32 old_data = barrier->m_data(); - CellSyncBarrier new_barrier; - new_barrier.m_data() = old_data; + const auto old = barrier->data.read_relaxed(); + auto _barrier = old; - s16 value = (s16)new_barrier.m_value; + s16 value = (s16)_barrier.m_value; if (value >= 0) { return CELL_SYNC_ERROR_BUSY; @@ -337,8 +308,8 @@ s32 cellSyncBarrierTryWait(vm::ptr barrier) { value = 0; } - new_barrier.m_value = value; - if (InterlockedCompareExchange(&barrier->m_data(), new_barrier.m_data(), old_data) == old_data) break; + _barrier.m_value = value; + if (barrier->data.compare_and_swap_test(old, _barrier)) break; } return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index dbcdc00586..6d2306469a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -31,26 +31,26 @@ enum struct CellSyncMutex { - be_t m_freed; - be_t m_order; - - volatile u32& m_data() + struct data_t { - return *reinterpret_cast(this); + be_t m_rel; // release order (increased when mutex is unlocked) + be_t m_acq; // acquire order (increased when mutex is locked) }; + + vm::atomic data; }; static_assert(sizeof(CellSyncMutex) == 4, "CellSyncMutex: wrong size"); struct CellSyncBarrier { - be_t m_value; - be_t m_count; - - volatile u32& m_data() + struct data_t { - return *reinterpret_cast(this); + be_t m_value; + be_t m_count; }; + + vm::atomic data; }; static_assert(sizeof(CellSyncBarrier) == 4, "CellSyncBarrier: wrong size"); From 3ab08e0d7aa745e31fa3dc07f0fc2c7698c31d19 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 21 Sep 2014 03:29:42 +0400 Subject: [PATCH 09/24] vm::atomic update (or, and, xor) CellSyncMutex, CellSyncBarrier, CellSyncRwm refactoring --- Utilities/GNU.h | 58 ++++- rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/Emu/Memory/vm_atomic.h | 36 +++ rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 283 +++++++++--------------- rpcs3/Emu/SysCalls/Modules/cellSync.h | 21 +- 5 files changed, 200 insertions(+), 200 deletions(-) diff --git a/Utilities/GNU.h b/Utilities/GNU.h index d4eb6cb103..3cf5d606c5 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -46,18 +46,21 @@ void strcpy_trunc(char(&dst)[size], const char(&src)[rsize]) #define _CRT_ALIGN(x) __attribute__((aligned(x))) #define InterlockedCompareExchange(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val) #define InterlockedExchange(ptr, value) __sync_lock_test_and_set(ptr, value) +#define InterlockedOr(ptr, value) __sync_fetch_and_or(ptr, value) +#define InterlockedAnd(ptr, value) __sync_fetch_and_and(ptr, value) +#define InterlockedXor(ptr, value) __sync_fetch_and_xor(ptr, value) -inline int64_t InterlockedOr64(volatile int64_t *dest, int64_t val) -{ - int64_t olderval; - int64_t oldval = *dest; - do - { - olderval = oldval; - oldval = __sync_val_compare_and_swap(dest, olderval | val, olderval); - } while (olderval != oldval); - return oldval; -} +//inline int64_t InterlockedOr64(volatile int64_t *dest, int64_t val) +//{ +// int64_t olderval; +// int64_t oldval = *dest; +// do +// { +// olderval = oldval; +// oldval = __sync_val_compare_and_swap(dest, olderval | val, olderval); +// } while (olderval != oldval); +// return oldval; +//} inline uint64_t __umulh(uint64_t a, uint64_t b) { @@ -112,3 +115,36 @@ static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint6 return _InterlockedExchange64((volatile long long*)dest, value); } #endif + +#ifndef InterlockedOr +static __forceinline uint32_t InterlockedOr(volatile uint32_t* dest, uint32_t value) +{ + return _InterlockedOr((volatile long*)dest, value); +} +static __forceinline uint64_t InterlockedOr(volatile uint64_t* dest, uint64_t value) +{ + return _InterlockedOr64((volatile long long*)dest, value); +} +#endif + +#ifndef InterlockedAnd +static __forceinline uint32_t InterlockedAnd(volatile uint32_t* dest, uint32_t value) +{ + return _InterlockedAnd((volatile long*)dest, value); +} +static __forceinline uint64_t InterlockedAnd(volatile uint64_t* dest, uint64_t value) +{ + return _InterlockedAnd64((volatile long long*)dest, value); +} +#endif + +#ifndef InterlockedXor +static __forceinline uint32_t InterlockedXor(volatile uint32_t* dest, uint32_t value) +{ + return _InterlockedXor((volatile long*)dest, value); +} +static __forceinline uint64_t InterlockedXor(volatile uint64_t* dest, uint64_t value) +{ + return _InterlockedXor64((volatile long long*)dest, value); +} +#endif diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 0e6070d0bf..e33291cf8c 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -358,7 +358,7 @@ public: } else { - InterlockedOr64((volatile s64*)m_indval, ((u64)value << 32) | 1); + InterlockedOr((volatile u64*)m_indval, ((u64)value << 32) | 1); } } diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h index dba8a6af84..1b74b898fb 100644 --- a/rpcs3/Emu/Memory/vm_atomic.h +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -93,6 +93,42 @@ namespace vm } } + __forceinline const T _or(const T right) volatile + { + const atomic_type res = InterlockedOr((volatile atomic_type*)&data, (atomic_type&)right); + return (T&)res; + } + + __forceinline const T _and(const T right) volatile + { + const atomic_type res = InterlockedAnd((volatile atomic_type*)&data, (atomic_type&)right); + return (T&)res; + } + + __forceinline const T _xor(const T right) volatile + { + const atomic_type res = InterlockedXor((volatile atomic_type*)&data, (atomic_type&)right); + return (T&)res; + } + + __forceinline const T operator |= (const T right) volatile + { + const atomic_type res = InterlockedOr((volatile atomic_type*)&data, (atomic_type&)right) | (atomic_type&)right; + return (T&)res; + } + + __forceinline const T operator &= (const T right) volatile + { + const atomic_type res = InterlockedAnd((volatile atomic_type*)&data, (atomic_type&)right) & (atomic_type&)right; + return (T&)res; + } + + __forceinline const T operator ^= (const T right) volatile + { + const atomic_type res = InterlockedXor((volatile atomic_type*)&data, (atomic_type&)right) ^ (atomic_type&)right; + return (T&)res; + } + }; template struct atomic_le : public _atomic_base diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index a832c15dfa..47893dea43 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -54,9 +54,9 @@ s32 cellSyncMutexLock(vm::ptr mutex) // prx: increase m_acq and remember its old value be_t order; - mutex->data.atomic_op([&order](CellSyncMutex::data_t& _mutex) + mutex->data.atomic_op([&order](CellSyncMutex::data_t& mutex) { - order = _mutex.m_acq++; + order = mutex.m_acq++; }); // prx: wait until this old value is equal to m_rel @@ -89,9 +89,9 @@ s32 cellSyncMutexTryLock(vm::ptr mutex) } // prx: exit if m_acq and m_rel are not equal, increase m_acq - return mutex->data.atomic_op(CELL_OK, [](CellSyncMutex::data_t& _mutex) -> s32 + return mutex->data.atomic_op(CELL_OK, [](CellSyncMutex::data_t& mutex) -> s32 { - if (_mutex.m_acq++ != _mutex.m_rel) + if (mutex.m_acq++ != mutex.m_rel) { return CELL_SYNC_ERROR_BUSY; } @@ -113,9 +113,9 @@ s32 cellSyncMutexUnlock(vm::ptr mutex) } mutex->data.read_sync(); - mutex->data.atomic_op([](CellSyncMutex::data_t& _mutex) + mutex->data.atomic_op([](CellSyncMutex::data_t& mutex) { - _mutex.m_rel++; + mutex.m_rel++; }); return CELL_OK; } @@ -147,6 +147,24 @@ s32 cellSyncBarrierInitialize(vm::ptr barrier, u16 total_count) return syncBarrierInitialize(barrier, total_count); } +s32 syncBarrierTryNotifyOp(CellSyncBarrier::data_t& barrier) +{ + // prx: extract m_value (repeat if < 0), increase, compare with second s16, set sign bit if equal, insert it back + s16 value = (s16)barrier.m_value; + if (value < 0) + { + return CELL_SYNC_ERROR_BUSY; + } + + value++; + if (value == (s16)barrier.m_count) + { + value |= 0x8000; + } + barrier.m_value = value; + return CELL_OK; +}; + s32 cellSyncBarrierNotify(vm::ptr barrier) { cellSync->Log("cellSyncBarrierNotify(barrier_addr=0x%x)", barrier.addr()); @@ -160,35 +178,16 @@ s32 cellSyncBarrierNotify(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - // prx: sync, extract m_value, repeat if < 0, increase, compare with second s16, set sign bit if equal, insert it back barrier->data.read_sync(); - - while (true) + while (barrier->data.atomic_op(CELL_OK, syncBarrierTryNotifyOp)) { - const auto old = barrier->data.read_relaxed(); - auto _barrier = old; - - s16 value = (s16)_barrier.m_value; - if (value < 0) + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + if (Emu.IsStopped()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncBarrierNotify(barrier_addr=0x%x) aborted", barrier.addr()); - return CELL_OK; - } - continue; + cellSync->Warning("cellSyncBarrierNotify(barrier_addr=0x%x) aborted", barrier.addr()); + return CELL_OK; } - - value++; - if (value == (s16)_barrier.m_count) - { - value |= 0x8000; - } - _barrier.m_value = value; - if (barrier->data.compare_and_swap_test(old, _barrier)) break; } - return CELL_OK; } @@ -206,29 +205,24 @@ s32 cellSyncBarrierTryNotify(vm::ptr barrier) } barrier->data.read_sync(); + return barrier->data.atomic_op(CELL_OK, syncBarrierTryNotifyOp); +} - while (true) +s32 syncBarrierTryWaitOp(CellSyncBarrier::data_t& barrier) +{ + // prx: extract m_value (repeat if >= 0), decrease it, set 0 if == 0x8000, insert it back + s16 value = (s16)barrier.m_value; + if (value >= 0) { - const auto old = barrier->data.read_relaxed(); - auto _barrier = old; - - s16 value = (s16)_barrier.m_value; - if (value >= 0) - { - value++; - if (value == (s16)_barrier.m_count) - { - value |= 0x8000; - } - _barrier.m_value = value; - if (barrier->data.compare_and_swap_test(old, _barrier)) break; - } - else - { - if (barrier->data.compare_and_swap_test(old, _barrier)) return CELL_SYNC_ERROR_BUSY; - } + return CELL_SYNC_ERROR_BUSY; } + value--; + if (value == (s16)0x8000) + { + value = 0; + } + barrier.m_value = value; return CELL_OK; } @@ -245,35 +239,16 @@ s32 cellSyncBarrierWait(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - // prx: sync, extract m_value (repeat if >= 0), decrease it, set 0 if == 0x8000, insert it back barrier->data.read_sync(); - - while (true) + while (barrier->data.atomic_op(CELL_OK, syncBarrierTryWaitOp)) { - const auto old = barrier->data.read_relaxed(); - auto _barrier = old; - - s16 value = (s16)_barrier.m_value; - if (value >= 0) + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + if (Emu.IsStopped()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncBarrierWait(barrier_addr=0x%x) aborted", barrier.addr()); - return CELL_OK; - } - continue; + cellSync->Warning("cellSyncBarrierWait(barrier_addr=0x%x) aborted", barrier.addr()); + return CELL_OK; } - - value--; - if (value == (s16)0x8000) - { - value = 0; - } - _barrier.m_value = value; - if (barrier->data.compare_and_swap_test(old, _barrier)) break; } - return CELL_OK; } @@ -291,28 +266,7 @@ s32 cellSyncBarrierTryWait(vm::ptr barrier) } barrier->data.read_sync(); - - while (true) - { - const auto old = barrier->data.read_relaxed(); - auto _barrier = old; - - s16 value = (s16)_barrier.m_value; - if (value >= 0) - { - return CELL_SYNC_ERROR_BUSY; - } - - value--; - if (value == (s16)0x8000) - { - value = 0; - } - _barrier.m_value = value; - if (barrier->data.compare_and_swap_test(old, _barrier)) break; - } - - return CELL_OK; + return barrier->data.atomic_op(CELL_OK, syncBarrierTryWaitOp); } s32 syncRwmInitialize(vm::ptr rwm, vm::ptr buffer, u32 buffer_size) @@ -331,10 +285,9 @@ s32 syncRwmInitialize(vm::ptr rwm, vm::ptr buffer, u32 buffer } // prx: zeroize first u16 and second u16, write buffer_size in second u32, write buffer_addr in second u64 and sync - rwm->m_data() = 0; rwm->m_size = buffer_size; rwm->m_buffer = buffer; - InterlockedCompareExchange(&rwm->m_data(), 0, 0); + rwm->data.exchange({}); return CELL_OK; } @@ -345,6 +298,27 @@ s32 cellSyncRwmInitialize(vm::ptr rwm, vm::ptr buffer, u32 bu return syncRwmInitialize(rwm, buffer, buffer_size); } +s32 syncRwmTryReadBeginOp(CellSyncRwm::data_t& rwm) +{ + if (rwm.m_writers.ToBE()) + { + return CELL_SYNC_ERROR_BUSY; + } + rwm.m_readers++; + return CELL_OK; +} + +s32 syncRwmReadEndOp(CellSyncRwm::data_t& rwm) +{ + if (!rwm.m_readers.ToBE()) + { + cellSync->Error("syncRwmReadEndOp(rwm_addr=0x%x): m_readers == 0 (m_writers=%d)", Memory.RealToVirtualAddr(&rwm), (u16)rwm.m_writers); + return CELL_SYNC_ERROR_ABORT; + } + rwm.m_readers--; + return CELL_OK; +} + s32 cellSyncRwmRead(vm::ptr rwm, vm::ptr buffer) { cellSync->Log("cellSyncRwmRead(rwm_addr=0x%x, buffer_addr=0x%x)", rwm.addr(), buffer.addr()); @@ -358,48 +332,22 @@ s32 cellSyncRwmRead(vm::ptr rwm, vm::ptr buffer) return CELL_SYNC_ERROR_ALIGN; } - // prx: atomically load first u32, repeat until second u16 == 0, increase first u16 and sync - while (true) + // prx: increase m_readers, wait until m_writers is zero + while (rwm->data.atomic_op(CELL_OK, syncRwmTryReadBeginOp)) { - const u32 old_data = rwm->m_data(); - CellSyncRwm new_rwm; - new_rwm.m_data() = old_data; - - if (new_rwm.m_writers.ToBE()) + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + if (Emu.IsStopped()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncRwmRead(rwm_addr=0x%x) aborted", rwm.addr()); - return CELL_OK; - } - continue; + cellSync->Warning("cellSyncRwmRead(rwm_addr=0x%x) aborted", rwm.addr()); + return CELL_OK; } - - new_rwm.m_readers++; - if (InterlockedCompareExchange(&rwm->m_data(), new_rwm.m_data(), old_data) == old_data) break; } // copy data to buffer_addr memcpy(buffer.get_ptr(), rwm->m_buffer.get_ptr(), (u32)rwm->m_size); - // prx: load first u32, return 0x8041010C if first u16 == 0, atomically decrease it - while (true) - { - const u32 old_data = rwm->m_data(); - CellSyncRwm new_rwm; - new_rwm.m_data() = old_data; - - if (!new_rwm.m_readers.ToBE()) - { - cellSync->Error("cellSyncRwmRead(rwm_addr=0x%x): m_readers == 0 (m_writers=%d)", rwm.addr(), (u16)new_rwm.m_writers); - return CELL_SYNC_ERROR_ABORT; - } - - new_rwm.m_readers--; - if (InterlockedCompareExchange(&rwm->m_data(), new_rwm.m_data(), old_data) == old_data) break; - } - return CELL_OK; + // prx: decrease m_readers (return 0x8041010C if already zero) + return rwm->data.atomic_op(CELL_OK, syncRwmReadEndOp); } s32 cellSyncRwmTryRead(vm::ptr rwm, vm::ptr buffer) @@ -415,38 +363,22 @@ s32 cellSyncRwmTryRead(vm::ptr rwm, vm::ptr buffer) return CELL_SYNC_ERROR_ALIGN; } - while (true) + if (s32 res = rwm->data.atomic_op(CELL_OK, syncRwmTryReadBeginOp)) { - const u32 old_data = rwm->m_data(); - CellSyncRwm new_rwm; - new_rwm.m_data() = old_data; - - if (new_rwm.m_writers.ToBE()) - { - return CELL_SYNC_ERROR_BUSY; - } - - new_rwm.m_readers++; - if (InterlockedCompareExchange(&rwm->m_data(), new_rwm.m_data(), old_data) == old_data) break; + return res; } - memcpy(buffer.get_ptr(), rwm->m_buffer.get_ptr(), (u32)rwm->m_size); - while (true) + return rwm->data.atomic_op(CELL_OK, syncRwmReadEndOp); +} + +s32 syncRwmTryWriteBeginOp(CellSyncRwm::data_t& rwm) +{ + if (rwm.m_writers.ToBE()) { - const u32 old_data = rwm->m_data(); - CellSyncRwm new_rwm; - new_rwm.m_data() = old_data; - - if (!new_rwm.m_readers.ToBE()) - { - cellSync->Error("cellSyncRwmRead(rwm_addr=0x%x): m_readers == 0 (m_writers=%d)", rwm.addr(), (u16)new_rwm.m_writers); - return CELL_SYNC_ERROR_ABORT; - } - - new_rwm.m_readers--; - if (InterlockedCompareExchange(&rwm->m_data(), new_rwm.m_data(), old_data) == old_data) break; + return CELL_SYNC_ERROR_BUSY; } + rwm.m_writers = 1; return CELL_OK; } @@ -463,30 +395,18 @@ s32 cellSyncRwmWrite(vm::ptr rwm, vm::ptr buffer) return CELL_SYNC_ERROR_ALIGN; } - // prx: atomically compare second u16 (m_writers) with 0, repeat if not 0, set 1, sync - while (true) + while (rwm->data.atomic_op(CELL_OK, syncRwmTryWriteBeginOp)) { - const u32 old_data = rwm->m_data(); - CellSyncRwm new_rwm; - new_rwm.m_data() = old_data; - - if (new_rwm.m_writers.ToBE()) + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + if (Emu.IsStopped()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncRwmWrite(rwm_addr=0x%x) aborted (I)", rwm.addr()); - return CELL_OK; - } - continue; + cellSync->Warning("cellSyncRwmWrite(rwm_addr=0x%x) aborted (I)", rwm.addr()); + return CELL_OK; } - - new_rwm.m_writers = 1; - if (InterlockedCompareExchange(&rwm->m_data(), new_rwm.m_data(), old_data) == old_data) break; } // prx: wait until m_readers == 0 - while (rwm->m_readers.ToBE()) + while (rwm->data.read_relaxed().m_readers.ToBE()) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack if (Emu.IsStopped()) @@ -500,8 +420,7 @@ s32 cellSyncRwmWrite(vm::ptr rwm, vm::ptr buffer) memcpy(rwm->m_buffer.get_ptr(), buffer.get_ptr(), (u32)rwm->m_size); // prx: sync and zeroize m_readers and m_writers - InterlockedCompareExchange(&rwm->m_data(), 0, 0); - rwm->m_data() = 0; + rwm->data.exchange({}); return CELL_OK; } @@ -518,15 +437,17 @@ s32 cellSyncRwmTryWrite(vm::ptr rwm, vm::ptr buffer) return CELL_SYNC_ERROR_ALIGN; } - // prx: compare m_readers | m_writers with 0, return busy if not zero, set m_writers to 1 - if (InterlockedCompareExchange(&rwm->m_data(), se32(1), 0) != 0) return CELL_SYNC_ERROR_BUSY; + // prx: compare m_readers | m_writers with 0, return if not zero, set m_writers to 1 + if (!rwm->data.compare_and_swap_test({}, {be_t::make(0), be_t::make(1)})) + { + return CELL_SYNC_ERROR_BUSY; + } // prx: copy data from buffer_addr memcpy(rwm->m_buffer.get_ptr(), buffer.get_ptr(), (u32)rwm->m_size); // prx: sync and zeroize m_readers and m_writers - InterlockedCompareExchange(&rwm->m_data(), 0, 0); - rwm->m_data() = 0; + rwm->data.exchange({}); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index 6d2306469a..15f94e46e0 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -57,23 +57,30 @@ static_assert(sizeof(CellSyncBarrier) == 4, "CellSyncBarrier: wrong size"); struct CellSyncRwm { - be_t m_readers; - be_t m_writers; + struct data_t + { + be_t m_readers; + be_t m_writers; + }; + + vm::atomic data; be_t m_size; vm::bptr m_buffer; - - volatile u32& m_data() - { - return *reinterpret_cast(this); - }; }; static_assert(sizeof(CellSyncRwm) == 16, "CellSyncRwm: wrong size"); struct CellSyncQueue { + struct data_t + { + be_t m_v1; + be_t m_v2; + }; + be_t m_v1; be_t m_v2; + //vm::atomic data; be_t m_size; be_t m_depth; vm::bptr m_buffer; From c9ad88b3ff23c6391decf366f447bf17cb5c2c0a Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 21 Sep 2014 17:02:05 +0400 Subject: [PATCH 10/24] ...+CellSyncQueue --- rpcs3/Emu/Memory/vm_atomic.h | 22 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 363 +++++++++--------------- rpcs3/Emu/SysCalls/Modules/cellSync.h | 60 ++-- 3 files changed, 190 insertions(+), 255 deletions(-) diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h index 1b74b898fb..fc4912a419 100644 --- a/rpcs3/Emu/Memory/vm_atomic.h +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -30,14 +30,14 @@ namespace vm public: // atomically compare data with cmp, replace with exch if equal, return previous data value anyway - __forceinline const T compare_and_swap(const T cmp, const T exch) volatile + __forceinline const T compare_and_swap(const T& cmp, const T& exch) volatile { const atomic_type res = InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp); return (T&)res; } // atomically compare data with cmp, replace with exch if equal, return true if data was replaced - __forceinline bool compare_and_swap_test(const T cmp, const T exch) volatile + __forceinline bool compare_and_swap_test(const T& cmp, const T& exch) volatile { return InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp) == (atomic_type&)cmp; } @@ -50,7 +50,7 @@ namespace vm } // atomically replace data with exch, return previous data value - __forceinline const T exchange(const T exch) volatile + __forceinline const T exchange(const T& exch) volatile { const atomic_type res = InterlockedExchange((volatile atomic_type*)&data, (atomic_type&)exch); return (T&)res; @@ -63,7 +63,7 @@ namespace vm } // write data without memory barrier - __forceinline void write_relaxed(const T value) volatile + __forceinline void write_relaxed(const T& value) volatile { (T&)data = value; } @@ -81,7 +81,7 @@ namespace vm } // perform atomic operation on data with special exit condition (if intermediate result != proceed_value) - template __forceinline RT atomic_op(const RT proceed_value, const FT atomic_proc) volatile + template __forceinline RT atomic_op(const RT& proceed_value, const FT atomic_proc) volatile { while (true) { @@ -93,37 +93,37 @@ namespace vm } } - __forceinline const T _or(const T right) volatile + __forceinline const T _or(const T& right) volatile { const atomic_type res = InterlockedOr((volatile atomic_type*)&data, (atomic_type&)right); return (T&)res; } - __forceinline const T _and(const T right) volatile + __forceinline const T _and(const T& right) volatile { const atomic_type res = InterlockedAnd((volatile atomic_type*)&data, (atomic_type&)right); return (T&)res; } - __forceinline const T _xor(const T right) volatile + __forceinline const T _xor(const T& right) volatile { const atomic_type res = InterlockedXor((volatile atomic_type*)&data, (atomic_type&)right); return (T&)res; } - __forceinline const T operator |= (const T right) volatile + __forceinline const T operator |= (const T& right) volatile { const atomic_type res = InterlockedOr((volatile atomic_type*)&data, (atomic_type&)right) | (atomic_type&)right; return (T&)res; } - __forceinline const T operator &= (const T right) volatile + __forceinline const T operator &= (const T& right) volatile { const atomic_type res = InterlockedAnd((volatile atomic_type*)&data, (atomic_type&)right) & (atomic_type&)right; return (T&)res; } - __forceinline const T operator ^= (const T right) volatile + __forceinline const T operator ^= (const T& right) volatile { const atomic_type res = InterlockedXor((volatile atomic_type*)&data, (atomic_type&)right) ^ (atomic_type&)right; return (T&)res; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 47893dea43..a09d4c6103 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -471,11 +471,10 @@ s32 syncQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 si } // prx: zeroize first u64, write size in third u32, write depth in fourth u32, write address in third u64 and sync - queue->m_data() = 0; queue->m_size = size; queue->m_depth = depth; queue->m_buffer = buffer; - InterlockedCompareExchange(&queue->m_data(), 0, 0); + queue->data.exchange({}); return CELL_OK; } @@ -486,6 +485,26 @@ s32 cellSyncQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 return syncQueueInitialize(queue, buffer, size, depth); } +s32 syncQueueTryPushOp(CellSyncQueue::data_t& queue, u32 depth, u32& position) +{ + const u32 v1 = (u32)queue.m_v1; + const u32 v2 = (u32)queue.m_v2; + // prx: compare 5th u8 with zero (break if not zero) + // prx: compare (second u32 (u24) + first u8) with depth (break if greater or equal) + if ((v2 >> 24) || ((v2 & 0xffffff) + (v1 >> 24)) >= depth) + { + return CELL_SYNC_ERROR_BUSY; + } + + // prx: extract first u32 (u24) (-> position), calculate (position + 1) % depth, insert it back + // prx: insert 1 in 5th u8 + // prx: extract second u32 (u24), increase it, insert it back + position = (v1 & 0xffffff); + queue.m_v1 = (v1 & 0xff000000) | ((position + 1) % depth); + queue.m_v2 = (1 << 24) | ((v2 & 0xffffff) + 1); + return CELL_OK; +} + s32 cellSyncQueuePush(vm::ptr queue, vm::ptr buffer) { cellSync->Log("cellSyncQueuePush(queue_addr=0x%x, buffer_addr=0x%x)", queue.addr(), buffer.addr()); @@ -501,52 +520,27 @@ s32 cellSyncQueuePush(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->m_v1 & 0xffffff) <= depth && ((u32)queue->m_v2 & 0xffffff) <= depth); + assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); u32 position; - while (true) + while (queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - const u32 v1 = (u32)new_queue.m_v1; - const u32 v2 = (u32)new_queue.m_v2; - // prx: compare 5th u8 with zero (repeat if not zero) - // prx: compare (second u32 (u24) + first u8) with depth (repeat if greater or equal) - if ((v2 >> 24) || ((v2 & 0xffffff) + (v1 >> 24)) >= depth) + return syncQueueTryPushOp(queue, depth, position); + })) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + if (Emu.IsStopped()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncQueuePush(queue_addr=0x%x) aborted", queue.addr()); - return CELL_OK; - } - continue; + cellSync->Warning("cellSyncQueuePush(queue_addr=0x%x) aborted", queue.addr()); + return CELL_OK; } - - // prx: extract first u32 (u24) (-> position), calculate (position + 1) % depth, insert it back - // prx: insert 1 in 5th u8 - // prx: extract second u32 (u24), increase it, insert it back - position = (v1 & 0xffffff); - new_queue.m_v1 = (v1 & 0xff000000) | ((position + 1) % depth); - new_queue.m_v2 = (1 << 24) | ((v2 & 0xffffff) + 1); - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; } // prx: memcpy(position * m_size + m_addr, buffer_addr, m_size), sync memcpy(&queue->m_buffer[position * size], buffer.get_ptr(), size); // prx: atomically insert 0 in 5th u8 - while (true) - { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - new_queue.m_v2 &= 0xffffff; // TODO: use InterlockedAnd() or something - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; - } + queue->data &= { be_t::make(~0), be_t::make(0xffffff) }; return CELL_OK; } @@ -565,39 +559,39 @@ s32 cellSyncQueueTryPush(vm::ptr queue, vm::ptr buffe const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->m_v1 & 0xffffff) <= depth && ((u32)queue->m_v2 & 0xffffff) <= depth); + assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); u32 position; - while (true) + if (s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - const u32 v1 = (u32)new_queue.m_v1; - const u32 v2 = (u32)new_queue.m_v2; - if ((v2 >> 24) || ((v2 & 0xffffff) + (v1 >> 24)) >= depth) - { - return CELL_SYNC_ERROR_BUSY; - } - - position = (v1 & 0xffffff); - new_queue.m_v1 = (v1 & 0xff000000) | ((position + 1) % depth); - new_queue.m_v2 = (1 << 24) | ((v2 & 0xffffff) + 1); - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; + return syncQueueTryPushOp(queue, depth, position); + })) + { + return res; } memcpy(&queue->m_buffer[position * size], buffer.get_ptr(), size); + queue->data &= { be_t::make(~0), be_t::make(0xffffff) }; + return CELL_OK; +} - while (true) +s32 syncQueueTryPopOp(CellSyncQueue::data_t& queue, u32 depth, u32& position) +{ + const u32 v1 = (u32)queue.m_v1; + const u32 v2 = (u32)queue.m_v2; + // prx: extract first u8, repeat if not zero + // prx: extract second u32 (u24), subtract 5th u8, compare with zero, repeat if less or equal + if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24))) { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - new_queue.m_v2 &= 0xffffff; // TODO: use InterlockedAnd() or something - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; + return CELL_SYNC_ERROR_BUSY; } + + // prx: insert 1 in first u8 + // prx: extract first u32 (u24), add depth, subtract second u32 (u24), calculate (% depth), save to position + // prx: extract second u32 (u24), decrease it, insert it back + queue.m_v1 = 0x1000000 | v1; + position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth; + queue.m_v2 = (v2 & 0xff000000) | ((v2 & 0xffffff) - 1); return CELL_OK; } @@ -616,52 +610,27 @@ s32 cellSyncQueuePop(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->m_v1 & 0xffffff) <= depth && ((u32)queue->m_v2 & 0xffffff) <= depth); + assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); u32 position; - while (true) + while (queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - const u32 v1 = (u32)new_queue.m_v1; - const u32 v2 = (u32)new_queue.m_v2; - // prx: extract first u8, repeat if not zero - // prx: extract second u32 (u24), subtract 5th u8, compare with zero, repeat if less or equal - if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24))) + return syncQueueTryPopOp(queue, depth, position); + })) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + if (Emu.IsStopped()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncQueuePop(queue_addr=0x%x) aborted", queue.addr()); - return CELL_OK; - } - continue; + cellSync->Warning("cellSyncQueuePop(queue_addr=0x%x) aborted", queue.addr()); + return CELL_OK; } - - // prx: insert 1 in first u8 - // prx: extract first u32 (u24), add depth, subtract second u32 (u24), calculate (% depth), save to position - // prx: extract second u32 (u24), decrease it, insert it back - new_queue.m_v1 = 0x1000000 | v1; - position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth; - new_queue.m_v2 = (v2 & 0xff000000) | ((v2 & 0xffffff) - 1); - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; } // prx: (sync), memcpy(buffer_addr, position * m_size + m_addr, m_size) memcpy(buffer.get_ptr(), &queue->m_buffer[position * size], size); // prx: atomically insert 0 in first u8 - while (true) - { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - new_queue.m_v1 &= 0xffffff; // TODO: use InterlockedAnd() or something - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; - } + queue->data &= { be_t::make(0xffffff), be_t::make(~0) }; return CELL_OK; } @@ -680,39 +649,33 @@ s32 cellSyncQueueTryPop(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->m_v1 & 0xffffff) <= depth && ((u32)queue->m_v2 & 0xffffff) <= depth); + assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); u32 position; - while (true) + if (s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - const u32 v1 = (u32)new_queue.m_v1; - const u32 v2 = (u32)new_queue.m_v2; - if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24))) - { - return CELL_SYNC_ERROR_BUSY; - } - - new_queue.m_v1 = 0x1000000 | v1; - position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth; - new_queue.m_v2 = (v2 & 0xff000000) | ((v2 & 0xffffff) - 1); - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; + return syncQueueTryPopOp(queue, depth, position); + })) + { + return res; } memcpy(buffer.get_ptr(), &queue->m_buffer[position * size], size); + queue->data &= { be_t::make(0xffffff), be_t::make(~0) }; + return CELL_OK; +} - while (true) +s32 syncQueueTryPeekOp(CellSyncQueue::data_t& queue, u32 depth, u32& position) +{ + const u32 v1 = (u32)queue.m_v1; + const u32 v2 = (u32)queue.m_v2; + if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24))) { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - new_queue.m_v1 &= 0xffffff; // TODO: use InterlockedAnd() or something - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; + return CELL_SYNC_ERROR_BUSY; } + + queue.m_v1 = 0x1000000 | v1; + position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth; return CELL_OK; } @@ -731,44 +694,24 @@ s32 cellSyncQueuePeek(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->m_v1 & 0xffffff) <= depth && ((u32)queue->m_v2 & 0xffffff) <= depth); + assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); u32 position; - while (true) + while (queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - const u32 v1 = (u32)new_queue.m_v1; - const u32 v2 = (u32)new_queue.m_v2; - if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24))) + return syncQueueTryPeekOp(queue, depth, position); + })) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + if (Emu.IsStopped()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncQueuePeek(queue_addr=0x%x) aborted", queue.addr()); - return CELL_OK; - } - continue; + cellSync->Warning("cellSyncQueuePeek(queue_addr=0x%x) aborted", queue.addr()); + return CELL_OK; } - - new_queue.m_v1 = 0x1000000 | v1; - position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth; - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; } memcpy(buffer.get_ptr(), &queue->m_buffer[position * size], size); - - while (true) - { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - new_queue.m_v1 &= 0xffffff; // TODO: use InterlockedAnd() or something - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; - } + queue->data &= { be_t::make(0xffffff), be_t::make(~0) }; return CELL_OK; } @@ -787,38 +730,19 @@ s32 cellSyncQueueTryPeek(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->m_v1 & 0xffffff) <= depth && ((u32)queue->m_v2 & 0xffffff) <= depth); + assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); u32 position; - while (true) + if (s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - const u32 v1 = (u32)new_queue.m_v1; - const u32 v2 = (u32)new_queue.m_v2; - if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24))) - { - return CELL_SYNC_ERROR_BUSY; - } - - new_queue.m_v1 = 0x1000000 | v1; - position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth; - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; + return syncQueueTryPeekOp(queue, depth, position); + })) + { + return res; } memcpy(buffer.get_ptr(), &queue->m_buffer[position * size], size); - - while (true) - { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - new_queue.m_v1 &= 0xffffff; // TODO: use InterlockedAnd() or something - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; - } + queue->data &= { be_t::make(0xffffff), be_t::make(~0) }; return CELL_OK; } @@ -835,9 +759,9 @@ s32 cellSyncQueueSize(vm::ptr queue) return CELL_SYNC_ERROR_ALIGN; } - const u32 count = (u32)queue->m_v2 & 0xffffff; + const u32 count = (u32)queue->data.read_relaxed().m_v2 & 0xffffff; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->m_v1 & 0xffffff) <= depth && count <= depth); + assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && count <= depth); return count; } @@ -856,55 +780,50 @@ s32 cellSyncQueueClear(vm::ptr queue) } const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->m_v1 & 0xffffff) <= depth && ((u32)queue->m_v2 & 0xffffff) <= depth); + assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); // TODO: optimize if possible - while (true) + while (queue->data.atomic_op(CELL_OK, [depth](CellSyncQueue::data_t& queue) -> s32 { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - const u32 v1 = (u32)new_queue.m_v1; + const u32 v1 = (u32)queue.m_v1; // prx: extract first u8, repeat if not zero, insert 1 if (v1 >> 24) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncQueueClear(queue_addr=0x%x) aborted (I)", queue.addr()); - return CELL_OK; - } - continue; + return CELL_SYNC_ERROR_BUSY; + } + queue.m_v1 = v1 | 0x1000000; + return CELL_OK; + })) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + if (Emu.IsStopped()) + { + cellSync->Warning("cellSyncQueueClear(queue_addr=0x%x) aborted (I)", queue.addr()); + return CELL_OK; } - new_queue.m_v1 = v1 | 0x1000000; - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; } - while (true) + while (queue->data.atomic_op(CELL_OK, [depth](CellSyncQueue::data_t& queue) -> s32 { - const u64 old_data = queue->m_data(); - CellSyncQueue new_queue; - new_queue.m_data() = old_data; - - const u32 v2 = (u32)new_queue.m_v2; + const u32 v2 = (u32)queue.m_v2; // prx: extract 5th u8, repeat if not zero, insert 1 if (v2 >> 24) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (Emu.IsStopped()) - { - cellSync->Warning("cellSyncQueueClear(queue_addr=0x%x) aborted (II)", queue.addr()); - return CELL_OK; - } - continue; + return CELL_SYNC_ERROR_BUSY; + } + queue.m_v2 = v2 | 0x1000000; + return CELL_OK; + })) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + if (Emu.IsStopped()) + { + cellSync->Warning("cellSyncQueueClear(queue_addr=0x%x) aborted (II)", queue.addr()); + return CELL_OK; } - new_queue.m_v2 = v2 | 0x1000000; - if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break; } - queue->m_data() = 0; - InterlockedCompareExchange(&queue->m_data(), 0, 0); + queue->data.exchange({}); return CELL_OK; } @@ -921,28 +840,18 @@ void syncLFQueueDump(vm::ptr queue) void syncLFQueueInit(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) { - queue->m_h1 = 0; - queue->m_h2 = 0; - queue->m_h4 = 0; - queue->m_h5 = 0; - queue->m_h6 = 0; - queue->m_h8 = 0; queue->m_size = size; queue->m_depth = depth; queue->m_buffer = buffer; queue->m_direction = direction; - for (u32 i = 0; i < sizeof(queue->m_hs) / sizeof(queue->m_hs[0]); i++) - { - queue->m_hs[i] = 0; - } + *queue->m_hs = {}; queue->m_eaSignal = eaSignal; if (direction == CELL_SYNC_QUEUE_ANY2ANY) { - queue->m_h3 = 0; - queue->m_h7 = 0; - queue->m_buffer = buffer + 1; - assert(queue->m_buffer.addr() % 2); + queue->pop1.write_relaxed({}); + queue->push1.write_relaxed({}); + queue->m_buffer.set(queue->m_buffer.addr() | be_t::make(1)); queue->m_bs[0] = -1; queue->m_bs[1] = -1; //m_bs[2] @@ -955,8 +864,8 @@ void syncLFQueueInit(vm::ptr queue, vm::ptr buffer, u32 siz } else { - //m_h3 - //m_h7 + queue->pop1.write_relaxed({ be_t::make(0), be_t::make(0), queue->pop1.read_relaxed().m_h3, be_t::make(0) }); + queue->push1.write_relaxed({ be_t::make(0), be_t::make(0), queue->push1.read_relaxed().m_h7, be_t::make(0) }); queue->m_bs[0] = -1; // written as u32 queue->m_bs[1] = -1; queue->m_bs[2] = -1; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index 15f94e46e0..a2cb2fcadd 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -78,18 +78,11 @@ struct CellSyncQueue be_t m_v2; }; - be_t m_v1; - be_t m_v2; - //vm::atomic data; + vm::atomic data; be_t m_size; be_t m_depth; vm::bptr m_buffer; be_t reserved; - - volatile u64& m_data() - { - return *reinterpret_cast(this); - }; }; static_assert(sizeof(CellSyncQueue) == 32, "CellSyncQueue: wrong size"); @@ -104,21 +97,54 @@ enum CellSyncQueueDirection : u32 // CellSyncLFQueueDirection struct CellSyncLFQueue { - be_t m_h1; // 0x0 - be_t m_h2; // 0x2 - be_t m_h3; // 0x4 - be_t m_h4; // 0x6 - be_t m_h5; // 0x8 - be_t m_h6; // 0xA - be_t m_h7; // 0xC - be_t m_h8; // 0xE + struct init_t + { + be_t m_sync; + }; + + struct pop1_t + { + be_t m_h1; + be_t m_h2; + be_t m_h3; + be_t m_h4; + }; + + struct push1_t + { + be_t m_h5; + be_t m_h6; + be_t m_h7; + be_t m_h8; + }; + + union + { + struct + { + vm::atomic pop1; + vm::atomic push1; + }; + struct + { + be_t m_h1; // 0x0 + be_t m_h2; // 0x2 + be_t m_h3; // 0x4 + be_t m_h4; // 0x6 + be_t m_h5; // 0x8 + be_t m_h6; // 0xA + be_t m_h7; // 0xC + be_t m_h8; // 0xE + }; + }; + be_t m_size; // 0x10 be_t m_depth; // 0x14 vm::bptr m_buffer; // 0x18 u8 m_bs[4]; // 0x20 be_t m_direction; // 0x24 be_t m_v1; // 0x28 - be_t m_sync; // 0x2C + vm::atomic init; // 0x2C be_t m_hs[32]; // 0x30 vm::bptr m_eaSignal; // 0x70 be_t m_v2; // 0x78 From 449e7c1049ca72168baaeb4f6be7b9e9a010621d Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 21 Sep 2014 19:14:13 +0400 Subject: [PATCH 11/24] Small fix --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 26dd568e54..6b7ba92de5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -20,12 +20,12 @@ extern u32 libsre; extern u32 libsre_rtoc; #endif -s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, u32 arg3, u32 arg4) +s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, u32 arg3, u32 arg4, u64 name_u64) { #ifdef PRX_DEBUG vm::var> queue; - s32 res = cb_call, vm::ptr>, u32, u32>(GetCurrentPPUThread(), libsre + 0xB14C, libsre_rtoc, - spurs, queue, arg3, arg4); + s32 res = cb_call, vm::ptr>, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0xB14C, libsre_rtoc, + spurs, queue, arg3, arg4, vm::read32(libsre_rtoc - 0x7E2C)); queue_id = queue->ToLE(); return res; #else @@ -182,7 +182,7 @@ s64 spursInit( spurs->m.ppuPriority = ppuPriority; u32 queue; - assert(spursCreateLv2EventQueue(spurs, queue, spurs.addr() + 0xc9, 0x2a) == CELL_OK); + assert(spursCreateLv2EventQueue(spurs, queue, spurs.addr() + 0xc9, 0x2a, *(u64*)"_spuPrv") == CELL_OK); spurs->m.queue = queue; u32 port = event_port_create(0); @@ -247,7 +247,7 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 cellSpurs->Warning("cellSpursInitialize(spurs_addr=0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)", spurs.addr(), nSpus, spuPriority, ppuPriority, exitIfNoWork ? 1 : 0); -#ifdef PRX_DEBUG +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x8480, libsre_rtoc); #else return spursInit( From e5a485e50b6555239d0cab1495405d6cc5a443d9 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 23 Sep 2014 03:07:40 +0400 Subject: [PATCH 12/24] More changes --- rpcs3/Emu/Cell/SPURecompiler.h | 39 +++--- rpcs3/Emu/Cell/SPURecompilerCore.cpp | 40 ++++-- rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/Emu/Memory/vm_atomic.h | 26 ++-- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 89 ++++++++++-- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 4 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 171 ++++++++++++----------- rpcs3/Emu/SysCalls/Modules/cellSync.h | 67 +++------ 8 files changed, 250 insertions(+), 188 deletions(-) diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 390db51594..455e058658 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -78,6 +78,7 @@ public: SPUInterpreter* inter; JitRuntime runtime; bool first; + bool need_check; struct SPURecEntry { @@ -457,7 +458,7 @@ private: c.mov(cpu_dword(PC), CPU.PC); // This instruction must be used following a store instruction that modifies the instruction stream. c.mfence(); - c.mov(*pos_var, (CPU.PC >> 2) + 1); + c.mov(*pos_var, (CPU.PC >> 2) + 1 + 0x2000000); do_finalize = true; LOG_OPCODE(); } @@ -1142,6 +1143,7 @@ private: c.mov(*addr, CPU.PC + 4); c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); c.cmovne(*pos_var, *addr); c.shr(*pos_var, 2); @@ -1160,6 +1162,7 @@ private: c.mov(*addr, CPU.PC + 4); c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); c.cmove(*pos_var, *addr); c.shr(*pos_var, 2); @@ -1178,6 +1181,7 @@ private: c.mov(*addr, CPU.PC + 4); c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) c.cmp(cpu_word(GPR[rt]._u16[6]), 0); c.cmovne(*pos_var, *addr); c.shr(*pos_var, 2); @@ -1196,6 +1200,7 @@ private: c.mov(*addr, CPU.PC + 4); c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) c.cmp(cpu_word(GPR[rt]._u16[6]), 0); c.cmove(*pos_var, *addr); c.shr(*pos_var, 2); @@ -1244,6 +1249,7 @@ private: do_finalize = true; c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) c.shr(*pos_var, 2); LOG_OPCODE(); } @@ -1267,6 +1273,7 @@ private: c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4); c.shr(*pos_var, 2); + c.or_(*pos_var, 0x2000000); LOG_OPCODE(); } void IRET(u32 ra) @@ -1947,11 +1954,10 @@ private: { c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); c.cmp(*addr, cpu_dword(GPR[rb]._s32[3])); - c.mov(*addr, 0); c.setg(addr->r8()); - c.neg(*addr); + c.shl(*addr, 24); c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.xor_(*pos_var, *addr); + c.or_(*pos_var, *addr); do_finalize = true; LOG_OPCODE(); } @@ -2308,11 +2314,10 @@ private: { c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.cmp(*addr, cpu_dword(GPR[rb]._u32[3])); - c.mov(*addr, 0); c.seta(addr->r8()); - c.neg(*addr); + c.shl(*addr, 24); c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.xor_(*pos_var, *addr); + c.or_(*pos_var, *addr); do_finalize = true; LOG_OPCODE(); } @@ -2662,11 +2667,10 @@ private: { c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); c.cmp(*addr, cpu_dword(GPR[rb]._s32[3])); - c.mov(*addr, 0); c.sete(addr->r8()); - c.neg(*addr); + c.shl(*addr, 24); c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.xor_(*pos_var, *addr); + c.or_(*pos_var, *addr); do_finalize = true; LOG_OPCODE(); } @@ -3324,11 +3328,10 @@ private: { c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); c.cmp(*addr, i10); - c.mov(*addr, 0); c.setg(addr->r8()); - c.neg(*addr); + c.shl(*addr, 24); c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.xor_(*pos_var, *addr); + c.or_(*pos_var, *addr); do_finalize = true; LOG_OPCODE(); } @@ -3390,11 +3393,10 @@ private: { c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.cmp(*addr, i10); - c.mov(*addr, 0); c.seta(addr->r8()); - c.neg(*addr); + c.shl(*addr, 24); c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.xor_(*pos_var, *addr); + c.or_(*pos_var, *addr); do_finalize = true; LOG_OPCODE(); } @@ -3441,11 +3443,10 @@ private: { c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.cmp(*addr, i10); - c.mov(*addr, 0); c.sete(addr->r8()); - c.neg(*addr); + c.shl(*addr, 24); c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.xor_(*pos_var, *addr); + c.or_(*pos_var, *addr); do_finalize = true; LOG_OPCODE(); } diff --git a/rpcs3/Emu/Cell/SPURecompilerCore.cpp b/rpcs3/Emu/Cell/SPURecompilerCore.cpp index 0427e8effb..68e929edf3 100644 --- a/rpcs3/Emu/Cell/SPURecompilerCore.cpp +++ b/rpcs3/Emu/Cell/SPURecompilerCore.cpp @@ -20,6 +20,7 @@ SPURecompilerCore::SPURecompilerCore(SPUThread& cpu) , inter(new SPUInterpreter(cpu)) , CPU(cpu) , first(true) + , need_check(false) { memset(entry, 0, sizeof(entry)); X86CpuInfo inf; @@ -192,20 +193,26 @@ u8 SPURecompilerCore::DecodeMemory(const u32 address) { // check data (hard way) bool is_valid = true; - //for (u32 i = pos; i < (u32)(entry[pos].count + pos); i++) - //{ - // if (entry[i].valid != ls[i]) - // { - // is_valid = false; - // break; - // } - //} + if (need_check) + { + for (u32 i = 0; i < 0x10000; i++) + { + if (entry[i].valid && entry[i].valid != ls[i]) + { + is_valid = false; + break; + } + } + need_check = false; + } // invalidate if necessary if (!is_valid) { for (u32 i = 0; i < 0x10000; i++) { - if (entry[i].pointer && + if (!entry[i].pointer) continue; + + if (!entry[i].valid || entry[i].valid != ls[i] || i + (u32)entry[i].count > (u32)pos && i < (u32)pos + (u32)entry[pos].count) { @@ -214,6 +221,11 @@ u8 SPURecompilerCore::DecodeMemory(const u32 address) //RtlDeleteFunctionTable(&entry[i].info); #endif entry[i].pointer = nullptr; + for (u32 j = i; j < i + (u32)entry[i].count; j++) + { + entry[j].valid = 0; + } + //need_check = true; } } //LOG_ERROR(Log::SPU, "SPURecompilerCore::DecodeMemory(ls_addr=0x%x): code has changed", pos * sizeof(u32)); @@ -254,11 +266,17 @@ u8 SPURecompilerCore::DecodeMemory(const u32 address) u32 res = pos; res = func(cpu, vm::get_ptr(m_offset), imm_table.data(), &g_imm_table); - if (res > 0xffff) + if (res & 0x1000000) { CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); CPU.Stop(); - res = ~res; + res &= ~0x1000000; + } + + if (res & 0x2000000) + { + need_check = true; + res &= ~0x2000000; } if (did_compile) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index e33291cf8c..ca17de309d 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -358,7 +358,7 @@ public: } else { - InterlockedOr((volatile u64*)m_indval, ((u64)value << 32) | 1); + InterlockedOr(&m_indval, ((u64)value << 32) | 1); } } diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h index fc4912a419..867a8f0e9d 100644 --- a/rpcs3/Emu/Memory/vm_atomic.h +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -25,34 +25,34 @@ namespace vm template class _atomic_base { - volatile T data; typedef typename _to_atomic::type atomic_type; + atomic_type data; public: // atomically compare data with cmp, replace with exch if equal, return previous data value anyway __forceinline const T compare_and_swap(const T& cmp, const T& exch) volatile { - const atomic_type res = InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp); + const atomic_type res = InterlockedCompareExchange(&data, (atomic_type&)(exch), (atomic_type&)(cmp)); return (T&)res; } // atomically compare data with cmp, replace with exch if equal, return true if data was replaced __forceinline bool compare_and_swap_test(const T& cmp, const T& exch) volatile { - return InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp) == (atomic_type&)cmp; + return InterlockedCompareExchange(&data, (atomic_type&)(exch), (atomic_type&)(cmp)) == (atomic_type&)(cmp); } // read data with memory barrier __forceinline const T read_sync() const volatile { - const atomic_type res = InterlockedCompareExchange((volatile atomic_type*)&data, 0, 0); + const atomic_type res = InterlockedCompareExchange(const_cast(&data), 0, 0); return (T&)res; } // atomically replace data with exch, return previous data value __forceinline const T exchange(const T& exch) volatile { - const atomic_type res = InterlockedExchange((volatile atomic_type*)&data, (atomic_type&)exch); + const atomic_type res = InterlockedExchange(&data, (atomic_type&)(exch)); return (T&)res; } @@ -65,7 +65,7 @@ namespace vm // write data without memory barrier __forceinline void write_relaxed(const T& value) volatile { - (T&)data = value; + data = (atomic_type&)(value); } // perform atomic operation on data @@ -81,7 +81,7 @@ namespace vm } // perform atomic operation on data with special exit condition (if intermediate result != proceed_value) - template __forceinline RT atomic_op(const RT& proceed_value, const FT atomic_proc) volatile + template __forceinline RT atomic_op(const RT proceed_value, const FT atomic_proc) volatile { while (true) { @@ -95,37 +95,37 @@ namespace vm __forceinline const T _or(const T& right) volatile { - const atomic_type res = InterlockedOr((volatile atomic_type*)&data, (atomic_type&)right); + const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)); return (T&)res; } __forceinline const T _and(const T& right) volatile { - const atomic_type res = InterlockedAnd((volatile atomic_type*)&data, (atomic_type&)right); + const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)); return (T&)res; } __forceinline const T _xor(const T& right) volatile { - const atomic_type res = InterlockedXor((volatile atomic_type*)&data, (atomic_type&)right); + const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)); return (T&)res; } __forceinline const T operator |= (const T& right) volatile { - const atomic_type res = InterlockedOr((volatile atomic_type*)&data, (atomic_type&)right) | (atomic_type&)right; + const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)) | (atomic_type&)(right); return (T&)res; } __forceinline const T operator &= (const T& right) volatile { - const atomic_type res = InterlockedAnd((volatile atomic_type*)&data, (atomic_type&)right) & (atomic_type&)right; + const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)) & (atomic_type&)(right); return (T&)res; } __forceinline const T operator ^= (const T& right) volatile { - const atomic_type res = InterlockedXor((volatile atomic_type*)&data, (atomic_type&)right) ^ (atomic_type&)right; + const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)) ^ (atomic_type&)(right); return (T&)res; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 6b7ba92de5..440c2f08f4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -20,17 +20,86 @@ extern u32 libsre; extern u32 libsre_rtoc; #endif -s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, u32 arg3, u32 arg4, u64 name_u64) +s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated) { +#ifdef PRX_DEBUG_XXX + return cb_call, u32, vm::ptr, s32, bool>(GetCurrentPPUThread(), libsre + 0xAE34, libsre_rtoc, + spurs, queue, port, isDynamic, wasCreated); +#else + if (!spurs || !port) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + if (spurs->m.unk21.ToBE()) + { + return CELL_SPURS_CORE_ERROR_STAT; + } + + u32 unk1 = 0; #ifdef PRX_DEBUG + unk1 = cb_call(GetCurrentPPUThread(), libsre + 0x10900, libsre_rtoc); +#endif + + u8 _port = 0x3f; + u8 port_start = 0x10; + u64 port_mask = 0; + if (isDynamic == 0) + { + _port = *port; + if (_port > 0x3f) + { + return CELL_SPURS_CORE_ERROR_INVAL; + } + if (unk1 <= 0x17ffff && _port > 0xf) + { + return CELL_SPURS_CORE_ERROR_PERM; + } + port_start = _port; + } + + for (u32 i = port_start + 1; i < _port; i++) + { + port_mask |= 1ull << (i - 1); + } + + if (s32 res = sys_spu_thread_group_connect_event_all_threads(spurs->m.spuTG, queue, port_mask, port)) + { + if (res == CELL_EISCONN) + { + return CELL_SPURS_CORE_ERROR_BUSY; + } + return res; + } + + if (!wasCreated) + { + spurs->m.spups |= be_t::make(1ull << *port); // atomic bitwise or + } + + return CELL_OK; +#endif +} + +s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptr port, s32 size, u64 name_u64) +{ +#ifdef PRX_DEBUG_XXX vm::var> queue; - s32 res = cb_call, vm::ptr>, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0xB14C, libsre_rtoc, - spurs, queue, arg3, arg4, vm::read32(libsre_rtoc - 0x7E2C)); + s32 res = cb_call, vm::ptr>, vm::ptr, s32, u32>(GetCurrentPPUThread(), libsre + 0xB14C, libsre_rtoc, + spurs, queue, port, size, vm::read32(libsre_rtoc - 0x7E2C)); queue_id = queue->ToLE(); return res; #else - // TODO - queue_id = event_queue_create(SYS_SYNC_PRIORITY, SYS_PPU_QUEUE, *(u64*)"+QUEUE+", 0, 1); + queue_id = event_queue_create(SYS_SYNC_FIFO, SYS_PPU_QUEUE, name_u64, 0, size); + if (!queue_id) + { + return CELL_EAGAIN; // rough + } + + assert(spursAttachLv2EventQueue(spurs, queue_id, port, 1, true) == CELL_OK); return CELL_OK; #endif } @@ -108,7 +177,7 @@ s64 spursInit( for (u32 i = 0; i < 0x10; i++) { sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl"); - assert(sem && ~sem); // should rollback if semaphore creating failed and return the error + assert(sem && ~sem); // should rollback if semaphore creation failed and return the error spurs->m.sub1[i].sem = sem; } if (isSecond) @@ -182,7 +251,7 @@ s64 spursInit( spurs->m.ppuPriority = ppuPriority; u32 queue; - assert(spursCreateLv2EventQueue(spurs, queue, spurs.addr() + 0xc9, 0x2a, *(u64*)"_spuPrv") == CELL_OK); + assert(spursCreateLv2EventQueue(spurs, queue, vm::ptr::make(spurs.addr() + 0xc9), 0x2a, *(u64*)"_spuPrv") == CELL_OK); spurs->m.queue = queue; u32 port = event_port_create(0); @@ -618,13 +687,13 @@ s64 cellSpursSetPreemptionVictimHints(vm::ptr spurs, vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=%d, port_addr=0x%x, isDynamic=%d)", spurs.addr(), queue, port.addr(), isDynamic); + +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xAFE0, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; + return spursAttachLv2EventQueue(spurs, queue, port, isDynamic, false); #endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 717e9afe94..d3ab987c2d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -185,7 +185,7 @@ struct CellSpurs u8 unknown0[0xB0 - 0x78]; be_t unk0; // 0x0B0 u8 unknown2[0xC0 - 0xB4]; - u8 unk6[0x10]; // 0x0C0 + u8 unk6[0x10]; // 0x0C0 (SPU port at 0xc9) u8 unknown1[0x100 - 0x0D0]; _sub_str1 sub1[0x10]; // 0x100 be_t unk22; // 0x900 @@ -219,7 +219,7 @@ struct CellSpurs be_t unk5; // 0xD9C be_t revision; // 0xDA0 be_t sdkVersion; // 0xDA4 - u8 unknown8[0xDB0 - 0xDA8]; + vm::atomic spups;// 0xDA8 sys_lwmutex_t mutex; // 0xDB0 sys_lwcond_t cond; // 0xDC8 u8 unknown9[0xF00 - 0xDD0]; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index a09d4c6103..793115d879 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -923,17 +923,16 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 u32 old_value; while (true) { - const u32 old_data = queue->m_data(); - CellSyncLFQueue new_data; - new_data.m_data() = old_data; + const auto old = queue->init.read_relaxed(); + auto init = old; - if (old_data) + if (old.ToBE()) { - if (sdk_ver > 0x17ffff && old_data != se32(2)) + if (sdk_ver > 0x17ffff && old != 2) { return CELL_SYNC_ERROR_STAT; } - old_value = old_data; + old_value = old.ToLE(); } else { @@ -948,14 +947,14 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 } } } - new_data.m_data() = se32(1); - old_value = se32(1); + init = 1; + old_value = 1; } - if (InterlockedCompareExchange(&queue->m_data(), new_data.m_data(), old_data) == old_data) break; + if (queue->init.compare_and_swap_test(old, init)) break; } - if (old_value == se32(2)) + if (old_value == 2) { if ((u32)queue->m_size != size || (u32)queue->m_depth != depth || queue->m_buffer.addr() != buffer.addr()) { @@ -975,12 +974,11 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 syncLFQueueInit(queue, buffer, size, depth, direction, eaSignal); // prx: sync, zeroize u32 at 0x2c offset - InterlockedCompareExchange(&queue->m_data(), 0, 0); - queue->m_data() = 0; + queue->init.exchange({}); } // prx: sync - InterlockedCompareExchange(&queue->m_data(), 0, 0); + queue->init.read_sync(); return CELL_OK; #endif } @@ -1011,28 +1009,27 @@ s32 syncLFQueueGetPushPointer(vm::ptr queue, s32& pointer, u32 return -1; } - const u64 old_data = InterlockedCompareExchange(&queue->m_push1(), 0, 0); - CellSyncLFQueue new_queue; - new_queue.m_push1() = old_data; + const auto old = queue->push1.read_sync(); + auto push = old; if (var1) { - new_queue.m_h7 = 0; + push.m_h7 = 0; } if (isBlocking && useEventQueue && *(u32*)queue->m_bs == -1) { return CELL_SYNC_ERROR_STAT; } - s32 var2 = (s32)(s16)new_queue.m_h8; + s32 var2 = (s32)(s16)push.m_h8; s32 res; - if (useEventQueue && ((s32)(u16)new_queue.m_h5 != var2 || new_queue.m_h7.ToBE() != 0)) + if (useEventQueue && ((s32)push.m_h5 != var2 || push.m_h7.ToBE() != 0)) { res = CELL_SYNC_ERROR_BUSY; } else { - var2 -= (s32)(u16)queue->m_h1; + var2 -= (s32)(u16)queue->pop1.read_relaxed().m_h1; if (var2 < 0) { var2 += depth * 2; @@ -1040,21 +1037,21 @@ s32 syncLFQueueGetPushPointer(vm::ptr queue, s32& pointer, u32 if (var2 < depth) { - pointer = (s16)new_queue.m_h8; + pointer = (s16)push.m_h8; if (pointer + 1 >= depth * 2) { - new_queue.m_h8 = 0; + push.m_h8 = 0; } else { - new_queue.m_h8++; + push.m_h8++; } res = CELL_OK; } else if (!isBlocking) { res = CELL_SYNC_ERROR_AGAIN; - if (!new_queue.m_h7.ToBE() || res) + if (!push.m_h7.ToBE() || res) { return res; } @@ -1067,7 +1064,7 @@ s32 syncLFQueueGetPushPointer(vm::ptr queue, s32& pointer, u32 else { res = CELL_OK; - new_queue.m_h7 = 3; + push.m_h7 = 3; if (isBlocking != 3) { break; @@ -1075,9 +1072,9 @@ s32 syncLFQueueGetPushPointer(vm::ptr queue, s32& pointer, u32 } } - if (InterlockedCompareExchange(&queue->m_push1(), new_queue.m_push1(), old_data) == old_data) + if (queue->push1.compare_and_swap_test(old, push)) { - if (!new_queue.m_h7.ToBE() || res) + if (!push.m_h7.ToBE() || res) { return res; } @@ -1138,19 +1135,19 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, while (true) { const u32 old_data = InterlockedCompareExchange(&queue->m_push2(), 0, 0); - CellSyncLFQueue new_queue; - new_queue.m_push2() = old_data; + CellSyncLFQueue new_; + new_.m_push2() = old_data; - const u32 old_data2 = queue->m_push3(); - new_queue.m_push3() = old_data2; + const auto old2 = queue->push3.read_relaxed(); + auto push = old2; - s32 var1 = pointer - (u16)new_queue.m_h5; + s32 var1 = pointer - (u16)push.m_h5; if (var1 < 0) { var1 += depth * 2; } - s32 var2 = (s32)(s16)queue->m_h4 - (s32)(u16)queue->m_h1; + s32 var2 = (s32)(s16)queue->pop1.read_relaxed().m_h4 - (s32)(u16)queue->pop1.read_relaxed().m_h1; if (var2 < 0) { var2 += depth * 2; @@ -1166,7 +1163,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, { var9_ = 1 << var9_; } - s32 var9 = ~(var9_ | (u16)new_queue.m_h6); + s32 var9 = ~(var9_ | (u16)push.m_h6); // count leading zeros in u16 { u16 v = var9; @@ -1179,7 +1176,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, } } - s32 var5 = (s32)(u16)new_queue.m_h6 | var9_; + s32 var5 = (s32)(u16)push.m_h6 | var9_; if (var9 & 0x30) { var5 = 0; @@ -1189,13 +1186,13 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, var5 <<= var9; } - s32 var3 = (u16)new_queue.m_h5 + var9; + s32 var3 = (u16)push.m_h5 + var9; if (var3 >= depth * 2) { var3 -= depth * 2; } - u16 pack = new_queue.m_hs[0]; // three packed 5-bit fields + u16 pack = new_.m_hs[0]; // three packed 5-bit fields s32 var4 = ((pack >> 10) & 0x1f) - ((pack >> 5) & 0x1f); if (var4 < 0) @@ -1233,7 +1230,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, var12 = (var12 + 1) << 10; } - new_queue.m_hs[0] = (pack & 0x83ff) | var12; + new_.m_hs[0] = (pack & 0x83ff) | var12; var6 = (u16)queue->m_hs[1 + 2 * var11]; } else @@ -1241,14 +1238,15 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, var6 = -1; } - s32 var7 = (var3 << 16) | (var5 & 0xffff); + push.m_h5 = (u16)var3; + push.m_h6 = (u16)var5; - if (InterlockedCompareExchange(&queue->m_push2(), new_queue.m_push2(), old_data) == old_data) + if (InterlockedCompareExchange(&queue->m_push2(), new_.m_push2(), old_data) == old_data) { assert(var2 + var4 < 16); if (var6 != -1) { - bool exch = InterlockedCompareExchange(&queue->m_push3(), re32(var7), old_data2) == old_data2; + bool exch = queue->push3.compare_and_swap_test(old2, push); assert(exch); if (exch) { @@ -1261,7 +1259,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, pack = queue->m_hs[0]; if ((pack & 0x1f) == ((pack >> 10) & 0x1f)) { - if (InterlockedCompareExchange(&queue->m_push3(), re32(var7), old_data2) == old_data2) + if (queue->push3.compare_and_swap_test(old2, push)) { return CELL_OK; } @@ -1409,28 +1407,27 @@ s32 syncLFQueueGetPopPointer(vm::ptr queue, s32& pointer, u32 i return -1; } - const u64 old_data = InterlockedCompareExchange(&queue->m_pop1(), 0, 0); - CellSyncLFQueue new_queue; - new_queue.m_pop1() = old_data; + const auto old = queue->pop1.read_sync(); + auto pop = old; if (var1) { - new_queue.m_h3 = 0; + pop.m_h3 = 0; } if (isBlocking && useEventQueue && *(u32*)queue->m_bs == -1) { return CELL_SYNC_ERROR_STAT; } - s32 var2 = (s32)(s16)new_queue.m_h4; + s32 var2 = (s32)(s16)pop.m_h4; s32 res; - if (useEventQueue && ((s32)(u16)new_queue.m_h1 != var2 || new_queue.m_h3.ToBE() != 0)) + if (useEventQueue && ((s32)(u16)pop.m_h1 != var2 || pop.m_h3.ToBE() != 0)) { res = CELL_SYNC_ERROR_BUSY; } else { - var2 = (s32)(u16)queue->m_h5 - var2; + var2 = (s32)(u16)queue->push1.read_relaxed().m_h5 - var2; if (var2 < 0) { var2 += depth * 2; @@ -1438,21 +1435,21 @@ s32 syncLFQueueGetPopPointer(vm::ptr queue, s32& pointer, u32 i if (var2 > 0) { - pointer = (s16)new_queue.m_h4; + pointer = (s16)pop.m_h4; if (pointer + 1 >= depth * 2) { - new_queue.m_h4 = 0; + pop.m_h4 = 0; } else { - new_queue.m_h4++; + pop.m_h4++; } res = CELL_OK; } else if (!isBlocking) { res = CELL_SYNC_ERROR_AGAIN; - if (!new_queue.m_h3.ToBE() || res) + if (!pop.m_h3.ToBE() || res) { return res; } @@ -1465,7 +1462,7 @@ s32 syncLFQueueGetPopPointer(vm::ptr queue, s32& pointer, u32 i else { res = CELL_OK; - new_queue.m_h3 = 3; + pop.m_h3 = 3; if (isBlocking != 3) { break; @@ -1473,9 +1470,9 @@ s32 syncLFQueueGetPopPointer(vm::ptr queue, s32& pointer, u32 i } } - if (InterlockedCompareExchange(&queue->m_pop1(), new_queue.m_pop1(), old_data) == old_data) + if (queue->pop1.compare_and_swap_test(old, pop)) { - if (!new_queue.m_h3.ToBE() || res) + if (!pop.m_h3.ToBE() || res) { return res; } @@ -1536,19 +1533,19 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c while (true) { const u32 old_data = InterlockedCompareExchange(&queue->m_pop2(), 0, 0); - CellSyncLFQueue new_queue; - new_queue.m_pop2() = old_data; + CellSyncLFQueue new_; + new_.m_pop2() = old_data; - const u32 old_data2 = queue->m_pop3(); - new_queue.m_pop3() = old_data2; + const auto old2 = queue->pop3.read_relaxed(); + auto pop = old2; - s32 var1 = pointer - (u16)new_queue.m_h1; + s32 var1 = pointer - (u16)pop.m_h1; if (var1 < 0) { var1 += depth * 2; } - s32 var2 = (s32)(s16)queue->m_h8 - (s32)(u16)queue->m_h5; + s32 var2 = (s32)(s16)queue->push1.read_relaxed().m_h8 - (s32)(u16)queue->push1.read_relaxed().m_h5; if (var2 < 0) { var2 += depth * 2; @@ -1564,7 +1561,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c { var9_ = 1 << var9_; } - s32 var9 = ~(var9_ | (u16)new_queue.m_h2); + s32 var9 = ~(var9_ | (u16)pop.m_h2); // count leading zeros in u16 { u16 v = var9; @@ -1577,7 +1574,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c } } - s32 var5 = (s32)(u16)new_queue.m_h2 | var9_; + s32 var5 = (s32)(u16)pop.m_h2 | var9_; if (var9 & 0x30) { var5 = 0; @@ -1587,13 +1584,13 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c var5 <<= var9; } - s32 var3 = (u16)new_queue.m_h1 + var9; + s32 var3 = (u16)pop.m_h1 + var9; if (var3 >= depth * 2) { var3 -= depth * 2; } - u16 pack = new_queue.m_hs[16]; // three packed 5-bit fields + u16 pack = new_.m_hs[16]; // three packed 5-bit fields s32 var4 = ((pack >> 10) & 0x1f) - ((pack >> 5) & 0x1f); if (var4 < 0) @@ -1635,17 +1632,18 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c var12 = (var12 + 1) << 10; } - new_queue.m_hs[0] = (pack & 0x83ff) | var12; + new_.m_hs[0] = (pack & 0x83ff) | var12; var6 = (u16)queue->m_hs[17 + 2 * var11]; } - s32 var7 = (var3 << 16) | (var5 & 0xffff); + pop.m_h1 = (u16)var3; + pop.m_h2 = (u16)var5; - if (InterlockedCompareExchange(&queue->m_pop2(), new_queue.m_pop2(), old_data) == old_data) + if (InterlockedCompareExchange(&queue->m_pop2(), new_.m_pop2(), old_data) == old_data) { if (var6 != -1) { - bool exch = InterlockedCompareExchange(&queue->m_pop3(), re32(var7), old_data2) == old_data2; + bool exch = queue->pop3.compare_and_swap_test(old2, pop); assert(exch); if (exch) { @@ -1658,7 +1656,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c pack = queue->m_hs[16]; if ((pack & 0x1f) == ((pack >> 10) & 0x1f)) { - if (InterlockedCompareExchange(&queue->m_pop3(), re32(var7), old_data2) == old_data2) + if (queue->pop3.compare_and_swap_test(old2, pop)) { return CELL_OK; } @@ -1798,12 +1796,10 @@ s32 cellSyncLFQueueClear(vm::ptr queue) // TODO: optimize if possible while (true) { - const u64 old_data = InterlockedCompareExchange(&queue->m_pop1(), 0, 0); - CellSyncLFQueue new_queue; - new_queue.m_pop1() = old_data; + const auto old = queue->pop1.read_sync(); + auto pop = old; - const u64 new_data = queue->m_push1(); - new_queue.m_push1() = new_data; + const auto push = queue->push1.read_relaxed(); s32 var1, var2; if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) @@ -1812,19 +1808,24 @@ s32 cellSyncLFQueueClear(vm::ptr queue) } else { - var1 = (u16)new_queue.m_h7; - var2 = (u16)new_queue.m_h3; + var1 = (u16)push.m_h7; + var2 = (u16)pop.m_h3; } - if ((s32)(s16)new_queue.m_h4 != (s32)(u16)new_queue.m_h1 || - (s32)(s16)new_queue.m_h8 != (s32)(u16)new_queue.m_h5 || + if ((s32)(s16)pop.m_h4 != (s32)(u16)pop.m_h1 || + (s32)(s16)push.m_h8 != (s32)(u16)push.m_h5 || ((var2 >> 10) & 0x1f) != (var2 & 0x1f) || ((var1 >> 10) & 0x1f) != (var1 & 0x1f)) { return CELL_SYNC_ERROR_BUSY; } - if (InterlockedCompareExchange(&queue->m_pop1(), new_data, old_data) == old_data) break; + pop.m_h1 = push.m_h5; + pop.m_h2 = push.m_h6; + pop.m_h3 = push.m_h7; + pop.m_h4 = push.m_h8; + + if (queue->pop1.compare_and_swap_test(old, pop)) break; } return CELL_OK; @@ -1846,12 +1847,12 @@ s32 cellSyncLFQueueSize(vm::ptr queue, vm::ptr> size) // TODO: optimize if possible while (true) { - const u32 old_data = InterlockedCompareExchange(&queue->m_pop3(), 0, 0); + const auto old = queue->pop3.read_sync(); - u32 var1 = (u16)queue->m_h1; - u32 var2 = (u16)queue->m_h5; + u32 var1 = (u16)queue->pop1.read_relaxed().m_h1; + u32 var2 = (u16)queue->push1.read_relaxed().m_h5; - if (InterlockedCompareExchange(&queue->m_pop3(), old_data, old_data) == old_data) + if (queue->pop3.compare_and_swap_test(old, old)) { if (var1 <= var2) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index a2cb2fcadd..4a8086624b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -97,11 +97,6 @@ enum CellSyncQueueDirection : u32 // CellSyncLFQueueDirection struct CellSyncLFQueue { - struct init_t - { - be_t m_sync; - }; - struct pop1_t { be_t m_h1; @@ -110,6 +105,12 @@ struct CellSyncLFQueue be_t m_h4; }; + struct pop3_t + { + be_t m_h1; + be_t m_h2; + }; + struct push1_t { be_t m_h5; @@ -118,72 +119,44 @@ struct CellSyncLFQueue be_t m_h8; }; - union + struct push3_t { - struct - { - vm::atomic pop1; - vm::atomic push1; - }; - struct - { - be_t m_h1; // 0x0 - be_t m_h2; // 0x2 - be_t m_h3; // 0x4 - be_t m_h4; // 0x6 - be_t m_h5; // 0x8 - be_t m_h6; // 0xA - be_t m_h7; // 0xC - be_t m_h8; // 0xE - }; + be_t m_h5; + be_t m_h6; }; + union + { + vm::atomic pop1; + vm::atomic pop3; + }; + union + { + vm::atomic push1; + vm::atomic push3; + }; be_t m_size; // 0x10 be_t m_depth; // 0x14 vm::bptr m_buffer; // 0x18 u8 m_bs[4]; // 0x20 be_t m_direction; // 0x24 be_t m_v1; // 0x28 - vm::atomic init; // 0x2C + vm::atomic init; // 0x2C be_t m_hs[32]; // 0x30 vm::bptr m_eaSignal; // 0x70 be_t m_v2; // 0x78 be_t m_v3; // 0x7C - volatile u32& m_data() - { - return *reinterpret_cast((u8*)this + 0x2c); - } - - volatile u64& m_push1() - { - return *reinterpret_cast((u8*)this + 0x8); - } - volatile u32& m_push2() { return *reinterpret_cast((u8*)this + 0x30); } - volatile u32& m_push3() - { - return *reinterpret_cast((u8*)this + 0x8); - } - - volatile u64& m_pop1() - { - return *reinterpret_cast((u8*)this + 0x0); - } - volatile u32& m_pop2() { return *reinterpret_cast((u8*)this + 0x50); } - volatile u32& m_pop3() - { - return *reinterpret_cast((u8*)this + 0x0); - } }; static_assert(sizeof(CellSyncLFQueue) == 128, "CellSyncLFQueue: wrong size"); From a4a4e572a0b13c33c41fda40fa71a9a1d02bbaba Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 23 Sep 2014 18:27:18 +0400 Subject: [PATCH 13/24] vm::atomic update, small fixes --- Utilities/GNU.h | 20 ++++ Utilities/SMutex.h | 4 +- rpcs3/Emu/Memory/vm_atomic.h | 11 +- rpcs3/Emu/SysCalls/CB_FUNC.h | 4 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 9 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 130 +++++++++++------------ rpcs3/Emu/SysCalls/Modules/cellSync.h | 48 +++++---- rpcs3/Emu/SysCalls/SC_FUNC.h | 6 +- rpcs3/Emu/SysCalls/lv2/sys_event.cpp | 34 +++--- rpcs3/Emu/SysCalls/lv2/sys_event.h | 2 +- 10 files changed, 145 insertions(+), 123 deletions(-) diff --git a/Utilities/GNU.h b/Utilities/GNU.h index 3cf5d606c5..3581907afc 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -95,6 +95,10 @@ int clock_gettime(int foo, struct timespec *ts); #endif #ifndef InterlockedCompareExchange +static __forceinline uint16_t InterlockedCompareExchange(volatile uint16_t* dest, uint16_t exch, uint16_t comp) +{ + return _InterlockedCompareExchange16((volatile short*)dest, exch, comp); +} static __forceinline uint32_t InterlockedCompareExchange(volatile uint32_t* dest, uint32_t exch, uint32_t comp) { return _InterlockedCompareExchange((volatile long*)dest, exch, comp); @@ -106,6 +110,10 @@ static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest #endif #ifndef InterlockedExchange +static __forceinline uint16_t InterlockedExchange(volatile uint16_t* dest, uint16_t value) +{ + return _InterlockedExchange16((volatile short*)dest, value); +} static __forceinline uint32_t InterlockedExchange(volatile uint32_t* dest, uint32_t value) { return _InterlockedExchange((volatile long*)dest, value); @@ -117,6 +125,10 @@ static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint6 #endif #ifndef InterlockedOr +static __forceinline uint16_t InterlockedOr(volatile uint16_t* dest, uint16_t value) +{ + return _InterlockedOr16((volatile short*)dest, value); +} static __forceinline uint32_t InterlockedOr(volatile uint32_t* dest, uint32_t value) { return _InterlockedOr((volatile long*)dest, value); @@ -128,6 +140,10 @@ static __forceinline uint64_t InterlockedOr(volatile uint64_t* dest, uint64_t va #endif #ifndef InterlockedAnd +static __forceinline uint16_t InterlockedAnd(volatile uint16_t* dest, uint16_t value) +{ + return _InterlockedAnd16((volatile short*)dest, value); +} static __forceinline uint32_t InterlockedAnd(volatile uint32_t* dest, uint32_t value) { return _InterlockedAnd((volatile long*)dest, value); @@ -139,6 +155,10 @@ static __forceinline uint64_t InterlockedAnd(volatile uint64_t* dest, uint64_t v #endif #ifndef InterlockedXor +static __forceinline uint16_t InterlockedXor(volatile uint16_t* dest, uint16_t value) +{ + return _InterlockedXor16((volatile short*)dest, value); +} static __forceinline uint32_t InterlockedXor(volatile uint32_t* dest, uint32_t value) { return _InterlockedXor((volatile long*)dest, value); diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index e62361b304..8258f2ff54 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -33,13 +33,13 @@ public: static const T GetFreeValue() { static const u64 value = free_value; - return (const T&)value; + return (T&)value; } static const T GetDeadValue() { static const u64 value = dead_value; - return (const T&)value; + return (T&)value; } void initialize() diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h index 867a8f0e9d..8f737940fe 100644 --- a/rpcs3/Emu/Memory/vm_atomic.h +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -5,11 +5,17 @@ namespace vm template struct _to_atomic { - static_assert(size == 4 || size == 8, "Invalid atomic type"); + static_assert(size == 2 || size == 4 || size == 8, "Invalid atomic type"); typedef T type; }; + template + struct _to_atomic + { + typedef uint16_t type; + }; + template struct _to_atomic { @@ -93,18 +99,21 @@ namespace vm } } + // atomic bitwise logical OR, returns previous data __forceinline const T _or(const T& right) volatile { const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)); return (T&)res; } + // atomic bitwise logical AND, returns previous data __forceinline const T _and(const T& right) volatile { const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)); return (T&)res; } + // atomic bitwise logical XOR, returns previous data __forceinline const T _xor(const T& right) volatile { const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)); diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index d989d13e2f..6d3ab37f40 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -55,7 +55,7 @@ namespace cb_detail template struct _func_arg { - static_assert(f_count <= 12, "TODO: Unsupported stack argument type (float)"); + static_assert(f_count <= 13, "TODO: Unsupported stack argument type (float)"); static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)"); static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_STACK"); @@ -84,7 +84,7 @@ namespace cb_detail const bool is_float = std::is_floating_point::value; const bool is_vector = std::is_same::value; const _func_arg_type t = is_float - ? ((f_count >= 12) ? ARG_STACK : ARG_FLOAT) + ? ((f_count >= 13) ? ARG_STACK : ARG_FLOAT) : (is_vector ? ((v_count >= 12) ? ARG_STACK : ARG_VECTOR) : ((g_count >= 8) ? ARG_STACK : ARG_GENERAL)); const int g = g_count + (is_float || is_vector ? 0 : 1); const int f = f_count + (is_float ? 1 : 0); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 440c2f08f4..0039cfd3b1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -39,10 +39,9 @@ s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr po return CELL_SPURS_CORE_ERROR_STAT; } - u32 unk1 = 0; -#ifdef PRX_DEBUG - unk1 = cb_call(GetCurrentPPUThread(), libsre + 0x10900, libsre_rtoc); -#endif + s32 sdk_ver; + assert(process_get_sdk_version(process_getpid(), sdk_ver) == CELL_OK); + if (sdk_ver == -1) sdk_ver = 0x460000; u8 _port = 0x3f; u8 port_start = 0x10; @@ -54,7 +53,7 @@ s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr po { return CELL_SPURS_CORE_ERROR_INVAL; } - if (unk1 <= 0x17ffff && _port > 0xf) + if (sdk_ver <= 0x17ffff && _port > 0xf) { return CELL_SPURS_CORE_ERROR_PERM; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 793115d879..84e1bf877f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -844,7 +844,8 @@ void syncLFQueueInit(vm::ptr queue, vm::ptr buffer, u32 siz queue->m_depth = depth; queue->m_buffer = buffer; queue->m_direction = direction; - *queue->m_hs = {}; + *queue->m_hs1 = {}; + *queue->m_hs2 = {}; queue->m_eaSignal = eaSignal; if (direction == CELL_SYNC_QUEUE_ANY2ANY) @@ -857,10 +858,8 @@ void syncLFQueueInit(vm::ptr queue, vm::ptr buffer, u32 siz //m_bs[2] //m_bs[3] queue->m_v1 = -1; - queue->m_hs[0] = -1; - queue->m_hs[16] = -1; - queue->m_v2 = 0; - queue->m_v3 = 0; + queue->push2.write_relaxed({ be_t::make(-1) }); + queue->pop2.write_relaxed({ be_t::make(-1) }); } else { @@ -871,9 +870,12 @@ void syncLFQueueInit(vm::ptr queue, vm::ptr buffer, u32 siz queue->m_bs[2] = -1; queue->m_bs[3] = -1; queue->m_v1 = 0; - queue->m_v2 = 0; // written as u64 - queue->m_v3 = 0; + queue->push2.write_relaxed({}); + queue->pop2.write_relaxed({}); } + + queue->m_v2 = 0; + queue->m_eq_id = 0; } s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) @@ -1082,14 +1084,9 @@ s32 syncLFQueueGetPushPointer(vm::ptr queue, s32& pointer, u32 } } - u32 eq = (u32)queue->m_v3; // 0x7c - sys_event_data event; - assert(0); - // TODO: sys_event_queue_receive (event data is not used), assert if error returned + assert(sys_event_queue_receive(queue->m_eq_id, {}, 0) == CELL_OK); var1 = 1; } - - assert(0); } s32 _cellSyncLFQueueGetPushPointer(vm::ptr queue, vm::ptr> pointer, u32 isBlocking, u32 useEventQueue) @@ -1134,14 +1131,13 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, while (true) { - const u32 old_data = InterlockedCompareExchange(&queue->m_push2(), 0, 0); - CellSyncLFQueue new_; - new_.m_push2() = old_data; + const auto old = queue->push2.read_sync(); + auto push2 = old; const auto old2 = queue->push3.read_relaxed(); - auto push = old2; + auto push3 = old2; - s32 var1 = pointer - (u16)push.m_h5; + s32 var1 = pointer - (u16)push3.m_h5; if (var1 < 0) { var1 += depth * 2; @@ -1163,7 +1159,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, { var9_ = 1 << var9_; } - s32 var9 = ~(var9_ | (u16)push.m_h6); + s32 var9 = ~(var9_ | (u16)push3.m_h6); // count leading zeros in u16 { u16 v = var9; @@ -1176,7 +1172,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, } } - s32 var5 = (s32)(u16)push.m_h6 | var9_; + s32 var5 = (s32)(u16)push3.m_h6 | var9_; if (var9 & 0x30) { var5 = 0; @@ -1186,13 +1182,13 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, var5 <<= var9; } - s32 var3 = (u16)push.m_h5 + var9; + s32 var3 = (u16)push3.m_h5 + var9; if (var3 >= depth * 2) { var3 -= depth * 2; } - u16 pack = new_.m_hs[0]; // three packed 5-bit fields + u16 pack = push2.pack; // three packed 5-bit fields s32 var4 = ((pack >> 10) & 0x1f) - ((pack >> 5) & 0x1f); if (var4 < 0) @@ -1230,23 +1226,23 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, var12 = (var12 + 1) << 10; } - new_.m_hs[0] = (pack & 0x83ff) | var12; - var6 = (u16)queue->m_hs[1 + 2 * var11]; + push2.pack = (pack & 0x83ff) | var12; + var6 = (u16)queue->m_hs1[var11]; } else { var6 = -1; } - push.m_h5 = (u16)var3; - push.m_h6 = (u16)var5; + push3.m_h5 = (u16)var3; + push3.m_h6 = (u16)var5; - if (InterlockedCompareExchange(&queue->m_push2(), new_.m_push2(), old_data) == old_data) + if (queue->push2.compare_and_swap_test(old, push2)) { assert(var2 + var4 < 16); if (var6 != -1) { - bool exch = queue->push3.compare_and_swap_test(old2, push); + bool exch = queue->push3.compare_and_swap_test(old2, push3); assert(exch); if (exch) { @@ -1256,10 +1252,10 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, } else { - pack = queue->m_hs[0]; + pack = queue->push2.read_relaxed().pack; if ((pack & 0x1f) == ((pack >> 10) & 0x1f)) { - if (queue->push3.compare_and_swap_test(old2, push)) + if (queue->push3.compare_and_swap_test(old2, push3)) { return CELL_OK; } @@ -1267,8 +1263,6 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, } } } - - assert(0); } s32 _cellSyncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) @@ -1480,14 +1474,9 @@ s32 syncLFQueueGetPopPointer(vm::ptr queue, s32& pointer, u32 i } } - u32 eq = (u32)queue->m_v3; // 0x7c - sys_event_data event; - assert(0); - // TODO: sys_event_queue_receive (event data is not used), assert if error returned + assert(sys_event_queue_receive(queue->m_eq_id, {}, 0) == CELL_OK); var1 = 1; } - - assert(0); } s32 _cellSyncLFQueueGetPopPointer(vm::ptr queue, vm::ptr> pointer, u32 isBlocking, u32 arg4, u32 useEventQueue) @@ -1532,14 +1521,13 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c while (true) { - const u32 old_data = InterlockedCompareExchange(&queue->m_pop2(), 0, 0); - CellSyncLFQueue new_; - new_.m_pop2() = old_data; + const auto old = queue->pop2.read_sync(); + auto pop2 = old; const auto old2 = queue->pop3.read_relaxed(); - auto pop = old2; + auto pop3 = old2; - s32 var1 = pointer - (u16)pop.m_h1; + s32 var1 = pointer - (u16)pop3.m_h1; if (var1 < 0) { var1 += depth * 2; @@ -1561,7 +1549,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c { var9_ = 1 << var9_; } - s32 var9 = ~(var9_ | (u16)pop.m_h2); + s32 var9 = ~(var9_ | (u16)pop3.m_h2); // count leading zeros in u16 { u16 v = var9; @@ -1574,7 +1562,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c } } - s32 var5 = (s32)(u16)pop.m_h2 | var9_; + s32 var5 = (s32)(u16)pop3.m_h2 | var9_; if (var9 & 0x30) { var5 = 0; @@ -1584,13 +1572,13 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c var5 <<= var9; } - s32 var3 = (u16)pop.m_h1 + var9; + s32 var3 = (u16)pop3.m_h1 + var9; if (var3 >= depth * 2) { var3 -= depth * 2; } - u16 pack = new_.m_hs[16]; // three packed 5-bit fields + u16 pack = pop2.pack; // three packed 5-bit fields s32 var4 = ((pack >> 10) & 0x1f) - ((pack >> 5) & 0x1f); if (var4 < 0) @@ -1632,18 +1620,18 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c var12 = (var12 + 1) << 10; } - new_.m_hs[0] = (pack & 0x83ff) | var12; - var6 = (u16)queue->m_hs[17 + 2 * var11]; + pop2.pack = (pack & 0x83ff) | var12; + var6 = (u16)queue->m_hs2[var11]; } - pop.m_h1 = (u16)var3; - pop.m_h2 = (u16)var5; + pop3.m_h1 = (u16)var3; + pop3.m_h2 = (u16)var5; - if (InterlockedCompareExchange(&queue->m_pop2(), new_.m_pop2(), old_data) == old_data) + if (queue->pop2.compare_and_swap_test(old, pop2)) { if (var6 != -1) { - bool exch = queue->pop3.compare_and_swap_test(old2, pop); + bool exch = queue->pop3.compare_and_swap_test(old2, pop3); assert(exch); if (exch) { @@ -1653,10 +1641,10 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c } else { - pack = queue->m_hs[16]; + pack = queue->pop2.read_relaxed().pack; if ((pack & 0x1f) == ((pack >> 10) & 0x1f)) { - if (queue->pop3.compare_and_swap_test(old2, pop)) + if (queue->pop3.compare_and_swap_test(old2, pop3)) { return CELL_OK; } @@ -1664,8 +1652,6 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c } } } - - assert(0); } s32 _cellSyncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) @@ -1793,7 +1779,6 @@ s32 cellSyncLFQueueClear(vm::ptr queue) return CELL_SYNC_ERROR_ALIGN; } - // TODO: optimize if possible while (true) { const auto old = queue->pop1.read_sync(); @@ -1804,7 +1789,7 @@ s32 cellSyncLFQueueClear(vm::ptr queue) s32 var1, var2; if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) { - var1 = var2 = (u16)queue->m_hs[16]; + var1 = var2 = (u16)queue->pop2.read_relaxed().pack; } else { @@ -1844,7 +1829,6 @@ s32 cellSyncLFQueueSize(vm::ptr queue, vm::ptr> size) return CELL_SYNC_ERROR_ALIGN; } - // TODO: optimize if possible while (true) { const auto old = queue->pop3.read_sync(); @@ -1865,8 +1849,6 @@ s32 cellSyncLFQueueSize(vm::ptr queue, vm::ptr> size) return CELL_OK; } } - - assert(0); } s32 cellSyncLFQueueDepth(vm::ptr queue, vm::ptr> depth) @@ -1937,28 +1919,36 @@ s32 cellSyncLFQueueGetEntrySize(vm::ptr queue, vm::ptr> spus, u32 num, vm::ptr queue) +s32 syncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) { - // TODO - assert(0); +#ifdef PRX_DEBUG + return cb_call, u32, vm::ptr>(GetCurrentPPUThread(), libsre + 0x19A8, libsre_rtoc, + spus, num, queue); +#else + assert(!syncLFQueueAttachLv2EventQueue); return CELL_OK; +#endif } -s32 _cellSyncLFQueueAttachLv2EventQueue(vm::ptr> spus, u32 num, vm::ptr queue) +s32 _cellSyncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) { cellSync->Todo("_cellSyncLFQueueAttachLv2EventQueue(spus_addr=0x%x, num=%d, queue_addr=0x%x)", spus.addr(), num, queue.addr()); return syncLFQueueAttachLv2EventQueue(spus, num, queue); } -s32 syncLFQueueDetachLv2EventQueue(vm::ptr> spus, u32 num, vm::ptr queue) +s32 syncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) { - // TODO - assert(0); +#ifdef PRX_DEBUG + return cb_call, u32, vm::ptr>(GetCurrentPPUThread(), libsre + 0x1DA0, libsre_rtoc, + spus, num, queue); +#else + assert(!syncLFQueueDetachLv2EventQueue); return CELL_OK; +#endif } -s32 _cellSyncLFQueueDetachLv2EventQueue(vm::ptr> spus, u32 num, vm::ptr queue) +s32 _cellSyncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) { cellSync->Todo("_cellSyncLFQueueDetachLv2EventQueue(spus_addr=0x%x, num=%d, queue_addr=0x%x)", spus.addr(), num, queue.addr()); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index 4a8086624b..62ce8551f2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -105,6 +105,11 @@ struct CellSyncLFQueue be_t m_h4; }; + struct pop2_t + { + be_t pack; + }; + struct pop3_t { be_t m_h1; @@ -119,6 +124,11 @@ struct CellSyncLFQueue be_t m_h8; }; + struct push2_t + { + be_t pack; + }; + struct push3_t { be_t m_h5; @@ -127,36 +137,28 @@ struct CellSyncLFQueue union { - vm::atomic pop1; + vm::atomic pop1; // 0x0 vm::atomic pop3; }; union { - vm::atomic push1; + vm::atomic push1; // 0x8 vm::atomic push3; }; - be_t m_size; // 0x10 - be_t m_depth; // 0x14 + be_t m_size; // 0x10 + be_t m_depth; // 0x14 vm::bptr m_buffer; // 0x18 - u8 m_bs[4]; // 0x20 + u8 m_bs[4]; // 0x20 be_t m_direction; // 0x24 - be_t m_v1; // 0x28 - vm::atomic init; // 0x2C - be_t m_hs[32]; // 0x30 + be_t m_v1; // 0x28 + vm::atomic init; // 0x2C + vm::atomic push2; // 0x30 + be_t m_hs1[15]; // 0x32 + vm::atomic pop2; // 0x50 + be_t m_hs2[15]; // 0x52 vm::bptr m_eaSignal; // 0x70 - be_t m_v2; // 0x78 - be_t m_v3; // 0x7C - - volatile u32& m_push2() - { - return *reinterpret_cast((u8*)this + 0x30); - } - - volatile u32& m_pop2() - { - return *reinterpret_cast((u8*)this + 0x50); - } - + be_t m_v2; // 0x78 + be_t m_eq_id; // 0x7C }; static_assert(sizeof(CellSyncLFQueue) == 128, "CellSyncLFQueue: wrong size"); @@ -178,5 +180,5 @@ s32 syncLFQueueGetPopPointer(vm::ptr queue, s32& pointer, u32 i s32 syncLFQueueGetPopPointer2(vm::ptr queue, s32& pointer, u32 isBlocking, u32 useEventQueue); s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, const std::function fpSendSignal, u32 noQueueFull); s32 syncLFQueueCompletePopPointer2(vm::ptr queue, s32 pointer, const 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); +s32 syncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue); +s32 syncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue); diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index fbb3e676eb..28c4ef0582 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -57,14 +57,14 @@ namespace detail template struct bind_arg { - static_assert(f_count <= 12, "TODO: Unsupported stack argument type (float)"); + static_assert(f_count <= 13, "TODO: Unsupported stack argument type (float)"); static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)"); static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_STACK"); static __forceinline T func(PPUThread& CPU) { // TODO: check stack argument displacement - const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 12, 0) + std::max(v_count - 12, 0)); + const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 13, 0) + std::max(v_count - 12, 0)); return (T&)res; } }; @@ -144,7 +144,7 @@ namespace detail const bool is_float = std::is_floating_point::value; const bool is_vector = std::is_same::value; const bind_arg_type t = is_float - ? ((f_count >= 12) ? ARG_STACK : ARG_FLOAT) + ? ((f_count >= 13) ? ARG_STACK : ARG_FLOAT) : (is_vector ? ((v_count >= 12) ? ARG_STACK : ARG_VECTOR) : ((g_count >= 8) ? ARG_STACK : ARG_GENERAL)); const int g = g_count + (is_float || is_vector ? 0 : 1); const int f = f_count + (is_float ? 1 : 0); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp index d34acadf30..e2f76cb351 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp @@ -151,10 +151,11 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_arra return CELL_OK; } -s32 sys_event_queue_receive(u32 equeue_id, vm::ptr event, u64 timeout) +s32 sys_event_queue_receive(u32 equeue_id, vm::ptr dummy_event, u64 timeout) { - sys_event.Log("sys_event_queue_receive(equeue_id=%d, event_addr=0x%x, timeout=%lld)", - equeue_id, event.addr(), timeout); + // dummy_event argument is ignored, data returned in registers + sys_event.Log("sys_event_queue_receive(equeue_id=%d, dummy_event_addr=0x%x, timeout=%lld)", + equeue_id, dummy_event.addr(), timeout); EventQueue* eq; if (!Emu.GetIdManager().GetIDData(equeue_id, eq)) @@ -193,19 +194,20 @@ s32 sys_event_queue_receive(u32 equeue_id, vm::ptr event, u64 ti } } case SMR_SIGNAL: - { - eq->events.pop(*event); - eq->owner.unlock(tid); - sys_event.Log(" *** event received: source=0x%llx, d1=0x%llx, d2=0x%llx, d3=0x%llx", - (u64)event->source, (u64)event->data1, (u64)event->data2, (u64)event->data3); - /* passing event data in registers */ - PPUThread& t = GetCurrentPPUThread(); - t.GPR[4] = event->source; - t.GPR[5] = event->data1; - t.GPR[6] = event->data2; - t.GPR[7] = event->data3; - return CELL_OK; - } + { + sys_event_data event; + eq->events.pop(event); + eq->owner.unlock(tid); + sys_event.Log(" *** event received: source=0x%llx, d1=0x%llx, d2=0x%llx, d3=0x%llx", + (u64)event.source, (u64)event.data1, (u64)event.data2, (u64)event.data3); + /* passing event data in registers */ + PPUThread& t = GetCurrentPPUThread(); + t.GPR[4] = event.source; + t.GPR[5] = event.data1; + t.GPR[6] = event.data2; + t.GPR[7] = event.data3; + return CELL_OK; + } case SMR_FAILED: break; default: eq->sq.invalidate(tid); return CELL_ECANCELED; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.h b/rpcs3/Emu/SysCalls/lv2/sys_event.h index 59d2796e0b..16b99d7ec9 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.h @@ -223,7 +223,7 @@ u32 event_queue_create(u32 protocol, s32 type, u64 name_u64, u64 event_queue_key // SysCalls s32 sys_event_queue_create(vm::ptr> equeue_id, vm::ptr attr, u64 event_queue_key, s32 size); s32 sys_event_queue_destroy(u32 equeue_id, s32 mode); -s32 sys_event_queue_receive(u32 equeue_id, vm::ptr event, u64 timeout); +s32 sys_event_queue_receive(u32 equeue_id, vm::ptr dummy_event, u64 timeout); s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_array, s32 size, vm::ptr> number); s32 sys_event_queue_drain(u32 event_queue_id); From 05a7466a5a9befa604af267cf497519dbee6a6c1 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 24 Sep 2014 22:44:26 +0400 Subject: [PATCH 14/24] m_custom_task thread member --- rpcs3/Emu/Cell/PPUThread.cpp | 16 ++++++- rpcs3/Emu/Cell/PPUThread.h | 13 +++--- rpcs3/Emu/Cell/SPUThread.cpp | 42 ++++++++++++++--- rpcs3/Emu/Cell/SPUThread.h | 3 ++ rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 55 ++++++++++++----------- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 27 +++++++---- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 3 +- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h | 2 +- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 3 +- rpcs3/Emu/SysCalls/lv2/sys_spu.h | 2 +- 10 files changed, 113 insertions(+), 53 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 03e49b8aa0..6cb0686122 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -187,7 +187,7 @@ u64 PPUThread::FastCall2(u32 addr, u32 rtoc) LR = Emu.m_ppu_thr_stop; SetCurrentNamedThread(this); - Task(); + CPUThread::Task(); m_status = old_status; PC = old_PC; @@ -202,4 +202,16 @@ u64 PPUThread::FastCall2(u32 addr, u32 rtoc) void PPUThread::FastStop() { m_status = Stopped; -} \ No newline at end of file +} + +void PPUThread::Task() +{ + if (m_custom_task) + { + m_custom_task(*this); + } + else + { + CPUThread::Task(); + } +} diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 0fb4e2867b..34021a2d6a 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -470,9 +470,6 @@ struct FPRdouble class PPUThread : public PPCThread { -public: - u32 owned_mutexes; - public: PPCdouble FPR[32]; //Floating Point Register FPSCRhdr FPSCR; //Floating Point Status and Control Register @@ -556,6 +553,9 @@ public: u64 R_ADDR; // reservation address u64 R_VALUE; // reservation value (BE) + u32 owned_mutexes; + std::function m_custom_task; + public: PPUThread(); virtual ~PPUThread(); @@ -785,17 +785,18 @@ public: public: virtual void InitRegs(); + virtual void Task(); u64 GetStackArg(s32 i); u64 FastCall2(u32 addr, u32 rtoc); void FastStop(); - - virtual void DoReset() override; virtual void DoRun() override; + +protected: + virtual void DoReset() override; virtual void DoPause() override; virtual void DoResume() override; virtual void DoStop() override; -protected: virtual void Step() override { //if(++cycle > 20) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index f7dc30ca73..0ff0af3c6a 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -50,7 +50,15 @@ void SPUThread::Task() const int round = std::fegetround(); std::fesetround(FE_TOWARDZERO); - CPUThread::Task(); + if (m_custom_task) + { + m_custom_task(*this); + } + else + { + CPUThread::Task(); + } + if (std::fegetround() != FE_TOWARDZERO) { LOG_ERROR(Log::SPU, "Rounding mode has changed(%d)", std::fegetround()); @@ -68,7 +76,7 @@ void SPUThread::DoReset() void SPUThread::InitRegs() { - GPR[1]._u32[3] = 0x40000 - 120; + GPR[1]._u32[3] = 0x3FFF0; // initial stack frame pointer cfg.Reset(); @@ -138,6 +146,23 @@ void SPUThread::DoClose() } } +void SPUThread::FastCall(u32 ls_addr) +{ + // doesn't touch thread status (instead of PPUThread::FastCall2); + // can't be called from another thread (because it doesn't make sense); + // FastStop-like routine is not defined (TODO); + + auto old_PC = PC; + auto old_stack = GPR[1]; // only saved and restored (may be wrong) + + PC = ls_addr; + + CPUThread::Task(); + + PC = old_PC; + GPR[1] = old_stack; +} + void SPUThread::WriteSNR(bool number, u32 value) { if (cfg.value & ((u64)1 << (u64)number)) @@ -272,7 +297,7 @@ void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFC auto rec = vm::ptr::make(dmac.ls_offset + list_addr + i * 8); u32 size = rec->ts; - if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8) + if (!(rec->s.ToBE() & se16(0x8000)) && size < 16 && size != 1 && size != 2 && size != 4 && size != 8) { LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size); result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; @@ -280,13 +305,16 @@ void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFC } u32 addr = rec->ea; - ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size); - if (Ini.HLELogging.GetValue() || rec->s) + if (size) + ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size); + + if (Ini.HLELogging.GetValue() || rec->s.ToBE()) LOG_NOTICE(Log::SPU, "*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)", i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf)); - lsa += std::max(size, (u32)16); + if (size) + lsa += std::max(size, (u32)16); if (rec->s.ToBE() & se16(0x8000)) { @@ -454,7 +482,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) } else // store unconditional { - if (R_ADDR) + if (R_ADDR) // may be wrong { m_events |= SPU_EVENT_LR; } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index ca17de309d..eba9dd6a0c 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -503,6 +503,8 @@ public: void WriteLS64 (const u32 lsa, const u64& data) const { vm::write64 (lsa + m_offset, data); } void WriteLS128(const u32 lsa, const u128& data) const { vm::write128(lsa + m_offset, data); } + std::function m_custom_task; + public: SPUThread(CPUThreadType type = CPU_THREAD_SPU); virtual ~SPUThread(); @@ -560,6 +562,7 @@ public: public: virtual void InitRegs(); virtual void Task(); + void FastCall(u32 ls_addr); protected: virtual void DoReset(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 0039cfd3b1..6c4ef20f46 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -44,8 +44,8 @@ s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr po if (sdk_ver == -1) sdk_ver = 0x460000; u8 _port = 0x3f; - u8 port_start = 0x10; u64 port_mask = 0; + if (isDynamic == 0) { _port = *port; @@ -53,18 +53,18 @@ s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr po { return CELL_SPURS_CORE_ERROR_INVAL; } - if (sdk_ver <= 0x17ffff && _port > 0xf) + if (sdk_ver > 0x17ffff && _port > 0xf) { return CELL_SPURS_CORE_ERROR_PERM; } - port_start = _port; } - for (u32 i = port_start + 1; i < _port; i++) + for (u32 i = isDynamic ? 0x10 : _port; i <= _port; i++) { - port_mask |= 1ull << (i - 1); + port_mask |= 1ull << (i); } + assert(port_mask); // zero mask will return CELL_EINVAL if (s32 res = sys_spu_thread_group_connect_event_all_threads(spurs->m.spuTG, queue, port_mask, port)) { if (res == CELL_EISCONN) @@ -78,7 +78,6 @@ s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr po { spurs->m.spups |= be_t::make(1ull << *port); // atomic bitwise or } - return CELL_OK; #endif } @@ -141,7 +140,7 @@ s64 spursInit( return CELL_SPURS_CORE_ERROR_PERM; } - const bool isSecond = flags & SAF_SECOND_VERSION; + const bool isSecond = (flags & SAF_SECOND_VERSION) != 0; memset(spurs.get_ptr(), 0, CellSpurs::size1 + isSecond * CellSpurs::size2); spurs->m.revision = revision; spurs->m.sdkVersion = sdkVersion; @@ -198,10 +197,9 @@ s64 spursInit( spurs->m.spuPriority = spuPriority; #ifdef PRX_DEBUG assert(spu_image_import(spurs->m.spuImg, vm::read32(libsre_rtoc - (isSecond ? 0x7E94 : 0x7E98)), 1) == CELL_OK); +#else + spurs->m.spuImg.addr = Memory.Alloc(0x40000, 4096); #endif - //char str1[0x80]; - //memcpy(str1, prefix, prefixSize); // strcpy - //memcpy(str1 + prefixSize, "CellSpursKernelGroup", 21); // strcat s32 tgt = SYS_SPU_THREAD_GROUP_TYPE_NORMAL; if (flags & SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT) @@ -222,10 +220,17 @@ s64 spursInit( spurs->m.spuTG = tg->m_id; name += "CellSpursKernel0"; - for (s32 i = 0; i < nSpus; i++, name[name.size() - 1]++) + for (s32 num = 0; num < nSpus; num++, name[name.size() - 1]++) { - auto spu = spu_thread_initialize(tg, i, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, u64(i) << 32, spurs.addr(), 0, 0); - spurs->m.spus[i] = spu->GetId(); + spurs->m.spus[num] = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, 0, 0, 0, 0, [spurs, num, isSecond](SPUThread& CPU) + { +#ifdef PRX_DEBUG + CPU.GPR[3]._u32[3] = num; + CPU.GPR[4]._u64[1] = spurs.addr(); + return CPU.FastCall(CPU.PC); +#endif + + })->GetId(); } if (flags & SAF_SPU_PRINTF_ENABLED) @@ -261,22 +266,24 @@ s64 spursInit( name = std::string(prefix, prefixSize); - PPUThread* ppu0 = nullptr; + spurs->m.ppu0 = ppu_thread_create(0, 0, ppuPriority, 0x4000, true, false, name + "SpursHdlr0", [spurs](PPUThread& CPU) + { #ifdef PRX_DEBUG - ppu0 = ppu_thread_create(vm::read32(libsre_rtoc - 0x7E60), spurs.addr(), ppuPriority, 0x4000, true, false, name + "SpursHdlr0"); + return cb_call>(CPU, libsre + 0x9214, libsre_rtoc, spurs); #endif - assert(ppu0); - spurs->m.ppu0 = ppu0->GetId(); - PPUThread* ppu1 = nullptr; + })->GetId(); + + spurs->m.ppu1 = ppu_thread_create(0, 0, ppuPriority, 0x8000, true, false, name + "SpursHdlr1", [spurs](PPUThread& CPU) + { #ifdef PRX_DEBUG - ppu1 = ppu_thread_create(vm::read32(libsre_rtoc - 0x7E24), spurs.addr(), ppuPriority, 0x8000, true, false, name + "SpursHdlr1"); + return cb_call>(CPU, libsre + 0xB40C, libsre_rtoc, spurs); #endif - assert(ppu1); - spurs->m.ppu1 = ppu1->GetId(); + + })->GetId(); // enable exception event handler - if (spurs->m.enableEH.compare_and_swap(be_t::make(0), be_t::make(1)).ToBE() == 0) + if (spurs->m.enableEH.compare_and_swap_test(be_t::make(0), be_t::make(1))) { assert(sys_spu_thread_group_connect_event(spurs->m.spuTG, spurs->m.queue, SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION) == CELL_OK); } @@ -291,12 +298,10 @@ s64 spursInit( if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) // initialize system workload { - s32 res; + s32 res = CELL_OK; #ifdef PRX_DEBUG res = cb_call, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x10428, libsre_rtoc, spurs, Memory.RealToVirtualAddr(swlPriority), swlMaxSpu, swlIsPreem); -#else - res = -1; #endif assert(res == CELL_OK); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 84e1bf877f..8f06a48660 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -367,6 +367,7 @@ s32 cellSyncRwmTryRead(vm::ptr rwm, vm::ptr buffer) { return res; } + memcpy(buffer.get_ptr(), rwm->m_buffer.get_ptr(), (u32)rwm->m_size); return rwm->data.atomic_op(CELL_OK, syncRwmReadEndOp); @@ -520,7 +521,8 @@ s32 cellSyncQueuePush(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); + const auto data = queue->data.read_relaxed(); + assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); u32 position; while (queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 @@ -559,7 +561,8 @@ s32 cellSyncQueueTryPush(vm::ptr queue, vm::ptr buffe const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); + const auto data = queue->data.read_relaxed(); + assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); u32 position; if (s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 @@ -610,7 +613,8 @@ s32 cellSyncQueuePop(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); + const auto data = queue->data.read_relaxed(); + assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); u32 position; while (queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 @@ -649,7 +653,8 @@ s32 cellSyncQueueTryPop(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); + const auto data = queue->data.read_relaxed(); + assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); u32 position; if (s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 @@ -694,7 +699,8 @@ s32 cellSyncQueuePeek(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); + const auto data = queue->data.read_relaxed(); + assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); u32 position; while (queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 @@ -730,7 +736,8 @@ s32 cellSyncQueueTryPeek(vm::ptr queue, vm::ptr buffer) const u32 size = (u32)queue->m_size; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); + const auto data = queue->data.read_relaxed(); + assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); u32 position; if (s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32 @@ -759,9 +766,10 @@ s32 cellSyncQueueSize(vm::ptr queue) return CELL_SYNC_ERROR_ALIGN; } - const u32 count = (u32)queue->data.read_relaxed().m_v2 & 0xffffff; + const auto data = queue->data.read_relaxed(); + const u32 count = (u32)data.m_v2 & 0xffffff; const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && count <= depth); + assert(((u32)data.m_v1 & 0xffffff) <= depth && count <= depth); return count; } @@ -780,7 +788,8 @@ s32 cellSyncQueueClear(vm::ptr queue) } const u32 depth = (u32)queue->m_depth; - assert(((u32)queue->data.read_relaxed().m_v1 & 0xffffff) <= depth && ((u32)queue->data.read_relaxed().m_v2 & 0xffffff) <= depth); + const auto data = queue->data.read_relaxed(); + assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth); // TODO: optimize if possible while (queue->data.atomic_op(CELL_OK, [depth](CellSyncQueue::data_t& queue) -> s32 diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index 3e504cffc9..0c33f0e25d 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -147,7 +147,7 @@ s32 sys_ppu_thread_restart(u64 thread_id) return CELL_OK; } -PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, const std::string& name) +PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, const std::string& name, std::function task) { PPUThread& new_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); @@ -159,6 +159,7 @@ PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool i new_thread.m_has_interrupt = false; new_thread.m_is_interrupt = is_interrupt; new_thread.SetName(name); + new_thread.m_custom_task = task; sys_ppu_thread.Notice("*** New PPU Thread [%s] (%s, entry=0x%x): id = %d", name.c_str(), is_interrupt ? "interrupt" : diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h index b5d8540d32..c76c49b461 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h @@ -15,7 +15,7 @@ enum ppu_thread_flags : u64 }; // Aux -PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, const std::string& name); +PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, const std::string& name, std::function task = nullptr); // SysCalls void sys_ppu_thread_exit(PPUThread& CPU, u64 errorcode); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 26909c9408..2f790c5ecf 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -59,7 +59,7 @@ s32 sys_spu_image_open(vm::ptr img, vm::ptr path) return CELL_OK; } -SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4) +SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4, std::function task) { if (option) { @@ -77,6 +77,7 @@ SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image new_thread.SetOffset(spu_offset); new_thread.SetEntry(spu_ep); new_thread.SetName(name); + new_thread.m_custom_task = task; new_thread.Run(); new_thread.GPR[3] = u128::from64(0, a1); new_thread.GPR[4] = u128::from64(0, a2); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.h b/rpcs3/Emu/SysCalls/lv2/sys_spu.h index 526334fe36..203138e8c8 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.h @@ -158,7 +158,7 @@ class SPUThread; // Aux s32 spu_image_import(sys_spu_image& img, u32 src, u32 type); SpuGroupInfo* spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container); -SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4); +SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4, std::function task = nullptr); // SysCalls s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu); From e40776ba79a465b8202cb09beb4bb41012823f7f Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 26 Sep 2014 01:41:35 +0400 Subject: [PATCH 15/24] cellSpursWakeUp, CellSpursWorkloadAttribute +vm_atomic update (8bit type) --- Utilities/GNU.h | 20 + rpcs3/Emu/Memory/vm_atomic.h | 14 +- rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp | 11 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 863 +++++++++++-------- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 57 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 15 +- 6 files changed, 599 insertions(+), 381 deletions(-) diff --git a/Utilities/GNU.h b/Utilities/GNU.h index 3581907afc..fc693a24b3 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -95,6 +95,10 @@ int clock_gettime(int foo, struct timespec *ts); #endif #ifndef InterlockedCompareExchange +static __forceinline uint8_t InterlockedCompareExchange(volatile uint8_t* dest, uint8_t exch, uint8_t comp) +{ + return _InterlockedCompareExchange8((volatile char*)dest, exch, comp); +} static __forceinline uint16_t InterlockedCompareExchange(volatile uint16_t* dest, uint16_t exch, uint16_t comp) { return _InterlockedCompareExchange16((volatile short*)dest, exch, comp); @@ -110,6 +114,10 @@ static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest #endif #ifndef InterlockedExchange +static __forceinline uint8_t InterlockedExchange(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedExchange8((volatile char*)dest, value); +} static __forceinline uint16_t InterlockedExchange(volatile uint16_t* dest, uint16_t value) { return _InterlockedExchange16((volatile short*)dest, value); @@ -125,6 +133,10 @@ static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint6 #endif #ifndef InterlockedOr +static __forceinline uint8_t InterlockedOr(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedOr8((volatile char*)dest, value); +} static __forceinline uint16_t InterlockedOr(volatile uint16_t* dest, uint16_t value) { return _InterlockedOr16((volatile short*)dest, value); @@ -140,6 +152,10 @@ static __forceinline uint64_t InterlockedOr(volatile uint64_t* dest, uint64_t va #endif #ifndef InterlockedAnd +static __forceinline uint8_t InterlockedAnd(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedAnd8((volatile char*)dest, value); +} static __forceinline uint16_t InterlockedAnd(volatile uint16_t* dest, uint16_t value) { return _InterlockedAnd16((volatile short*)dest, value); @@ -155,6 +171,10 @@ static __forceinline uint64_t InterlockedAnd(volatile uint64_t* dest, uint64_t v #endif #ifndef InterlockedXor +static __forceinline uint8_t InterlockedXor(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedXor8((volatile char*)dest, value); +} static __forceinline uint16_t InterlockedXor(volatile uint16_t* dest, uint16_t value) { return _InterlockedXor16((volatile short*)dest, value); diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h index 8f737940fe..7c117ac066 100644 --- a/rpcs3/Emu/Memory/vm_atomic.h +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -5,11 +5,17 @@ namespace vm template struct _to_atomic { - static_assert(size == 2 || size == 4 || size == 8, "Invalid atomic type"); + static_assert(size == 1 || size == 2 || size == 4 || size == 8, "Invalid atomic type"); typedef T type; }; + template + struct _to_atomic + { + typedef uint8_t type; + }; + template struct _to_atomic { @@ -99,21 +105,21 @@ namespace vm } } - // atomic bitwise logical OR, returns previous data + // atomic bitwise OR, returns previous data __forceinline const T _or(const T& right) volatile { const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)); return (T&)res; } - // atomic bitwise logical AND, returns previous data + // atomic bitwise AND, returns previous data __forceinline const T _and(const T& right) volatile { const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)); return (T&)res; } - // atomic bitwise logical XOR, returns previous data + // atomic bitwise XOR, returns previous data __forceinline const T _xor(const T& right) volatile { const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)); diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp index 8df2d3f476..53cf172f63 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp @@ -21,6 +21,7 @@ enum MsgDialogState }; std::atomic g_msg_dialog_state(msgDialogNone); +u64 g_msg_dialog_status; u64 g_msg_dialog_wait_until; u32 g_msg_dialog_progress_bar_count; @@ -100,14 +101,14 @@ int cellMsgDialogOpen2(u32 type, vm::ptr msgString, vm::ptr msgString, vm::ptr s32 + Emu.GetCallbackManager().Register([callback, userData]() -> s32 { - callback((s32)status, userData); + callback((s32)g_msg_dialog_status, userData); return CELL_OK; }); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 6c4ef20f46..5edb2e5731 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -20,68 +20,6 @@ extern u32 libsre; extern u32 libsre_rtoc; #endif -s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated) -{ -#ifdef PRX_DEBUG_XXX - return cb_call, u32, vm::ptr, s32, bool>(GetCurrentPPUThread(), libsre + 0xAE34, libsre_rtoc, - spurs, queue, port, isDynamic, wasCreated); -#else - if (!spurs || !port) - { - return CELL_SPURS_CORE_ERROR_NULL_POINTER; - } - if (spurs.addr() % 128) - { - return CELL_SPURS_CORE_ERROR_ALIGN; - } - if (spurs->m.unk21.ToBE()) - { - return CELL_SPURS_CORE_ERROR_STAT; - } - - s32 sdk_ver; - assert(process_get_sdk_version(process_getpid(), sdk_ver) == CELL_OK); - if (sdk_ver == -1) sdk_ver = 0x460000; - - u8 _port = 0x3f; - u64 port_mask = 0; - - if (isDynamic == 0) - { - _port = *port; - if (_port > 0x3f) - { - return CELL_SPURS_CORE_ERROR_INVAL; - } - if (sdk_ver > 0x17ffff && _port > 0xf) - { - return CELL_SPURS_CORE_ERROR_PERM; - } - } - - for (u32 i = isDynamic ? 0x10 : _port; i <= _port; i++) - { - port_mask |= 1ull << (i); - } - - assert(port_mask); // zero mask will return CELL_EINVAL - if (s32 res = sys_spu_thread_group_connect_event_all_threads(spurs->m.spuTG, queue, port_mask, port)) - { - if (res == CELL_EISCONN) - { - return CELL_SPURS_CORE_ERROR_BUSY; - } - return res; - } - - if (!wasCreated) - { - spurs->m.spups |= be_t::make(1ull << *port); // atomic bitwise or - } - return CELL_OK; -#endif -} - s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptr port, s32 size, u64 name_u64) { #ifdef PRX_DEBUG_XXX @@ -90,7 +28,8 @@ s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptrToLE(); return res; -#else +#endif + queue_id = event_queue_create(SYS_SYNC_FIFO, SYS_PPU_QUEUE, name_u64, 0, size); if (!queue_id) { @@ -99,7 +38,6 @@ s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptr, u32, u32, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc, spurs, revision, sdkVersion, nSpus, spuPriority, ppuPriority, flags, Memory.RealToVirtualAddr(prefix), prefixSize, container, Memory.RealToVirtualAddr(swlPriority), swlMaxSpu, swlIsPreem); -#else +#endif // SPURS initialization (asserts should actually rollback and return the error instead) if (!spurs) @@ -307,12 +245,10 @@ s64 spursInit( } else if (flags & SAF_EXIT_IF_NO_WORK) // wakeup { -#ifdef PRX_DEBUG - return cb_call>(GetCurrentPPUThread(), libsre + 0x84D8, libsre_rtoc, spurs); -#endif + return spursWakeUp(spurs); } + return CELL_OK; -#endif } s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork) @@ -322,7 +258,7 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x8480, libsre_rtoc); -#else +#endif return spursInit( spurs, 0, @@ -337,7 +273,6 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 nullptr, 0, 0); -#endif } s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptr attr) @@ -346,7 +281,7 @@ s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptr spurs, vm::ptrm.swlPriority, attr->m.swlMaxSpu, attr->m.swlIsPreem); -#endif } s64 cellSpursInitializeWithAttribute2(vm::ptr spurs, vm::ptr attr) @@ -383,7 +317,7 @@ s64 cellSpursInitializeWithAttribute2(vm::ptr spurs, vm::ptr spurs, vm::ptrm.swlPriority, attr->m.swlMaxSpu, attr->m.swlIsPreem); -#endif } s64 _cellSpursAttributeInitialize(vm::ptr attr, u32 revision, u32 sdkVersion, u32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork) @@ -421,7 +354,7 @@ s64 _cellSpursAttributeInitialize(vm::ptr attr, u32 revision #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x72CC, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -439,7 +372,6 @@ s64 _cellSpursAttributeInitialize(vm::ptr attr, u32 revision attr->m.ppuPriority = ppuPriority; attr->m.exitIfNoWork = exitIfNoWork; return CELL_OK; -#endif } s64 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr attr, u32 container) @@ -448,7 +380,7 @@ s64 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x6FF8, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -466,7 +398,6 @@ s64 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr attr->m.container = container; attr->m.flags |= SAF_SPU_MEMORY_CONTAINER_SET; return CELL_OK; -#endif } s64 cellSpursAttributeSetNamePrefix(vm::ptr attr, vm::ptr prefix, u32 size) @@ -475,7 +406,7 @@ s64 cellSpursAttributeSetNamePrefix(vm::ptr attr, vm::ptr attr, vm::ptrm.prefix, prefix.get_ptr(), size); attr->m.prefixSize = size; return CELL_OK; -#endif } s64 cellSpursAttributeEnableSpuPrintfIfAvailable(vm::ptr attr) @@ -502,7 +432,7 @@ s64 cellSpursAttributeEnableSpuPrintfIfAvailable(vm::ptr att #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x7150, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -514,7 +444,6 @@ s64 cellSpursAttributeEnableSpuPrintfIfAvailable(vm::ptr att attr->m.flags |= SAF_SPU_PRINTF_ENABLED; return CELL_OK; -#endif } s64 cellSpursAttributeSetSpuThreadGroupType(vm::ptr attr, s32 type) @@ -523,7 +452,7 @@ s64 cellSpursAttributeSetSpuThreadGroupType(vm::ptr attr, s3 #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x70C8, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -550,7 +479,6 @@ s64 cellSpursAttributeSetSpuThreadGroupType(vm::ptr attr, s3 return CELL_SPURS_CORE_ERROR_INVAL; } return CELL_OK; -#endif } s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm::ptr priority, u32 maxSpu, vm::ptr isPreemptible) @@ -560,7 +488,7 @@ s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm: #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xF410, libsre_rtoc); -#else +#endif if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -609,7 +537,6 @@ s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm: } } return CELL_SPURS_CORE_ERROR_INVAL; -#endif } s64 cellSpursFinalize(vm::ptr spurs) @@ -618,7 +545,100 @@ s64 cellSpursFinalize(vm::ptr spurs) #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x8568, libsre_rtoc); +#endif + return CELL_OK; +} + +s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated) +{ +#ifdef PRX_DEBUG_XXX + return cb_call, u32, vm::ptr, s32, bool>(GetCurrentPPUThread(), libsre + 0xAE34, libsre_rtoc, + spurs, queue, port, isDynamic, wasCreated); +#endif + if (!spurs || !port) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + if (spurs->m.unk21.ToBE()) + { + return CELL_SPURS_CORE_ERROR_STAT; + } + + s32 sdk_ver; + assert(process_get_sdk_version(process_getpid(), sdk_ver) == CELL_OK); + if (sdk_ver == -1) sdk_ver = 0x460000; + + u8 _port = 0x3f; + u64 port_mask = 0; + + if (isDynamic == 0) + { + _port = *port; + if (_port > 0x3f) + { + return CELL_SPURS_CORE_ERROR_INVAL; + } + if (sdk_ver > 0x17ffff && _port > 0xf) + { + return CELL_SPURS_CORE_ERROR_PERM; + } + } + + for (u32 i = isDynamic ? 0x10 : _port; i <= _port; i++) + { + port_mask |= 1ull << (i); + } + + assert(port_mask); // zero mask will return CELL_EINVAL + if (s32 res = sys_spu_thread_group_connect_event_all_threads(spurs->m.spuTG, queue, port_mask, port)) + { + if (res == CELL_EISCONN) + { + return CELL_SPURS_CORE_ERROR_BUSY; + } + return res; + } + + if (!wasCreated) + { + spurs->m.spups |= be_t::make(1ull << *port); // atomic bitwise or + } + return CELL_OK; +} + +s64 cellSpursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic) +{ + cellSpurs->Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=%d, port_addr=0x%x, isDynamic=%d)", + spurs.addr(), queue, port.addr(), isDynamic); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0xAFE0, libsre_rtoc); +#endif + return spursAttachLv2EventQueue(spurs, queue, port, isDynamic, false); +} + +s64 cellSpursDetachLv2EventQueue(vm::ptr spurs, u8 port) +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=%d)", spurs.addr(), port); + return GetCurrentPPUThread().FastCall2(libsre + 0xB144, libsre_rtoc); #else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursGetSpuGuid() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xEFB0, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); return CELL_OK; #endif } @@ -689,29 +709,6 @@ s64 cellSpursSetPreemptionVictimHints(vm::ptr spurs, vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic) -{ - cellSpurs->Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=%d, port_addr=0x%x, isDynamic=%d)", - spurs.addr(), queue, port.addr(), isDynamic); - -#ifdef PRX_DEBUG_XXX - return GetCurrentPPUThread().FastCall2(libsre + 0xAFE0, libsre_rtoc); -#else - return spursAttachLv2EventQueue(spurs, queue, port, isDynamic, false); -#endif -} - -s64 cellSpursDetachLv2EventQueue(vm::ptr spurs, u8 port) -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=0x%x)", spurs.addr(), port); - return GetCurrentPPUThread().FastCall2(libsre + 0xB144, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - s64 cellSpursEnableExceptionEventHandler(vm::ptr spurs, bool flag) { #ifdef PRX_DEBUG @@ -757,6 +754,399 @@ s64 cellSpursGetInfo(vm::ptr spurs, vm::ptr info) #endif } +s64 spursWakeUp(vm::ptr spurs) +{ +#ifdef PRX_DEBUG + return cb_call>(GetCurrentPPUThread(), libsre + 0x84D8, libsre_rtoc, spurs); +#endif + if (!spurs) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (spurs->m.unk21.ToBE()) + { + return CELL_SPURS_POLICY_MODULE_ERROR_STAT; + } + + spurs->m.unk19[0].exchange(1); + if (spurs->m.unk19[1].read_sync()) + { + assert(sys_lwmutex_lock(vm::ptr::make(spurs.addr() + 0xdb0), 0) == 0); + assert(sys_lwcond_signal(vm::ptr::make(spurs.addr() + 0xdc8)) == 0); + assert(sys_lwmutex_unlock(vm::ptr::make(spurs.addr() + 0xdb0)) == 0); + } + return CELL_OK; +} + +s64 cellSpursWakeUp(vm::ptr spurs) +{ + cellSpurs->Warning("%s(spurs_addr=0x%x)", __FUNCTION__, spurs.addr()); + + return spursWakeUp(spurs); +} + +s32 spursAddWorkload( + vm::ptr spurs, + vm::ptr wid, + vm::ptr pm, + u32 size, + u64 data, + const u8 priorityTable[], + u32 minContention, + u32 maxContention, + const char* nameClass, + const char* nameInstance, + vm::ptr hook, + vm::ptr hookArg) +{ +#ifdef PRX_DEBUG + return cb_call, vm::ptr, vm::ptr, u32, u64, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x96EC, libsre_rtoc, + spurs, wid, pm, size, data, Memory.RealToVirtualAddr(priorityTable), minContention, maxContention, + Memory.RealToVirtualAddr(nameClass), Memory.RealToVirtualAddr(nameInstance), hook.addr(), hookArg.addr()); +#endif + + return CELL_OK; +} + +s64 cellSpursAddWorkload( + vm::ptr spurs, + vm::ptr wid, + vm::ptr pm, + u32 size, + u64 data, + vm::ptr priorityTable, + u32 minContention, + u32 maxContention) +{ + cellSpurs->Warning("%s(spurs_addr=0x%x, wid_addr=0x%x, pm_addr=0x%x, size=0x%x, data=0x%llx, priorityTable_addr=0x%x, minContention=0x%x, maxContention=0x%x)", + __FUNCTION__, spurs.addr(), wid.addr(), pm.addr(), size, data, priorityTable.addr(), minContention, maxContention); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x9ED0, libsre_rtoc); +#endif + + return spursAddWorkload( + spurs, + wid, + pm, + size, + data, + *priorityTable, + minContention, + maxContention, + nullptr, + nullptr, + {}, + {}); +} + +s64 _cellSpursWorkloadAttributeInitialize( + vm::ptr attr, + u32 revision, + u32 sdkVersion, + vm::ptr pm, + u32 size, + u64 data, + vm::ptr priorityTable, + u32 minContention, + u32 maxContention) +{ + cellSpurs->Warning("%s(attr_addr=0x%x, revision=%d, sdkVersion=0x%x, pm_addr=0x%x, size=0x%x, data=0x%llx, priorityTable_addr=0x%x, minContention=0x%x, maxContention=0x%x)", + __FUNCTION__, attr.addr(), revision, sdkVersion, pm.addr(), size, data, priorityTable.addr(), minContention, maxContention); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x9F08, libsre_rtoc); +#endif + if (!attr) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (!pm) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (pm.addr() % 16) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (minContention == 0 || *(u64*)*priorityTable & 0xf0f0f0f0f0f0f0f0ull) // check if some priority > 15 + { + return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; + } + + memset(attr.get_ptr(), 0, CellSpursWorkloadAttribute::size); + attr->m.revision = revision; + attr->m.sdkVersion = sdkVersion; + attr->m.pm = pm; + attr->m.size = size; + attr->m.data = data; + *(u64*)attr->m.priority = *(u64*)*priorityTable; + attr->m.minContention = minContention; + attr->m.maxContention = maxContention; + return CELL_OK; +} + +s64 cellSpursWorkloadAttributeSetName(vm::ptr attr, vm::ptr nameClass, vm::ptr nameInstance) +{ + cellSpurs->Warning("%s(attr_addr=0x%x, nameClass_addr=0x%x, nameInstance_addr=0x%x)", __FUNCTION__, attr.addr(), nameClass.addr(), nameInstance.addr()); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x9664, libsre_rtoc); +#endif + if (!attr) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + + attr->m.nameClass = nameClass; + attr->m.nameInstance = nameInstance; + return CELL_OK; +} + +s64 cellSpursWorkloadAttributeSetShutdownCompletionEventHook(vm::ptr attr, vm::ptr hook, vm::ptr arg) +{ + cellSpurs->Warning("%s(attr_addr=0x%x, hook_addr=0x%x, arg=0x%x)", __FUNCTION__, attr.addr(), hook.addr(), arg.addr()); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x96A4, libsre_rtoc); +#endif + if (!attr || !hook) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + + attr->m.hook = hook; + attr->m.hookArg = arg; + return CELL_OK; +} + +s64 cellSpursAddWorkloadWithAttribute(vm::ptr spurs, vm::ptr wid, vm::ptr attr) +{ + cellSpurs->Warning("%s(spurs_addr=0x%x, wid_addr=0x%x, attr_addr=0x%x)", __FUNCTION__, spurs.addr(), wid.addr(), attr.addr()); + +#ifdef PRX_DEBUG_XXX + return GetCurrentPPUThread().FastCall2(libsre + 0x9E14, libsre_rtoc); +#endif + if (!attr) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (attr->m.revision != be_t::make(1)) + { + return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; + } + + return spursAddWorkload( + spurs, + wid, + vm::ptr::make(attr->m.pm.addr()), + attr->m.size, + attr->m.data, + attr->m.priority, + attr->m.minContention, + attr->m.maxContention, + attr->m.nameClass.get_ptr(), + attr->m.nameInstance.get_ptr(), + vm::ptr::make(attr->m.hook.addr()), + vm::ptr::make(attr->m.hookArg.addr())); +} + +s64 cellSpursRemoveWorkload() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA414, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursWaitForWorkloadShutdown() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA20C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursShutdownWorkload() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA060, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 _cellSpursWorkloadFlagReceiver() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xF158, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursGetWorkloadFlag() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xEC00, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursSendWorkloadSignal() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA658, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursGetWorkloadData() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA78C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursReadyCountStore() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xAB2C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursReadyCountAdd() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA868, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursReadyCountCompareAndSwap() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xA9CC, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursReadyCountSwap() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xAC34, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursRequestIdleSpu() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xAD88, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursGetWorkloadInfo() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xE70C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 _cellSpursWorkloadFlagReceiver2() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xF298, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursSetExceptionEventHandler() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xDB54, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + +s64 cellSpursUnsetExceptionEventHandler() +{ +#ifdef PRX_DEBUG + cellSpurs->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libsre + 0xD77C, libsre_rtoc); +#else + UNIMPLEMENTED_FUNC(cellSpurs); + return CELL_OK; +#endif +} + s64 _cellSpursEventFlagInitialize(vm::ptr spurs, vm::ptr taskset, vm::ptr eventFlag, u32 flagClearMode, u32 flagDirection) { #ifdef PRX_DEBUG @@ -1552,28 +1942,6 @@ s64 cellSpursTasksetGetSpursAddress() #endif } -s64 cellSpursSetExceptionEventHandler() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xDB54, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursUnsetExceptionEventHandler() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xD77C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - s64 cellSpursGetTasksetInfo() { #ifdef PRX_DEBUG @@ -1695,237 +2063,6 @@ s64 cellSpursJobChainGetError() #endif } -s64 cellSpursWorkloadAttributeSetName() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x9664, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursWorkloadAttributeSetShutdownCompletionEventHook() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x96A4, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursAddWorkloadWithAttribute() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x9E14, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursRemoveWorkload() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA414, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursWaitForWorkloadShutdown() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA20C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursAddWorkload() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x9ED0, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursWakeUp(vm::ptr spurs) -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x84D8, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursShutdownWorkload() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA060, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 _cellSpursWorkloadFlagReceiver() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xF158, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursGetWorkloadFlag() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xEC00, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursReadyCountStore() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xAB2C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 _cellSpursWorkloadAttributeInitialize() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0x9F08, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursSendWorkloadSignal() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA658, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursGetWorkloadData() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA78C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursReadyCountAdd() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA868, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursReadyCountCompareAndSwap() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xA9CC, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursReadyCountSwap() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xAC34, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursRequestIdleSpu() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xAD88, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursGetWorkloadInfo() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xE70C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 cellSpursGetSpuGuid() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xEFB0, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - -s64 _cellSpursWorkloadFlagReceiver2() -{ -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); - return GetCurrentPPUThread().FastCall2(libsre + 0xF298, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; -#endif -} - s64 cellSpursGetJobPipelineInfo() { #ifdef PRX_DEBUG diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index d3ab987c2d..404a3ed463 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -17,6 +17,27 @@ enum CELL_SPURS_CORE_ERROR_NULL_POINTER = 0x80410711, }; +// +enum +{ + CELL_SPURS_POLICY_MODULE_ERROR_AGAIN = 0x80410801, + CELL_SPURS_POLICY_MODULE_ERROR_INVAL = 0x80410802, + CELL_SPURS_POLICY_MODULE_ERROR_NOSYS = 0x80410803, + CELL_SPURS_POLICY_MODULE_ERROR_NOMEM = 0x80410804, + CELL_SPURS_POLICY_MODULE_ERROR_SRCH = 0x80410805, + CELL_SPURS_POLICY_MODULE_ERROR_NOENT = 0x80410806, + CELL_SPURS_POLICY_MODULE_ERROR_NOEXEC = 0x80410807, + CELL_SPURS_POLICY_MODULE_ERROR_DEADLK = 0x80410808, + CELL_SPURS_POLICY_MODULE_ERROR_PERM = 0x80410809, + CELL_SPURS_POLICY_MODULE_ERROR_BUSY = 0x8041080A, + CELL_SPURS_POLICY_MODULE_ERROR_ABORT = 0x8041080C, + CELL_SPURS_POLICY_MODULE_ERROR_FAULT = 0x8041080D, + CELL_SPURS_POLICY_MODULE_ERROR_CHILD = 0x8041080E, + CELL_SPURS_POLICY_MODULE_ERROR_STAT = 0x8041080F, + CELL_SPURS_POLICY_MODULE_ERROR_ALIGN = 0x80410810, + CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER = 0x80410811, +}; + // Task return codes. enum { @@ -207,7 +228,7 @@ struct CellSpurs u8 unknown3[0xD5C - 0xD54]; be_t queue; // 0xD5C be_t port; // 0xD60 - be_t unk19; // 0xD64 + vm::atomic unk19[4]; // 0xD64 (used in wakeup) vm::atomic enableEH; // 0xD68 be_t unk21; // 0xD6C sys_spu_image spuImg; // 0xD70 @@ -239,6 +260,37 @@ struct CellSpurs typedef CellSpurs CellSpurs2; +typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); + +struct CellSpursWorkloadAttribute +{ + static const uint align = 8; + static const uint size = 512; + + union + { + // raw data + u8 _u8[size]; + + // real data + struct + { + be_t revision; + be_t sdkVersion; + vm::bptr pm; + be_t size; + be_t data; + u8 priority[8]; + be_t minContention; + be_t maxContention; + vm::bptr nameClass; + vm::bptr nameInstance; + vm::bptr hook; + vm::bptr hookArg; + } m; + }; +}; + struct CellSpursEventFlag { SPURSManagerEventFlag *eventFlag; @@ -435,3 +487,6 @@ struct CellSpursTaskBinInfo be_t __reserved__; CellSpursTaskLsPattern lsPattern; }; + +s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated); +s64 spursWakeUp(vm::ptr spurs); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 8f06a48660..f647f6c871 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -892,7 +892,7 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 #ifdef PRX_DEBUG_XXX return cb_caller, vm::ptr, u32, u32, CellSyncQueueDirection, vm::ptr>::call(GetCurrentPPUThread(), libsre + 0x205C, libsre_rtoc, queue, buffer, size, depth, direction, eaSignal); -#else +#endif if (!queue) { @@ -991,7 +991,6 @@ s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u3 // prx: sync queue->init.read_sync(); return CELL_OK; -#endif } s32 cellSyncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) @@ -1933,10 +1932,10 @@ s32 syncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr, u32, vm::ptr>(GetCurrentPPUThread(), libsre + 0x19A8, libsre_rtoc, spus, num, queue); -#else - assert(!syncLFQueueAttachLv2EventQueue); - return CELL_OK; #endif + + assert(!"syncLFQueueAttachLv2EventQueue"); + return CELL_OK; } s32 _cellSyncLFQueueAttachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) @@ -1951,10 +1950,10 @@ s32 syncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr, u32, vm::ptr>(GetCurrentPPUThread(), libsre + 0x1DA0, libsre_rtoc, spus, num, queue); -#else - assert(!syncLFQueueDetachLv2EventQueue); - return CELL_OK; #endif + + assert(!"syncLFQueueDetachLv2EventQueue"); + return CELL_OK; } s32 _cellSyncLFQueueDetachLv2EventQueue(vm::ptr spus, u32 num, vm::ptr queue) From ae17ef4d68a2413aeb637006cd4553dbe655f63d Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 27 Sep 2014 22:49:33 +0400 Subject: [PATCH 16/24] vm::atomic -> atomic_t --- Utilities/GNU.h | 34 +++++ Utilities/SMutex.h | 6 +- rpcs3/Emu/Memory/atomic_type.h | 174 ++++++++++++++++++++++ rpcs3/Emu/Memory/vm.h | 2 +- rpcs3/Emu/Memory/vm_atomic.h | 172 --------------------- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 101 +++++++++++-- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 85 ++++++++--- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 30 +--- rpcs3/Emu/SysCalls/Modules/cellSync.h | 24 +-- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h | 2 +- rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp | 8 +- rpcs3/Emu/SysCalls/lv2/sys_spinlock.h | 8 +- rpcs3/emucore.vcxproj | 2 +- rpcs3/emucore.vcxproj.filters | 2 +- 15 files changed, 394 insertions(+), 258 deletions(-) create mode 100644 rpcs3/Emu/Memory/atomic_type.h delete mode 100644 rpcs3/Emu/Memory/vm_atomic.h diff --git a/Utilities/GNU.h b/Utilities/GNU.h index fc693a24b3..b1bcbfb982 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -188,3 +188,37 @@ static __forceinline uint64_t InterlockedXor(volatile uint64_t* dest, uint64_t v return _InterlockedXor64((volatile long long*)dest, value); } #endif + +static __forceinline uint32_t cntlz32(uint32_t arg) +{ +#if defined(__GNUG__) + return __builtin_clzl(arg); +#else + unsigned long res; + if (!_BitScanReverse(&res, arg)) + { + return 32; + } + else + { + return res ^ 31; + } +#endif +} + +static __forceinline uint64_t cntlz64(uint64_t arg) +{ +#if defined(__GNUG__) + return __builtin_clzll(arg); +#else + unsigned long res; + if (!_BitScanReverse64(&res, arg)) + { + return 64; + } + else + { + return res ^ 63; + } +#endif +} diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index 8258f2ff54..88d22d7a68 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -1,5 +1,5 @@ #pragma once -#include "Emu/Memory/vm_atomic.h" +#include "Emu/Memory/atomic_type.h" bool SM_IsAborted(); void SM_Sleep(); @@ -25,9 +25,9 @@ template > class SMutexBase { - static_assert(sizeof(T) == sizeof(vm::atomic_le), "Invalid SMutexBase type"); + static_assert(sizeof(T) == sizeof(atomic_le_t), "Invalid SMutexBase type"); T owner; - typedef vm::atomic_le AT; + typedef atomic_le_t AT; public: static const T GetFreeValue() diff --git a/rpcs3/Emu/Memory/atomic_type.h b/rpcs3/Emu/Memory/atomic_type.h new file mode 100644 index 0000000000..3334e748fa --- /dev/null +++ b/rpcs3/Emu/Memory/atomic_type.h @@ -0,0 +1,174 @@ +#pragma once + +template +struct _to_atomic +{ + static_assert(size == 1 || size == 2 || size == 4 || size == 8, "Invalid atomic type"); + + typedef T type; +}; + +template +struct _to_atomic +{ + typedef uint8_t type; +}; + +template +struct _to_atomic +{ + typedef uint16_t type; +}; + +template +struct _to_atomic +{ + typedef uint32_t type; +}; + +template +struct _to_atomic +{ + typedef uint64_t type; +}; + +template +class _atomic_base +{ + typedef typename _to_atomic::type atomic_type; + atomic_type data; + +public: + // atomically compare data with cmp, replace with exch if equal, return previous data value anyway + __forceinline const T compare_and_swap(const T& cmp, const T& exch) volatile + { + const atomic_type res = InterlockedCompareExchange(&data, (atomic_type&)(exch), (atomic_type&)(cmp)); + return (T&)res; + } + + // atomically compare data with cmp, replace with exch if equal, return true if data was replaced + __forceinline bool compare_and_swap_test(const T& cmp, const T& exch) volatile + { + return InterlockedCompareExchange(&data, (atomic_type&)(exch), (atomic_type&)(cmp)) == (atomic_type&)(cmp); + } + + // read data with memory barrier + __forceinline const T read_sync() const volatile + { + const atomic_type res = InterlockedCompareExchange(const_cast(&data), 0, 0); + return (T&)res; + } + + // atomically replace data with exch, return previous data value + __forceinline const T exchange(const T& exch) volatile + { + const atomic_type res = InterlockedExchange(&data, (atomic_type&)(exch)); + return (T&)res; + } + + // read data without memory barrier + __forceinline const T read_relaxed() const volatile + { + return (T&)data; + } + + // write data without memory barrier + __forceinline void write_relaxed(const T& value) volatile + { + data = (atomic_type&)(value); + } + + // perform atomic operation on data + template __forceinline void atomic_op(const FT atomic_proc) volatile + { + while (true) + { + const T old = read_relaxed(); + T _new = old; + atomic_proc(_new); // function should accept reference to T type + if (compare_and_swap_test(old, _new)) return; + } + } + + // perform atomic operation on data with special exit condition (if intermediate result != proceed_value) + template __forceinline RT atomic_op(const RT proceed_value, const FT atomic_proc) volatile + { + while (true) + { + const T old = read_relaxed(); + T _new = old; + RT res = (RT)atomic_proc(_new); // function should accept reference to T type and return some value + if (res != proceed_value) return res; + if (compare_and_swap_test(old, _new)) return proceed_value; + } + } + + template __forceinline void direct_op(const FT direct_proc) volatile + { + direct_proc((T&)data); + } + + // atomic bitwise OR, returns previous data + __forceinline const T _or(const T& right) volatile + { + const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)); + return (T&)res; + } + + // atomic bitwise AND, returns previous data + __forceinline const T _and(const T& right) volatile + { + const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)); + return (T&)res; + } + + // atomic bitwise XOR, returns previous data + __forceinline const T _xor(const T& right) volatile + { + const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)); + return (T&)res; + } + + __forceinline const T operator |= (const T& right) volatile + { + const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)) | (atomic_type&)(right); + return (T&)res; + } + + __forceinline const T operator &= (const T& right) volatile + { + const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)) & (atomic_type&)(right); + return (T&)res; + } + + __forceinline const T operator ^= (const T& right) volatile + { + const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)) ^ (atomic_type&)(right); + return (T&)res; + } + +}; + +template struct atomic_le_t : public _atomic_base +{ +}; + +template struct atomic_be_t : public _atomic_base::type> +{ +}; + +namespace ps3 +{ + template struct atomic_t : public atomic_be_t + { + }; +} + +namespace psv +{ + template struct atomic_t : public atomic_le_t + { + }; +} + +using namespace ps3; diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index af24ccf86e..d272df0744 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -205,4 +205,4 @@ namespace vm #include "vm_ref.h" #include "vm_ptr.h" #include "vm_var.h" -#include "vm_atomic.h" +#include "atomic_type.h" diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h deleted file mode 100644 index 7c117ac066..0000000000 --- a/rpcs3/Emu/Memory/vm_atomic.h +++ /dev/null @@ -1,172 +0,0 @@ -#pragma once - -namespace vm -{ - template - struct _to_atomic - { - static_assert(size == 1 || size == 2 || size == 4 || size == 8, "Invalid atomic type"); - - typedef T type; - }; - - template - struct _to_atomic - { - typedef uint8_t type; - }; - - template - struct _to_atomic - { - typedef uint16_t type; - }; - - template - struct _to_atomic - { - typedef uint32_t type; - }; - - template - struct _to_atomic - { - typedef uint64_t type; - }; - - template - class _atomic_base - { - typedef typename _to_atomic::type atomic_type; - atomic_type data; - - public: - // atomically compare data with cmp, replace with exch if equal, return previous data value anyway - __forceinline const T compare_and_swap(const T& cmp, const T& exch) volatile - { - const atomic_type res = InterlockedCompareExchange(&data, (atomic_type&)(exch), (atomic_type&)(cmp)); - return (T&)res; - } - - // atomically compare data with cmp, replace with exch if equal, return true if data was replaced - __forceinline bool compare_and_swap_test(const T& cmp, const T& exch) volatile - { - return InterlockedCompareExchange(&data, (atomic_type&)(exch), (atomic_type&)(cmp)) == (atomic_type&)(cmp); - } - - // read data with memory barrier - __forceinline const T read_sync() const volatile - { - const atomic_type res = InterlockedCompareExchange(const_cast(&data), 0, 0); - return (T&)res; - } - - // atomically replace data with exch, return previous data value - __forceinline const T exchange(const T& exch) volatile - { - const atomic_type res = InterlockedExchange(&data, (atomic_type&)(exch)); - return (T&)res; - } - - // read data without memory barrier - __forceinline const T read_relaxed() const volatile - { - return (T&)data; - } - - // write data without memory barrier - __forceinline void write_relaxed(const T& value) volatile - { - data = (atomic_type&)(value); - } - - // perform atomic operation on data - template __forceinline void atomic_op(const FT atomic_proc) volatile - { - while (true) - { - const T old = read_relaxed(); - T _new = old; - atomic_proc(_new); // function should accept reference to T type - if (compare_and_swap_test(old, _new)) return; - } - } - - // perform atomic operation on data with special exit condition (if intermediate result != proceed_value) - template __forceinline RT atomic_op(const RT proceed_value, const FT atomic_proc) volatile - { - while (true) - { - const T old = read_relaxed(); - T _new = old; - RT res = (RT)atomic_proc(_new); // function should accept reference to T type and return some value - if (res != proceed_value) return res; - if (compare_and_swap_test(old, _new)) return proceed_value; - } - } - - // atomic bitwise OR, returns previous data - __forceinline const T _or(const T& right) volatile - { - const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)); - return (T&)res; - } - - // atomic bitwise AND, returns previous data - __forceinline const T _and(const T& right) volatile - { - const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)); - return (T&)res; - } - - // atomic bitwise XOR, returns previous data - __forceinline const T _xor(const T& right) volatile - { - const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)); - return (T&)res; - } - - __forceinline const T operator |= (const T& right) volatile - { - const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)) | (atomic_type&)(right); - return (T&)res; - } - - __forceinline const T operator &= (const T& right) volatile - { - const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)) & (atomic_type&)(right); - return (T&)res; - } - - __forceinline const T operator ^= (const T& right) volatile - { - const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)) ^ (atomic_type&)(right); - return (T&)res; - } - - }; - - template struct atomic_le : public _atomic_base - { - }; - - template struct atomic_be : public _atomic_base::type> - { - }; - - namespace ps3 - { - template struct atomic : public atomic_be - { - }; - } - - namespace psv - { - template struct atomic : public atomic_le - { - }; - } - - using namespace ps3; -} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 5edb2e5731..6751a5c548 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -92,7 +92,7 @@ s64 spursInit( if (!isSecond) { - spurs->m.unk0 = 0xffff; + spurs->m.wklMask.write_relaxed(be_t::make(0xffff)); } spurs->m.unk6[0xC] = 0; spurs->m.unk6[0xD] = 0; @@ -114,7 +114,7 @@ s64 spursInit( { sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl"); assert(sem && ~sem); // should rollback if semaphore creation failed and return the error - spurs->m.sub1[i].sem = sem; + spurs->m.wklF1[i].sem = sem; } if (isSecond) { @@ -122,7 +122,7 @@ s64 spursInit( { sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl"); assert(sem && ~sem); - spurs->m.sub2[i].sem = sem; + spurs->m.wklF2[i].sem = sem; } } sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuPrv"); @@ -131,7 +131,10 @@ s64 spursInit( spurs->m.unk11 = -1; spurs->m.unk12 = -1; spurs->m.unk13 = 0; - spurs->m.nSpus = nSpus; + spurs->m.x70.direct_op([nSpus](CellSpurs::_sub_x70& x70) + { + x70.nSpus = nSpus; + }); spurs->m.spuPriority = spuPriority; #ifdef PRX_DEBUG assert(spu_image_import(spurs->m.spuImg, vm::read32(libsre_rtoc - (isSecond ? 0x7E94 : 0x7E98)), 1) == CELL_OK); @@ -184,8 +187,11 @@ s64 spursInit( assert(lwmutex_create(spurs->m.mutex, SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, *(u64*)"_spuPrv") == CELL_OK); assert(lwcond_create(spurs->m.cond, spurs->m.mutex, *(u64*)"_spuPrv") == CELL_OK); - spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK) << 7 | (isSecond ? 0x40 : 0); - spurs->m.unk15 = -1; + spurs->m.x70.direct_op([flags, isSecond](CellSpurs::_sub_x70& x70) + { + x70.flags1 = (flags & SAF_EXIT_IF_NO_WORK) << 7 | (isSecond ? 0x40 : 0); + x70.unk7 = -1; + }); spurs->m.unk18 = -1; spurs->_u8[0xD64] = 0; spurs->_u8[0xD65] = 0; @@ -798,16 +804,85 @@ s32 spursAddWorkload( const u8 priorityTable[], u32 minContention, u32 maxContention, - const char* nameClass, - const char* nameInstance, + vm::ptr nameClass, + vm::ptr nameInstance, vm::ptr hook, vm::ptr hookArg) { #ifdef PRX_DEBUG return cb_call, vm::ptr, vm::ptr, u32, u64, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x96EC, libsre_rtoc, spurs, wid, pm, size, data, Memory.RealToVirtualAddr(priorityTable), minContention, maxContention, - Memory.RealToVirtualAddr(nameClass), Memory.RealToVirtualAddr(nameInstance), hook.addr(), hookArg.addr()); + nameClass.addr(), nameInstance.addr(), hook.addr(), hookArg.addr()); #endif + if (!spurs || !wid || !pm) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128 || pm.addr() % 16) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (minContention == 0 || *(u64*)priorityTable & 0xf0f0f0f0f0f0f0f0ull) // check if some priority > 15 + { + return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; + } + if (spurs->m.unk21.ToBE()) + { + return CELL_SPURS_POLICY_MODULE_ERROR_STAT; + } + + u32 wnum; + const u32 wmax = spurs->m.x70.read_relaxed().flags1 & 0x40 ? 0x20 : 0x10; // check isSecond (TODO: check if can be changed) + spurs->m.wklMask.atomic_op([spurs, wmax, &wnum](be_t& value) + { + wnum = cntlz32(~(u32)value); // found empty position + if (wnum < wmax) + { + value |= (u32)(0x80000000ull >> wnum); // set workload bit + } + }); + + *wid = wnum; // store workload id + if (wnum >= wmax) + { + return CELL_SPURS_POLICY_MODULE_ERROR_AGAIN; + } + + if (wnum <= 15) + { + assert((spurs->m.wklA1[wnum] & 0xf) == 0); + assert((spurs->m.wklB1[wnum] & 0xf) == 0); + spurs->m.wklC1[wnum] = 1; + spurs->m.wklD1[wnum] = 0; + spurs->m.wklE1[wnum] = 0; + spurs->m.wklG1[wnum].wklPm = pm; + spurs->m.wklG1[wnum].wklArg = data; + spurs->m.wklG1[wnum].wklSize = size; + spurs->m.wklG1[wnum].wklPriority = *(be_t*)priorityTable; + spurs->m.wklH1[wnum].nameClass = nameClass; + spurs->m.wklH1[wnum].nameInstance = nameInstance; + memset(spurs->m.wklF1[wnum].unk0, 0, 0x18); + // (preserve semaphore id) + memset(spurs->m.wklF1[wnum].unk1, 0, 0x60); + if (hook) + { + spurs->m.wklF1[wnum].hook = hook; + spurs->m.wklF1[wnum].hookArg = hookArg; + } + spurs->m.wklY1[wnum] = 0; + if (spurs->m.x70.read_relaxed().flags1 & 0x40) + { + } + else + { + spurs->m.wklZ1[wnum] = 0; + spurs->m.wklMinCnt[wnum] = minContention > 8 ? 8 : 0; + } + } + else + { + + } return CELL_OK; } @@ -838,8 +913,8 @@ s64 cellSpursAddWorkload( *priorityTable, minContention, maxContention, - nullptr, - nullptr, + {}, + {}, {}, {}); } @@ -965,8 +1040,8 @@ s64 cellSpursAddWorkloadWithAttribute(vm::ptr spurs, vm::ptr wid attr->m.priority, attr->m.minContention, attr->m.maxContention, - attr->m.nameClass.get_ptr(), - attr->m.nameInstance.get_ptr(), + vm::ptr::make(attr->m.nameClass.addr()), + vm::ptr::make(attr->m.nameInstance.addr()), vm::ptr::make(attr->m.hook.addr()), vm::ptr::make(attr->m.hookArg.addr())); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 404a3ed463..db8e50735d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -104,6 +104,8 @@ class SPURSManager; class SPURSManagerEventFlag; class SPURSManagerTaskset; +struct CellSpurs; + enum SpursAttrFlags : u32 { SAF_NONE = 0x0, @@ -158,6 +160,8 @@ struct CellSpursAttribute }; }; +typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); + // Core CellSpurs structures struct CellSpurs { @@ -172,7 +176,11 @@ struct CellSpurs u8 unk0[0x20]; be_t sem; // 0x20 - u8 unk_[0x58]; + u8 unk1[0x8]; + u32 pad; + vm::bptr hook; // 0x30 + vm::bptr hookArg; // 0x38 + u8 unk2[0x40]; }; struct _sub_str2 @@ -187,6 +195,41 @@ struct CellSpurs u8 unk_[0x68]; }; + struct _sub_str3 + { + static const uint size = 0x20; + + vm::bptr wklPm; // policy module + be_t wklArg; // spu argument + be_t wklSize; + be_t wklPriority; + }; + + struct _sub_str4 + { + static const uint size = 0x10; + + vm::bptr nameClass; + vm::bptr nameInstance; + }; + + struct _sub_x70 + { + u8 unk0; + u8 unk1; + u8 unk2; + u8 unk3; + u8 flags1; + u8 unk5; + u8 nSpus; + u8 unk7; + }; + + struct _sub_x78 + { + u64 unk; + }; + union { // raw data @@ -196,26 +239,31 @@ struct CellSpurs // real data struct { - u8 unknown[0x6C]; + u8 wklY1[0x10]; + u8 wklZ1[0x10]; // 0x10 + u8 wklA1[0x10]; // 0x20 + u8 wklB1[0x10]; // 0x30 + u8 wklMinCnt[0x10]; // 0x40 + u8 unknown0[0x6C - 0x50]; be_t unk18; // 0x6C - u8 unk17[4]; // 0x70 - u8 flags1; // 0x74 - u8 unk16; // 0x75 - u8 nSpus; // 0x76 - u8 unk15; // 0x77 - u8 unknown0[0xB0 - 0x78]; - be_t unk0; // 0x0B0 + atomic_t<_sub_x70> x70; // 0x70 + atomic_t<_sub_x78> x78; // 0x78 + u8 wklC1[0x10]; // 0x80 + u8 wklD1[0x10]; // 0x90 + u8 wklE1[0x10]; // 0xA0 + atomic_t wklMask;// 0xB0 u8 unknown2[0xC0 - 0xB4]; - u8 unk6[0x10]; // 0x0C0 (SPU port at 0xc9) + u8 unk6[0x10]; // 0xC0 (SPU port at 0xc9) u8 unknown1[0x100 - 0x0D0]; - _sub_str1 sub1[0x10]; // 0x100 + _sub_str1 wklF1[0x10];// 0x100 be_t unk22; // 0x900 u8 unknown7[0x980 - 0x908]; be_t semPrv; // 0x980 be_t unk11; // 0x988 be_t unk12; // 0x98C be_t unk13; // 0x990 - u8 unknown4[0xD00 - 0x998]; + u8 unknown4[0xB00 - 0x998]; + _sub_str3 wklG1[0x10];// 0xB00 be_t unk7; // 0xD00 be_t unk8; // 0xD08 be_t unk9; // 0xD10 @@ -228,8 +276,8 @@ struct CellSpurs u8 unknown3[0xD5C - 0xD54]; be_t queue; // 0xD5C be_t port; // 0xD60 - vm::atomic unk19[4]; // 0xD64 (used in wakeup) - vm::atomic enableEH; // 0xD68 + atomic_t unk19[4]; // 0xD64 (used in wakeup) + atomic_t enableEH; // 0xD68 be_t unk21; // 0xD6C sys_spu_image spuImg; // 0xD70 be_t flags; // 0xD80 @@ -240,13 +288,14 @@ struct CellSpurs be_t unk5; // 0xD9C be_t revision; // 0xDA0 be_t sdkVersion; // 0xDA4 - vm::atomic spups;// 0xDA8 + atomic_t spups;// 0xDA8 sys_lwmutex_t mutex; // 0xDB0 sys_lwcond_t cond; // 0xDC8 - u8 unknown9[0xF00 - 0xDD0]; + u8 unknown9[0xE00 - 0xDD0]; + _sub_str4 wklH1[0x10];// 0xE00 _sub_str2 sub3; // 0xF00 u8 unknown6[0x1200 - 0xF80]; - _sub_str1 sub2[0x10]; // 0x1200 + _sub_str1 wklF2[0x10];// 0x1200 // ... } m; @@ -260,8 +309,6 @@ struct CellSpurs typedef CellSpurs CellSpurs2; -typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); - struct CellSpursWorkloadAttribute { static const uint align = 8; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index f647f6c871..1c5f4a773a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -1158,7 +1158,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, } s32 var9_ = 15 - var1; - // calculate (1 slw (15 - var1)) + // calculate (u16)(1 slw (15 - var1)) if (var9_ & 0x30) { var9_ = 0; @@ -1167,18 +1167,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, { var9_ = 1 << var9_; } - s32 var9 = ~(var9_ | (u16)push3.m_h6); - // count leading zeros in u16 - { - u16 v = var9; - for (var9 = 0; var9 < 16; var9++) - { - if (v & (1 << (15 - var9))) - { - break; - } - } - } + 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) @@ -1548,7 +1537,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c } s32 var9_ = 15 - var1; - // calculate (1 slw (15 - var1)) + // calculate (u16)(1 slw (15 - var1)) if (var9_ & 0x30) { var9_ = 0; @@ -1557,18 +1546,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c { var9_ = 1 << var9_; } - s32 var9 = ~(var9_ | (u16)pop3.m_h2); - // count leading zeros in u16 - { - u16 v = var9; - for (var9 = 0; var9 < 16; var9++) - { - if (v & (1 << (15 - var9))) - { - break; - } - } - } + s32 var9 = cntlz32((u32)(u16)~(var9_ | (u16)pop3.m_h2)) - 16; // count leading zeros in u16 s32 var5 = (s32)(u16)pop3.m_h2 | var9_; if (var9 & 0x30) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index 62ce8551f2..998418615a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -37,7 +37,7 @@ struct CellSyncMutex be_t m_acq; // acquire order (increased when mutex is locked) }; - vm::atomic data; + atomic_t data; }; static_assert(sizeof(CellSyncMutex) == 4, "CellSyncMutex: wrong size"); @@ -50,7 +50,7 @@ struct CellSyncBarrier be_t m_count; }; - vm::atomic data; + atomic_t data; }; static_assert(sizeof(CellSyncBarrier) == 4, "CellSyncBarrier: wrong size"); @@ -63,7 +63,7 @@ struct CellSyncRwm be_t m_writers; }; - vm::atomic data; + atomic_t data; be_t m_size; vm::bptr m_buffer; }; @@ -78,7 +78,7 @@ struct CellSyncQueue be_t m_v2; }; - vm::atomic data; + atomic_t data; be_t m_size; be_t m_depth; vm::bptr m_buffer; @@ -137,13 +137,13 @@ struct CellSyncLFQueue union { - vm::atomic pop1; // 0x0 - vm::atomic pop3; + atomic_t pop1; // 0x0 + atomic_t pop3; }; union { - vm::atomic push1; // 0x8 - vm::atomic push3; + atomic_t push1; // 0x8 + atomic_t push3; }; be_t m_size; // 0x10 be_t m_depth; // 0x14 @@ -151,10 +151,10 @@ struct CellSyncLFQueue u8 m_bs[4]; // 0x20 be_t m_direction; // 0x24 be_t m_v1; // 0x28 - vm::atomic init; // 0x2C - vm::atomic push2; // 0x30 + atomic_t init; // 0x2C + atomic_t push2; // 0x30 be_t m_hs1[15]; // 0x32 - vm::atomic pop2; // 0x50 + atomic_t pop2; // 0x50 be_t m_hs2[15]; // 0x52 vm::bptr m_eaSignal; // 0x70 be_t m_v2; // 0x78 @@ -163,7 +163,7 @@ struct CellSyncLFQueue static_assert(sizeof(CellSyncLFQueue) == 128, "CellSyncLFQueue: wrong size"); -s32 syncMutexInitialize(vm::ptr> mutex); +s32 syncMutexInitialize(vm::ptr mutex); s32 syncBarrierInitialize(vm::ptr barrier, u16 total_count); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index 0c33f0e25d..688109de37 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -211,7 +211,7 @@ s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 return CELL_OK; } -void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init) +void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init) { sys_ppu_thread.Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, init_addr=0x%x)", once_ctrl.addr(), init.addr()); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h index c76c49b461..923ef045fe 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h @@ -30,6 +30,6 @@ s32 sys_ppu_thread_get_stack_information(PPUThread& CPU, u32 info_addr); s32 sys_ppu_thread_stop(u64 thread_id); s32 sys_ppu_thread_restart(u64 thread_id); s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::ptr threadname); -void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init); +void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init); s32 sys_ppu_thread_get_id(PPUThread& CPU, vm::ptr> thread_id); s32 sys_ppu_thread_rename(u64 thread_id, vm::ptr name); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp index 0598dcc654..36dc03fb3c 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp @@ -7,7 +7,7 @@ SysCallBase sys_spinlock("sys_spinlock"); -void sys_spinlock_initialize(vm::ptr> lock) +void sys_spinlock_initialize(vm::ptr> lock) { sys_spinlock.Log("sys_spinlock_initialize(lock_addr=0x%x)", lock.addr()); @@ -15,7 +15,7 @@ void sys_spinlock_initialize(vm::ptr> lock) lock->exchange(be_t::make(0)); } -void sys_spinlock_lock(vm::ptr> lock) +void sys_spinlock_lock(vm::ptr> lock) { sys_spinlock.Log("sys_spinlock_lock(lock_addr=0x%x)", lock.addr()); @@ -39,7 +39,7 @@ void sys_spinlock_lock(vm::ptr> lock) } } -s32 sys_spinlock_trylock(vm::ptr> lock) +s32 sys_spinlock_trylock(vm::ptr> lock) { sys_spinlock.Log("sys_spinlock_trylock(lock_addr=0x%x)", lock.addr()); @@ -52,7 +52,7 @@ s32 sys_spinlock_trylock(vm::ptr> lock) return CELL_OK; } -void sys_spinlock_unlock(vm::ptr> lock) +void sys_spinlock_unlock(vm::ptr> lock) { sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.addr()); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h index 5102d7d588..42a2bb5a6c 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h @@ -1,7 +1,7 @@ #pragma once // SysCalls -void sys_spinlock_initialize(vm::ptr> lock); -void sys_spinlock_lock(vm::ptr> lock); -s32 sys_spinlock_trylock(vm::ptr> lock); -void sys_spinlock_unlock(vm::ptr> lock); +void sys_spinlock_initialize(vm::ptr> lock); +void sys_spinlock_lock(vm::ptr> lock); +s32 sys_spinlock_trylock(vm::ptr> lock); +void sys_spinlock_unlock(vm::ptr> lock); diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index e46932a9d3..439d865c40 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -311,7 +311,7 @@ - + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 573ebd2fed..27371a0d22 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1219,7 +1219,7 @@ Emu\SysCalls - + Emu\Memory From c53a822c4e0c04af6a01da3f6380c7aaf23a3e83 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 28 Sep 2014 23:10:13 +0400 Subject: [PATCH 17/24] spursAddWorkload --- rpcs3/Emu/Memory/atomic_type.h | 37 ++++++++ rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 115 +++++++++++++++++++---- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 35 ++++--- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 15 +-- 4 files changed, 161 insertions(+), 41 deletions(-) diff --git a/rpcs3/Emu/Memory/atomic_type.h b/rpcs3/Emu/Memory/atomic_type.h index 3334e748fa..35ebf639bd 100644 --- a/rpcs3/Emu/Memory/atomic_type.h +++ b/rpcs3/Emu/Memory/atomic_type.h @@ -103,6 +103,36 @@ public: } } + // perform atomic operation on data with additional memory barrier + template __forceinline void atomic_op_sync(const FT atomic_proc) volatile + { + T old = read_sync(); + while (true) + { + T _new = old; + atomic_proc(_new); // function should accept reference to T type + const T val = compare_and_swap(old, _new); + if ((atomic_type&)val == (atomic_type&)old) return; + old = val; + } + } + + // perform atomic operation on data with additional memory barrier and special exit condition (if intermediate result != proceed_value) + template __forceinline RT atomic_op_sync(const RT proceed_value, const FT atomic_proc) volatile + { + T old = read_sync(); + while (true) + { + T _new = old; + RT res = (RT)atomic_proc(_new); // function should accept reference to T type and return some value + if (res != proceed_value) return res; + const T val = compare_and_swap(old, _new); + if ((atomic_type&)val == (atomic_type&)old) return proceed_value; + old = val; + } + } + + // perform non-atomic operation on data directly without memory barriers template __forceinline void direct_op(const FT direct_proc) volatile { direct_proc((T&)data); @@ -122,6 +152,13 @@ public: return (T&)res; } + // atomic bitwise AND NOT (inverts right argument), returns previous data + __forceinline const T _and_not(const T& right) volatile + { + const atomic_type res = InterlockedAnd(&data, ~(atomic_type&)(right)); + return (T&)res; + } + // atomic bitwise XOR, returns previous data __forceinline const T _xor(const T& right) volatile { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 6751a5c548..efc7c91bf3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -92,7 +92,7 @@ s64 spursInit( if (!isSecond) { - spurs->m.wklMask.write_relaxed(be_t::make(0xffff)); + spurs->m.wklMsk1.write_relaxed(be_t::make(0xffff)); } spurs->m.unk6[0xC] = 0; spurs->m.unk6[0xD] = 0; @@ -762,7 +762,7 @@ s64 cellSpursGetInfo(vm::ptr spurs, vm::ptr info) s64 spursWakeUp(vm::ptr spurs) { -#ifdef PRX_DEBUG +#ifdef PRX_DEBUG_XXX return cb_call>(GetCurrentPPUThread(), libsre + 0x84D8, libsre_rtoc, spurs); #endif if (!spurs) @@ -809,7 +809,7 @@ s32 spursAddWorkload( vm::ptr hook, vm::ptr hookArg) { -#ifdef PRX_DEBUG +#ifdef PRX_DEBUG_XXX return cb_call, vm::ptr, vm::ptr, u32, u64, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x96EC, libsre_rtoc, spurs, wid, pm, size, data, Memory.RealToVirtualAddr(priorityTable), minContention, maxContention, nameClass.addr(), nameInstance.addr(), hook.addr(), hookArg.addr()); @@ -833,7 +833,7 @@ s32 spursAddWorkload( u32 wnum; const u32 wmax = spurs->m.x70.read_relaxed().flags1 & 0x40 ? 0x20 : 0x10; // check isSecond (TODO: check if can be changed) - spurs->m.wklMask.atomic_op([spurs, wmax, &wnum](be_t& value) + spurs->m.wklMsk1.atomic_op([spurs, wmax, &wnum](be_t& value) { wnum = cntlz32(~(u32)value); // found empty position if (wnum < wmax) @@ -848,10 +848,11 @@ s32 spursAddWorkload( return CELL_SPURS_POLICY_MODULE_ERROR_AGAIN; } + u32 index = wnum % 0x10; if (wnum <= 15) { - assert((spurs->m.wklA1[wnum] & 0xf) == 0); - assert((spurs->m.wklB1[wnum] & 0xf) == 0); + assert((spurs->m.wklA[wnum] & 0xf) == 0); + assert((spurs->m.wklB[wnum] & 0xf) == 0); spurs->m.wklC1[wnum] = 1; spurs->m.wklD1[wnum] = 0; spurs->m.wklE1[wnum] = 0; @@ -861,29 +862,111 @@ s32 spursAddWorkload( spurs->m.wklG1[wnum].wklPriority = *(be_t*)priorityTable; spurs->m.wklH1[wnum].nameClass = nameClass; spurs->m.wklH1[wnum].nameInstance = nameInstance; - memset(spurs->m.wklF1[wnum].unk0, 0, 0x18); - // (preserve semaphore id) + memset(spurs->m.wklF1[wnum].unk0, 0, 0x18); // clear struct preserving semaphore id memset(spurs->m.wklF1[wnum].unk1, 0, 0x60); if (hook) { spurs->m.wklF1[wnum].hook = hook; spurs->m.wklF1[wnum].hookArg = hookArg; + spurs->m.wklE1[wnum] |= 2; } - spurs->m.wklY1[wnum] = 0; - if (spurs->m.x70.read_relaxed().flags1 & 0x40) + spurs->m.wklZ1[wnum] = 0; + if ((spurs->m.x70.read_relaxed().flags1 & 0x40) == 0) { - } - else - { - spurs->m.wklZ1[wnum] = 0; - spurs->m.wklMinCnt[wnum] = minContention > 8 ? 8 : 0; + spurs->m.wklZ2[wnum] = 0; + spurs->m.wklMinCnt[wnum] = minContention > 8 ? 8 : minContention; } } else { - + assert((spurs->m.wklA[index] & 0xf0) == 0); + assert((spurs->m.wklB[index] & 0xf0) == 0); + spurs->m.wklC2[index] = 1; + spurs->m.wklD2[index] = 0; + spurs->m.wklE2[index] = 0; + spurs->m.wklG2[index].wklPm = pm; + spurs->m.wklG2[index].wklArg = data; + spurs->m.wklG2[index].wklSize = size; + spurs->m.wklG2[index].wklPriority = *(be_t*)priorityTable; + spurs->m.wklH2[index].nameClass = nameClass; + spurs->m.wklH2[index].nameInstance = nameInstance; + memset(spurs->m.wklF2[index].unk0, 0, 0x18); // clear struct preserving semaphore id + memset(spurs->m.wklF2[index].unk1, 0, 0x60); + if (hook) + { + spurs->m.wklF2[index].hook = hook; + spurs->m.wklF2[index].hookArg = hookArg; + spurs->m.wklE2[index] |= 2; + } + spurs->m.wklZ2[index] = 0; } + u32 pos = ((~wnum * 8) | (wnum / 4)) & 0x1c; + spurs->m.wklMaxCnt[index / 4].atomic_op([pos, maxContention](be_t& v) + { + v &= ~(0xf << pos); + v |= (maxContention > 8 ? 8 : maxContention) << pos; + }); + + if (wnum <= 15) + { + spurs->m.x70._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag1 + } + else + { + spurs->m.x78._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag2 + } + + spurs->m.x70.atomic_op([wnum](CellSpurs::_sub_x70& x70) + { + if (x70.unk7 == wnum) + { + x70.unk7 = 0xff; + } + }); + + u32 res_wkl; + spurs->m.wklMsk2.atomic_op_sync([spurs, wnum, &res_wkl](be_t& v) + { + CellSpurs::_sub_str3& wkl = wnum <= 15 ? spurs->m.wklG1[wnum] : spurs->m.wklG2[wnum & 0xf]; + const u32 mask = v.ToLE() & ~(0x80000000 >> wnum); + res_wkl = 0; + + for (u32 i = 0, m = 0x80000000, k = 0; i < 32; i++, m >>= 1) + { + if (mask & m) + { + CellSpurs::_sub_str3& current = i <= 15 ? spurs->m.wklG1[i] : spurs->m.wklG2[i & 0xf]; + if (current.wklPm.addr() == wkl.wklPm.addr()) + { + // if a workload with identical policy module found + res_wkl = current.wklCopy.read_relaxed(); + break; + } + else + { + k |= 0x80000000 >> current.wklCopy.read_relaxed(); + res_wkl = cntlz32(~k); + } + } + } + + wkl.wklCopy.exchange((u8)res_wkl); + }); + assert(res_wkl <= 31); + + if (wnum <= 15) + { + spurs->m.wklC1[wnum] = 2; + } + else + { + spurs->m.wklC2[index] = 2; + } + + spurs->m.unk23[5].exchange(-1); // write 0xff byte at 0xbd + spurs->m.x70._and_not({ {}, -1 }); // clear byte at 0x72 + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index db8e50735d..47ab8d975f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -177,7 +177,6 @@ struct CellSpurs u8 unk0[0x20]; be_t sem; // 0x20 u8 unk1[0x8]; - u32 pad; vm::bptr hook; // 0x30 vm::bptr hookArg; // 0x38 u8 unk2[0x40]; @@ -202,6 +201,7 @@ struct CellSpurs vm::bptr wklPm; // policy module be_t wklArg; // spu argument be_t wklSize; + atomic_t wklCopy; be_t wklPriority; }; @@ -215,9 +215,8 @@ struct CellSpurs struct _sub_x70 { - u8 unk0; - u8 unk1; - u8 unk2; + be_t wklFlag1; // 0x70 + u8 unk2; // 0x72 u8 unk3; u8 flags1; u8 unk5; @@ -227,7 +226,8 @@ struct CellSpurs struct _sub_x78 { - u64 unk; + be_t wklFlag2; + u8 unk[6]; }; union @@ -239,22 +239,26 @@ struct CellSpurs // real data struct { - u8 wklY1[0x10]; - u8 wklZ1[0x10]; // 0x10 - u8 wklA1[0x10]; // 0x20 - u8 wklB1[0x10]; // 0x30 + u8 wklZ1[0x10]; // 0x0 + u8 wklZ2[0x10]; // 0x10 + u8 wklA[0x10]; // 0x20 + u8 wklB[0x10]; // 0x30 u8 wklMinCnt[0x10]; // 0x40 - u8 unknown0[0x6C - 0x50]; + atomic_t wklMaxCnt[4]; // 0x50 + u8 unknown0[0x6C - 0x60]; be_t unk18; // 0x6C atomic_t<_sub_x70> x70; // 0x70 atomic_t<_sub_x78> x78; // 0x78 u8 wklC1[0x10]; // 0x80 u8 wklD1[0x10]; // 0x90 u8 wklE1[0x10]; // 0xA0 - atomic_t wklMask;// 0xB0 - u8 unknown2[0xC0 - 0xB4]; + atomic_t wklMsk1;// 0xB0 + atomic_t wklMsk2;// 0xB4 + atomic_t unk23[8];// 0xB8 u8 unk6[0x10]; // 0xC0 (SPU port at 0xc9) - u8 unknown1[0x100 - 0x0D0]; + u8 wklC2[0x10]; // 0xD0 + u8 wklD2[0x10]; // 0xE0 + u8 wklE2[0x10]; // 0xF0 _sub_str1 wklF1[0x10];// 0x100 be_t unk22; // 0x900 u8 unknown7[0x980 - 0x908]; @@ -294,9 +298,10 @@ struct CellSpurs u8 unknown9[0xE00 - 0xDD0]; _sub_str4 wklH1[0x10];// 0xE00 _sub_str2 sub3; // 0xF00 - u8 unknown6[0x1200 - 0xF80]; + u8 unknown6[0x1000 - 0xF80]; + _sub_str3 wklG2[0x10];// 0x1000 _sub_str1 wklF2[0x10];// 0x1200 - // ... + _sub_str4 wklH2[0x10];// 0x1A00 } m; // alternative implementation diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 1c5f4a773a..5592521d18 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -112,8 +112,7 @@ s32 cellSyncMutexUnlock(vm::ptr mutex) return CELL_SYNC_ERROR_ALIGN; } - mutex->data.read_sync(); - mutex->data.atomic_op([](CellSyncMutex::data_t& mutex) + mutex->data.atomic_op_sync([](CellSyncMutex::data_t& mutex) { mutex.m_rel++; }); @@ -178,8 +177,7 @@ s32 cellSyncBarrierNotify(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - barrier->data.read_sync(); - while (barrier->data.atomic_op(CELL_OK, syncBarrierTryNotifyOp)) + while (barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryNotifyOp)) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack if (Emu.IsStopped()) @@ -204,8 +202,7 @@ s32 cellSyncBarrierTryNotify(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - barrier->data.read_sync(); - return barrier->data.atomic_op(CELL_OK, syncBarrierTryNotifyOp); + return barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryNotifyOp); } s32 syncBarrierTryWaitOp(CellSyncBarrier::data_t& barrier) @@ -239,8 +236,7 @@ s32 cellSyncBarrierWait(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - barrier->data.read_sync(); - while (barrier->data.atomic_op(CELL_OK, syncBarrierTryWaitOp)) + while (barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryWaitOp)) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack if (Emu.IsStopped()) @@ -265,8 +261,7 @@ s32 cellSyncBarrierTryWait(vm::ptr barrier) return CELL_SYNC_ERROR_ALIGN; } - barrier->data.read_sync(); - return barrier->data.atomic_op(CELL_OK, syncBarrierTryWaitOp); + return barrier->data.atomic_op_sync(CELL_OK, syncBarrierTryWaitOp); } s32 syncRwmInitialize(vm::ptr rwm, vm::ptr buffer, u32 buffer_size) From 7d95311a0107d1c4a76006b5775137ec586bbee5 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 29 Sep 2014 19:38:04 +0400 Subject: [PATCH 18/24] Some %x fixed --- Utilities/AutoPause.cpp | 8 ++-- rpcs3/Emu/Cell/PPUDisAsm.h | 2 +- rpcs3/Emu/Cell/PPUInterpreter.h | 8 ++-- rpcs3/Emu/RSX/RSXThread.cpp | 56 +++++++++++------------ rpcs3/Emu/SysCalls/Modules/cellL10n.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp | 8 ++-- rpcs3/Emu/SysCalls/Modules/cellPamf.cpp | 2 +- rpcs3/Loader/ELF32.cpp | 16 +++---- rpcs3/Loader/ELF64.cpp | 16 +++---- rpcs3/Loader/Loader.cpp | 8 ++-- rpcs3/Loader/PSF.cpp | 2 +- rpcs3/Loader/TRP.cpp | 2 +- 12 files changed, 66 insertions(+), 66 deletions(-) diff --git a/Utilities/AutoPause.cpp b/Utilities/AutoPause.cpp index 9c3fc70edf..b1e4c3ed0a 100644 --- a/Utilities/AutoPause.cpp +++ b/Utilities/AutoPause.cpp @@ -69,12 +69,12 @@ void AutoPause::Reload(void) //Less than 1024 - be regarded as a system call. //emplace_back may not cause reductant move/copy operation. m_pause_syscall.emplace_back(num); - LOG_WARNING(HLE, "Auto Pause: Find System Call ID %x", num); + LOG_WARNING(HLE, "Auto Pause: Find System Call ID 0x%x", num); } else { m_pause_function.emplace_back(num); - LOG_WARNING(HLE, "Auto Pause: Find Function Call ID %x", num); + LOG_WARNING(HLE, "Auto Pause: Find Function Call ID 0x%x", num); } } list.Close(); @@ -103,7 +103,7 @@ void AutoPause::TryPause(u32 code) { if (code == m_pause_syscall[i]) { Emu.Pause(); - LOG_ERROR(HLE, "Auto Pause Triggered: System call %x", code); //Used Error + LOG_ERROR(HLE, "Auto Pause Triggered: System call 0x%x", code); // Used Error } } } @@ -121,7 +121,7 @@ void AutoPause::TryPause(u32 code) { if (code == m_pause_function[i]) { Emu.Pause(); - LOG_ERROR(HLE, "Auto Pause Triggered: Function call %x", code); //Used Error + LOG_ERROR(HLE, "Auto Pause Triggered: Function call 0x%x", code); // Used Error } } } diff --git a/rpcs3/Emu/Cell/PPUDisAsm.h b/rpcs3/Emu/Cell/PPUDisAsm.h index 34e51f7fb2..81cd3029d4 100644 --- a/rpcs3/Emu/Cell/PPUDisAsm.h +++ b/rpcs3/Emu/Cell/PPUDisAsm.h @@ -1037,7 +1037,7 @@ private: case 0x1: Write("HyperCall"); break; case 0x2: Write("sc"); break; case 0x22: Write("HyperCall LV1"); break; - default: Write(fmt::Format("Unknown sc: %x", sc_code)); + default: Write(fmt::Format("Unknown sc: 0x%x", sc_code)); } } void B(s32 ll, u32 aa, u32 lk) diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 3ad8ba2eea..c44c8a9a21 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -149,7 +149,7 @@ private: ((u64)a < (u64)simm16 && (to & 0x2)) || ((u64)a > (u64)simm16 && (to & 0x1)) ) { - UNK(fmt::Format("Trap! (tdi %x, r%d, %x)", to, ra, simm16)); + UNK(fmt::Format("Trap! (tdi 0x%x, r%d, 0x%x)", to, ra, simm16)); } } @@ -163,7 +163,7 @@ private: ((u32)a < (u32)simm16 && (to & 0x2)) || ((u32)a > (u32)simm16 && (to & 0x1)) ) { - UNK(fmt::Format("Trap! (twi %x, r%d, %x)", to, ra, simm16)); + UNK(fmt::Format("Trap! (twi 0x%x, r%d, 0x%x)", to, ra, simm16)); } } @@ -2102,7 +2102,7 @@ private: break; case 0x4: CPU.FastStop(); break; case 0x22: UNK("HyperCall LV1"); break; - default: UNK(fmt::Format("Unknown sc: %x", sc_code)); + default: UNK(fmt::Format("Unknown sc: 0x%x", sc_code)); } } void B(s32 ll, u32 aa, u32 lk) @@ -2266,7 +2266,7 @@ private: ((u32)a < (u32)b && (to & 0x2)) || ((u32)a > (u32)b && (to & 0x1)) ) { - UNK(fmt::Format("Trap! (tw %x, r%d, r%d)", to, ra, rb)); + UNK(fmt::Format("Trap! (tw 0x%x, r%d, r%d)", to, ra, rb)); } } void LVSL(u32 vd, u32 ra, u32 rb) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 952a963f1b..02231cf848 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -239,7 +239,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV406E_SET_CONTEXT_DMA_SEMAPHORE: { if (ARGS(0)) - LOG_WARNING(RSX, "NV406E_SET_CONTEXT_DMA_SEMAPHORE: %x", ARGS(0)); + LOG_WARNING(RSX, "NV406E_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", ARGS(0)); } break; @@ -254,7 +254,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV406E_SEMAPHORE_ACQUIRE: { if (ARGS(0)) - LOG_WARNING(RSX, "NV406E_SEMAPHORE_ACQUIRE: %x", ARGS(0)); + LOG_WARNING(RSX, "NV406E_SEMAPHORE_ACQUIRE: 0x%x", ARGS(0)); } break; @@ -315,21 +315,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_NOTIFY: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_NOTIFY: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_NOTIFY: 0x%x", ARGS(0)); } break; case NV4097_WAIT_FOR_IDLE: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_WAIT_FOR_IDLE: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_WAIT_FOR_IDLE: 0x%x", ARGS(0)); } break; case NV4097_PM_TRIGGER: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_PM_TRIGGER: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_PM_TRIGGER: 0x%x", ARGS(0)); } break; @@ -458,7 +458,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: 0x%x", ARGS(0)); //VertexData[0].prog.attributeInputMask = ARGS(0); } @@ -467,7 +467,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: 0x%x", ARGS(0)); //VertexData[0].prog.attributeOutputMask = ARGS(0); //FragmentData.prog.attributeInputMask = ARGS(0)/* & ~0x20*/; @@ -490,7 +490,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_COLOR_MASK_MRT: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_COLOR_MASK_MRT: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_COLOR_MASK_MRT: 0x%x", ARGS(0)); } break; @@ -829,14 +829,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_CLEAR_RECT_HORIZONTAL: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_HORIZONTAL: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_HORIZONTAL: 0x%x", ARGS(0)); } break; case NV4097_SET_CLEAR_RECT_VERTICAL: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_VERTICAL: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_VERTICAL: 0x%x", ARGS(0)); } break; @@ -933,7 +933,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { const u32 a0 = ARGS(0); - //LOG_WARNING(RSX, "NV4097_SET_BEGIN_END: %x", a0); + //LOG_WARNING(RSX, "NV4097_SET_BEGIN_END: 0x%x", a0); m_read_buffer = false; @@ -1066,7 +1066,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_INVALIDATE_L2: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_INVALIDATE_L2: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_INVALIDATE_L2: 0x%x", ARGS(0)); } break; @@ -1085,7 +1085,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_INVALIDATE_ZCULL: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_INVALIDATE_ZCULL: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_INVALIDATE_ZCULL: 0x%x", ARGS(0)); } break; @@ -1249,7 +1249,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_SCULL_CONTROL: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_SCULL_CONTROL: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_SCULL_CONTROL: 0x%x", ARGS(0)); //This is stencil culling , nothing to do with stencil masking on regular color or depth buffer //const u32 a0 = ARGS(0); @@ -1287,7 +1287,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_POINT_PARAMS_ENABLE: { if (ARGS(0)) - LOG_ERROR(RSX, "NV4097_SET_POINT_PARAMS_ENABLE: %x", ARGS(0)); + LOG_ERROR(RSX, "NV4097_SET_POINT_PARAMS_ENABLE: 0x%x", ARGS(0)); } break; @@ -1427,7 +1427,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_SURFACE_PITCH_D: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_SURFACE_PITCH_D: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_SURFACE_PITCH_D: 0x%x", ARGS(0)); } break; @@ -1467,7 +1467,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_CONTEXT_DMA_COLOR_D: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_COLOR_D: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_COLOR_D: 0x%x", ARGS(0)); } break; @@ -1481,14 +1481,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_CONTEXT_DMA_SEMAPHORE: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_SEMAPHORE: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", ARGS(0)); } break; case NV4097_SET_CONTEXT_DMA_NOTIFIES: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_NOTIFIES: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_NOTIFIES: 0x%x", ARGS(0)); } break; @@ -1529,7 +1529,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u8 alphaToOne = (a0 >> 8) & 0xf; const u16 sampleMask = a0 >> 16; - LOG_WARNING(RSX, "TODO: NV4097_SET_ANTI_ALIASING_CONTROL: %x", a0); + LOG_WARNING(RSX, "TODO: NV4097_SET_ANTI_ALIASING_CONTROL: 0x%x", a0); } break; @@ -1599,7 +1599,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_ZCULL_CONTROL0: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL0: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL0: 0x%x", ARGS(0)); //m_set_depth_func = true; //m_depth_func = ARGS(0) >> 4; @@ -1609,7 +1609,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_ZCULL_CONTROL1: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL1: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL1: 0x%x", ARGS(0)); //m_set_depth_func = true; //m_depth_func = ARGS(0) >> 4; @@ -1619,14 +1619,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_ZCULL_STATS_ENABLE: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_SET_ZCULL_STATS_ENABLE: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_SET_ZCULL_STATS_ENABLE: 0x%x", ARGS(0)); } break; case NV4097_ZCULL_SYNC: { if (ARGS(0)) - LOG_WARNING(RSX, "NV4097_ZCULL_SYNC: %x", ARGS(0)); + LOG_WARNING(RSX, "NV4097_ZCULL_SYNC: 0x%x", ARGS(0)); } break; @@ -1745,7 +1745,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { const u32 offset = ARGS(0) & 0xffffff; const u8 mode = ARGS(0) >> 24; - LOG_WARNING(RSX, "NV4097_SET_RENDER_ENABLE: Offset=%06x, Mode=%x", offset, mode); + LOG_WARNING(RSX, "NV4097_SET_RENDER_ENABLE: Offset=0x%06x, Mode=0x%x", offset, mode); } break; @@ -1812,14 +1812,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV0039_PITCH_IN: { if (ARGS(0)) - LOG_WARNING(RSX, "NV0039_PITCH_IN: %x", ARGS(0)); + LOG_WARNING(RSX, "NV0039_PITCH_IN: 0x%x", ARGS(0)); } break; case NV0039_BUFFER_NOTIFY: { if (ARGS(0)) - LOG_WARNING(RSX, "NV0039_BUFFER_NOTIFY: %x", ARGS(0)); + LOG_WARNING(RSX, "NV0039_BUFFER_NOTIFY: 0x%x", ARGS(0)); } break; @@ -1848,7 +1848,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV309E_SET_CONTEXT_DMA_IMAGE: { if (ARGS(0)) - LOG_WARNING(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: %x", ARGS(0)); + LOG_WARNING(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: 0x%x", ARGS(0)); } break; diff --git a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp b/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp index ef71786077..6c06746ebb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp @@ -283,9 +283,9 @@ int _L10nConvertStr(int src_code, const void* src, size_t * src_len, int dst_cod //TODO: Check the code in emulation. If support for UTF8/UTF16/UTF32/UCS2/UCS4 should use wider chars.. awful. int L10nConvertStr(int src_code, vm::ptr src, vm::ptr> src_len, int dst_code, vm::ptr dst, vm::ptr> dst_len) { - cellL10n->Todo("L10nConvertStr(src_code=%d,src=0x%x,src_len=%ld,dst_code=%d,dst=0x%x,dst_len=%ld)", + cellL10n->Error("L10nConvertStr(src_code=%d, srca_addr=0x%x, src_len_addr=0x%x, dst_code=%d, dst_addr=0x%x, dst_len_addr=0x%x)", src_code, src.addr(), src_len.addr(), dst_code, dst.addr(), dst_len.addr()); - cellL10n->Todo("L10nConvertStr: 1st char at dst: %x(Hex)", *((char*)src.get_ptr())); + //cellL10n->Todo("L10nConvertStr: 1st char at dst: 0x%x", *((char*)src.get_ptr())); #ifdef _MSC_VER unsigned int srcCode = 0, dstCode = 0; //OEM code pages bool src_page_converted = _L10nCodeParse(src_code, srcCode); //Check if code is in list. diff --git a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp b/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp index 995b633b96..389ae23c34 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp @@ -46,7 +46,7 @@ int cellNetCtlTerm() int cellNetCtlGetState(vm::ptr> state) { - cellNetCtl->Log("cellNetCtlGetState(state_addr=0x%x)", state.addr()); + cellNetCtl->Warning("cellNetCtlGetState(state_addr=0x%x)", state.addr()); *state = CELL_NET_CTL_STATE_Disconnected; // TODO: Allow other states @@ -55,21 +55,21 @@ int cellNetCtlGetState(vm::ptr> state) int cellNetCtlAddHandler(vm::ptr handler, vm::ptr> arg, s32 hid) { - cellNetCtl->Todo("cellNetCtlAddHandler(handler_addr=0x%x, arg_addr=0x%x, hid=%x)", handler.addr(), arg.addr(), hid); + cellNetCtl->Todo("cellNetCtlAddHandler(handler_addr=0x%x, arg_addr=0x%x, hid=0x%x)", handler.addr(), arg.addr(), hid); return CELL_OK; } int cellNetCtlDelHandler(s32 hid) { - cellNetCtl->Todo("cellNetCtlDelHandler(hid=%x)", hid); + cellNetCtl->Todo("cellNetCtlDelHandler(hid=0x%x)", hid); return CELL_OK; } int cellNetCtlGetInfo(s32 code, vm::ptr info) { - cellNetCtl->Todo("cellNetCtlGetInfo(code=%x, info_addr=0x%x)", code, info.addr()); + cellNetCtl->Todo("cellNetCtlGetInfo(code=0x%x, info_addr=0x%x)", code, info.addr()); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index e06df6d5dd..ae5095c809 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -105,7 +105,7 @@ u8 pamfGetStreamChannel(vm::ptr pSelf, u8 stream) } else { - cellPamf->Error("pamfGetStreamChannel: stream type %x got invalid stream id=%x", pAddr->stream_headers[stream].type, pAddr->stream_headers[stream].stream_id); + cellPamf->Error("pamfGetStreamChannel: stream type 0x%x got invalid stream id=0x%x", pAddr->stream_headers[stream].type, pAddr->stream_headers[stream].stream_id); return 0; } case 0xdc: diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 03517368e9..430ae52f32 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -155,16 +155,16 @@ void Elf32_Shdr::LoadLE(vfsStream& f) void Elf32_Shdr::Show() { #ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "Name offset: %x", sh_name); - LOG_NOTICE(LOADER, "Type: %d", sh_type); - LOG_NOTICE(LOADER, "Addr: %x", sh_addr); - LOG_NOTICE(LOADER, "Offset: %x", sh_offset); - LOG_NOTICE(LOADER, "Size: %x", sh_size); + LOG_NOTICE(LOADER, "Name offset: 0x%x", sh_name); + LOG_NOTICE(LOADER, "Type: 0x%d", sh_type); + LOG_NOTICE(LOADER, "Addr: 0x%x", sh_addr); + LOG_NOTICE(LOADER, "Offset: 0x%x", sh_offset); + LOG_NOTICE(LOADER, "Size: 0x%x", sh_size); LOG_NOTICE(LOADER, "EntSize: %d", sh_entsize); - LOG_NOTICE(LOADER, "Flags: %x", sh_flags); - LOG_NOTICE(LOADER, "Link: %x", sh_link); + LOG_NOTICE(LOADER, "Flags: 0x%x", sh_flags); + LOG_NOTICE(LOADER, "Link: 0x%x", sh_link); LOG_NOTICE(LOADER, "Info: %d", sh_info); - LOG_NOTICE(LOADER, "Address align: %x", sh_addralign); + LOG_NOTICE(LOADER, "Address align: 0x%x", sh_addralign); #endif } diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index 141d5b5031..b8a917b6e7 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -77,16 +77,16 @@ void Elf64_Shdr::Load(vfsStream& f) void Elf64_Shdr::Show() { #ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "Name offset: %x", sh_name); + LOG_NOTICE(LOADER, "Name offset: 0x%x", sh_name); LOG_NOTICE(LOADER, "Type: %d", sh_type); - LOG_NOTICE(LOADER, "Addr: %llx", sh_addr); - LOG_NOTICE(LOADER, "Offset: %llx", sh_offset); - LOG_NOTICE(LOADER, "Size: %llx", sh_size); + LOG_NOTICE(LOADER, "Addr: 0x%llx", sh_addr); + LOG_NOTICE(LOADER, "Offset: 0x%llx", sh_offset); + LOG_NOTICE(LOADER, "Size: 0x%llx", sh_size); LOG_NOTICE(LOADER, "EntSize: %lld", sh_entsize); - LOG_NOTICE(LOADER, "Flags: %llx", sh_flags); - LOG_NOTICE(LOADER, "Link: %x", sh_link); - LOG_NOTICE(LOADER, "Info: %x", sh_info); - LOG_NOTICE(LOADER, "Address align: %llx", sh_addralign); + LOG_NOTICE(LOADER, "Flags: 0x%llx", sh_flags); + LOG_NOTICE(LOADER, "Link: 0x%x", sh_link); + LOG_NOTICE(LOADER, "Info: 0x%x", sh_info); + LOG_NOTICE(LOADER, "Address align: 0x%llx", sh_addralign); #endif } diff --git a/rpcs3/Loader/Loader.cpp b/rpcs3/Loader/Loader.cpp index d06511889e..ed804f1f40 100644 --- a/rpcs3/Loader/Loader.cpp +++ b/rpcs3/Loader/Loader.cpp @@ -35,7 +35,7 @@ const std::string Ehdr_OS_ABIToString(const u8 os_abi) case 0x66: return "Cell OS LV-2"; }; - return fmt::Format("Unknown (%x)", os_abi); + return fmt::Format("Unknown (0x%x)", os_abi); } const std::string Ehdr_MachineToString(const u16 machine) @@ -48,7 +48,7 @@ const std::string Ehdr_MachineToString(const u16 machine) case MACHINE_ARM: return "ARM"; }; - return fmt::Format("Unknown (%x)", machine); + return fmt::Format("Unknown (0x%x)", machine); } const std::string Phdr_FlagsToString(u32 flags) @@ -73,7 +73,7 @@ const std::string Phdr_FlagsToString(u32 flags) flags &= ~spu << 0x14; flags &= ~rsx << 0x18; - if(flags != 0) return fmt::Format("Unknown %s PPU[%x] SPU[%x] RSX[%x]", ret.c_str(), ppu, spu, rsx); + if(flags != 0) return fmt::Format("Unknown %s PPU[0x%x] SPU[0x%x] RSX[0x%x]", ret.c_str(), ppu, spu, rsx); ret += "PPU[" + FLAGS_TO_STRING(ppu) + "] "; ret += "SPU[" + FLAGS_TO_STRING(spu) + "] "; @@ -93,7 +93,7 @@ const std::string Phdr_TypeToString(const u32 type) case 0x60000002: return "LOOS+2"; }; - return fmt::Format("Unknown (%x)", type); + return fmt::Format("Unknown (0x%x)", type); } Loader::Loader() diff --git a/rpcs3/Loader/PSF.cpp b/rpcs3/Loader/PSF.cpp index 9f9813a950..6bf66f4378 100644 --- a/rpcs3/Loader/PSF.cpp +++ b/rpcs3/Loader/PSF.cpp @@ -44,7 +44,7 @@ bool PSFLoader::LoadHeader() if(!m_header.CheckMagic()) return false; - if(m_show_log) LOG_NOTICE(LOADER, "PSF version: %x", m_header.psf_version); + if(m_show_log) LOG_NOTICE(LOADER, "PSF version: 0x%x", m_header.psf_version); m_psfindxs.clear(); m_entries.clear(); diff --git a/rpcs3/Loader/TRP.cpp b/rpcs3/Loader/TRP.cpp index 8f3e55c4ab..6c02e4221a 100644 --- a/rpcs3/Loader/TRP.cpp +++ b/rpcs3/Loader/TRP.cpp @@ -51,7 +51,7 @@ bool TRPLoader::LoadHeader(bool show) return false; if (show) - LOG_NOTICE(LOADER, "TRP version: %x", m_header.trp_version); + LOG_NOTICE(LOADER, "TRP version: 0x%x", m_header.trp_version); m_entries.clear(); m_entries.resize(m_header.trp_files_count); From 6b53479ac3cf63bf6775e854c5123e6dce049604 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 29 Sep 2014 19:39:44 +0400 Subject: [PATCH 19/24] _cellSpursWorkloadFlagReceiver, cellSpursReadyCountStore --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 202 ++++++++++++++++------- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 117 +++++++++---- 2 files changed, 222 insertions(+), 97 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index efc7c91bf3..82cff805eb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -94,12 +94,12 @@ s64 spursInit( { spurs->m.wklMsk1.write_relaxed(be_t::make(0xffff)); } - spurs->m.unk6[0xC] = 0; - spurs->m.unk6[0xD] = 0; - spurs->m.unk6[0xE] = 0; + spurs->m.xCC = 0; + spurs->m.xCD = 0; + spurs->m.xCE = 0; for (u32 i = 0; i < 8; i++) { - spurs->m.unk6[i] = -1; + spurs->m.xC0[i] = -1; } #ifdef PRX_DEBUG spurs->m.unk7 = vm::read32(libsre_rtoc - 0x7EA4); // write 64-bit pointer to unknown data @@ -131,10 +131,7 @@ s64 spursInit( spurs->m.unk11 = -1; spurs->m.unk12 = -1; spurs->m.unk13 = 0; - spurs->m.x70.direct_op([nSpus](CellSpurs::_sub_x70& x70) - { - x70.nSpus = nSpus; - }); + spurs->m.nSpus = nSpus; spurs->m.spuPriority = spuPriority; #ifdef PRX_DEBUG assert(spu_image_import(spurs->m.spuImg, vm::read32(libsre_rtoc - (isSecond ? 0x7E94 : 0x7E98)), 1) == CELL_OK); @@ -187,12 +184,9 @@ s64 spursInit( assert(lwmutex_create(spurs->m.mutex, SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, *(u64*)"_spuPrv") == CELL_OK); assert(lwcond_create(spurs->m.cond, spurs->m.mutex, *(u64*)"_spuPrv") == CELL_OK); - spurs->m.x70.direct_op([flags, isSecond](CellSpurs::_sub_x70& x70) - { - x70.flags1 = (flags & SAF_EXIT_IF_NO_WORK) << 7 | (isSecond ? 0x40 : 0); - x70.unk7 = -1; - }); - spurs->m.unk18 = -1; + spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK) << 7 | (isSecond ? 0x40 : 0); + spurs->m.flagRecv.write_relaxed(0xff); + spurs->m.wklFlag.flag.write_relaxed(be_t::make(-1)); spurs->_u8[0xD64] = 0; spurs->_u8[0xD65] = 0; spurs->_u8[0xD66] = 0; @@ -569,7 +563,7 @@ s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr po { return CELL_SPURS_CORE_ERROR_ALIGN; } - if (spurs->m.unk21.ToBE()) + if (spurs->m.exception.ToBE()) { return CELL_SPURS_CORE_ERROR_STAT; } @@ -773,13 +767,13 @@ s64 spursWakeUp(vm::ptr spurs) { return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; } - if (spurs->m.unk21.ToBE()) + if (spurs->m.exception.ToBE()) { return CELL_SPURS_POLICY_MODULE_ERROR_STAT; } - spurs->m.unk19[0].exchange(1); - if (spurs->m.unk19[1].read_sync()) + spurs->m.xD64.exchange(1); + if (spurs->m.xD65.read_sync()) { assert(sys_lwmutex_lock(vm::ptr::make(spurs.addr() + 0xdb0), 0) == 0); assert(sys_lwcond_signal(vm::ptr::make(spurs.addr() + 0xdc8)) == 0); @@ -826,13 +820,13 @@ s32 spursAddWorkload( { return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; } - if (spurs->m.unk21.ToBE()) + if (spurs->m.exception.ToBE()) { return CELL_SPURS_POLICY_MODULE_ERROR_STAT; } u32 wnum; - const u32 wmax = spurs->m.x70.read_relaxed().flags1 & 0x40 ? 0x20 : 0x10; // check isSecond (TODO: check if can be changed) + const u32 wmax = spurs->m.flags1 & 0x40 ? 0x20 : 0x10; // check isSecond (TODO: check if can be changed) spurs->m.wklMsk1.atomic_op([spurs, wmax, &wnum](be_t& value) { wnum = cntlz32(~(u32)value); // found empty position @@ -853,7 +847,7 @@ s32 spursAddWorkload( { assert((spurs->m.wklA[wnum] & 0xf) == 0); assert((spurs->m.wklB[wnum] & 0xf) == 0); - spurs->m.wklC1[wnum] = 1; + spurs->m.wklStat1[wnum].write_relaxed(1); spurs->m.wklD1[wnum] = 0; spurs->m.wklE1[wnum] = 0; spurs->m.wklG1[wnum].wklPm = pm; @@ -870,10 +864,9 @@ s32 spursAddWorkload( spurs->m.wklF1[wnum].hookArg = hookArg; spurs->m.wklE1[wnum] |= 2; } - spurs->m.wklZ1[wnum] = 0; - if ((spurs->m.x70.read_relaxed().flags1 & 0x40) == 0) + if ((spurs->m.flags1 & 0x40) == 0) { - spurs->m.wklZ2[wnum] = 0; + spurs->m.wklReadyCount[wnum + 16].write_relaxed(0); spurs->m.wklMinCnt[wnum] = minContention > 8 ? 8 : minContention; } } @@ -881,7 +874,7 @@ s32 spursAddWorkload( { assert((spurs->m.wklA[index] & 0xf0) == 0); assert((spurs->m.wklB[index] & 0xf0) == 0); - spurs->m.wklC2[index] = 1; + spurs->m.wklStat2[index].write_relaxed(1); spurs->m.wklD2[index] = 0; spurs->m.wklE2[index] = 0; spurs->m.wklG2[index].wklPm = pm; @@ -898,8 +891,8 @@ s32 spursAddWorkload( spurs->m.wklF2[index].hookArg = hookArg; spurs->m.wklE2[index] |= 2; } - spurs->m.wklZ2[index] = 0; } + spurs->m.wklReadyCount[wnum].write_relaxed(0); u32 pos = ((~wnum * 8) | (wnum / 4)) & 0x1c; spurs->m.wklMaxCnt[index / 4].atomic_op([pos, maxContention](be_t& v) @@ -910,26 +903,26 @@ s32 spursAddWorkload( if (wnum <= 15) { - spurs->m.x70._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag1 + spurs->m.wklSet1._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag1 } else { - spurs->m.x78._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag2 + spurs->m.wklSet2._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag2 } - spurs->m.x70.atomic_op([wnum](CellSpurs::_sub_x70& x70) + spurs->m.flagRecv.atomic_op([wnum](u8& FR) { - if (x70.unk7 == wnum) + if (FR == wnum) { - x70.unk7 = 0xff; + FR = 0xff; } }); u32 res_wkl; - spurs->m.wklMsk2.atomic_op_sync([spurs, wnum, &res_wkl](be_t& v) + CellSpurs::_sub_str3& wkl = wnum <= 15 ? spurs->m.wklG1[wnum] : spurs->m.wklG2[wnum & 0xf]; + spurs->m.wklMsk2.atomic_op_sync([spurs, &wkl, wnum, &res_wkl](be_t& v) { - CellSpurs::_sub_str3& wkl = wnum <= 15 ? spurs->m.wklG1[wnum] : spurs->m.wklG2[wnum & 0xf]; - const u32 mask = v.ToLE() & ~(0x80000000 >> wnum); + const u32 mask = v.ToLE() & ~(0x80000000u >> wnum); res_wkl = 0; for (u32 i = 0, m = 0x80000000, k = 0; i < 32; i++, m >>= 1) @@ -952,21 +945,13 @@ s32 spursAddWorkload( } wkl.wklCopy.exchange((u8)res_wkl); + v = mask | (0x80000000u >> wnum); }); assert(res_wkl <= 31); - if (wnum <= 15) - { - spurs->m.wklC1[wnum] = 2; - } - else - { - spurs->m.wklC2[index] = 2; - } - - spurs->m.unk23[5].exchange(-1); // write 0xff byte at 0xbd - spurs->m.x70._and_not({ {}, -1 }); // clear byte at 0x72 - + spurs->wklStat(wnum).exchange(2); + spurs->m.xBD.exchange(0xff); + spurs->m.x72.exchange(0); return CELL_OK; } @@ -1162,26 +1147,94 @@ s64 cellSpursShutdownWorkload() #endif } -s64 _cellSpursWorkloadFlagReceiver() +s64 _cellSpursWorkloadFlagReceiver(vm::ptr spurs, u32 wid, u32 is_set) { -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); + cellSpurs->Warning("%s(spurs_addr=0x%x, wid=%d, is_set=%d)", __FUNCTION__, spurs.addr(), wid, is_set); + +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xF158, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; #endif + if (!spurs) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (wid >= (spurs->m.flags1 & 0x40 ? 0x20u : 0x10u)) + { + return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; + } + if ((spurs->m.wklMsk1.read_relaxed().ToLE() & (0x80000000u >> wid)) == 0) + { + return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; + } + if (spurs->m.exception.ToBE()) + { + return CELL_SPURS_POLICY_MODULE_ERROR_STAT; + } + if (s32 res = spurs->m.wklFlag.flag.atomic_op_sync(0, [spurs, wid, is_set](be_t& flag) -> s32 + { + if (is_set) + { + if (spurs->m.flagRecv.read_relaxed() != 0xff) + { + return CELL_SPURS_POLICY_MODULE_ERROR_BUSY; + } + } + else + { + if (spurs->m.flagRecv.read_relaxed() != wid) + { + return CELL_SPURS_POLICY_MODULE_ERROR_PERM; + } + } + flag = -1; + return 0; + })) + { + return res; + } + + spurs->m.flagRecv.atomic_op([wid, is_set](u8& FR) + { + if (is_set) + { + if (FR == 0xff) + { + FR = (u8)wid; + } + } + else + { + if (FR == wid) + { + FR = 0xff; + } + } + }); + return CELL_OK; } -s64 cellSpursGetWorkloadFlag() +s64 cellSpursGetWorkloadFlag(vm::ptr spurs, vm::ptr> flag) { -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); + cellSpurs->Warning("%s(spurs_addr=0x%x, flag_addr=0x%x)", __FUNCTION__, spurs.addr(), flag.addr()); + +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xEC00, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; #endif + if (!spurs || !flag) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + + *flag = vm::bptr::make(Memory.RealToVirtualAddr(&spurs->m.wklFlag)); + return CELL_OK; } s64 cellSpursSendWorkloadSignal() @@ -1206,15 +1259,36 @@ s64 cellSpursGetWorkloadData() #endif } -s64 cellSpursReadyCountStore() +s64 cellSpursReadyCountStore(vm::ptr spurs, u32 wid, u32 value) { -#ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); + cellSpurs->Warning("%s(spurs_addr=0x%x, wid=%d, value=0x%x)", __FUNCTION__, spurs.addr(), wid, value); + +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xAB2C, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; #endif + if (!spurs) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + if (wid >= (spurs->m.flags1 & 0x40 ? 0x20u : 0x10u) || value > 0xff) + { + return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; + } + if ((spurs->m.wklMsk1.read_relaxed().ToLE() & (0x80000000u >> wid)) == 0) + { + return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; + } + if (spurs->m.exception.ToBE() || spurs->wklStat(wid).read_relaxed() != 2) + { + return CELL_SPURS_POLICY_MODULE_ERROR_STAT; + } + + spurs->m.wklReadyCount[wid].exchange((u8)value); + return CELL_OK; } s64 cellSpursReadyCountAdd() diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 47ab8d975f..87a01466f1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -56,6 +56,38 @@ enum CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920, }; +enum +{ + CELL_SPURS_JOB_ERROR_AGAIN = 0x80410A01, + CELL_SPURS_JOB_ERROR_INVAL = 0x80410A02, + CELL_SPURS_JOB_ERROR_NOSYS = 0x80410A03, + CELL_SPURS_JOB_ERROR_NOMEM = 0x80410A04, + CELL_SPURS_JOB_ERROR_SRCH = 0x80410A05, + CELL_SPURS_JOB_ERROR_NOENT = 0x80410A06, + CELL_SPURS_JOB_ERROR_NOEXEC = 0x80410A07, + CELL_SPURS_JOB_ERROR_DEADLK = 0x80410A08, + CELL_SPURS_JOB_ERROR_PERM = 0x80410A09, + CELL_SPURS_JOB_ERROR_BUSY = 0x80410A0A, + CELL_SPURS_JOB_ERROR_JOB_DESCRIPTOR = 0x80410A0B, + CELL_SPURS_JOB_ERROR_JOB_DESCRIPTOR_SIZE = 0x80410A0C, + CELL_SPURS_JOB_ERROR_FAULT = 0x80410A0D, + CELL_SPURS_JOB_ERROR_CHILD = 0x80410A0E, + CELL_SPURS_JOB_ERROR_STAT = 0x80410A0F, + CELL_SPURS_JOB_ERROR_ALIGN = 0x80410A10, + CELL_SPURS_JOB_ERROR_NULL_POINTER = 0x80410A11, + CELL_SPURS_JOB_ERROR_MEMORY_CORRUPTED = 0x80410A12, + + CELL_SPURS_JOB_ERROR_MEMORY_SIZE = 0x80410A17, + CELL_SPURS_JOB_ERROR_UNKNOWN_COMMAND = 0x80410A18, + CELL_SPURS_JOB_ERROR_JOBLIST_ALIGNMENT = 0x80410A19, + CELL_SPURS_JOB_ERROR_JOB_ALIGNMENT = 0x80410A1a, + CELL_SPURS_JOB_ERROR_CALL_OVERFLOW = 0x80410A1b, + CELL_SPURS_JOB_ERROR_ABORT = 0x80410A1c, + CELL_SPURS_JOB_ERROR_DMALIST_ELEMENT = 0x80410A1d, + CELL_SPURS_JOB_ERROR_NUM_CACHE = 0x80410A1e, + CELL_SPURS_JOB_ERROR_INVALID_BINARY = 0x80410A1f, +}; + // SPURS defines. enum SPURSKernelInterfaces { @@ -160,6 +192,13 @@ struct CellSpursAttribute }; }; +struct CellSpursWorkloadFlag +{ + be_t unused0; + be_t unused1; + atomic_t flag; +}; + typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); // Core CellSpurs structures @@ -213,23 +252,6 @@ struct CellSpurs vm::bptr nameInstance; }; - struct _sub_x70 - { - be_t wklFlag1; // 0x70 - u8 unk2; // 0x72 - u8 unk3; - u8 flags1; - u8 unk5; - u8 nSpus; - u8 unk7; - }; - - struct _sub_x78 - { - be_t wklFlag2; - u8 unk[6]; - }; - union { // raw data @@ -239,27 +261,42 @@ struct CellSpurs // real data struct { - u8 wklZ1[0x10]; // 0x0 - u8 wklZ2[0x10]; // 0x10 + atomic_t wklReadyCount[0x20]; u8 wklA[0x10]; // 0x20 u8 wklB[0x10]; // 0x30 u8 wklMinCnt[0x10]; // 0x40 atomic_t wklMaxCnt[4]; // 0x50 - u8 unknown0[0x6C - 0x60]; - be_t unk18; // 0x6C - atomic_t<_sub_x70> x70; // 0x70 - atomic_t<_sub_x78> x78; // 0x78 - u8 wklC1[0x10]; // 0x80 + CellSpursWorkloadFlag wklFlag; // 0x60 + atomic_t wklSet1; // 0x70 + atomic_t x72; // 0x72 + u8 x73; // 0x73 + u8 flags1; // 0x74 + u8 x75; // 0x75 + u8 nSpus; // 0x76 + atomic_t flagRecv; // 0x77 + atomic_t wklSet2; // 0x78 + u8 x7A[6]; // 0x7A + atomic_t wklStat1[0x10]; // 0x80 u8 wklD1[0x10]; // 0x90 u8 wklE1[0x10]; // 0xA0 - atomic_t wklMsk1;// 0xB0 - atomic_t wklMsk2;// 0xB4 - atomic_t unk23[8];// 0xB8 - u8 unk6[0x10]; // 0xC0 (SPU port at 0xc9) - u8 wklC2[0x10]; // 0xD0 + atomic_t wklMsk1; // 0xB0 + atomic_t wklMsk2; // 0xB4 + u8 xB8[5]; // 0xB8 + atomic_t xBD; // 0xBD + u8 xBE[2]; // 0xBE + u8 xC0[8]; // 0xC0 + u8 xC8; // 0xC8 + u8 spuPort; // 0xC9 + u8 xCA; // 0xCA + u8 xCB; // 0xCB + u8 xCC; // 0xCC + u8 xCD; // 0xCD + u8 xCE; // 0xCE + u8 xCF; // 0xCF + atomic_t wklStat2[0x10]; // 0xD0 u8 wklD2[0x10]; // 0xE0 u8 wklE2[0x10]; // 0xF0 - _sub_str1 wklF1[0x10];// 0x100 + _sub_str1 wklF1[0x10]; // 0x100 be_t unk22; // 0x900 u8 unknown7[0x980 - 0x908]; be_t semPrv; // 0x980 @@ -280,9 +317,11 @@ struct CellSpurs u8 unknown3[0xD5C - 0xD54]; be_t queue; // 0xD5C be_t port; // 0xD60 - atomic_t unk19[4]; // 0xD64 (used in wakeup) + atomic_t xD64; // 0xD64 + atomic_t xD65; // 0xD65 + atomic_t xD66; // 0xD66 atomic_t enableEH; // 0xD68 - be_t unk21; // 0xD6C + be_t exception; // 0xD6C sys_spu_image spuImg; // 0xD70 be_t flags; // 0xD80 be_t spuPriority;// 0xD84 @@ -292,7 +331,7 @@ struct CellSpurs be_t unk5; // 0xD9C be_t revision; // 0xDA0 be_t sdkVersion; // 0xDA4 - atomic_t spups;// 0xDA8 + atomic_t spups; // 0xDA8 sys_lwmutex_t mutex; // 0xDB0 sys_lwcond_t cond; // 0xDC8 u8 unknown9[0xE00 - 0xDD0]; @@ -310,6 +349,18 @@ struct CellSpurs SPURSManager *spurs; } c; }; + + __forceinline atomic_t& wklStat(const u32 wid) + { + if (wid & 0x10) + { + return m.wklStat2[wid & 0xf]; + } + else + { + return m.wklStat1[wid & 0xf]; + } + } }; typedef CellSpurs CellSpurs2; From 68cdc95da57b95255ee461e79133e903885cc129 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 30 Sep 2014 02:28:02 +0400 Subject: [PATCH 20/24] Some fixes --- rpcs3/Emu/SysCalls/LogBase.cpp | 2 +- rpcs3/Emu/SysCalls/LogBase.h | 8 +- rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp | 16 +-- rpcs3/Emu/SysCalls/Modules/cellResc.cpp | 10 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 149 ++++++++++++++++++---- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 26 +++- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 4 +- 7 files changed, 168 insertions(+), 47 deletions(-) diff --git a/rpcs3/Emu/SysCalls/LogBase.cpp b/rpcs3/Emu/SysCalls/LogBase.cpp index 2afeb52bae..0f1a48edf4 100644 --- a/rpcs3/Emu/SysCalls/LogBase.cpp +++ b/rpcs3/Emu/SysCalls/LogBase.cpp @@ -6,7 +6,7 @@ bool LogBase::CheckLogging() const { - return Ini.HLELogging.GetValue(); + return Ini.HLELogging.GetValue() || m_logging; } void LogBase::LogOutput(LogType type, const char* info, const std::string& text) const diff --git a/rpcs3/Emu/SysCalls/LogBase.h b/rpcs3/Emu/SysCalls/LogBase.h index d3ba9cc16b..92848e7ba0 100644 --- a/rpcs3/Emu/SysCalls/LogBase.h +++ b/rpcs3/Emu/SysCalls/LogBase.h @@ -31,12 +31,12 @@ public: template __noinline void Notice(const u32 id, const char* fmt, Targs... args) const { - LogOutput(LogNotice, id, ": ", fmt::Format(fmt, args...)); + LogOutput(LogNotice, id, " : ", fmt::Format(fmt, args...)); } template __noinline void Notice(const char* fmt, Targs... args) const { - LogOutput(LogNotice, ": ", fmt::Format(fmt, args...)); + LogOutput(LogNotice, " : ", fmt::Format(fmt, args...)); } template __forceinline void Log(const char* fmt, Targs... args) const @@ -57,12 +57,12 @@ public: template __noinline void Success(const u32 id, const char* fmt, Targs... args) const { - LogOutput(LogSuccess, id, ": ", fmt::Format(fmt, args...)); + LogOutput(LogSuccess, id, " : ", fmt::Format(fmt, args...)); } template __noinline void Success(const char* fmt, Targs... args) const { - LogOutput(LogSuccess, ": ", fmt::Format(fmt, args...)); + LogOutput(LogSuccess, " : ", fmt::Format(fmt, args...)); } template __noinline void Warning(const u32 id, const char* fmt, Targs... args) const diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index ea76f998d2..609096d59c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -19,7 +19,7 @@ u32 libpngdec_rtoc; s32 pngDecCreate( vm::ptr mainHandle, vm::ptr param, - vm::ptr ext = {}) + vm::ptr ext = vm::ptr::make(0)) { // alloc memory (should probably use param->cbCtrlMallocFunc) auto dec = CellPngDecMainHandle::make(Memory.Alloc(sizeof(PngDecoder), 128)); @@ -60,8 +60,8 @@ s32 pngDecOpen( vm::ptr subHandle, vm::ptr src, vm::ptr openInfo, - vm::ptr cb = {}, - vm::ptr param = {}) + vm::ptr cb = vm::ptr::make(0), + vm::ptr param = vm::ptr::make(0)) { // alloc memory (should probably use dec->malloc) auto stream = CellPngDecSubHandle::make(Memory.Alloc(sizeof(PngStream), 128)); @@ -129,7 +129,7 @@ s32 pngDecClose(CellPngDecSubHandle stream) s32 pngReadHeader( CellPngDecSubHandle stream, vm::ptr info, - vm::ptr extInfo = {}) + vm::ptr extInfo = vm::ptr::make(0)) { CellPngDecInfo& current_info = stream->info; @@ -193,8 +193,8 @@ s32 pngDecSetParameter( CellPngDecSubHandle stream, vm::ptr inParam, vm::ptr outParam, - vm::ptr extInParam = {}, - vm::ptr extOutParam = {}) + vm::ptr extInParam = vm::ptr::make(0), + vm::ptr extOutParam = vm::ptr::make(0)) { CellPngDecInfo& current_info = stream->info; CellPngDecOutParam& current_outParam = stream->outParam; @@ -235,8 +235,8 @@ s32 pngDecodeData( vm::ptr data, vm::ptr dataCtrlParam, vm::ptr dataOutInfo, - vm::ptr cbCtrlDisp = {}, - vm::ptr dispParam = {}) + vm::ptr cbCtrlDisp = vm::ptr::make(0), + vm::ptr dispParam = vm::ptr::make(0)) { dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP; diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp index 9c07072b33..8c7961e5b1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp @@ -603,7 +603,7 @@ void cellRescExit() if (IsPalTemporal()) { cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_DISABLE); - cellGcmSetVBlankHandler({}); + cellGcmSetVBlankHandler(vm::ptr::make(0)); //GcmSysTypePrefix::cellGcmSetSecondVHandler(NULL); if (IsPalInterpolate()) @@ -780,20 +780,20 @@ int cellRescSetDisplayMode(u32 displayMode) cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); //cellGcmSetVBlankHandler(IntrHandler50); //cellGcmSetSecondVHandler(IntrHandler60); - cellGcmSetFlipHandler({}); + cellGcmSetFlipHandler(vm::ptr::make(0)); } else if (IsPalDrop()) { //InitLabels(); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); - cellGcmSetVBlankHandler({}); + cellGcmSetVBlankHandler(vm::ptr::make(0)); //cellGcmSetSecondVHandler(IntrHandler60Drop); - cellGcmSetFlipHandler({}); + cellGcmSetFlipHandler(vm::ptr::make(0)); } else if (IsPal60Hsync()) { cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); - cellGcmSetVBlankHandler({}); + cellGcmSetVBlankHandler(vm::ptr::make(0)); } if (s_rescInternalInstance->s_applicationVBlankHandler) SetVBlankHandler(s_rescInternalInstance->s_applicationVBlankHandler); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 82cff805eb..feb8651edc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "Emu/Memory/Memory.h" +#include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Callback.h" @@ -92,7 +93,7 @@ s64 spursInit( if (!isSecond) { - spurs->m.wklMsk1.write_relaxed(be_t::make(0xffff)); + spurs->m.wklMskA.write_relaxed(be_t::make(0xffff)); } spurs->m.xCC = 0; spurs->m.xCD = 0; @@ -184,7 +185,7 @@ s64 spursInit( assert(lwmutex_create(spurs->m.mutex, SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, *(u64*)"_spuPrv") == CELL_OK); assert(lwcond_create(spurs->m.cond, spurs->m.mutex, *(u64*)"_spuPrv") == CELL_OK); - spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK) << 7 | (isSecond ? 0x40 : 0); + spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK ? SF1_EXIT_IF_NO_WORK : 0) | (isSecond ? SF1_IS_SECOND : 0); spurs->m.flagRecv.write_relaxed(0xff); spurs->m.wklFlag.flag.write_relaxed(be_t::make(-1)); spurs->_u8[0xD64] = 0; @@ -206,10 +207,110 @@ s64 spursInit( spurs->m.ppu0 = ppu_thread_create(0, 0, ppuPriority, 0x4000, true, false, name + "SpursHdlr0", [spurs](PPUThread& CPU) { -#ifdef PRX_DEBUG +#ifdef PRX_DEBUG_XXX return cb_call>(CPU, libsre + 0x9214, libsre_rtoc, spurs); #endif + if (spurs->m.flags & SAF_UNKNOWN_FLAG_30) + { + return; + } + while (true) + { + if (Emu.IsStopped()) + { + cellSpurs->Warning("SPURS Handler Thread 0 aborted"); + return; + } + + if (spurs->m.flags1 & SF1_EXIT_IF_NO_WORK) + { + assert(sys_lwmutex_lock(spurs->get_lwmutex(), 0) == CELL_OK); + if (spurs->m.xD66.read_relaxed()) + { + assert(sys_lwmutex_unlock(spurs->get_lwmutex()) == CELL_OK); + return; + } + else while (true) + { + spurs->m.xD64.exchange(0); + if (spurs->m.exception.ToBE() == 0) + { + bool do_break = false; + for (u32 i = 0; i < 16; i++) + { + if (spurs->m.wklStat1[i].read_relaxed() == 2 && + spurs->m.wklG1[i].wklPriority.ToBE() != 0 && + spurs->_u8[0x50 + i] & 0xf // check wklMaxCnt + ) + { + if (spurs->m.wklReadyCount[i].read_relaxed() || + spurs->m.wklSet1.read_relaxed() & (0x8000u >> i) || + spurs->m.wklFlag.flag.read_relaxed() == 0 && + spurs->m.flagRecv.read_relaxed() == (u8)i + ) + { + do_break = true; + break; + } + } + } + if (spurs->m.flags1 & SF1_IS_SECOND) for (u32 i = 0; i < 16; i++) + { + if (spurs->m.wklStat2[i].read_relaxed() == 2 && + spurs->m.wklG2[i].wklPriority.ToBE() != 0 && + spurs->_u8[0x50 + i] & 0xf0 // check wklMaxCnt + ) + { + if (spurs->m.wklReadyCount[i + 0x10].read_relaxed() || + spurs->m.wklSet2.read_relaxed() & (0x8000u >> i) || + spurs->m.wklFlag.flag.read_relaxed() == 0 && + spurs->m.flagRecv.read_relaxed() == (u8)i + 0x10 + ) + { + do_break = true; + break; + } + } + } + if (do_break) break; // from while + } + + spurs->m.xD65.exchange(1); + if (spurs->m.xD64.read_relaxed() == 0) + { + assert(sys_lwcond_wait(spurs->get_lwcond(), 0) == CELL_OK); + } + spurs->m.xD65.exchange(0); + if (spurs->m.xD66.read_relaxed()) + { + assert(sys_lwmutex_unlock(spurs->get_lwmutex()) == CELL_OK); + return; + } + } + assert(sys_lwmutex_unlock(spurs->get_lwmutex()) == CELL_OK); + } + + if (Emu.IsStopped()) continue; + + assert(sys_spu_thread_group_start(spurs->m.spuTG) == CELL_OK); + if (s32 res = sys_spu_thread_group_join(spurs->m.spuTG, vm::ptr>::make(0), vm::ptr>::make(0))) + { + if (res == CELL_ESTAT) + { + return; + } + assert(res == CELL_OK); + } + + if (Emu.IsStopped()) continue; + + if ((spurs->m.flags1 & SF1_EXIT_IF_NO_WORK) == 0) + { + assert(spurs->m.xD66.read_relaxed() == 1 || Emu.IsStopped()); + return; + } + } })->GetId(); spurs->m.ppu1 = ppu_thread_create(0, 0, ppuPriority, 0x8000, true, false, name + "SpursHdlr1", [spurs](PPUThread& CPU) @@ -775,9 +876,9 @@ s64 spursWakeUp(vm::ptr spurs) spurs->m.xD64.exchange(1); if (spurs->m.xD65.read_sync()) { - assert(sys_lwmutex_lock(vm::ptr::make(spurs.addr() + 0xdb0), 0) == 0); - assert(sys_lwcond_signal(vm::ptr::make(spurs.addr() + 0xdc8)) == 0); - assert(sys_lwmutex_unlock(vm::ptr::make(spurs.addr() + 0xdb0)) == 0); + assert(sys_lwmutex_lock(spurs->get_lwmutex(), 0) == 0); + assert(sys_lwcond_signal(spurs->get_lwcond()) == 0); + assert(sys_lwmutex_unlock(spurs->get_lwmutex()) == 0); } return CELL_OK; } @@ -826,8 +927,8 @@ s32 spursAddWorkload( } u32 wnum; - const u32 wmax = spurs->m.flags1 & 0x40 ? 0x20 : 0x10; // check isSecond (TODO: check if can be changed) - spurs->m.wklMsk1.atomic_op([spurs, wmax, &wnum](be_t& value) + const u32 wmax = spurs->m.flags1 & SF1_IS_SECOND ? 0x20u : 0x10u; // TODO: check if can be changed + spurs->m.wklMskA.atomic_op([spurs, wmax, &wnum](be_t& value) { wnum = cntlz32(~(u32)value); // found empty position if (wnum < wmax) @@ -842,7 +943,7 @@ s32 spursAddWorkload( return CELL_SPURS_POLICY_MODULE_ERROR_AGAIN; } - u32 index = wnum % 0x10; + u32 index = wnum & 0xf; if (wnum <= 15) { assert((spurs->m.wklA[wnum] & 0xf) == 0); @@ -856,15 +957,15 @@ s32 spursAddWorkload( spurs->m.wklG1[wnum].wklPriority = *(be_t*)priorityTable; spurs->m.wklH1[wnum].nameClass = nameClass; spurs->m.wklH1[wnum].nameInstance = nameInstance; - memset(spurs->m.wklF1[wnum].unk0, 0, 0x18); // clear struct preserving semaphore id - memset(spurs->m.wklF1[wnum].unk1, 0, 0x60); + memset(spurs->m.wklF1[wnum].unk0, 0, 0x20); // clear struct preserving semaphore id + memset(spurs->m.wklF1[wnum].unk1, 0, 0x58); if (hook) { spurs->m.wklF1[wnum].hook = hook; spurs->m.wklF1[wnum].hookArg = hookArg; spurs->m.wklE1[wnum] |= 2; } - if ((spurs->m.flags1 & 0x40) == 0) + if ((spurs->m.flags1 & SF1_IS_SECOND) == 0) { spurs->m.wklReadyCount[wnum + 16].write_relaxed(0); spurs->m.wklMinCnt[wnum] = minContention > 8 ? 8 : minContention; @@ -883,8 +984,8 @@ s32 spursAddWorkload( spurs->m.wklG2[index].wklPriority = *(be_t*)priorityTable; spurs->m.wklH2[index].nameClass = nameClass; spurs->m.wklH2[index].nameInstance = nameInstance; - memset(spurs->m.wklF2[index].unk0, 0, 0x18); // clear struct preserving semaphore id - memset(spurs->m.wklF2[index].unk1, 0, 0x60); + memset(spurs->m.wklF2[index].unk0, 0, 0x20); // clear struct preserving semaphore id + memset(spurs->m.wklF2[index].unk1, 0, 0x58); if (hook) { spurs->m.wklF2[index].hook = hook; @@ -920,7 +1021,7 @@ s32 spursAddWorkload( u32 res_wkl; CellSpurs::_sub_str3& wkl = wnum <= 15 ? spurs->m.wklG1[wnum] : spurs->m.wklG2[wnum & 0xf]; - spurs->m.wklMsk2.atomic_op_sync([spurs, &wkl, wnum, &res_wkl](be_t& v) + spurs->m.wklMskB.atomic_op_sync([spurs, &wkl, wnum, &res_wkl](be_t& v) { const u32 mask = v.ToLE() & ~(0x80000000u >> wnum); res_wkl = 0; @@ -951,7 +1052,7 @@ s32 spursAddWorkload( spurs->wklStat(wnum).exchange(2); spurs->m.xBD.exchange(0xff); - spurs->m.x72.exchange(0); + spurs->m.x72.exchange(0xff); return CELL_OK; } @@ -981,10 +1082,10 @@ s64 cellSpursAddWorkload( *priorityTable, minContention, maxContention, - {}, - {}, - {}, - {}); + vm::ptr::make(0), + vm::ptr::make(0), + vm::ptr::make(0), + vm::ptr::make(0)); } s64 _cellSpursWorkloadAttributeInitialize( @@ -1162,11 +1263,11 @@ s64 _cellSpursWorkloadFlagReceiver(vm::ptr spurs, u32 wid, u32 is_set { return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; } - if (wid >= (spurs->m.flags1 & 0x40 ? 0x20u : 0x10u)) + if (wid >= (spurs->m.flags1 & SF1_IS_SECOND ? 0x20u : 0x10u)) { return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; } - if ((spurs->m.wklMsk1.read_relaxed().ToLE() & (0x80000000u >> wid)) == 0) + if ((spurs->m.wklMskA.read_relaxed().ToLE() & (0x80000000u >> wid)) == 0) { return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; } @@ -1274,11 +1375,11 @@ s64 cellSpursReadyCountStore(vm::ptr spurs, u32 wid, u32 value) { return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; } - if (wid >= (spurs->m.flags1 & 0x40 ? 0x20u : 0x10u) || value > 0xff) + if (wid >= (spurs->m.flags1 & SF1_IS_SECOND ? 0x20u : 0x10u) || value > 0xff) { return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; } - if ((spurs->m.wklMsk1.read_relaxed().ToLE() & (0x80000000u >> wid)) == 0) + if ((spurs->m.wklMskA.read_relaxed().ToLE() & (0x80000000u >> wid)) == 0) { return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 87a01466f1..873c14d6ca 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -141,8 +141,10 @@ struct CellSpurs; enum SpursAttrFlags : u32 { SAF_NONE = 0x0, + SAF_EXIT_IF_NO_WORK = 0x1, - SAF_SECOND_VERSION = 0x4, + SAF_UNKNOWN_FLAG_30 = 0x2, + SAF_SECOND_VERSION = 0x4, SAF_UNKNOWN_FLAG_9 = 0x00400000, SAF_UNKNOWN_FLAG_8 = 0x00800000, @@ -154,6 +156,14 @@ enum SpursAttrFlags : u32 SAF_UNKNOWN_FLAG_0 = 0x80000000, }; +enum SpursFlags1 : u8 +{ + SF1_NONE = 0x0, + + SF1_IS_SECOND = 0x40, + SF1_EXIT_IF_NO_WORK = 0x80, +}; + struct CellSpursAttribute { static const uint align = 8; @@ -279,8 +289,8 @@ struct CellSpurs atomic_t wklStat1[0x10]; // 0x80 u8 wklD1[0x10]; // 0x90 u8 wklE1[0x10]; // 0xA0 - atomic_t wklMsk1; // 0xB0 - atomic_t wklMsk2; // 0xB4 + atomic_t wklMskA; // 0xB0 + atomic_t wklMskB; // 0xB4 u8 xB8[5]; // 0xB8 atomic_t xBD; // 0xBD u8 xBE[2]; // 0xBE @@ -361,6 +371,16 @@ struct CellSpurs return m.wklStat1[wid & 0xf]; } } + + __forceinline vm::ptr get_lwmutex() + { + return vm::ptr::make(Memory.RealToVirtualAddr(&m.mutex)); + } + + __forceinline vm::ptr get_lwcond() + { + return vm::ptr::make(Memory.RealToVirtualAddr(&m.cond)); + } }; typedef CellSpurs CellSpurs2; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 5592521d18..4a0e1a3ccd 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -1087,7 +1087,7 @@ s32 syncLFQueueGetPushPointer(vm::ptr queue, s32& pointer, u32 } } - assert(sys_event_queue_receive(queue->m_eq_id, {}, 0) == CELL_OK); + assert(sys_event_queue_receive(queue->m_eq_id, vm::ptr::make(0), 0) == CELL_OK); var1 = 1; } } @@ -1466,7 +1466,7 @@ s32 syncLFQueueGetPopPointer(vm::ptr queue, s32& pointer, u32 i } } - assert(sys_event_queue_receive(queue->m_eq_id, {}, 0) == CELL_OK); + assert(sys_event_queue_receive(queue->m_eq_id, vm::ptr::make(0), 0) == CELL_OK); var1 = 1; } } From ce97a7e7a605f6eb8189e844826cb505dc6d1ae4 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 30 Sep 2014 23:06:04 +0400 Subject: [PATCH 21/24] Channel<> rewritten --- rpcs3/Emu/Cell/SPUThread.h | 227 +++++++++------------- rpcs3/Emu/Memory/vm.h | 1 - rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 21 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 2 +- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 1 + rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp | 1 + rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 2 +- 7 files changed, 103 insertions(+), 152 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index eba9dd6a0c..d8df863bc6 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -1,4 +1,5 @@ #pragma once +#include "Emu/Memory/atomic_type.h" #include "PPCThread.h" #include "Emu/Event.h" #include "MFC.h" @@ -246,181 +247,127 @@ public: } } m_intrtag[3]; - template + // limited lock-free queue, most functions are barrier-free + template class Channel { - public: - static const size_t max_count = _max_count; + static_assert(max_count >= 1, "Invalid channel count"); - private: - union _CRT_ALIGN(8) { - struct { - volatile u32 m_index; - u32 m_value[max_count]; - }; - volatile u64 m_indval; + struct ChannelData + { + u32 value; + u32 is_set; }; - std::mutex m_lock; + + atomic_t m_data[max_count]; + size_t m_push; + size_t m_pop; public: - Channel() + __noinline Channel() { - Init(); - } - - void Init() - { - m_indval = 0; - } - - __forceinline bool Pop(u32& res) - { - if (max_count > 1) + for (size_t i = 0; i < max_count; i++) { - std::lock_guard lock(m_lock); - if(!m_index) - { - return false; - } - res = m_value[0]; - if (max_count > 1) for (u32 i = 1; i < max_count; i++) // FIFO - { - m_value[i-1] = m_value[i]; - } - m_value[max_count-1] = 0; - m_index--; - return true; - } - else - { //lock-free - if ((m_indval & 0xffffffff) == 0) - return false; - else - { - res = (m_indval >> 32); - m_indval = 0; - return true; - } - } - } - - __forceinline bool Push(u32 value) - { - if (max_count > 1) - { - std::lock_guard lock(m_lock); - if(m_index >= max_count) - { - return false; - } - m_value[m_index++] = value; - return true; - } - else - { //lock-free - if (m_indval & 0xffffffff) - return false; - else - { - const u64 new_value = ((u64)value << 32) | 1; - m_indval = new_value; - return true; - } - } - } - - __forceinline void PushUncond(u32 value) - { - if (max_count > 1) - { - std::lock_guard lock(m_lock); - if(m_index >= max_count) - m_value[max_count-1] = value; //last message is overwritten - else - m_value[m_index++] = value; - } - else - { //lock-free - const u64 new_value = ((u64)value << 32) | 1; - m_indval = new_value; - } - } - - __forceinline void PushUncond_OR(u32 value) - { - if (max_count > 1) - { - std::lock_guard lock(m_lock); - if(m_index >= max_count) - m_value[max_count-1] |= value; //last message is logically ORed - else - m_value[m_index++] = value; - } - else - { - InterlockedOr(&m_indval, ((u64)value << 32) | 1); + m_data[i].write_relaxed({}); } + m_push = 0; + m_pop = 0; } __forceinline void PopUncond(u32& res) { - if (max_count > 1) - { - std::lock_guard lock(m_lock); - if(!m_index) - res = 0; //result is undefined - else - { - res = m_value[--m_index]; - m_value[m_index] = 0; - } - } - else - { //lock-free - if(!m_index) - res = 0; - else - { - res = (m_indval >> 32); - m_indval = 0; - } - } + res = m_data[m_pop].read_relaxed().value; + m_data[m_pop].write_relaxed({}); + m_pop = (m_pop + 1) % max_count; } - __forceinline u32 GetCount() + __forceinline bool Pop(u32& res) { - if (max_count > 1) + const auto data = m_data[m_pop].read_relaxed(); + if (data.is_set) { - std::lock_guard lock(m_lock); - return m_index; + res = data.value; + m_data[m_pop].write_relaxed({}); + m_pop = (m_pop + 1) % max_count; + return true; } else { - return m_index; + return false; } } - __forceinline u32 GetFreeCount() + __forceinline bool Pop_XCHG(u32& res) // not barrier-free, not tested { - if (max_count > 1) + const auto data = m_data[m_pop].exchange({}); + if (data.is_set) { - std::lock_guard lock(m_lock); - return max_count - m_index; + res = data.value; + m_pop = (m_pop + 1) % max_count; + return true; } else { - return max_count - m_index; + return false; } } - void SetValue(u32 value) + __forceinline void PushUncond_OR(const u32 value) // not barrier-free, not tested { - m_value[0] = value; + m_data[m_push]._or({ value, 1 }); + m_push = (m_push + 1) % max_count; } - u32 GetValue() const + __forceinline void PushUncond(const u32 value) { - return m_value[0]; + m_data[m_push].write_relaxed({ value, 1 }); + m_push = (m_push + 1) % max_count; + } + + __forceinline bool Push(const u32 value) + { + if (m_data[m_push].read_relaxed().is_set) + { + return false; + } + else + { + PushUncond(value); + return true; + } + } + + __forceinline u32 GetCount() const + { + u32 res = 0; + for (size_t i = 0; i < max_count; i++) + { + res += m_data[i].read_relaxed().is_set ? 1 : 0; + } + return res; + } + + __forceinline u32 GetFreeCount() const + { + u32 res = 0; + for (size_t i = 0; i < max_count; i++) + { + res += m_data[i].read_relaxed().is_set ? 0 : 1; + } + return res; + } + + __forceinline void SetValue(const u32 value) + { + m_data[m_push].direct_op([value](ChannelData& v) + { + v.value = value; + }); + } + + __forceinline u32 GetValue() const + { + return m_data[m_pop].read_relaxed().value; } }; diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index d272df0744..bf300eb175 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -205,4 +205,3 @@ namespace vm #include "vm_ref.h" #include "vm_ptr.h" #include "vm_var.h" -#include "atomic_type.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index feb8651edc..51e6d2d84f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -241,7 +241,7 @@ s64 spursInit( { if (spurs->m.wklStat1[i].read_relaxed() == 2 && spurs->m.wklG1[i].wklPriority.ToBE() != 0 && - spurs->_u8[0x50 + i] & 0xf // check wklMaxCnt + spurs->m.wklMaxCnt[i].read_relaxed() & 0xf ) { if (spurs->m.wklReadyCount[i].read_relaxed() || @@ -259,7 +259,7 @@ s64 spursInit( { if (spurs->m.wklStat2[i].read_relaxed() == 2 && spurs->m.wklG2[i].wklPriority.ToBE() != 0 && - spurs->_u8[0x50 + i] & 0xf0 // check wklMaxCnt + spurs->m.wklMaxCnt[i].read_relaxed() & 0xf0 ) { if (spurs->m.wklReadyCount[i + 0x10].read_relaxed() || @@ -995,19 +995,22 @@ s32 spursAddWorkload( } spurs->m.wklReadyCount[wnum].write_relaxed(0); - u32 pos = ((~wnum * 8) | (wnum / 4)) & 0x1c; - spurs->m.wklMaxCnt[index / 4].atomic_op([pos, maxContention](be_t& v) - { - v &= ~(0xf << pos); - v |= (maxContention > 8 ? 8 : maxContention) << pos; - }); - if (wnum <= 15) { + spurs->m.wklMaxCnt[wnum].atomic_op([maxContention](u8& v) + { + v &= ~0xf; + v |= (maxContention > 8 ? 8 : maxContention); + }); spurs->m.wklSet1._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag1 } else { + spurs->m.wklMaxCnt[index].atomic_op([maxContention](u8& v) + { + v &= ~0xf0; + v |= (maxContention > 8 ? 8 : maxContention) << 4; + }); spurs->m.wklSet2._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag2 } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 873c14d6ca..587483c177 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -275,7 +275,7 @@ struct CellSpurs u8 wklA[0x10]; // 0x20 u8 wklB[0x10]; // 0x30 u8 wklMinCnt[0x10]; // 0x40 - atomic_t wklMaxCnt[4]; // 0x50 + atomic_t wklMaxCnt[0x10]; // 0x50 CellSpursWorkloadFlag wklFlag; // 0x60 atomic_t wklSet1; // 0x70 atomic_t x72; // 0x72 diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index 688109de37..f9e931ad60 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -3,6 +3,7 @@ #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/Callback.h" +#include "Emu/Memory/atomic_type.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/PPUThread.h" diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp index 36dc03fb3c..4a24c2b520 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/Memory/atomic_type.h" #include "sys_spinlock.h" diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 2f790c5ecf..adc2efb62a 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -589,7 +589,7 @@ s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr> value, u32 ty s32 sys_spu_thread_write_spu_mb(u32 id, u32 value) { - sys_spu.Log("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value); + sys_spu.Warning("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value); CPUThread* thr = Emu.GetCPU().GetThread(id); From 4a6779469c077f4dce16cb7166c410f9c38072a4 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 1 Oct 2014 17:18:38 +0400 Subject: [PATCH 22/24] Memory fixes --- rpcs3/Emu/Memory/Memory.cpp | 3 +- rpcs3/Emu/Memory/Memory.h | 1 - rpcs3/Emu/Memory/vm_ptr.h | 6 ++-- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 28 ++++++++--------- rpcs3/Emu/SysCalls/lv2/sys_vm.cpp | 33 ++++++++------------- 7 files changed, 32 insertions(+), 43 deletions(-) diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 50784d199a..005ccb8e6b 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -128,7 +128,6 @@ void MemoryBase::Init(MemoryType type) MemoryBlocks.push_back(MainMem.SetRange(0x00010000, 0x2FFF0000)); MemoryBlocks.push_back(UserMemory = PRXMem.SetRange(0x30000000, 0x10000000)); MemoryBlocks.push_back(RSXCMDMem.SetRange(0x40000000, 0x10000000)); - MemoryBlocks.push_back(MmaperMem.SetRange(0xB0000000, 0x10000000)); MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000)); MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000)); break; @@ -218,7 +217,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size) } MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size)); - LOG_WARNING(MEMORY, "MemoryBase::Map(0x%llx, 0x%x)", addr, size); + LOG_WARNING(MEMORY, "Memory mapped at 0x%llx: size=0x%x", addr, size); return true; } diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 394c48f399..bb6c83cc23 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -35,7 +35,6 @@ public: DynamicMemoryBlock MainMem; DynamicMemoryBlock PRXMem; DynamicMemoryBlock RSXCMDMem; - DynamicMemoryBlock MmaperMem; DynamicMemoryBlock RSXFBMem; DynamicMemoryBlock StackMem; MemoryBlock* RawSPUMem[(0x100000000 - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]; diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 9a7e150170..940f377ce8 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -366,7 +366,7 @@ namespace vm //BE pointer to LE data template struct bptrl : public _ptr_base::type> { - static bptrl make(AT addr) + static bptrl make(typename to_be_t::type addr) { return (bptrl&)addr; } @@ -378,7 +378,7 @@ namespace vm //BE pointer to BE data template struct bptrb : public _ptr_base::type, lvl, typename to_be_t::type> { - static bptrb make(AT addr) + static bptrb make(typename to_be_t::type addr) { return (bptrb&)addr; } @@ -428,7 +428,7 @@ namespace vm //default pointer for HLE structures (BE ptrerence to BE data) template struct bptr : public bptrb { - static bptr make(AT addr) + static bptr make(typename to_be_t::type addr) { return (bptr&)addr; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index ecc5bf8625..5f12fc853b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -178,7 +178,7 @@ void getSaveDataStat(SaveDataEntry entry, vm::ptr statGet) strcpy_trunc(statGet->getParam.listParam, entry.listParam); statGet->fileNum = 0; - statGet->fileList = vm::bptr::make(0); + statGet->fileList.set(be_t::make(0)); statGet->fileListNum = 0; std::string saveDir = "/dev_hdd0/home/00000001/savedata/" + entry.dirName; // TODO: Get the path of the current user vfsDir dir(saveDir); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 51e6d2d84f..cd91d4271c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -1337,7 +1337,7 @@ s64 cellSpursGetWorkloadFlag(vm::ptr spurs, vm::ptr::make(Memory.RealToVirtualAddr(&spurs->m.wklFlag)); + flag->set(be_t::make(Memory.RealToVirtualAddr(&spurs->m.wklFlag))); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 587483c177..6ce2ae8ee1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -271,20 +271,20 @@ struct CellSpurs // real data struct { - atomic_t wklReadyCount[0x20]; - u8 wklA[0x10]; // 0x20 - u8 wklB[0x10]; // 0x30 - u8 wklMinCnt[0x10]; // 0x40 - atomic_t wklMaxCnt[0x10]; // 0x50 + atomic_t wklReadyCount[0x20]; // 0x0 (index = wid) + u8 wklA[0x10]; // 0x20 (packed 4-bit data, index = wid % 16, internal index = wid / 16) + u8 wklB[0x10]; // 0x30 (packed 4-bit data, index = wid % 16, internal index = wid / 16) + u8 wklMinCnt[0x10]; // 0x40 (seems only for first 0..15 wids) + atomic_t wklMaxCnt[0x10]; // 0x50 (packed 4-bit data, index = wid % 16, internal index = wid / 16) CellSpursWorkloadFlag wklFlag; // 0x60 - atomic_t wklSet1; // 0x70 + atomic_t wklSet1; // 0x70 (bitset for 0..15 wids) atomic_t x72; // 0x72 u8 x73; // 0x73 u8 flags1; // 0x74 u8 x75; // 0x75 u8 nSpus; // 0x76 atomic_t flagRecv; // 0x77 - atomic_t wklSet2; // 0x78 + atomic_t wklSet2; // 0x78 (bitset for 16..32 wids) u8 x7A[6]; // 0x7A atomic_t wklStat1[0x10]; // 0x80 u8 wklD1[0x10]; // 0x90 @@ -314,7 +314,7 @@ struct CellSpurs be_t unk12; // 0x98C be_t unk13; // 0x990 u8 unknown4[0xB00 - 0x998]; - _sub_str3 wklG1[0x10];// 0xB00 + _sub_str3 wklG1[0x10]; // 0xB00 be_t unk7; // 0xD00 be_t unk8; // 0xD08 be_t unk9; // 0xD10 @@ -334,8 +334,8 @@ struct CellSpurs be_t exception; // 0xD6C sys_spu_image spuImg; // 0xD70 be_t flags; // 0xD80 - be_t spuPriority;// 0xD84 - be_t ppuPriority;// 0xD88 + be_t spuPriority; // 0xD84 + be_t ppuPriority; // 0xD88 char prefix[0x0f]; // 0xD8C u8 prefixSize; // 0xD9B be_t unk5; // 0xD9C @@ -345,12 +345,12 @@ struct CellSpurs sys_lwmutex_t mutex; // 0xDB0 sys_lwcond_t cond; // 0xDC8 u8 unknown9[0xE00 - 0xDD0]; - _sub_str4 wklH1[0x10];// 0xE00 + _sub_str4 wklH1[0x10]; // 0xE00 _sub_str2 sub3; // 0xF00 u8 unknown6[0x1000 - 0xF80]; - _sub_str3 wklG2[0x10];// 0x1000 - _sub_str1 wklF2[0x10];// 0x1200 - _sub_str4 wklH2[0x10];// 0x1A00 + _sub_str3 wklG2[0x10]; // 0x1000 + _sub_str1 wklF2[0x10]; // 0x1200 + _sub_str4 wklH2[0x10]; // 0x1A00 } m; // alternative implementation diff --git a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp index 5075183a71..8eca02c483 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp @@ -11,7 +11,7 @@ MemoryContainerInfo* current_ct; s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr) { - sys_vm.Todo("sys_vm_memory_map(vsize=0x%x,psize=0x%x,cidr=0x%x,flags=0x%llx,policy=0x%llx,addr=0x%x)", + sys_vm.Error("sys_vm_memory_map(vsize=0x%x, psize=0x%x, cidr=0x%x, flags=0x%llx, policy=0x%llx, addr_addr=0x%x)", vsize, psize, cid, flag, policy, addr); // Check virtual size. @@ -26,25 +26,12 @@ s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 a return CELL_ENOMEM; } + // Use fixed address (TODO: search and use some free address instead) + u32 new_addr = Memory.IsGoodAddr(0x60000000) ? 0x70000000 : 0x60000000; + // If container ID is SYS_MEMORY_CONTAINER_ID_INVALID, allocate directly. if(cid == SYS_MEMORY_CONTAINER_ID_INVALID) { - u32 new_addr; - switch(flag) - { - case SYS_MEMORY_PAGE_SIZE_1M: - new_addr = (u32)Memory.Alloc(psize, 0x100000); - break; - - case SYS_MEMORY_PAGE_SIZE_64K: - new_addr = (u32)Memory.Alloc(psize, 0x10000); - break; - - default: return CELL_EINVAL; - } - - if(!new_addr) return CELL_ENOMEM; - // Create a new MemoryContainerInfo to act as default container with vsize. current_ct = new MemoryContainerInfo(new_addr, vsize); } @@ -57,18 +44,22 @@ s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 a current_ct = ct; } + // Allocate actual memory using virtual size (physical size is ignored) + assert(Memory.Map(new_addr, vsize)); + // Write a pointer for the allocated memory. - vm::write32(addr, current_ct->addr); + vm::write32(addr, new_addr); return CELL_OK; } s32 sys_vm_unmap(u32 addr) { - sys_vm.Todo("sys_vm_unmap(addr=0x%x)", addr); + sys_vm.Error("sys_vm_unmap(addr=0x%x)", addr); - // Simply free the memory to unmap. - if(!Memory.Free(addr)) return CELL_EINVAL; + // Unmap memory. + assert(addr == 0x60000000 || addr == 0x70000000); + if(!Memory.Unmap(addr)) return CELL_EINVAL; return CELL_OK; } From 752449bbc005a5ef38191986c7fb8a42f6bc57cb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 2 Oct 2014 14:29:20 +0400 Subject: [PATCH 23/24] Small update --- Utilities/BEType.h | 10 +++ rpcs3/Emu/Cell/MFC.h | 1 - rpcs3/Emu/Cell/RawSPUThread.cpp | 2 +- rpcs3/Emu/Cell/SPUInterpreter.h | 2 +- rpcs3/Emu/Cell/SPURecompilerCore.cpp | 8 +- rpcs3/Emu/Cell/SPUThread.cpp | 97 +++++++++++++++++------- rpcs3/Emu/Cell/SPUThread.h | 3 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 95 +++++++++++++++++------ rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 28 +++---- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 3 +- 10 files changed, 173 insertions(+), 76 deletions(-) diff --git a/Utilities/BEType.h b/Utilities/BEType.h index ee5989f100..29848bc4ae 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -104,6 +104,16 @@ union u128 return ret; } + static u128 from32r(u32 _3, u32 _2 = 0, u32 _1 = 0, u32 _0 = 0) + { + u128 ret; + ret._u32[0] = _0; + ret._u32[1] = _1; + ret._u32[2] = _2; + ret._u32[3] = _3; + return ret; + } + static u128 fromBit(u32 bit) { u128 ret = {}; diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index 5669daabe9..a6c731d3da 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -61,5 +61,4 @@ enum struct DMAC { - u32 ls_offset; }; diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 0a8270e670..92e0425628 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -190,7 +190,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) void RawSPUThread::InitRegs() { - dmac.ls_offset = m_offset = (u32)GetStartAddr() + RAW_SPU_LS_OFFSET; + ls_offset = m_offset = (u32)GetStartAddr() + RAW_SPU_LS_OFFSET; SPUThread::InitRegs(); } diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index ac6e5df820..eb5b90eb7b 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -3,7 +3,7 @@ #define UNIMPLEMENTED() UNK(__FUNCTION__) #define MEM_AND_REG_HASH() \ - unsigned char mem_h[20]; sha1(vm::get_ptr(CPU.dmac.ls_offset), 256*1024, mem_h); \ + unsigned char mem_h[20]; sha1(vm::get_ptr(CPU.ls_offset), 256*1024, mem_h); \ unsigned char reg_h[20]; sha1((const unsigned char*)CPU.GPR, sizeof(CPU.GPR), reg_h); \ LOG_NOTICE(Log::SPU, "Mem hash: 0x%llx, reg hash: 0x%llx", *(u64*)mem_h, *(u64*)reg_h); diff --git a/rpcs3/Emu/Cell/SPURecompilerCore.cpp b/rpcs3/Emu/Cell/SPURecompilerCore.cpp index 68e929edf3..66c1181a34 100644 --- a/rpcs3/Emu/Cell/SPURecompilerCore.cpp +++ b/rpcs3/Emu/Cell/SPURecompilerCore.cpp @@ -49,7 +49,7 @@ void SPURecompilerCore::Compile(u16 pos) u64 time0 = 0; SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); - dis_asm.offset = vm::get_ptr(CPU.dmac.ls_offset); + dis_asm.offset = vm::get_ptr(CPU.ls_offset); StringLogger stringLogger; stringLogger.setOption(kLoggerOptionBinaryForm, true); @@ -103,7 +103,7 @@ void SPURecompilerCore::Compile(u16 pos) while (true) { - const u32 opcode = vm::read32(CPU.dmac.ls_offset + pos * 4); + const u32 opcode = vm::read32(CPU.ls_offset + pos * 4); m_enc->do_finalize = false; if (opcode) { @@ -182,8 +182,8 @@ void SPURecompilerCore::Compile(u16 pos) u8 SPURecompilerCore::DecodeMemory(const u32 address) { - assert(CPU.dmac.ls_offset == address - CPU.PC); - const u32 m_offset = CPU.dmac.ls_offset; + assert(CPU.ls_offset == address - CPU.PC); + const u32 m_offset = CPU.ls_offset; const u16 pos = (u16)(CPU.PC >> 2); //ConLog.Write("DecodeMemory: pos=%d", pos); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 0ff0af3c6a..6d494b7ca0 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -80,7 +80,7 @@ void SPUThread::InitRegs() cfg.Reset(); - dmac.ls_offset = m_offset; + ls_offset = m_offset; SPU.Status.SetValue(SPU_STATUS_STOPPED); @@ -148,19 +148,27 @@ void SPUThread::DoClose() void SPUThread::FastCall(u32 ls_addr) { - // doesn't touch thread status (instead of PPUThread::FastCall2); - // can't be called from another thread (because it doesn't make sense); - // FastStop-like routine is not defined (TODO); + // can't be called from another thread (because it doesn't make sense) + WriteLS32(0x0, 2); auto old_PC = PC; - auto old_stack = GPR[1]; // only saved and restored (may be wrong) + auto old_LR = GPR[0]._u32[3]; + auto old_stack = GPR[1]._u32[3]; // only saved and restored (may be wrong) + m_status = Running; PC = ls_addr; + GPR[0]._u32[3] = 0x0; CPUThread::Task(); PC = old_PC; - GPR[1] = old_stack; + GPR[0]._u32[3] = old_LR; + GPR[1]._u32[3] = old_stack; +} + +void SPUThread::FastStop() +{ + m_status = Stopped; } void SPUThread::WriteSNR(bool number, u32 value) @@ -206,11 +214,11 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) if ((addr <= 0x3ffff) && (addr + size <= 0x40000)) { // LS access - ea = spu->dmac.ls_offset + addr; + ea = spu->ls_offset + addr; } else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2)) { - spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(dmac.ls_offset + lsa)); + spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(ls_offset + lsa)); return; } else @@ -256,13 +264,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) { case MFC_PUT_CMD: { - memcpy(vm::get_ptr(ea), vm::get_ptr(dmac.ls_offset + lsa), size); + memcpy(vm::get_ptr(ea), vm::get_ptr(ls_offset + lsa), size); return; } case MFC_GET_CMD: { - memcpy(vm::get_ptr(dmac.ls_offset + lsa), vm::get_ptr(ea), size); + memcpy(vm::get_ptr(ls_offset + lsa), vm::get_ptr(ea), size); return; } @@ -294,7 +302,7 @@ void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFC for (u32 i = 0; i < list_size; i++) { - auto rec = vm::ptr::make(dmac.ls_offset + list_addr + i * 8); + auto rec = vm::ptr::make(ls_offset + list_addr + i * 8); u32 size = rec->ts; if (!(rec->s.ToBE() & se16(0x8000)) && size < 16 && size != 1 && size != 2 && size != 4 && size != 8) @@ -405,7 +413,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) for (u32 i = 0; i < 16; i++) { R_DATA[i] = vm::get_ptr(R_ADDR)[i]; - vm::get_ptr(dmac.ls_offset + lsa)[i] = R_DATA[i]; + vm::get_ptr(ls_offset + lsa)[i] = R_DATA[i]; } MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); } @@ -419,7 +427,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) u64 buf[16]; for (u32 i = 0; i < 16; i++) { - buf[i] = vm::get_ptr(dmac.ls_offset + lsa)[i]; + buf[i] = vm::get_ptr(ls_offset + lsa)[i]; if (buf[i] != R_DATA[i]) { changed++; @@ -464,8 +472,8 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4) { dis_asm.dump_pc = i; - dis_asm.offset = vm::get_ptr(dmac.ls_offset); - const u32 opcode = vm::read32(i + dmac.ls_offset); + dis_asm.offset = vm::get_ptr(ls_offset); + const u32 opcode = vm::read32(i + ls_offset); (*SPU_instr::rrr_list)(&dis_asm, opcode); if (i >= 0 && i < 0x40000) { @@ -526,18 +534,20 @@ bool SPUThread::CheckEvents() u32 SPUThread::GetChannelCount(u32 ch) { + u32 res = 0xdeafbeef; + switch (ch) { - case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount(); - case SPU_WrOutIntrMbox: return SPU.Out_IntrMBox.GetFreeCount(); - case SPU_RdInMbox: return SPU.In_MBox.GetCount(); - case MFC_RdTagStat: return MFC1.TagStatus.GetCount(); - case MFC_RdListStallStat: return StallStat.GetCount(); - case MFC_WrTagUpdate: return MFC1.TagStatus.GetCount(); // hack - case SPU_RdSigNotify1: return SPU.SNR[0].GetCount(); - case SPU_RdSigNotify2: return SPU.SNR[1].GetCount(); - case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount(); - case SPU_RdEventStat: return CheckEvents() ? 1 : 0; + case SPU_WrOutMbox: res = SPU.Out_MBox.GetFreeCount(); break; + case SPU_WrOutIntrMbox: res = SPU.Out_IntrMBox.GetFreeCount(); break; + case SPU_RdInMbox: res = SPU.In_MBox.GetCount(); break; + case MFC_RdTagStat: res = MFC1.TagStatus.GetCount(); break; + case MFC_RdListStallStat: res = StallStat.GetCount(); break; + case MFC_WrTagUpdate: res = MFC1.TagStatus.GetCount(); break;// hack + case SPU_RdSigNotify1: res = SPU.SNR[0].GetCount(); break; + case SPU_RdSigNotify2: res = SPU.SNR[1].GetCount(); break; + case MFC_RdAtomicStat: res = MFC1.AtomicStat.GetCount(); break; + case SPU_RdEventStat: res = CheckEvents() ? 1 : 0; break; default: { @@ -546,12 +556,17 @@ u32 SPUThread::GetChannelCount(u32 ch) return 0; } } + + //LOG_NOTICE(Log::SPU, "%s(%s) -> 0x%x", __FUNCTION__, spu_ch_name[ch], res); + return res; } void SPUThread::WriteChannel(u32 ch, const u128& r) { const u32 v = r._u32[3]; + //LOG_NOTICE(Log::SPU, "%s(%s): v=0x%x", __FUNCTION__, spu_ch_name[ch], v); + switch (ch) { case SPU_WrOutIntrMbox: @@ -908,13 +923,27 @@ void SPUThread::ReadChannel(u128& r, u32 ch) case SPU_RdSigNotify1: { - while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if (cfg.value & 1) + { + while (!SPU.SNR[0].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + else + { + while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } break; } case SPU_RdSigNotify2: { - while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if (cfg.value & 2) + { + while (!SPU.SNR[1].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + else + { + while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } break; } @@ -964,6 +993,8 @@ void SPUThread::ReadChannel(u128& r, u32 ch) } if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); + + //LOG_NOTICE(Log::SPU, "%s(%s) -> 0x%x", __FUNCTION__, spu_ch_name[ch], v); } void SPUThread::StopAndSignal(u32 code) @@ -973,6 +1004,18 @@ void SPUThread::StopAndSignal(u32 code) switch (code) { + case 0x001: + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + break; + } + + case 0x002: + { + FastStop(); + break; + } + case 0x110: { /* ===== sys_spu_thread_receive_event ===== */ diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index d8df863bc6..f97c9b2cd6 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -420,7 +420,7 @@ public: struct { u32 EAH, EAL; }; }; - DMAC dmac; + u32 ls_offset; void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size); @@ -510,6 +510,7 @@ public: virtual void InitRegs(); virtual void Task(); void FastCall(u32 ls_addr); + void FastStop(); protected: virtual void DoReset(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index cd91d4271c..f47af44642 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -102,14 +102,16 @@ s64 spursInit( { spurs->m.xC0[i] = -1; } + + // default or system workload: #ifdef PRX_DEBUG - spurs->m.unk7 = vm::read32(libsre_rtoc - 0x7EA4); // write 64-bit pointer to unknown data + spurs->m.wklSysG.pm.set(be_t::make(vm::read32(libsre_rtoc - 0x7EA4))); #else - spurs->m.unk7 = 0x7ull << 48 | 0x7; // wrong 64-bit address + spurs->m.wklSysG.pm.set(be_t::make(0x100)); // wrong 64-bit address #endif - spurs->m.unk8 = 0ull; - spurs->m.unk9 = 0x2200; - spurs->m.unk10 = -1; + spurs->m.wklSysG.data = 0; + spurs->m.wklSysG.size = 0x2200; + spurs->m.wklSysG.copy.write_relaxed(0xff); u32 sem; for (u32 i = 0; i < 0x10; i++) { @@ -161,13 +163,58 @@ s64 spursInit( name += "CellSpursKernel0"; for (s32 num = 0; num < nSpus; num++, name[name.size() - 1]++) { - spurs->m.spus[num] = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, 0, 0, 0, 0, [spurs, num, isSecond](SPUThread& CPU) + spurs->m.spus[num] = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, 0, 0, 0, 0, [spurs, num, isSecond](SPUThread& SPU) { -#ifdef PRX_DEBUG - CPU.GPR[3]._u32[3] = num; - CPU.GPR[4]._u64[1] = spurs.addr(); - return CPU.FastCall(CPU.PC); +#ifdef PRX_DEBUG_XXX + SPU.GPR[3]._u32[3] = num; + SPU.GPR[4]._u64[1] = spurs.addr(); + return SPU.FastCall(SPU.PC); #endif + SPU.WriteLS128(0x1c0, u128::from32r(0, spurs.addr(), num, 0x1f)); + + u32 wid = 0x20; + while (true) + { + if (Emu.IsStopped()) + { + cellSpurs->Warning("Spurs Kernel aborted"); + return; + } + + // get current workload info: + auto& wkl = wid <= 15 ? spurs->m.wklG1[wid] : (wid <= 31 && isSecond ? spurs->m.wklG2[wid & 0xf] : spurs->m.wklSysG); + + if (SPU.ReadLS64(0x1d0) != wkl.pm.addr()) + { + // load executable code: + memcpy(vm::get_ptr(SPU.ls_offset + 0xa00), wkl.pm.get_ptr(), wkl.size); + SPU.WriteLS64(0x1d0, wkl.pm.addr()); + SPU.WriteLS32(0x1d8, wkl.priority.ToLE() >> 24 & 0xff); // ??? + } + + if (!isSecond) SPU.WriteLS16(0x1e8, 0); + + // run workload: + SPU.GPR[1]._u32[3] = 0x3FFB0; + SPU.GPR[3]._u32[3] = 0x100; + SPU.GPR[4]._u64[1] = wkl.data; + SPU.GPR[5]._u32[3] = 0; + SPU.FastCall(0xa00); + + // check status: + auto status = SPU.SPU.Status.GetValue(); + if (status == SPU_STATUS_STOPPED_BY_STOP) + { + return; + } + else + { + assert(status == SPU_STATUS_RUNNING); + } + + // get workload id: + + } })->GetId(); } @@ -240,7 +287,7 @@ s64 spursInit( for (u32 i = 0; i < 16; i++) { if (spurs->m.wklStat1[i].read_relaxed() == 2 && - spurs->m.wklG1[i].wklPriority.ToBE() != 0 && + spurs->m.wklG1[i].priority.ToBE() != 0 && spurs->m.wklMaxCnt[i].read_relaxed() & 0xf ) { @@ -258,7 +305,7 @@ s64 spursInit( if (spurs->m.flags1 & SF1_IS_SECOND) for (u32 i = 0; i < 16; i++) { if (spurs->m.wklStat2[i].read_relaxed() == 2 && - spurs->m.wklG2[i].wklPriority.ToBE() != 0 && + spurs->m.wklG2[i].priority.ToBE() != 0 && spurs->m.wklMaxCnt[i].read_relaxed() & 0xf0 ) { @@ -951,10 +998,10 @@ s32 spursAddWorkload( spurs->m.wklStat1[wnum].write_relaxed(1); spurs->m.wklD1[wnum] = 0; spurs->m.wklE1[wnum] = 0; - spurs->m.wklG1[wnum].wklPm = pm; - spurs->m.wklG1[wnum].wklArg = data; - spurs->m.wklG1[wnum].wklSize = size; - spurs->m.wklG1[wnum].wklPriority = *(be_t*)priorityTable; + spurs->m.wklG1[wnum].pm = pm; + spurs->m.wklG1[wnum].data = data; + spurs->m.wklG1[wnum].size = size; + spurs->m.wklG1[wnum].priority = *(be_t*)priorityTable; spurs->m.wklH1[wnum].nameClass = nameClass; spurs->m.wklH1[wnum].nameInstance = nameInstance; memset(spurs->m.wklF1[wnum].unk0, 0, 0x20); // clear struct preserving semaphore id @@ -978,10 +1025,10 @@ s32 spursAddWorkload( spurs->m.wklStat2[index].write_relaxed(1); spurs->m.wklD2[index] = 0; spurs->m.wklE2[index] = 0; - spurs->m.wklG2[index].wklPm = pm; - spurs->m.wklG2[index].wklArg = data; - spurs->m.wklG2[index].wklSize = size; - spurs->m.wklG2[index].wklPriority = *(be_t*)priorityTable; + spurs->m.wklG2[index].pm = pm; + spurs->m.wklG2[index].data = data; + spurs->m.wklG2[index].size = size; + spurs->m.wklG2[index].priority = *(be_t*)priorityTable; spurs->m.wklH2[index].nameClass = nameClass; spurs->m.wklH2[index].nameInstance = nameInstance; memset(spurs->m.wklF2[index].unk0, 0, 0x20); // clear struct preserving semaphore id @@ -1034,21 +1081,21 @@ s32 spursAddWorkload( if (mask & m) { CellSpurs::_sub_str3& current = i <= 15 ? spurs->m.wklG1[i] : spurs->m.wklG2[i & 0xf]; - if (current.wklPm.addr() == wkl.wklPm.addr()) + if (current.pm.addr() == wkl.pm.addr()) { // if a workload with identical policy module found - res_wkl = current.wklCopy.read_relaxed(); + res_wkl = current.copy.read_relaxed(); break; } else { - k |= 0x80000000 >> current.wklCopy.read_relaxed(); + k |= 0x80000000 >> current.copy.read_relaxed(); res_wkl = cntlz32(~k); } } } - wkl.wklCopy.exchange((u8)res_wkl); + wkl.copy.exchange((u8)res_wkl); v = mask | (0x80000000u >> wnum); }); assert(res_wkl <= 31); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 6ce2ae8ee1..4e72b50826 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -221,8 +221,6 @@ struct CellSpurs struct _sub_str1 { - static const uint size = 0x80; - u8 unk0[0x20]; be_t sem; // 0x20 u8 unk1[0x8]; @@ -231,10 +229,10 @@ struct CellSpurs u8 unk2[0x40]; }; + static_assert(sizeof(_sub_str1) == 0x80, "Wrong _sub_str1 size"); + struct _sub_str2 { - static const uint size = 0x80; - be_t unk0; be_t unk1; be_t unk2; @@ -243,17 +241,19 @@ struct CellSpurs u8 unk_[0x68]; }; + static_assert(sizeof(_sub_str2) == 0x80, "Wrong _sub_str2 size"); + struct _sub_str3 { - static const uint size = 0x20; - - vm::bptr wklPm; // policy module - be_t wklArg; // spu argument - be_t wklSize; - atomic_t wklCopy; - be_t wklPriority; + vm::bptr pm; // policy module + be_t data; // spu argument + be_t size; + atomic_t copy; + be_t priority; }; + static_assert(sizeof(_sub_str3) == 0x20, "Wrong _sub_str3 size"); + struct _sub_str4 { static const uint size = 0x10; @@ -315,11 +315,7 @@ struct CellSpurs be_t unk13; // 0x990 u8 unknown4[0xB00 - 0x998]; _sub_str3 wklG1[0x10]; // 0xB00 - be_t unk7; // 0xD00 - be_t unk8; // 0xD08 - be_t unk9; // 0xD10 - u8 unk10; // 0xD14 - u8 unknown5[0xD20 - 0xD15]; + _sub_str3 wklSysG; // 0xD00 be_t ppu0; // 0xD20 be_t ppu1; // 0xD28 be_t spuTG; // 0xD30 diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index adc2efb62a..94326ef56e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -236,6 +236,7 @@ s32 sys_spu_thread_group_start(u32 id) CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]); if (t) { + ((SPUThread*)t)->SPU.Status.SetValue(SPU_STATUS_RUNNING); t->Exec(); } } @@ -471,7 +472,7 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr> cause, vm::ptrlist[i])) { - if (!t->IsRunning()) + if (!t->IsAlive()) { if (((SPUThread*)t)->SPU.Status.GetValue() != SPU_STATUS_STOPPED_BY_STOP) { From 74007d5e5d84f5fbc965949132c78c25807d7bde Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 4 Oct 2014 18:43:46 +0400 Subject: [PATCH 24/24] Small changes in memory and RSXIOMem Some bugs fixed, some other changes. --- rpcs3/Emu/Cell/SPUInterpreter.h | 5 +- rpcs3/Emu/Cell/SPURecompiler.h | 6 +- rpcs3/Emu/Cell/SPUThread.cpp | 6 ++ rpcs3/Emu/Cell/SPUThread.h | 3 +- rpcs3/Emu/Memory/Memory.cpp | 70 +++++++++++------------ rpcs3/Emu/Memory/MemoryBlock.h | 7 ++- rpcs3/Emu/Memory/vm.h | 12 ---- rpcs3/Emu/RSX/RSXThread.cpp | 30 ++++++---- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 29 +++++----- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 11 +++- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 4 +- rpcs3/Emu/SysCalls/lv2/sys_vm.cpp | 2 +- rpcs3/Loader/ELF64.cpp | 2 +- 13 files changed, 95 insertions(+), 92 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index eb5b90eb7b..d903353991 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -432,9 +432,7 @@ private: } void LQX(u32 rt, u32 ra, u32 rb) { - u32 a = CPU.GPR[ra]._u32[3], b = CPU.GPR[rb]._u32[3]; - - u32 lsa = (a + b) & 0x3fff0; + u32 lsa = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0x3fff0; CPU.GPR[rt] = CPU.ReadLS128(lsa); } @@ -1088,6 +1086,7 @@ private: for (int i = 0; i < 4; i++) { CPU.GPR[rt]._f[i] = (float)CPU.GPR[ra]._u32[i]; + u32 exp = ((CPU.GPR[rt]._u32[i] >> 23) & 0xff) - scale; if (exp > 255) //< 0 diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 455e058658..dafae1842b 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -1964,12 +1964,12 @@ private: void CLZ(u32 rt, u32 ra) { XmmInvalidate(rt); + c.mov(*qw0, 32 + 31); for (u32 i = 0; i < 4; i++) { c.bsr(*addr, cpu_dword(GPR[ra]._u32[i])); - c.cmovz(*addr, dword_ptr(*g_imm_var, (s32)offsetof(g_imm_table_struct, fsmb_table[0xffff]))); // load 0xffffffff - c.neg(*addr); - c.add(*addr, 31); + c.cmovz(*addr, qw0->r32()); + c.xor_(*addr, 31); c.mov(cpu_dword(GPR[rt]._u32[i]), *addr); } LOG_OPCODE(); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 6d494b7ca0..04bb14b88f 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1016,6 +1016,12 @@ void SPUThread::StopAndSignal(u32 code) break; } + case 0x003: + { + GPR[3]._u32[3] = m_code3_func(*this); + break; + } + case 0x110: { /* ===== sys_spu_thread_receive_event ===== */ diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index f97c9b2cd6..8eef83d71f 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -450,7 +450,8 @@ public: void WriteLS64 (const u32 lsa, const u64& data) const { vm::write64 (lsa + m_offset, data); } void WriteLS128(const u32 lsa, const u128& data) const { vm::write128(lsa + m_offset, data); } - std::function m_custom_task; + std::function m_custom_task; + std::function m_code3_func; public: SPUThread(CPUThreadType type = CPU_THREAD_SPU); diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index c11f8e2de0..1cc432d4cd 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -578,73 +578,71 @@ bool VirtualMemoryBlock::IsMyAddress(const u64 addr) return false; } -u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr) +u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size) { - if(addr) + for (u64 addr = GetStartAddr(); addr <= GetEndAddr() - GetReservedAmount() - size;) { - if(!IsInMyRange(addr, size) && (IsMyAddress(addr) || IsMyAddress(addr + size - 1))) - return 0; + bool is_good_addr = true; - m_mapped_memory.emplace_back(addr, realaddr, size); - return addr; - } - else - { - for(u64 addr = GetStartAddr(); addr <= GetEndAddr() - GetReservedAmount() - size;) + // check if address is already mapped + for (u32 i = 0; i= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) || + (m_mapped_memory[i].addr >= addr && m_mapped_memory[i].addr < addr + size)) { - if((addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) || - (m_mapped_memory[i].addr >= addr && m_mapped_memory[i].addr < addr + size)) - { - is_good_addr = false; - addr = m_mapped_memory[i].addr + m_mapped_memory[i].size; - break; - } + is_good_addr = false; + addr = m_mapped_memory[i].addr + m_mapped_memory[i].size; + break; } - - if(!is_good_addr) continue; - - m_mapped_memory.emplace_back(addr, realaddr, size); - - return addr; } - return 0; + if (!is_good_addr) continue; + + m_mapped_memory.emplace_back(addr, realaddr, size); + + return addr; } + + return 0; } -u32 VirtualMemoryBlock::UnmapRealAddress(u64 realaddr) +bool VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr) +{ + if(!IsInMyRange(addr, size) && (IsMyAddress(addr) || IsMyAddress(addr + size - 1))) + return false; + + m_mapped_memory.emplace_back(addr, realaddr, size); + return true; +} + +bool VirtualMemoryBlock::UnmapRealAddress(u64 realaddr, u32& size) { for(u32 i=0; i - T* const get_ptr(u64 addr) - { - return get_ptr((u32)addr); - } template T& get_ref(u32 addr) @@ -25,12 +19,6 @@ namespace vm return *get_ptr(addr); } - template - T& get_ref(u64 addr) - { - return get_ref((u32)addr); - } - namespace ps3 { static u8 read8(u32 addr) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 02231cf848..b1de17eb0e 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -48,7 +48,7 @@ u32 GetAddress(u32 offset, u32 location) switch(location) { case CELL_GCM_LOCATION_LOCAL: return (u32)Memory.RSXFBMem.GetStartAddr() + offset; - case CELL_GCM_LOCATION_MAIN: return (u32)Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + offset); // TODO: Error Check? + case CELL_GCM_LOCATION_MAIN: return (u32)Memory.RSXIOMem.RealAddr(offset); // TODO: Error Check? } LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x)", location); @@ -296,9 +296,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const if(m_flip_handler) { auto cb = m_flip_handler; - Emu.GetCallbackManager().Async([cb]() + Emu.GetCallbackManager().Register([cb]() { cb(1); + return 0; }); } @@ -1947,13 +1948,17 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u8* pixels_src = vm::get_ptr(GetAddress(offset, m_context_dma_img_src - 0xfeed0000)); u8* pixels_dst = vm::get_ptr(GetAddress(m_dst_offset, m_context_dma_img_dst - 0xfeed0000)); + LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: width=%d, height=%d, pitch=%d, origin=%d, inter=%d, offset=0x%x, u=%d, v=%d", width, height, pitch, origin, inter, offset, u, v); + LOG_WARNING(RSX, "*** m_dst_offset=0x%x, m_color: conv_in_h=0x%x, format_src_pitch=0x%x, conv_in_x=0x%x, conv_in_y=0x%x, conv_out_x=0x%x, conv_out_y=0x%x", + m_dst_offset, m_color_conv_in_h, m_color_format_src_pitch, m_color_conv_in_x, m_color_conv_in_y, m_color_conv_out_x, m_color_conv_out_y); + for(u16 y=0; y> 18) & 0x7ff; //if(cmd == 0) continue; + //LOG_NOTICE(Log::RSX, "put=0x%x, get=0x%x, cmd=0x%x (%s)", put, get, cmd, GetMethodName(cmd & 0xffff).c_str()); if(cmd & CELL_GCM_METHOD_FLAG_JUMP) { @@ -2212,7 +2220,7 @@ void RSXThread::Task() { m_call_stack.push(get + 4); u32 offs = cmd & ~CELL_GCM_METHOD_FLAG_CALL; - //u32 addr = Memory.RSXIOMem.GetStartAddr() + offs; + //u32 addr = offs; //LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x - 0x%x", offs, addr, cmd, get); m_ctrl->get = offs; continue; @@ -2234,14 +2242,14 @@ void RSXThread::Task() if(cmd == 0) { + LOG_ERROR(Log::RSX, "null cmd: cmd=0x%x, put=0x%x, get=0x%x (addr=0x%x)", cmd, put, get, (u32)Memory.RSXIOMem.RealAddr(get)); + Emu.Pause(); //HACK! We couldn't be here - //ConLog.Error("null cmd: addr=0x%x, put=0x%x, get=0x%x", Memory.RSXIOMem.GetStartAddr() + get, m_ctrl->put, get); - //Emu.Pause(); m_ctrl->get = get + (count + 1) * 4; continue; } - auto args = vm::ptr>::make((u32)Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + get + 4)); + auto args = vm::ptr>::make((u32)Memory.RSXIOMem.RealAddr(get + 4)); for(u32 i=0; i context, u32 cmdSize, u32 ioSiz if (system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB) { cellGcmSys->Warning("cellGcmInit(): 512MB io address space used"); - Memory.RSXIOMem.SetRange(0x50000000, 0x20000000 /*512MB*/); + Memory.RSXIOMem.SetRange(0, 0x20000000 /*512MB*/); } else { cellGcmSys->Warning("cellGcmInit(): 256MB io address space used"); - Memory.RSXIOMem.SetRange(0x50000000, 0x10000000 /*256MB*/); + Memory.RSXIOMem.SetRange(0, 0x10000000 /*256MB*/); } if(cellGcmMapEaIoAddress(ioAddress, 0, ioSize) != CELL_OK) @@ -833,7 +833,7 @@ u32 cellGcmGetMaxIoMapSize() { cellGcmSys->Log("cellGcmGetMaxIoMapSize()"); - return (u32)(Memory.RSXIOMem.GetEndAddr() - Memory.RSXIOMem.GetStartAddr() - Memory.RSXIOMem.GetReservedAmount()); + return (u32)(Memory.RSXIOMem.GetEndAddr() - Memory.RSXIOMem.GetReservedAmount()); } void cellGcmGetOffsetTable(vm::ptr table) @@ -850,7 +850,7 @@ s32 cellGcmIoOffsetToAddress(u32 ioOffset, u64 address) u64 realAddr; - if (!Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + ioOffset, realAddr)) + if (!Memory.RSXIOMem.getRealAddr(ioOffset, realAddr)) return CELL_GCM_ERROR_FAILURE; vm::write64(address, realAddr); @@ -865,7 +865,7 @@ s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size) if ((ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE; // Check if the mapping was successfull - if (Memory.RSXIOMem.Map(ea, size, Memory.RSXIOMem.GetStartAddr() + io)) + if (Memory.RSXIOMem.Map(ea, size, io)) { // Fill the offset table for (u32 i = 0; i<(size >> 20); i++) @@ -914,16 +914,13 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr> offset) { cellGcmSys->Warning("cellGcmMapMainMemory(ea=0x%x,size=0x%x,offset_addr=0x%x)", ea, size, offset.addr()); - u32 io; - if ((ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE; - //check if the mapping was successfull - if (io = (u32)Memory.RSXIOMem.Map(ea, size, 0)) - { - // convert to offset - io = io - (u32)Memory.RSXIOMem.GetStartAddr(); + u32 io = Memory.RSXIOMem.Map(ea, size); + //check if the mapping was successfull + if (Memory.RSXIOMem.Write32(io, 0)) + { //fill the offset table for (u32 i = 0; i<(size >> 20); i++) { @@ -968,8 +965,8 @@ s32 cellGcmUnmapEaIoAddress(u64 ea) { cellGcmSys->Log("cellGcmUnmapEaIoAddress(ea=0x%llx)", ea); - u32 size = Memory.RSXIOMem.UnmapRealAddress(ea); - if (size) + u32 size; + if (Memory.RSXIOMem.UnmapRealAddress(ea, size)) { u64 io; ea = ea >> 20; @@ -994,8 +991,8 @@ s32 cellGcmUnmapIoAddress(u64 io) { cellGcmSys->Log("cellGcmUnmapIoAddress(io=0x%llx)", io); - u32 size = Memory.RSXIOMem.UnmapAddress(io); - if (size) + u32 size; + if (Memory.RSXIOMem.UnmapAddress(io, size)) { u64 ea; io = io >> 20; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index f47af44642..ac46056b38 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -106,11 +106,11 @@ s64 spursInit( // default or system workload: #ifdef PRX_DEBUG spurs->m.wklSysG.pm.set(be_t::make(vm::read32(libsre_rtoc - 0x7EA4))); + spurs->m.wklSysG.size = 0x2200; #else spurs->m.wklSysG.pm.set(be_t::make(0x100)); // wrong 64-bit address #endif spurs->m.wklSysG.data = 0; - spurs->m.wklSysG.size = 0x2200; spurs->m.wklSysG.copy.write_relaxed(0xff); u32 sem; for (u32 i = 0; i < 0x10; i++) @@ -170,6 +170,10 @@ s64 spursInit( SPU.GPR[4]._u64[1] = spurs.addr(); return SPU.FastCall(SPU.PC); #endif + //SPU.WriteLS32(0x808, 2); // hack for cellSpursModuleExit + //SPU.WriteLS32(0x260, 3); // hack for cellSpursModulePollStatus + //SPU.WriteLS32(0x264, 0x35000000); // bi $0 + SPU.WriteLS128(0x1c0, u128::from32r(0, spurs.addr(), num, 0x1f)); u32 wid = 0x20; @@ -189,7 +193,7 @@ s64 spursInit( // load executable code: memcpy(vm::get_ptr(SPU.ls_offset + 0xa00), wkl.pm.get_ptr(), wkl.size); SPU.WriteLS64(0x1d0, wkl.pm.addr()); - SPU.WriteLS32(0x1d8, wkl.priority.ToLE() >> 24 & 0xff); // ??? + SPU.WriteLS32(0x1d8, wkl.copy.read_relaxed()); } if (!isSecond) SPU.WriteLS16(0x1e8, 0); @@ -213,7 +217,8 @@ s64 spursInit( } // get workload id: - + //SPU.GPR[3].clear(); + //wid = SPU.m_code3_func(SPU); } })->GetId(); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 94326ef56e..7ca0a0ebb6 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -88,8 +88,8 @@ SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image if (group) group->list[spu_num] = id; new_thread.group = group; - sys_spu.Warning("*** New SPU Thread [%s] (ep=0x%x, opt=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d", - name.c_str(), spu_ep, option, a1, a2, a3, a4, id); + sys_spu.Warning("*** New SPU Thread [%s] (ep=0x%x, opt=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d, spu_offset=0x%x", + name.c_str(), spu_ep, option, a1, a2, a3, a4, id, spu_offset); return &new_thread; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp index 8eca02c483..d2557be42d 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp @@ -6,7 +6,7 @@ #include "sys_memory.h" #include "sys_vm.h" -SysCallBase sys_vm("vm"); +SysCallBase sys_vm("sys_vm"); MemoryContainerInfo* current_ct; s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr) diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index 90fb00cd5f..2b236aace5 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -455,7 +455,7 @@ bool ELF64Loader::LoadPhdrData(u64 offset) const u32 nid = vm::read32(stub.s_nid + i * 4); const u32 text = vm::read32(stub.s_text + i * 4); - if (module && !module->Load(nid)) + if (!module || !module->Load(nid)) { LOG_WARNING(LOADER, "Unimplemented function '%s' in '%s' module", SysCalls::GetHLEFuncName(nid).c_str(), module_name.c_str()); }