Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PPU/LLVM: Fix for most of the remaining crashes on exit with jit #1222

Merged
merged 2 commits into from Sep 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 12 additions & 9 deletions rpcs3/Emu/Cell/PPULLVMRecompiler.cpp
Expand Up @@ -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;

Expand Down Expand Up @@ -154,7 +153,7 @@ std::pair<Executable, llvm::ExecutionEngine *> 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
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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 true;
}
}
#endif // LLVM_AVAILABLE
29 changes: 25 additions & 4 deletions rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -1785,10 +1784,32 @@ void Compiler::HACK(u32 index) {
}
}

static u32 wrappedDoSyscall(PPUThread &CPU, u64 code) noexcept {
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<void>("SysCalls.DoSyscall", SysCalls::DoSyscall, m_state.args[CompileTaskState::Args::State], GetGpr(11));
{
llvm::Value *status = Call<u32>("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<void>("PPUThread.FastStop", &PPUThread::fast_stop, m_state.args[CompileTaskState::Args::State]);
Expand Down