#include "stdafx.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "SPUDisAsm.h" #include "SPUThread.h" #include "SPUInterpreter.h" #include "SPUASMJITRecompiler.h" #include #define ASMJIT_STATIC #define ASMJIT_DEBUG #include "asmjit.h" #define SPU_OFF_128(x) asmjit::host::oword_ptr(*cpu, OFFSET_32(SPUThread, x)) #define SPU_OFF_64(x) asmjit::host::qword_ptr(*cpu, OFFSET_32(SPUThread, x)) #define SPU_OFF_32(x) asmjit::host::dword_ptr(*cpu, OFFSET_32(SPUThread, x)) #define SPU_OFF_16(x) asmjit::host::word_ptr(*cpu, OFFSET_32(SPUThread, x)) #define SPU_OFF_8(x) asmjit::host::byte_ptr(*cpu, OFFSET_32(SPUThread, x)) const spu_decoder s_spu_interpreter; // TODO: remove const spu_decoder s_spu_decoder; spu_recompiler::spu_recompiler() : m_jit(std::make_shared()) { asmjit::X86CpuInfo inf; asmjit::X86CpuUtil::detect(&inf); LOG_SUCCESS(SPU, "SPU Recompiler (ASMJIT) created..."); fs::file(fs::get_config_dir() + "SPUJIT.log", fs::rewrite).write(fmt::format("SPU JIT initialization...\n\nTitle: %s\nTitle ID: %s\n\n", Emu.GetTitle().c_str(), Emu.GetTitleID().c_str())); } void spu_recompiler::compile(spu_function_t& f) { std::lock_guard lock(m_mutex); if (f.compiled) { // return if function already compiled return; } if (f.addr >= 0x40000 || f.addr % 4 || f.size == 0 || f.size > 0x40000 - f.addr || f.size % 4) { fmt::throw_exception("Invalid SPU function (addr=0x%05x, size=0x%x)" HERE, f.addr, f.size); } using namespace asmjit; SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); dis_asm.offset = reinterpret_cast(f.data.data()) - f.addr; StringLogger logger; logger.setOption(kLoggerOptionBinaryForm, true); std::string log = fmt::format("========== SPU FUNCTION 0x%05x - 0x%05x ==========\n\n", f.addr, f.addr + f.size); this->m_func = &f; X86Compiler compiler(m_jit.get()); this->c = &compiler; compiler.setLogger(&logger); compiler.addFunc(kFuncConvHost, FuncBuilder2()); // Initialize variables X86GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu"); compiler.setArg(0, cpu_var); compiler.alloc(cpu_var, asmjit::host::rbp); // ASMJIT bug workaround this->cpu = &cpu_var; X86GpVar ls_var(compiler, kVarTypeIntPtr, "ls"); compiler.setArg(1, ls_var); compiler.alloc(ls_var, asmjit::host::rbx); // ASMJIT bug workaround this->ls = &ls_var; X86GpVar addr_var(compiler, kVarTypeUInt32, "addr"); this->addr = &addr_var; X86GpVar qw0_var(compiler, kVarTypeUInt64, "qw0"); this->qw0 = &qw0_var; X86GpVar qw1_var(compiler, kVarTypeUInt64, "qw1"); this->qw1 = &qw1_var; X86GpVar qw2_var(compiler, kVarTypeUInt64, "qw2"); this->qw2 = &qw2_var; std::array vec_vars; for (u32 i = 0; i < vec_vars.size(); i++) { vec_vars[i] = X86XmmVar{ compiler, kX86VarTypeXmm, fmt::format("vec%d", i).c_str() }; vec.at(i) = vec_vars.data() + i; } // Initialize labels std::vector