Merge pull request #365 from Nekotekina/master

Work on RawSPU: interrupt mailbox
This commit is contained in:
Hykem 2014-06-23 03:41:11 +01:00
commit 35b57fc78e
15 changed files with 458 additions and 52 deletions

View File

@ -130,6 +130,10 @@ public:
u64 cycle;
bool m_is_branch;
bool m_is_interrupt;
bool m_has_interrupt;
u64 m_interrupt_arg;
protected:
CPUThread(CPUThreadType type);

View File

@ -108,6 +108,26 @@ CPUThread* CPUThreadManager::GetThread(u32 id)
return res;
}
RawSPUThread* CPUThreadManager::GetRawSPUThread(u32 num)
{
std::lock_guard<std::mutex> lock(m_mtx_thread);
for (u32 i = 0; i < m_threads.size(); i++)
{
if (m_threads[i]->GetType() == CPU_THREAD_RAW_SPU)
{
RawSPUThread* t = (RawSPUThread*)m_threads[i];
if (t->GetIndex() == num)
{
return t;
}
}
}
return nullptr;
}
void CPUThreadManager::NotifyThread(const u32 id)
{
if (!id) return;

View File

@ -1,5 +1,6 @@
#pragma once
class CPUThread;
class RawSPUThread;
enum CPUThreadType : unsigned char;
class CPUThreadManager
@ -21,6 +22,7 @@ public:
std::vector<CPUThread*>& GetThreads() { return m_threads; }
s32 GetThreadNumById(CPUThreadType type, u32 id);
CPUThread* GetThread(u32 id);
RawSPUThread* GetRawSPUThread(u32 num);
void Exec();
void Task();

View File

@ -79,7 +79,7 @@ bool RawSPUThread::Read32(const u64 addr, u32* value)
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break;
case SPU_Out_MBox_offs:
ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index);
//ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index);
SPU.Out_MBox.PopUncond(*value); //if Out_MBox is empty yet, the result will be undefined
break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); while(!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break;
@ -89,7 +89,10 @@ bool RawSPUThread::Read32(const u64 addr, u32* value)
*value = SPU.MBox_Status.GetValue();
break;
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break;
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index); *value = SPU.Status.GetValue(); break;
case SPU_Status_offs:
//ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index);
*value = SPU.Status.GetValue();
break;
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.SNR[0].GetValue(); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.SNR[1].GetValue(); break;
@ -199,7 +202,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); while(!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_In_MBox_offs:
ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value);
//ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value);
SPU.In_MBox.PushUncond(value); //if In_MBox is already full, the last message will be overwritten
break;
case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break;

View File

@ -679,7 +679,11 @@ private:
//HGT uses signed values. HLGT uses unsigned values
void HGT(u32 rt, s32 ra, s32 rb)
{
if(CPU.GPR[ra]._i32[3] > CPU.GPR[rb]._i32[3]) CPU.Stop();
if (CPU.GPR[ra]._i32[3] > CPU.GPR[rb]._i32[3])
{
CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
CPU.Stop();
}
}
void CLZ(u32 rt, u32 ra)
{
@ -806,7 +810,11 @@ private:
}
void HLGT(u32 rt, u32 ra, u32 rb)
{
if(CPU.GPR[ra]._u32[3] > CPU.GPR[rb]._u32[3]) CPU.Stop();
if (CPU.GPR[ra]._u32[3] > CPU.GPR[rb]._u32[3])
{
CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
CPU.Stop();
}
}
void DFMA(u32 rt, u32 ra, u32 rb)
{
@ -1018,7 +1026,11 @@ private:
}
void HEQ(u32 rt, u32 ra, u32 rb)
{
if(CPU.GPR[ra]._i32[3] == CPU.GPR[rb]._i32[3]) CPU.Stop();
if (CPU.GPR[ra]._i32[3] == CPU.GPR[rb]._i32[3])
{
CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
CPU.Stop();
}
}
//0 - 9
@ -1373,7 +1385,11 @@ private:
}
void HGTI(u32 rt, u32 ra, s32 i10)
{
if(CPU.GPR[ra]._i32[3] > i10) CPU.Stop();
if (CPU.GPR[ra]._i32[3] > i10)
{
CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
CPU.Stop();
}
}
void CLGTI(u32 rt, u32 ra, s32 i10)
{
@ -1396,7 +1412,11 @@ private:
}
void HLGTI(u32 rt, u32 ra, s32 i10)
{
if(CPU.GPR[ra]._u32[3] > (u32)i10) CPU.Stop();
if (CPU.GPR[ra]._u32[3] > (u32)i10)
{
CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
CPU.Stop();
}
}
void MPYI(u32 rt, u32 ra, s32 i10)
{
@ -1425,7 +1445,11 @@ private:
}
void HEQI(u32 rt, u32 ra, s32 i10)
{
if(CPU.GPR[ra]._i32[3] == i10) CPU.Stop();
if (CPU.GPR[ra]._i32[3] == i10)
{
CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
CPU.Stop();
}
}

