Fixed some bugs that prevented the recompiler from terminating properly

This commit is contained in:
S Gopal Rajagopal 2014-09-15 20:05:51 +05:30
parent 840ae2f86b
commit d69de9c332
3 changed files with 73 additions and 64 deletions

View file

@ -16,7 +16,6 @@ using namespace llvm;
PPULLVMRecompiler::PPULLVMRecompiler()
: ThreadBase("PPULLVMRecompiler")
, m_decoder(this)
, m_compilation_time(0.0)
, m_idling_time(0.0) {
InitializeNativeTarget();
@ -34,8 +33,6 @@ PPULLVMRecompiler::PPULLVMRecompiler()
m_execution_engine = engine_builder.create();
m_disassembler = LLVMCreateDisasm(sys::getProcessTriple().c_str(), nullptr, 0, nullptr, nullptr);
Start();
}
PPULLVMRecompiler::~PPULLVMRecompiler() {
@ -71,18 +68,22 @@ PPULLVMRecompiler::CompiledBlock PPULLVMRecompiler::GetCompiledBlock(u64 address
m_pending_blocks_set_mutex.lock();
m_pending_blocks_set.insert(address);
m_pending_blocks_set_mutex.unlock();
if (!IsAlive()) {
Start();
}
Notify();
return nullptr;
}
void PPULLVMRecompiler::Task() {
while (!TestDestroy()) {
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);
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
while (!TestDestroy()) {
while (!TestDestroy() && !Emu.IsStopped()) {
WaitForAnySignal();
while (!TestDestroy() && !Emu.IsStopped()) {
u64 address;
m_pending_blocks_set_mutex.lock();
@ -99,56 +100,13 @@ void PPULLVMRecompiler::Task() {
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) {
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);
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::Decode(const u32 code) {
(*PPU_instr::main_list)(this, code);
}
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);
}
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() {
return m_function->arg_begin();
}

View file

@ -14,7 +14,7 @@
struct PPURegState;
/// PPU to LLVM recompiler
class PPULLVMRecompiler : public ThreadBase, protected PPUOpcodes {
class PPULLVMRecompiler : public ThreadBase, protected PPUOpcodes, protected PPCDecoder {
public:
typedef void(*CompiledBlock)(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter);
@ -37,8 +37,7 @@ public:
void Task() override;
protected:
/// Compile a block of code
void Compile(u64 address);
void Decode(const u32 code) override;
void NULL_OP() override;
void NOP() override;
@ -441,9 +440,6 @@ protected:
void UNK(const u32 code, const u32 opcode, const u32 gcode) override;
private:
/// PPU instruction decoder
PPUDecoder m_decoder;
/// 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;
@ -489,6 +485,9 @@ private:
/// Contains the number of times the interpreter fallback was used
std::map<std::string, u64> m_interpreter_fallback_stats;
/// Compile a block of code
void Compile(u64 address);
/// Get PPU state pointer
llvm::Value * GetPPUState();

View file

@ -112,7 +112,9 @@ void PPUThread::DoRun()
break;
case 3:
m_dec = new PPULLVMEmulator(*this);
if (!m_dec) {
m_dec = new PPULLVMEmulator(*this);
}
break;
default: