PPU LLVM: remove unnecessary code

This commit is contained in:
Nekotekina 2017-06-26 00:15:54 +03:00
parent cd4f290d3d
commit 1196e9decc
3 changed files with 25 additions and 198 deletions

View File

@ -875,141 +875,6 @@ static bool adde_carry(u64 a, u64 b, bool c)
#endif
}
static std::string ppu_context_prologue()
{
std::string c;
//c += "\xCC";
#ifndef _WIN32
c += "\x48\x89\xF9"; // mov rcx, rdi
#endif
c += "\x48\xB8"; // mov rax, imm64
uptr ptr = (uptr)&vm::g_base_addr;
c.append((const char*)&ptr, 8);
c += "\x48\x8B"; // mov rax, [rax]
c += '\0';
c += "\x48\x03\x41"; // add rax, [ppu+r3]
c += char(offset32(&ppu_thread::gpr, 3));
c += "\x48\x83\xC0\x0F"; // add rax, 15
c += "\x48\x83\xE0\xF0"; // and rax, -16
return c;
}
const auto ppu_get_context = []() -> std::string
{
std::string c = ppu_context_prologue();
c += "\x48\x8B\x51"; // mov rdx, [rcx+r1]
c += char(offset32(&ppu_thread::gpr, 1));
c += "\x48\x89\x10"; // mov [rax], rdx
c += "\x48\x8B\x51"; // mov rdx, [rcx+r2]
c += char(offset32(&ppu_thread::gpr, 2));
c += "\x48\x89\x50\x08"; // mov [rax+8], rdx
c += "\x48\x8B\x54\x24\xF8"; // mov rdx, [rsp-8]
c += "\x48\x89\x50\x10"; // mov [rax+0x10], rdx
c += "\x48\x89\x60\x18"; // mov [rax+0x18], rsp
c += "\x48\x89\x58\x20"; // mov [rax+0x20], rbx
c += "\x48\x89\x68\x28"; // mov [rax+0x28], rbp
#ifdef _WIN32
c += "\x48\x89\x70\x30"; // mov [rax+0x30], rsi
c += "\x48\x89\x78\x38"; // mov [rax+0x38], rdi
#endif
c += "\x4C\x89\x60\x40"; // mov [rax+0x40], r12
c += "\x4C\x89\x68\x48"; // mov [rax+0x48], r13
c += "\x4C\x89\x70\x50"; // mov [rax+0x50], r14
c += "\x4C\x89\x78\x58"; // mov [rax+0x58], r15
#ifdef _WIN32
c += "\x66\x0F\x7F\x70\x60"; // movdqa [rax+0x60], xmm6
c += "\x66\x0F\x7F\x78\x70"; // movdqa [rax+0x70], xmm7
c += "\x66\x44\x0F\x7F\x80\x80\x00\x00\x00"s; // ...
c += "\x66\x44\x0F\x7F\x88\x90\x00\x00\x00"s;
c += "\x66\x44\x0F\x7F\x90\xA0\x00\x00\x00"s;
c += "\x66\x44\x0F\x7F\x98\xB0\x00\x00\x00"s;
c += "\x66\x44\x0F\x7F\xA0\xC0\x00\x00\x00"s;
c += "\x66\x44\x0F\x7F\xA8\xD0\x00\x00\x00"s;
c += "\x66\x44\x0F\x7F\xB0\xE0\x00\x00\x00"s;
c += "\x66\x44\x0F\x7F\xB8\xF0\x00\x00\x00"s;
#endif
c += "\x48\xC7\x41"; // mov [rcx+r3], 0
c += char(offset32(&ppu_thread::gpr, 3));
c.append(4, '\0');
//c += "\xCC";
c += "\xC3"; // ret
return c;
}();
const auto ppu_set_context = []() -> std::string
{
std::string c = ppu_context_prologue();
c += "\xCC";
c += "\x48\x8B\x10"; // mov rdx, [rax]
c += "\x48\x89\x51"; // mov [rcx+r1], rdx
c += char(offset32(&ppu_thread::gpr, 1));
c += "\x48\x8B\x50\x08"; // mov rdx, [rax+8]
c += "\x48\x89\x51"; // mov [rcx+r2], rdx
c += char(offset32(&ppu_thread::gpr, 2));
c += "\x48\x8B\x60\x18"; // mov rsp, [rax+0x18]
c += "\x48\x8B\x58\x20"; // mov rbx, [rax+0x20]
c += "\x48\x8B\x68\x28"; // mov rbp, [rax+0x28]
#ifdef _WIN32
c += "\x48\x8B\x70\x30"; // mov rsi, [rax+0x30]
c += "\x48\x8B\x78\x38"; // mov rdi, [rax+0x38]
#endif
c += "\x4C\x8B\x60\x40"; // mov r12, [rax+0x40]
c += "\x4C\x8B\x68\x48"; // mov r13, [rax+0x48]
c += "\x4C\x8B\x70\x50"; // mov r14, [rax+0x50]
c += "\x4C\x8B\x78\x58"; // mov r15, [rax+0x58]
#ifdef _WIN32
c += "\x66\x0F\x6F\x70\x60"; // movdqa xmm6, [rax+0x60]
c += "\x66\x0F\x6F\x78\x70"; // movdqa xmm7, [rax+0x70]
c += "\x66\x44\x0F\x6F\x80\x80\x00\x00\x00"s; // ...
c += "\x66\x44\x0F\x6F\x88\x90\x00\x00\x00"s;
c += "\x66\x44\x0F\x6F\x90\xA0\x00\x00\x00"s;
c += "\x66\x44\x0F\x6F\x98\xB0\x00\x00\x00"s;
c += "\x66\x44\x0F\x6F\xA0\xC0\x00\x00\x00"s;
c += "\x66\x44\x0F\x6F\xA8\xD0\x00\x00\x00"s;
c += "\x66\x44\x0F\x6F\xB0\xE0\x00\x00\x00"s;
c += "\x66\x44\x0F\x6F\xB8\xF0\x00\x00\x00"s;
#endif
c += "\x48\x8B\x50\x10"; // mov rdx, [rax+0x10]
c += "\x48\x89\x54\x24\xF8"; // mov [rsp-8], rdx
c += "\x48\x8B\x51"; // mov rdx, [rcx+r4]
c += char(offset32(&ppu_thread::gpr, 4));
c += "\x48\x85\xD2"; // test rdx, rdx
c += "\x0F\x94\xC2"; // setz dl
c += "\x48\x0F\xB6\xD2"; // movzx rdx, dl
c += "\x48\x89\x51"; // mov [rcx+r3], rdx
c += char(offset32(&ppu_thread::gpr, 3));
c += "\xC3"; // ret
return c;
}();
const auto ppu_use_context = []() -> std::string
{
std::string c;
c += "\x48\xB8"; // mov rax, imm64
uptr ptr = (uptr)&vm::g_exec_addr;
c.append((const char*)&ptr, 8);
c += "\x48\x8B\x20"; // mov rsp, [rax]
#ifdef _WIN32
c += "\x48\x01\xD4"; // add rsp,rdx
#else
c += "\x48\x01\xFC"; // add rsp,rsi
#endif
//c += "\x48\x83\xE4\xE0"; // and rsp, -0x20
#ifdef _WIN32
c += "\x41\xFF\xD0"; // call r8
#else
c += "\xFF\xD2"; // call rdx
#endif
return c;
}();
extern void ppu_initialize()
{
const auto _funcs = fxm::withdraw<std::vector<ppu_function>>();
@ -1380,60 +1245,6 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
// Run optimization passes
pm.run(*func);
const auto _syscall = module->getFunction("__syscall");
for (auto i = inst_begin(*func), end = inst_end(*func); i != end;)
{
const auto inst = &*i++;
if (const auto ci = dyn_cast<CallInst>(inst))
{
const auto cif = ci->getCalledFunction();
const auto op1 = ci->getNumArgOperands() > 1 ? ci->getArgOperand(1) : nullptr;
if (cif == _syscall && op1 && isa<ConstantInt>(op1))
{
// Try to determine syscall using the value from r11 (requires constant propagation)
const u64 index = cast<ConstantInt>(op1)->getZExtValue();
if (const auto ptr = ppu_get_syscall(index))
{
const auto n = ppu_get_syscall_name(index);
const auto f = cast<Function>(module->getOrInsertFunction(n, _func));
// Call the syscall directly
ReplaceInstWithInst(ci, CallInst::Create(f, {ci->getArgOperand(0)}));
}
}
continue;
}
if (const auto li = dyn_cast<LoadInst>(inst))
{
// TODO: more careful check
if (li->getNumUses() == 0)
{
// Remove unreferenced volatile loads
li->eraseFromParent();
}
continue;
}
if (const auto si = dyn_cast<StoreInst>(inst))
{
// TODO: more careful check
if (isa<UndefValue>(si->getOperand(0)) && si->getParent() == &func->getEntryBlock())
{
// Remove undef volatile stores
si->eraseFromParent();
}
continue;
}
}
}
}