View File

@ -232,6 +232,7 @@ u8 SPURecompilerCore::DecodeMemory(const u64 address)
if (res > 0xffff)
{
CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
CPU.Stop();
res = ~res;
}

View File

@ -295,6 +295,22 @@ public:
EventManager SPUQs; // SPU Queue Mapping
SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu)
struct IntrTag
{
u32 enabled; // 1 == true
u32 thread; // established interrupt PPU thread
u64 mask;
u64 stat;
IntrTag()
: enabled(0)
, thread(0)
, mask(0)
, stat(0)
{
}
} m_intrtag[3];
template<size_t _max_count>
class Channel
{
@ -510,6 +526,7 @@ public:
struct
{
Channel<1> Out_MBox;
Channel<1> Out_IntrMBox;
Channel<4> In_MBox;
Channel<1> MBox_Status;
Channel<1> RunCntl;
@ -544,7 +561,7 @@ public:
{
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
if ((ea & 0xf0000000) == SYS_SPU_THREAD_BASE_LOW)
if (ea >= SYS_SPU_THREAD_BASE_LOW)
{
if (group)
{
@ -902,9 +919,24 @@ public:
case SPU_WrOutIntrMbox:
if (!group) // if RawSPU
{
// TODO: run PPU interrupt thread
ConLog.Error("SPU_WrOutIntrMbox interrupt unimplemented");
Emu.Pause();
if (Ini.HLELogging.GetValue()) ConLog.Write("SPU_WrOutIntrMbox: interrupt(v=0x%x)", v);
SPU.Out_IntrMBox.PushUncond(v);
m_intrtag[2].stat |= 1;
if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread))
{
while (t->IsAlive())
{
Sleep(1);
if (Emu.IsStopped())
{
ConLog.Warning("%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
return;
}
}
t->SetArg(0, t->m_interrupt_arg);
t->Run();
t->Exec();
}
}
else
{
@ -1223,6 +1255,7 @@ public:
// the real exit status
ConLog.Write("sys_spu_thread_exit (status=0x%x)", SPU.Out_MBox.GetValue());
}
SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP);
Stop();
break;
default:
@ -1234,6 +1267,7 @@ public:
{
ConLog.Error("Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue());
}
SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP);
Stop();
break;
}

View File

@ -102,15 +102,15 @@ static func_caller* sc_table[kSyscallTableLength] =
null_func,
null_func,//bind_func(sys_interrupt_tag_create) //80 (0x050)
null_func,//bind_func(sys_interrupt_tag_destroy) //81 (0x051)
bind_func(sys_interrupt_tag_destroy), //81 (0x051)
bind_func(sys_event_flag_create), //82 (0x052)
bind_func(sys_event_flag_destroy), //83 (0x053)
null_func,//bind_func(sys_interrupt_thread_establish) //84 (0x054)
bind_func(sys_interrupt_thread_establish), //84 (0x054)
bind_func(sys_event_flag_wait), //85 (0x055)
bind_func(sys_event_flag_trywait), //86 (0x056)
bind_func(sys_event_flag_set), //87 (0x057)
null_func,//bind_func(sys_interrupt_thread_eoi) //88 (0x058)
null_func,//bind_func(sys_interrupt_thread_disestablish)//89 (0x059)
bind_func(sys_interrupt_thread_eoi), //88 (0x058)
bind_func(sys_interrupt_thread_disestablish), //89 (0x059)
bind_func(sys_semaphore_create), //90 (0x05A)
bind_func(sys_semaphore_destroy), //91 (0x05B)
bind_func(sys_semaphore_wait), //92 (0x05C)
@ -174,20 +174,20 @@ static func_caller* sc_table[kSyscallTableLength] =
// Unused: 149
null_func,
null_func,//bind_func(sys_raw_spu_create_interrupt_tag) //150 (0x096)
null_func,//bind_func(sys_raw_spu_set_int_mask) //151 (0x097)
null_func,//bind_func(sys_raw_spu_get_int_mask) //152 (0x098)
null_func,//bind_func(sys_raw_spu_set_int_stat) //153 (0x099)
null_func,//bind_func(sys_raw_spu_get_int_stat) //154 (0x09A)
bind_func(sys_raw_spu_create_interrupt_tag), //150 (0x096)
bind_func(sys_raw_spu_set_int_mask), //151 (0x097)
bind_func(sys_raw_spu_get_int_mask), //152 (0x098)
bind_func(sys_raw_spu_set_int_stat), //153 (0x099)
bind_func(sys_raw_spu_get_int_stat), //154 (0x09A)
null_func,//bind_func(sys_spu_image_get_information?) //155 (0x09B)
bind_func(sys_spu_image_open), //156 (0x09C)
null_func,//bind_func(sys_spu_image_import) //157 (0x09D)
null_func,//bind_func(sys_spu_image_close) //158 (0x09E)
null_func,//bind_func(sys_raw_spu_load) //159 (0x09F)
bind_func(sys_raw_spu_create), //160 (0x0A0)
null_func,//bind_func(sys_raw_spu_destroy) //161 (0x0A1)
bind_func(sys_raw_spu_destroy), //161 (0x0A1)
null_func, //
null_func,//bind_func(sys_raw_spu_read_puint_mb) //163 (0x0A3)
bind_func(sys_raw_spu_read_puint_mb), //163 (0x0A3)
null_func, //
bind_func(sys_spu_thread_get_exit_status), //165 (0x0A5)
bind_func(sys_spu_thread_set_argument), //166 (0x0A6)
@ -220,8 +220,8 @@ static func_caller* sc_table[kSyscallTableLength] =
bind_func(sys_spu_thread_bind_queue), //193 (0x0C1)
bind_func(sys_spu_thread_unbind_queue), //194 (0x0C2)
null_func, //
null_func,//bind_func(sys_raw_spu_set_spu_cfg) //196 (0x0C4)
null_func,//bind_func(sys_raw_spu_get_spu_cfg) //197 (0x0C5)
bind_func(sys_raw_spu_set_spu_cfg), //196 (0x0C4)
bind_func(sys_raw_spu_get_spu_cfg), //197 (0x0C5)
null_func,//bind_func(sys_spu_thread_recover_page_fault)//198 (0x0C6)
null_func,//bind_func(sys_raw_spu_recover_page_fault) //199 (0x0C7)

View File

@ -358,7 +358,6 @@ extern int sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et);
extern int sys_spu_thread_group_disconnect_event(u32 id, u32 et);
extern int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr);
extern int sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup);
extern int sys_raw_spu_create(mem32_t id, u32 attr_addr);
extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type);
extern int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type);
@ -371,6 +370,22 @@ extern int sys_spu_thread_disconnect_event(u32 id, u32 event_type, u8 spup);
extern int sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num);
extern int sys_spu_thread_unbind_queue(u32 id, u32 spuq_num);
extern int sys_spu_thread_get_exit_status(u32 id, mem32_t status);
extern int sys_raw_spu_create(mem32_t id, u32 attr_addr);
extern int sys_raw_spu_destroy(u32 id);
extern int sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, mem32_t intrtag);
extern int sys_raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask);
extern int sys_raw_spu_get_int_mask(u32 id, u32 class_id, mem64_t mask);
extern int sys_raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat);
extern int sys_raw_spu_get_int_stat(u32 id, u32 class_id, mem64_t stat);
extern int sys_raw_spu_read_puint_mb(u32 id, mem32_t value);
extern int sys_raw_spu_set_spu_cfg(u32 id, u32 value);
extern int sys_raw_spu_get_spu_cfg(u32 id, mem32_t value);
//sys_interrupt
extern int sys_interrupt_tag_destroy(u32 intrtag);
extern int sys_interrupt_thread_establish(mem32_t ih, u32 intrtag, u64 intrthread, u64 arg);
extern int sys_interrupt_thread_disestablish(u32 ih);
extern void sys_interrupt_thread_eoi();
//sys_time
extern int sys_time_get_timezone(mem32_t timezone, mem32_t summertime);

