Run recompilation in the background

This commit is contained in:
S Gopal Rajagopal 2014-09-15 20:05:18 +05:30
parent 1f3a117744
commit 840ae2f86b
5 changed files with 594 additions and 500 deletions

View File

@ -56,7 +56,7 @@ u64 rotr64(const u64 x, const u8 n) { return (x >> n) | (x << (64 - n)); }
class PPUInterpreter : public PPUOpcodes
{
friend class PPULLVMRecompilerWorker;
friend class PPULLVMRecompiler;
private:
PPUThread& CPU;

File diff suppressed because it is too large Load Diff

View File

@ -13,31 +13,33 @@
struct PPURegState;
/// PPU recompiler
class PPULLVMRecompilerWorker : protected PPUOpcodes {
/// PPU to LLVM recompiler
class PPULLVMRecompiler : public ThreadBase, protected PPUOpcodes {
public:
typedef void(*CompiledBlock)(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter);
PPULLVMRecompilerWorker();
PPULLVMRecompiler();
PPULLVMRecompilerWorker(const PPULLVMRecompilerWorker & other) = delete;
PPULLVMRecompilerWorker(PPULLVMRecompilerWorker && other) = delete;
PPULLVMRecompiler(const PPULLVMRecompiler & other) = delete;
PPULLVMRecompiler(PPULLVMRecompiler && other) = delete;
virtual ~PPULLVMRecompilerWorker();
virtual ~PPULLVMRecompiler();
PPULLVMRecompilerWorker & operator = (const PPULLVMRecompilerWorker & other) = delete;
PPULLVMRecompilerWorker & operator = (PPULLVMRecompilerWorker && other) = delete;
PPULLVMRecompiler & operator = (const PPULLVMRecompiler & other) = delete;
PPULLVMRecompiler & operator = (PPULLVMRecompiler && other) = delete;
/// Compile a block of code
void Compile(u64 address);
/// Get a function pointer to a compiled block
/// Get a pointer to a compiled block
CompiledBlock GetCompiledBlock(u64 address);
/// Execute all tests
void RunAllTests(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter);
void Task() override;
protected:
/// Compile a block of code
void Compile(u64 address);
void NULL_OP() override;
void NOP() override;
@ -442,9 +444,19 @@ 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;
/// Map from address to compiled block
std::map<u64, CompiledBlock> 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<u64> m_pending_blocks_set;
/// LLVM context
llvm::LLVMContext * m_llvm_context;
@ -605,19 +617,19 @@ private:
void RunTest(const char * name, std::function<void()> test_case, std::function<void()> input, std::function<bool(std::string & msg)> check_result);
};
/// A dynarec PPU emulator that uses LLVM as the backend
class PPULLVMRecompiler : public CPUDecoder {
/// PPU emulator that uses LLVM to convert PPU instructions to host CPU instructions
class PPULLVMEmulator : public CPUDecoder {
public:
PPULLVMRecompiler(PPUThread & ppu);
PPULLVMRecompiler() = delete;
PPULLVMEmulator(PPUThread & ppu);
PPULLVMEmulator() = delete;
PPULLVMRecompiler(const PPULLVMRecompilerWorker & other) = delete;
PPULLVMRecompiler(PPULLVMRecompilerWorker && other) = delete;
PPULLVMEmulator(const PPULLVMEmulator & other) = delete;
PPULLVMEmulator(PPULLVMEmulator && other) = delete;
virtual ~PPULLVMRecompiler();
virtual ~PPULLVMEmulator();
PPULLVMRecompiler & operator = (const PPULLVMRecompiler & other) = delete;
PPULLVMRecompiler & operator = (PPULLVMRecompiler && other) = delete;
PPULLVMEmulator & operator = (const PPULLVMEmulator & other) = delete;
PPULLVMEmulator & operator = (PPULLVMEmulator && other) = delete;
u8 DecodeMemory(const u64 address);
@ -626,10 +638,19 @@ private:
PPUThread & m_ppu;
/// PPU Interpreter
PPUInterpreter m_interpreter;
PPUInterpreter * m_interpreter;
/// The actual compiler
PPULLVMRecompilerWorker m_worker;
/// PPU instruction Decoder
PPUDecoder m_decoder;
/// Number of instances of this class
static u32 s_num_instances;
/// Mutex used prevent multiple instances of the recompiler from being created
static std::mutex s_recompiler_mutex;
/// PPU to LLVM recompiler
static PPULLVMRecompiler * s_recompiler;
};
#endif // PPU_LLVM_RECOMPILER_H

View File

@ -9,7 +9,7 @@
using namespace llvm;
#define VERIFY_INSTRUCTION_AGAINST_INTERPRETER(fn, tc, input, ...) \
VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &PPULLVMRecompilerWorker::fn, &PPUInterpreter::fn, input, __VA_ARGS__)
VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &PPULLVMRecompiler::fn, &PPUInterpreter::fn, input, __VA_ARGS__)
#define VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(fn, s, n, ...) { \
PPURegState input; \
@ -160,7 +160,7 @@ static u64 s_base_address = 0;
static PPUInterpreter * s_interpreter = nullptr;
template <class PPULLVMRecompilerFn, class PPUInterpreterFn, class... Args>
void PPULLVMRecompilerWorker::VerifyInstructionAgainstInterpreter(const char * name, PPULLVMRecompilerFn recomp_fn, PPUInterpreterFn interp_fn, PPURegState & input_reg_state, Args... args) {
void PPULLVMRecompiler::VerifyInstructionAgainstInterpreter(const char * name, PPULLVMRecompilerFn recomp_fn, PPUInterpreterFn interp_fn, PPURegState & input_reg_state, Args... args) {
auto test_case = [&]() {
(this->*recomp_fn)(args...);
};
@ -188,7 +188,7 @@ void PPULLVMRecompilerWorker::VerifyInstructionAgainstInterpreter(const char * n
RunTest(name, test_case, input, check_result);
}
void PPULLVMRecompilerWorker::RunTest(const char * name, std::function<void()> test_case, std::function<void()> input, std::function<bool(std::string & msg)> check_result) {
void PPULLVMRecompiler::RunTest(const char * name, std::function<void()> test_case, std::function<void()> input, std::function<bool(std::string & msg)> check_result) {
// Create the unit test function
m_function = (Function *)m_module->getOrInsertFunction(name, m_ir_builder->getVoidTy(),
m_ir_builder->getInt8PtrTy() /*ppu_state*/,
@ -256,7 +256,7 @@ void PPULLVMRecompilerWorker::RunTest(const char * name, std::function<void()> t
m_execution_engine->freeMachineCodeForFunction(m_function);
}
void PPULLVMRecompilerWorker::RunAllTests(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter) {
void PPULLVMRecompiler::RunAllTests(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter) {
s_ppu_state = ppu_state;
s_base_address = base_address;
s_interpreter = interpreter;

View File

@ -112,7 +112,7 @@ void PPUThread::DoRun()
break;
case 3:
m_dec = new PPULLVMRecompiler(*this);
m_dec = new PPULLVMEmulator(*this);
break;
default: