mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-28 22:13:24 +00:00
SPU JIT WIP
This commit is contained in:
parent
4a9310755f
commit
e614a7313c
@ -92,12 +92,12 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>.\libs\$(Configuration)\</OutDir>
|
||||
<OutDir>.\libs\$(Configuration)_x86\</OutDir>
|
||||
<IntDir>
|
||||
</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>.\libs\$(Configuration)\</OutDir>
|
||||
<OutDir>.\libs\$(Configuration)_x86\</OutDir>
|
||||
<IntDir>
|
||||
</IntDir>
|
||||
</PropertyGroup>
|
||||
@ -115,7 +115,7 @@
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>ASMJIT_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@ -139,7 +139,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>ASMJIT_STATIC;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@ -154,7 +154,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>ASMJIT_STATIC;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
@ -12,19 +12,19 @@ public:
|
||||
|
||||
|
||||
template<typename TO, uint from, uint to>
|
||||
static InstrList<1 << CodeField<from, to>::size, TO>* new_list(const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
|
||||
static InstrList<(1 << (CodeField<from, to>::size)), TO>* new_list(const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
|
||||
{
|
||||
return new InstrList<1 << CodeField<from, to>::size, TO>(func, error_func);
|
||||
return new InstrList<(1 << (CodeField<from, to>::size)), TO>(func, error_func);
|
||||
}
|
||||
|
||||
template<int count, typename TO, uint from, uint to>
|
||||
static InstrList<1 << CodeField<from, to>::size, TO>* new_list(InstrList<count, TO>* parent, int opcode, const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
|
||||
static InstrList<(1 << (CodeField<from, to>::size)), TO>* new_list(InstrList<count, TO>* parent, int opcode, const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
|
||||
{
|
||||
return connect_list(parent, new InstrList<1 << CodeField<from, to>::size, TO>(func, error_func), opcode);
|
||||
return connect_list(parent, new InstrList<(1 << (CodeField<from, to>::size)), TO>(func, error_func), opcode);
|
||||
}
|
||||
|
||||
template<int count, typename TO, uint from, uint to>
|
||||
static InstrList<1 << CodeField<from, to>::size, TO>* new_list(InstrList<count, TO>* parent, const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
|
||||
static InstrList<(1 << (CodeField<from, to>::size)), TO>* new_list(InstrList<count, TO>* parent, const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
|
||||
{
|
||||
return connect_list(parent, new InstrList<1 << CodeField<from, to>::size, TO>(func, error_func));
|
||||
return connect_list(parent, new InstrList<(1 << (CodeField<from, to>::size)), TO>(func, error_func));
|
||||
}
|
@ -32,121 +32,19 @@ private:
|
||||
//0 - 10
|
||||
void STOP(u32 code)
|
||||
{
|
||||
CPU.SetExitStatus(code); // exit code (not status)
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 0x110: /* ===== sys_spu_thread_receive_event ===== */
|
||||
{
|
||||
u32 spuq = 0;
|
||||
if (!CPU.SPU.Out_MBox.Pop(spuq))
|
||||
{
|
||||
ConLog.Error("sys_spu_thread_receive_event: cannot read Out_MBox");
|
||||
CPU.SPU.In_MBox.PushUncond(CELL_EINVAL); // ???
|
||||
return;
|
||||
}
|
||||
|
||||
if (CPU.SPU.In_MBox.GetCount())
|
||||
{
|
||||
ConLog.Error("sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq);
|
||||
CPU.SPU.In_MBox.PushUncond(CELL_EBUSY); // ???
|
||||
return;
|
||||
}
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
ConLog.Write("sys_spu_thread_receive_event(spuq=0x%x)", spuq);
|
||||
}
|
||||
|
||||
EventQueue* eq;
|
||||
if (!CPU.SPUQs.GetEventQueue(FIX_SPUQ(spuq), eq))
|
||||
{
|
||||
CPU.SPU.In_MBox.PushUncond(CELL_EINVAL); // TODO: check error value
|
||||
return;
|
||||
}
|
||||
|
||||
u32 tid = GetCurrentSPUThread().GetId();
|
||||
|
||||
eq->sq.push(tid); // add thread to sleep queue
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (eq->owner.trylock(tid))
|
||||
{
|
||||
case SMR_OK:
|
||||
if (!eq->events.count())
|
||||
{
|
||||
eq->owner.unlock(tid);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio();
|
||||
if (next != tid)
|
||||
{
|
||||
eq->owner.unlock(tid, next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case SMR_SIGNAL:
|
||||
{
|
||||
sys_event_data event;
|
||||
eq->events.pop(event);
|
||||
eq->owner.unlock(tid);
|
||||
CPU.SPU.In_MBox.PushUncond(CELL_OK);
|
||||
CPU.SPU.In_MBox.PushUncond(event.data1);
|
||||
CPU.SPU.In_MBox.PushUncond(event.data2);
|
||||
CPU.SPU.In_MBox.PushUncond(event.data3);
|
||||
return;
|
||||
}
|
||||
case SMR_FAILED: break;
|
||||
default: eq->sq.invalidate(tid); CPU.SPU.In_MBox.PushUncond(CELL_ECANCELED); return;
|
||||
}
|
||||
|
||||
Sleep(1);
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_spu_thread_receive_event(spuq=0x%x) aborted", spuq);
|
||||
eq->sq.invalidate(tid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x102:
|
||||
if (!CPU.SPU.Out_MBox.GetCount())
|
||||
{
|
||||
ConLog.Error("sys_spu_thread_exit (no status, code 0x102)");
|
||||
}
|
||||
else if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
// the real exit status
|
||||
ConLog.Write("sys_spu_thread_exit (status=0x%x)", CPU.SPU.Out_MBox.GetValue());
|
||||
}
|
||||
CPU.Stop();
|
||||
break;
|
||||
default:
|
||||
if (!CPU.SPU.Out_MBox.GetCount())
|
||||
{
|
||||
ConLog.Error("Unknown STOP code: 0x%x (no message)", code);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConLog.Error("Unknown STOP code: 0x%x (message=0x%x)", code, CPU.SPU.Out_MBox.GetValue());
|
||||
}
|
||||
CPU.Stop();
|
||||
break;
|
||||
}
|
||||
CPU.DoStop(code);
|
||||
}
|
||||
void LNOP()
|
||||
{
|
||||
}
|
||||
void SYNC(u32 Cbit)
|
||||
{
|
||||
// This instruction must be used following a store instruction that modifies the instruction stream.
|
||||
_mm_mfence();
|
||||
}
|
||||
void DSYNC()
|
||||
{
|
||||
// This instruction forces all earlier load, store, and channel instructions to complete before proceeding.
|
||||
_mm_mfence();
|
||||
}
|
||||
void MFSPR(u32 rt, u32 sa)
|
||||
@ -389,6 +287,7 @@ private:
|
||||
}
|
||||
void STOPD(u32 rc, u32 ra, u32 rb)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
Emu.Pause();
|
||||
}
|
||||
void STQX(u32 rt, u32 ra, u32 rb)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ static const SPUImmTable g_spu_imm;
|
||||
|
||||
SPURecompilerCore::SPURecompilerCore(SPUThread& cpu)
|
||||
: m_enc(new SPURecompiler(cpu, *this))
|
||||
, m_inter(new SPUInterpreter(cpu))
|
||||
, inter(new SPUInterpreter(cpu))
|
||||
, CPU(cpu)
|
||||
, compiler(&runtime)
|
||||
{
|
||||
@ -17,17 +17,17 @@ SPURecompilerCore::SPURecompilerCore(SPUThread& cpu)
|
||||
SPURecompilerCore::~SPURecompilerCore()
|
||||
{
|
||||
delete m_enc;
|
||||
delete m_inter;
|
||||
delete inter;
|
||||
}
|
||||
|
||||
void SPURecompilerCore::Decode(const u32 code) // decode instruction and run with interpreter
|
||||
{
|
||||
(*SPU_instr::rrr_list)(m_inter, code);
|
||||
(*SPU_instr::rrr_list)(inter, code);
|
||||
}
|
||||
|
||||
void SPURecompilerCore::Compile(u16 pos)
|
||||
{
|
||||
compiler.addFunc(kFuncConvHost, FuncBuilder4<u16, void*, void*, void*, u16>());
|
||||
compiler.addFunc(kFuncConvHost, FuncBuilder4<u32, void*, void*, void*, u32>());
|
||||
entry[pos].host = pos;
|
||||
|
||||
GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu");
|
||||
@ -45,15 +45,26 @@ void SPURecompilerCore::Compile(u16 pos)
|
||||
compiler.alloc(imm_var);
|
||||
m_enc->imm_var = &imm_var;
|
||||
|
||||
GpVar pos_var(compiler, kVarTypeUInt16, "pos");
|
||||
GpVar pos_var(compiler, kVarTypeUInt32, "pos");
|
||||
compiler.setArg(3, pos_var);
|
||||
compiler.alloc(pos_var);
|
||||
|
||||
m_enc->pos_var = &pos_var;
|
||||
|
||||
compiler.xor_(pos_var, pos_var);
|
||||
|
||||
while (true)
|
||||
{
|
||||
const u32 opcode = Memory.Read32(CPU.dmac.ls_offset + pos * 4);
|
||||
m_enc->do_finalize = false;
|
||||
(*SPU_instr::rrr_list)(m_enc, opcode); // compile single opcode
|
||||
if (opcode)
|
||||
{
|
||||
(*SPU_instr::rrr_list)(m_enc, opcode); // compile single opcode
|
||||
}
|
||||
else
|
||||
{
|
||||
m_enc->do_finalize = true;
|
||||
}
|
||||
bool fin = m_enc->do_finalize;
|
||||
entry[pos].valid = opcode;
|
||||
|
||||
@ -63,7 +74,6 @@ void SPURecompilerCore::Compile(u16 pos)
|
||||
entry[pos].host = entry[pos - 1].host;
|
||||
}
|
||||
|
||||
compiler.xor_(pos_var, pos_var);
|
||||
compiler.ret(pos_var);
|
||||
compiler.endFunc();
|
||||
entry[entry[pos].host].pointer = compiler.make();
|
||||
@ -74,6 +84,7 @@ u8 SPURecompilerCore::DecodeMemory(const u64 address)
|
||||
const u64 m_offset = address - CPU.PC;
|
||||
const u16 pos = (CPU.PC >> 2);
|
||||
|
||||
//ConLog.Write("DecodeMemory: pos=%d", pos);
|
||||
u32* ls = (u32*)Memory.VirtualToRealAddr(m_offset);
|
||||
|
||||
if (!pos)
|
||||
@ -115,16 +126,16 @@ u8 SPURecompilerCore::DecodeMemory(const u64 address)
|
||||
return 0;
|
||||
}
|
||||
// jump
|
||||
typedef u16(*Func)(void* _cpu, void* _ls, const SPUImmTable* _imm, u16 _pos);
|
||||
typedef u32(*Func)(void* _cpu, void* _ls, const SPUImmTable* _imm, u32 _pos);
|
||||
|
||||
Func func = asmjit_cast<Func>(entry[entry[pos].host].pointer);
|
||||
|
||||
void* cpu = (u8*)&CPU.GPR[0] - offsetof(SPUThread, GPR[0]); // ugly cpu base offset detection
|
||||
|
||||
u16 res = pos == entry[pos].host ? 0 : pos;
|
||||
res = func(cpu, ls, &g_spu_imm, res);
|
||||
u16 res = (pos == entry[pos].host) ? 0 : pos;
|
||||
res = (u16)func(cpu, ls, &g_spu_imm, res);
|
||||
|
||||
ConLog.Write("func -> %d", res);
|
||||
CPU.SetBranch((u64)res << 2);
|
||||
|
||||
return 0;
|
||||
/*Decode(Memory.Read32(address));
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Emu/Cell/SPUDecoder.h"
|
||||
#include "Emu/Cell/SPUInterpreter.h"
|
||||
#include "Emu/Cell/SPUDisAsm.h"
|
||||
#include "Emu/Cell/SPURecompiler.h"
|
||||
|
||||
SPUThread& GetCurrentSPUThread()
|
||||
{
|
||||
@ -75,6 +76,8 @@ void SPUThread::DoRun()
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_dec = new SPURecompilerCore(*this);
|
||||
break;
|
||||
case 2:
|
||||
m_dec = new SPUDecoder(*new SPUInterpreter(*this));
|
||||
break;
|
||||
|
@ -213,20 +213,21 @@ public:
|
||||
|
||||
union SPU_GPR_hdr
|
||||
{
|
||||
u32 _u32[4];
|
||||
float _f[4];
|
||||
u128 _u128;
|
||||
s128 _i128;
|
||||
__m128 _m128;
|
||||
__m128i _m128i;
|
||||
u64 _u64[2];
|
||||
s64 _i64[2];
|
||||
u32 _u32[4];
|
||||
s32 _i32[4];
|
||||
u16 _u16[8];
|
||||
s16 _i16[8];
|
||||
u8 _u8[16];
|
||||
s8 _i8[16];
|
||||
double _d[2];
|
||||
float _f[4];
|
||||
|
||||
|
||||
SPU_GPR_hdr() {}
|
||||
|
||||
@ -243,9 +244,9 @@ union SPU_GPR_hdr
|
||||
|
||||
union SPU_SPR_hdr
|
||||
{
|
||||
u32 _u32[4];
|
||||
u128 _u128;
|
||||
s128 _i128;
|
||||
u32 _u32[4];
|
||||
|
||||
SPU_SPR_hdr() {}
|
||||
|
||||
@ -299,19 +300,19 @@ public:
|
||||
#else
|
||||
static const bool x86 = true;
|
||||
#endif
|
||||
|
||||
private:
|
||||
union _CRT_ALIGN(8) {
|
||||
struct {
|
||||
volatile u32 m_index;
|
||||
u32 m_value[max_count];
|
||||
};
|
||||
struct {
|
||||
volatile u32 m_index2;
|
||||
u16 m_val16[max_count * 2];
|
||||
};
|
||||
volatile u64 m_indval;
|
||||
};
|
||||
std::mutex m_lock;
|
||||
|
||||
public:
|
||||
|
||||
Channel()
|
||||
{
|
||||
Init();
|
||||
@ -586,7 +587,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
Sleep(1); // hack
|
||||
//Sleep(1); // hack
|
||||
|
||||
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK))
|
||||
{
|
||||
@ -1125,6 +1126,115 @@ public:
|
||||
if (Emu.IsStopped()) ConLog.Warning("%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
|
||||
}
|
||||
|
||||
void DoStop(u32 code)
|
||||
{
|
||||
SetExitStatus(code); // exit code (not status)
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 0x110: /* ===== sys_spu_thread_receive_event ===== */
|
||||
{
|
||||
u32 spuq = 0;
|
||||
if (!SPU.Out_MBox.Pop(spuq))
|
||||
{
|
||||
ConLog.Error("sys_spu_thread_receive_event: cannot read Out_MBox");
|
||||
SPU.In_MBox.PushUncond(CELL_EINVAL); // ???
|
||||
return;
|
||||
}
|
||||
|
||||
if (SPU.In_MBox.GetCount())
|
||||
{
|
||||
ConLog.Error("sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq);
|
||||
SPU.In_MBox.PushUncond(CELL_EBUSY); // ???
|
||||
return;
|
||||
}
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
ConLog.Write("sys_spu_thread_receive_event(spuq=0x%x)", spuq);
|
||||
}
|
||||
|
||||
EventQueue* eq;
|
||||
if (!SPUQs.GetEventQueue(FIX_SPUQ(spuq), eq))
|
||||
{
|
||||
SPU.In_MBox.PushUncond(CELL_EINVAL); // TODO: check error value
|
||||
return;
|
||||
}
|
||||
|
||||
u32 tid = GetId();
|
||||
|
||||
eq->sq.push(tid); // add thread to sleep queue
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (eq->owner.trylock(tid))
|
||||
{
|
||||
case SMR_OK:
|
||||
if (!eq->events.count())
|
||||
{
|
||||
eq->owner.unlock(tid);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio();
|
||||
if (next != tid)
|
||||
{
|
||||
eq->owner.unlock(tid, next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case SMR_SIGNAL:
|
||||
{
|
||||
sys_event_data event;
|
||||
eq->events.pop(event);
|
||||
eq->owner.unlock(tid);
|
||||
SPU.In_MBox.PushUncond(CELL_OK);
|
||||
SPU.In_MBox.PushUncond(event.data1);
|
||||
SPU.In_MBox.PushUncond(event.data2);
|
||||
SPU.In_MBox.PushUncond(event.data3);
|
||||
return;
|
||||
}
|
||||
case SMR_FAILED: break;
|
||||
default: eq->sq.invalidate(tid); SPU.In_MBox.PushUncond(CELL_ECANCELED); return;
|
||||
}
|
||||
|
||||
Sleep(1);
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_spu_thread_receive_event(spuq=0x%x) aborted", spuq);
|
||||
eq->sq.invalidate(tid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x102:
|
||||
if (!SPU.Out_MBox.GetCount())
|
||||
{
|
||||
ConLog.Error("sys_spu_thread_exit (no status, code 0x102)");
|
||||
}
|
||||
else if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
// the real exit status
|
||||
ConLog.Write("sys_spu_thread_exit (status=0x%x)", SPU.Out_MBox.GetValue());
|
||||
}
|
||||
Stop();
|
||||
break;
|
||||
default:
|
||||
if (!SPU.Out_MBox.GetCount())
|
||||
{
|
||||
ConLog.Error("Unknown STOP code: 0x%x (no message)", code);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConLog.Error("Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue());
|
||||
}
|
||||
Stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset) && lsa < 0x40000; }
|
||||
virtual u8 ReadLS8 (const u32 lsa) const { return Memory.Read8 (lsa + m_offset); } // m_offset & 0x3fffc ?????
|
||||
virtual u16 ReadLS16 (const u32 lsa) const { return Memory.Read16 (lsa + m_offset); }
|
||||
|
@ -393,6 +393,7 @@
|
||||
<ClInclude Include="Emu\Cell\SPUDisAsm.h" />
|
||||
<ClInclude Include="Emu\Cell\SPUInterpreter.h" />
|
||||
<ClInclude Include="Emu\Cell\SPUOpcodes.h" />
|
||||
<ClInclude Include="Emu\Cell\SPURecompiler.h" />
|
||||
<ClInclude Include="Emu\Cell\SPURSManager.h" />
|
||||
<ClInclude Include="Emu\Cell\SPUThread.h" />
|
||||
<ClInclude Include="Emu\DbgConsole.h" />
|
||||
|
@ -702,5 +702,8 @@
|
||||
<ClInclude Include="..\Utilities\StrFmt.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\Cell\SPURecompiler.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user