View File

@ -0,0 +1,111 @@
#include "stdafx.h"
#include "Emu/ConLog.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/SysCalls/SC_FUNC.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/SysCalls.h"
#include "SC_Interrupt.h"
static SysCallBase sc_int("sys_interrupt");
int sys_interrupt_tag_destroy(u32 intrtag)
{
sc_int.Error("sys_interrupt_tag_destroy(intrtag=%d)", intrtag);
u32 id = intrtag & 0xff;
u32 class_id = intrtag >> 8;
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t || class_id > 2 || class_id == 1)
{
return CELL_ESRCH;
}
if (!t->m_intrtag[class_id].enabled)
{
return CELL_ESRCH;
}
if (t->m_intrtag[class_id].thread)
{
return CELL_EBUSY;
}
t->m_intrtag[class_id].enabled = 0;
return CELL_OK;
}
int sys_interrupt_thread_establish(mem32_t ih, u32 intrtag, u64 intrthread, u64 arg)
{
sc_int.Error("sys_interrupt_thread_establish(ih_addr=0x%x, intrtag=%d, intrthread=%lld, arg=0x%llx)", ih.GetAddr(), intrtag, intrthread, arg);
if (!ih.IsGood())
{
return CELL_EFAULT;
}
u32 id = intrtag & 0xff;
u32 class_id = intrtag >> 8;
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t || class_id > 2 || class_id == 1)
{
return CELL_ESRCH;
}
if (!t->m_intrtag[class_id].enabled)
{
return CELL_ESRCH;
}
if (t->m_intrtag[class_id].thread) // ???
{
return CELL_ESTAT;
}
CPUThread* it = Emu.GetCPU().GetThread(intrthread);
if (!it)
{
return CELL_ESRCH;
}
if (it->m_has_interrupt || !it->m_is_interrupt)
{
return CELL_EAGAIN;
}
ih = (t->m_intrtag[class_id].thread = intrthread);
it->m_interrupt_arg = arg;
return CELL_OK;
}
int sys_interrupt_thread_disestablish(u32 ih)
{
sc_int.Error("sys_interrupt_thread_disestablish(ih=%d)", ih);
CPUThread* it = Emu.GetCPU().GetThread(ih);
if (!it)
{
return CELL_ESRCH;
}
if (!it->m_has_interrupt || !it->m_is_interrupt)
{
return CELL_ESRCH;
}
// TODO: wait for sys_interrupt_thread_eoi() and destroy interrupt thread
return CELL_OK;
}
void sys_interrupt_thread_eoi()
{
sc_int.Log("sys_interrupt_thread_eoi()");
GetCurrentPPUThread().Stop();
return;
}

