mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 23:41:26 +12:00
Fixed some bugs that prevented the recompiler from terminating properly
This commit is contained in:
parent
840ae2f86b
commit
d69de9c332
3 changed files with 73 additions and 64 deletions
|
@ -16,7 +16,6 @@ using namespace llvm;
|
||||||
|
|
||||||
PPULLVMRecompiler::PPULLVMRecompiler()
|
PPULLVMRecompiler::PPULLVMRecompiler()
|
||||||
: ThreadBase("PPULLVMRecompiler")
|
: ThreadBase("PPULLVMRecompiler")
|
||||||
, m_decoder(this)
|
|
||||||
, m_compilation_time(0.0)
|
, m_compilation_time(0.0)
|
||||||
, m_idling_time(0.0) {
|
, m_idling_time(0.0) {
|
||||||
InitializeNativeTarget();
|
InitializeNativeTarget();
|
||||||
|
@ -34,8 +33,6 @@ PPULLVMRecompiler::PPULLVMRecompiler()
|
||||||
m_execution_engine = engine_builder.create();
|
m_execution_engine = engine_builder.create();
|
||||||
|
|
||||||
m_disassembler = LLVMCreateDisasm(sys::getProcessTriple().c_str(), nullptr, 0, nullptr, nullptr);
|
m_disassembler = LLVMCreateDisasm(sys::getProcessTriple().c_str(), nullptr, 0, nullptr, nullptr);
|
||||||
|
|
||||||
Start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PPULLVMRecompiler::~PPULLVMRecompiler() {
|
PPULLVMRecompiler::~PPULLVMRecompiler() {
|
||||||
|
@ -71,18 +68,22 @@ PPULLVMRecompiler::CompiledBlock PPULLVMRecompiler::GetCompiledBlock(u64 address
|
||||||
m_pending_blocks_set_mutex.lock();
|
m_pending_blocks_set_mutex.lock();
|
||||||
m_pending_blocks_set.insert(address);
|
m_pending_blocks_set.insert(address);
|
||||||
m_pending_blocks_set_mutex.unlock();
|
m_pending_blocks_set_mutex.unlock();
|
||||||
|
|
||||||
|
if (!IsAlive()) {
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
Notify();
|
Notify();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPULLVMRecompiler::Task() {
|
void PPULLVMRecompiler::Task() {
|
||||||
while (!TestDestroy()) {
|
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
|
||||||
std::chrono::high_resolution_clock::time_point idle_start = std::chrono::high_resolution_clock::now();
|
|
||||||
WaitForAnySignal();
|
|
||||||
std::chrono::high_resolution_clock::time_point idle_end = std::chrono::high_resolution_clock::now();
|
|
||||||
m_idling_time += std::chrono::duration_cast<std::chrono::duration<double>>(idle_end - idle_start);
|
|
||||||
|
|
||||||
while (!TestDestroy()) {
|
while (!TestDestroy() && !Emu.IsStopped()) {
|
||||||
|
WaitForAnySignal();
|
||||||
|
|
||||||
|
while (!TestDestroy() && !Emu.IsStopped()) {
|
||||||
u64 address;
|
u64 address;
|
||||||
|
|
||||||
m_pending_blocks_set_mutex.lock();
|
m_pending_blocks_set_mutex.lock();
|
||||||
|
@ -99,56 +100,13 @@ void PPULLVMRecompiler::Task() {
|
||||||
Compile(address);
|
Compile(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
|
||||||
|
m_idling_time = std::chrono::duration_cast<std::chrono::duration<double>>(end - start - m_compilation_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPULLVMRecompiler::Compile(const u64 address) {
|
void PPULLVMRecompiler::Decode(const u32 code) {
|
||||||
m_address_to_compiled_block_map_mutex.lock();
|
(*PPU_instr::main_list)(this, code);
|
||||||
auto i = m_address_to_compiled_block_map.find(address);
|
|
||||||
m_address_to_compiled_block_map_mutex.unlock();
|
|
||||||
|
|
||||||
if (i != m_address_to_compiled_block_map.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::chrono::high_resolution_clock::time_point compilation_start = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
auto function_name = fmt::Format("fn_0x%llX", address);
|
|
||||||
m_function = m_module->getFunction(function_name);
|
|
||||||
if (!m_function) {
|
|
||||||
|
|
||||||
m_function = (Function *)m_module->getOrInsertFunction(function_name, m_ir_builder->getVoidTy(),
|
|
||||||
m_ir_builder->getInt8PtrTy() /*ppu_state*/,
|
|
||||||
m_ir_builder->getInt64Ty() /*base_addres*/,
|
|
||||||
m_ir_builder->getInt8PtrTy() /*interpreter*/, nullptr);
|
|
||||||
m_function->setCallingConv(CallingConv::X86_64_Win64);
|
|
||||||
auto arg_i = m_function->arg_begin();
|
|
||||||
arg_i->setName("ppu_state");
|
|
||||||
(++arg_i)->setName("base_address");
|
|
||||||
(++arg_i)->setName("interpreter");
|
|
||||||
|
|
||||||
auto block = BasicBlock::Create(*m_llvm_context, "start", m_function);
|
|
||||||
m_ir_builder->SetInsertPoint(block);
|
|
||||||
|
|
||||||
u64 offset = 0;
|
|
||||||
m_hit_branch_instruction = false;
|
|
||||||
while (!m_hit_branch_instruction) {
|
|
||||||
u32 instr = Memory.Read32(address + offset);
|
|
||||||
m_decoder.Decode(instr);
|
|
||||||
offset += 4;
|
|
||||||
|
|
||||||
SetPc(m_ir_builder->getInt64(address + offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ir_builder->CreateRetVoid();
|
|
||||||
m_execution_engine->runJITOnFunction(m_function);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_address_to_compiled_block_map_mutex.lock();
|
|
||||||
m_address_to_compiled_block_map[address] = (CompiledBlock)m_execution_engine->getPointerToFunction(m_function);
|
|
||||||
m_address_to_compiled_block_map_mutex.unlock();
|
|
||||||
|
|
||||||
std::chrono::high_resolution_clock::time_point compilation_end = std::chrono::high_resolution_clock::now();
|
|
||||||
m_compilation_time += std::chrono::duration_cast<std::chrono::duration<double>>(compilation_end - compilation_start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPULLVMRecompiler::NULL_OP() {
|
void PPULLVMRecompiler::NULL_OP() {
|
||||||
|
@ -2506,6 +2464,56 @@ void PPULLVMRecompiler::UNK(const u32 code, const u32 opcode, const u32 gcode) {
|
||||||
//InterpreterCall("UNK", &PPUInterpreter::UNK, code, opcode, gcode);
|
//InterpreterCall("UNK", &PPUInterpreter::UNK, code, opcode, gcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PPULLVMRecompiler::Compile(const u64 address) {
|
||||||
|
m_address_to_compiled_block_map_mutex.lock();
|
||||||
|
auto i = m_address_to_compiled_block_map.find(address);
|
||||||
|
m_address_to_compiled_block_map_mutex.unlock();
|
||||||
|
|
||||||
|
if (i != m_address_to_compiled_block_map.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::high_resolution_clock::time_point compilation_start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
auto function_name = fmt::Format("fn_0x%llX", address);
|
||||||
|
m_function = m_module->getFunction(function_name);
|
||||||
|
if (!m_function) {
|
||||||
|
|
||||||
|
m_function = (Function *)m_module->getOrInsertFunction(function_name, m_ir_builder->getVoidTy(),
|
||||||
|
m_ir_builder->getInt8PtrTy() /*ppu_state*/,
|
||||||
|
m_ir_builder->getInt64Ty() /*base_addres*/,
|
||||||
|
m_ir_builder->getInt8PtrTy() /*interpreter*/, nullptr);
|
||||||
|
m_function->setCallingConv(CallingConv::X86_64_Win64);
|
||||||
|
auto arg_i = m_function->arg_begin();
|
||||||
|
arg_i->setName("ppu_state");
|
||||||
|
(++arg_i)->setName("base_address");
|
||||||
|
(++arg_i)->setName("interpreter");
|
||||||
|
|
||||||
|
auto block = BasicBlock::Create(*m_llvm_context, "start", m_function);
|
||||||
|
m_ir_builder->SetInsertPoint(block);
|
||||||
|
|
||||||
|
u64 offset = 0;
|
||||||
|
m_hit_branch_instruction = false;
|
||||||
|
while (!m_hit_branch_instruction) {
|
||||||
|
u32 instr = Memory.Read32(address + offset);
|
||||||
|
Decode(instr);
|
||||||
|
offset += 4;
|
||||||
|
|
||||||
|
SetPc(m_ir_builder->getInt64(address + offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ir_builder->CreateRetVoid();
|
||||||
|
m_execution_engine->runJITOnFunction(m_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_address_to_compiled_block_map_mutex.lock();
|
||||||
|
m_address_to_compiled_block_map[address] = (CompiledBlock)m_execution_engine->getPointerToFunction(m_function);
|
||||||
|
m_address_to_compiled_block_map_mutex.unlock();
|
||||||
|
|
||||||
|
std::chrono::high_resolution_clock::time_point compilation_end = std::chrono::high_resolution_clock::now();
|
||||||
|
m_compilation_time += std::chrono::duration_cast<std::chrono::duration<double>>(compilation_end - compilation_start);
|
||||||
|
}
|
||||||
|
|
||||||
Value * PPULLVMRecompiler::GetPPUState() {
|
Value * PPULLVMRecompiler::GetPPUState() {
|
||||||
return m_function->arg_begin();
|
return m_function->arg_begin();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
struct PPURegState;
|
struct PPURegState;
|
||||||
|
|
||||||
/// PPU to LLVM recompiler
|
/// PPU to LLVM recompiler
|
||||||
class PPULLVMRecompiler : public ThreadBase, protected PPUOpcodes {
|
class PPULLVMRecompiler : public ThreadBase, protected PPUOpcodes, protected PPCDecoder {
|
||||||
public:
|
public:
|
||||||
typedef void(*CompiledBlock)(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter);
|
typedef void(*CompiledBlock)(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter);
|
||||||
|
|
||||||
|
@ -37,8 +37,7 @@ public:
|
||||||
void Task() override;
|
void Task() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Compile a block of code
|
void Decode(const u32 code) override;
|
||||||
void Compile(u64 address);
|
|
||||||
|
|
||||||
void NULL_OP() override;
|
void NULL_OP() override;
|
||||||
void NOP() override;
|
void NOP() override;
|
||||||
|
@ -441,9 +440,6 @@ protected:
|
||||||
void UNK(const u32 code, const u32 opcode, const u32 gcode) override;
|
void UNK(const u32 code, const u32 opcode, const u32 gcode) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// PPU instruction decoder
|
|
||||||
PPUDecoder m_decoder;
|
|
||||||
|
|
||||||
/// Mutex for accessing m_address_to_compiled_block_map
|
/// Mutex for accessing m_address_to_compiled_block_map
|
||||||
/// TODO: Use a RW lock instead of mutex
|
/// TODO: Use a RW lock instead of mutex
|
||||||
std::mutex m_address_to_compiled_block_map_mutex;
|
std::mutex m_address_to_compiled_block_map_mutex;
|
||||||
|
@ -489,6 +485,9 @@ private:
|
||||||
/// Contains the number of times the interpreter fallback was used
|
/// Contains the number of times the interpreter fallback was used
|
||||||
std::map<std::string, u64> m_interpreter_fallback_stats;
|
std::map<std::string, u64> m_interpreter_fallback_stats;
|
||||||
|
|
||||||
|
/// Compile a block of code
|
||||||
|
void Compile(u64 address);
|
||||||
|
|
||||||
/// Get PPU state pointer
|
/// Get PPU state pointer
|
||||||
llvm::Value * GetPPUState();
|
llvm::Value * GetPPUState();
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,9 @@ void PPUThread::DoRun()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
m_dec = new PPULLVMEmulator(*this);
|
if (!m_dec) {
|
||||||
|
m_dec = new PPULLVMEmulator(*this);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue