From 488928eca21634f0908316a328e23319c2091e14 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 5 Nov 2018 14:24:08 +0300 Subject: [PATCH] Fix SPU STOP instruction Check thread state after STOP instruction --- rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp | 16 +++++++++++++++- rpcs3/Emu/Cell/SPUInterpreter.cpp | 13 ++++++++++++- rpcs3/Emu/Cell/SPURecompiler.cpp | 4 ++++ rpcs3/Emu/Cell/SPUThread.cpp | 2 +- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index 2d3a230de5..da2db5d559 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -1580,12 +1580,26 @@ void spu_recompiler::STOP(spu_opcode_t op) c->align(kAlignCode, 16); c->bind(ret); + c->mov(SPU_OFF_32(pc), m_pos + 4); + if (g_cfg.core.spu_block_size == spu_block_size_type::safe) { - c->mov(SPU_OFF_32(pc), m_pos + 4); c->ret(); m_pos = -1; } + else + { + Label label_next = c->newLabel(); + Label label_check = c->newLabel(); + c->cmp(SPU_OFF_32(state), 0); + c->jnz(label_check); + c->jmp(label_next); + c->bind(label_check); + c->lea(*ls, x86::qword_ptr(label_next)); + c->jmp(imm_ptr(&check_state)); + c->align(kAlignCode, 16); + c->bind(label_next); + } } void spu_recompiler::LNOP(spu_opcode_t op) diff --git a/rpcs3/Emu/Cell/SPUInterpreter.cpp b/rpcs3/Emu/Cell/SPUInterpreter.cpp index 62d918a111..5518ed864c 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/SPUInterpreter.cpp @@ -117,7 +117,18 @@ void spu_interpreter::set_interrupt_status(spu_thread& spu, spu_opcode_t op) bool spu_interpreter::STOP(spu_thread& spu, spu_opcode_t op) { - return spu.stop_and_signal(op.opcode & 0x3fff); + if (!spu.stop_and_signal(op.opcode & 0x3fff)) + { + return false; + } + + if (spu.state) + { + spu.pc += 4; + return false; + } + + return true; } bool spu_interpreter::LNOP(spu_thread& spu, spu_opcode_t op) diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 0fa85f78c8..9eafdcb7a8 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -3056,6 +3056,10 @@ public: m_ir->CreateStore(m_ir->getInt32(m_pos + 4), spu_ptr(&spu_thread::pc)); m_ir->CreateRetVoid(); } + else + { + check_state(m_pos + 4); + } } void STOPD(spu_opcode_t op) // diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index cfb4699ba5..dd88629239 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -2066,7 +2066,7 @@ bool spu_thread::stop_and_signal(u32 code) int_ctrl[2].set(SPU_INT2_STAT_SPU_STOP_AND_SIGNAL_INT); state += cpu_flag::stop; - return true; // ??? + return true; } switch (code)