View File

@ -0,0 +1 @@
#pragma once

View File

@ -49,7 +49,7 @@ int sys_ppu_thread_yield()
int sys_ppu_thread_join(u64 thread_id, mem64_t vptr)
{
sysPrxForUser->Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr.GetAddr());
sysPrxForUser->Warning("sys_ppu_thread_join(thread_id=%lld, vptr_addr=0x%x)", thread_id, vptr.GetAddr());
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
if(!thr) return CELL_ESRCH;
@ -70,7 +70,7 @@ int sys_ppu_thread_join(u64 thread_id, mem64_t vptr)
int sys_ppu_thread_detach(u64 thread_id)
{
sysPrxForUser->Error("sys_ppu_thread_detach(thread_id=%d)", thread_id);
sysPrxForUser->Error("sys_ppu_thread_detach(thread_id=%lld)", thread_id);
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
if(!thr) return CELL_ESRCH;
@ -90,7 +90,7 @@ void sys_ppu_thread_get_join_state(u32 isjoinable_addr)
int sys_ppu_thread_set_priority(u64 thread_id, int prio)
{
sysPrxForUser->Log("sys_ppu_thread_set_priority(thread_id=%d, prio=%d)", thread_id, prio);
sysPrxForUser->Log("sys_ppu_thread_set_priority(thread_id=%lld, prio=%d)", thread_id, prio);
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
if(!thr) return CELL_ESRCH;
@ -102,7 +102,7 @@ int sys_ppu_thread_set_priority(u64 thread_id, int prio)
int sys_ppu_thread_get_priority(u64 thread_id, u32 prio_addr)
{
sysPrxForUser->Log("sys_ppu_thread_get_priority(thread_id=%d, prio_addr=0x%x)", thread_id, prio_addr);
sysPrxForUser->Log("sys_ppu_thread_get_priority(thread_id=%lld, prio_addr=0x%x)", thread_id, prio_addr);
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
if(!thr) return CELL_ESRCH;
@ -129,7 +129,7 @@ int sys_ppu_thread_get_stack_information(u32 info_addr)
int sys_ppu_thread_stop(u64 thread_id)
{
sysPrxForUser->Warning("sys_ppu_thread_stop(thread_id=%d)", thread_id);
sysPrxForUser->Warning("sys_ppu_thread_stop(thread_id=%lld)", thread_id);
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
if(!thr) return CELL_ESRCH;
@ -141,7 +141,7 @@ int sys_ppu_thread_stop(u64 thread_id)
int sys_ppu_thread_restart(u64 thread_id)
{
sysPrxForUser->Warning("sys_ppu_thread_restart(thread_id=%d)", thread_id);
sysPrxForUser->Warning("sys_ppu_thread_restart(thread_id=%lld)", thread_id);
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
if(!thr) return CELL_ESRCH;
@ -158,12 +158,12 @@ int sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, int prio, u32 s
if (Memory.IsGoodAddr(threadname_addr))
{
threadname = Memory.ReadString(threadname_addr);
sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))",
sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))",
thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr, threadname.c_str());
}
else
{
sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x)",
sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x)",
thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr);
if (threadname_addr != 0) return CELL_EFAULT;
}
@ -186,7 +186,6 @@ int sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, int prio, u32 s
}
case SYS_PPU_THREAD_CREATE_INTERRUPT:
{
sysPrxForUser->Error("sys_ppu_thread_create: unimplemented flag (SYS_PPU_THREAD_CREATE_INTERRUPT)");
is_interrupt = true;
break;
}
@ -201,12 +200,17 @@ int sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, int prio, u32 s
new_thread.SetPrio(prio);
new_thread.SetStackSize(stacksize);
//new_thread.flags = flags;
new_thread.m_has_interrupt = false;
new_thread.m_is_interrupt = is_interrupt;
new_thread.SetName(threadname);
ConLog.Write("*** New PPU Thread [%s] (flags=0x%llx, entry=0x%x): id = %d", new_thread.GetName().c_str(), flags, entry, new_thread.GetId());
new_thread.Run();
new_thread.Exec();
if (!is_interrupt)
{
new_thread.Run();
new_thread.Exec();
}
return CELL_OK;
}

