From f5188cdb3233e2885c0774692f479df598372a74 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Mon, 15 Sep 2014 20:04:09 +0530 Subject: [PATCH] Some refactoring. Added support for some load/store instructions. --- rpcs3/Emu/Cell/PPUInterpreter.h | 8 +- rpcs3/Emu/Cell/PPULLVMRecompiler.cpp | 2925 ++++++++++++--------- rpcs3/Emu/Cell/PPULLVMRecompiler.h | 167 +- rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp | 207 +- 4 files changed, 1997 insertions(+), 1310 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 037256de9a..b8cdda82d5 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -56,7 +56,7 @@ u64 rotr64(const u64 x, const u8 n) { return (x >> n) | (x << (64 - n)); } class PPUInterpreter : public PPUOpcodes { - friend class PPULLVMRecompiler; + friend class PPULLVMRecompilerWorker; private: PPUThread& CPU; @@ -2207,7 +2207,7 @@ private: } void ORIS(u32 ra, u32 rs, u32 uimm16) { - CPU.GPR[ra] = CPU.GPR[rs] | (uimm16 << 16); + CPU.GPR[ra] = CPU.GPR[rs] | ((u64)uimm16 << 16); } void XORI(u32 ra, u32 rs, u32 uimm16) { @@ -2215,7 +2215,7 @@ private: } void XORIS(u32 ra, u32 rs, u32 uimm16) { - CPU.GPR[ra] = CPU.GPR[rs] ^ (uimm16 << 16); + CPU.GPR[ra] = CPU.GPR[rs] ^ ((u64)uimm16 << 16); } void ANDI_(u32 ra, u32 rs, u32 uimm16) { @@ -2224,7 +2224,7 @@ private: } void ANDIS_(u32 ra, u32 rs, u32 uimm16) { - CPU.GPR[ra] = CPU.GPR[rs] & (uimm16 << 16); + CPU.GPR[ra] = CPU.GPR[rs] & ((u64)uimm16 << 16); CPU.UpdateCR0(CPU.GPR[ra]); } void RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 1af2c166f2..410c7cb704 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -12,213 +12,168 @@ using namespace llvm; -u32 PPULLVMRecompiler::s_num_instances; -std::map PPULLVMRecompiler::s_address_to_code_map; -std::mutex PPULLVMRecompiler::s_address_to_code_map_mutex; -std::mutex PPULLVMRecompiler::s_llvm_mutex; -LLVMContext * PPULLVMRecompiler::s_llvm_context; -IRBuilder<> * PPULLVMRecompiler::s_ir_builder; -llvm::Module * PPULLVMRecompiler::s_module; -Function * PPULLVMRecompiler::s_execute_this_call_fn; -MDNode * PPULLVMRecompiler::s_execute_this_call_fn_name_and_args_md_node; -ExecutionEngine * PPULLVMRecompiler::s_execution_engine; -LLVMDisasmContextRef PPULLVMRecompiler::s_disassembler; -Value * PPULLVMRecompiler::s_state_ptr; -std::chrono::duration PPULLVMRecompiler::s_compilation_time; -std::chrono::duration PPULLVMRecompiler::s_execution_time; -std::map PPULLVMRecompiler::s_interpreter_invocation_stats; -std::list *> PPULLVMRecompiler::s_this_call_ptrs_list; +PPULLVMRecompilerWorker::PPULLVMRecompilerWorker() + : m_decoder(this) + , m_compilation_time(0.0) + , m_idling_time(0.0) { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetDisassembler(); -PPULLVMRecompiler::PPULLVMRecompiler(PPUThread & ppu) - : m_ppu(ppu) - , m_decoder(this) - , m_interpreter(ppu) { - std::lock_guard lock(s_llvm_mutex); + m_llvm_context = new LLVMContext(); + m_ir_builder = new IRBuilder<>(*m_llvm_context); + m_module = new llvm::Module("Module", *m_llvm_context); - s_num_instances++; - if (!s_llvm_context) { - InitializeNativeTarget(); - InitializeNativeTargetAsmPrinter(); - InitializeNativeTargetDisassembler(); + EngineBuilder engine_builder(m_module); + engine_builder.setMCPU(sys::getHostCPUName()); + engine_builder.setEngineKind(EngineKind::JIT); + engine_builder.setOptLevel(CodeGenOpt::Default); + m_execution_engine = engine_builder.create(); - s_llvm_context = new LLVMContext(); - s_ir_builder = new IRBuilder<>(*s_llvm_context); - s_module = new llvm::Module("Module", *s_llvm_context); - - s_execute_this_call_fn = cast(s_module->getOrInsertFunction("ExecuteThisCall", s_ir_builder->getVoidTy(), s_ir_builder->getInt64Ty()->getPointerTo(), nullptr)); - s_execute_this_call_fn->setCallingConv(CallingConv::X86_64_Win64); - s_execute_this_call_fn_name_and_args_md_node = MDNode::get(*s_llvm_context, MDString::get(*s_llvm_context, "Function name and arguments")); - - EngineBuilder engine_builder(s_module); - engine_builder.setMCPU(sys::getHostCPUName()); - engine_builder.setEngineKind(EngineKind::JIT); - engine_builder.setOptLevel(CodeGenOpt::Default); - s_execution_engine = engine_builder.create(); - - s_execution_engine->addGlobalMapping(s_execute_this_call_fn, (void *)&PPULLVMRecompiler::ExecuteThisCall); - - s_disassembler = LLVMCreateDisasm(sys::getProcessTriple().c_str(), nullptr, 0, nullptr, nullptr); - - //RunAllTests(); - } + m_disassembler = LLVMCreateDisasm(sys::getProcessTriple().c_str(), nullptr, 0, nullptr, nullptr); } -PPULLVMRecompiler::~PPULLVMRecompiler() { - std::lock_guard lock(s_llvm_mutex); +PPULLVMRecompilerWorker::~PPULLVMRecompilerWorker() { + std::string error; + raw_fd_ostream log_file("PPULLVMRecompilerWorker.log", error, sys::fs::F_Text); + log_file << "Time spent compiling = " << m_compilation_time.count() << "s\n"; + log_file << "Time spent idling = " << m_idling_time.count() << "s\n\n"; + log_file << "Interpreter fallback stats:\n"; + for (auto i = m_interpreter_fallback_stats.begin(); i != m_interpreter_fallback_stats.end(); i++) { + log_file << i->first << " = " << i->second << "\n"; + } - s_num_instances--; - if (s_num_instances == 0) { - for (auto i = s_this_call_ptrs_list.begin(); i != s_this_call_ptrs_list.end(); i++) { - delete *i; + log_file << "\nLLVM IR:\n"; + log_file << *m_module; + + LLVMDisasmDispose(m_disassembler); + delete m_execution_engine; + delete m_ir_builder; + delete m_llvm_context; +} + +void PPULLVMRecompilerWorker::Compile(const u64 address) { + auto i = m_address_to_compiled_block_map.find(address); + 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)); } - s_this_call_ptrs_list.clear(); - - std::string error; - raw_fd_ostream log_file("PPULLVMRecompiler.log", error, sys::fs::F_Text); - log_file << "Time spent compiling = " << s_compilation_time.count() << "s\n"; - log_file << "Time spent executing = " << s_execution_time.count() << "s\n\n"; - log_file << "Interpreter invocation stats:\n"; - for (auto i = s_interpreter_invocation_stats.begin(); i != s_interpreter_invocation_stats.end(); i++) { - log_file << i->first << " = " << i->second << "\n"; - } - - log_file << "\nLLVM IR:\n"; - log_file << *s_module; - - s_address_to_code_map.clear(); - LLVMDisasmDispose(s_disassembler); - delete s_execution_engine; - delete s_ir_builder; - delete s_llvm_context; - } -} - -u8 PPULLVMRecompiler::DecodeMemory(const u64 address) { - void * compiled_code = nullptr; - - s_address_to_code_map_mutex.lock(); - auto i = s_address_to_code_map.find(address); - s_address_to_code_map_mutex.unlock(); - - if (i != s_address_to_code_map.end()) { - compiled_code = i->second; + m_ir_builder->CreateRetVoid(); + m_execution_engine->runJITOnFunction(m_function); } - if (!compiled_code) { - std::lock_guard lock(s_llvm_mutex); + m_address_to_compiled_block_map[address] = (CompiledBlock)m_execution_engine->getPointerToFunction(m_function); - auto function_name = fmt::Format("fn_0x%llX", address); - auto function = s_module->getFunction(function_name); - if (!function) { - std::chrono::high_resolution_clock::time_point compilation_start = std::chrono::high_resolution_clock::now(); + std::chrono::high_resolution_clock::time_point compilation_end = std::chrono::high_resolution_clock::now(); + m_compilation_time += std::chrono::duration_cast>(compilation_end - compilation_start); +} - function = cast(s_module->getOrInsertFunction(function_name, s_ir_builder->getVoidTy(), s_ir_builder->getInt8Ty()->getPointerTo(), nullptr)); - function->setCallingConv(CallingConv::X86_64_Win64); - s_state_ptr = function->arg_begin(); - s_state_ptr->setName("state"); - - auto block = BasicBlock::Create(*s_llvm_context, "start", function); - s_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(s_ir_builder->getInt64(m_ppu.PC + offset)); - } - - s_ir_builder->CreateRetVoid(); - s_execution_engine->runJITOnFunction(function); - - compiled_code = s_execution_engine->getPointerToFunction(function); - s_address_to_code_map_mutex.lock(); - s_address_to_code_map[address] = compiled_code; - s_address_to_code_map_mutex.unlock(); - - std::chrono::high_resolution_clock::time_point compilation_end = std::chrono::high_resolution_clock::now(); - s_compilation_time += std::chrono::duration_cast>(compilation_end - compilation_start); - } +PPULLVMRecompilerWorker::CompiledBlock PPULLVMRecompilerWorker::GetCompiledBlock(u64 address) { + auto i = m_address_to_compiled_block_map.find(address); + if (i != m_address_to_compiled_block_map.end()) { + return i->second; } - std::chrono::high_resolution_clock::time_point execution_start = std::chrono::high_resolution_clock::now(); - ((void(*)(PPUThread *))(compiled_code))(&m_ppu); - std::chrono::high_resolution_clock::time_point execution_end = std::chrono::high_resolution_clock::now(); - s_execution_time += std::chrono::duration_cast>(execution_end - execution_start); - return 0; + return nullptr; } -void PPULLVMRecompiler::NULL_OP() { - ThisCall("NULL_OP", &PPUInterpreter::NULL_OP, &m_interpreter); +void PPULLVMRecompilerWorker::NULL_OP() { + InterpreterCall("NULL_OP", &PPUInterpreter::NULL_OP); } -void PPULLVMRecompiler::NOP() { - ThisCall("NOP", &PPUInterpreter::NOP, &m_interpreter); +void PPULLVMRecompilerWorker::NOP() { + InterpreterCall("NOP", &PPUInterpreter::NOP); } -void PPULLVMRecompiler::TDI(u32 to, u32 ra, s32 simm16) { - ThisCall("TDI", &PPUInterpreter::TDI, &m_interpreter, to, ra, simm16); +void PPULLVMRecompilerWorker::TDI(u32 to, u32 ra, s32 simm16) { + InterpreterCall("TDI", &PPUInterpreter::TDI, to, ra, simm16); } -void PPULLVMRecompiler::TWI(u32 to, u32 ra, s32 simm16) { - ThisCall("TWI", &PPUInterpreter::TWI, &m_interpreter, to, ra, simm16); +void PPULLVMRecompilerWorker::TWI(u32 to, u32 ra, s32 simm16) { + InterpreterCall("TWI", &PPUInterpreter::TWI, to, ra, simm16); } -void PPULLVMRecompiler::MFVSCR(u32 vd) { +void PPULLVMRecompilerWorker::MFVSCR(u32 vd) { auto vscr_i32 = GetVscr(); - auto vscr_i128 = s_ir_builder->CreateZExt(vscr_i32, s_ir_builder->getIntNTy(128)); + auto vscr_i128 = m_ir_builder->CreateZExt(vscr_i32, m_ir_builder->getIntNTy(128)); SetVr(vd, vscr_i128); } -void PPULLVMRecompiler::MTVSCR(u32 vb) { +void PPULLVMRecompilerWorker::MTVSCR(u32 vb) { auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto vscr_i32 = s_ir_builder->CreateExtractElement(vb_v4i32, s_ir_builder->getInt32(0)); - vscr_i32 = s_ir_builder->CreateAnd(vscr_i32, 0x00010001); + auto vscr_i32 = m_ir_builder->CreateExtractElement(vb_v4i32, m_ir_builder->getInt32(0)); + vscr_i32 = m_ir_builder->CreateAnd(vscr_i32, 0x00010001); SetVscr(vscr_i32); } -void PPULLVMRecompiler::VADDCUW(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDCUW(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); u32 not_mask_v4i32[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; - va_v4i32 = s_ir_builder->CreateXor(va_v4i32, ConstantDataVector::get(*s_llvm_context, not_mask_v4i32)); - auto cmpv4i1 = s_ir_builder->CreateICmpULT(va_v4i32, vb_v4i32); - auto cmpv4i32 = s_ir_builder->CreateZExt(cmpv4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); + va_v4i32 = m_ir_builder->CreateXor(va_v4i32, ConstantDataVector::get(*m_llvm_context, not_mask_v4i32)); + auto cmpv4i1 = m_ir_builder->CreateICmpULT(va_v4i32, vb_v4i32); + auto cmpv4i32 = m_ir_builder->CreateZExt(cmpv4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); SetVr(vd, cmpv4i32); // TODO: Implement with overflow intrinsics and check if the generated code is better } -void PPULLVMRecompiler::VADDFP(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDFP(u32 vd, u32 va, u32 vb) { auto va_v4f32 = GetVrAsFloatVec(va); auto vb_v4f32 = GetVrAsFloatVec(vb); - auto sum_v4f32 = s_ir_builder->CreateFAdd(va_v4f32, vb_v4f32); + auto sum_v4f32 = m_ir_builder->CreateFAdd(va_v4f32, vb_v4f32); SetVr(vd, sum_v4f32); } -void PPULLVMRecompiler::VADDSBS(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDSBS(u32 vd, u32 va, u32 vb) { auto va_v16i8 = GetVrAsIntVec(va, 8); auto vb_v16i8 = GetVrAsIntVec(vb, 8); - auto sum_v16i8 = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_sse2_padds_b), va_v16i8, vb_v16i8); + auto sum_v16i8 = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_sse2_padds_b), va_v16i8, vb_v16i8); SetVr(vd, sum_v16i8); // TODO: Set VSCR.SAT } -void PPULLVMRecompiler::VADDSHS(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDSHS(u32 vd, u32 va, u32 vb) { auto va_v8i16 = GetVrAsIntVec(va, 16); auto vb_v8i16 = GetVrAsIntVec(vb, 16); - auto sum_v8i16 = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_sse2_padds_w), va_v8i16, vb_v8i16); + auto sum_v8i16 = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_sse2_padds_w), va_v8i16, vb_v8i16); SetVr(vd, sum_v8i16); // TODO: Set VSCR.SAT } -void PPULLVMRecompiler::VADDSWS(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDSWS(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); @@ -229,1953 +184,2381 @@ void PPULLVMRecompiler::VADDSWS(u32 vd, u32 va, u32 vb) { // number and a +ve number cannot cause overflow. So the result in case of an overflow is 0x7FFFFFFF + sign bit // of any one of the operands. u32 tmp1_v4i32[4] = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF}; - auto tmp2_v4i32 = s_ir_builder->CreateLShr(va_v4i32, 31); - tmp2_v4i32 = s_ir_builder->CreateAdd(tmp2_v4i32, ConstantDataVector::get(*s_llvm_context, tmp1_v4i32)); - auto tmp2_v16i8 = s_ir_builder->CreateBitCast(tmp2_v4i32, VectorType::get(s_ir_builder->getInt8Ty(), 16)); + auto tmp2_v4i32 = m_ir_builder->CreateLShr(va_v4i32, 31); + tmp2_v4i32 = m_ir_builder->CreateAdd(tmp2_v4i32, ConstantDataVector::get(*m_llvm_context, tmp1_v4i32)); + auto tmp2_v16i8 = m_ir_builder->CreateBitCast(tmp2_v4i32, VectorType::get(m_ir_builder->getInt8Ty(), 16)); // Next, we find if the addition can actually result in an overflow. Since an overflow can only happen if the operands // have the same sign, we bitwise XOR both the operands. If the sign bit of the result is 0 then the operands have the // same sign and so may cause an overflow. We invert the result so that the sign bit is 1 when the operands have the // same sign. - auto tmp3_v4i32 = s_ir_builder->CreateXor(va_v4i32, vb_v4i32); + auto tmp3_v4i32 = m_ir_builder->CreateXor(va_v4i32, vb_v4i32); u32 not_mask_v4i32[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; - tmp3_v4i32 = s_ir_builder->CreateXor(tmp3_v4i32, ConstantDataVector::get(*s_llvm_context, not_mask_v4i32)); + tmp3_v4i32 = m_ir_builder->CreateXor(tmp3_v4i32, ConstantDataVector::get(*m_llvm_context, not_mask_v4i32)); // Perform the sum. - auto sum_v4i32 = s_ir_builder->CreateAdd(va_v4i32, vb_v4i32); - auto sum_v16i8 = s_ir_builder->CreateBitCast(sum_v4i32, VectorType::get(s_ir_builder->getInt8Ty(), 16)); + auto sum_v4i32 = m_ir_builder->CreateAdd(va_v4i32, vb_v4i32); + auto sum_v16i8 = m_ir_builder->CreateBitCast(sum_v4i32, VectorType::get(m_ir_builder->getInt8Ty(), 16)); // If an overflow occurs, then the sign of the sum will be different from the sign of the operands. So, we xor the // result with one of the operands. The sign bit of the result will be 1 if the sign bit of the sum and the sign bit of the // result is different. This result is again ANDed with tmp3 (the sign bit of tmp3 is 1 only if the operands have the same // sign and so can cause an overflow). - auto tmp4_v4i32 = s_ir_builder->CreateXor(va_v4i32, sum_v4i32); - tmp4_v4i32 = s_ir_builder->CreateAnd(tmp3_v4i32, tmp4_v4i32); - tmp4_v4i32 = s_ir_builder->CreateAShr(tmp4_v4i32, 31); - auto tmp4_v16i8 = s_ir_builder->CreateBitCast(tmp4_v4i32, VectorType::get(s_ir_builder->getInt8Ty(), 16)); + auto tmp4_v4i32 = m_ir_builder->CreateXor(va_v4i32, sum_v4i32); + tmp4_v4i32 = m_ir_builder->CreateAnd(tmp3_v4i32, tmp4_v4i32); + tmp4_v4i32 = m_ir_builder->CreateAShr(tmp4_v4i32, 31); + auto tmp4_v16i8 = m_ir_builder->CreateBitCast(tmp4_v4i32, VectorType::get(m_ir_builder->getInt8Ty(), 16)); // tmp4 is equal to 0xFFFFFFFF if an overflow occured and 0x00000000 otherwise. - auto res_v16i8 = s_ir_builder->CreateCall3(Intrinsic::getDeclaration(s_module, Intrinsic::x86_sse41_pblendvb), sum_v16i8, tmp2_v16i8, tmp4_v16i8); + auto res_v16i8 = m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::x86_sse41_pblendvb), sum_v16i8, tmp2_v16i8, tmp4_v16i8); SetVr(vd, res_v16i8); // TODO: Set SAT } -void PPULLVMRecompiler::VADDUBM(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDUBM(u32 vd, u32 va, u32 vb) { auto va_v16i8 = GetVrAsIntVec(va, 8); auto vb_v16i8 = GetVrAsIntVec(vb, 8); - auto sum_v16i8 = s_ir_builder->CreateAdd(va_v16i8, vb_v16i8); + auto sum_v16i8 = m_ir_builder->CreateAdd(va_v16i8, vb_v16i8); SetVr(vd, sum_v16i8); } -void PPULLVMRecompiler::VADDUBS(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDUBS(u32 vd, u32 va, u32 vb) { auto va_v16i8 = GetVrAsIntVec(va, 8); auto vb_v16i8 = GetVrAsIntVec(vb, 8); - auto sum_v16i8 = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_sse2_paddus_b), va_v16i8, vb_v16i8); + auto sum_v16i8 = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_sse2_paddus_b), va_v16i8, vb_v16i8); SetVr(vd, sum_v16i8); // TODO: Set SAT } -void PPULLVMRecompiler::VADDUHM(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDUHM(u32 vd, u32 va, u32 vb) { auto va_v8i16 = GetVrAsIntVec(va, 16); auto vb_v8i16 = GetVrAsIntVec(vb, 16); - auto sum_v8i16 = s_ir_builder->CreateAdd(va_v8i16, vb_v8i16); + auto sum_v8i16 = m_ir_builder->CreateAdd(va_v8i16, vb_v8i16); SetVr(vd, sum_v8i16); } -void PPULLVMRecompiler::VADDUHS(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDUHS(u32 vd, u32 va, u32 vb) { auto va_v8i16 = GetVrAsIntVec(va, 16); auto vb_v8i16 = GetVrAsIntVec(vb, 16); - auto sum_v8i16 = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_sse2_paddus_w), va_v8i16, vb_v8i16); + auto sum_v8i16 = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_sse2_paddus_w), va_v8i16, vb_v8i16); SetVr(vd, sum_v8i16); // TODO: Set SAT } -void PPULLVMRecompiler::VADDUWM(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDUWM(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto sum_v4i32 = s_ir_builder->CreateAdd(va_v4i32, vb_v4i32); + auto sum_v4i32 = m_ir_builder->CreateAdd(va_v4i32, vb_v4i32); SetVr(vd, sum_v4i32); } -void PPULLVMRecompiler::VADDUWS(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VADDUWS(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto sum_v4i32 = s_ir_builder->CreateAdd(va_v4i32, vb_v4i32); - auto cmp_v4i1 = s_ir_builder->CreateICmpULT(sum_v4i32, va_v4i32); - auto cmp_v4i32 = s_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); - auto res_v4i32 = s_ir_builder->CreateOr(sum_v4i32, cmp_v4i32); + auto sum_v4i32 = m_ir_builder->CreateAdd(va_v4i32, vb_v4i32); + auto cmp_v4i1 = m_ir_builder->CreateICmpULT(sum_v4i32, va_v4i32); + auto cmp_v4i32 = m_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); + auto res_v4i32 = m_ir_builder->CreateOr(sum_v4i32, cmp_v4i32); SetVr(vd, res_v4i32); // TODO: Set SAT } -void PPULLVMRecompiler::VAND(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VAND(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto res_v4i32 = s_ir_builder->CreateAnd(va_v4i32, vb_v4i32); + auto res_v4i32 = m_ir_builder->CreateAnd(va_v4i32, vb_v4i32); SetVr(vd, res_v4i32); } -void PPULLVMRecompiler::VANDC(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VANDC(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); u32 not_mask_v4i32[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; - vb_v4i32 = s_ir_builder->CreateXor(vb_v4i32, ConstantDataVector::get(*s_llvm_context, not_mask_v4i32)); - auto res_v4i32 = s_ir_builder->CreateAnd(va_v4i32, vb_v4i32); + vb_v4i32 = m_ir_builder->CreateXor(vb_v4i32, ConstantDataVector::get(*m_llvm_context, not_mask_v4i32)); + auto res_v4i32 = m_ir_builder->CreateAnd(va_v4i32, vb_v4i32); SetVr(vd, res_v4i32); } -void PPULLVMRecompiler::VAVGSB(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VAVGSB(u32 vd, u32 va, u32 vb) { auto va_v16i8 = GetVrAsIntVec(va, 8); auto vb_v16i8 = GetVrAsIntVec(vb, 8); - auto va_v16i16 = s_ir_builder->CreateSExt(va_v16i8, VectorType::get(s_ir_builder->getInt16Ty(), 16)); - auto vb_v16i16 = s_ir_builder->CreateSExt(vb_v16i8, VectorType::get(s_ir_builder->getInt16Ty(), 16)); - auto sum_v16i16 = s_ir_builder->CreateAdd(va_v16i16, vb_v16i16); + auto va_v16i16 = m_ir_builder->CreateSExt(va_v16i8, VectorType::get(m_ir_builder->getInt16Ty(), 16)); + auto vb_v16i16 = m_ir_builder->CreateSExt(vb_v16i8, VectorType::get(m_ir_builder->getInt16Ty(), 16)); + auto sum_v16i16 = m_ir_builder->CreateAdd(va_v16i16, vb_v16i16); u16 one_v16i16[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - sum_v16i16 = s_ir_builder->CreateAdd(sum_v16i16, ConstantDataVector::get(*s_llvm_context, one_v16i16)); - auto avg_v16i16 = s_ir_builder->CreateAShr(sum_v16i16, 1); - auto avg_v16i8 = s_ir_builder->CreateTrunc(avg_v16i16, VectorType::get(s_ir_builder->getInt8Ty(), 16)); + sum_v16i16 = m_ir_builder->CreateAdd(sum_v16i16, ConstantDataVector::get(*m_llvm_context, one_v16i16)); + auto avg_v16i16 = m_ir_builder->CreateAShr(sum_v16i16, 1); + auto avg_v16i8 = m_ir_builder->CreateTrunc(avg_v16i16, VectorType::get(m_ir_builder->getInt8Ty(), 16)); SetVr(vd, avg_v16i8); } -void PPULLVMRecompiler::VAVGSH(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VAVGSH(u32 vd, u32 va, u32 vb) { auto va_v8i16 = GetVrAsIntVec(va, 16); auto vb_v8i16 = GetVrAsIntVec(vb, 16); - auto va_v8i32 = s_ir_builder->CreateSExt(va_v8i16, VectorType::get(s_ir_builder->getInt32Ty(), 8)); - auto vb_v8i32 = s_ir_builder->CreateSExt(vb_v8i16, VectorType::get(s_ir_builder->getInt32Ty(), 8)); - auto sum_v8i32 = s_ir_builder->CreateAdd(va_v8i32, vb_v8i32); + auto va_v8i32 = m_ir_builder->CreateSExt(va_v8i16, VectorType::get(m_ir_builder->getInt32Ty(), 8)); + auto vb_v8i32 = m_ir_builder->CreateSExt(vb_v8i16, VectorType::get(m_ir_builder->getInt32Ty(), 8)); + auto sum_v8i32 = m_ir_builder->CreateAdd(va_v8i32, vb_v8i32); u32 one_v8i32[8] = {1, 1, 1, 1, 1, 1, 1, 1}; - sum_v8i32 = s_ir_builder->CreateAdd(sum_v8i32, ConstantDataVector::get(*s_llvm_context, one_v8i32)); - auto avg_v8i32 = s_ir_builder->CreateAShr(sum_v8i32, 1); - auto avg_v8i16 = s_ir_builder->CreateTrunc(avg_v8i32, VectorType::get(s_ir_builder->getInt16Ty(), 8)); + sum_v8i32 = m_ir_builder->CreateAdd(sum_v8i32, ConstantDataVector::get(*m_llvm_context, one_v8i32)); + auto avg_v8i32 = m_ir_builder->CreateAShr(sum_v8i32, 1); + auto avg_v8i16 = m_ir_builder->CreateTrunc(avg_v8i32, VectorType::get(m_ir_builder->getInt16Ty(), 8)); SetVr(vd, avg_v8i16); } -void PPULLVMRecompiler::VAVGSW(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VAVGSW(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto va_v4i64 = s_ir_builder->CreateSExt(va_v4i32, VectorType::get(s_ir_builder->getInt64Ty(), 4)); - auto vb_v4i64 = s_ir_builder->CreateSExt(vb_v4i32, VectorType::get(s_ir_builder->getInt64Ty(), 4)); - auto sum_v4i64 = s_ir_builder->CreateAdd(va_v4i64, vb_v4i64); + auto va_v4i64 = m_ir_builder->CreateSExt(va_v4i32, VectorType::get(m_ir_builder->getInt64Ty(), 4)); + auto vb_v4i64 = m_ir_builder->CreateSExt(vb_v4i32, VectorType::get(m_ir_builder->getInt64Ty(), 4)); + auto sum_v4i64 = m_ir_builder->CreateAdd(va_v4i64, vb_v4i64); u64 one_v4i64[4] = {1, 1, 1, 1}; - sum_v4i64 = s_ir_builder->CreateAdd(sum_v4i64, ConstantDataVector::get(*s_llvm_context, one_v4i64)); - auto avg_v4i64 = s_ir_builder->CreateAShr(sum_v4i64, 1); - auto avg_v4i32 = s_ir_builder->CreateTrunc(avg_v4i64, VectorType::get(s_ir_builder->getInt32Ty(), 4)); + sum_v4i64 = m_ir_builder->CreateAdd(sum_v4i64, ConstantDataVector::get(*m_llvm_context, one_v4i64)); + auto avg_v4i64 = m_ir_builder->CreateAShr(sum_v4i64, 1); + auto avg_v4i32 = m_ir_builder->CreateTrunc(avg_v4i64, VectorType::get(m_ir_builder->getInt32Ty(), 4)); SetVr(vd, avg_v4i32); } -void PPULLVMRecompiler::VAVGUB(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VAVGUB(u32 vd, u32 va, u32 vb) { auto va_v16i8 = GetVrAsIntVec(va, 8); auto vb_v16i8 = GetVrAsIntVec(vb, 8); - auto avg_v16i8 = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_sse2_pavg_b), va_v16i8, vb_v16i8); + auto avg_v16i8 = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_sse2_pavg_b), va_v16i8, vb_v16i8); SetVr(vd, avg_v16i8); } -void PPULLVMRecompiler::VAVGUH(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VAVGUH(u32 vd, u32 va, u32 vb) { auto va_v8i16 = GetVrAsIntVec(va, 16); auto vb_v8i16 = GetVrAsIntVec(vb, 16); - auto avg_v8i16 = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_sse2_pavg_w), va_v8i16, vb_v8i16); + auto avg_v8i16 = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_sse2_pavg_w), va_v8i16, vb_v8i16); SetVr(vd, avg_v8i16); } -void PPULLVMRecompiler::VAVGUW(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VAVGUW(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto va_v4i64 = s_ir_builder->CreateZExt(va_v4i32, VectorType::get(s_ir_builder->getInt64Ty(), 4)); - auto vb_v4i64 = s_ir_builder->CreateZExt(vb_v4i32, VectorType::get(s_ir_builder->getInt64Ty(), 4)); - auto sum_v4i64 = s_ir_builder->CreateAdd(va_v4i64, vb_v4i64); + auto va_v4i64 = m_ir_builder->CreateZExt(va_v4i32, VectorType::get(m_ir_builder->getInt64Ty(), 4)); + auto vb_v4i64 = m_ir_builder->CreateZExt(vb_v4i32, VectorType::get(m_ir_builder->getInt64Ty(), 4)); + auto sum_v4i64 = m_ir_builder->CreateAdd(va_v4i64, vb_v4i64); u64 one_v4i64[4] = {1, 1, 1, 1}; - sum_v4i64 = s_ir_builder->CreateAdd(sum_v4i64, ConstantDataVector::get(*s_llvm_context, one_v4i64)); - auto avg_v4i64 = s_ir_builder->CreateLShr(sum_v4i64, 1); - auto avg_v4i32 = s_ir_builder->CreateTrunc(avg_v4i64, VectorType::get(s_ir_builder->getInt32Ty(), 4)); + sum_v4i64 = m_ir_builder->CreateAdd(sum_v4i64, ConstantDataVector::get(*m_llvm_context, one_v4i64)); + auto avg_v4i64 = m_ir_builder->CreateLShr(sum_v4i64, 1); + auto avg_v4i32 = m_ir_builder->CreateTrunc(avg_v4i64, VectorType::get(m_ir_builder->getInt32Ty(), 4)); SetVr(vd, avg_v4i32); } -void PPULLVMRecompiler::VCFSX(u32 vd, u32 uimm5, u32 vb) { +void PPULLVMRecompilerWorker::VCFSX(u32 vd, u32 uimm5, u32 vb) { auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto res_v4f32 = s_ir_builder->CreateSIToFP(vb_v4i32, VectorType::get(s_ir_builder->getFloatTy(), 4)); + auto res_v4f32 = m_ir_builder->CreateSIToFP(vb_v4i32, VectorType::get(m_ir_builder->getFloatTy(), 4)); if (uimm5) { - float scale = (float)(1 << uimm5); + float scale = (float)((u64)1 << uimm5); float scale_v4f32[4] = {scale, scale, scale, scale}; - res_v4f32 = s_ir_builder->CreateFDiv(res_v4f32, ConstantDataVector::get(*s_llvm_context, scale_v4f32)); + res_v4f32 = m_ir_builder->CreateFDiv(res_v4f32, ConstantDataVector::get(*m_llvm_context, scale_v4f32)); } SetVr(vd, res_v4f32); } -void PPULLVMRecompiler::VCFUX(u32 vd, u32 uimm5, u32 vb) { +void PPULLVMRecompilerWorker::VCFUX(u32 vd, u32 uimm5, u32 vb) { auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto res_v4f32 = s_ir_builder->CreateUIToFP(vb_v4i32, VectorType::get(s_ir_builder->getFloatTy(), 4)); + auto res_v4f32 = m_ir_builder->CreateUIToFP(vb_v4i32, VectorType::get(m_ir_builder->getFloatTy(), 4)); if (uimm5) { - float scale = (float)(1 << uimm5); + float scale = (float)((u64)1 << uimm5); float scale_v4f32[4] = {scale, scale, scale, scale}; - res_v4f32 = s_ir_builder->CreateFDiv(res_v4f32, ConstantDataVector::get(*s_llvm_context, scale_v4f32)); + res_v4f32 = m_ir_builder->CreateFDiv(res_v4f32, ConstantDataVector::get(*m_llvm_context, scale_v4f32)); } SetVr(vd, res_v4f32); } -void PPULLVMRecompiler::VCMPBFP(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPBFP(u32 vd, u32 va, u32 vb) { auto va_v4f32 = GetVrAsFloatVec(va); auto vb_v4f32 = GetVrAsFloatVec(vb); - auto cmp_gt_v4i1 = s_ir_builder->CreateFCmpOGT(va_v4f32, vb_v4f32); - vb_v4f32 = s_ir_builder->CreateFNeg(vb_v4f32); - auto cmp_lt_v4i1 = s_ir_builder->CreateFCmpOLT(va_v4f32, vb_v4f32); - auto cmp_gt_v4i32 = s_ir_builder->CreateZExt(cmp_gt_v4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); - auto cmp_lt_v4i32 = s_ir_builder->CreateZExt(cmp_lt_v4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); - cmp_gt_v4i32 = s_ir_builder->CreateShl(cmp_gt_v4i32, 31); - cmp_lt_v4i32 = s_ir_builder->CreateShl(cmp_lt_v4i32, 30); - auto res_v4i32 = s_ir_builder->CreateOr(cmp_gt_v4i32, cmp_lt_v4i32); + auto cmp_gt_v4i1 = m_ir_builder->CreateFCmpOGT(va_v4f32, vb_v4f32); + vb_v4f32 = m_ir_builder->CreateFNeg(vb_v4f32); + auto cmp_lt_v4i1 = m_ir_builder->CreateFCmpOLT(va_v4f32, vb_v4f32); + auto cmp_gt_v4i32 = m_ir_builder->CreateZExt(cmp_gt_v4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); + auto cmp_lt_v4i32 = m_ir_builder->CreateZExt(cmp_lt_v4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); + cmp_gt_v4i32 = m_ir_builder->CreateShl(cmp_gt_v4i32, 31); + cmp_lt_v4i32 = m_ir_builder->CreateShl(cmp_lt_v4i32, 30); + auto res_v4i32 = m_ir_builder->CreateOr(cmp_gt_v4i32, cmp_lt_v4i32); SetVr(vd, res_v4i32); // TODO: Implement NJ mode } -void PPULLVMRecompiler::VCMPBFP_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPBFP_(u32 vd, u32 va, u32 vb) { VCMPBFP(vd, va, vb); auto vd_v16i8 = GetVrAsIntVec(vd, 8); u8 mask_v16i8[16] = {3, 7, 11, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - vd_v16i8 = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_ssse3_pshuf_b_128), vd_v16i8, ConstantDataVector::get(*s_llvm_context, mask_v16i8)); - auto vd_v4i32 = s_ir_builder->CreateBitCast(vd_v16i8, VectorType::get(s_ir_builder->getInt32Ty(), 4)); - auto vd_mask_i32 = s_ir_builder->CreateExtractElement(vd_v4i32, s_ir_builder->getInt32(0)); - auto cmp_i1 = s_ir_builder->CreateICmpEQ(vd_mask_i32, s_ir_builder->getInt32(0)); + vd_v16i8 = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_ssse3_pshuf_b_128), vd_v16i8, ConstantDataVector::get(*m_llvm_context, mask_v16i8)); + auto vd_v4i32 = m_ir_builder->CreateBitCast(vd_v16i8, VectorType::get(m_ir_builder->getInt32Ty(), 4)); + auto vd_mask_i32 = m_ir_builder->CreateExtractElement(vd_v4i32, m_ir_builder->getInt32(0)); + auto cmp_i1 = m_ir_builder->CreateICmpEQ(vd_mask_i32, m_ir_builder->getInt32(0)); SetCrField(6, nullptr, nullptr, cmp_i1, nullptr); } -void PPULLVMRecompiler::VCMPEQFP(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPEQFP(u32 vd, u32 va, u32 vb) { auto va_v4f32 = GetVrAsFloatVec(va); auto vb_v4f32 = GetVrAsFloatVec(vb); - auto cmp_v4i1 = s_ir_builder->CreateFCmpOEQ(va_v4f32, vb_v4f32); - auto cmp_v4i32 = s_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); + auto cmp_v4i1 = m_ir_builder->CreateFCmpOEQ(va_v4f32, vb_v4f32); + auto cmp_v4i32 = m_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); SetVr(vd, cmp_v4i32); } -void PPULLVMRecompiler::VCMPEQFP_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPEQFP_(u32 vd, u32 va, u32 vb) { VCMPEQFP(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPEQUB(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPEQUB(u32 vd, u32 va, u32 vb) { auto va_v16i8 = GetVrAsIntVec(va, 8); auto vb_v16i8 = GetVrAsIntVec(vb, 8); - auto cmp_v16i1 = s_ir_builder->CreateICmpEQ(va_v16i8, vb_v16i8); - auto cmp_v16i8 = s_ir_builder->CreateSExt(cmp_v16i1, VectorType::get(s_ir_builder->getInt8Ty(), 16)); + auto cmp_v16i1 = m_ir_builder->CreateICmpEQ(va_v16i8, vb_v16i8); + auto cmp_v16i8 = m_ir_builder->CreateSExt(cmp_v16i1, VectorType::get(m_ir_builder->getInt8Ty(), 16)); SetVr(vd, cmp_v16i8); } -void PPULLVMRecompiler::VCMPEQUB_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPEQUB_(u32 vd, u32 va, u32 vb) { VCMPEQUB(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPEQUH(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPEQUH(u32 vd, u32 va, u32 vb) { auto va_v8i16 = GetVrAsIntVec(va, 16); auto vb_v8i16 = GetVrAsIntVec(vb, 16); - auto cmp_v8i1 = s_ir_builder->CreateICmpEQ(va_v8i16, vb_v8i16); - auto cmp_v8i16 = s_ir_builder->CreateSExt(cmp_v8i1, VectorType::get(s_ir_builder->getInt16Ty(), 8)); + auto cmp_v8i1 = m_ir_builder->CreateICmpEQ(va_v8i16, vb_v8i16); + auto cmp_v8i16 = m_ir_builder->CreateSExt(cmp_v8i1, VectorType::get(m_ir_builder->getInt16Ty(), 8)); SetVr(vd, cmp_v8i16); } -void PPULLVMRecompiler::VCMPEQUH_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPEQUH_(u32 vd, u32 va, u32 vb) { VCMPEQUH(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPEQUW(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPEQUW(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto cmp_v4i1 = s_ir_builder->CreateICmpEQ(va_v4i32, vb_v4i32); - auto cmp_v4i32 = s_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); + auto cmp_v4i1 = m_ir_builder->CreateICmpEQ(va_v4i32, vb_v4i32); + auto cmp_v4i32 = m_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); SetVr(vd, cmp_v4i32); } -void PPULLVMRecompiler::VCMPEQUW_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPEQUW_(u32 vd, u32 va, u32 vb) { VCMPEQUW(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPGEFP(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGEFP(u32 vd, u32 va, u32 vb) { auto va_v4f32 = GetVrAsFloatVec(va); auto vb_v4f32 = GetVrAsFloatVec(vb); - auto cmp_v4i1 = s_ir_builder->CreateFCmpOGE(va_v4f32, vb_v4f32); - auto cmp_v4i32 = s_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); + auto cmp_v4i1 = m_ir_builder->CreateFCmpOGE(va_v4f32, vb_v4f32); + auto cmp_v4i32 = m_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); SetVr(vd, cmp_v4i32); } -void PPULLVMRecompiler::VCMPGEFP_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGEFP_(u32 vd, u32 va, u32 vb) { VCMPGEFP(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPGTFP(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTFP(u32 vd, u32 va, u32 vb) { auto va_v4f32 = GetVrAsFloatVec(va); auto vb_v4f32 = GetVrAsFloatVec(vb); - auto cmp_v4i1 = s_ir_builder->CreateFCmpOGT(va_v4f32, vb_v4f32); - auto cmp_v4i32 = s_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); + auto cmp_v4i1 = m_ir_builder->CreateFCmpOGT(va_v4f32, vb_v4f32); + auto cmp_v4i32 = m_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); SetVr(vd, cmp_v4i32); } -void PPULLVMRecompiler::VCMPGTFP_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTFP_(u32 vd, u32 va, u32 vb) { VCMPGTFP(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPGTSB(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTSB(u32 vd, u32 va, u32 vb) { auto va_v16i8 = GetVrAsIntVec(va, 8); auto vb_v16i8 = GetVrAsIntVec(vb, 8); - auto cmp_v16i1 = s_ir_builder->CreateICmpSGT(va_v16i8, vb_v16i8); - auto cmp_v16i8 = s_ir_builder->CreateSExt(cmp_v16i1, VectorType::get(s_ir_builder->getInt8Ty(), 16)); + auto cmp_v16i1 = m_ir_builder->CreateICmpSGT(va_v16i8, vb_v16i8); + auto cmp_v16i8 = m_ir_builder->CreateSExt(cmp_v16i1, VectorType::get(m_ir_builder->getInt8Ty(), 16)); SetVr(vd, cmp_v16i8); } -void PPULLVMRecompiler::VCMPGTSB_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTSB_(u32 vd, u32 va, u32 vb) { VCMPGTSB(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPGTSH(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTSH(u32 vd, u32 va, u32 vb) { auto va_v8i16 = GetVrAsIntVec(va, 16); auto vb_v8i16 = GetVrAsIntVec(vb, 16); - auto cmp_v8i1 = s_ir_builder->CreateICmpSGT(va_v8i16, vb_v8i16); - auto cmp_v8i16 = s_ir_builder->CreateSExt(cmp_v8i1, VectorType::get(s_ir_builder->getInt16Ty(), 8)); + auto cmp_v8i1 = m_ir_builder->CreateICmpSGT(va_v8i16, vb_v8i16); + auto cmp_v8i16 = m_ir_builder->CreateSExt(cmp_v8i1, VectorType::get(m_ir_builder->getInt16Ty(), 8)); SetVr(vd, cmp_v8i16); } -void PPULLVMRecompiler::VCMPGTSH_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTSH_(u32 vd, u32 va, u32 vb) { VCMPGTSH(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPGTSW(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTSW(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto cmp_v4i1 = s_ir_builder->CreateICmpSGT(va_v4i32, vb_v4i32); - auto cmp_v4i32 = s_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); + auto cmp_v4i1 = m_ir_builder->CreateICmpSGT(va_v4i32, vb_v4i32); + auto cmp_v4i32 = m_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); SetVr(vd, cmp_v4i32); } -void PPULLVMRecompiler::VCMPGTSW_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTSW_(u32 vd, u32 va, u32 vb) { VCMPGTSW(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPGTUB(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTUB(u32 vd, u32 va, u32 vb) { auto va_v16i8 = GetVrAsIntVec(va, 8); auto vb_v16i8 = GetVrAsIntVec(vb, 8); - auto cmp_v16i1 = s_ir_builder->CreateICmpUGT(va_v16i8, vb_v16i8); - auto cmp_v16i8 = s_ir_builder->CreateSExt(cmp_v16i1, VectorType::get(s_ir_builder->getInt8Ty(), 16)); + auto cmp_v16i1 = m_ir_builder->CreateICmpUGT(va_v16i8, vb_v16i8); + auto cmp_v16i8 = m_ir_builder->CreateSExt(cmp_v16i1, VectorType::get(m_ir_builder->getInt8Ty(), 16)); SetVr(vd, cmp_v16i8); } -void PPULLVMRecompiler::VCMPGTUB_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTUB_(u32 vd, u32 va, u32 vb) { VCMPGTUB(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPGTUH(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTUH(u32 vd, u32 va, u32 vb) { auto va_v8i16 = GetVrAsIntVec(va, 16); auto vb_v8i16 = GetVrAsIntVec(vb, 16); - auto cmp_v8i1 = s_ir_builder->CreateICmpUGT(va_v8i16, vb_v8i16); - auto cmp_v8i16 = s_ir_builder->CreateSExt(cmp_v8i1, VectorType::get(s_ir_builder->getInt16Ty(), 8)); + auto cmp_v8i1 = m_ir_builder->CreateICmpUGT(va_v8i16, vb_v8i16); + auto cmp_v8i16 = m_ir_builder->CreateSExt(cmp_v8i1, VectorType::get(m_ir_builder->getInt16Ty(), 8)); SetVr(vd, cmp_v8i16); } -void PPULLVMRecompiler::VCMPGTUH_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTUH_(u32 vd, u32 va, u32 vb) { VCMPGTUH(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCMPGTUW(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTUW(u32 vd, u32 va, u32 vb) { auto va_v4i32 = GetVrAsIntVec(va, 32); auto vb_v4i32 = GetVrAsIntVec(vb, 32); - auto cmp_v4i1 = s_ir_builder->CreateICmpUGT(va_v4i32, vb_v4i32); - auto cmp_v4i32 = s_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(s_ir_builder->getInt32Ty(), 4)); + auto cmp_v4i1 = m_ir_builder->CreateICmpUGT(va_v4i32, vb_v4i32); + auto cmp_v4i32 = m_ir_builder->CreateSExt(cmp_v4i1, VectorType::get(m_ir_builder->getInt32Ty(), 4)); SetVr(vd, cmp_v4i32); } -void PPULLVMRecompiler::VCMPGTUW_(u32 vd, u32 va, u32 vb) { +void PPULLVMRecompilerWorker::VCMPGTUW_(u32 vd, u32 va, u32 vb) { VCMPGTUW(vd, va, vb); SetCr6AfterVectorCompare(vd); } -void PPULLVMRecompiler::VCTSXS(u32 vd, u32 uimm5, u32 vb) { - ThisCall("VCTSXS", &PPUInterpreter::VCTSXS, &m_interpreter, vd, uimm5, vb); +void PPULLVMRecompilerWorker::VCTSXS(u32 vd, u32 uimm5, u32 vb) { + InterpreterCall("VCTSXS", &PPUInterpreter::VCTSXS, vd, uimm5, vb); } -void PPULLVMRecompiler::VCTUXS(u32 vd, u32 uimm5, u32 vb) { - ThisCall("VCTUXS", &PPUInterpreter::VCTUXS, &m_interpreter, vd, uimm5, vb); +void PPULLVMRecompilerWorker::VCTUXS(u32 vd, u32 uimm5, u32 vb) { + InterpreterCall("VCTUXS", &PPUInterpreter::VCTUXS, vd, uimm5, vb); } -void PPULLVMRecompiler::VEXPTEFP(u32 vd, u32 vb) { - ThisCall("VEXPTEFP", &PPUInterpreter::VEXPTEFP, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VEXPTEFP(u32 vd, u32 vb) { + InterpreterCall("VEXPTEFP", &PPUInterpreter::VEXPTEFP, vd, vb); } -void PPULLVMRecompiler::VLOGEFP(u32 vd, u32 vb) { - ThisCall("VLOGEFP", &PPUInterpreter::VLOGEFP, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VLOGEFP(u32 vd, u32 vb) { + InterpreterCall("VLOGEFP", &PPUInterpreter::VLOGEFP, vd, vb); } -void PPULLVMRecompiler::VMADDFP(u32 vd, u32 va, u32 vc, u32 vb) { - ThisCall("VMADDFP", &PPUInterpreter::VMADDFP, &m_interpreter, vd, va, vc, vb); +void PPULLVMRecompilerWorker::VMADDFP(u32 vd, u32 va, u32 vc, u32 vb) { + InterpreterCall("VMADDFP", &PPUInterpreter::VMADDFP, vd, va, vc, vb); } -void PPULLVMRecompiler::VMAXFP(u32 vd, u32 va, u32 vb) { - ThisCall("VMAXFP", &PPUInterpreter::VMAXFP, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMAXFP(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMAXFP", &PPUInterpreter::VMAXFP, vd, va, vb); } -void PPULLVMRecompiler::VMAXSB(u32 vd, u32 va, u32 vb) { - ThisCall("VMAXSB", &PPUInterpreter::VMAXSB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMAXSB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMAXSB", &PPUInterpreter::VMAXSB, vd, va, vb); } -void PPULLVMRecompiler::VMAXSH(u32 vd, u32 va, u32 vb) { - ThisCall("VMAXSH", &PPUInterpreter::VMAXSH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMAXSH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMAXSH", &PPUInterpreter::VMAXSH, vd, va, vb); } -void PPULLVMRecompiler::VMAXSW(u32 vd, u32 va, u32 vb) { - ThisCall("VMAXSW", &PPUInterpreter::VMAXSW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMAXSW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMAXSW", &PPUInterpreter::VMAXSW, vd, va, vb); } -void PPULLVMRecompiler::VMAXUB(u32 vd, u32 va, u32 vb) { - ThisCall("VMAXUB", &PPUInterpreter::VMAXUB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMAXUB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMAXUB", &PPUInterpreter::VMAXUB, vd, va, vb); } -void PPULLVMRecompiler::VMAXUH(u32 vd, u32 va, u32 vb) { - ThisCall("VMAXUH", &PPUInterpreter::VMAXUH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMAXUH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMAXUH", &PPUInterpreter::VMAXUH, vd, va, vb); } -void PPULLVMRecompiler::VMAXUW(u32 vd, u32 va, u32 vb) { - ThisCall("VMAXUW", &PPUInterpreter::VMAXUW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMAXUW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMAXUW", &PPUInterpreter::VMAXUW, vd, va, vb); } -void PPULLVMRecompiler::VMHADDSHS(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VMHADDSHS", &PPUInterpreter::VMHADDSHS, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VMHADDSHS(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VMHADDSHS", &PPUInterpreter::VMHADDSHS, vd, va, vb, vc); } -void PPULLVMRecompiler::VMHRADDSHS(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VMHRADDSHS", &PPUInterpreter::VMHRADDSHS, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VMHRADDSHS(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VMHRADDSHS", &PPUInterpreter::VMHRADDSHS, vd, va, vb, vc); } -void PPULLVMRecompiler::VMINFP(u32 vd, u32 va, u32 vb) { - ThisCall("VMINFP", &PPUInterpreter::VMINFP, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMINFP(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMINFP", &PPUInterpreter::VMINFP, vd, va, vb); } -void PPULLVMRecompiler::VMINSB(u32 vd, u32 va, u32 vb) { - ThisCall("VMINSB", &PPUInterpreter::VMINSB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMINSB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMINSB", &PPUInterpreter::VMINSB, vd, va, vb); } -void PPULLVMRecompiler::VMINSH(u32 vd, u32 va, u32 vb) { - ThisCall("VMINSH", &PPUInterpreter::VMINSH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMINSH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMINSH", &PPUInterpreter::VMINSH, vd, va, vb); } -void PPULLVMRecompiler::VMINSW(u32 vd, u32 va, u32 vb) { - ThisCall("VMINSW", &PPUInterpreter::VMINSW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMINSW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMINSW", &PPUInterpreter::VMINSW, vd, va, vb); } -void PPULLVMRecompiler::VMINUB(u32 vd, u32 va, u32 vb) { - ThisCall("VMINUB", &PPUInterpreter::VMINUB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMINUB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMINUB", &PPUInterpreter::VMINUB, vd, va, vb); } -void PPULLVMRecompiler::VMINUH(u32 vd, u32 va, u32 vb) { - ThisCall("VMINUH", &PPUInterpreter::VMINUH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMINUH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMINUH", &PPUInterpreter::VMINUH, vd, va, vb); } -void PPULLVMRecompiler::VMINUW(u32 vd, u32 va, u32 vb) { - ThisCall("VMINUW", &PPUInterpreter::VMINUW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMINUW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMINUW", &PPUInterpreter::VMINUW, vd, va, vb); } -void PPULLVMRecompiler::VMLADDUHM(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VMLADDUHM", &PPUInterpreter::VMLADDUHM, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VMLADDUHM(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VMLADDUHM", &PPUInterpreter::VMLADDUHM, vd, va, vb, vc); } -void PPULLVMRecompiler::VMRGHB(u32 vd, u32 va, u32 vb) { - ThisCall("VMRGHB", &PPUInterpreter::VMRGHB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMRGHB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMRGHB", &PPUInterpreter::VMRGHB, vd, va, vb); } -void PPULLVMRecompiler::VMRGHH(u32 vd, u32 va, u32 vb) { - ThisCall("VMRGHH", &PPUInterpreter::VMRGHH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMRGHH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMRGHH", &PPUInterpreter::VMRGHH, vd, va, vb); } -void PPULLVMRecompiler::VMRGHW(u32 vd, u32 va, u32 vb) { - ThisCall("VMRGHW", &PPUInterpreter::VMRGHW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMRGHW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMRGHW", &PPUInterpreter::VMRGHW, vd, va, vb); } -void PPULLVMRecompiler::VMRGLB(u32 vd, u32 va, u32 vb) { - ThisCall("VMRGLB", &PPUInterpreter::VMRGLB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMRGLB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMRGLB", &PPUInterpreter::VMRGLB, vd, va, vb); } -void PPULLVMRecompiler::VMRGLH(u32 vd, u32 va, u32 vb) { - ThisCall("VMRGLH", &PPUInterpreter::VMRGLH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMRGLH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMRGLH", &PPUInterpreter::VMRGLH, vd, va, vb); } -void PPULLVMRecompiler::VMRGLW(u32 vd, u32 va, u32 vb) { - ThisCall("VMRGLW", &PPUInterpreter::VMRGLW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMRGLW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMRGLW", &PPUInterpreter::VMRGLW, vd, va, vb); } -void PPULLVMRecompiler::VMSUMMBM(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VMSUMMBM", &PPUInterpreter::VMSUMMBM, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VMSUMMBM(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VMSUMMBM", &PPUInterpreter::VMSUMMBM, vd, va, vb, vc); } -void PPULLVMRecompiler::VMSUMSHM(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VMSUMSHM", &PPUInterpreter::VMSUMSHM, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VMSUMSHM(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VMSUMSHM", &PPUInterpreter::VMSUMSHM, vd, va, vb, vc); } -void PPULLVMRecompiler::VMSUMSHS(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VMSUMSHS", &PPUInterpreter::VMSUMSHS, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VMSUMSHS(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VMSUMSHS", &PPUInterpreter::VMSUMSHS, vd, va, vb, vc); } -void PPULLVMRecompiler::VMSUMUBM(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VMSUMUBM", &PPUInterpreter::VMSUMUBM, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VMSUMUBM(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VMSUMUBM", &PPUInterpreter::VMSUMUBM, vd, va, vb, vc); } -void PPULLVMRecompiler::VMSUMUHM(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VMSUMUHM", &PPUInterpreter::VMSUMUHM, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VMSUMUHM(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VMSUMUHM", &PPUInterpreter::VMSUMUHM, vd, va, vb, vc); } -void PPULLVMRecompiler::VMSUMUHS(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VMSUMUHS", &PPUInterpreter::VMSUMUHS, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VMSUMUHS(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VMSUMUHS", &PPUInterpreter::VMSUMUHS, vd, va, vb, vc); } -void PPULLVMRecompiler::VMULESB(u32 vd, u32 va, u32 vb) { - ThisCall("VMULESB", &PPUInterpreter::VMULESB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMULESB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMULESB", &PPUInterpreter::VMULESB, vd, va, vb); } -void PPULLVMRecompiler::VMULESH(u32 vd, u32 va, u32 vb) { - ThisCall("VMULESH", &PPUInterpreter::VMULESH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMULESH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMULESH", &PPUInterpreter::VMULESH, vd, va, vb); } -void PPULLVMRecompiler::VMULEUB(u32 vd, u32 va, u32 vb) { - ThisCall("VMULEUB", &PPUInterpreter::VMULEUB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMULEUB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMULEUB", &PPUInterpreter::VMULEUB, vd, va, vb); } -void PPULLVMRecompiler::VMULEUH(u32 vd, u32 va, u32 vb) { - ThisCall("VMULEUH", &PPUInterpreter::VMULEUH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMULEUH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMULEUH", &PPUInterpreter::VMULEUH, vd, va, vb); } -void PPULLVMRecompiler::VMULOSB(u32 vd, u32 va, u32 vb) { - ThisCall("VMULOSB", &PPUInterpreter::VMULOSB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMULOSB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMULOSB", &PPUInterpreter::VMULOSB, vd, va, vb); } -void PPULLVMRecompiler::VMULOSH(u32 vd, u32 va, u32 vb) { - ThisCall("VMULOSH", &PPUInterpreter::VMULOSH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMULOSH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMULOSH", &PPUInterpreter::VMULOSH, vd, va, vb); } -void PPULLVMRecompiler::VMULOUB(u32 vd, u32 va, u32 vb) { - ThisCall("VMULOUB", &PPUInterpreter::VMULOUB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMULOUB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMULOUB", &PPUInterpreter::VMULOUB, vd, va, vb); } -void PPULLVMRecompiler::VMULOUH(u32 vd, u32 va, u32 vb) { - ThisCall("VMULOUH", &PPUInterpreter::VMULOUH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VMULOUH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VMULOUH", &PPUInterpreter::VMULOUH, vd, va, vb); } -void PPULLVMRecompiler::VNMSUBFP(u32 vd, u32 va, u32 vc, u32 vb) { - ThisCall("VNMSUBFP", &PPUInterpreter::VNMSUBFP, &m_interpreter, vd, va, vc, vb); +void PPULLVMRecompilerWorker::VNMSUBFP(u32 vd, u32 va, u32 vc, u32 vb) { + InterpreterCall("VNMSUBFP", &PPUInterpreter::VNMSUBFP, vd, va, vc, vb); } -void PPULLVMRecompiler::VNOR(u32 vd, u32 va, u32 vb) { - ThisCall("VNOR", &PPUInterpreter::VNOR, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VNOR(u32 vd, u32 va, u32 vb) { + InterpreterCall("VNOR", &PPUInterpreter::VNOR, vd, va, vb); } -void PPULLVMRecompiler::VOR(u32 vd, u32 va, u32 vb) { - ThisCall("VOR", &PPUInterpreter::VOR, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VOR(u32 vd, u32 va, u32 vb) { + InterpreterCall("VOR", &PPUInterpreter::VOR, vd, va, vb); } -void PPULLVMRecompiler::VPERM(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VPERM", &PPUInterpreter::VPERM, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VPERM(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VPERM", &PPUInterpreter::VPERM, vd, va, vb, vc); } -void PPULLVMRecompiler::VPKPX(u32 vd, u32 va, u32 vb) { - ThisCall("VPKPX", &PPUInterpreter::VPKPX, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VPKPX(u32 vd, u32 va, u32 vb) { + InterpreterCall("VPKPX", &PPUInterpreter::VPKPX, vd, va, vb); } -void PPULLVMRecompiler::VPKSHSS(u32 vd, u32 va, u32 vb) { - ThisCall("VPKSHSS", &PPUInterpreter::VPKSHSS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VPKSHSS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VPKSHSS", &PPUInterpreter::VPKSHSS, vd, va, vb); } -void PPULLVMRecompiler::VPKSHUS(u32 vd, u32 va, u32 vb) { - ThisCall("VPKSHUS", &PPUInterpreter::VPKSHUS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VPKSHUS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VPKSHUS", &PPUInterpreter::VPKSHUS, vd, va, vb); } -void PPULLVMRecompiler::VPKSWSS(u32 vd, u32 va, u32 vb) { - ThisCall("VPKSWSS", &PPUInterpreter::VPKSWSS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VPKSWSS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VPKSWSS", &PPUInterpreter::VPKSWSS, vd, va, vb); } -void PPULLVMRecompiler::VPKSWUS(u32 vd, u32 va, u32 vb) { - ThisCall("VPKSWUS", &PPUInterpreter::VPKSWUS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VPKSWUS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VPKSWUS", &PPUInterpreter::VPKSWUS, vd, va, vb); } -void PPULLVMRecompiler::VPKUHUM(u32 vd, u32 va, u32 vb) { - ThisCall("VPKUHUM", &PPUInterpreter::VPKUHUM, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VPKUHUM(u32 vd, u32 va, u32 vb) { + InterpreterCall("VPKUHUM", &PPUInterpreter::VPKUHUM, vd, va, vb); } -void PPULLVMRecompiler::VPKUHUS(u32 vd, u32 va, u32 vb) { - ThisCall("VPKUHUS", &PPUInterpreter::VPKUHUS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VPKUHUS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VPKUHUS", &PPUInterpreter::VPKUHUS, vd, va, vb); } -void PPULLVMRecompiler::VPKUWUM(u32 vd, u32 va, u32 vb) { - ThisCall("VPKUWUM", &PPUInterpreter::VPKUWUM, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VPKUWUM(u32 vd, u32 va, u32 vb) { + InterpreterCall("VPKUWUM", &PPUInterpreter::VPKUWUM, vd, va, vb); } -void PPULLVMRecompiler::VPKUWUS(u32 vd, u32 va, u32 vb) { - ThisCall("VPKUWUS", &PPUInterpreter::VPKUWUS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VPKUWUS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VPKUWUS", &PPUInterpreter::VPKUWUS, vd, va, vb); } -void PPULLVMRecompiler::VREFP(u32 vd, u32 vb) { - ThisCall("VREFP", &PPUInterpreter::VREFP, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VREFP(u32 vd, u32 vb) { + InterpreterCall("VREFP", &PPUInterpreter::VREFP, vd, vb); } -void PPULLVMRecompiler::VRFIM(u32 vd, u32 vb) { - ThisCall("VRFIM", &PPUInterpreter::VRFIM, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VRFIM(u32 vd, u32 vb) { + InterpreterCall("VRFIM", &PPUInterpreter::VRFIM, vd, vb); } -void PPULLVMRecompiler::VRFIN(u32 vd, u32 vb) { - ThisCall("VRFIN", &PPUInterpreter::VRFIN, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VRFIN(u32 vd, u32 vb) { + InterpreterCall("VRFIN", &PPUInterpreter::VRFIN, vd, vb); } -void PPULLVMRecompiler::VRFIP(u32 vd, u32 vb) { - ThisCall("VRFIP", &PPUInterpreter::VRFIP, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VRFIP(u32 vd, u32 vb) { + InterpreterCall("VRFIP", &PPUInterpreter::VRFIP, vd, vb); } -void PPULLVMRecompiler::VRFIZ(u32 vd, u32 vb) { - ThisCall("VRFIZ", &PPUInterpreter::VRFIZ, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VRFIZ(u32 vd, u32 vb) { + InterpreterCall("VRFIZ", &PPUInterpreter::VRFIZ, vd, vb); } -void PPULLVMRecompiler::VRLB(u32 vd, u32 va, u32 vb) { - ThisCall("VRLB", &PPUInterpreter::VRLB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VRLB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VRLB", &PPUInterpreter::VRLB, vd, va, vb); } -void PPULLVMRecompiler::VRLH(u32 vd, u32 va, u32 vb) { - ThisCall("VRLH", &PPUInterpreter::VRLH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VRLH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VRLH", &PPUInterpreter::VRLH, vd, va, vb); } -void PPULLVMRecompiler::VRLW(u32 vd, u32 va, u32 vb) { - ThisCall("VRLW", &PPUInterpreter::VRLW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VRLW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VRLW", &PPUInterpreter::VRLW, vd, va, vb); } -void PPULLVMRecompiler::VRSQRTEFP(u32 vd, u32 vb) { - ThisCall("VRSQRTEFP", &PPUInterpreter::VRSQRTEFP, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VRSQRTEFP(u32 vd, u32 vb) { + InterpreterCall("VRSQRTEFP", &PPUInterpreter::VRSQRTEFP, vd, vb); } -void PPULLVMRecompiler::VSEL(u32 vd, u32 va, u32 vb, u32 vc) { - ThisCall("VSEL", &PPUInterpreter::VSEL, &m_interpreter, vd, va, vb, vc); +void PPULLVMRecompilerWorker::VSEL(u32 vd, u32 va, u32 vb, u32 vc) { + InterpreterCall("VSEL", &PPUInterpreter::VSEL, vd, va, vb, vc); } -void PPULLVMRecompiler::VSL(u32 vd, u32 va, u32 vb) { - ThisCall("VSL", &PPUInterpreter::VSL, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSL(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSL", &PPUInterpreter::VSL, vd, va, vb); } -void PPULLVMRecompiler::VSLB(u32 vd, u32 va, u32 vb) { - ThisCall("VSLB", &PPUInterpreter::VSLB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSLB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSLB", &PPUInterpreter::VSLB, vd, va, vb); } -void PPULLVMRecompiler::VSLDOI(u32 vd, u32 va, u32 vb, u32 sh) { - ThisCall("VSLDOI", &PPUInterpreter::VSLDOI, &m_interpreter, vd, va, vb, sh); +void PPULLVMRecompilerWorker::VSLDOI(u32 vd, u32 va, u32 vb, u32 sh) { + InterpreterCall("VSLDOI", &PPUInterpreter::VSLDOI, vd, va, vb, sh); } -void PPULLVMRecompiler::VSLH(u32 vd, u32 va, u32 vb) { - ThisCall("VSLH", &PPUInterpreter::VSLH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSLH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSLH", &PPUInterpreter::VSLH, vd, va, vb); } -void PPULLVMRecompiler::VSLO(u32 vd, u32 va, u32 vb) { - ThisCall("VSLO", &PPUInterpreter::VSLO, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSLO(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSLO", &PPUInterpreter::VSLO, vd, va, vb); } -void PPULLVMRecompiler::VSLW(u32 vd, u32 va, u32 vb) { - ThisCall("VSLW", &PPUInterpreter::VSLW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSLW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSLW", &PPUInterpreter::VSLW, vd, va, vb); } -void PPULLVMRecompiler::VSPLTB(u32 vd, u32 uimm5, u32 vb) { - ThisCall("VSPLTB", &PPUInterpreter::VSPLTB, &m_interpreter, vd, uimm5, vb); +void PPULLVMRecompilerWorker::VSPLTB(u32 vd, u32 uimm5, u32 vb) { + InterpreterCall("VSPLTB", &PPUInterpreter::VSPLTB, vd, uimm5, vb); } -void PPULLVMRecompiler::VSPLTH(u32 vd, u32 uimm5, u32 vb) { - ThisCall("VSPLTH", &PPUInterpreter::VSPLTH, &m_interpreter, vd, uimm5, vb); +void PPULLVMRecompilerWorker::VSPLTH(u32 vd, u32 uimm5, u32 vb) { + InterpreterCall("VSPLTH", &PPUInterpreter::VSPLTH, vd, uimm5, vb); } -void PPULLVMRecompiler::VSPLTISB(u32 vd, s32 simm5) { - ThisCall("VSPLTISB", &PPUInterpreter::VSPLTISB, &m_interpreter, vd, simm5); +void PPULLVMRecompilerWorker::VSPLTISB(u32 vd, s32 simm5) { + InterpreterCall("VSPLTISB", &PPUInterpreter::VSPLTISB, vd, simm5); } -void PPULLVMRecompiler::VSPLTISH(u32 vd, s32 simm5) { - ThisCall("VSPLTISH", &PPUInterpreter::VSPLTISH, &m_interpreter, vd, simm5); +void PPULLVMRecompilerWorker::VSPLTISH(u32 vd, s32 simm5) { + InterpreterCall("VSPLTISH", &PPUInterpreter::VSPLTISH, vd, simm5); } -void PPULLVMRecompiler::VSPLTISW(u32 vd, s32 simm5) { - ThisCall("VSPLTISW", &PPUInterpreter::VSPLTISW, &m_interpreter, vd, simm5); +void PPULLVMRecompilerWorker::VSPLTISW(u32 vd, s32 simm5) { + InterpreterCall("VSPLTISW", &PPUInterpreter::VSPLTISW, vd, simm5); } -void PPULLVMRecompiler::VSPLTW(u32 vd, u32 uimm5, u32 vb) { - ThisCall("VSPLTW", &PPUInterpreter::VSPLTW, &m_interpreter, vd, uimm5, vb); +void PPULLVMRecompilerWorker::VSPLTW(u32 vd, u32 uimm5, u32 vb) { + InterpreterCall("VSPLTW", &PPUInterpreter::VSPLTW, vd, uimm5, vb); } -void PPULLVMRecompiler::VSR(u32 vd, u32 va, u32 vb) { - ThisCall("VSR", &PPUInterpreter::VSR, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSR(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSR", &PPUInterpreter::VSR, vd, va, vb); } -void PPULLVMRecompiler::VSRAB(u32 vd, u32 va, u32 vb) { - ThisCall("VSRAB", &PPUInterpreter::VSRAB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSRAB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSRAB", &PPUInterpreter::VSRAB, vd, va, vb); } -void PPULLVMRecompiler::VSRAH(u32 vd, u32 va, u32 vb) { - ThisCall("VSRAH", &PPUInterpreter::VSRAH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSRAH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSRAH", &PPUInterpreter::VSRAH, vd, va, vb); } -void PPULLVMRecompiler::VSRAW(u32 vd, u32 va, u32 vb) { - ThisCall("VSRAW", &PPUInterpreter::VSRAW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSRAW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSRAW", &PPUInterpreter::VSRAW, vd, va, vb); } -void PPULLVMRecompiler::VSRB(u32 vd, u32 va, u32 vb) { - ThisCall("VSRB", &PPUInterpreter::VSRB, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSRB(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSRB", &PPUInterpreter::VSRB, vd, va, vb); } -void PPULLVMRecompiler::VSRH(u32 vd, u32 va, u32 vb) { - ThisCall("VSRH", &PPUInterpreter::VSRH, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSRH(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSRH", &PPUInterpreter::VSRH, vd, va, vb); } -void PPULLVMRecompiler::VSRO(u32 vd, u32 va, u32 vb) { - ThisCall("VSRO", &PPUInterpreter::VSRO, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSRO(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSRO", &PPUInterpreter::VSRO, vd, va, vb); } -void PPULLVMRecompiler::VSRW(u32 vd, u32 va, u32 vb) { - ThisCall("VSRW", &PPUInterpreter::VSRW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSRW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSRW", &PPUInterpreter::VSRW, vd, va, vb); } -void PPULLVMRecompiler::VSUBCUW(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBCUW", &PPUInterpreter::VSUBCUW, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBCUW(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBCUW", &PPUInterpreter::VSUBCUW, vd, va, vb); } -void PPULLVMRecompiler::VSUBFP(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBFP", &PPUInterpreter::VSUBFP, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBFP(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBFP", &PPUInterpreter::VSUBFP, vd, va, vb); } -void PPULLVMRecompiler::VSUBSBS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBSBS", &PPUInterpreter::VSUBSBS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBSBS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBSBS", &PPUInterpreter::VSUBSBS, vd, va, vb); } -void PPULLVMRecompiler::VSUBSHS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBSHS", &PPUInterpreter::VSUBSHS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBSHS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBSHS", &PPUInterpreter::VSUBSHS, vd, va, vb); } -void PPULLVMRecompiler::VSUBSWS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBSWS", &PPUInterpreter::VSUBSWS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBSWS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBSWS", &PPUInterpreter::VSUBSWS, vd, va, vb); } -void PPULLVMRecompiler::VSUBUBM(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBUBM", &PPUInterpreter::VSUBUBM, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBUBM(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBUBM", &PPUInterpreter::VSUBUBM, vd, va, vb); } -void PPULLVMRecompiler::VSUBUBS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBUBS", &PPUInterpreter::VSUBUBS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBUBS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBUBS", &PPUInterpreter::VSUBUBS, vd, va, vb); } -void PPULLVMRecompiler::VSUBUHM(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBUHM", &PPUInterpreter::VSUBUHM, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBUHM(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBUHM", &PPUInterpreter::VSUBUHM, vd, va, vb); } -void PPULLVMRecompiler::VSUBUHS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBUHS", &PPUInterpreter::VSUBUHS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBUHS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBUHS", &PPUInterpreter::VSUBUHS, vd, va, vb); } -void PPULLVMRecompiler::VSUBUWM(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBUWM", &PPUInterpreter::VSUBUWM, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBUWM(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBUWM", &PPUInterpreter::VSUBUWM, vd, va, vb); } -void PPULLVMRecompiler::VSUBUWS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUBUWS", &PPUInterpreter::VSUBUWS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUBUWS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUBUWS", &PPUInterpreter::VSUBUWS, vd, va, vb); } -void PPULLVMRecompiler::VSUMSWS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUMSWS", &PPUInterpreter::VSUMSWS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUMSWS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUMSWS", &PPUInterpreter::VSUMSWS, vd, va, vb); } -void PPULLVMRecompiler::VSUM2SWS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUM2SWS", &PPUInterpreter::VSUM2SWS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUM2SWS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUM2SWS", &PPUInterpreter::VSUM2SWS, vd, va, vb); } -void PPULLVMRecompiler::VSUM4SBS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUM4SBS", &PPUInterpreter::VSUM4SBS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUM4SBS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUM4SBS", &PPUInterpreter::VSUM4SBS, vd, va, vb); } -void PPULLVMRecompiler::VSUM4SHS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUM4SHS", &PPUInterpreter::VSUM4SHS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUM4SHS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUM4SHS", &PPUInterpreter::VSUM4SHS, vd, va, vb); } -void PPULLVMRecompiler::VSUM4UBS(u32 vd, u32 va, u32 vb) { - ThisCall("VSUM4UBS", &PPUInterpreter::VSUM4UBS, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VSUM4UBS(u32 vd, u32 va, u32 vb) { + InterpreterCall("VSUM4UBS", &PPUInterpreter::VSUM4UBS, vd, va, vb); } -void PPULLVMRecompiler::VUPKHPX(u32 vd, u32 vb) { - ThisCall("VUPKHPX", &PPUInterpreter::VUPKHPX, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VUPKHPX(u32 vd, u32 vb) { + InterpreterCall("VUPKHPX", &PPUInterpreter::VUPKHPX, vd, vb); } -void PPULLVMRecompiler::VUPKHSB(u32 vd, u32 vb) { - ThisCall("VUPKHSB", &PPUInterpreter::VUPKHSB, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VUPKHSB(u32 vd, u32 vb) { + InterpreterCall("VUPKHSB", &PPUInterpreter::VUPKHSB, vd, vb); } -void PPULLVMRecompiler::VUPKHSH(u32 vd, u32 vb) { - ThisCall("VUPKHSH", &PPUInterpreter::VUPKHSH, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VUPKHSH(u32 vd, u32 vb) { + InterpreterCall("VUPKHSH", &PPUInterpreter::VUPKHSH, vd, vb); } -void PPULLVMRecompiler::VUPKLPX(u32 vd, u32 vb) { - ThisCall("VUPKLPX", &PPUInterpreter::VUPKLPX, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VUPKLPX(u32 vd, u32 vb) { + InterpreterCall("VUPKLPX", &PPUInterpreter::VUPKLPX, vd, vb); } -void PPULLVMRecompiler::VUPKLSB(u32 vd, u32 vb) { - ThisCall("VUPKLSB", &PPUInterpreter::VUPKLSB, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VUPKLSB(u32 vd, u32 vb) { + InterpreterCall("VUPKLSB", &PPUInterpreter::VUPKLSB, vd, vb); } -void PPULLVMRecompiler::VUPKLSH(u32 vd, u32 vb) { - ThisCall("VUPKLSH", &PPUInterpreter::VUPKLSH, &m_interpreter, vd, vb); +void PPULLVMRecompilerWorker::VUPKLSH(u32 vd, u32 vb) { + InterpreterCall("VUPKLSH", &PPUInterpreter::VUPKLSH, vd, vb); } -void PPULLVMRecompiler::VXOR(u32 vd, u32 va, u32 vb) { - ThisCall("VXOR", &PPUInterpreter::VXOR, &m_interpreter, vd, va, vb); +void PPULLVMRecompilerWorker::VXOR(u32 vd, u32 va, u32 vb) { + InterpreterCall("VXOR", &PPUInterpreter::VXOR, vd, va, vb); } -void PPULLVMRecompiler::MULLI(u32 rd, u32 ra, s32 simm16) { - //auto ra_i64 = GetGpr(ra); - //auto res_i64 = s_ir_builder->CreateMul(ra_i64, s_ir_builder->getInt64((s64)simm16)); - //SetGpr(rd, res_i64); - ThisCall("MULLI", &PPUInterpreter::MULLI, &m_interpreter, rd, ra, simm16); +void PPULLVMRecompilerWorker::MULLI(u32 rd, u32 ra, s32 simm16) { + auto ra_i64 = GetGpr(ra); + auto res_i64 = m_ir_builder->CreateMul(ra_i64, m_ir_builder->getInt64((s64)simm16)); + SetGpr(rd, res_i64); + //InterpreterCall("MULLI", &PPUInterpreter::MULLI, rd, ra, simm16); } -void PPULLVMRecompiler::SUBFIC(u32 rd, u32 ra, s32 simm16) { - //auto ra_i64 = GetGpr(ra); - //auto res_s = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::ssub_with_overflow), s_ir_builder->getInt64((s64)simm16), ra_i64); - //auto diff_i64 = s_ir_builder->CreateExtractValue(res_s, {0}); - //auto carry_i1 = s_ir_builder->CreateExtractValue(res_s, {1}); - //SetGpr(rd, diff_i64); - //SetXerCa(carry_i1); - ThisCall("SUBFIC", &PPUInterpreter::SUBFIC, &m_interpreter, rd, ra, simm16); +void PPULLVMRecompilerWorker::SUBFIC(u32 rd, u32 ra, s32 simm16) { + auto ra_i64 = GetGpr(ra); + auto res_s = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::ssub_with_overflow, {m_ir_builder->getInt64Ty()}), m_ir_builder->getInt64((s64)simm16), ra_i64); + auto diff_i64 = m_ir_builder->CreateExtractValue(res_s, {0}); + auto carry_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); + SetGpr(rd, diff_i64); + SetXerCa(carry_i1); + //InterpreterCall("SUBFIC", &PPUInterpreter::SUBFIC, rd, ra, simm16); } -void PPULLVMRecompiler::CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16) { - //auto ra_i64 = GetGpr(ra); - //if (l == 0) { - // ra_i64 = s_ir_builder->CreateAnd(ra_i64, 0xFFFFFFFF); - //} +void PPULLVMRecompilerWorker::CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16) { + Value * ra_i64; + if (l == 0) { + ra_i64 = m_ir_builder->CreateZExt(GetGpr(ra, 32), m_ir_builder->getInt64Ty()); + } else { + ra_i64 = GetGpr(ra); + } - //SetCrFieldUnsignedCmp(crfd, ra_i64, s_ir_builder->getInt64(uimm16)); - ThisCall("CMPLI", &PPUInterpreter::CMPLI, &m_interpreter, crfd, l, ra, uimm16); + SetCrFieldUnsignedCmp(crfd, ra_i64, m_ir_builder->getInt64(uimm16)); + //InterpreterCall("CMPLI", &PPUInterpreter::CMPLI, crfd, l, ra, uimm16); } -void PPULLVMRecompiler::CMPI(u32 crfd, u32 l, u32 ra, s32 simm16) { - //auto ra_i64 = GetGpr(ra); - //if (l == 0) { - // auto ra_i32 = s_ir_builder->CreateTrunc(ra_i64, s_ir_builder->getInt32Ty()); - // ra_i64 = s_ir_builder->CreateSExt(ra_i64, s_ir_builder->getInt64Ty()); - //} +void PPULLVMRecompilerWorker::CMPI(u32 crfd, u32 l, u32 ra, s32 simm16) { + Value * ra_i64; + if (l == 0) { + ra_i64 = m_ir_builder->CreateSExt(GetGpr(ra, 32), m_ir_builder->getInt64Ty()); + } else { + ra_i64 = GetGpr(ra); + } - //SetCrFieldSignedCmp(crfd, ra_i64, s_ir_builder->getInt64((s64)simm16)); - ThisCall("CMPI", &PPUInterpreter::CMPI, &m_interpreter, crfd, l, ra, simm16); + SetCrFieldSignedCmp(crfd, ra_i64, m_ir_builder->getInt64((s64)simm16)); + //InterpreterCall("CMPI", &PPUInterpreter::CMPI, crfd, l, ra, simm16); } -void PPULLVMRecompiler::ADDIC(u32 rd, u32 ra, s32 simm16) { - //auto ra_i64 = GetGpr(ra); - //auto res_s = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::sadd_with_overflow), s_ir_builder->getInt64((s64)simm16), ra_i64); - //auto sum_i64 = s_ir_builder->CreateExtractValue(res_s, {0}); - //auto carry_i1 = s_ir_builder->CreateExtractValue(res_s, {1}); - //SetGpr(rd, sum_i64); - //SetXerCa(carry_i1); - ThisCall("ADDIC", &PPUInterpreter::ADDIC, &m_interpreter, rd, ra, simm16); +void PPULLVMRecompilerWorker::ADDIC(u32 rd, u32 ra, s32 simm16) { + auto ra_i64 = GetGpr(ra); + auto res_s = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::sadd_with_overflow, {m_ir_builder->getInt64Ty()}), m_ir_builder->getInt64((s64)simm16), ra_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); + //InterpreterCall("ADDIC", &PPUInterpreter::ADDIC, rd, ra, simm16); } -void PPULLVMRecompiler::ADDIC_(u32 rd, u32 ra, s32 simm16) { - //ADDIC(rd, ra, simm16); - //SetCrFieldSignedCmp(0, GetGpr(rd), s_ir_builder->getInt64(0)); - ThisCall("ADDIC_", &PPUInterpreter::ADDIC_, &m_interpreter, rd, ra, simm16); +void PPULLVMRecompilerWorker::ADDIC_(u32 rd, u32 ra, s32 simm16) { + ADDIC(rd, ra, simm16); + SetCrFieldSignedCmp(0, GetGpr(rd), m_ir_builder->getInt64(0)); + //InterpreterCall("ADDIC_", &PPUInterpreter::ADDIC_, rd, ra, simm16); } -void PPULLVMRecompiler::ADDI(u32 rd, u32 ra, s32 simm16) { +void PPULLVMRecompilerWorker::ADDI(u32 rd, u32 ra, s32 simm16) { if (ra == 0) { - SetGpr(rd, s_ir_builder->getInt64((s64)simm16)); + SetGpr(rd, m_ir_builder->getInt64((s64)simm16)); } else { auto ra_i64 = GetGpr(ra); - auto sum_i64 = s_ir_builder->CreateAdd(ra_i64, s_ir_builder->getInt64((s64)simm16)); + auto sum_i64 = m_ir_builder->CreateAdd(ra_i64, m_ir_builder->getInt64((s64)simm16)); SetGpr(rd, sum_i64); } - //ThisCall("ADDI", &PPUInterpreter::ADDI, &m_interpreter, rd, ra, simm16); + //InterpreterCall("ADDI", &PPUInterpreter::ADDI, rd, ra, simm16); } -void PPULLVMRecompiler::ADDIS(u32 rd, u32 ra, s32 simm16) { - //if (ra == 0) { - // SetGpr(rd, s_ir_builder->getInt64((s64)(simm16 << 16))); - //} else { - // auto ra_i64 = GetGpr(ra); - // auto sum_i64 = s_ir_builder->CreateAdd(ra_i64, s_ir_builder->getInt64((s64)(simm16 << 16))); - // SetGpr(rd, sum_i64); - //} - ThisCall("ADDIS", &PPUInterpreter::ADDIS, &m_interpreter, rd, ra, simm16); +void PPULLVMRecompilerWorker::ADDIS(u32 rd, u32 ra, s32 simm16) { + if (ra == 0) { + SetGpr(rd, m_ir_builder->getInt64((s64)simm16 << 16)); + } else { + auto ra_i64 = GetGpr(ra); + auto sum_i64 = m_ir_builder->CreateAdd(ra_i64, m_ir_builder->getInt64((s64)simm16 << 16)); + SetGpr(rd, sum_i64); + } + //InterpreterCall("ADDIS", &PPUInterpreter::ADDIS, rd, ra, simm16); } -void PPULLVMRecompiler::BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) { - ThisCall("BC", &PPUInterpreter::BC, &m_interpreter, bo, bi, bd, aa, lk); +void PPULLVMRecompilerWorker::BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) { + InterpreterCall("BC", &PPUInterpreter::BC, bo, bi, bd, aa, lk); m_hit_branch_instruction = true; } -void PPULLVMRecompiler::SC(u32 sc_code) { - ThisCall("SC", &PPUInterpreter::SC, &m_interpreter, sc_code); +void PPULLVMRecompilerWorker::SC(u32 sc_code) { + InterpreterCall("SC", &PPUInterpreter::SC, sc_code); } -void PPULLVMRecompiler::B(s32 ll, u32 aa, u32 lk) { - ThisCall("B", &PPUInterpreter::B, &m_interpreter, ll, aa, lk); +void PPULLVMRecompilerWorker::B(s32 ll, u32 aa, u32 lk) { + InterpreterCall("B", &PPUInterpreter::B, ll, aa, lk); m_hit_branch_instruction = true; } -void PPULLVMRecompiler::MCRF(u32 crfd, u32 crfs) { - //if (crfd != crfs) { - // auto cr_i32 = GetCr(); - // auto crf_i32 = GetNibble(cr_i32, crfs); - // cr_i32 = SetNibble(cr_i32, crfd, crf_i32); - // SetCr(cr_i32); - //} - ThisCall("MCRF", &PPUInterpreter::MCRF, &m_interpreter, crfd, crfs); +void PPULLVMRecompilerWorker::MCRF(u32 crfd, u32 crfs) { + if (crfd != crfs) { + auto cr_i32 = GetCr(); + auto crf_i32 = GetNibble(cr_i32, crfs); + cr_i32 = SetNibble(cr_i32, crfd, crf_i32); + SetCr(cr_i32); + } + //InterpreterCall("MCRF", &PPUInterpreter::MCRF, crfd, crfs); } -void PPULLVMRecompiler::BCLR(u32 bo, u32 bi, u32 bh, u32 lk) { - ThisCall("BCLR", &PPUInterpreter::BCLR, &m_interpreter, bo, bi, bh, lk); +void PPULLVMRecompilerWorker::BCLR(u32 bo, u32 bi, u32 bh, u32 lk) { + InterpreterCall("BCLR", &PPUInterpreter::BCLR, bo, bi, bh, lk); m_hit_branch_instruction = true; } -void PPULLVMRecompiler::CRNOR(u32 crbd, u32 crba, u32 crbb) { - //auto cr_i32 = GetCr(); - //auto ba_i32 = GetBit(cr_i32, crba); - //auto bb_i32 = GetBit(cr_i32, crbb); - //auto res_i32 = s_ir_builder->CreateOr(ba_i32, bb_i32); - //res_i32 = s_ir_builder->CreateXor(res_i32, 1); - //cr_i32 = SetBit(cr_i32, crbd, res_i32); - //SetCr(cr_i32); - ThisCall("CRNOR", &PPUInterpreter::CRNOR, &m_interpreter, crbd, crba, crbb); +void PPULLVMRecompilerWorker::CRNOR(u32 crbd, u32 crba, u32 crbb) { + auto cr_i32 = GetCr(); + auto ba_i32 = GetBit(cr_i32, crba); + auto bb_i32 = GetBit(cr_i32, crbb); + auto res_i32 = m_ir_builder->CreateOr(ba_i32, bb_i32); + res_i32 = m_ir_builder->CreateXor(res_i32, 1); + cr_i32 = SetBit(cr_i32, crbd, res_i32); + SetCr(cr_i32); + //InterpreterCall("CRNOR", &PPUInterpreter::CRNOR, crbd, crba, crbb); } -void PPULLVMRecompiler::CRANDC(u32 crbd, u32 crba, u32 crbb) { - //auto cr_i32 = GetCr(); - //auto ba_i32 = GetBit(cr_i32, crba); - //auto bb_i32 = GetBit(cr_i32, crbb); - //auto res_i32 = s_ir_builder->CreateXor(bb_i32, 1); - //res_i32 = s_ir_builder->CreateAnd(ba_i32, res_i32); - //cr_i32 = SetBit(cr_i32, crbd, res_i32); - //SetCr(cr_i32); - ThisCall("CRANDC", &PPUInterpreter::CRANDC, &m_interpreter, crbd, crba, crbb); +void PPULLVMRecompilerWorker::CRANDC(u32 crbd, u32 crba, u32 crbb) { + auto cr_i32 = GetCr(); + auto ba_i32 = GetBit(cr_i32, crba); + auto bb_i32 = GetBit(cr_i32, crbb); + auto res_i32 = m_ir_builder->CreateXor(bb_i32, 1); + res_i32 = m_ir_builder->CreateAnd(ba_i32, res_i32); + cr_i32 = SetBit(cr_i32, crbd, res_i32); + SetCr(cr_i32); + //InterpreterCall("CRANDC", &PPUInterpreter::CRANDC, crbd, crba, crbb); } -void PPULLVMRecompiler::ISYNC() { - s_ir_builder->CreateCall(Intrinsic::getDeclaration(s_module, Intrinsic::x86_sse2_mfence)); +void PPULLVMRecompilerWorker::ISYNC() { + m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::x86_sse2_mfence)); } -void PPULLVMRecompiler::CRXOR(u32 crbd, u32 crba, u32 crbb) { - //auto cr_i32 = GetCr(); - //auto ba_i32 = GetBit(cr_i32, crba); - //auto bb_i32 = GetBit(cr_i32, crbb); - //auto res_i32 = s_ir_builder->CreateXor(ba_i32, bb_i32); - //cr_i32 = SetBit(cr_i32, crbd, res_i32); - //SetCr(cr_i32); - ThisCall("CRXOR", &PPUInterpreter::CRXOR, &m_interpreter, crbd, crba, crbb); +void PPULLVMRecompilerWorker::CRXOR(u32 crbd, u32 crba, u32 crbb) { + auto cr_i32 = GetCr(); + auto ba_i32 = GetBit(cr_i32, crba); + auto bb_i32 = GetBit(cr_i32, crbb); + auto res_i32 = m_ir_builder->CreateXor(ba_i32, bb_i32); + cr_i32 = SetBit(cr_i32, crbd, res_i32); + SetCr(cr_i32); + //InterpreterCall("CRXOR", &PPUInterpreter::CRXOR, crbd, crba, crbb); } -void PPULLVMRecompiler::CRNAND(u32 crbd, u32 crba, u32 crbb) { - //auto cr_i32 = GetCr(); - //auto ba_i32 = GetBit(cr_i32, crba); - //auto bb_i32 = GetBit(cr_i32, crbb); - //auto res_i32 = s_ir_builder->CreateAnd(ba_i32, bb_i32); - //res_i32 = s_ir_builder->CreateXor(res_i32, 1); - //cr_i32 = SetBit(cr_i32, crbd, res_i32); - //SetCr(cr_i32); - ThisCall("CRNAND", &PPUInterpreter::CRNAND, &m_interpreter, crbd, crba, crbb); +void PPULLVMRecompilerWorker::CRNAND(u32 crbd, u32 crba, u32 crbb) { + auto cr_i32 = GetCr(); + auto ba_i32 = GetBit(cr_i32, crba); + auto bb_i32 = GetBit(cr_i32, crbb); + auto res_i32 = m_ir_builder->CreateAnd(ba_i32, bb_i32); + res_i32 = m_ir_builder->CreateXor(res_i32, 1); + cr_i32 = SetBit(cr_i32, crbd, res_i32); + SetCr(cr_i32); + //InterpreterCall("CRNAND", &PPUInterpreter::CRNAND, crbd, crba, crbb); } -void PPULLVMRecompiler::CRAND(u32 crbd, u32 crba, u32 crbb) { - //auto cr_i32 = GetCr(); - //auto ba_i32 = GetBit(cr_i32, crba); - //auto bb_i32 = GetBit(cr_i32, crbb); - //auto res_i32 = s_ir_builder->CreateAnd(ba_i32, bb_i32); - //cr_i32 = SetBit(cr_i32, crbd, res_i32); - //SetCr(cr_i32); - ThisCall("CRAND", &PPUInterpreter::CRAND, &m_interpreter, crbd, crba, crbb); +void PPULLVMRecompilerWorker::CRAND(u32 crbd, u32 crba, u32 crbb) { + auto cr_i32 = GetCr(); + auto ba_i32 = GetBit(cr_i32, crba); + auto bb_i32 = GetBit(cr_i32, crbb); + auto res_i32 = m_ir_builder->CreateAnd(ba_i32, bb_i32); + cr_i32 = SetBit(cr_i32, crbd, res_i32); + SetCr(cr_i32); + //InterpreterCall("CRAND", &PPUInterpreter::CRAND, crbd, crba, crbb); } -void PPULLVMRecompiler::CREQV(u32 crbd, u32 crba, u32 crbb) { - //auto cr_i32 = GetCr(); - //auto ba_i32 = GetBit(cr_i32, crba); - //auto bb_i32 = GetBit(cr_i32, crbb); - //auto res_i32 = s_ir_builder->CreateXor(ba_i32, bb_i32); - //res_i32 = s_ir_builder->CreateXor(res_i32, 1); - //cr_i32 = SetBit(cr_i32, crbd, res_i32); - //SetCr(cr_i32); - ThisCall("CREQV", &PPUInterpreter::CREQV, &m_interpreter, crbd, crba, crbb); +void PPULLVMRecompilerWorker::CREQV(u32 crbd, u32 crba, u32 crbb) { + auto cr_i32 = GetCr(); + auto ba_i32 = GetBit(cr_i32, crba); + auto bb_i32 = GetBit(cr_i32, crbb); + auto res_i32 = m_ir_builder->CreateXor(ba_i32, bb_i32); + res_i32 = m_ir_builder->CreateXor(res_i32, 1); + cr_i32 = SetBit(cr_i32, crbd, res_i32); + SetCr(cr_i32); + //InterpreterCall("CREQV", &PPUInterpreter::CREQV, crbd, crba, crbb); } -void PPULLVMRecompiler::CRORC(u32 crbd, u32 crba, u32 crbb) { - //auto cr_i32 = GetCr(); - //auto ba_i32 = GetBit(cr_i32, crba); - //auto bb_i32 = GetBit(cr_i32, crbb); - //auto res_i32 = s_ir_builder->CreateXor(bb_i32, 1); - //res_i32 = s_ir_builder->CreateOr(ba_i32, res_i32); - //cr_i32 = SetBit(cr_i32, crbd, res_i32); - //SetCr(cr_i32); - ThisCall("CRORC", &PPUInterpreter::CRORC, &m_interpreter, crbd, crba, crbb); +void PPULLVMRecompilerWorker::CRORC(u32 crbd, u32 crba, u32 crbb) { + auto cr_i32 = GetCr(); + auto ba_i32 = GetBit(cr_i32, crba); + auto bb_i32 = GetBit(cr_i32, crbb); + auto res_i32 = m_ir_builder->CreateXor(bb_i32, 1); + res_i32 = m_ir_builder->CreateOr(ba_i32, res_i32); + cr_i32 = SetBit(cr_i32, crbd, res_i32); + SetCr(cr_i32); + //InterpreterCall("CRORC", &PPUInterpreter::CRORC, crbd, crba, crbb); } -void PPULLVMRecompiler::CROR(u32 crbd, u32 crba, u32 crbb) { - //auto cr_i32 = GetCr(); - //auto ba_i32 = GetBit(cr_i32, crba); - //auto bb_i32 = GetBit(cr_i32, crbb); - //auto res_i32 = s_ir_builder->CreateOr(ba_i32, bb_i32); - //cr_i32 = SetBit(cr_i32, crbd, res_i32); - //SetCr(cr_i32); - ThisCall("CROR", &PPUInterpreter::CROR, &m_interpreter, crbd, crba, crbb); +void PPULLVMRecompilerWorker::CROR(u32 crbd, u32 crba, u32 crbb) { + auto cr_i32 = GetCr(); + auto ba_i32 = GetBit(cr_i32, crba); + auto bb_i32 = GetBit(cr_i32, crbb); + auto res_i32 = m_ir_builder->CreateOr(ba_i32, bb_i32); + cr_i32 = SetBit(cr_i32, crbd, res_i32); + SetCr(cr_i32); + //InterpreterCall("CROR", &PPUInterpreter::CROR, crbd, crba, crbb); } -void PPULLVMRecompiler::BCCTR(u32 bo, u32 bi, u32 bh, u32 lk) { - ThisCall("BCCTR", &PPUInterpreter::BCCTR, &m_interpreter, bo, bi, bh, lk); +void PPULLVMRecompilerWorker::BCCTR(u32 bo, u32 bi, u32 bh, u32 lk) { + InterpreterCall("BCCTR", &PPUInterpreter::BCCTR, bo, bi, bh, lk); m_hit_branch_instruction = true; } -void PPULLVMRecompiler::RLWIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, bool rc) { - ThisCall("RLWIMI", &PPUInterpreter::RLWIMI, &m_interpreter, ra, rs, sh, mb, me, rc); +void PPULLVMRecompilerWorker::RLWIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, bool rc) { + InterpreterCall("RLWIMI", &PPUInterpreter::RLWIMI, ra, rs, sh, mb, me, rc); } -void PPULLVMRecompiler::RLWINM(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, bool rc) { - ThisCall("RLWINM", &PPUInterpreter::RLWINM, &m_interpreter, ra, rs, sh, mb, me, rc); +void PPULLVMRecompilerWorker::RLWINM(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, bool rc) { + InterpreterCall("RLWINM", &PPUInterpreter::RLWINM, ra, rs, sh, mb, me, rc); } -void PPULLVMRecompiler::RLWNM(u32 ra, u32 rs, u32 rb, u32 mb, u32 me, bool rc) { - ThisCall("RLWNM", &PPUInterpreter::RLWNM, &m_interpreter, ra, rs, rb, mb, me, rc); +void PPULLVMRecompilerWorker::RLWNM(u32 ra, u32 rs, u32 rb, u32 mb, u32 me, bool rc) { + InterpreterCall("RLWNM", &PPUInterpreter::RLWNM, ra, rs, rb, mb, me, rc); } -void PPULLVMRecompiler::ORI(u32 ra, u32 rs, u32 uimm16) { - //auto rs_i64 = GetGpr(rs); - //auto res_i64 = s_ir_builder->CreateOr(rs_i64, uimm16); - //SetGpr(ra, res_i64); - ThisCall("ORI", &PPUInterpreter::ORI, &m_interpreter, ra, rs, uimm16); +void PPULLVMRecompilerWorker::ORI(u32 ra, u32 rs, u32 uimm16) { + auto rs_i64 = GetGpr(rs); + auto res_i64 = m_ir_builder->CreateOr(rs_i64, uimm16); + SetGpr(ra, res_i64); + //InterpreterCall("ORI", &PPUInterpreter::ORI, ra, rs, uimm16); } -void PPULLVMRecompiler::ORIS(u32 ra, u32 rs, u32 uimm16) { - //auto rs_i64 = GetGpr(rs); - //auto res_i64 = s_ir_builder->CreateOr(rs_i64, uimm16 << 16); - //SetGpr(ra, res_i64); - ThisCall("ORIS", &PPUInterpreter::ORIS, &m_interpreter, ra, rs, uimm16); +void PPULLVMRecompilerWorker::ORIS(u32 ra, u32 rs, u32 uimm16) { + auto rs_i64 = GetGpr(rs); + auto res_i64 = m_ir_builder->CreateOr(rs_i64, (u64)uimm16 << 16); + SetGpr(ra, res_i64); + //InterpreterCall("ORIS", &PPUInterpreter::ORIS, ra, rs, uimm16); } -void PPULLVMRecompiler::XORI(u32 ra, u32 rs, u32 uimm16) { - //auto rs_i64 = GetGpr(rs); - //auto res_i64 = s_ir_builder->CreateXor(rs_i64, uimm16); - //SetGpr(ra, res_i64); - ThisCall("XORI", &PPUInterpreter::XORI, &m_interpreter, ra, rs, uimm16); +void PPULLVMRecompilerWorker::XORI(u32 ra, u32 rs, u32 uimm16) { + auto rs_i64 = GetGpr(rs); + auto res_i64 = m_ir_builder->CreateXor(rs_i64, uimm16); + SetGpr(ra, res_i64); + //InterpreterCall("XORI", &PPUInterpreter::XORI, ra, rs, uimm16); } -void PPULLVMRecompiler::XORIS(u32 ra, u32 rs, u32 uimm16) { - //auto rs_i64 = GetGpr(rs); - //auto res_i64 = s_ir_builder->CreateXor(rs_i64, uimm16 << 16); - //SetGpr(ra, res_i64); - ThisCall("XORIS", &PPUInterpreter::XORIS, &m_interpreter, ra, rs, uimm16); +void PPULLVMRecompilerWorker::XORIS(u32 ra, u32 rs, u32 uimm16) { + auto rs_i64 = GetGpr(rs); + auto res_i64 = m_ir_builder->CreateXor(rs_i64, (u64)uimm16 << 16); + SetGpr(ra, res_i64); + //InterpreterCall("XORIS", &PPUInterpreter::XORIS, ra, rs, uimm16); } -void PPULLVMRecompiler::ANDI_(u32 ra, u32 rs, u32 uimm16) { - //auto rs_i64 = GetGpr(rs); - //auto res_i64 = s_ir_builder->CreateAnd(rs_i64, uimm16); - //SetGpr(ra, res_i64); - //SetCrFieldSignedCmp(0, res_i64, s_ir_builder->getInt64(0)); - ThisCall("ANDI_", &PPUInterpreter::ANDI_, &m_interpreter, ra, rs, uimm16); +void PPULLVMRecompilerWorker::ANDI_(u32 ra, u32 rs, u32 uimm16) { + auto rs_i64 = GetGpr(rs); + auto res_i64 = m_ir_builder->CreateAnd(rs_i64, uimm16); + SetGpr(ra, res_i64); + SetCrFieldSignedCmp(0, res_i64, m_ir_builder->getInt64(0)); + //InterpreterCall("ANDI_", &PPUInterpreter::ANDI_, ra, rs, uimm16); } -void PPULLVMRecompiler::ANDIS_(u32 ra, u32 rs, u32 uimm16) { - //auto rs_i64 = GetGpr(rs); - //auto res_i64 = s_ir_builder->CreateAnd(rs_i64, uimm16 << 16); - //SetGpr(ra, res_i64); - //SetCrFieldSignedCmp(0, res_i64, s_ir_builder->getInt64(0)); - ThisCall("ANDIS_", &PPUInterpreter::ANDIS_, &m_interpreter, ra, rs, uimm16); +void PPULLVMRecompilerWorker::ANDIS_(u32 ra, u32 rs, u32 uimm16) { + auto rs_i64 = GetGpr(rs); + auto res_i64 = m_ir_builder->CreateAnd(rs_i64, (u64)uimm16 << 16); + SetGpr(ra, res_i64); + SetCrFieldSignedCmp(0, res_i64, m_ir_builder->getInt64(0)); + //InterpreterCall("ANDIS_", &PPUInterpreter::ANDIS_, ra, rs, uimm16); } -void PPULLVMRecompiler::RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) { - ThisCall("RLDICL", &PPUInterpreter::RLDICL, &m_interpreter, ra, rs, sh, mb, rc); +void PPULLVMRecompilerWorker::RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) { + InterpreterCall("RLDICL", &PPUInterpreter::RLDICL, ra, rs, sh, mb, rc); } -void PPULLVMRecompiler::RLDICR(u32 ra, u32 rs, u32 sh, u32 me, bool rc) { - ThisCall("RLDICR", &PPUInterpreter::RLDICR, &m_interpreter, ra, rs, sh, me, rc); +void PPULLVMRecompilerWorker::RLDICR(u32 ra, u32 rs, u32 sh, u32 me, bool rc) { + InterpreterCall("RLDICR", &PPUInterpreter::RLDICR, ra, rs, sh, me, rc); } -void PPULLVMRecompiler::RLDIC(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) { - ThisCall("RLDIC", &PPUInterpreter::RLDIC, &m_interpreter, ra, rs, sh, mb, rc); +void PPULLVMRecompilerWorker::RLDIC(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) { + InterpreterCall("RLDIC", &PPUInterpreter::RLDIC, ra, rs, sh, mb, rc); } -void PPULLVMRecompiler::RLDIMI(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) { - ThisCall("RLDIMI", &PPUInterpreter::RLDIMI, &m_interpreter, ra, rs, sh, mb, rc); +void PPULLVMRecompilerWorker::RLDIMI(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) { + InterpreterCall("RLDIMI", &PPUInterpreter::RLDIMI, ra, rs, sh, mb, rc); } -void PPULLVMRecompiler::RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, bool is_r, bool rc) { - ThisCall("RLDC_LR", &PPUInterpreter::RLDC_LR, &m_interpreter, ra, rs, rb, m_eb, is_r, rc); +void PPULLVMRecompilerWorker::RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, bool is_r, bool rc) { + InterpreterCall("RLDC_LR", &PPUInterpreter::RLDC_LR, ra, rs, rb, m_eb, is_r, rc); } -void PPULLVMRecompiler::CMP(u32 crfd, u32 l, u32 ra, u32 rb) { - ThisCall("CMP", &PPUInterpreter::CMP, &m_interpreter, crfd, l, ra, rb); +void PPULLVMRecompilerWorker::CMP(u32 crfd, u32 l, u32 ra, u32 rb) { + Value * ra_i64; + Value * rb_i64; + if (l == 0) { + ra_i64 = m_ir_builder->CreateSExt(GetGpr(ra, 32), m_ir_builder->getInt64Ty()); + rb_i64 = m_ir_builder->CreateSExt(GetGpr(rb, 32), m_ir_builder->getInt64Ty()); + } else { + ra_i64 = GetGpr(ra); + rb_i64 = GetGpr(rb); + } + + SetCrFieldSignedCmp(crfd, ra_i64, rb_i64); + //InterpreterCall("CMP", &PPUInterpreter::CMP, crfd, l, ra, rb); } -void PPULLVMRecompiler::TW(u32 to, u32 ra, u32 rb) { - ThisCall("TW", &PPUInterpreter::TW, &m_interpreter, to, ra, rb); +void PPULLVMRecompilerWorker::TW(u32 to, u32 ra, u32 rb) { + InterpreterCall("TW", &PPUInterpreter::TW, to, ra, rb); } -void PPULLVMRecompiler::LVSL(u32 vd, u32 ra, u32 rb) { - ThisCall("LVSL", &PPUInterpreter::LVSL, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVSL(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVSL", &PPUInterpreter::LVSL, vd, ra, rb); } -void PPULLVMRecompiler::LVEBX(u32 vd, u32 ra, u32 rb) { - ThisCall("LVEBX", &PPUInterpreter::LVEBX, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVEBX(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVEBX", &PPUInterpreter::LVEBX, vd, ra, rb); } -void PPULLVMRecompiler::SUBFC(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("SUBFC", &PPUInterpreter::SUBFC, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::SUBFC(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("SUBFC", &PPUInterpreter::SUBFC, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::ADDC(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("ADDC", &PPUInterpreter::ADDC, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::ADDC(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("ADDC", &PPUInterpreter::ADDC, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::MULHDU(u32 rd, u32 ra, u32 rb, bool rc) { - ThisCall("MULHDU", &PPUInterpreter::MULHDU, &m_interpreter, rd, ra, rb, rc); +void PPULLVMRecompilerWorker::MULHDU(u32 rd, u32 ra, u32 rb, bool rc) { + InterpreterCall("MULHDU", &PPUInterpreter::MULHDU, rd, ra, rb, rc); } -void PPULLVMRecompiler::MULHWU(u32 rd, u32 ra, u32 rb, bool rc) { - ThisCall("MULHWU", &PPUInterpreter::MULHWU, &m_interpreter, rd, ra, rb, rc); +void PPULLVMRecompilerWorker::MULHWU(u32 rd, u32 ra, u32 rb, bool rc) { + InterpreterCall("MULHWU", &PPUInterpreter::MULHWU, rd, ra, rb, rc); } -void PPULLVMRecompiler::MFOCRF(u32 a, u32 rd, u32 crm) { - ThisCall("MFOCRF", &PPUInterpreter::MFOCRF, &m_interpreter, a, rd, crm); +void PPULLVMRecompilerWorker::MFOCRF(u32 a, u32 rd, u32 crm) { + InterpreterCall("MFOCRF", &PPUInterpreter::MFOCRF, a, rd, crm); } -void PPULLVMRecompiler::LWARX(u32 rd, u32 ra, u32 rb) { - ThisCall("LWARX", &PPUInterpreter::LWARX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LWARX(u32 rd, u32 ra, u32 rb) { + InterpreterCall("LWARX", &PPUInterpreter::LWARX, rd, ra, rb); } -void PPULLVMRecompiler::LDX(u32 rd, u32 ra, u32 rb) { - ThisCall("LDX", &PPUInterpreter::LDX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LDX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i64 = ReadMemory(addr_i64, 64); + SetGpr(rd, mem_i64); + //InterpreterCall("LDX", &PPUInterpreter::LDX, rd, ra, rb); } -void PPULLVMRecompiler::LWZX(u32 rd, u32 ra, u32 rb) { - ThisCall("LWZX", &PPUInterpreter::LWZX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LWZX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i32 = ReadMemory(addr_i64, 32); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LWZX", &PPUInterpreter::LWZX, rd, ra, rb); } -void PPULLVMRecompiler::SLW(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("SLW", &PPUInterpreter::SLW, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::SLW(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("SLW", &PPUInterpreter::SLW, ra, rs, rb, rc); } -void PPULLVMRecompiler::CNTLZW(u32 ra, u32 rs, bool rc) { - ThisCall("CNTLZW", &PPUInterpreter::CNTLZW, &m_interpreter, ra, rs, rc); +void PPULLVMRecompilerWorker::CNTLZW(u32 ra, u32 rs, bool rc) { + InterpreterCall("CNTLZW", &PPUInterpreter::CNTLZW, ra, rs, rc); } -void PPULLVMRecompiler::SLD(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("SLD", &PPUInterpreter::SLD, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::SLD(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("SLD", &PPUInterpreter::SLD, ra, rs, rb, rc); } -void PPULLVMRecompiler::AND(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("AND", &PPUInterpreter::AND, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::AND(u32 ra, u32 rs, u32 rb, bool rc) { + auto rs_i64 = GetGpr(rs); + auto rb_i64 = GetGpr(rb); + auto res_i64 = m_ir_builder->CreateAnd(rs_i64, rb_i64); + SetGpr(ra, res_i64); + + if (rc) { + SetCrFieldSignedCmp(0, res_i64, m_ir_builder->getInt64(0)); + } + //InterpreterCall("AND", &PPUInterpreter::AND, ra, rs, rb, rc); } -void PPULLVMRecompiler::CMPL(u32 crfd, u32 l, u32 ra, u32 rb) { - ThisCall("CMPL", &PPUInterpreter::CMPL, &m_interpreter, crfd, l, ra, rb); +void PPULLVMRecompilerWorker::CMPL(u32 crfd, u32 l, u32 ra, u32 rb) { + Value * ra_i64; + Value * rb_i64; + if (l == 0) { + ra_i64 = m_ir_builder->CreateZExt(GetGpr(ra, 32), m_ir_builder->getInt64Ty()); + rb_i64 = m_ir_builder->CreateZExt(GetGpr(rb, 32), m_ir_builder->getInt64Ty()); + } else { + ra_i64 = GetGpr(ra); + rb_i64 = GetGpr(rb); + } + + SetCrFieldUnsignedCmp(crfd, ra_i64, rb_i64); + //InterpreterCall("CMPL", &PPUInterpreter::CMPL, crfd, l, ra, rb); } -void PPULLVMRecompiler::LVSR(u32 vd, u32 ra, u32 rb) { - ThisCall("LVSR", &PPUInterpreter::LVSR, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVSR(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVSR", &PPUInterpreter::LVSR, vd, ra, rb); } -void PPULLVMRecompiler::LVEHX(u32 vd, u32 ra, u32 rb) { - ThisCall("LVEHX", &PPUInterpreter::LVEHX, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVEHX(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVEHX", &PPUInterpreter::LVEHX, vd, ra, rb); } -void PPULLVMRecompiler::SUBF(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("SUBF", &PPUInterpreter::SUBF, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::SUBF(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("SUBF", &PPUInterpreter::SUBF, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::LDUX(u32 rd, u32 ra, u32 rb) { - ThisCall("LDUX", &PPUInterpreter::LDUX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LDUX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i64 = ReadMemory(addr_i64, 64); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LDUX", &PPUInterpreter::LDUX, rd, ra, rb); } -void PPULLVMRecompiler::DCBST(u32 ra, u32 rb) { - ThisCall("DCBST", &PPUInterpreter::DCBST, &m_interpreter, ra, rb); +void PPULLVMRecompilerWorker::DCBST(u32 ra, u32 rb) { + InterpreterCall("DCBST", &PPUInterpreter::DCBST, ra, rb); } -void PPULLVMRecompiler::LWZUX(u32 rd, u32 ra, u32 rb) { - ThisCall("LWZUX", &PPUInterpreter::LWZUX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LWZUX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i32 = ReadMemory(addr_i64, 32); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LWZUX", &PPUInterpreter::LWZUX, rd, ra, rb); } -void PPULLVMRecompiler::CNTLZD(u32 ra, u32 rs, bool rc) { - ThisCall("CNTLZD", &PPUInterpreter::CNTLZD, &m_interpreter, ra, rs, rc); +void PPULLVMRecompilerWorker::CNTLZD(u32 ra, u32 rs, bool rc) { + InterpreterCall("CNTLZD", &PPUInterpreter::CNTLZD, ra, rs, rc); } -void PPULLVMRecompiler::ANDC(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("ANDC", &PPUInterpreter::ANDC, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::ANDC(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("ANDC", &PPUInterpreter::ANDC, ra, rs, rb, rc); } -void PPULLVMRecompiler::TD(u32 to, u32 ra, u32 rb) { - ThisCall("TD", &PPUInterpreter::TD, &m_interpreter, to, ra, rb); +void PPULLVMRecompilerWorker::TD(u32 to, u32 ra, u32 rb) { + InterpreterCall("TD", &PPUInterpreter::TD, to, ra, rb); } -void PPULLVMRecompiler::LVEWX(u32 vd, u32 ra, u32 rb) { - ThisCall("LVEWX", &PPUInterpreter::LVEWX, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVEWX(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVEWX", &PPUInterpreter::LVEWX, vd, ra, rb); } -void PPULLVMRecompiler::MULHD(u32 rd, u32 ra, u32 rb, bool rc) { - ThisCall("MULHD", &PPUInterpreter::MULHD, &m_interpreter, rd, ra, rb, rc); +void PPULLVMRecompilerWorker::MULHD(u32 rd, u32 ra, u32 rb, bool rc) { + InterpreterCall("MULHD", &PPUInterpreter::MULHD, rd, ra, rb, rc); } -void PPULLVMRecompiler::MULHW(u32 rd, u32 ra, u32 rb, bool rc) { - ThisCall("MULHW", &PPUInterpreter::MULHW, &m_interpreter, rd, ra, rb, rc); +void PPULLVMRecompilerWorker::MULHW(u32 rd, u32 ra, u32 rb, bool rc) { + InterpreterCall("MULHW", &PPUInterpreter::MULHW, rd, ra, rb, rc); } -void PPULLVMRecompiler::LDARX(u32 rd, u32 ra, u32 rb) { - ThisCall("LDARX", &PPUInterpreter::LDARX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LDARX(u32 rd, u32 ra, u32 rb) { + InterpreterCall("LDARX", &PPUInterpreter::LDARX, rd, ra, rb); } -void PPULLVMRecompiler::DCBF(u32 ra, u32 rb) { - ThisCall("DCBF", &PPUInterpreter::DCBF, &m_interpreter, ra, rb); +void PPULLVMRecompilerWorker::DCBF(u32 ra, u32 rb) { + InterpreterCall("DCBF", &PPUInterpreter::DCBF, ra, rb); } -void PPULLVMRecompiler::LBZX(u32 rd, u32 ra, u32 rb) { - ThisCall("LBZX", &PPUInterpreter::LBZX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LBZX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i8 = ReadMemory(addr_i64, 8); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i8, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LBZX", &PPUInterpreter::LBZX, rd, ra, rb); } -void PPULLVMRecompiler::LVX(u32 vd, u32 ra, u32 rb) { - ThisCall("LVX", &PPUInterpreter::LVX, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVX(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVX", &PPUInterpreter::LVX, vd, ra, rb); } -void PPULLVMRecompiler::NEG(u32 rd, u32 ra, u32 oe, bool rc) { - ThisCall("NEG", &PPUInterpreter::NEG, &m_interpreter, rd, ra, oe, rc); +void PPULLVMRecompilerWorker::NEG(u32 rd, u32 ra, u32 oe, bool rc) { + InterpreterCall("NEG", &PPUInterpreter::NEG, rd, ra, oe, rc); } -void PPULLVMRecompiler::LBZUX(u32 rd, u32 ra, u32 rb) { - ThisCall("LBZUX", &PPUInterpreter::LBZUX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LBZUX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i8 = ReadMemory(addr_i64, 8); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i8, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LBZUX", &PPUInterpreter::LBZUX, rd, ra, rb); } -void PPULLVMRecompiler::NOR(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("NOR", &PPUInterpreter::NOR, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::NOR(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("NOR", &PPUInterpreter::NOR, ra, rs, rb, rc); } -void PPULLVMRecompiler::STVEBX(u32 vs, u32 ra, u32 rb) { - ThisCall("STVEBX", &PPUInterpreter::STVEBX, &m_interpreter, vs, ra, rb); +void PPULLVMRecompilerWorker::STVEBX(u32 vs, u32 ra, u32 rb) { + InterpreterCall("STVEBX", &PPUInterpreter::STVEBX, vs, ra, rb); } -void PPULLVMRecompiler::SUBFE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("SUBFE", &PPUInterpreter::SUBFE, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::SUBFE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("SUBFE", &PPUInterpreter::SUBFE, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::ADDE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("ADDE", &PPUInterpreter::ADDE, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::ADDE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("ADDE", &PPUInterpreter::ADDE, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::MTOCRF(u32 l, u32 crm, u32 rs) { - ThisCall("MTOCRF", &PPUInterpreter::MTOCRF, &m_interpreter, l, crm, rs); +void PPULLVMRecompilerWorker::MTOCRF(u32 l, u32 crm, u32 rs) { + InterpreterCall("MTOCRF", &PPUInterpreter::MTOCRF, l, crm, rs); } -void PPULLVMRecompiler::STDX(u32 rs, u32 ra, u32 rb) { - ThisCall("STDX", &PPUInterpreter::STDX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STDX(u32 rs, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + WriteMemory(addr_i64, GetGpr(rs, 64)); + //InterpreterCall("STDX", &PPUInterpreter::STDX, rs, ra, rb); } -void PPULLVMRecompiler::STWCX_(u32 rs, u32 ra, u32 rb) { - ThisCall("STWCX_", &PPUInterpreter::STWCX_, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STWCX_(u32 rs, u32 ra, u32 rb) { + InterpreterCall("STWCX_", &PPUInterpreter::STWCX_, rs, ra, rb); } -void PPULLVMRecompiler::STWX(u32 rs, u32 ra, u32 rb) { - ThisCall("STWX", &PPUInterpreter::STWX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STWX(u32 rs, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + WriteMemory(addr_i64, GetGpr(rs, 32)); + //InterpreterCall("STWX", &PPUInterpreter::STWX, rs, ra, rb); } -void PPULLVMRecompiler::STVEHX(u32 vs, u32 ra, u32 rb) { - ThisCall("STVEHX", &PPUInterpreter::STVEHX, &m_interpreter, vs, ra, rb); +void PPULLVMRecompilerWorker::STVEHX(u32 vs, u32 ra, u32 rb) { + InterpreterCall("STVEHX", &PPUInterpreter::STVEHX, vs, ra, rb); } -void PPULLVMRecompiler::STDUX(u32 rs, u32 ra, u32 rb) { - ThisCall("STDUX", &PPUInterpreter::STDUX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STDUX(u32 rs, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + WriteMemory(addr_i64, GetGpr(rs, 64)); + SetGpr(ra, addr_i64); + //InterpreterCall("STDUX", &PPUInterpreter::STDUX, rs, ra, rb); } -void PPULLVMRecompiler::STWUX(u32 rs, u32 ra, u32 rb) { - ThisCall("STWUX", &PPUInterpreter::STWUX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STWUX(u32 rs, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + WriteMemory(addr_i64, GetGpr(rs, 32)); + SetGpr(ra, addr_i64); + //InterpreterCall("STWUX", &PPUInterpreter::STWUX, rs, ra, rb); } -void PPULLVMRecompiler::STVEWX(u32 vs, u32 ra, u32 rb) { - ThisCall("STVEWX", &PPUInterpreter::STVEWX, &m_interpreter, vs, ra, rb); +void PPULLVMRecompilerWorker::STVEWX(u32 vs, u32 ra, u32 rb) { + InterpreterCall("STVEWX", &PPUInterpreter::STVEWX, vs, ra, rb); } -void PPULLVMRecompiler::ADDZE(u32 rd, u32 ra, u32 oe, bool rc) { - ThisCall("ADDZE", &PPUInterpreter::ADDZE, &m_interpreter, rd, ra, oe, rc); +void PPULLVMRecompilerWorker::ADDZE(u32 rd, u32 ra, u32 oe, bool rc) { + InterpreterCall("ADDZE", &PPUInterpreter::ADDZE, rd, ra, oe, rc); } -void PPULLVMRecompiler::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) { - ThisCall("SUBFZE", &PPUInterpreter::SUBFZE, &m_interpreter, rd, ra, oe, rc); +void PPULLVMRecompilerWorker::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) { + InterpreterCall("SUBFZE", &PPUInterpreter::SUBFZE, rd, ra, oe, rc); } -void PPULLVMRecompiler::STDCX_(u32 rs, u32 ra, u32 rb) { - ThisCall("STDCX_", &PPUInterpreter::STDCX_, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STDCX_(u32 rs, u32 ra, u32 rb) { + InterpreterCall("STDCX_", &PPUInterpreter::STDCX_, rs, ra, rb); } -void PPULLVMRecompiler::STBX(u32 rs, u32 ra, u32 rb) { - ThisCall("STBX", &PPUInterpreter::STBX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STBX(u32 rs, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + WriteMemory(addr_i64, GetGpr(rs, 8)); + //InterpreterCall("STBX", &PPUInterpreter::STBX, rs, ra, rb); } -void PPULLVMRecompiler::STVX(u32 vs, u32 ra, u32 rb) { - ThisCall("STVX", &PPUInterpreter::STVX, &m_interpreter, vs, ra, rb); +void PPULLVMRecompilerWorker::STVX(u32 vs, u32 ra, u32 rb) { + InterpreterCall("STVX", &PPUInterpreter::STVX, vs, ra, rb); } -void PPULLVMRecompiler::SUBFME(u32 rd, u32 ra, u32 oe, bool rc) { - ThisCall("SUBFME", &PPUInterpreter::SUBFME, &m_interpreter, rd, ra, oe, rc); +void PPULLVMRecompilerWorker::SUBFME(u32 rd, u32 ra, u32 oe, bool rc) { + InterpreterCall("SUBFME", &PPUInterpreter::SUBFME, rd, ra, oe, rc); } -void PPULLVMRecompiler::MULLD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("MULLD", &PPUInterpreter::MULLD, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::MULLD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("MULLD", &PPUInterpreter::MULLD, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::ADDME(u32 rd, u32 ra, u32 oe, bool rc) { - ThisCall("ADDME", &PPUInterpreter::ADDME, &m_interpreter, rd, ra, oe, rc); +void PPULLVMRecompilerWorker::ADDME(u32 rd, u32 ra, u32 oe, bool rc) { + InterpreterCall("ADDME", &PPUInterpreter::ADDME, rd, ra, oe, rc); } -void PPULLVMRecompiler::MULLW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("MULLW", &PPUInterpreter::MULLW, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::MULLW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("MULLW", &PPUInterpreter::MULLW, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::DCBTST(u32 ra, u32 rb, u32 th) { - ThisCall("DCBTST", &PPUInterpreter::DCBTST, &m_interpreter, ra, rb, th); +void PPULLVMRecompilerWorker::DCBTST(u32 ra, u32 rb, u32 th) { + InterpreterCall("DCBTST", &PPUInterpreter::DCBTST, ra, rb, th); } -void PPULLVMRecompiler::STBUX(u32 rs, u32 ra, u32 rb) { - ThisCall("STBUX", &PPUInterpreter::STBUX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STBUX(u32 rs, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + WriteMemory(addr_i64, GetGpr(rs, 8)); + SetGpr(ra, addr_i64); + //InterpreterCall("STBUX", &PPUInterpreter::STBUX, rs, ra, rb); } -void PPULLVMRecompiler::ADD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("ADD", &PPUInterpreter::ADD, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::ADD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + auto ra_i64 = GetGpr(ra); + auto rb_i64 = GetGpr(rb); + auto sum_i64 = m_ir_builder->CreateAdd(ra_i64, rb_i64); + SetGpr(rd, sum_i64); + + if (rc) { + SetCrFieldSignedCmp(0, sum_i64, m_ir_builder->getInt64(0)); + } + + if (oe) { + // TODO: Implement this + } + //InterpreterCall("ADD", &PPUInterpreter::ADD, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::DCBT(u32 ra, u32 rb, u32 th) { - ThisCall("DCBT", &PPUInterpreter::DCBT, &m_interpreter, ra, rb, th); +void PPULLVMRecompilerWorker::DCBT(u32 ra, u32 rb, u32 th) { + InterpreterCall("DCBT", &PPUInterpreter::DCBT, ra, rb, th); } -void PPULLVMRecompiler::LHZX(u32 rd, u32 ra, u32 rb) { - ThisCall("LHZX", &PPUInterpreter::LHZX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LHZX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i16 = ReadMemory(addr_i64, 16); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i16, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LHZX", &PPUInterpreter::LHZX, rd, ra, rb); } -void PPULLVMRecompiler::EQV(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("EQV", &PPUInterpreter::EQV, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::EQV(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("EQV", &PPUInterpreter::EQV, ra, rs, rb, rc); } -void PPULLVMRecompiler::ECIWX(u32 rd, u32 ra, u32 rb) { - ThisCall("ECIWX", &PPUInterpreter::ECIWX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::ECIWX(u32 rd, u32 ra, u32 rb) { + InterpreterCall("ECIWX", &PPUInterpreter::ECIWX, rd, ra, rb); } -void PPULLVMRecompiler::LHZUX(u32 rd, u32 ra, u32 rb) { - ThisCall("LHZUX", &PPUInterpreter::LHZUX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LHZUX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i16 = ReadMemory(addr_i64, 16); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i16, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LHZUX", &PPUInterpreter::LHZUX, rd, ra, rb); } -void PPULLVMRecompiler::XOR(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("XOR", &PPUInterpreter::XOR, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::XOR(u32 ra, u32 rs, u32 rb, bool rc) { + auto rs_i64 = GetGpr(rs); + auto rb_i64 = GetGpr(rb); + auto res_i64 = m_ir_builder->CreateXor(rs_i64, rb_i64); + SetGpr(ra, res_i64); + + if (rc) { + SetCrFieldSignedCmp(0, res_i64, m_ir_builder->getInt64(0)); + } + //InterpreterCall("XOR", &PPUInterpreter::XOR, ra, rs, rb, rc); } -void PPULLVMRecompiler::MFSPR(u32 rd, u32 spr) { - ThisCall("MFSPR", &PPUInterpreter::MFSPR, &m_interpreter, rd, spr); +void PPULLVMRecompilerWorker::MFSPR(u32 rd, u32 spr) { + InterpreterCall("MFSPR", &PPUInterpreter::MFSPR, rd, spr); } -void PPULLVMRecompiler::LWAX(u32 rd, u32 ra, u32 rb) { - ThisCall("LWAX", &PPUInterpreter::LWAX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LWAX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i32 = ReadMemory(addr_i64, 32); + auto mem_i64 = m_ir_builder->CreateSExt(mem_i32, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LWAX", &PPUInterpreter::LWAX, rd, ra, rb); } -void PPULLVMRecompiler::DST(u32 ra, u32 rb, u32 strm, u32 t) { - ThisCall("DST", &PPUInterpreter::DST, &m_interpreter, ra, rb, strm, t); +void PPULLVMRecompilerWorker::DST(u32 ra, u32 rb, u32 strm, u32 t) { + InterpreterCall("DST", &PPUInterpreter::DST, ra, rb, strm, t); } -void PPULLVMRecompiler::LHAX(u32 rd, u32 ra, u32 rb) { - ThisCall("LHAX", &PPUInterpreter::LHAX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LHAX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i16 = ReadMemory(addr_i64, 16); + auto mem_i64 = m_ir_builder->CreateSExt(mem_i16, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LHAX", &PPUInterpreter::LHAX, rd, ra, rb); } -void PPULLVMRecompiler::LVXL(u32 vd, u32 ra, u32 rb) { - ThisCall("LVXL", &PPUInterpreter::LVXL, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVXL(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVXL", &PPUInterpreter::LVXL, vd, ra, rb); } -void PPULLVMRecompiler::MFTB(u32 rd, u32 spr) { - ThisCall("MFTB", &PPUInterpreter::MFTB, &m_interpreter, rd, spr); +void PPULLVMRecompilerWorker::MFTB(u32 rd, u32 spr) { + InterpreterCall("MFTB", &PPUInterpreter::MFTB, rd, spr); } -void PPULLVMRecompiler::LWAUX(u32 rd, u32 ra, u32 rb) { - ThisCall("LWAUX", &PPUInterpreter::LWAUX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LWAUX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i32 = ReadMemory(addr_i64, 32); + auto mem_i64 = m_ir_builder->CreateSExt(mem_i32, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LWAUX", &PPUInterpreter::LWAUX, rd, ra, rb); } -void PPULLVMRecompiler::DSTST(u32 ra, u32 rb, u32 strm, u32 t) { - ThisCall("DSTST", &PPUInterpreter::DSTST, &m_interpreter, ra, rb, strm, t); +void PPULLVMRecompilerWorker::DSTST(u32 ra, u32 rb, u32 strm, u32 t) { + InterpreterCall("DSTST", &PPUInterpreter::DSTST, ra, rb, strm, t); } -void PPULLVMRecompiler::LHAUX(u32 rd, u32 ra, u32 rb) { - ThisCall("LHAUX", &PPUInterpreter::LHAUX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LHAUX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i16 = ReadMemory(addr_i64, 16); + auto mem_i64 = m_ir_builder->CreateSExt(mem_i16, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LHAUX", &PPUInterpreter::LHAUX, rd, ra, rb); } -void PPULLVMRecompiler::STHX(u32 rs, u32 ra, u32 rb) { - ThisCall("STHX", &PPUInterpreter::STHX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STHX(u32 rs, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + WriteMemory(addr_i64, GetGpr(rs, 16)); + //InterpreterCall("STHX", &PPUInterpreter::STHX, rs, ra, rb); } -void PPULLVMRecompiler::ORC(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("ORC", &PPUInterpreter::ORC, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::ORC(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("ORC", &PPUInterpreter::ORC, ra, rs, rb, rc); } -void PPULLVMRecompiler::ECOWX(u32 rs, u32 ra, u32 rb) { - ThisCall("ECOWX", &PPUInterpreter::ECOWX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::ECOWX(u32 rs, u32 ra, u32 rb) { + InterpreterCall("ECOWX", &PPUInterpreter::ECOWX, rs, ra, rb); } -void PPULLVMRecompiler::STHUX(u32 rs, u32 ra, u32 rb) { - ThisCall("STHUX", &PPUInterpreter::STHUX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STHUX(u32 rs, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + WriteMemory(addr_i64, GetGpr(rs, 16)); + SetGpr(ra, addr_i64); + //InterpreterCall("STHUX", &PPUInterpreter::STHUX, rs, ra, rb); } -void PPULLVMRecompiler::OR(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("OR", &PPUInterpreter::OR, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::OR(u32 ra, u32 rs, u32 rb, bool rc) { + auto rs_i64 = GetGpr(rs); + auto rb_i64 = GetGpr(rb); + auto res_i64 = m_ir_builder->CreateOr(rs_i64, rb_i64); + SetGpr(ra, res_i64); + + if (rc) { + SetCrFieldSignedCmp(0, res_i64, m_ir_builder->getInt64(0)); + } + //InterpreterCall("OR", &PPUInterpreter::OR, ra, rs, rb, rc); } -void PPULLVMRecompiler::DIVDU(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("DIVDU", &PPUInterpreter::DIVDU, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::DIVDU(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("DIVDU", &PPUInterpreter::DIVDU, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::DIVWU(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("DIVWU", &PPUInterpreter::DIVWU, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::DIVWU(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("DIVWU", &PPUInterpreter::DIVWU, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::MTSPR(u32 spr, u32 rs) { - ThisCall("MTSPR", &PPUInterpreter::MTSPR, &m_interpreter, spr, rs); +void PPULLVMRecompilerWorker::MTSPR(u32 spr, u32 rs) { + InterpreterCall("MTSPR", &PPUInterpreter::MTSPR, spr, rs); } -void PPULLVMRecompiler::NAND(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("NAND", &PPUInterpreter::NAND, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::NAND(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("NAND", &PPUInterpreter::NAND, ra, rs, rb, rc); } -void PPULLVMRecompiler::STVXL(u32 vs, u32 ra, u32 rb) { - ThisCall("STVXL", &PPUInterpreter::STVXL, &m_interpreter, vs, ra, rb); +void PPULLVMRecompilerWorker::STVXL(u32 vs, u32 ra, u32 rb) { + InterpreterCall("STVXL", &PPUInterpreter::STVXL, vs, ra, rb); } -void PPULLVMRecompiler::DIVD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("DIVD", &PPUInterpreter::DIVD, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::DIVD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("DIVD", &PPUInterpreter::DIVD, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::DIVW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - ThisCall("DIVW", &PPUInterpreter::DIVW, &m_interpreter, rd, ra, rb, oe, rc); +void PPULLVMRecompilerWorker::DIVW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { + InterpreterCall("DIVW", &PPUInterpreter::DIVW, rd, ra, rb, oe, rc); } -void PPULLVMRecompiler::LVLX(u32 vd, u32 ra, u32 rb) { - ThisCall("LVLX", &PPUInterpreter::LVLX, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVLX(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVLX", &PPUInterpreter::LVLX, vd, ra, rb); } -void PPULLVMRecompiler::LDBRX(u32 rd, u32 ra, u32 rb) { - ThisCall("LDBRX", &PPUInterpreter::LDBRX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LDBRX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i64 = ReadMemory(addr_i64, 64, false); + SetGpr(rd, mem_i64); + //InterpreterCall("LDBRX", &PPUInterpreter::LDBRX, rd, ra, rb); } -void PPULLVMRecompiler::LSWX(u32 rd, u32 ra, u32 rb) { - ThisCall("LSWX", &PPUInterpreter::LSWX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LSWX(u32 rd, u32 ra, u32 rb) { + InterpreterCall("LSWX", &PPUInterpreter::LSWX, rd, ra, rb); } -void PPULLVMRecompiler::LWBRX(u32 rd, u32 ra, u32 rb) { - ThisCall("LWBRX", &PPUInterpreter::LWBRX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LWBRX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i32 = ReadMemory(addr_i64, 32, false); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LWBRX", &PPUInterpreter::LWBRX, rd, ra, rb); } -void PPULLVMRecompiler::LFSX(u32 frd, u32 ra, u32 rb) { - ThisCall("LFSX", &PPUInterpreter::LFSX, &m_interpreter, frd, ra, rb); +void PPULLVMRecompilerWorker::LFSX(u32 frd, u32 ra, u32 rb) { + InterpreterCall("LFSX", &PPUInterpreter::LFSX, frd, ra, rb); } -void PPULLVMRecompiler::SRW(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("SRW", &PPUInterpreter::SRW, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::SRW(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("SRW", &PPUInterpreter::SRW, ra, rs, rb, rc); } -void PPULLVMRecompiler::SRD(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("SRD", &PPUInterpreter::SRD, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::SRD(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("SRD", &PPUInterpreter::SRD, ra, rs, rb, rc); } -void PPULLVMRecompiler::LVRX(u32 vd, u32 ra, u32 rb) { - ThisCall("LVRX", &PPUInterpreter::LVRX, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVRX(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVRX", &PPUInterpreter::LVRX, vd, ra, rb); } -void PPULLVMRecompiler::LSWI(u32 rd, u32 ra, u32 nb) { - ThisCall("LSWI", &PPUInterpreter::LSWI, &m_interpreter, rd, ra, nb); +void PPULLVMRecompilerWorker::LSWI(u32 rd, u32 ra, u32 nb) { + InterpreterCall("LSWI", &PPUInterpreter::LSWI, rd, ra, nb); } -void PPULLVMRecompiler::LFSUX(u32 frd, u32 ra, u32 rb) { - ThisCall("LFSUX", &PPUInterpreter::LFSUX, &m_interpreter, frd, ra, rb); +void PPULLVMRecompilerWorker::LFSUX(u32 frd, u32 ra, u32 rb) { + InterpreterCall("LFSUX", &PPUInterpreter::LFSUX, frd, ra, rb); } -void PPULLVMRecompiler::SYNC(u32 l) { - ThisCall("SYNC", &PPUInterpreter::SYNC, &m_interpreter, l); +void PPULLVMRecompilerWorker::SYNC(u32 l) { + InterpreterCall("SYNC", &PPUInterpreter::SYNC, l); } -void PPULLVMRecompiler::LFDX(u32 frd, u32 ra, u32 rb) { - ThisCall("LFDX", &PPUInterpreter::LFDX, &m_interpreter, frd, ra, rb); +void PPULLVMRecompilerWorker::LFDX(u32 frd, u32 ra, u32 rb) { + InterpreterCall("LFDX", &PPUInterpreter::LFDX, frd, ra, rb); } -void PPULLVMRecompiler::LFDUX(u32 frd, u32 ra, u32 rb) { - ThisCall("LFDUX", &PPUInterpreter::LFDUX, &m_interpreter, frd, ra, rb); +void PPULLVMRecompilerWorker::LFDUX(u32 frd, u32 ra, u32 rb) { + InterpreterCall("LFDUX", &PPUInterpreter::LFDUX, frd, ra, rb); } -void PPULLVMRecompiler::STVLX(u32 vs, u32 ra, u32 rb) { - ThisCall("STVLX", &PPUInterpreter::STVLX, &m_interpreter, vs, ra, rb); +void PPULLVMRecompilerWorker::STVLX(u32 vs, u32 ra, u32 rb) { + InterpreterCall("STVLX", &PPUInterpreter::STVLX, vs, ra, rb); } -void PPULLVMRecompiler::STSWX(u32 rs, u32 ra, u32 rb) { - ThisCall("STSWX", &PPUInterpreter::STSWX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STSWX(u32 rs, u32 ra, u32 rb) { + InterpreterCall("STSWX", &PPUInterpreter::STSWX, rs, ra, rb); } -void PPULLVMRecompiler::STWBRX(u32 rs, u32 ra, u32 rb) { - ThisCall("STWBRX", &PPUInterpreter::STWBRX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STWBRX(u32 rs, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + WriteMemory(addr_i64, GetGpr(rs, 32), false); + //InterpreterCall("STWBRX", &PPUInterpreter::STWBRX, rs, ra, rb); } -void PPULLVMRecompiler::STFSX(u32 frs, u32 ra, u32 rb) { - ThisCall("STFSX", &PPUInterpreter::STFSX, &m_interpreter, frs, ra, rb); +void PPULLVMRecompilerWorker::STFSX(u32 frs, u32 ra, u32 rb) { + InterpreterCall("STFSX", &PPUInterpreter::STFSX, frs, ra, rb); } -void PPULLVMRecompiler::STVRX(u32 vs, u32 ra, u32 rb) { - ThisCall("STVRX", &PPUInterpreter::STVRX, &m_interpreter, vs, ra, rb); +void PPULLVMRecompilerWorker::STVRX(u32 vs, u32 ra, u32 rb) { + InterpreterCall("STVRX", &PPUInterpreter::STVRX, vs, ra, rb); } -void PPULLVMRecompiler::STFSUX(u32 frs, u32 ra, u32 rb) { - ThisCall("STFSUX", &PPUInterpreter::STFSUX, &m_interpreter, frs, ra, rb); +void PPULLVMRecompilerWorker::STFSUX(u32 frs, u32 ra, u32 rb) { + InterpreterCall("STFSUX", &PPUInterpreter::STFSUX, frs, ra, rb); } -void PPULLVMRecompiler::STSWI(u32 rd, u32 ra, u32 nb) { - ThisCall("STSWI", &PPUInterpreter::STSWI, &m_interpreter, rd, ra, nb); +void PPULLVMRecompilerWorker::STSWI(u32 rd, u32 ra, u32 nb) { + InterpreterCall("STSWI", &PPUInterpreter::STSWI, rd, ra, nb); } -void PPULLVMRecompiler::STFDX(u32 frs, u32 ra, u32 rb) { - ThisCall("STFDX", &PPUInterpreter::STFDX, &m_interpreter, frs, ra, rb); +void PPULLVMRecompilerWorker::STFDX(u32 frs, u32 ra, u32 rb) { + InterpreterCall("STFDX", &PPUInterpreter::STFDX, frs, ra, rb); } -void PPULLVMRecompiler::STFDUX(u32 frs, u32 ra, u32 rb) { - ThisCall("STFDUX", &PPUInterpreter::STFDUX, &m_interpreter, frs, ra, rb); +void PPULLVMRecompilerWorker::STFDUX(u32 frs, u32 ra, u32 rb) { + InterpreterCall("STFDUX", &PPUInterpreter::STFDUX, frs, ra, rb); } -void PPULLVMRecompiler::LVLXL(u32 vd, u32 ra, u32 rb) { - ThisCall("LVLXL", &PPUInterpreter::LVLXL, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVLXL(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVLXL", &PPUInterpreter::LVLXL, vd, ra, rb); } -void PPULLVMRecompiler::LHBRX(u32 rd, u32 ra, u32 rb) { - ThisCall("LHBRX", &PPUInterpreter::LHBRX, &m_interpreter, rd, ra, rb); +void PPULLVMRecompilerWorker::LHBRX(u32 rd, u32 ra, u32 rb) { + auto addr_i64 = GetGpr(rb); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i16 = ReadMemory(addr_i64, 16, false); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i16, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LHBRX", &PPUInterpreter::LHBRX, rd, ra, rb); } -void PPULLVMRecompiler::SRAW(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("SRAW", &PPUInterpreter::SRAW, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::SRAW(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("SRAW", &PPUInterpreter::SRAW, ra, rs, rb, rc); } -void PPULLVMRecompiler::SRAD(u32 ra, u32 rs, u32 rb, bool rc) { - ThisCall("SRAD", &PPUInterpreter::SRAD, &m_interpreter, ra, rs, rb, rc); +void PPULLVMRecompilerWorker::SRAD(u32 ra, u32 rs, u32 rb, bool rc) { + InterpreterCall("SRAD", &PPUInterpreter::SRAD, ra, rs, rb, rc); } -void PPULLVMRecompiler::LVRXL(u32 vd, u32 ra, u32 rb) { - ThisCall("LVRXL", &PPUInterpreter::LVRXL, &m_interpreter, vd, ra, rb); +void PPULLVMRecompilerWorker::LVRXL(u32 vd, u32 ra, u32 rb) { + InterpreterCall("LVRXL", &PPUInterpreter::LVRXL, vd, ra, rb); } -void PPULLVMRecompiler::DSS(u32 strm, u32 a) { - ThisCall("DSS", &PPUInterpreter::DSS, &m_interpreter, strm, a); +void PPULLVMRecompilerWorker::DSS(u32 strm, u32 a) { + InterpreterCall("DSS", &PPUInterpreter::DSS, strm, a); } -void PPULLVMRecompiler::SRAWI(u32 ra, u32 rs, u32 sh, bool rc) { - ThisCall("SRAWI", &PPUInterpreter::SRAWI, &m_interpreter, ra, rs, sh, rc); +void PPULLVMRecompilerWorker::SRAWI(u32 ra, u32 rs, u32 sh, bool rc) { + InterpreterCall("SRAWI", &PPUInterpreter::SRAWI, ra, rs, sh, rc); } -void PPULLVMRecompiler::SRADI1(u32 ra, u32 rs, u32 sh, bool rc) { - ThisCall("SRADI1", &PPUInterpreter::SRADI1, &m_interpreter, ra, rs, sh, rc); +void PPULLVMRecompilerWorker::SRADI1(u32 ra, u32 rs, u32 sh, bool rc) { + InterpreterCall("SRADI1", &PPUInterpreter::SRADI1, ra, rs, sh, rc); } -void PPULLVMRecompiler::SRADI2(u32 ra, u32 rs, u32 sh, bool rc) { - ThisCall("SRADI2", &PPUInterpreter::SRADI2, &m_interpreter, ra, rs, sh, rc); +void PPULLVMRecompilerWorker::SRADI2(u32 ra, u32 rs, u32 sh, bool rc) { + InterpreterCall("SRADI2", &PPUInterpreter::SRADI2, ra, rs, sh, rc); } -void PPULLVMRecompiler::EIEIO() { - ThisCall("EIEIO", &PPUInterpreter::EIEIO, &m_interpreter); +void PPULLVMRecompilerWorker::EIEIO() { + InterpreterCall("EIEIO", &PPUInterpreter::EIEIO); } -void PPULLVMRecompiler::STVLXL(u32 vs, u32 ra, u32 rb) { - ThisCall("STVLXL", &PPUInterpreter::STVLXL, &m_interpreter, vs, ra, rb); +void PPULLVMRecompilerWorker::STVLXL(u32 vs, u32 ra, u32 rb) { + InterpreterCall("STVLXL", &PPUInterpreter::STVLXL, vs, ra, rb); } -void PPULLVMRecompiler::STHBRX(u32 rs, u32 ra, u32 rb) { - ThisCall("STHBRX", &PPUInterpreter::STHBRX, &m_interpreter, rs, ra, rb); +void PPULLVMRecompilerWorker::STHBRX(u32 rs, u32 ra, u32 rb) { + InterpreterCall("STHBRX", &PPUInterpreter::STHBRX, rs, ra, rb); } -void PPULLVMRecompiler::EXTSH(u32 ra, u32 rs, bool rc) { - ThisCall("EXTSH", &PPUInterpreter::EXTSH, &m_interpreter, ra, rs, rc); +void PPULLVMRecompilerWorker::EXTSH(u32 ra, u32 rs, bool rc) { + auto rs_i16 = GetGpr(rs, 16); + auto rs_i64 = m_ir_builder->CreateSExt(rs_i16, m_ir_builder->getInt64Ty()); + SetGpr(ra, rs_i64); + + if (rc) { + SetCrFieldSignedCmp(0, rs_i64, m_ir_builder->getInt64(0)); + } + //InterpreterCall("EXTSH", &PPUInterpreter::EXTSH, ra, rs, rc); } -void PPULLVMRecompiler::STVRXL(u32 vs, u32 ra, u32 rb) { - ThisCall("STVRXL", &PPUInterpreter::STVRXL, &m_interpreter, vs, ra, rb); +void PPULLVMRecompilerWorker::STVRXL(u32 vs, u32 ra, u32 rb) { + InterpreterCall("STVRXL", &PPUInterpreter::STVRXL, vs, ra, rb); } -void PPULLVMRecompiler::EXTSB(u32 ra, u32 rs, bool rc) { - ThisCall("EXTSB", &PPUInterpreter::EXTSB, &m_interpreter, ra, rs, rc); +void PPULLVMRecompilerWorker::EXTSB(u32 ra, u32 rs, bool rc) { + auto rs_i8 = GetGpr(rs, 8); + auto rs_i64 = m_ir_builder->CreateSExt(rs_i8, m_ir_builder->getInt64Ty()); + SetGpr(ra, rs_i64); + + if (rc) { + SetCrFieldSignedCmp(0, rs_i64, m_ir_builder->getInt64(0)); + } + //InterpreterCall("EXTSB", &PPUInterpreter::EXTSB, ra, rs, rc); } -void PPULLVMRecompiler::STFIWX(u32 frs, u32 ra, u32 rb) { - ThisCall("STFIWX", &PPUInterpreter::STFIWX, &m_interpreter, frs, ra, rb); +void PPULLVMRecompilerWorker::STFIWX(u32 frs, u32 ra, u32 rb) { + InterpreterCall("STFIWX", &PPUInterpreter::STFIWX, frs, ra, rb); } -void PPULLVMRecompiler::EXTSW(u32 ra, u32 rs, bool rc) { - ThisCall("EXTSW", &PPUInterpreter::EXTSW, &m_interpreter, ra, rs, rc); +void PPULLVMRecompilerWorker::EXTSW(u32 ra, u32 rs, bool rc) { + auto rs_i32 = GetGpr(rs, 32); + auto rs_i64 = m_ir_builder->CreateSExt(rs_i32, m_ir_builder->getInt64Ty()); + SetGpr(ra, rs_i64); + + if (rc) { + SetCrFieldSignedCmp(0, rs_i64, m_ir_builder->getInt64(0)); + } + //InterpreterCall("EXTSW", &PPUInterpreter::EXTSW, ra, rs, rc); } -void PPULLVMRecompiler::ICBI(u32 ra, u32 rs) { - ThisCall("ICBI", &PPUInterpreter::ICBI, &m_interpreter, ra, rs); +void PPULLVMRecompilerWorker::ICBI(u32 ra, u32 rs) { + InterpreterCall("ICBI", &PPUInterpreter::ICBI, ra, rs); } -void PPULLVMRecompiler::DCBZ(u32 ra, u32 rb) { - ThisCall("DCBZ", &PPUInterpreter::DCBZ, &m_interpreter, ra, rb); +void PPULLVMRecompilerWorker::DCBZ(u32 ra, u32 rb) { + InterpreterCall("DCBZ", &PPUInterpreter::DCBZ, ra, rb); } -void PPULLVMRecompiler::LWZ(u32 rd, u32 ra, s32 d) { - ThisCall("LWZ", &PPUInterpreter::LWZ, &m_interpreter, rd, ra, d); +void PPULLVMRecompilerWorker::LWZ(u32 rd, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i32 = ReadMemory(addr_i64, 32); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LWZ", &PPUInterpreter::LWZ, rd, ra, d); } -void PPULLVMRecompiler::LWZU(u32 rd, u32 ra, s32 d) { - ThisCall("LWZU", &PPUInterpreter::LWZU, &m_interpreter, rd, ra, d); +void PPULLVMRecompilerWorker::LWZU(u32 rd, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i32 = ReadMemory(addr_i64, 32); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LWZU", &PPUInterpreter::LWZU, rd, ra, d); } -void PPULLVMRecompiler::LBZ(u32 rd, u32 ra, s32 d) { - ThisCall("LBZ", &PPUInterpreter::LBZ, &m_interpreter, rd, ra, d); +void PPULLVMRecompilerWorker::LBZ(u32 rd, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i8 = ReadMemory(addr_i64, 8); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i8, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LBZ", &PPUInterpreter::LBZ, rd, ra, d); } -void PPULLVMRecompiler::LBZU(u32 rd, u32 ra, s32 d) { - ThisCall("LBZU", &PPUInterpreter::LBZU, &m_interpreter, rd, ra, d); +void PPULLVMRecompilerWorker::LBZU(u32 rd, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i8 = ReadMemory(addr_i64, 8); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i8, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LBZU", &PPUInterpreter::LBZU, rd, ra, d); } -void PPULLVMRecompiler::STW(u32 rs, u32 ra, s32 d) { - ThisCall("STW", &PPUInterpreter::STW, &m_interpreter, rs, ra, d); +void PPULLVMRecompilerWorker::STW(u32 rs, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + WriteMemory(addr_i64, GetGpr(rs, 32)); + //InterpreterCall("STW", &PPUInterpreter::STW, rs, ra, d); } -void PPULLVMRecompiler::STWU(u32 rs, u32 ra, s32 d) { - ThisCall("STWU", &PPUInterpreter::STWU, &m_interpreter, rs, ra, d); +void PPULLVMRecompilerWorker::STWU(u32 rs, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + WriteMemory(addr_i64, GetGpr(rs, 32)); + SetGpr(ra, addr_i64); + //InterpreterCall("STWU", &PPUInterpreter::STWU, rs, ra, d); } -void PPULLVMRecompiler::STB(u32 rs, u32 ra, s32 d) { - ThisCall("STB", &PPUInterpreter::STB, &m_interpreter, rs, ra, d); +void PPULLVMRecompilerWorker::STB(u32 rs, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + WriteMemory(addr_i64, GetGpr(rs, 8)); + //InterpreterCall("STB", &PPUInterpreter::STB, rs, ra, d); } -void PPULLVMRecompiler::STBU(u32 rs, u32 ra, s32 d) { - ThisCall("STBU", &PPUInterpreter::STBU, &m_interpreter, rs, ra, d); +void PPULLVMRecompilerWorker::STBU(u32 rs, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + WriteMemory(addr_i64, GetGpr(rs, 8)); + SetGpr(ra, addr_i64); + //InterpreterCall("STBU", &PPUInterpreter::STBU, rs, ra, d); } -void PPULLVMRecompiler::LHZ(u32 rd, u32 ra, s32 d) { - ThisCall("LHZ", &PPUInterpreter::LHZ, &m_interpreter, rd, ra, d); +void PPULLVMRecompilerWorker::LHZ(u32 rd, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i16 = ReadMemory(addr_i64, 16); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i16, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LHZ", &PPUInterpreter::LHZ, rd, ra, d); } -void PPULLVMRecompiler::LHZU(u32 rd, u32 ra, s32 d) { - ThisCall("LHZU", &PPUInterpreter::LHZU, &m_interpreter, rd, ra, d); +void PPULLVMRecompilerWorker::LHZU(u32 rd, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i16 = ReadMemory(addr_i64, 16); + auto mem_i64 = m_ir_builder->CreateZExt(mem_i16, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LHZU", &PPUInterpreter::LHZU, rd, ra, d); } -void PPULLVMRecompiler::LHA(u32 rd, u32 ra, s32 d) { - ThisCall("LHA", &PPUInterpreter::LHA, &m_interpreter, rd, ra, d); +void PPULLVMRecompilerWorker::LHA(u32 rd, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i16 = ReadMemory(addr_i64, 16); + auto mem_i64 = m_ir_builder->CreateSExt(mem_i16, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LHA", &PPUInterpreter::LHA, rd, ra, d); } -void PPULLVMRecompiler::LHAU(u32 rd, u32 ra, s32 d) { - ThisCall("LHAU", &PPUInterpreter::LHAU, &m_interpreter, rd, ra, d); +void PPULLVMRecompilerWorker::LHAU(u32 rd, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i16 = ReadMemory(addr_i64, 16); + auto mem_i64 = m_ir_builder->CreateSExt(mem_i16, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LHAU", &PPUInterpreter::LHAU, rd, ra, d); +} + +void PPULLVMRecompilerWorker::STH(u32 rs, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + WriteMemory(addr_i64, GetGpr(rs, 16)); + //InterpreterCall("STH", &PPUInterpreter::STH, rs, ra, d); +} + +void PPULLVMRecompilerWorker::STHU(u32 rs, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + WriteMemory(addr_i64, GetGpr(rs, 16)); + SetGpr(ra, addr_i64); + //InterpreterCall("STHU", &PPUInterpreter::STHU, rs, ra, d); } -void PPULLVMRecompiler::STH(u32 rs, u32 ra, s32 d) { - ThisCall("STH", &PPUInterpreter::STH, &m_interpreter, rs, ra, d); +void PPULLVMRecompilerWorker::LMW(u32 rd, u32 ra, s32 d) { + InterpreterCall("LMW", &PPUInterpreter::LMW, rd, ra, d); } -void PPULLVMRecompiler::STHU(u32 rs, u32 ra, s32 d) { - ThisCall("STHU", &PPUInterpreter::STHU, &m_interpreter, rs, ra, d); +void PPULLVMRecompilerWorker::STMW(u32 rs, u32 ra, s32 d) { + InterpreterCall("STMW", &PPUInterpreter::STMW, rs, ra, d); } -void PPULLVMRecompiler::LMW(u32 rd, u32 ra, s32 d) { - ThisCall("LMW", &PPUInterpreter::LMW, &m_interpreter, rd, ra, d); +void PPULLVMRecompilerWorker::LFS(u32 frd, u32 ra, s32 d) { + InterpreterCall("LFS", &PPUInterpreter::LFS, frd, ra, d); } -void PPULLVMRecompiler::STMW(u32 rs, u32 ra, s32 d) { - ThisCall("STMW", &PPUInterpreter::STMW, &m_interpreter, rs, ra, d); +void PPULLVMRecompilerWorker::LFSU(u32 frd, u32 ra, s32 ds) { + InterpreterCall("LFSU", &PPUInterpreter::LFSU, frd, ra, ds); } -void PPULLVMRecompiler::LFS(u32 frd, u32 ra, s32 d) { - ThisCall("LFS", &PPUInterpreter::LFS, &m_interpreter, frd, ra, d); +void PPULLVMRecompilerWorker::LFD(u32 frd, u32 ra, s32 d) { + InterpreterCall("LFD", &PPUInterpreter::LFD, frd, ra, d); } -void PPULLVMRecompiler::LFSU(u32 frd, u32 ra, s32 ds) { - ThisCall("LFSU", &PPUInterpreter::LFSU, &m_interpreter, frd, ra, ds); +void PPULLVMRecompilerWorker::LFDU(u32 frd, u32 ra, s32 ds) { + InterpreterCall("LFDU", &PPUInterpreter::LFDU, frd, ra, ds); } -void PPULLVMRecompiler::LFD(u32 frd, u32 ra, s32 d) { - ThisCall("LFD", &PPUInterpreter::LFD, &m_interpreter, frd, ra, d); +void PPULLVMRecompilerWorker::STFS(u32 frs, u32 ra, s32 d) { + InterpreterCall("STFS", &PPUInterpreter::STFS, frs, ra, d); } -void PPULLVMRecompiler::LFDU(u32 frd, u32 ra, s32 ds) { - ThisCall("LFDU", &PPUInterpreter::LFDU, &m_interpreter, frd, ra, ds); +void PPULLVMRecompilerWorker::STFSU(u32 frs, u32 ra, s32 d) { + InterpreterCall("STFSU", &PPUInterpreter::STFSU, frs, ra, d); } -void PPULLVMRecompiler::STFS(u32 frs, u32 ra, s32 d) { - ThisCall("STFS", &PPUInterpreter::STFS, &m_interpreter, frs, ra, d); +void PPULLVMRecompilerWorker::STFD(u32 frs, u32 ra, s32 d) { + InterpreterCall("STFD", &PPUInterpreter::STFD, frs, ra, d); } -void PPULLVMRecompiler::STFSU(u32 frs, u32 ra, s32 d) { - ThisCall("STFSU", &PPUInterpreter::STFSU, &m_interpreter, frs, ra, d); +void PPULLVMRecompilerWorker::STFDU(u32 frs, u32 ra, s32 d) { + InterpreterCall("STFDU", &PPUInterpreter::STFDU, frs, ra, d); } -void PPULLVMRecompiler::STFD(u32 frs, u32 ra, s32 d) { - ThisCall("STFD", &PPUInterpreter::STFD, &m_interpreter, frs, ra, d); +void PPULLVMRecompilerWorker::LD(u32 rd, u32 ra, s32 ds) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)ds); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i64 = ReadMemory(addr_i64, 64); + SetGpr(rd, mem_i64); + //InterpreterCall("LD", &PPUInterpreter::LD, rd, ra, ds); } -void PPULLVMRecompiler::STFDU(u32 frs, u32 ra, s32 d) { - ThisCall("STFDU", &PPUInterpreter::STFDU, &m_interpreter, frs, ra, d); +void PPULLVMRecompilerWorker::LDU(u32 rd, u32 ra, s32 ds) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)ds); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + auto mem_i64 = ReadMemory(addr_i64, 64); + SetGpr(rd, mem_i64); + SetGpr(ra, addr_i64); + //InterpreterCall("LDU", &PPUInterpreter::LDU, rd, ra, ds); } -void PPULLVMRecompiler::LD(u32 rd, u32 ra, s32 ds) { - ThisCall("LD", &PPUInterpreter::LD, &m_interpreter, rd, ra, ds); +void PPULLVMRecompilerWorker::LWA(u32 rd, u32 ra, s32 ds) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)ds); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + auto mem_i32 = ReadMemory(addr_i64, 32); + auto mem_i64 = m_ir_builder->CreateSExt(mem_i32, m_ir_builder->getInt64Ty()); + SetGpr(rd, mem_i64); + //InterpreterCall("LWA", &PPUInterpreter::LWA, rd, ra, ds); } -void PPULLVMRecompiler::LDU(u32 rd, u32 ra, s32 ds) { - ThisCall("LDU", &PPUInterpreter::LDU, &m_interpreter, rd, ra, ds); +void PPULLVMRecompilerWorker::FDIVS(u32 frd, u32 fra, u32 frb, bool rc) { + InterpreterCall("FDIVS", &PPUInterpreter::FDIVS, frd, fra, frb, rc); } -void PPULLVMRecompiler::LWA(u32 rd, u32 ra, s32 ds) { - ThisCall("LWA", &PPUInterpreter::LWA, &m_interpreter, rd, ra, ds); +void PPULLVMRecompilerWorker::FSUBS(u32 frd, u32 fra, u32 frb, bool rc) { + InterpreterCall("FSUBS", &PPUInterpreter::FSUBS, frd, fra, frb, rc); } -void PPULLVMRecompiler::FDIVS(u32 frd, u32 fra, u32 frb, bool rc) { - ThisCall("FDIVS", &PPUInterpreter::FDIVS, &m_interpreter, frd, fra, frb, rc); +void PPULLVMRecompilerWorker::FADDS(u32 frd, u32 fra, u32 frb, bool rc) { + InterpreterCall("FADDS", &PPUInterpreter::FADDS, frd, fra, frb, rc); } -void PPULLVMRecompiler::FSUBS(u32 frd, u32 fra, u32 frb, bool rc) { - ThisCall("FSUBS", &PPUInterpreter::FSUBS, &m_interpreter, frd, fra, frb, rc); +void PPULLVMRecompilerWorker::FSQRTS(u32 frd, u32 frb, bool rc) { + InterpreterCall("FSQRTS", &PPUInterpreter::FSQRTS, frd, frb, rc); } -void PPULLVMRecompiler::FADDS(u32 frd, u32 fra, u32 frb, bool rc) { - ThisCall("FADDS", &PPUInterpreter::FADDS, &m_interpreter, frd, fra, frb, rc); +void PPULLVMRecompilerWorker::FRES(u32 frd, u32 frb, bool rc) { + InterpreterCall("FRES", &PPUInterpreter::FRES, frd, frb, rc); } -void PPULLVMRecompiler::FSQRTS(u32 frd, u32 frb, bool rc) { - ThisCall("FSQRTS", &PPUInterpreter::FSQRTS, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FMULS(u32 frd, u32 fra, u32 frc, bool rc) { + InterpreterCall("FMULS", &PPUInterpreter::FMULS, frd, fra, frc, rc); } -void PPULLVMRecompiler::FRES(u32 frd, u32 frb, bool rc) { - ThisCall("FRES", &PPUInterpreter::FRES, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + InterpreterCall("FMADDS", &PPUInterpreter::FMADDS, frd, fra, frc, frb, rc); } -void PPULLVMRecompiler::FMULS(u32 frd, u32 fra, u32 frc, bool rc) { - ThisCall("FMULS", &PPUInterpreter::FMULS, &m_interpreter, frd, fra, frc, rc); +void PPULLVMRecompilerWorker::FMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + InterpreterCall("FMSUBS", &PPUInterpreter::FMSUBS, frd, fra, frc, frb, rc); } -void PPULLVMRecompiler::FMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - ThisCall("FMADDS", &PPUInterpreter::FMADDS, &m_interpreter, frd, fra, frc, frb, rc); +void PPULLVMRecompilerWorker::FNMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + InterpreterCall("FNMSUBS", &PPUInterpreter::FNMSUBS, frd, fra, frc, frb, rc); } -void PPULLVMRecompiler::FMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - ThisCall("FMSUBS", &PPUInterpreter::FMSUBS, &m_interpreter, frd, fra, frc, frb, rc); +void PPULLVMRecompilerWorker::FNMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + InterpreterCall("FNMADDS", &PPUInterpreter::FNMADDS, frd, fra, frc, frb, rc); } -void PPULLVMRecompiler::FNMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - ThisCall("FNMSUBS", &PPUInterpreter::FNMSUBS, &m_interpreter, frd, fra, frc, frb, rc); +void PPULLVMRecompilerWorker::STD(u32 rs, u32 ra, s32 d) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); + if (ra) { + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + } + + WriteMemory(addr_i64, GetGpr(rs, 64)); + //InterpreterCall("STD", &PPUInterpreter::STD, rs, ra, d); +} + +void PPULLVMRecompilerWorker::STDU(u32 rs, u32 ra, s32 ds) { + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)ds); + auto ra_i64 = GetGpr(ra); + addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + + WriteMemory(addr_i64, GetGpr(rs, 64)); + SetGpr(ra, addr_i64); + //InterpreterCall("STDU", &PPUInterpreter::STDU, rs, ra, ds); } -void PPULLVMRecompiler::FNMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - ThisCall("FNMADDS", &PPUInterpreter::FNMADDS, &m_interpreter, frd, fra, frc, frb, rc); +void PPULLVMRecompilerWorker::MTFSB1(u32 crbd, bool rc) { + InterpreterCall("MTFSB1", &PPUInterpreter::MTFSB1, crbd, rc); } -void PPULLVMRecompiler::STD(u32 rs, u32 ra, s32 d) { - ThisCall("STD", &PPUInterpreter::STD, &m_interpreter, rs, ra, d); +void PPULLVMRecompilerWorker::MCRFS(u32 crbd, u32 crbs) { + InterpreterCall("MCRFS", &PPUInterpreter::MCRFS, crbd, crbs); } -void PPULLVMRecompiler::STDU(u32 rs, u32 ra, s32 ds) { - ThisCall("STDU", &PPUInterpreter::STDU, &m_interpreter, rs, ra, ds); +void PPULLVMRecompilerWorker::MTFSB0(u32 crbd, bool rc) { + InterpreterCall("MTFSB0", &PPUInterpreter::MTFSB0, crbd, rc); } -void PPULLVMRecompiler::MTFSB1(u32 crbd, bool rc) { - ThisCall("MTFSB1", &PPUInterpreter::MTFSB1, &m_interpreter, crbd, rc); +void PPULLVMRecompilerWorker::MTFSFI(u32 crfd, u32 i, bool rc) { + InterpreterCall("MTFSFI", &PPUInterpreter::MTFSFI, crfd, i, rc); } -void PPULLVMRecompiler::MCRFS(u32 crbd, u32 crbs) { - ThisCall("MCRFS", &PPUInterpreter::MCRFS, &m_interpreter, crbd, crbs); +void PPULLVMRecompilerWorker::MFFS(u32 frd, bool rc) { + InterpreterCall("MFFS", &PPUInterpreter::MFFS, frd, rc); } -void PPULLVMRecompiler::MTFSB0(u32 crbd, bool rc) { - ThisCall("MTFSB0", &PPUInterpreter::MTFSB0, &m_interpreter, crbd, rc); +void PPULLVMRecompilerWorker::MTFSF(u32 flm, u32 frb, bool rc) { + InterpreterCall("MTFSF", &PPUInterpreter::MTFSF, flm, frb, rc); } -void PPULLVMRecompiler::MTFSFI(u32 crfd, u32 i, bool rc) { - ThisCall("MTFSFI", &PPUInterpreter::MTFSFI, &m_interpreter, crfd, i, rc); +void PPULLVMRecompilerWorker::FCMPU(u32 crfd, u32 fra, u32 frb) { + InterpreterCall("FCMPU", &PPUInterpreter::FCMPU, crfd, fra, frb); } -void PPULLVMRecompiler::MFFS(u32 frd, bool rc) { - ThisCall("MFFS", &PPUInterpreter::MFFS, &m_interpreter, frd, rc); +void PPULLVMRecompilerWorker::FRSP(u32 frd, u32 frb, bool rc) { + InterpreterCall("FRSP", &PPUInterpreter::FRSP, frd, frb, rc); } -void PPULLVMRecompiler::MTFSF(u32 flm, u32 frb, bool rc) { - ThisCall("MTFSF", &PPUInterpreter::MTFSF, &m_interpreter, flm, frb, rc); +void PPULLVMRecompilerWorker::FCTIW(u32 frd, u32 frb, bool rc) { + InterpreterCall("FCTIW", &PPUInterpreter::FCTIW, frd, frb, rc); } -void PPULLVMRecompiler::FCMPU(u32 crfd, u32 fra, u32 frb) { - ThisCall("FCMPU", &PPUInterpreter::FCMPU, &m_interpreter, crfd, fra, frb); +void PPULLVMRecompilerWorker::FCTIWZ(u32 frd, u32 frb, bool rc) { + InterpreterCall("FCTIWZ", &PPUInterpreter::FCTIWZ, frd, frb, rc); } -void PPULLVMRecompiler::FRSP(u32 frd, u32 frb, bool rc) { - ThisCall("FRSP", &PPUInterpreter::FRSP, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FDIV(u32 frd, u32 fra, u32 frb, bool rc) { + InterpreterCall("FDIV", &PPUInterpreter::FDIV, frd, fra, frb, rc); } -void PPULLVMRecompiler::FCTIW(u32 frd, u32 frb, bool rc) { - ThisCall("FCTIW", &PPUInterpreter::FCTIW, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FSUB(u32 frd, u32 fra, u32 frb, bool rc) { + InterpreterCall("FSUB", &PPUInterpreter::FSUB, frd, fra, frb, rc); } -void PPULLVMRecompiler::FCTIWZ(u32 frd, u32 frb, bool rc) { - ThisCall("FCTIWZ", &PPUInterpreter::FCTIWZ, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FADD(u32 frd, u32 fra, u32 frb, bool rc) { + InterpreterCall("FADD", &PPUInterpreter::FADD, frd, fra, frb, rc); } -void PPULLVMRecompiler::FDIV(u32 frd, u32 fra, u32 frb, bool rc) { - ThisCall("FDIV", &PPUInterpreter::FDIV, &m_interpreter, frd, fra, frb, rc); +void PPULLVMRecompilerWorker::FSQRT(u32 frd, u32 frb, bool rc) { + InterpreterCall("FSQRT", &PPUInterpreter::FSQRT, frd, frb, rc); } -void PPULLVMRecompiler::FSUB(u32 frd, u32 fra, u32 frb, bool rc) { - ThisCall("FSUB", &PPUInterpreter::FSUB, &m_interpreter, frd, fra, frb, rc); +void PPULLVMRecompilerWorker::FSEL(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + InterpreterCall("FSEL", &PPUInterpreter::FSEL, frd, fra, frc, frb, rc); } -void PPULLVMRecompiler::FADD(u32 frd, u32 fra, u32 frb, bool rc) { - ThisCall("FADD", &PPUInterpreter::FADD, &m_interpreter, frd, fra, frb, rc); +void PPULLVMRecompilerWorker::FMUL(u32 frd, u32 fra, u32 frc, bool rc) { + InterpreterCall("FMUL", &PPUInterpreter::FMUL, frd, fra, frc, rc); } -void PPULLVMRecompiler::FSQRT(u32 frd, u32 frb, bool rc) { - ThisCall("FSQRT", &PPUInterpreter::FSQRT, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FRSQRTE(u32 frd, u32 frb, bool rc) { + InterpreterCall("FRSQRTE", &PPUInterpreter::FRSQRTE, frd, frb, rc); } -void PPULLVMRecompiler::FSEL(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - ThisCall("FSEL", &PPUInterpreter::FSEL, &m_interpreter, frd, fra, frc, frb, rc); +void PPULLVMRecompilerWorker::FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + InterpreterCall("FMSUB", &PPUInterpreter::FMSUB, frd, fra, frc, frb, rc); } -void PPULLVMRecompiler::FMUL(u32 frd, u32 fra, u32 frc, bool rc) { - ThisCall("FMUL", &PPUInterpreter::FMUL, &m_interpreter, frd, fra, frc, rc); +void PPULLVMRecompilerWorker::FMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + InterpreterCall("FMADD", &PPUInterpreter::FMADD, frd, fra, frc, frb, rc); } -void PPULLVMRecompiler::FRSQRTE(u32 frd, u32 frb, bool rc) { - ThisCall("FRSQRTE", &PPUInterpreter::FRSQRTE, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FNMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + InterpreterCall("FNMSUB", &PPUInterpreter::FNMSUB, frd, fra, frc, frb, rc); } -void PPULLVMRecompiler::FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - ThisCall("FMSUB", &PPUInterpreter::FMSUB, &m_interpreter, frd, fra, frc, frb, rc); +void PPULLVMRecompilerWorker::FNMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { + InterpreterCall("FNMADD", &PPUInterpreter::FNMADD, frd, fra, frc, frb, rc); } -void PPULLVMRecompiler::FMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - ThisCall("FMADD", &PPUInterpreter::FMADD, &m_interpreter, frd, fra, frc, frb, rc); +void PPULLVMRecompilerWorker::FCMPO(u32 crfd, u32 fra, u32 frb) { + InterpreterCall("FCMPO", &PPUInterpreter::FCMPO, crfd, fra, frb); } -void PPULLVMRecompiler::FNMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - ThisCall("FNMSUB", &PPUInterpreter::FNMSUB, &m_interpreter, frd, fra, frc, frb, rc); +void PPULLVMRecompilerWorker::FNEG(u32 frd, u32 frb, bool rc) { + InterpreterCall("FNEG", &PPUInterpreter::FNEG, frd, frb, rc); } -void PPULLVMRecompiler::FNMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - ThisCall("FNMADD", &PPUInterpreter::FNMADD, &m_interpreter, frd, fra, frc, frb, rc); +void PPULLVMRecompilerWorker::FMR(u32 frd, u32 frb, bool rc) { + InterpreterCall("FMR", &PPUInterpreter::FMR, frd, frb, rc); } -void PPULLVMRecompiler::FCMPO(u32 crfd, u32 fra, u32 frb) { - ThisCall("FCMPO", &PPUInterpreter::FCMPO, &m_interpreter, crfd, fra, frb); +void PPULLVMRecompilerWorker::FNABS(u32 frd, u32 frb, bool rc) { + InterpreterCall("FNABS", &PPUInterpreter::FNABS, frd, frb, rc); } -void PPULLVMRecompiler::FNEG(u32 frd, u32 frb, bool rc) { - ThisCall("FNEG", &PPUInterpreter::FNEG, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FABS(u32 frd, u32 frb, bool rc) { + InterpreterCall("FABS", &PPUInterpreter::FABS, frd, frb, rc); } -void PPULLVMRecompiler::FMR(u32 frd, u32 frb, bool rc) { - ThisCall("FMR", &PPUInterpreter::FMR, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FCTID(u32 frd, u32 frb, bool rc) { + InterpreterCall("FCTID", &PPUInterpreter::FCTID, frd, frb, rc); } -void PPULLVMRecompiler::FNABS(u32 frd, u32 frb, bool rc) { - ThisCall("FNABS", &PPUInterpreter::FNABS, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FCTIDZ(u32 frd, u32 frb, bool rc) { + InterpreterCall("FCTIDZ", &PPUInterpreter::FCTIDZ, frd, frb, rc); } -void PPULLVMRecompiler::FABS(u32 frd, u32 frb, bool rc) { - ThisCall("FABS", &PPUInterpreter::FABS, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::FCFID(u32 frd, u32 frb, bool rc) { + InterpreterCall("FCFID", &PPUInterpreter::FCFID, frd, frb, rc); } -void PPULLVMRecompiler::FCTID(u32 frd, u32 frb, bool rc) { - ThisCall("FCTID", &PPUInterpreter::FCTID, &m_interpreter, frd, frb, rc); +void PPULLVMRecompilerWorker::UNK(const u32 code, const u32 opcode, const u32 gcode) { + //InterpreterCall("UNK", &PPUInterpreter::UNK, code, opcode, gcode); } -void PPULLVMRecompiler::FCTIDZ(u32 frd, u32 frb, bool rc) { - ThisCall("FCTIDZ", &PPUInterpreter::FCTIDZ, &m_interpreter, frd, frb, rc); +Value * PPULLVMRecompilerWorker::GetPPUState() { + return m_function->arg_begin(); } -void PPULLVMRecompiler::FCFID(u32 frd, u32 frb, bool rc) { - ThisCall("FCFID", &PPUInterpreter::FCFID, &m_interpreter, frd, frb, rc); +Value * PPULLVMRecompilerWorker::GetBaseAddress() { + auto i = m_function->arg_begin(); + i++; + return i; } -void PPULLVMRecompiler::UNK(const u32 code, const u32 opcode, const u32 gcode) { - //ThisCall("UNK", &PPUInterpreter::UNK, &m_interpreter, code, opcode, gcode); +Value * PPULLVMRecompilerWorker::GetInterpreter() { + auto i = m_function->arg_begin(); + i++; + i++; + return i; } -Value * PPULLVMRecompiler::GetBit(Value * val, u32 n) { +Value * PPULLVMRecompilerWorker::GetBit(Value * val, u32 n) { Value * bit; if (val->getType()->isIntegerTy(32)) { - bit = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_bmi_pext_32), val, s_ir_builder->getInt32(1 << (31- n))); + bit = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_bmi_pext_32), val, m_ir_builder->getInt32(1 << (31- n))); } else if (val->getType()->isIntegerTy(64)) { - bit = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_bmi_pext_64), val, s_ir_builder->getInt64(1 << (63 - n))); + bit = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_bmi_pext_64), val, m_ir_builder->getInt64((u64)1 << (63 - n))); } else { if (val->getType()->getIntegerBitWidth() != (n + 1)) { - bit = s_ir_builder->CreateLShr(val, val->getType()->getIntegerBitWidth() - n - 1); + bit = m_ir_builder->CreateLShr(val, val->getType()->getIntegerBitWidth() - n - 1); } - bit = s_ir_builder->CreateAnd(val, 1); + bit = m_ir_builder->CreateAnd(val, 1); } return bit; } -Value * PPULLVMRecompiler::ClrBit(Value * val, u32 n) { - return s_ir_builder->CreateAnd(val, ~(1 << (val->getType()->getIntegerBitWidth() - n - 1))); +Value * PPULLVMRecompilerWorker::ClrBit(Value * val, u32 n) { + return m_ir_builder->CreateAnd(val, ~((u64)1 << (val->getType()->getIntegerBitWidth() - n - 1))); } -Value * PPULLVMRecompiler::SetBit(Value * val, u32 n, Value * bit, bool doClear) { +Value * PPULLVMRecompilerWorker::SetBit(Value * val, u32 n, Value * bit, bool doClear) { if (doClear) { val = ClrBit(val, n); } if (bit->getType()->getIntegerBitWidth() < val->getType()->getIntegerBitWidth()) { - bit = s_ir_builder->CreateZExt(bit, val->getType()); + bit = m_ir_builder->CreateZExt(bit, val->getType()); } else if (bit->getType()->getIntegerBitWidth() > val->getType()->getIntegerBitWidth()) { - bit = s_ir_builder->CreateTrunc(bit, val->getType()); + bit = m_ir_builder->CreateTrunc(bit, val->getType()); } if (val->getType()->getIntegerBitWidth() != (n + 1)) { - bit = s_ir_builder->CreateShl(bit, bit->getType()->getIntegerBitWidth() - n - 1); + bit = m_ir_builder->CreateShl(bit, bit->getType()->getIntegerBitWidth() - n - 1); } - return s_ir_builder->CreateOr(val, bit); + return m_ir_builder->CreateOr(val, bit); } -Value * PPULLVMRecompiler::GetNibble(Value * val, u32 n) { +Value * PPULLVMRecompilerWorker::GetNibble(Value * val, u32 n) { Value * nibble; if (val->getType()->isIntegerTy(32)) { - nibble = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_bmi_pext_32), val, s_ir_builder->getInt32(0xF << ((7 - n) * 4))); + nibble = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_bmi_pext_32), val, m_ir_builder->getInt32((u64)0xF << ((7 - n) * 4))); } else if (val->getType()->isIntegerTy(64)) { - nibble = s_ir_builder->CreateCall2(Intrinsic::getDeclaration(s_module, Intrinsic::x86_bmi_pext_64), val, s_ir_builder->getInt64(0xF << ((15 - n) * 4))); + nibble = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::x86_bmi_pext_64), val, m_ir_builder->getInt64((u64)0xF << ((15 - n) * 4))); } else { if ((val->getType()->getIntegerBitWidth() >> 2) != (n + 1)) { - nibble = s_ir_builder->CreateLShr(val, (((val->getType()->getIntegerBitWidth() >> 2) - 1) - n) * 4); + nibble = m_ir_builder->CreateLShr(val, (((val->getType()->getIntegerBitWidth() >> 2) - 1) - n) * 4); } - nibble = s_ir_builder->CreateAnd(val, 0xF); + nibble = m_ir_builder->CreateAnd(val, 0xF); } return nibble; } -Value * PPULLVMRecompiler::ClrNibble(Value * val, u32 n) { - return s_ir_builder->CreateAnd(val, ~(0xF << ((((val->getType()->getIntegerBitWidth() >> 2) - 1) - n) * 4))); +Value * PPULLVMRecompilerWorker::ClrNibble(Value * val, u32 n) { + return m_ir_builder->CreateAnd(val, ~((u64)0xF << ((((val->getType()->getIntegerBitWidth() >> 2) - 1) - n) * 4))); } -Value * PPULLVMRecompiler::SetNibble(Value * val, u32 n, Value * nibble, bool doClear) { +Value * PPULLVMRecompilerWorker::SetNibble(Value * val, u32 n, Value * nibble, bool doClear) { if (doClear) { val = ClrNibble(val, n); } if (nibble->getType()->getIntegerBitWidth() < val->getType()->getIntegerBitWidth()) { - nibble = s_ir_builder->CreateZExt(nibble, val->getType()); + nibble = m_ir_builder->CreateZExt(nibble, val->getType()); } else if (nibble->getType()->getIntegerBitWidth() > val->getType()->getIntegerBitWidth()) { - nibble = s_ir_builder->CreateTrunc(nibble, val->getType()); + nibble = m_ir_builder->CreateTrunc(nibble, val->getType()); } if ((val->getType()->getIntegerBitWidth() >> 2) != (n + 1)) { - nibble = s_ir_builder->CreateShl(nibble, (((val->getType()->getIntegerBitWidth() >> 2) - 1) - n) * 4); + nibble = m_ir_builder->CreateShl(nibble, (((val->getType()->getIntegerBitWidth() >> 2) - 1) - n) * 4); } - return s_ir_builder->CreateOr(val, nibble); + return m_ir_builder->CreateOr(val, nibble); } -Value * PPULLVMRecompiler::SetNibble(Value * val, u32 n, Value * b0, Value * b1, Value * b2, Value * b3, bool doClear) { +Value * PPULLVMRecompilerWorker::SetNibble(Value * val, u32 n, Value * b0, Value * b1, Value * b2, Value * b3, bool doClear) { if (doClear) { val = ClrNibble(val, n); } @@ -2199,189 +2582,315 @@ Value * PPULLVMRecompiler::SetNibble(Value * val, u32 n, Value * b0, Value * b1, return val; } -Value * PPULLVMRecompiler::GetPc() { - auto pc_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, PC)); - auto pc_i64_ptr = s_ir_builder->CreateBitCast(pc_i8_ptr, s_ir_builder->getInt64Ty()->getPointerTo()); - return s_ir_builder->CreateLoad(pc_i64_ptr); +Value * PPULLVMRecompilerWorker::GetPc() { + auto pc_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, PC)); + auto pc_i64_ptr = m_ir_builder->CreateBitCast(pc_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + return m_ir_builder->CreateLoad(pc_i64_ptr); } -void PPULLVMRecompiler::SetPc(Value * val_i64) { - auto pc_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, PC)); - auto pc_i64_ptr = s_ir_builder->CreateBitCast(pc_i8_ptr, s_ir_builder->getInt64Ty()->getPointerTo()); - s_ir_builder->CreateStore(val_i64, pc_i64_ptr); +void PPULLVMRecompilerWorker::SetPc(Value * val_i64) { + auto pc_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, PC)); + auto pc_i64_ptr = m_ir_builder->CreateBitCast(pc_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + m_ir_builder->CreateStore(val_i64, pc_i64_ptr); } -Value * PPULLVMRecompiler::GetGpr(u32 r) { - auto r_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, GPR[r])); - auto r_i64_ptr = s_ir_builder->CreateBitCast(r_i8_ptr, s_ir_builder->getInt64Ty()->getPointerTo()); - return s_ir_builder->CreateLoad(r_i64_ptr); +Value * PPULLVMRecompilerWorker::GetGpr(u32 r, u32 num_bits) { + auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, GPR[r])); + auto r_ix_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getIntNTy(num_bits)->getPointerTo()); + return m_ir_builder->CreateLoad(r_ix_ptr); } -void PPULLVMRecompiler::SetGpr(u32 r, Value * val_x64) { - auto r_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, GPR[r])); - auto r_i64_ptr = s_ir_builder->CreateBitCast(r_i8_ptr, s_ir_builder->getInt64Ty()->getPointerTo()); - auto val_i64 = s_ir_builder->CreateBitCast(val_x64, s_ir_builder->getInt64Ty()); - s_ir_builder->CreateStore(val_i64, r_i64_ptr); +void PPULLVMRecompilerWorker::SetGpr(u32 r, Value * val_x64) { + auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, GPR[r])); + auto r_i64_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty()); + m_ir_builder->CreateStore(val_i64, r_i64_ptr); } -Value * PPULLVMRecompiler::GetCr() { - auto cr_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, CR)); - auto cr_i32_ptr = s_ir_builder->CreateBitCast(cr_i8_ptr, s_ir_builder->getInt32Ty()->getPointerTo()); - return s_ir_builder->CreateLoad(cr_i32_ptr); +Value * PPULLVMRecompilerWorker::GetCr() { + auto cr_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, CR)); + auto cr_i32_ptr = m_ir_builder->CreateBitCast(cr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); + return m_ir_builder->CreateLoad(cr_i32_ptr); } -Value * PPULLVMRecompiler::GetCrField(u32 n) { +Value * PPULLVMRecompilerWorker::GetCrField(u32 n) { return GetNibble(GetCr(), n); } -void PPULLVMRecompiler::SetCr(Value * val_x32) { - auto val_i32 = s_ir_builder->CreateBitCast(val_x32, s_ir_builder->getInt32Ty()); - auto cr_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, CR)); - auto cr_i32_ptr = s_ir_builder->CreateBitCast(cr_i8_ptr, s_ir_builder->getInt32Ty()->getPointerTo()); - s_ir_builder->CreateStore(val_i32, cr_i32_ptr); +void PPULLVMRecompilerWorker::SetCr(Value * val_x32) { + auto val_i32 = m_ir_builder->CreateBitCast(val_x32, m_ir_builder->getInt32Ty()); + auto cr_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, CR)); + auto cr_i32_ptr = m_ir_builder->CreateBitCast(cr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); + m_ir_builder->CreateStore(val_i32, cr_i32_ptr); } -void PPULLVMRecompiler::SetCrField(u32 n, Value * field) { +void PPULLVMRecompilerWorker::SetCrField(u32 n, Value * field) { SetCr(SetNibble(GetCr(), n, field)); } -void PPULLVMRecompiler::SetCrField(u32 n, Value * b0, Value * b1, Value * b2, Value * b3) { +void PPULLVMRecompilerWorker::SetCrField(u32 n, Value * b0, Value * b1, Value * b2, Value * b3) { SetCr(SetNibble(GetCr(), n, b0, b1, b2, b3)); } -void PPULLVMRecompiler::SetCrFieldSignedCmp(u32 n, Value * a, Value * b) { - auto lt_i1 = s_ir_builder->CreateICmpSLT(a, b); - auto gt_i1 = s_ir_builder->CreateICmpSGT(a, b); - auto eq_i1 = s_ir_builder->CreateICmpEQ(a, b); +void PPULLVMRecompilerWorker::SetCrFieldSignedCmp(u32 n, Value * a, Value * b) { + auto lt_i1 = m_ir_builder->CreateICmpSLT(a, b); + auto gt_i1 = m_ir_builder->CreateICmpSGT(a, b); + auto eq_i1 = m_ir_builder->CreateICmpEQ(a, b); auto cr_i32 = GetCr(); cr_i32 = SetNibble(cr_i32, n, lt_i1, gt_i1, eq_i1, GetXerSo()); SetCr(cr_i32); } -void PPULLVMRecompiler::SetCrFieldUnsignedCmp(u32 n, Value * a, Value * b) { - auto lt_i1 = s_ir_builder->CreateICmpULT(a, b); - auto gt_i1 = s_ir_builder->CreateICmpUGT(a, b); - auto eq_i1 = s_ir_builder->CreateICmpEQ(a, b); +void PPULLVMRecompilerWorker::SetCrFieldUnsignedCmp(u32 n, Value * a, Value * b) { + auto lt_i1 = m_ir_builder->CreateICmpULT(a, b); + auto gt_i1 = m_ir_builder->CreateICmpUGT(a, b); + auto eq_i1 = m_ir_builder->CreateICmpEQ(a, b); auto cr_i32 = GetCr(); cr_i32 = SetNibble(cr_i32, n, lt_i1, gt_i1, eq_i1, GetXerSo()); SetCr(cr_i32); } -void PPULLVMRecompiler::SetCr6AfterVectorCompare(u32 vr) { +void PPULLVMRecompilerWorker::SetCr6AfterVectorCompare(u32 vr) { auto vr_v16i8 = GetVrAsIntVec(vr, 8); - auto vr_mask_i32 = s_ir_builder->CreateCall(Intrinsic::getDeclaration(s_module, Intrinsic::x86_sse2_pmovmskb_128), vr_v16i8); - auto cmp0_i1 = s_ir_builder->CreateICmpEQ(vr_mask_i32, s_ir_builder->getInt32(0)); - auto cmp1_i1 = s_ir_builder->CreateICmpEQ(vr_mask_i32, s_ir_builder->getInt32(0xFFFF)); + auto vr_mask_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::x86_sse2_pmovmskb_128), vr_v16i8); + auto cmp0_i1 = m_ir_builder->CreateICmpEQ(vr_mask_i32, m_ir_builder->getInt32(0)); + auto cmp1_i1 = m_ir_builder->CreateICmpEQ(vr_mask_i32, m_ir_builder->getInt32(0xFFFF)); auto cr_i32 = GetCr(); cr_i32 = SetNibble(cr_i32, 6, cmp1_i1, nullptr, cmp0_i1, nullptr); SetCr(cr_i32); } -Value * PPULLVMRecompiler::GetXer() { - auto xer_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, XER)); - auto xer_i64_ptr = s_ir_builder->CreateBitCast(xer_i8_ptr, s_ir_builder->getInt64Ty()->getPointerTo()); - return s_ir_builder->CreateLoad(xer_i64_ptr); +Value * PPULLVMRecompilerWorker::GetXer() { + auto xer_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, XER)); + auto xer_i64_ptr = m_ir_builder->CreateBitCast(xer_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + return m_ir_builder->CreateLoad(xer_i64_ptr); } -Value * PPULLVMRecompiler::GetXerCa() { +Value * PPULLVMRecompilerWorker::GetXerCa() { return GetBit(GetXer(), 34); } -Value * PPULLVMRecompiler::GetXerSo() { +Value * PPULLVMRecompilerWorker::GetXerSo() { return GetBit(GetXer(), 32); } -void PPULLVMRecompiler::SetXer(Value * val_x64) { - auto val_i64 = s_ir_builder->CreateBitCast(val_x64, s_ir_builder->getInt64Ty()); - auto xer_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, XER)); - auto xer_i64_ptr = s_ir_builder->CreateBitCast(xer_i8_ptr, s_ir_builder->getInt64Ty()->getPointerTo()); - s_ir_builder->CreateStore(val_i64, xer_i64_ptr); +void PPULLVMRecompilerWorker::SetXer(Value * val_x64) { + auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty()); + auto xer_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, XER)); + auto xer_i64_ptr = m_ir_builder->CreateBitCast(xer_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + m_ir_builder->CreateStore(val_i64, xer_i64_ptr); } -void PPULLVMRecompiler::SetXerCa(Value * ca) { +void PPULLVMRecompilerWorker::SetXerCa(Value * ca) { auto xer_i64 = GetXer(); xer_i64 = SetBit(xer_i64, 34, ca); SetXer(xer_i64); } -void PPULLVMRecompiler::SetXerSo(Value * so) { +void PPULLVMRecompilerWorker::SetXerSo(Value * so) { auto xer_i64 = GetXer(); xer_i64 = SetBit(xer_i64, 32, so); SetXer(xer_i64); } -Value * PPULLVMRecompiler::GetVscr() { - auto vscr_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, VSCR)); - auto vscr_i32_ptr = s_ir_builder->CreateBitCast(vscr_i8_ptr, s_ir_builder->getInt32Ty()->getPointerTo()); - return s_ir_builder->CreateLoad(vscr_i32_ptr); +Value * PPULLVMRecompilerWorker::GetVscr() { + auto vscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, VSCR)); + auto vscr_i32_ptr = m_ir_builder->CreateBitCast(vscr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); + return m_ir_builder->CreateLoad(vscr_i32_ptr); } -void PPULLVMRecompiler::SetVscr(Value * val_x32) { - auto val_i32 = s_ir_builder->CreateBitCast(val_x32, s_ir_builder->getInt32Ty()); - auto vscr_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, VSCR)); - auto vscr_i32_ptr = s_ir_builder->CreateBitCast(vscr_i8_ptr, s_ir_builder->getInt32Ty()->getPointerTo()); - s_ir_builder->CreateStore(val_i32, vscr_i32_ptr); +void PPULLVMRecompilerWorker::SetVscr(Value * val_x32) { + auto val_i32 = m_ir_builder->CreateBitCast(val_x32, m_ir_builder->getInt32Ty()); + auto vscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, VSCR)); + auto vscr_i32_ptr = m_ir_builder->CreateBitCast(vscr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); + m_ir_builder->CreateStore(val_i32, vscr_i32_ptr); } -Value * PPULLVMRecompiler::GetVrAsIntVec(u32 vr, u32 vec_elt_num_bits) { - auto vr_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, VPR[vr])); - auto vr_i128_ptr = s_ir_builder->CreateBitCast(vr_i8_ptr, s_ir_builder->getIntNTy(128)->getPointerTo()); - auto vr_vec_ptr = s_ir_builder->CreateBitCast(vr_i128_ptr, VectorType::get(s_ir_builder->getIntNTy(vec_elt_num_bits), 128 / vec_elt_num_bits)->getPointerTo()); - return s_ir_builder->CreateLoad(vr_vec_ptr); +Value * PPULLVMRecompilerWorker::GetVrAsIntVec(u32 vr, u32 vec_elt_num_bits) { + auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, VPR[vr])); + auto vr_i128_ptr = m_ir_builder->CreateBitCast(vr_i8_ptr, m_ir_builder->getIntNTy(128)->getPointerTo()); + auto vr_vec_ptr = m_ir_builder->CreateBitCast(vr_i128_ptr, VectorType::get(m_ir_builder->getIntNTy(vec_elt_num_bits), 128 / vec_elt_num_bits)->getPointerTo()); + return m_ir_builder->CreateLoad(vr_vec_ptr); } -Value * PPULLVMRecompiler::GetVrAsFloatVec(u32 vr) { - auto vr_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, VPR[vr])); - auto vr_i128_ptr = s_ir_builder->CreateBitCast(vr_i8_ptr, s_ir_builder->getIntNTy(128)->getPointerTo()); - auto vr_v4f32_ptr = s_ir_builder->CreateBitCast(vr_i128_ptr, VectorType::get(s_ir_builder->getFloatTy(), 4)->getPointerTo()); - return s_ir_builder->CreateLoad(vr_v4f32_ptr); +Value * PPULLVMRecompilerWorker::GetVrAsFloatVec(u32 vr) { + auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, VPR[vr])); + auto vr_i128_ptr = m_ir_builder->CreateBitCast(vr_i8_ptr, m_ir_builder->getIntNTy(128)->getPointerTo()); + auto vr_v4f32_ptr = m_ir_builder->CreateBitCast(vr_i128_ptr, VectorType::get(m_ir_builder->getFloatTy(), 4)->getPointerTo()); + return m_ir_builder->CreateLoad(vr_v4f32_ptr); } -Value * PPULLVMRecompiler::GetVrAsDoubleVec(u32 vr) { - auto vr_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, VPR[vr])); - auto vr_i128_ptr = s_ir_builder->CreateBitCast(vr_i8_ptr, s_ir_builder->getIntNTy(128)->getPointerTo()); - auto vr_v2f64_ptr = s_ir_builder->CreateBitCast(vr_i128_ptr, VectorType::get(s_ir_builder->getDoubleTy(), 2)->getPointerTo()); - return s_ir_builder->CreateLoad(vr_v2f64_ptr); +Value * PPULLVMRecompilerWorker::GetVrAsDoubleVec(u32 vr) { + auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, VPR[vr])); + auto vr_i128_ptr = m_ir_builder->CreateBitCast(vr_i8_ptr, m_ir_builder->getIntNTy(128)->getPointerTo()); + auto vr_v2f64_ptr = m_ir_builder->CreateBitCast(vr_i128_ptr, VectorType::get(m_ir_builder->getDoubleTy(), 2)->getPointerTo()); + return m_ir_builder->CreateLoad(vr_v2f64_ptr); } -void PPULLVMRecompiler::SetVr(u32 vr, Value * val_x128) { - auto vr_i8_ptr = s_ir_builder->CreateConstGEP1_32(s_state_ptr, offsetof(PPUThread, VPR[vr])); - auto vr_i128_ptr = s_ir_builder->CreateBitCast(vr_i8_ptr, s_ir_builder->getIntNTy(128)->getPointerTo()); - auto val_i128 = s_ir_builder->CreateBitCast(val_x128, s_ir_builder->getIntNTy(128)); - s_ir_builder->CreateStore(val_i128, vr_i128_ptr); +void PPULLVMRecompilerWorker::SetVr(u32 vr, Value * val_x128) { + auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), offsetof(PPUThread, VPR[vr])); + auto vr_i128_ptr = m_ir_builder->CreateBitCast(vr_i8_ptr, m_ir_builder->getIntNTy(128)->getPointerTo()); + auto val_i128 = m_ir_builder->CreateBitCast(val_x128, m_ir_builder->getIntNTy(128)); + m_ir_builder->CreateStore(val_i128, vr_i128_ptr); } -template -void PPULLVMRecompiler::ThisCall(const char * name, F function, C * this_ptr, Args... args) { - auto this_call_fn = new std::function(std::bind(function, this_ptr, args...)); - s_this_call_ptrs_list.push_back(this_call_fn); +Value * PPULLVMRecompilerWorker::ReadMemory(Value * addr_i64, u32 bits, bool bswap) { + if (bits != 32) { + auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, GetBaseAddress()); + auto eaddr_ix_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, m_ir_builder->getIntNTy(bits)->getPointerTo()); + auto val_ix = (Value *)m_ir_builder->CreateLoad(eaddr_ix_ptr); + if (bits > 8 && bswap) { + val_ix = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, {m_ir_builder->getIntNTy(bits)}), val_ix); + } - auto this_call_fn_i64 = s_ir_builder->getInt64((uint64_t)this_call_fn); - auto this_call_fn_ptr = s_ir_builder->CreateIntToPtr(this_call_fn_i64, s_ir_builder->getInt64Ty()->getPointerTo()); - std::vector execute_this_call_fn_args; - execute_this_call_fn_args.push_back(this_call_fn_ptr); - auto call_execute_this_call_fn_instr = s_ir_builder->CreateCall(s_execute_this_call_fn, execute_this_call_fn_args); + return val_ix; + } else { + auto cmp_i1 = m_ir_builder->CreateICmpULT(addr_i64, m_ir_builder->getInt64(RAW_SPU_BASE_ADDR)); + auto then_bb = BasicBlock::Create(m_ir_builder->getContext(), "", m_ir_builder->GetInsertBlock()->getParent()); + auto else_bb = BasicBlock::Create(m_ir_builder->getContext()); + auto merge_bb = BasicBlock::Create(m_ir_builder->getContext()); + m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); - std::string comment = fmt::Format("%s.%s", name, ArgsToString(args...).c_str()); - call_execute_this_call_fn_instr->setMetadata(comment, s_execute_this_call_fn_name_and_args_md_node); + m_ir_builder->SetInsertPoint(then_bb); + auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, GetBaseAddress()); + auto eaddr_i32_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, m_ir_builder->getInt32Ty()->getPointerTo()); + auto val_then_i32 = (Value *)m_ir_builder->CreateLoad(eaddr_i32_ptr); + if (bswap) { + val_then_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, {m_ir_builder->getInt32Ty()}), val_then_i32); + } - auto i = s_interpreter_invocation_stats.find(name); - if (i == s_interpreter_invocation_stats.end()) { - i = s_interpreter_invocation_stats.insert(s_interpreter_invocation_stats.end(), std::make_pair(name, 0)); + m_ir_builder->CreateBr(merge_bb); + + m_ir_builder->GetInsertBlock()->getParent()->getBasicBlockList().push_back(else_bb); + m_ir_builder->SetInsertPoint(else_bb); + auto this_ptr = (Value *)m_ir_builder->getInt64((u64)&Memory); + this_ptr = m_ir_builder->CreateIntToPtr(this_ptr, this_ptr->getType()->getPointerTo()); + auto val_else_i32 = Call("Read32", &MemoryBase::Read32, this_ptr, addr_i64); + if (!bswap) { + val_else_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, {m_ir_builder->getInt32Ty()}), val_else_i32); + } + m_ir_builder->CreateBr(merge_bb); + + m_ir_builder->GetInsertBlock()->getParent()->getBasicBlockList().push_back(merge_bb); + m_ir_builder->SetInsertPoint(merge_bb); + auto phi = m_ir_builder->CreatePHI(m_ir_builder->getInt32Ty(), 2); + phi->addIncoming(val_then_i32, then_bb); + phi->addIncoming(val_else_i32, else_bb); + return phi; + } +} + +void PPULLVMRecompilerWorker::WriteMemory(Value * addr_i64, Value * val_ix, bool bswap) { + if (val_ix->getType()->getIntegerBitWidth() != 32) { + if (val_ix->getType()->getIntegerBitWidth() > 8 && bswap) { + val_ix = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, {val_ix->getType()}), val_ix); + } + + auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, GetBaseAddress()); + auto eaddr_ix_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, val_ix->getType()->getPointerTo()); + m_ir_builder->CreateStore(val_ix, eaddr_ix_ptr); + } else { + auto cmp_i1 = m_ir_builder->CreateICmpULT(addr_i64, m_ir_builder->getInt64(RAW_SPU_BASE_ADDR)); + auto then_bb = BasicBlock::Create(m_ir_builder->getContext(), "", m_ir_builder->GetInsertBlock()->getParent()); + auto else_bb = BasicBlock::Create(m_ir_builder->getContext()); + auto merge_bb = BasicBlock::Create(m_ir_builder->getContext()); + m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); + + m_ir_builder->SetInsertPoint(then_bb); + Value * val_then_ix = val_ix; + if (bswap) { + val_then_ix = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, {m_ir_builder->getInt32Ty()}), val_then_ix); + } + + auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, GetBaseAddress()); + auto eaddr_i32_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, m_ir_builder->getInt32Ty()->getPointerTo()); + m_ir_builder->CreateStore(val_then_ix, eaddr_i32_ptr); + m_ir_builder->CreateBr(merge_bb); + + m_ir_builder->GetInsertBlock()->getParent()->getBasicBlockList().push_back(else_bb); + m_ir_builder->SetInsertPoint(else_bb); + Value * val_else_ix = val_ix; + if (!bswap) { + val_else_ix = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, {m_ir_builder->getInt32Ty()}), val_else_ix); + } + + auto this_ptr = (Value *)m_ir_builder->getInt64((u64)&Memory); + this_ptr = m_ir_builder->CreateIntToPtr(this_ptr, this_ptr->getType()->getPointerTo()); + Call("Write32", &MemoryBase::Write32, this_ptr, addr_i64, val_else_ix); + m_ir_builder->CreateBr(merge_bb); + + m_ir_builder->GetInsertBlock()->getParent()->getBasicBlockList().push_back(merge_bb); + m_ir_builder->SetInsertPoint(merge_bb); + } +} + +template +Value * PPULLVMRecompilerWorker::InterpreterCall(const char * name, Func function, Args... args) { + auto i = m_interpreter_fallback_stats.find(name); + if (i == m_interpreter_fallback_stats.end()) { + i = m_interpreter_fallback_stats.insert(m_interpreter_fallback_stats.end(), std::make_pair(name, 0)); } i->second++; + + return Call(name, function, GetInterpreter(), m_ir_builder->getInt32(args)...); } -void PPULLVMRecompiler::ExecuteThisCall(std::function * function) { - (*function)(); +template +Type * PPULLVMRecompilerWorker::CppToLlvmType() { + if (std::is_void::value) { + return m_ir_builder->getVoidTy(); + } else if (std::is_same::value || std::is_same::value) { + return m_ir_builder->getInt64Ty(); + } else if (std::is_same::value || std::is_same::value) { + return m_ir_builder->getInt32Ty(); + } else if (std::is_same::value || std::is_same::value) { + return m_ir_builder->getInt16Ty(); + } else if (std::is_same::value || std::is_same::value) { + return m_ir_builder->getInt8Ty(); + } else if (std::is_same::value) { + return m_ir_builder->getFloatTy(); + } else if (std::is_same::value) { + return m_ir_builder->getDoubleTy(); + } else if (std::is_pointer::value) { + return m_ir_builder->getInt8PtrTy(); + } else { + assert(0); + } + + return nullptr; } -template -std::string PPULLVMRecompiler::ArgsToString(T arg1, Args... args) { - return fmt::Format("%d", arg1) + "." + ArgsToString(args...); +template +Value * PPULLVMRecompilerWorker::Call(const char * name, Func function, Args... args) { + typedef std::result_of::type ReturnType; + + auto fn = m_module->getFunction(name); + if (!fn) { + std::vector fn_args_type = {args->getType()...}; + auto fn_type = FunctionType::get(CppToLlvmType(), fn_args_type, false); + fn = cast(m_module->getOrInsertFunction(name, fn_type)); + fn->setCallingConv(CallingConv::X86_64_Win64); + m_execution_engine->addGlobalMapping(fn, (void *&)function); + } + + std::vector fn_args = {args...}; + return m_ir_builder->CreateCall(fn, fn_args); } -std::string PPULLVMRecompiler::ArgsToString() { - return ""; +PPULLVMRecompiler::PPULLVMRecompiler(PPUThread & ppu) + : m_ppu(ppu) + , m_interpreter(ppu) { + m_worker.RunAllTests(&m_ppu, (u64)Memory.GetBaseAddr(), &m_interpreter); +} + +PPULLVMRecompiler::~PPULLVMRecompiler() { + +} + +u8 PPULLVMRecompiler::DecodeMemory(const u64 address) { + m_worker.Compile(address); + auto fn = m_worker.GetCompiledBlock(address); + fn(&m_ppu, (u64)Memory.GetBaseAddr(), &m_interpreter); + return 0; } diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.h b/rpcs3/Emu/Cell/PPULLVMRecompiler.h index a969a460e9..f02e84cb0c 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.h +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.h @@ -13,21 +13,29 @@ struct PPURegState; -/// LLVM based PPU emulator -class PPULLVMRecompiler : public CPUDecoder, protected PPUOpcodes { +/// PPU recompiler +class PPULLVMRecompilerWorker : protected PPUOpcodes { public: - PPULLVMRecompiler() = delete; - PPULLVMRecompiler(PPUThread & ppu); + typedef void(*CompiledBlock)(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter); - PPULLVMRecompiler(const PPULLVMRecompiler & other) = delete; - PPULLVMRecompiler(PPULLVMRecompiler && other) = delete; + PPULLVMRecompilerWorker(); - virtual ~PPULLVMRecompiler(); + PPULLVMRecompilerWorker(const PPULLVMRecompilerWorker & other) = delete; + PPULLVMRecompilerWorker(PPULLVMRecompilerWorker && other) = delete; - PPULLVMRecompiler & operator = (const PPULLVMRecompiler & other) = delete; - PPULLVMRecompiler & operator = (PPULLVMRecompiler && other) = delete; + virtual ~PPULLVMRecompilerWorker(); - u8 DecodeMemory(const u64 address) override; + PPULLVMRecompilerWorker & operator = (const PPULLVMRecompilerWorker & other) = delete; + PPULLVMRecompilerWorker & operator = (PPULLVMRecompilerWorker && other) = delete; + + /// Compile a block of code + void Compile(u64 address); + + /// Get a function pointer to a compiled block + CompiledBlock GetCompiledBlock(u64 address); + + /// Execute all tests + void RunAllTests(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter); protected: void NULL_OP() override; @@ -431,20 +439,53 @@ protected: void UNK(const u32 code, const u32 opcode, const u32 gcode) override; private: - /// PPU processor context - PPUThread & m_ppu; - /// PPU instruction decoder PPUDecoder m_decoder; - /// PPU Interpreter - PPUInterpreter m_interpreter; + /// Map from address to compiled block + std::map m_address_to_compiled_block_map; + + /// LLVM context + llvm::LLVMContext * m_llvm_context; + + /// LLVM IR builder + llvm::IRBuilder<> * m_ir_builder; + + /// Module to which all generated code is output to + llvm::Module * m_module; + + /// JIT execution engine + llvm::ExecutionEngine * m_execution_engine; + + /// Disassembler + LLVMDisasmContextRef m_disassembler; /// A flag used to detect branch instructions. /// This is set to false at the start of compilation of a block. /// When a branch instruction is encountered, this is set to true by the decode function. bool m_hit_branch_instruction; + /// The function being compiled + llvm::Function * m_function; + + /// Time spent compiling + std::chrono::duration m_compilation_time; + + /// Time spent idling + std::chrono::duration m_idling_time; + + /// Contains the number of times the interpreter fallback was used + std::map m_interpreter_fallback_stats; + + /// Get PPU state pointer + llvm::Value * GetPPUState(); + + /// Get base address + llvm::Value * GetBaseAddress(); + + /// Get interpreter pointer + llvm::Value * GetInterpreter(); + /// Get a bit llvm::Value * GetBit(llvm::Value * val, u32 n); @@ -473,7 +514,7 @@ private: void SetPc(llvm::Value * val_i64); /// Load GPR - llvm::Value * GetGpr(u32 r); + llvm::Value * GetGpr(u32 r, u32 num_bits = 64); /// Set GPR void SetGpr(u32 r, llvm::Value * val_x64); @@ -538,77 +579,57 @@ private: /// Set VR to the specified value void SetVr(u32 vr, llvm::Value * val_x128); + /// Read from memory + llvm::Value * ReadMemory(llvm::Value * addr_i64, u32 bits, bool bswap = true); + + /// Write to memory + void WriteMemory(llvm::Value * addr_i64, llvm::Value * val_ix, bool bswap = true); + + /// Call an interpreter function + template + llvm::Value * InterpreterCall(const char * name, Func function, Args... args); + + /// Convert a C++ type to an LLVM type + template + llvm::Type * CppToLlvmType(); + + /// Call a function + template + llvm::Value * Call(const char * name, Func function, Args... args); + /// Test an instruction against the interpreter template void VerifyInstructionAgainstInterpreter(const char * name, PPULLVMRecompilerFn recomp_fn, PPUInterpreterFn interp_fn, PPURegState & input_reg_state, Args... args); /// Excute a test void RunTest(const char * name, std::function test_case, std::function input, std::function check_result); +}; - /// Execute all tests - void RunAllTests(); +/// A dynarec PPU emulator that uses LLVM as the backend +class PPULLVMRecompiler : public CPUDecoder { +public: + PPULLVMRecompiler(PPUThread & ppu); + PPULLVMRecompiler() = delete; - /// Call a member function - template - void ThisCall(const char * name, F function, C * this_ptr, Args... args); + PPULLVMRecompiler(const PPULLVMRecompilerWorker & other) = delete; + PPULLVMRecompiler(PPULLVMRecompilerWorker && other) = delete; - /// Number of instances - static u32 s_num_instances; + virtual ~PPULLVMRecompiler(); - /// Map from address to compiled code - static std::map s_address_to_code_map; + PPULLVMRecompiler & operator = (const PPULLVMRecompiler & other) = delete; + PPULLVMRecompiler & operator = (PPULLVMRecompiler && other) = delete; - /// Mutex for s_address_to_code_map - static std::mutex s_address_to_code_map_mutex; + u8 DecodeMemory(const u64 address); - /// LLVM mutex - static std::mutex s_llvm_mutex; +private: + /// PPU processor context + PPUThread & m_ppu; - /// LLVM context - static llvm::LLVMContext * s_llvm_context; + /// PPU Interpreter + PPUInterpreter m_interpreter; - /// LLVM IR builder - static llvm::IRBuilder<> * s_ir_builder; - - /// Module to which all generated code is output to - static llvm::Module * s_module; - - /// Function in m_module that corresponds to ExecuteThisCall - static llvm::Function * s_execute_this_call_fn; - - /// A metadata node for s_execute_this_call_fn that records the function name and args - static llvm::MDNode * s_execute_this_call_fn_name_and_args_md_node; - - /// JIT execution engine - static llvm::ExecutionEngine * s_execution_engine; - - /// Disassembler - static LLVMDisasmContextRef s_disassembler; - - /// The pointer to the PPU state - static llvm::Value * s_state_ptr; - - /// Time spent compiling - static std::chrono::duration s_compilation_time; - - /// Time spent executing - static std::chrono::duration s_execution_time; - - /// Contains the number of times the interpreter was invoked for an instruction - static std::map s_interpreter_invocation_stats; - - /// List of std::function pointers created by ThisCall() - static std::list *> s_this_call_ptrs_list; - - /// Execute a this call - static void ExecuteThisCall(std::function * function); - - /// Convert args to a string - template - static std::string ArgsToString(T arg1, Args... args); - - /// Terminator for ArgsToString(T arg1, Args... args); - static std::string ArgsToString(); + /// The actual compiler + PPULLVMRecompilerWorker m_worker; }; #endif // PPU_LLVM_RECOMPILER_H diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp index 66ab60b9e0..fc87753734 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp @@ -9,7 +9,7 @@ using namespace llvm; #define VERIFY_INSTRUCTION_AGAINST_INTERPRETER(fn, tc, input, ...) \ -VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &PPULLVMRecompiler::fn, &PPUInterpreter::fn, input, __VA_ARGS__) +VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &PPULLVMRecompilerWorker::fn, &PPUInterpreter::fn, input, __VA_ARGS__) #define VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(fn, s, n, ...) { \ PPURegState input; \ @@ -155,22 +155,26 @@ struct PPURegState { } }; +static PPUThread * s_ppu_state = nullptr; +static u64 s_base_address = 0; +static PPUInterpreter * s_interpreter = nullptr; + template -void PPULLVMRecompiler::VerifyInstructionAgainstInterpreter(const char * name, PPULLVMRecompilerFn recomp_fn, PPUInterpreterFn interp_fn, PPURegState & input_reg_state, Args... args) { +void PPULLVMRecompilerWorker::VerifyInstructionAgainstInterpreter(const char * name, PPULLVMRecompilerFn recomp_fn, PPUInterpreterFn interp_fn, PPURegState & input_reg_state, Args... args) { auto test_case = [&]() { (this->*recomp_fn)(args...); }; auto input = [&]() { - input_reg_state.Store(m_ppu); + input_reg_state.Store(*s_ppu_state); }; auto check_result = [&](std::string & msg) { PPURegState recomp_output_reg_state; PPURegState interp_output_reg_state; - recomp_output_reg_state.Load(m_ppu); - input_reg_state.Store(m_ppu); - (&m_interpreter->*interp_fn)(args...); - interp_output_reg_state.Load(m_ppu); + recomp_output_reg_state.Load(*s_ppu_state); + input_reg_state.Store(*s_ppu_state); + (s_interpreter->*interp_fn)(args...); + interp_output_reg_state.Load(*s_ppu_state); if (interp_output_reg_state.ToString() != recomp_output_reg_state.ToString()) { msg = std::string("Input register states:\n") + input_reg_state.ToString() + @@ -184,36 +188,48 @@ void PPULLVMRecompiler::VerifyInstructionAgainstInterpreter(const char * name, P RunTest(name, test_case, input, check_result); } -void PPULLVMRecompiler::RunTest(const char * name, std::function test_case, std::function input, std::function check_result) { +void PPULLVMRecompilerWorker::RunTest(const char * name, std::function test_case, std::function input, std::function check_result) { // Create the unit test function - auto function = cast(s_module->getOrInsertFunction(name, s_ir_builder->getVoidTy(), s_ir_builder->getInt8Ty()->getPointerTo(), nullptr)); - s_state_ptr = function->arg_begin(); - s_state_ptr->setName("state"); + m_function = (Function *)m_module->getOrInsertFunction(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(*s_llvm_context, "start", function); - s_ir_builder->SetInsertPoint(block); + auto block = BasicBlock::Create(*m_llvm_context, "start", m_function); + m_ir_builder->SetInsertPoint(block); test_case(); - s_ir_builder->CreateRetVoid(); - verifyFunction(*function); + m_ir_builder->CreateRetVoid(); // Print the IR std::string ir; raw_string_ostream ir_ostream(ir); - function->print(ir_ostream); + m_function->print(ir_ostream); LOG_NOTICE(PPU, "[UT %s] LLVM IR:%s", name, ir.c_str()); + std::string verify; + raw_string_ostream verify_ostream(verify); + if (verifyFunction(*m_function, &verify_ostream)) { + LOG_ERROR(PPU, "[UT %s] Verification Failed:%s", name, verify.c_str()); + return; + } + // Generate the function MachineCodeInfo mci; - s_execution_engine->runJITOnFunction(function, &mci); + m_execution_engine->runJITOnFunction(m_function, &mci); // Disassember the generated function LOG_NOTICE(PPU, "[UT %s] Disassembly:", name); for (uint64_t pc = 0; pc < mci.size();) { char str[1024]; - auto size = LLVMDisasmInstruction(s_disassembler, (uint8_t *)mci.address() + pc, mci.size() - pc, (uint64_t)((uint8_t *)mci.address() + pc), str, sizeof(str)); + auto size = LLVMDisasmInstruction(m_disassembler, (uint8_t *)mci.address() + pc, mci.size() - pc, (uint64_t)((uint8_t *)mci.address() + pc), str, sizeof(str)); LOG_NOTICE(PPU, "[UT %s] %p: %s.", name, (uint8_t *)mci.address() + pc, str); pc += size; } @@ -221,8 +237,12 @@ void PPULLVMRecompiler::RunTest(const char * name, std::function test_ca // Run the test input(); std::vector args; - args.push_back(GenericValue(&m_ppu)); - s_execution_engine->runFunction(function, args); + args.push_back(GenericValue(s_ppu_state)); + GenericValue base_address; + base_address.IntVal = APInt(64, s_base_address); + args.push_back(base_address); + args.push_back(GenericValue(s_interpreter)); + m_execution_engine->runFunction(m_function, args); // Verify results std::string msg; @@ -233,13 +253,16 @@ void PPULLVMRecompiler::RunTest(const char * name, std::function test_ca LOG_ERROR(PPU, "[UT %s] Test failed. %s", name, msg.c_str()); } - s_execution_engine->freeMachineCodeForFunction(function); + m_execution_engine->freeMachineCodeForFunction(m_function); } -void PPULLVMRecompiler::RunAllTests() { - std::function test_case; - std::function input; - std::function check_result; +void PPULLVMRecompilerWorker::RunAllTests(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter) { + s_ppu_state = ppu_state; + s_base_address = base_address; + s_interpreter = interpreter; + + PPURegState initial_state; + initial_state.Load(*ppu_state); LOG_NOTICE(PPU, "Running Unit Tests"); @@ -320,4 +343,138 @@ void PPULLVMRecompiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW, 5, 5, 0, 1, 1); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW_, 0, 5, 0, 1, 2); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW_, 5, 5, 0, 1, 1); + // TODO: Rest of the vector instructions + + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLI, 0, 5, 1, 2, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFIC, 0, 5, 1, 2, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPLI, 0, 5, 1, 0, 7, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPLI, 5, 5, 1, 1, 7, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPI, 0, 5, 5, 0, 7, -12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPI, 5, 5, 5, 1, 7, -12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDIC, 0, 5, 1, 2, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDIC_, 0, 5, 1, 2, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDI, 0, 5, 1, 2, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDI, 5, 5, 0, 2, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDIS, 0, 5, 1, 2, -12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDIS, 5, 5, 0, 2, -12345); + // TODO: BC + // TODO: SC + // TODO: B + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MCRF, 0, 5, 0, 7); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MCRF, 5, 5, 6, 2); + // TODO: BCLR + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRNOR, 0, 5, 0, 7, 3); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRANDC, 0, 5, 5, 6, 7); + // TODO: ISYNC + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRXOR, 0, 5, 7, 7, 7); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRNAND, 0, 5, 3, 4, 5); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRAND, 0, 5, 1, 2, 3); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CREQV, 0, 5, 2, 1, 0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRORC, 0, 5, 3, 4, 5); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CROR, 0, 5, 6, 7, 0); + // TODO: BCCTR + // TODO: RLWIMI + // TODO: RLWINM + // TODO: RLWNM + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ORI, 0, 5, 25, 29, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ORIS, 0, 5, 7, 31, -12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XORI, 0, 5, 0, 19, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XORIS, 0, 5, 3, 14, -12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ANDI_, 0, 5, 16, 7, 12345); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ANDIS_, 0, 5, 23, 21, -12345); + + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADD, 0, 5, 7, 8, 9, 0, 0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADD, 5, 5, 21, 22, 23, 0, 1); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(AND, 0, 5, 7, 8, 9, 0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(AND, 5, 5, 21, 22, 23, 1); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(OR, 0, 5, 7, 8, 9, 0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(OR, 5, 5, 21, 22, 23, 1); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XOR, 0, 5, 7, 8, 9, 0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XOR, 5, 5, 21, 22, 23, 1); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMP, 0, 5, 3, 0, 9, 31); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMP, 5, 5, 6, 1, 23, 14); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPL, 0, 5, 3, 0, 9, 31); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPL, 5, 5, 6, 1, 23, 14); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSB, 0, 5, 3, 5, 0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSB, 5, 5, 3, 5, 1); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSH, 0, 5, 6, 9, 0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSH, 5, 5, 6, 9, 1); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSW, 0, 5, 25, 29, 0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSW, 5, 5, 25, 29, 1); + + PPURegState input; + input.SetRandom(); + input.GPR[14] = 10; + input.GPR[23] = 0x10000; + for (int i = 0; i < 1000; i++) { + ((u8*)base_address)[i + 0x10000] = (u8)i; + } + + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 0, input, 5, 0, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 1, input, 5, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZU, 0, input, 5, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZX, 0, input, 5, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZX, 1, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZUX, 0, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZ, 0, input, 5, 0, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZ, 1, input, 5, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZU, 0, input, 5, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 0, input, 5, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 1, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZUX, 0, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 0, input, 5, 0, 0x100F0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 1, input, 5, 14, 0x100F0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHAU, 0, input, 5, 14, 0x100F0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHAX, 0, input, 5, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHAX, 1, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHAUX, 0, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHBRX, 0, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZ, 0, input, 5, 0, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZ, 1, input, 5, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZU, 0, input, 5, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZX, 0, input, 5, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZX, 1, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZUX, 0, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWA, 0, input, 5, 0, 0x100F0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWA, 1, input, 5, 14, 0x100F0); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWAX, 0, input, 5, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWAX, 1, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWAUX, 0, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWBRX, 0, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LD, 0, input, 5, 0, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LD, 1, input, 5, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDU, 0, input, 5, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDX, 0, input, 5, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDX, 1, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDUX, 0, input, 5, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDBRX, 0, input, 5, 14, 23); + + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 0, input, 3, 0, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 1, input, 3, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBU, 0, input, 3, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 0, input, 3, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 1, input, 3, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBUX, 0, input, 3, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STH, 0, input, 3, 0, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STH, 1, input, 3, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHU, 0, input, 3, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 0, input, 3, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 1, input, 3, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHUX, 0, input, 3, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHBRX, 0, input, 3, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 0, input, 3, 0, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 1, input, 3, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWU, 0, input, 3, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWX, 0, input, 3, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWX, 1, input, 3, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWUX, 0, input, 3, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWBRX, 0, input, 3, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STD, 0, input, 3, 0, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STD, 1, input, 3, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDU, 0, input, 3, 14, 0x10000); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 0, input, 3, 0, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 1, input, 3, 14, 23); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDUX, 0, input, 3, 14, 23); + + initial_state.Store(*ppu_state); }