From e687a9124368e494923659c6628f2996a09e0c2b Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Thu, 18 Sep 2014 16:59:49 +0530 Subject: [PATCH] Implemented some FP instructions but did not add support for updating the FPSCR. Many misc changes. --- rpcs3/Emu/Cell/PPULLVMRecompiler.cpp | 296 +++++++++++++++++++++------ rpcs3/Emu/Cell/PPULLVMRecompiler.h | 72 ++++--- 2 files changed, 278 insertions(+), 90 deletions(-) diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index dd71d63677..28acb54b10 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -84,21 +84,15 @@ PPULLVMRecompiler::~PPULLVMRecompiler() { log_file << i->first << " = " << i->second << "\n"; } - std::set> sorted_block_info; - for (auto i = m_address_to_compiled_block_map.begin(); i != m_address_to_compiled_block_map.end(); i++) { - sorted_block_info.insert(std::make_pair(~i->second.request_count, i->first)); - } - log_file << "\nBlock Information:\n"; - for (auto i = sorted_block_info.begin(); i != sorted_block_info.end(); i++) { - auto j = m_address_to_compiled_block_map.find(i->second); - log_file << fmt::Format("%s: Size = %u bytes, Times requested = %llu\n", j->second.llvm_function->getName().str().c_str(), j->second.size, j->second.request_count); + for (auto i = m_compiled_blocks.begin(); i != m_compiled_blocks.end(); i++) { + log_file << fmt::Format("\n%s: Size = %u bytes, Reference count = %llu\n", i->second.llvm_function->getName().str().c_str(), i->second.size, i->second.reference_count); - log_file << "\nDisassembly:\n"; - for (size_t pc = 0; pc < j->second.size;) { + log_file << "Disassembly:\n"; + for (size_t pc = 0; pc < i->second.size;) { char str[1024]; - auto size = LLVMDisasmInstruction(m_disassembler, (uint8_t *)j->second.block + pc, j->second.size - pc, (uint64_t)((uint8_t *)j->second.block + pc), str, sizeof(str)); + auto size = LLVMDisasmInstruction(m_disassembler, (uint8_t *)i->second.block + pc, i->second.size - pc, (uint64_t)((uint8_t *)i->second.block + pc), str, sizeof(str)); log_file << str << '\n'; pc += size; } @@ -113,19 +107,33 @@ PPULLVMRecompiler::~PPULLVMRecompiler() { delete m_llvm_context; } -PPULLVMRecompiler::CompiledBlock PPULLVMRecompiler::GetCompiledBlock(u32 address) { - { - std::lock_guard lock(m_address_to_compiled_block_map_mutex); - auto i = m_address_to_compiled_block_map.find(address); - if (i != m_address_to_compiled_block_map.end()) { - i->second.request_count++; - return i->second.block; - } +PPULLVMRecompiler::CompiledBlockInfo PPULLVMRecompiler::GetCompiledBlock(u32 address) { + static CompiledBlockInfo unknown_block_info = {0}; + + std::lock_guard lock(m_compiled_blocks_mutex); + + auto compiled_block = m_compiled_blocks.lower_bound(std::make_pair(address, 0)); + if (compiled_block != m_compiled_blocks.end() && compiled_block->first.first == address) { + compiled_block->second.reference_count++; + return compiled_block->second; } + return unknown_block_info; +} + +void PPULLVMRecompiler::ReleaseCompiledBlock(u32 address, u32 revision) { + std::lock_guard lock(m_compiled_blocks_mutex); + + auto compiled_block = m_compiled_blocks.find(std::make_pair(address, revision)); + if (compiled_block != m_compiled_blocks.end()) { + compiled_block->second.reference_count--; + } +} + +void PPULLVMRecompiler::RequestCompilation(u32 address) { { - std::lock_guard lock(m_pending_blocks_set_mutex); - m_pending_blocks_set.insert(address); + std::lock_guard lock(m_pending_compilation_blocks_mutex); + m_pending_compilation_blocks.insert(address); } if (!IsAlive()) { @@ -133,7 +141,6 @@ PPULLVMRecompiler::CompiledBlock PPULLVMRecompiler::GetCompiledBlock(u32 address } Notify(); - return nullptr; } void PPULLVMRecompiler::Task() { @@ -146,12 +153,12 @@ void PPULLVMRecompiler::Task() { u32 address; { - std::lock_guard lock(m_pending_blocks_set_mutex); + std::lock_guard lock(m_pending_compilation_blocks_mutex); - auto i = m_pending_blocks_set.begin(); - if (i != m_pending_blocks_set.end()) { + auto i = m_pending_compilation_blocks.begin(); + if (i != m_pending_compilation_blocks.end()) { address = *i; - m_pending_blocks_set.erase(i); + m_pending_compilation_blocks.erase(i); } else { break; } @@ -1536,7 +1543,10 @@ void PPULLVMRecompiler::MULHWU(u32 rd, u32 ra, u32 rb, bool rc) { } void PPULLVMRecompiler::MFOCRF(u32 a, u32 rd, u32 crm) { - InterpreterCall("MFOCRF", &PPUInterpreter::MFOCRF, a, rd, crm); + auto cr_i32 = GetCr(); + auto cr_i64 = m_ir_builder->CreateZExt(cr_i32, m_ir_builder->getInt64Ty()); + SetGpr(rd, cr_i64); + //InterpreterCall("MFOCRF", &PPUInterpreter::MFOCRF, a, rd, crm); } void PPULLVMRecompiler::LWARX(u32 rd, u32 ra, u32 rb) { @@ -1785,7 +1795,24 @@ void PPULLVMRecompiler::ADDE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { } void PPULLVMRecompiler::MTOCRF(u32 l, u32 crm, u32 rs) { - InterpreterCall("MTOCRF", &PPUInterpreter::MTOCRF, l, crm, rs); + auto rs_i32 = GetGpr(rs, 32); + auto cr_i32 = GetCr(); + u32 mask = 0; + + for (u32 i = 0; i < 8; i++) { + if (crm & (1 << i)) { + mask |= 0xF << ((7 - i) * 4); + if (l) { + break; + } + } + } + + cr_i32 = m_ir_builder->CreateAnd(cr_i32, ~mask); + rs_i32 = m_ir_builder->CreateAnd(rs_i32, ~mask); + cr_i32 = m_ir_builder->CreateOr(cr_i32, rs_i32); + SetCr(cr_i32); + //InterpreterCall("MTOCRF", &PPUInterpreter::MTOCRF, l, crm, rs); } void PPULLVMRecompiler::STDX(u32 rs, u32 ra, u32 rb) { @@ -1843,7 +1870,18 @@ void PPULLVMRecompiler::STVEWX(u32 vs, u32 ra, u32 rb) { } void PPULLVMRecompiler::ADDZE(u32 rd, u32 ra, u32 oe, bool rc) { - InterpreterCall("ADDZE", &PPUInterpreter::ADDZE, rd, ra, oe, rc); + auto ra_i64 = GetGpr(ra); + auto ca_i64 = GetXerCa(); + auto res_s = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::sadd_with_overflow, {m_ir_builder->getInt64Ty()}), ra_i64, ca_i64); + auto sum_i64 = m_ir_builder->CreateExtractValue(res_s, {0}); + auto carry_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); + SetGpr(rd, sum_i64); + SetXerCa(carry_i1); + + if (rc) { + SetCrFieldSignedCmp(0, sum_i64, m_ir_builder->getInt64(0)); + } + //InterpreterCall("ADDZE", &PPUInterpreter::ADDZE, rd, ra, oe, rc); } void PPULLVMRecompiler::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) { @@ -2418,14 +2456,34 @@ void PPULLVMRecompiler::DSS(u32 strm, u32 a) { } void PPULLVMRecompiler::SRAWI(u32 ra, u32 rs, u32 sh, bool rc) { + //auto rs_i32 = GetGpr(rs, 32); + //auto res_i32 = m_ir_builder->CreateAShr(rs_i32, sh); + //auto res_i64 = m_ir_builder->CreateSExt(rs_i32, m_ir_builder->getInt64Ty()); + //SetGpr(ra, res_i64); + + //if (rc) { + // SetCrFieldSignedCmp(0, res_i64, m_ir_builder->getInt64(0)); + //} + + // TODO: Set XER.CA InterpreterCall("SRAWI", &PPUInterpreter::SRAWI, ra, rs, sh, rc); } void PPULLVMRecompiler::SRADI1(u32 ra, u32 rs, u32 sh, bool rc) { + //auto rs_i64 = GetGpr(rs); + //auto res_i64 = m_ir_builder->CreateAShr(rs_i64, sh); + //SetGpr(ra, res_i64); + + //if (rc) { + // SetCrFieldSignedCmp(0, res_i64, m_ir_builder->getInt64(0)); + //} + + // TODO: Set XER.CA InterpreterCall("SRADI1", &PPUInterpreter::SRADI1, ra, rs, sh, rc); } void PPULLVMRecompiler::SRADI2(u32 ra, u32 rs, u32 sh, bool rc) { + //SRADI1(ra, rs, sh, rc); InterpreterCall("SRADI2", &PPUInterpreter::SRADI2, ra, rs, sh, rc); } @@ -2805,7 +2863,13 @@ void PPULLVMRecompiler::LWA(u32 rd, u32 ra, s32 ds) { } void PPULLVMRecompiler::FDIVS(u32 frd, u32 fra, u32 frb, bool rc) { - InterpreterCall("FDIVS", &PPUInterpreter::FDIVS, frd, fra, frb, rc); + auto ra_f32 = GetFpr(fra, 32); + auto rb_f32 = GetFpr(frb, 32); + auto res_f32 = m_ir_builder->CreateFDiv(ra_f32, rb_f32); + SetFpr(frd, res_f32); + + // TODO: Set flags + //InterpreterCall("FDIVS", &PPUInterpreter::FDIVS, frd, fra, frb, rc); } void PPULLVMRecompiler::FSUBS(u32 frd, u32 fra, u32 frb, bool rc) { @@ -2813,7 +2877,13 @@ void PPULLVMRecompiler::FSUBS(u32 frd, u32 fra, u32 frb, bool rc) { } void PPULLVMRecompiler::FADDS(u32 frd, u32 fra, u32 frb, bool rc) { - InterpreterCall("FADDS", &PPUInterpreter::FADDS, frd, fra, frb, rc); + auto ra_f32 = GetFpr(fra, 32); + auto rb_f32 = GetFpr(frb, 32); + auto res_f32 = m_ir_builder->CreateFAdd(ra_f32, rb_f32); + SetFpr(frd, res_f32); + + // TODO: Set flags + //InterpreterCall("FADDS", &PPUInterpreter::FADDS, frd, fra, frb, rc); } void PPULLVMRecompiler::FSQRTS(u32 frd, u32 frb, bool rc) { @@ -2825,14 +2895,35 @@ void PPULLVMRecompiler::FRES(u32 frd, u32 frb, bool rc) { } void PPULLVMRecompiler::FMULS(u32 frd, u32 fra, u32 frc, bool rc) { - InterpreterCall("FMULS", &PPUInterpreter::FMULS, frd, fra, frc, rc); + auto ra_f32 = GetFpr(fra, 32); + auto rc_f32 = GetFpr(frc, 32); + auto res_f32 = m_ir_builder->CreateFMul(ra_f32, rc_f32); + SetFpr(frd, res_f32); + + // TODO: Set flags + //InterpreterCall("FMULS", &PPUInterpreter::FMULS, frd, fra, frc, rc); } void PPULLVMRecompiler::FMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - InterpreterCall("FMADDS", &PPUInterpreter::FMADDS, frd, fra, frc, frb, rc); + auto ra_f64 = GetFpr(fra); + auto rb_f64 = GetFpr(frb); + auto rc_f64 = GetFpr(frc); + auto res_f64 = m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fma, {m_ir_builder->getDoubleTy()}), ra_f64, rc_f64, rb_f64); + SetFpr(frd, res_f64); + + // TODO: Set flags + //InterpreterCall("FMADDS", &PPUInterpreter::FMADDS, frd, fra, frc, frb, rc); } void PPULLVMRecompiler::FMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + //auto ra_f64 = GetFpr(fra); + //auto rb_f64 = GetFpr(frb); + //auto rc_f64 = GetFpr(frc); + //rb_f64 = m_ir_builder->CreateNeg(rb_f64); + //auto res_f64 = m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fma, {m_ir_builder->getDoubleTy()}), ra_f64, rc_f64, rb_f64); + //SetFpr(frd, res_f64); + + // TODO: Set flags InterpreterCall("FMSUBS", &PPUInterpreter::FMSUBS, frd, fra, frc, frb, rc); } @@ -2894,7 +2985,11 @@ void PPULLVMRecompiler::FCMPU(u32 crfd, u32 fra, u32 frb) { } void PPULLVMRecompiler::FRSP(u32 frd, u32 frb, bool rc) { - InterpreterCall("FRSP", &PPUInterpreter::FRSP, frd, frb, rc); + auto rb_f64 = GetFpr(frb); + SetFpr(frd, rb_f64); + + // TODO: Set flags + //InterpreterCall("FRSP", &PPUInterpreter::FRSP, frd, frb, rc); } void PPULLVMRecompiler::FCTIW(u32 frd, u32 frb, bool rc) { @@ -2906,21 +3001,33 @@ void PPULLVMRecompiler::FCTIWZ(u32 frd, u32 frb, bool rc) { } void PPULLVMRecompiler::FDIV(u32 frd, u32 fra, u32 frb, bool rc) { - InterpreterCall("FDIV", &PPUInterpreter::FDIV, frd, fra, frb, rc); + auto ra_f64 = GetFpr(fra); + auto rb_f64 = GetFpr(frb); + auto res_f64 = m_ir_builder->CreateFDiv(ra_f64, rb_f64); + SetFpr(frd, res_f64); + + // TODO: Set flags + //InterpreterCall("FDIV", &PPUInterpreter::FDIV, frd, fra, frb, rc); } void PPULLVMRecompiler::FSUB(u32 frd, u32 fra, u32 frb, bool rc) { - InterpreterCall("FSUB", &PPUInterpreter::FSUB, frd, fra, frb, rc); + auto ra_f64 = GetFpr(fra); + auto rb_f64 = GetFpr(frb); + auto res_f64 = m_ir_builder->CreateFSub(ra_f64, rb_f64); + SetFpr(frd, res_f64); + + // TODO: Set flags + //InterpreterCall("FSUB", &PPUInterpreter::FSUB, frd, fra, frb, rc); } void PPULLVMRecompiler::FADD(u32 frd, u32 fra, u32 frb, bool rc) { - //auto ra_f64 = GetFpr(fra); - //auto rb_f64 = GetFpr(frb); - //auto res_f64 = m_ir_builder->CreateFAdd(ra_f64, rb_f64); - //SetFpr(frd, res_f64); + auto ra_f64 = GetFpr(fra); + auto rb_f64 = GetFpr(frb); + auto res_f64 = m_ir_builder->CreateFAdd(ra_f64, rb_f64); + SetFpr(frd, res_f64); - // TODO: Set FPRF - InterpreterCall("FADD", &PPUInterpreter::FADD, frd, fra, frb, rc); + // TODO: Set flags + //InterpreterCall("FADD", &PPUInterpreter::FADD, frd, fra, frb, rc); } void PPULLVMRecompiler::FSQRT(u32 frd, u32 frb, bool rc) { @@ -2932,7 +3039,13 @@ void PPULLVMRecompiler::FSEL(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { } void PPULLVMRecompiler::FMUL(u32 frd, u32 fra, u32 frc, bool rc) { - InterpreterCall("FMUL", &PPUInterpreter::FMUL, frd, fra, frc, rc); + auto ra_f64 = GetFpr(fra); + auto rc_f64 = GetFpr(frc); + auto res_f64 = m_ir_builder->CreateFMul(ra_f64, rc_f64); + SetFpr(frd, res_f64); + + // TODO: Set flags + //InterpreterCall("FMUL", &PPUInterpreter::FMUL, frd, fra, frc, rc); } void PPULLVMRecompiler::FRSQRTE(u32 frd, u32 frb, bool rc) { @@ -2940,11 +3053,26 @@ void PPULLVMRecompiler::FRSQRTE(u32 frd, u32 frb, bool rc) { } void PPULLVMRecompiler::FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + //auto ra_f64 = GetFpr(fra); + //auto rb_f64 = GetFpr(frb); + //auto rc_f64 = GetFpr(frc); + //rb_f64 = m_ir_builder->CreateNeg(rb_f64); + //auto res_f64 = m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fma, {m_ir_builder->getDoubleTy()}), ra_f64, rc_f64, rb_f64); + //SetFpr(frd, res_f64); + + // TODO: Set flags InterpreterCall("FMSUB", &PPUInterpreter::FMSUB, frd, fra, frc, frb, rc); } void PPULLVMRecompiler::FMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - InterpreterCall("FMADD", &PPUInterpreter::FMADD, frd, fra, frc, frb, rc); + auto ra_f64 = GetFpr(fra); + auto rb_f64 = GetFpr(frb); + auto rc_f64 = GetFpr(frc); + auto res_f64 = m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fma, {m_ir_builder->getDoubleTy()}), ra_f64, rc_f64, rb_f64); + SetFpr(frd, res_f64); + + // TODO: Set flags + //InterpreterCall("FMADD", &PPUInterpreter::FMADD, frd, fra, frc, frb, rc); } void PPULLVMRecompiler::FNMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { @@ -2960,11 +3088,18 @@ void PPULLVMRecompiler::FCMPO(u32 crfd, u32 fra, u32 frb) { } void PPULLVMRecompiler::FNEG(u32 frd, u32 frb, bool rc) { + //auto rb_f64 = GetFpr(frb); + //rb_f64 = m_ir_builder->CreateSub(ConstantFP::getZeroValueForNegation(rb_f64->getType()), rb_f64); + //SetGpr(frd, rb_f64); + + // TODO: Set flags InterpreterCall("FNEG", &PPUInterpreter::FNEG, frd, frb, rc); } void PPULLVMRecompiler::FMR(u32 frd, u32 frb, bool rc) { - InterpreterCall("FMR", &PPUInterpreter::FMR, frd, frb, rc); + SetFpr(frd, GetFpr(frb)); + // TODO: Set flags + //InterpreterCall("FMR", &PPUInterpreter::FMR, frd, frb, rc); } void PPULLVMRecompiler::FNABS(u32 frd, u32 frb, bool rc) { @@ -2984,7 +3119,12 @@ void PPULLVMRecompiler::FCTIDZ(u32 frd, u32 frb, bool rc) { } void PPULLVMRecompiler::FCFID(u32 frd, u32 frb, bool rc) { - InterpreterCall("FCFID", &PPUInterpreter::FCFID, frd, frb, rc); + auto rb_i64 = GetFpr(frb, 64, true); + auto res_f64 = m_ir_builder->CreateSIToFP(rb_i64, m_ir_builder->getDoubleTy()); + SetFpr(frd, res_f64); + + // TODO: Set flag + //InterpreterCall("FCFID", &PPUInterpreter::FCFID, frd, frb, rc); } void PPULLVMRecompiler::UNK(const u32 code, const u32 opcode, const u32 gcode) { @@ -3028,13 +3168,15 @@ void PPULLVMRecompiler::Compile(u32 address) { m_execution_engine->runJITOnFunction(m_function, &mci); CompiledBlockInfo block_info; - block_info.block = (CompiledBlock)mci.address(); - block_info.request_count = 0; - block_info.size = mci.size(); - block_info.llvm_function = m_function; + block_info.block_address = address; + block_info.revision = 0xFFFFFFFF; + block_info.block = (CompiledBlock)mci.address(); + block_info.reference_count = 0; + block_info.size = mci.size(); + block_info.llvm_function = m_function; { - std::lock_guard lock(m_address_to_compiled_block_map_mutex); - m_address_to_compiled_block_map[address] = block_info; + std::lock_guard lock(m_compiled_blocks_mutex); + m_compiled_blocks[std::make_pair(address, block_info.revision)] = block_info; } } @@ -3313,14 +3455,24 @@ void PPULLVMRecompiler::SetUsprg0(Value * val_x64) { m_ir_builder->CreateStore(val_i64, usprg0_i64_ptr); } -Value * PPULLVMRecompiler::GetFpr(u32 r, u32 bits) { - auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), (unsigned int)offsetof(PPUThread, FPR[r])); - auto r_f64_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getDoubleTy()->getPointerTo()); - auto r_f64 = m_ir_builder->CreateLoad(r_f64_ptr); - if (bits == 32) { - return m_ir_builder->CreateFPTrunc(r_f64, m_ir_builder->getFloatTy()); +Value * PPULLVMRecompiler::GetFpr(u32 r, u32 bits, bool as_int) { + auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), (unsigned int)offsetof(PPUThread, FPR[r])); + if (!as_int) { + auto r_f64_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getDoubleTy()->getPointerTo()); + auto r_f64 = m_ir_builder->CreateLoad(r_f64_ptr); + if (bits == 32) { + return m_ir_builder->CreateFPTrunc(r_f64, m_ir_builder->getFloatTy()); + } else { + return r_f64; + } } else { - return r_f64; + auto r_i64_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + auto r_i64 = m_ir_builder->CreateLoad(r_i64_ptr); + if (bits == 32) { + return m_ir_builder->CreateTrunc(r_i64, m_ir_builder->getInt32Ty()); + } else { + return r_i64; + } } } @@ -3560,15 +3712,31 @@ PPULLVMEmulator::~PPULLVMEmulator() { u8 PPULLVMEmulator::DecodeMemory(const u32 address) { static u32 last_instr_address = 0; - PPULLVMRecompiler::CompiledBlock compiled_block = nullptr; - if (address != (last_instr_address + 4)) { - compiled_block = s_recompiler->GetCompiledBlock(address); + auto compiled_block = m_compiled_blocks.find(address); + if (compiled_block == m_compiled_blocks.end()) { + auto compiled_block_info = s_recompiler->GetCompiledBlock(address); + if (compiled_block_info.block) { + compiled_block = m_compiled_blocks.insert(m_compiled_blocks.end(), std::make_pair(address, std::make_pair(compiled_block_info.block, compiled_block_info.revision))); + m_pending_compilation_blocks.erase(address); + } else { + if (address != (last_instr_address + 4)) { + auto pending_compilation_block = m_pending_compilation_blocks.find(address); + if (pending_compilation_block != m_pending_compilation_blocks.end()) { + pending_compilation_block->second++; + if ((pending_compilation_block->second % 1000) == 0) { + s_recompiler->RequestCompilation(address); + } + } else { + m_pending_compilation_blocks[address] = 0; + } + } + } } last_instr_address = address; - if (compiled_block) { - compiled_block(&m_ppu, (u64)Memory.GetBaseAddr(), m_interpreter); + if (compiled_block != m_compiled_blocks.end()) { + compiled_block->second.first(&m_ppu, (u64)Memory.GetBaseAddr(), m_interpreter); return 0; } else { return m_decoder.DecodeMemory(address); diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.h b/rpcs3/Emu/Cell/PPULLVMRecompiler.h index eb056476cc..29531a0a66 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.h +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.h @@ -19,6 +19,26 @@ class PPULLVMRecompiler : public ThreadBase, protected PPUOpcodes, protected PPC public: typedef void(*CompiledBlock)(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter); + struct CompiledBlockInfo { + /// Address of the block + u32 block_address; + + /// The version of the block + u32 revision; + + /// Pointer to the block + CompiledBlock block; + + /// Size of the compiled block + size_t size; + + /// Reference count for the block + u64 reference_count; + + /// LLVM function for this block + llvm::Function * llvm_function; + }; + PPULLVMRecompiler(); PPULLVMRecompiler(const PPULLVMRecompiler & other) = delete; @@ -29,8 +49,14 @@ public: PPULLVMRecompiler & operator = (const PPULLVMRecompiler & other) = delete; PPULLVMRecompiler & operator = (PPULLVMRecompiler && other) = delete; - /// Get a pointer to a compiled block - CompiledBlock GetCompiledBlock(u32 address); + /// Get a compiled block + CompiledBlockInfo GetCompiledBlock(u32 address); + + /// Release a compiled block + void ReleaseCompiledBlock(u32 address, u32 revision); + + /// Request a block to be compiled + void RequestCompilation(u32 address); /// Execute all tests void RunAllTests(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter); @@ -441,32 +467,18 @@ protected: void UNK(const u32 code, const u32 opcode, const u32 gcode) override; private: - struct CompiledBlockInfo { - /// Pointer to the block - CompiledBlock block; + /// Mutex for accessing m_compiled_blocks + std::mutex m_compiled_blocks_mutex; - /// Size of the compiled block - size_t size; + /// Blocks that have been compiled + /// Key is block address + std::map, CompiledBlockInfo> m_compiled_blocks; - /// Number of times this block was requested - u64 request_count; + /// Mutex for accessing m_pending_compilation_blocks; + std::mutex m_pending_compilation_blocks_mutex; - /// LLVM function for this block - llvm::Function * llvm_function; - }; - - /// Mutex for accessing m_address_to_compiled_block_map - /// TODO: Use a RW lock instead of mutex - std::mutex m_address_to_compiled_block_map_mutex; - - /// Map from address to compiled block - std::map m_address_to_compiled_block_map; - - /// Mutex for accessing m_pending_blocks_set; - std::mutex m_pending_blocks_set_mutex; - - /// Set of blocks pending compilation - std::set m_pending_blocks_set; + /// Blocks pending compilation + std::set m_pending_compilation_blocks; /// LLVM context llvm::LLVMContext * m_llvm_context; @@ -609,7 +621,7 @@ private: void SetUsprg0(llvm::Value * val_x64); /// Get FPR - llvm::Value * GetFpr(u32 r, u32 bits = 64); + llvm::Value * GetFpr(u32 r, u32 bits = 64, bool as_int = false); /// Set FPR void SetFpr(u32 r, llvm::Value * val); @@ -693,6 +705,14 @@ private: /// PPU instruction Decoder PPUDecoder m_decoder; + /// Compiled blocks + /// Key is block address. + std::unordered_map> m_compiled_blocks; + + /// Uncompiled blocks + /// Key is block address + std::unordered_map m_pending_compilation_blocks; + /// Number of instances of this class static u32 s_num_instances;