View File

@ -364,20 +364,6 @@ int sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u
return CELL_OK;
}
//160
int sys_raw_spu_create(mem32_t id, u32 attr_addr)
{
sc_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id.GetAddr(), attr_addr);
//Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr));
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU);
id = ((RawSPUThread&)new_thread).GetIndex();
new_thread.Run();
new_thread.Exec();
return CELL_OK;
}
//169
int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
{
@ -760,3 +746,196 @@ int sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup)
return CELL_OK;
}
//160
int sys_raw_spu_create(mem32_t id, u32 attr_addr)
{
sc_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id.GetAddr(), attr_addr);
//Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr));
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU);
id = ((RawSPUThread&)new_thread).GetIndex();
new_thread.Run();
new_thread.Exec();
return CELL_OK;
}
int sys_raw_spu_destroy(u32 id)
{
sc_spu.Error("sys_raw_spu_destroy(id=%d)", id);
return CELL_OK;
}
int sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, mem32_t intrtag)
{
sc_spu.Error("sys_raw_spu_create_interrupt_tag(id=%d, class_id=%d, hwthread=0x%x, intrtag_addr=0x%x)", id, class_id, hwthread, intrtag.GetAddr());
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t)
{
return CELL_ESRCH;
}
if (class_id != 0 && class_id != 2)
{
return CELL_EINVAL;
}
if (!intrtag.IsGood())
{
return CELL_EFAULT;
}
if (t->m_intrtag[class_id].enabled)
{
return CELL_EAGAIN;
}
t->m_intrtag[class_id].enabled = 1;
intrtag = (id & 0xff) | (class_id << 8);
return CELL_OK;
}
int sys_raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask)
{
sc_spu.Warning("sys_raw_spu_set_int_mask(id=%d, class_id=%d, mask=0x%llx)", id, class_id, mask);
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t)
{
return CELL_ESRCH;
}
if (class_id != 0 && class_id != 2)
{
return CELL_EINVAL;
}
t->m_intrtag[class_id].mask = mask; // TODO: check this
return CELL_OK;
}
int sys_raw_spu_get_int_mask(u32 id, u32 class_id, mem64_t mask)
{
sc_spu.Log("sys_raw_spu_get_int_mask(id=%d, class_id=%d, mask_addr=0x%x)", id, class_id, mask.GetAddr());
if (!mask.IsGood())
{
return CELL_EFAULT;
}
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t)
{
return CELL_ESRCH;
}
if (class_id != 0 && class_id != 2)
{
return CELL_EINVAL;
}
mask = t->m_intrtag[class_id].mask;
return CELL_OK;
}
int sys_raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat)
{
sc_spu.Log("sys_raw_spu_set_int_stat(id=%d, class_id=%d, stat=0x%llx)", id, class_id, stat);
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t)
{
return CELL_ESRCH;
}
if (class_id != 0 && class_id != 2)
{
return CELL_EINVAL;
}
t->m_intrtag[class_id].stat = stat; // TODO: check this
return CELL_OK;
}
int sys_raw_spu_get_int_stat(u32 id, u32 class_id, mem64_t stat)
{
sc_spu.Log("sys_raw_spu_get_int_stat(id=%d, class_id=%d, stat_addr=0xx)", id, class_id, stat.GetAddr());
if (!stat.IsGood())
{
return CELL_EFAULT;
}
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t)
{
return CELL_ESRCH;
}
if (class_id != 0 && class_id != 2)
{
return CELL_EINVAL;
}
stat = t->m_intrtag[class_id].stat;
return CELL_OK;
}
int sys_raw_spu_read_puint_mb(u32 id, mem32_t value)
{
sc_spu.Log("sys_raw_spu_read_puint_mb(id=%d, value_addr=0x%x)", id, value.GetAddr());
if (!value.IsGood())
{
return CELL_EFAULT;
}
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t)
{
return CELL_ESRCH;
}
u32 v;
t->SPU.Out_IntrMBox.PopUncond(v);
value = v;
return CELL_OK;
}
int sys_raw_spu_set_spu_cfg(u32 id, u32 value)
{
sc_spu.Log("sys_raw_spu_set_spu_cfg(id=%d, value=0x%x)", id, value);
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t)
{
return CELL_ESRCH;
}
t->cfg.value = value;
return CELL_OK;
}
int sys_raw_spu_get_spu_cfg(u32 id, mem32_t value)
{
sc_spu.Log("sys_raw_spu_get_spu_afg(id=%d, value_addr=0x%x)", id, value.GetAddr());
if (!value.IsGood())
{
return CELL_EFAULT;
}
RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
if (!t)
{
return CELL_ESRCH;
}
value = t->cfg.value;
return CELL_OK;
}

