rpcsx/rpcs3/Emu/Cell/SPURecompiler.cpp

82 lines
1.5 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/IdManager.h"
#include "Emu/Memory/Memory.h"
#include "SPUThread.h"
#include "SPURecompiler.h"
#include "SPUASMJITRecompiler.h"
extern u64 get_system_time();
SPURecompilerDecoder::SPURecompilerDecoder(SPUThread& spu)
: db(fxm::get_always<SPUDatabase>())
, rec(fxm::get_always<spu_recompiler>())
, spu(spu)
{
}
u32 SPURecompilerDecoder::DecodeMemory(const u32 address)
{
if (spu.offset != address - spu.pc || spu.pc >= 0x40000 || spu.pc % 4)
{
throw EXCEPTION("Invalid address or PC (address=0x%x, PC=0x%05x)", address, spu.pc);
}
2015-09-04 01:23:31 +02:00
// get SPU LS pointer
const auto _ls = vm::get_ptr<be_t<u32>>(spu.offset);
2015-09-04 01:23:31 +02:00
// always validate (TODO)
const auto func = db->analyse(_ls, spu.pc);
2015-09-04 01:23:31 +02:00
// reset callstack if necessary
if (func->does_reset_stack && spu.recursion_level)
{
2015-09-04 01:23:31 +02:00
spu.m_state |= CPU_STATE_RETURN;
2015-09-04 01:23:31 +02:00
return 0;
}
2015-09-04 01:23:31 +02:00
if (!func->compiled)
{
rec->compile(*func);
2015-09-04 01:23:31 +02:00
if (!func->compiled) throw EXCEPTION("Compilation failed");
}
2015-09-04 01:23:31 +02:00
const u32 res = func->compiled(&spu, _ls);
if (const auto exception = spu.pending_exception)
{
spu.pending_exception = nullptr;
std::rethrow_exception(exception);
}
if (res & 0x1000000)
{
spu.halt();
}
if (res & 0x2000000)
{
}
if (res & 0x4000000)
{
if (res & 0x8000000)
{
throw EXCEPTION("Undefined behaviour");
}
spu.set_interrupt_status(true);
}
else if (res & 0x8000000)
{
spu.set_interrupt_status(false);
}
spu.pc = res & 0x3fffc;
return 0;
}