diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 8c57c78485..7f98249d9d 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -102,6 +102,33 @@ void ARMv7Thread::DoCode() { } +void ARMv7Thread::FastCall(u32 addr) +{ + auto old_status = m_status; + auto old_PC = PC; + auto old_stack = SP; + auto old_LR = LR; + auto old_thread = GetCurrentNamedThread(); + + m_status = Running; + PC = addr; + LR = Emu.m_cpu_thr_stop; + SetCurrentNamedThread(this); + + CPUThread::Task(); + + m_status = old_status; + PC = old_PC; + SP = old_stack; + LR = old_LR; + SetCurrentNamedThread(old_thread); +} + +void ARMv7Thread::FastStop() +{ + m_status = Stopped; +} + arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) { thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7); @@ -112,4 +139,4 @@ arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio); argc = 0; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index 1eeefff09c..8737454857 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -123,6 +123,8 @@ public: virtual void InitRegs(); virtual void InitStack(); u32 GetStackArg(u32 pos); + void FastCall(u32 addr); + void FastStop(); virtual void DoRun(); public: diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index 18a29f85eb..151d12ae21 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -140,9 +140,12 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr pAr return SCE_OK; } -s32 sceKernelExitThread(s32 exitStatus) +s32 sceKernelExitThread(ARMv7Thread& CPU, s32 exitStatus) { - sceLibKernel.Todo("sceKernelExitThread(exitStatus=0x%x)", exitStatus); + sceLibKernel.Error("sceKernelExitThread(exitStatus=0x%x)", exitStatus); + + // exit status is stored in r0 + CPU.Stop(); return SCE_OK; } diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index bde15b0dc9..5f644a6d10 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -6,20 +6,32 @@ std::vector g_psv_func_list = []() -> std::vector { std::vector v; - psv_func f = + psv_func unimplemented = { - 0xdeadbeef, + 0x00000000, // must not be a valid id "INVALID FUNCTION", new psv_func_detail::func_binder([]() -> u32 { - LOG_ERROR(HLE, "Unimplemented function found"); + LOG_ERROR(HLE, "Unimplemented function executed"); Emu.Pause(); return 0xffffffffu; }), nullptr, }; - v.push_back(f); + v.push_back(unimplemented); + + psv_func hle_return = + { + 0x00000001, // must not be a valid id + "INVALID FUNCTION", + new psv_func_detail::func_binder([](ARMv7Thread& CPU) + { + CPU.FastStop(); + }), + nullptr, + }; + v.push_back(hle_return); return v; }(); diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index c24509ea0f..85f86ef76c 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -1840,15 +1840,15 @@ private: { for (uint b = 0; b < 16; b++) { - s16 result = (s16)CPU.VPR[va]._u8[b] - (s16)CPU.VPR[vb]._u8[b]; + s16 result = (s16)CPU.VPR[va]._u8[b] - (s16)CPU.VPR[vb]._u8[b]; - if (result < 0) - { + if (result < 0) + { CPU.VPR[vd]._u8[b] = 0; CPU.VSCR.SAT = 1; - } - else - CPU.VPR[vd]._u8[b] = (u8)result; + } + else + CPU.VPR[vd]._u8[b] = (u8)result; } } void VSUBUHM(u32 vd, u32 va, u32 vb) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 06b2c8b926..c9703c10ce 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -202,7 +202,7 @@ u64 PPUThread::FastCall2(u32 addr, u32 rtoc) m_status = Running; PC = addr; GPR[2] = rtoc; - LR = Emu.m_ppu_thr_stop; + LR = Emu.m_cpu_thr_stop; SetCurrentNamedThread(this); CPUThread::Task(); @@ -288,4 +288,4 @@ ppu_thread& ppu_thread::gpr(uint index, u64 value) static_cast(thread)->GPR[index] = value; return *this; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 437ebbcd97..1b977a6e52 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -1715,13 +1715,10 @@ private: } else { + // rotate left const XmmLink& va = XmmGet(ra, rt); - const XmmLink& v1 = XmmCopy(va); - c.pslldq(va.get(), s); - c.psrldq(v1.get(), 16 - s); - c.por(va.get(), v1.get()); + c.palignr(va.get(), va.get(), 16 - s); XmmFinalize(va, rt); - XmmFinalize(v1); } LOG_OPCODE(); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index e480edc50f..3a11eedc17 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -181,9 +181,8 @@ int cellGameContentPermit(vm::ptr contentInfoPath, vm: cellGame->Warning("cellGameContentPermit(contentInfoPath_addr=0x%x, usrdirPath_addr=0x%x)", contentInfoPath.addr(), usrdirPath.addr()); - if (!contentInfoPath && !usrdirPath) + if (!contentInfoPath || !usrdirPath) { - cellGame->Warning("cellGameContentPermit(): CELL_GAME_ERROR_PARAM"); return CELL_GAME_ERROR_PARAM; } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 3e68915494..fb83221f96 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -86,16 +86,7 @@ namespace loader { case MACHINE_MIPS: break; case MACHINE_ARM: arm7_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; - case MACHINE_SPU: - { - if (!Emu.IsStopped()) - { - break; - } - - spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); - break; - } + case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; } return ok; @@ -117,7 +108,7 @@ namespace loader case 0x00000001: //LOAD if (phdr.data_le.p_memsz) { - if (machine != MACHINE_SPU && !vm::alloc(vaddr, memsz, vm::main)) + if ((machine != MACHINE_SPU || Emu.IsStopped()) && !vm::alloc(vaddr, memsz, vm::main)) { LOG_ERROR(LOADER, "%s(): AllocFixed(0x%llx, 0x%x) failed", __FUNCTION__, vaddr, memsz);