PPU/LLVM: Fix for crashes on exit with jit

This commit is contained in:
Danila Malyutin 2015-09-16 00:34:21 +03:00
parent 97f62571ff
commit 3208a7713f
2 changed files with 26 additions and 10 deletions

View File

@ -41,7 +41,6 @@ using namespace ppu_recompiler_llvm;
#define VIRTUAL_INSTRUCTION_COUNT 0x40000000 #define VIRTUAL_INSTRUCTION_COUNT 0x40000000
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
u64 Compiler::s_rotate_mask[64][64]; u64 Compiler::s_rotate_mask[64][64];
bool Compiler::s_rotate_mask_inited = false; bool Compiler::s_rotate_mask_inited = false;
@ -154,7 +153,7 @@ std::pair<Executable, llvm::ExecutionEngine *> Compiler::Compile(const std::stri
Decode(instr); Decode(instr);
if (!m_state.hit_branch_instruction) 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 // Generate exit logic for all empty blocks
@ -253,7 +252,6 @@ RecompilationEngine::RecompilationEngine()
, m_currentId(0) , m_currentId(0)
, m_last_cache_clear_time(std::chrono::high_resolution_clock::now()) , m_last_cache_clear_time(std::chrono::high_resolution_clock::now())
, m_compiler(*this, CPUHybridDecoderRecompiler::ExecuteFunction, CPUHybridDecoderRecompiler::ExecuteTillReturn, CPUHybridDecoderRecompiler::PollStatus) { , m_compiler(*this, CPUHybridDecoderRecompiler::ExecuteFunction, CPUHybridDecoderRecompiler::ExecuteTillReturn, CPUHybridDecoderRecompiler::PollStatus) {
FunctionCache = (ExecutableStorageType *)memory_helper::reserve_memory(VIRTUAL_INSTRUCTION_COUNT * sizeof(ExecutableStorageType)); FunctionCache = (ExecutableStorageType *)memory_helper::reserve_memory(VIRTUAL_INSTRUCTION_COUNT * sizeof(ExecutableStorageType));
// Each char can store 8 page status // Each char can store 8 page status
FunctionCachePagesCommited = (char *)malloc(VIRTUAL_INSTRUCTION_COUNT / (8 * PAGE_SIZE)); 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 SignExt16(s16 x) { return (s32)(s16)x; }
inline s32 SignExt26(u32 x) { return x & 0x2000000 ? (s32)(x | 0xFC000000) : (s32)(x); } inline s32 SignExt26(u32 x) { return x & 0x2000000 ? (s32)(x | 0xFC000000) : (s32)(x); }
bool RecompilationEngine::AnalyseBlock(BlockEntry &functionData, size_t maxSize) bool RecompilationEngine::AnalyseBlock(BlockEntry &functionData, size_t maxSize)
{ {
u32 startAddress = functionData.address; u32 startAddress = functionData.address;
@ -503,9 +500,8 @@ ppu_recompiler_llvm::CPUHybridDecoderRecompiler::~CPUHybridDecoderRecompiler() {
} }
u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::DecodeMemory(const u32 address) { u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::DecodeMemory(const u32 address) {
// TODO: exception_ptr doesnt work, should add every possible exception ExecuteFunction(&m_ppu, 0);
if (ExecuteFunction(&m_ppu, 0) == ExecutionStatus::ExecutionStatusPropagateException) if (m_ppu.pending_exception != nullptr) {
{
std::exception_ptr exn = m_ppu.pending_exception; std::exception_ptr exn = m_ppu.pending_exception;
m_ppu.pending_exception = nullptr; m_ppu.pending_exception = nullptr;
std::rethrow_exception(exn); std::rethrow_exception(exn);
@ -588,7 +584,6 @@ u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::ExecuteTillReturn(PPUThread
return 0; return 0;
case BranchType::FunctionCall: { case BranchType::FunctionCall: {
u32 status = ExecuteFunction(ppu_state, 0); u32 status = ExecuteFunction(ppu_state, 0);
// TODO: exception_ptr doesnt work, should add every possible exception
if (status == ExecutionStatus::ExecutionStatusPropagateException) if (status == ExecutionStatus::ExecutionStatusPropagateException)
return ExecutionStatus::ExecutionStatusPropagateException; return ExecutionStatus::ExecutionStatusPropagateException;
break; break;
@ -607,6 +602,14 @@ u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::ExecuteTillReturn(PPUThread
} }
bool ppu_recompiler_llvm::CPUHybridDecoderRecompiler::PollStatus(PPUThread * ppu_state) { 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 #endif // LLVM_AVAILABLE

View File

@ -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) { void Compiler::SC(u32 lev) {
switch (lev) { switch (lev) {
case 0: case 0:
Call<void>("SysCalls.DoSyscall", SysCalls::DoSyscall, m_state.args[CompileTaskState::Args::State], GetGpr(11)); Call<void>("wrappedDoSyscall", &wrappedDoSyscall, m_state.args[CompileTaskState::Args::State], GetGpr(11));
break; break;
case 3: case 3:
Call<void>("PPUThread.FastStop", &PPUThread::fast_stop, m_state.args[CompileTaskState::Args::State]); Call<void>("PPUThread.FastStop", &PPUThread::fast_stop, m_state.args[CompileTaskState::Args::State]);