View File

@ -97,6 +97,7 @@
<ClCompile Include="Emu\SysCalls\lv2\SC_FileSystem.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_GCM.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Heap.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Interrupt.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Keyboard.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwcond.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwmutex.cpp" />
@ -315,6 +316,7 @@
<ClInclude Include="Emu\SysCalls\lv2\SC_Condition.h" />
<ClInclude Include="Emu\SysCalls\lv2\SC_Event_flag.h" />
<ClInclude Include="Emu\SysCalls\lv2\SC_FileSystem.h" />
<ClInclude Include="Emu\SysCalls\lv2\SC_Interrupt.h" />
<ClInclude Include="Emu\SysCalls\lv2\SC_Lwcond.h" />
<ClInclude Include="Emu\SysCalls\lv2\SC_Lwmutex.h" />
<ClInclude Include="Emu\SysCalls\lv2\SC_Memory.h" />

View File

@ -578,6 +578,9 @@
<ClCompile Include="..\Utilities\SSemaphore.cpp">
<Filter>Utilities</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\lv2\SC_Interrupt.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@ -1048,5 +1051,8 @@
<ClInclude Include="Emu\SysCalls\lv2\SC_Semaphore.h">
<Filter>Emu\SysCalls\lv2</Filter>
</ClInclude>
<ClInclude Include="Emu\SysCalls\lv2\SC_Interrupt.h">
<Filter>Emu\SysCalls\lv2</Filter>
</ClInclude>
</ItemGroup>
</Project>