View File

@ -7,6 +7,8 @@
#include "../Utilities/Log.h"
#include <algorithm>
extern std::string ppu_get_syscall_name(u64 code);
using namespace llvm;
const ppu_decoder<PPUTranslator> s_ppu_decoder;
@ -1636,6 +1638,21 @@ void PPUTranslator::SC(ppu_opcode_t op)
const auto num = GetGpr(11);
RegStore(m_ir->getInt32(m_current_addr), m_cia);
FlushRegisters();
if (!op.lev && isa<ConstantInt>(num))
{
// Try to determine syscall using the constant value from r11
const u64 index = cast<ConstantInt>(num)->getZExtValue();
if (index < 1024)
{
// Call the syscall directly
Call(GetType<void>(), ppu_get_syscall_name(index), m_thread);
m_ir->CreateRetVoid();
return;
}
}
Call(GetType<void>(), op.lev ? "__lv1call" : "__syscall", m_thread, num);
m_ir->CreateRetVoid();
}

View File

@ -33,7 +33,13 @@
extern std::string ppu_get_syscall_name(u64 code);
static constexpr ppu_function_t null_func = nullptr;
static bool null_func(ppu_thread& ppu)
{
LOG_TODO(HLE, "Unimplemented syscall %s -> CELL_OK", ppu_get_syscall_name(ppu.gpr[11]));
ppu.gpr[3] = 0;
ppu.cia += 4;
return false;
}
std::array<ppu_function_t, 1024> g_ppu_syscall_table{};
@ -974,16 +980,9 @@ extern void ppu_execute_syscall(ppu_thread& ppu, u64 code)
{
func(ppu);
LOG_TRACE(PPU, "Syscall '%s' (%llu) finished, r3=0x%llx", ppu_get_syscall_name(code), code, ppu.gpr[3]);
}
else
{
LOG_TODO(HLE, "Unimplemented syscall %s -> CELL_OK", ppu_get_syscall_name(code));
ppu.gpr[3] = 0;
ppu.cia += 4;
}
return;
}
}
fmt::throw_exception("Invalid syscall number (%llu)", code);
}