mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-15 14:42:40 +00:00
Run recompilation in the background
This commit is contained in:
parent
1f3a117744
commit
840ae2f86b
@ -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
@ -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
|
||||
|
@ -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;
|
||||
|
@ -112,7 +112,7 @@ void PPUThread::DoRun()
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_dec = new PPULLVMRecompiler(*this);
|
||||
m_dec = new PPULLVMEmulator(*this);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user