diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 3f27b769ca..94cc1cde92 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2104,6 +2104,7 @@ private: Emu.GetSFuncManager()[CPU.GPR[11]]->name, CPU.GPR[3], CPU.PC); } break; + case 0x4: CPU.FastStop(); break; case 0x22: UNK("HyperCall LV1"); break; default: UNK(fmt::Format("Unknown sc: %x", sc_code)); } @@ -2368,13 +2369,9 @@ private: } void LWARX(u32 rd, u32 ra, u32 rb) { - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - - SMutexLockerR lock(reservation.mutex); - reservation.owner = lock.tid; - reservation.addr = addr; - reservation.size = 4; - reservation.data32 = CPU.GPR[rd] = Memory.Read32(addr); + CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + CPU.R_VALUE = (u32&)Memory[CPU.R_ADDR]; + CPU.GPR[rd] = re32((u32)CPU.R_VALUE); } void LDX(u32 rd, u32 ra, u32 rb) { @@ -2523,13 +2520,9 @@ private: } void LDARX(u32 rd, u32 ra, u32 rb) { - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - - SMutexLockerR lock(reservation.mutex); - reservation.owner = lock.tid; - reservation.addr = addr; - reservation.size = 8; - reservation.data64 = CPU.GPR[rd] = Memory.Read64(addr); + CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + CPU.R_VALUE = (u64&)Memory[CPU.R_ADDR]; + CPU.GPR[rd] = re64(CPU.R_VALUE); } void DCBF(u32 ra, u32 rb) { @@ -2644,17 +2637,13 @@ private: { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - SMutexLockerR lock(reservation.mutex); - if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 4) + if (CPU.R_ADDR == addr) { - // Memory.Write32(addr, CPU.GPR[rs]); - CPU.SetCR_EQ(0, InterlockedCompareExchange((volatile long*) (Memory + addr), re((u32) CPU.GPR[rs]), re(reservation.data32)) == re(reservation.data32)); - reservation.clear(); + CPU.SetCR_EQ(0, InterlockedCompareExchange((volatile u32*)(Memory + addr), re32((u32)CPU.GPR[rs]), (u32)CPU.R_VALUE) == (u32)CPU.R_VALUE); } else { CPU.SetCR_EQ(0, false); - if (lock.tid == reservation.owner) reservation.clear(); } } void STWX(u32 rs, u32 ra, u32 rb) @@ -2705,17 +2694,13 @@ private: { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - SMutexLockerR lock(reservation.mutex); - if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 8) + if (CPU.R_ADDR == addr) { - // Memory.Write64(addr, CPU.GPR[rs]); - CPU.SetCR_EQ(0, InterlockedCompareExchange64((volatile long long*)(Memory + addr), re(CPU.GPR[rs]), re(reservation.data64)) == re(reservation.data64)); - reservation.clear(); + CPU.SetCR_EQ(0, InterlockedCompareExchange((volatile u64*)(Memory + addr), re64(CPU.GPR[rs]), CPU.R_VALUE) == CPU.R_VALUE); } else { CPU.SetCR_EQ(0, false); - if (lock.tid == reservation.owner) reservation.clear(); } } void STBX(u32 rs, u32 ra, u32 rb) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 0b039e4886..c4907dc6e3 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -219,3 +219,34 @@ int FPRdouble::Cmp(PPCdouble a, PPCdouble b) return CR_SO; } + +u64 PPUThread::FastCall(u64 addr, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8) +{ + auto old_status = m_status; + auto old_PC = PC; + auto old_LR = LR; + + PC = addr; + GPR[3] = arg1; + GPR[4] = arg2; + GPR[5] = arg3; + GPR[6] = arg4; + GPR[7] = arg5; + GPR[8] = arg6; + GPR[9] = arg7; + GPR[10] = arg8; + LR = Emu.m_ppu_thr_stop; + + Task(); + + LR = old_LR; + PC = old_PC; + m_status = old_status; + + return GPR[3]; +} + +void PPUThread::FastStop() +{ + m_status = Stopped; +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 1fe6fffd01..7d8cd62197 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -607,6 +607,9 @@ public: u64 cycle; + u64 R_ADDR; // reservation address + u64 R_VALUE; // reservation value (BE) + public: PPUThread(); virtual ~PPUThread(); @@ -839,6 +842,8 @@ public: public: virtual void InitRegs(); virtual u64 GetFreeStackSize() const; + u64 FastCall(u64 addr, u64 arg1 = 0, u64 arg2 = 0, u64 arg3 = 0, u64 arg4 = 0, u64 arg5 = 0, u64 arg6 = 0, u64 arg7 = 0, u64 arg8 = 0); + void FastStop(); protected: virtual void DoReset() override; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 5bacd9f287..e3e538286d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -550,7 +550,7 @@ int cellAudioOutGetNumberOfDevice(u32 audioOut) int cellAudioOutGetDeviceInfo(u32 audioOut, u32 deviceIndex, mem_ptr_t info) { - cellSysutil->Todo("Unimplemented function: cellAudioOutGetDeviceInfo(audioOut=%u, deviceIndex=%u, info_addr=0x%x)", + cellSysutil->Todo("cellAudioOutGetDeviceInfo(audioOut=%u, deviceIndex=%u, info_addr=0x%x)", audioOut, deviceIndex, info.GetAddr()); if(deviceIndex) return CELL_AUDIO_OUT_ERROR_DEVICE_NOT_FOUND; diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index da13269249..ddea3cdd5b 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -45,7 +45,7 @@ static func_caller* sc_table[kSyscallTableLength] = bind_func(sys_process_kill), //19 (0x013) null_func, //20 (0x014) UNS null_func,//bind_func(_sys_process_spawn), //21 (0x015) DBG - bind_func(sys_process_exit), //22 (0x016) + null_func,//bind_func(sys_process_exit), //22 (0x016) bind_func(sys_process_wait_for_child2), //23 (0x017) DBG null_func,//bind_func(), //24 (0x018) DBG bind_func(sys_process_get_sdk_version), //25 (0x019) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 0745e1c49c..ec21d85dbd 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -324,11 +324,17 @@ void Emulator::Load() m_ppu_thr_exit = Memory.MainMem.AllocAlign(4 * 4); mem32_ptr_t ppu_thr_exit_data(m_ppu_thr_exit); - ppu_thr_exit_data += ADDI(3, 0, 0); + //ppu_thr_exit_data += ADDI(3, 0, 0); // why it kills return value (GPR[3]) ? ppu_thr_exit_data += ADDI(11, 0, 41); ppu_thr_exit_data += SC(2); ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0); + m_ppu_thr_stop = Memory.MainMem.AllocAlign(2 * 4); + + mem32_ptr_t ppu_thr_stop_data(m_ppu_thr_stop); + ppu_thr_stop_data += SC(4); + ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0); + Memory.Write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE); } break; @@ -422,11 +428,6 @@ void Emulator::Stop() break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); - if (counter++ > 3000) - { - LOG_ERROR(HLE, "%d threads not stopped (timeout)", (u32)(g_thread_count - uncounted)); - break; - } } m_rsx_callback = 0; diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index f2500878ac..66a087589e 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -106,6 +106,7 @@ public: std::string m_path; std::string m_elf_path; std::string m_title_id; + u32 m_ppu_thr_stop; s32 m_sdk_version; Emulator();