From 3208a7713f0089b1a3140555ff4b3980d12fed77 Mon Sep 17 00:00:00 2001 From: Danila Malyutin Date: Wed, 16 Sep 2015 00:34:21 +0300 Subject: [PATCH 1/2] PPU/LLVM: Fix for crashes on exit with jit --- rpcs3/Emu/Cell/PPULLVMRecompiler.cpp | 21 ++++++++++++--------- rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 82cf8ab0d8e..a6cbc9cf1d8 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -41,7 +41,6 @@ using namespace ppu_recompiler_llvm; #define VIRTUAL_INSTRUCTION_COUNT 0x40000000 #define PAGE_SIZE 4096 - u64 Compiler::s_rotate_mask[64][64]; bool Compiler::s_rotate_mask_inited = false; @@ -154,7 +153,7 @@ std::pair Compiler::Compile(const std::stri Decode(instr); if (!m_state.hit_branch_instruction) - m_ir_builder->CreateBr(GetBasicBlockFromAddress(instructionAddress + 4)); + m_ir_builder->CreateBr(GetBasicBlockFromAddress(instructionAddress + 4)); } // Generate exit logic for all empty blocks @@ -253,7 +252,6 @@ RecompilationEngine::RecompilationEngine() , m_currentId(0) , m_last_cache_clear_time(std::chrono::high_resolution_clock::now()) , m_compiler(*this, CPUHybridDecoderRecompiler::ExecuteFunction, CPUHybridDecoderRecompiler::ExecuteTillReturn, CPUHybridDecoderRecompiler::PollStatus) { - FunctionCache = (ExecutableStorageType *)memory_helper::reserve_memory(VIRTUAL_INSTRUCTION_COUNT * sizeof(ExecutableStorageType)); // Each char can store 8 page status FunctionCachePagesCommited = (char *)malloc(VIRTUAL_INSTRUCTION_COUNT / (8 * PAGE_SIZE)); @@ -392,7 +390,6 @@ bool RecompilationEngine::IncreaseHitCounterAndBuild(u32 address) { inline s32 SignExt16(s16 x) { return (s32)(s16)x; } inline s32 SignExt26(u32 x) { return x & 0x2000000 ? (s32)(x | 0xFC000000) : (s32)(x); } - bool RecompilationEngine::AnalyseBlock(BlockEntry &functionData, size_t maxSize) { u32 startAddress = functionData.address; @@ -503,9 +500,8 @@ ppu_recompiler_llvm::CPUHybridDecoderRecompiler::~CPUHybridDecoderRecompiler() { } u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::DecodeMemory(const u32 address) { - // TODO: exception_ptr doesnt work, should add every possible exception - if (ExecuteFunction(&m_ppu, 0) == ExecutionStatus::ExecutionStatusPropagateException) - { + ExecuteFunction(&m_ppu, 0); + if (m_ppu.pending_exception != nullptr) { std::exception_ptr exn = m_ppu.pending_exception; m_ppu.pending_exception = nullptr; std::rethrow_exception(exn); @@ -588,7 +584,6 @@ u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::ExecuteTillReturn(PPUThread return 0; case BranchType::FunctionCall: { u32 status = ExecuteFunction(ppu_state, 0); - // TODO: exception_ptr doesnt work, should add every possible exception if (status == ExecutionStatus::ExecutionStatusPropagateException) return ExecutionStatus::ExecutionStatusPropagateException; break; @@ -607,6 +602,14 @@ u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::ExecuteTillReturn(PPUThread } bool ppu_recompiler_llvm::CPUHybridDecoderRecompiler::PollStatus(PPUThread * ppu_state) { - return ppu_state->check_status(); + try + { + return ppu_state->check_status(); + } + catch (...) + { + ppu_state->pending_exception = std::current_exception(); + return ExecutionStatus::ExecutionStatusPropagateException; + } } #endif // LLVM_AVAILABLE diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp index b688d6006c6..6596cc3bcc7 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp @@ -1785,10 +1785,23 @@ void Compiler::HACK(u32 index) { } } +static u32 wrappedDoSyscall(PPUThread &CPU, u64 code) { + try + { + SysCalls::DoSyscall(CPU, code); + return ExecutionStatus::ExecutionStatusBlockEnded; + } + catch (...) + { + CPU.pending_exception = std::current_exception(); + return ExecutionStatus::ExecutionStatusPropagateException; + } +} + void Compiler::SC(u32 lev) { switch (lev) { case 0: - Call("SysCalls.DoSyscall", SysCalls::DoSyscall, m_state.args[CompileTaskState::Args::State], GetGpr(11)); + Call("wrappedDoSyscall", &wrappedDoSyscall, m_state.args[CompileTaskState::Args::State], GetGpr(11)); break; case 3: Call("PPUThread.FastStop", &PPUThread::fast_stop, m_state.args[CompileTaskState::Args::State]); From 11eeab0a1aef011a18ef27fcaea143efe98969d5 Mon Sep 17 00:00:00 2001 From: Danila Malyutin Date: Thu, 17 Sep 2015 01:24:16 +0300 Subject: [PATCH 2/2] PPU/LLVM: Added noexcept and some fixes --- rpcs3/Emu/Cell/PPULLVMRecompiler.cpp | 2 +- rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index a6cbc9cf1d8..306b1a3ba26 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -609,7 +609,7 @@ bool ppu_recompiler_llvm::CPUHybridDecoderRecompiler::PollStatus(PPUThread * ppu catch (...) { ppu_state->pending_exception = std::current_exception(); - return ExecutionStatus::ExecutionStatusPropagateException; + return true; } } #endif // LLVM_AVAILABLE diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp index 6596cc3bcc7..d3af52b2e9e 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp @@ -1754,9 +1754,8 @@ void Compiler::BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) { -static u32 -wrappedExecutePPUFuncByIndex(PPUThread &CPU, u32 index) -{ +static u32 +wrappedExecutePPUFuncByIndex(PPUThread &CPU, u32 index) noexcept { try { execute_ppu_func_by_index(CPU, index); @@ -1785,7 +1784,7 @@ void Compiler::HACK(u32 index) { } } -static u32 wrappedDoSyscall(PPUThread &CPU, u64 code) { +static u32 wrappedDoSyscall(PPUThread &CPU, u64 code) noexcept { try { SysCalls::DoSyscall(CPU, code); @@ -1801,7 +1800,16 @@ static u32 wrappedDoSyscall(PPUThread &CPU, u64 code) { void Compiler::SC(u32 lev) { switch (lev) { case 0: - Call("wrappedDoSyscall", &wrappedDoSyscall, m_state.args[CompileTaskState::Args::State], GetGpr(11)); + { + llvm::Value *status = Call("wrappedDoSyscall", &wrappedDoSyscall, m_state.args[CompileTaskState::Args::State], GetGpr(11)); + llvm::BasicBlock *cputhreadexitblock = GetBasicBlockFromAddress(m_state.current_instruction_address, "early_exit"); + llvm::Value *isCPUThreadExit = m_ir_builder->CreateICmpEQ(status, m_ir_builder->getInt32(ExecutionStatus::ExecutionStatusPropagateException)); + llvm::BasicBlock *normal_execution = GetBasicBlockFromAddress(m_state.current_instruction_address, "normal_execution"); + m_ir_builder->CreateCondBr(isCPUThreadExit, cputhreadexitblock, normal_execution); + m_ir_builder->SetInsertPoint(cputhreadexitblock); + m_ir_builder->CreateRet(m_ir_builder->getInt32(ExecutionStatus::ExecutionStatusPropagateException)); + m_ir_builder->SetInsertPoint(normal_execution); + } break; case 3: Call("PPUThread.FastStop", &PPUThread::fast_stop, m_state.args[CompileTaskState::Args::State]);