1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

CellSpurs initialization

This commit is contained in:
Nekotekina 2014-09-19 04:19:22 +04:00
parent df84e89d46
commit bb77249ac8
22 changed files with 599 additions and 272 deletions

View File

@ -153,7 +153,7 @@ union u128
std::string to_hex() const
{
return fmt::Format("%16llx%16llx", _u64[1], _u64[0]);
return fmt::Format("%016llx%016llx", _u64[1], _u64[0]);
}
std::string to_xyzw() const

View File

@ -13,13 +13,21 @@
#endif
template<size_t size>
void strcpy_trunc(char (&dst)[size], const std::string& src)
void strcpy_trunc(char(&dst)[size], const std::string& src)
{
const size_t count = (src.size() >= size) ? size - 1 /* truncation */ : src.size();
memcpy(dst, src.c_str(), count);
dst[count] = 0;
}
template<size_t size, size_t rsize>
void strcpy_trunc(char(&dst)[size], const char(&src)[rsize])
{
const size_t count = (rsize >= size) ? size - 1 /* truncation */ : rsize;
memcpy(dst, src, count);
dst[count] = 0;
}
#if defined(__GNUG__)
#include <cmath>
#include <stdlib.h>

View File

@ -25,7 +25,8 @@ template
class SMutexBase
{
static_assert(sizeof(T) == sizeof(std::atomic<T>), "Invalid SMutexBase type");
std::atomic<T> owner;
T owner;
typedef std::atomic<T> AT;
public:
static const T GetFreeValue()
@ -45,10 +46,10 @@ public:
owner = GetFreeValue();
}
SMutexBase()
{
initialize();
}
//SMutexBase()
//{
// initialize();
//}
void finalize()
{
@ -68,7 +69,7 @@ public:
}
T old = GetFreeValue();
if (!owner.compare_exchange_strong(old, tid))
if (!reinterpret_cast<AT&>(owner).compare_exchange_strong(old, tid))
{
if (old == tid)
{
@ -92,7 +93,7 @@ public:
}
T old = tid;
if (!owner.compare_exchange_strong(old, to))
if (!reinterpret_cast<AT&>(owner).compare_exchange_strong(old, to))
{
if (old == GetFreeValue())
{

View File

@ -2464,8 +2464,6 @@ private:
}
void DCBST(u32 ra, u32 rb)
{
//UNK("dcbst", false);
_mm_mfence();
}
void LWZUX(u32 rd, u32 ra, u32 rb)
{
@ -2521,8 +2519,6 @@ private:
}
void DCBF(u32 ra, u32 rb)
{
//UNK("dcbf", false);
_mm_mfence();
}
void LBZX(u32 rd, u32 ra, u32 rb)
{
@ -2739,8 +2735,6 @@ private:
}
void DCBTST(u32 ra, u32 rb, u32 th)
{
//UNK("dcbtst", false);
_mm_mfence();
}
void STBUX(u32 rs, u32 ra, u32 rb)
{
@ -2758,8 +2752,6 @@ private:
}
void DCBT(u32 ra, u32 rb, u32 th)
{
//UNK("dcbt", false);
_mm_mfence();
}
void LHZX(u32 rd, u32 ra, u32 rb)
{
@ -2796,7 +2788,6 @@ private:
}
void DST(u32 ra, u32 rb, u32 strm, u32 t)
{
_mm_mfence();
}
void LHAX(u32 rd, u32 ra, u32 rb)
{
@ -2825,7 +2816,6 @@ private:
}
void DSTST(u32 ra, u32 rb, u32 strm, u32 t)
{
_mm_mfence();
}
void LHAUX(u32 rd, u32 ra, u32 rb)
{
@ -3166,7 +3156,6 @@ private:
}
void DSS(u32 strm, u32 a)
{
_mm_mfence();
}
void SRAWI(u32 ra, u32 rs, u32 sh, bool rc)
{
@ -3239,7 +3228,6 @@ private:
auto const cache_line = vm::get_ptr<u8>(addr & ~127);
if (cache_line)
memset(cache_line, 0, 128);
_mm_mfence();
}
void LWZ(u32 rd, u32 ra, s32 d)
{

View File

@ -175,16 +175,16 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
return;
}
SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]);
u32 addr = (ea & SYS_SPU_THREAD_BASE_MASK) % SYS_SPU_THREAD_OFFSET;
if ((addr <= 0x3ffff) && (addr + size <= 0x40000))
{
SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]);
// LS access
ea = spu->dmac.ls_offset + addr;
}
else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2))
{
SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]);
spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(dmac.ls_offset + lsa));
return;
}

View File

@ -3,8 +3,13 @@
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/SysCalls/lv2/sys_spu.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/SysCalls/lv2/sys_memory.h"
#include "Emu/SysCalls/lv2/sys_process.h"
#include "Emu/SysCalls/lv2/sys_semaphore.h"
#include "Emu/SysCalls/lv2/sys_event.h"
#include "Emu/Cell/SPURSManager.h"
#include "sysPrxForUser.h"
#include "cellSpurs.h"
Module *cellSpurs = nullptr;
@ -14,27 +19,176 @@ extern u32 libsre;
extern u32 libsre_rtoc;
#endif
s64 spursCreateLv2EventQueue(vm::ptr<CellSpurs> spurs, u32& queue_id, u32 arg3, u32 arg4)
{
#ifdef PRX_DEBUG
vm::var<be_t<u32>> queue;
s32 res = cb_call<s32, vm::ptr<CellSpurs>, vm::ptr<be_t<u32>>, u32, u32>(GetCurrentPPUThread(), libsre + 0xB14C, libsre_rtoc,
spurs, queue, arg3, arg4);
queue_id = queue->ToLE();
return res;
#else
// TODO
queue_id = event_queue_create(SYS_SYNC_PRIORITY, SYS_PPU_QUEUE, *(u64*)"+QUEUE+", 0, 1);
return CELL_OK;
#endif
}
s64 spursInit(
vm::ptr<CellSpurs2> spurs,
u32 revision,
u32 sdkVersion,
s32 nSpus,
s32 spuPriority,
s32 ppuPriority,
vm::ptr<CellSpurs> spurs,
const u32 revision,
const u32 sdkVersion,
const s32 nSpus,
const s32 spuPriority,
const s32 ppuPriority,
u32 flags, // SpursAttrFlags
const char prefix[],
u32 prefixSize,
u32 container,
const u32 prefixSize,
const u32 container,
const u8 swlPriority[],
u32 swlMaxSpu,
u32 swlIsPreem)
const u32 swlMaxSpu,
const u32 swlIsPreem)
{
// internal function
#ifdef PRX_DEBUG
return cb_call<s32, vm::ptr<CellSpurs2>, u32, u32, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc,
#ifdef PRX_DEBUG_XXX
return cb_call<s32, vm::ptr<CellSpurs>, u32, u32, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc,
spurs, revision, sdkVersion, nSpus, spuPriority, ppuPriority, flags, Memory.RealToVirtualAddr(prefix), prefixSize, container, Memory.RealToVirtualAddr(swlPriority), swlMaxSpu, swlIsPreem);
#else
//spurs->spurs = new SPURSManager(attr);
// SPURS initialization (asserts should actually rollback and return the error instead)
if (!spurs)
{
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
}
if (spurs.addr() % 128)
{
return CELL_SPURS_CORE_ERROR_ALIGN;
}
if (prefixSize > CELL_SPURS_NAME_MAX_LENGTH)
{
return CELL_SPURS_CORE_ERROR_INVAL;
}
if (process_is_spu_lock_line_reservation_address(spurs.addr(), SYS_MEMORY_ACCESS_RIGHT_SPU_THR) != CELL_OK)
{
return CELL_SPURS_CORE_ERROR_PERM;
}
const bool isSecond = flags & SAF_SECOND_VERSION;
memset(spurs.get_ptr(), 0, CellSpurs::size1 + isSecond * CellSpurs::size2);
spurs->m.revision = revision;
spurs->m.sdkVersion = sdkVersion;
spurs->m.unk1 = 0xffffffffull;
spurs->m.unk2 = 0xffffffffull;
spurs->m.flags = flags;
memcpy(spurs->m.prefix, prefix, prefixSize);
spurs->m.prefixSize = (u8)prefixSize;
std::string name(prefix, prefixSize); // initialize name string
if (!isSecond)
{
spurs->m.unk0 = 0xffff;
}
spurs->m.unk6[0xC] = 0;
spurs->m.unk6[0xD] = 0;
spurs->m.unk6[0xE] = 0;
for (u32 i = 0; i < 8; i++)
{
spurs->m.unk6[i] = -1;
}
#ifdef PRX_DEBUG
spurs->m.unk7 = vm::read32(libsre_rtoc - 0x7EA4); // write 64-bit pointer to unknown data
#else
spurs->m.unk7 = 0x7ull << 48 | 0x7; // wrong 64-bit address
#endif
spurs->m.unk8 = 0ull;
spurs->m.unk9 = 0x2200;
spurs->m.unk10 = -1;
u32 sem;
for (u32 i = 0; i < 0x10; i++)
{
sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl");
assert(sem && ~sem); // should rollback if semaphore creating failed and return the error
spurs->m.sub1[i].sem = sem;
}
if (isSecond)
{
for (u32 i = 0; i < 0x10; i++)
{
sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl");
assert(sem && ~sem);
spurs->m.sub2[i].sem = sem;
}
}
sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuPrv");
assert(sem && ~sem);
spurs->m.semPrv = sem;
spurs->m.unk11 = -1;
spurs->m.unk12 = -1;
spurs->m.unk13 = 0;
spurs->m.nSpus = nSpus;
spurs->m.spuPriority = spuPriority;
#ifdef PRX_DEBUG
assert(spu_image_import(spurs->m.spuImg, vm::read32(libsre_rtoc - (isSecond ? 0x7E94 : 0x7E98)), 1) == CELL_OK);
#endif
//char str1[0x80];
//memcpy(str1, prefix, prefixSize); // strcpy
//memcpy(str1 + prefixSize, "CellSpursKernelGroup", 21); // strcat
s32 tgt = SYS_SPU_THREAD_GROUP_TYPE_NORMAL;
if (flags & SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT)
{
tgt = SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT;
}
else if (flags & SAF_UNKNOWN_FLAG_0)
{
tgt = 0xC02;
}
if (flags & SAF_SPU_MEMORY_CONTAINER_SET) tgt |= SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER;
if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) tgt |= SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM;
if (flags & SAF_UNKNOWN_FLAG_7) tgt |= 0x102;
if (flags & SAF_UNKNOWN_FLAG_8) tgt |= 0xC02;
if (flags & SAF_UNKNOWN_FLAG_9) tgt |= 0x800;
auto tg = spu_thread_group_create(name + "CellSpursKernelGroup", nSpus, spuPriority, tgt, container);
spurs->m.spuTG = tg->m_id;
name += "CellSpursKernel0";
for (s32 i = 0; i < nSpus; i++, name[name.size() - 1]++)
{
auto spu = spu_thread_initialize(tg, i, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, u64(i) << 32, spurs.addr(), 0, 0);
spurs->m.spus[i] = spu->GetId();
}
if (flags & SAF_SPU_PRINTF_ENABLED)
{
// spu_printf: attach group
if (!spu_printf_agcb || spu_printf_agcb(tg->m_id) != CELL_OK)
{
// remove flag if failed
spurs->m.flags &= ~SAF_SPU_PRINTF_ENABLED;
}
}
assert(lwmutex_create(spurs->m.mutex, SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, *(u64*)"_spuPrv") == CELL_OK);
assert(lwcond_create(spurs->m.cond, spurs->m.mutex, *(u64*)"_spuPrv") == CELL_OK);
spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK) << 7 | (isSecond ? 0x40 : 0);
spurs->m.unk15 = -1;
spurs->m.unk18 = -1;
spurs->_u8[0xD64] = 0;
spurs->_u8[0xD65] = 0;
spurs->_u8[0xD66] = 0;
spurs->m.ppuPriority = ppuPriority;
u32 queue;
assert(spursCreateLv2EventQueue(spurs, queue, spurs.addr() + 0xc9, 0x2a) == CELL_OK);
spurs->m.queue = queue;
u32 port = event_port_create(0);
assert(port && ~port);
spurs->m.port = port;
assert(sys_event_port_connect_local(port, queue) == CELL_OK);
return CELL_OK;
#endif
}
@ -48,7 +202,7 @@ s64 cellSpursInitialize(vm::ptr<CellSpurs> spurs, s32 nSpus, s32 spuPriority, s3
return GetCurrentPPUThread().FastCall2(libsre + 0x8480, libsre_rtoc);
#else
return spursInit(
vm::ptr<CellSpurs2>::make(spurs.addr()),
spurs,
0,
0,
nSpus,
@ -85,7 +239,7 @@ s64 cellSpursInitializeWithAttribute(vm::ptr<CellSpurs> spurs, vm::ptr<const Cel
}
return spursInit(
vm::ptr<CellSpurs2>::make(spurs.addr()),
spurs,
attr->m.revision,
attr->m.sdkVersion,
attr->m.nSpus,
@ -101,7 +255,7 @@ s64 cellSpursInitializeWithAttribute(vm::ptr<CellSpurs> spurs, vm::ptr<const Cel
#endif
}
s64 cellSpursInitializeWithAttribute2(vm::ptr<CellSpurs2> spurs, vm::ptr<const CellSpursAttribute> attr)
s64 cellSpursInitializeWithAttribute2(vm::ptr<CellSpurs> spurs, vm::ptr<const CellSpursAttribute> attr)
{
cellSpurs->Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, attr_addr=0x%x)", spurs.addr(), attr.addr());
@ -128,7 +282,7 @@ s64 cellSpursInitializeWithAttribute2(vm::ptr<CellSpurs2> spurs, vm::ptr<const C
attr->m.nSpus,
attr->m.spuPriority,
attr->m.ppuPriority,
attr->m.flags.ToLE() | (attr->m.exitIfNoWork ? SAF_EXIT_IF_NO_WORK : 0) | 4, // +add unknown flag
attr->m.flags.ToLE() | (attr->m.exitIfNoWork ? SAF_EXIT_IF_NO_WORK : 0) | SAF_SECOND_VERSION,
attr->m.prefix,
attr->m.prefixSize,
attr->m.container,

View File

@ -1,4 +1,7 @@
#pragma once
#include "Emu/SysCalls/lv2/sys_lwmutex.h"
#include "Emu/SysCalls/lv2/sys_lwcond.h"
#include "Emu/SysCalls/lv2/sys_spu.h"
// Core return codes.
enum
@ -80,26 +83,20 @@ class SPURSManager;
class SPURSManagerEventFlag;
class SPURSManagerTaskset;
// Core CellSpurs structures.
struct CellSpurs
{
SPURSManager *spurs;
};
struct CellSpurs2
{
SPURSManager *spurs;
};
enum SpursAttrFlags : u32
{
SAF_NONE = 0x0,
SAF_NONE = 0x0,
SAF_EXIT_IF_NO_WORK = 0x1,
SAF_SECOND_VERSION = 0x4,
SAF_UNKNOWN_FLAG_9 = 0x00400000,
SAF_UNKNOWN_FLAG_8 = 0x00800000,
SAF_UNKNOWN_FLAG_7 = 0x01000000,
SAF_SYSTEM_WORKLOAD_ENABLED = 0x02000000,
SAF_SPU_PRINTF_ENABLED = 0x10000000,
SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT = 0x20000000,
SAF_SPU_MEMORY_CONTAINER_SET = 0x40000000,
SAF_UNKNOWN_FLAG_0 = 0x80000000,
};
struct CellSpursAttribute
@ -113,7 +110,7 @@ struct CellSpursAttribute
u8 _u8[size];
struct { be_t<u32> _u32[size / sizeof(u32)]; };
// real structure
// real data
struct
{
be_t<u32> revision; // 0x0
@ -140,6 +137,90 @@ struct CellSpursAttribute
};
};
// Core CellSpurs structures
struct CellSpurs
{
static const uint align = 128;
static const uint size = 0x2000; // size of CellSpurs2
static const uint size1 = 0x1000; // size of CellSpurs
static const uint size2 = 0x1000;
struct _sub_str1
{
static const uint size = 0x80;
be_t<u64> sem;
u8 unk_[0x78];
};
union
{
// raw data
u8 _u8[size];
std::array<be_t<u32>, size / sizeof(u32)> _u32;
// real data
struct
{
u8 unknown[0x6C];
be_t<u32> unk18; // 0x6C
u8 unk17[4]; // 0x70
u8 flags1; // 0x74
u8 unk16; // 0x75
u8 nSpus; // 0x76
u8 unk15; // 0x77
u8 unknown0[0xB0 - 0x78];
be_t<u32> unk0; // 0x0B0
u8 unknown2[0xC0 - 0xB4];
u8 unk6[0x10]; // 0x0C0
u8 unknown1[0x120 - 0x0D0];
_sub_str1 sub1[0x10]; // 0x120
u8 unknown7[0x980 - 0x920];
be_t<u64> semPrv; // 0x980
be_t<u32> unk11; // 0x988
be_t<u32> unk12; // 0x98C
be_t<u64> unk13; // 0x990
u8 unknown4[0xD00 - 0x998];
be_t<u64> unk7; // 0xD00
be_t<u64> unk8; // 0xD08
be_t<u32> unk9; // 0xD10
u8 unk10; // 0xD14
u8 unknown5[0xD20 - 0xD15];
be_t<u64> unk1; // 0xD20
be_t<u64> unk2; // 0xD28
be_t<u32> spuTG; // 0xD30
be_t<u32> spus[8]; // 0xD34
u8 unknown3[0xD5C - 0xD54];
be_t<u32> queue; // 0xD5C
be_t<u32> port; // 0xD60
u8 unk19[0xC]; // 0xD64
sys_spu_image spuImg; // 0xD70
be_t<u32> flags; // 0xD80
be_t<s32> spuPriority;// 0xD84
be_t<u32> ppuPriority;// 0xD88
char prefix[0x0f]; // 0xD8C
u8 prefixSize; // 0xD9B
be_t<u32> unk5; // 0xD9C
be_t<u32> revision; // 0xDA0
be_t<u32> sdkVersion; // 0xDA4
u8 unknown8[0xDB0 - 0xDA8];
sys_lwmutex_t mutex; // 0xDB0
sys_lwcond_t cond; // 0xDC8
u8 unknown6[0x1220 - 0xDD0];
_sub_str1 sub2[0x10]; // 0x1220
// ...
} m;
// alternative implementation
struct
{
SPURSManager *spurs;
} c;
};
};
typedef CellSpurs CellSpurs2;
struct CellSpursEventFlag
{
SPURSManagerEventFlag *eventFlag;

View File

@ -5,7 +5,6 @@
#include "Emu/SysCalls/Callback.h"
#include "Emu/FS/vfsFile.h"
#include "Emu/FS/vfsStreamMemory.h"
#include "Emu/SysCalls/lv2/sys_spu.h"
#include "Emu/SysCalls/lv2/sys_lwmutex.h"
#include "Emu/SysCalls/lv2/sys_spinlock.h"
@ -21,8 +20,6 @@
Module *sysPrxForUser = nullptr;
extern u32 LoadSpuImage(vfsStream& stream, u32& spu_ep);
int _sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size)
{
sysPrxForUser->Warning("_sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size);
@ -97,18 +94,9 @@ int sys_spu_elf_get_segments(u32 elf_img, vm::ptr<sys_spu_segment> segments, int
int sys_spu_image_import(vm::ptr<sys_spu_image> img, u32 src, u32 type)
{
sysPrxForUser->Warning("sys_spu_image_import(img=0x%x, src=0x%x, type=0x%x)", img.addr(), src, type);
sysPrxForUser->Warning("sys_spu_image_import(img=0x%x, src=0x%x, type=%d)", img.addr(), src, type);
vfsStreamMemory f(src);
u32 entry;
u32 offset = LoadSpuImage(f, entry);
img->type = type;
img->entry_point = entry;
img->segs_addr = offset;
img->nsegs = 0;
return CELL_OK;
return spu_image_import(*img, src, type);
}
int sys_spu_image_close(vm::ptr<sys_spu_image> img)
@ -143,7 +131,7 @@ int sys_raw_spu_image_load(int id, vm::ptr<sys_spu_image> img)
sysPrxForUser->Warning("sys_raw_spu_image_load(id=0x%x, img_addr=0x%x)", id, img.addr());
// TODO: use segment info
memcpy(vm::get_ptr<void>(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id), vm::get_ptr<void>(img->segs_addr), 256 * 1024);
memcpy(vm::get_ptr<void>(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id), vm::get_ptr<void>(img->addr), 256 * 1024);
vm::write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, (u32)img->entry_point);
return CELL_OK;
@ -235,8 +223,6 @@ vm::ptr<char> _sys_strncpy(vm::ptr<char> dest, vm::ptr<const char> source, u32 l
return dest;
}
typedef s32(*spu_printf_cb_t)(u32 arg);
vm::ptr<spu_printf_cb_t> spu_printf_agcb;
vm::ptr<spu_printf_cb_t> spu_printf_dgcb;
vm::ptr<spu_printf_cb_t> spu_printf_atcb;
@ -270,68 +256,63 @@ s32 _sys_spu_printf_finalize()
return CELL_OK;
}
s64 _sys_spu_printf_attach_group(u32 arg)
s64 _sys_spu_printf_attach_group(u32 group)
{
sysPrxForUser->Warning("_sys_spu_printf_attach_group(arg=0x%x)", arg);
sysPrxForUser->Warning("_sys_spu_printf_attach_group(group=%d)", group);
if (!spu_printf_agcb)
{
return CELL_ESTAT;
}
return spu_printf_agcb(arg);
return spu_printf_agcb(group);
}
s64 _sys_spu_printf_detach_group(u32 arg)
s64 _sys_spu_printf_detach_group(u32 group)
{
sysPrxForUser->Warning("_sys_spu_printf_detach_group(arg=0x%x)", arg);
sysPrxForUser->Warning("_sys_spu_printf_detach_group(group=%d)", group);
if (!spu_printf_dgcb)
{
return CELL_ESTAT;
}
return spu_printf_dgcb(arg);
return spu_printf_dgcb(group);
}
s64 _sys_spu_printf_attach_thread(u32 arg)
s64 _sys_spu_printf_attach_thread(u32 thread)
{
sysPrxForUser->Warning("_sys_spu_printf_attach_thread(arg=0x%x)", arg);
sysPrxForUser->Warning("_sys_spu_printf_attach_thread(thread=%d)", thread);
if (!spu_printf_atcb)
{
return CELL_ESTAT;
}
return spu_printf_atcb(arg);
return spu_printf_atcb(thread);
}
s64 _sys_spu_printf_detach_thread(u32 arg)
s64 _sys_spu_printf_detach_thread(u32 thread)
{
sysPrxForUser->Warning("_sys_spu_printf_detach_thread(arg=0x%x)", arg);
sysPrxForUser->Warning("_sys_spu_printf_detach_thread(thread=%d)", thread);
if (!spu_printf_dtcb)
{
return CELL_ESTAT;
}
return spu_printf_dtcb(arg);
return spu_printf_dtcb(thread);
}
s32 _sys_snprintf(vm::ptr<char> dst, u32 count, vm::ptr<const char> fmt, u32 a1, u32 a2) // va_args...
s32 _sys_snprintf(vm::ptr<char> dst, u32 count, vm::ptr<const char> fmt) // va_args...
{
sysPrxForUser->Todo("_sys_snprintf(dst_addr=0x%x, count=%d, fmt_addr=0x%x['%s'], ...)", dst.addr(), count, fmt.addr(), fmt.get_ptr());
if (std::string(fmt.get_ptr()) == "%s_%08x")
{
return snprintf(dst.get_ptr(), count, fmt.get_ptr(), vm::get_ptr<char>(a1), a2);
}
Emu.Pause();
return 0;
}
s32 _sys_printf(vm::ptr<const char> fmt)
s32 _sys_printf(vm::ptr<const char> fmt) // va_args...
{
sysPrxForUser->Todo("_sys_printf(fmt_addr=0x%x, ...)", fmt.addr());

View File

@ -1,4 +1,4 @@
# pragma once
#pragma once
struct HeapInfo
{
@ -14,5 +14,13 @@ struct HeapInfo
}
};
typedef s32(*spu_printf_cb_t)(u32 arg);
// Aux
extern vm::ptr<spu_printf_cb_t> spu_printf_agcb;
extern vm::ptr<spu_printf_cb_t> spu_printf_dgcb;
extern vm::ptr<spu_printf_cb_t> spu_printf_atcb;
extern vm::ptr<spu_printf_cb_t> spu_printf_dtcb;
// SysCalls
vm::ptr<void> _sys_memset(vm::ptr<void> dst, s32 value, u32 size);

View File

@ -27,6 +27,7 @@ struct Cond
, m_queue(name)
, signaler(0)
{
signal.initialize();
}
};

View File

@ -10,7 +10,24 @@
SysCallBase sys_event("sys_event");
s32 sys_event_queue_create(vm::ptr<be_t<u32>> equeue_id, vm::ptr<sys_event_queue_attr> attr, u64 event_queue_key, int size)
u32 event_queue_create(u32 protocol, s32 type, u64 name_u64, u64 event_queue_key, s32 size)
{
EventQueue* eq = new EventQueue(protocol, type, name_u64, event_queue_key, size);
if (event_queue_key && !Emu.GetEventManager().RegisterKey(eq, event_queue_key))
{
delete eq;
return 0;
}
std::string name((const char*)&name_u64, 8);
u32 id = sys_event.GetNewId(eq, TYPE_EVENT_QUEUE);
sys_event.Warning("*** event_queue created [%s] (protocol=0x%x, type=0x%x, key=0x%llx, size=0x%x): id = %d",
name.c_str(), protocol, type, event_queue_key, size, id);
return id;
}
s32 sys_event_queue_create(vm::ptr<be_t<u32>> equeue_id, vm::ptr<sys_event_queue_attr> attr, u64 event_queue_key, s32 size)
{
sys_event.Warning("sys_event_queue_create(equeue_id_addr=0x%x, attr_addr=0x%x, event_queue_key=0x%llx, size=%d)",
equeue_id.addr(), attr.addr(), event_queue_key, size);
@ -33,7 +50,7 @@ s32 sys_event_queue_create(vm::ptr<be_t<u32>> equeue_id, vm::ptr<sys_event_queue
{
case se32(SYS_PPU_QUEUE): break;
case se32(SYS_SPU_QUEUE): break;
default: sys_event.Error("Unknown 0x%x type attr", (u32)attr->type); return CELL_EINVAL;
default: sys_event.Error("Unknown 0x%x type attr", (s32)attr->type); return CELL_EINVAL;
}
if (event_queue_key && Emu.GetEventManager().CheckKey(event_queue_key))
@ -41,20 +58,13 @@ s32 sys_event_queue_create(vm::ptr<be_t<u32>> equeue_id, vm::ptr<sys_event_queue
return CELL_EEXIST;
}
EventQueue* eq = new EventQueue((u32)attr->protocol, (int)attr->type, attr->name_u64, event_queue_key, size);
if (event_queue_key && !Emu.GetEventManager().RegisterKey(eq, event_queue_key))
if (u32 id = event_queue_create(attr->protocol, attr->type, attr->name_u64, event_queue_key, size))
{
delete eq;
return CELL_EAGAIN;
*equeue_id = id;
return CELL_OK;
}
u32 id = sys_event.GetNewId(eq, TYPE_EVENT_QUEUE);
*equeue_id = id;
sys_event.Warning("*** event_queue created [%s] (protocol=0x%x, type=0x%x): id = %d",
std::string(attr->name, 8).c_str(), (u32)attr->protocol, (int)attr->type, id);
return CELL_OK;
return CELL_EAGAIN;
}
s32 sys_event_queue_destroy(u32 equeue_id, int mode)
@ -102,7 +112,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, int mode)
return CELL_OK;
}
s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_data> event_array, int size, vm::ptr<be_t<u32>> number)
s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_data> event_array, s32 size, vm::ptr<be_t<u32>> number)
{
sys_event.Todo("sys_event_queue_tryreceive(equeue_id=%d, event_array_addr=0x%x, size=%d, number_addr=0x%x)",
equeue_id, event_array.addr(), size, number.addr());
@ -225,7 +235,16 @@ s32 sys_event_queue_drain(u32 equeue_id)
return CELL_OK;
}
s32 sys_event_port_create(vm::ptr<be_t<u32>> eport_id, int port_type, u64 name)
u32 event_port_create(u64 name)
{
EventPort* eport = new EventPort();
u32 id = sys_event.GetNewId(eport, TYPE_EVENT_PORT);
eport->name = name ? name : ((u64)process_getpid() << 32) | (u64)id;
sys_event.Warning("*** sys_event_port created: id = %d", id);
return id;
}
s32 sys_event_port_create(vm::ptr<be_t<u32>> eport_id, s32 port_type, u64 name)
{
sys_event.Warning("sys_event_port_create(eport_id_addr=0x%x, port_type=0x%x, name=0x%llx)",
eport_id.addr(), port_type, name);
@ -236,12 +255,7 @@ s32 sys_event_port_create(vm::ptr<be_t<u32>> eport_id, int port_type, u64 name)
return CELL_EINVAL;
}
EventPort* eport = new EventPort();
u32 id = sys_event.GetNewId(eport, TYPE_EVENT_PORT);
eport->name = name ? name : ((u64)process_getpid() << 32) | (u64)id;
*eport_id = id;
sys_event.Warning("*** sys_event_port created: id = %d", id);
*eport_id = event_port_create(name);
return CELL_OK;
}

View File

@ -37,7 +37,7 @@ enum EventSourceKey : u64
struct sys_event_queue_attr
{
be_t<u32> protocol; // SYS_SYNC_PRIORITY or SYS_SYNC_FIFO
be_t<int> type; // SYS_PPU_QUEUE or SYS_SPU_QUEUE
be_t<s32> type; // SYS_PPU_QUEUE or SYS_SPU_QUEUE
union
{
char name[8];
@ -212,17 +212,22 @@ struct EventQueue
, key(key)
, events(size) // size: max event count this queue can hold
{
owner.initialize();
}
};
// Aux
u32 event_port_create(u64 name);
u32 event_queue_create(u32 protocol, s32 type, u64 name_u64, u64 event_queue_key, s32 size);
// SysCalls
s32 sys_event_queue_create(vm::ptr<be_t<u32>> equeue_id, vm::ptr<sys_event_queue_attr> attr, u64 event_queue_key, int size);
s32 sys_event_queue_destroy(u32 equeue_id, int mode);
s32 sys_event_queue_create(vm::ptr<be_t<u32>> equeue_id, vm::ptr<sys_event_queue_attr> attr, u64 event_queue_key, s32 size);
s32 sys_event_queue_destroy(u32 equeue_id, s32 mode);
s32 sys_event_queue_receive(u32 equeue_id, vm::ptr<sys_event_data> event, u64 timeout);
s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_data> event_array, int size, vm::ptr<be_t<u32>> number);
s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_data> event_array, s32 size, vm::ptr<be_t<u32>> number);
s32 sys_event_queue_drain(u32 event_queue_id);
s32 sys_event_port_create(vm::ptr<be_t<u32>> eport_id, int port_type, u64 name);
s32 sys_event_port_create(vm::ptr<be_t<u32>> eport_id, s32 port_type, u64 name);
s32 sys_event_port_destroy(u32 eport_id);
s32 sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id);
s32 sys_event_port_disconnect(u32 eport_id);

View File

@ -45,6 +45,8 @@ struct EventFlag
, m_protocol(protocol)
, m_type(type)
{
m_mutex.initialize();
signal.initialize();
}
u32 check();

View File

@ -9,21 +9,29 @@
SysCallBase sys_lwcond("sys_lwcond");
s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64)
{
u32 id = sys_lwcond.GetNewId(new Lwcond(name_u64), TYPE_LWCOND);
u32 addr = Memory.RealToVirtualAddr(&lwmutex);
lwcond.lwmutex.set(be_t<u32>::MakeFromLE(addr));
lwcond.lwcond_queue = id;
std::string name((const char*)&name_u64, 8);
sys_lwcond.Warning("*** lwcond created [%s] (lwmutex_addr=0x%x): id = %d",
name.c_str(), addr, id);
Emu.GetSyncPrimManager().AddSyncPrimData(TYPE_LWCOND, id, name);
return CELL_OK;
}
s32 sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwcond_attribute_t> attr)
{
sys_lwcond.Log("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)",
lwcond.addr(), lwmutex.addr(), attr.addr());
u32 id = sys_lwcond.GetNewId(new Lwcond(attr->name_u64), TYPE_LWCOND);
lwcond->lwmutex = lwmutex.addr();
lwcond->lwcond_queue = id;
sys_lwcond.Warning("*** lwcond created [%s] (lwmutex_addr=0x%x): id = %d",
std::string(attr->name, 8).c_str(), lwmutex.addr(), (u32) lwcond->lwcond_queue);
Emu.GetSyncPrimManager().AddSyncPrimData(TYPE_LWCOND, id, std::string(attr->name, 8));
return CELL_OK;
return lwcond_create(*lwcond, *lwmutex, attr->name_u64);
}
s32 sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond)
@ -58,7 +66,7 @@ s32 sys_lwcond_signal(vm::ptr<sys_lwcond_t> lwcond)
return CELL_ESRCH;
}
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex);
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex.addr());
if (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop()))
{
@ -84,7 +92,7 @@ s32 sys_lwcond_signal_all(vm::ptr<sys_lwcond_t> lwcond)
return CELL_ESRCH;
}
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex);
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex.addr());
while (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop()))
{
@ -144,7 +152,7 @@ s32 sys_lwcond_wait(vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
return CELL_ESRCH;
}
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex);
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex.addr());
u32 tid_le = GetCurrentPPUThread().GetId();
be_t<u32> tid = be_t<u32>::MakeFromLE(tid_le);

View File

@ -1,5 +1,7 @@
#pragma once
struct sys_lwmutex_t;
struct sys_lwcond_attribute_t
{
union
@ -11,7 +13,7 @@ struct sys_lwcond_attribute_t
struct sys_lwcond_t
{
be_t<u32> lwmutex;
vm::bptr<sys_lwmutex_t> lwmutex;
be_t<u32> lwcond_queue;
};
@ -23,9 +25,13 @@ struct Lwcond
Lwcond(u64 name)
: m_queue(name)
{
signal.initialize();
}
};
// Aux
s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64);
// SysCalls
s32 sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwcond_attribute_t> attr);
s32 sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond);

View File

@ -11,43 +11,45 @@ SysCallBase sys_lwmutex("sys_lwmutex");
// TODO: move SleepQueue somewhere
s32 lwmutex_create(sys_lwmutex_t& lwmutex, u32 protocol, u32 recursive, u64 name_u64)
{
LV2_LOCK(0);
lwmutex.all_info() = 0;
lwmutex.attribute = protocol | recursive;
lwmutex.recursive_count = 0;
u32 sq_id = sys_lwmutex.GetNewId(new SleepQueue(name_u64), TYPE_LWMUTEX);
lwmutex.sleep_queue = sq_id;
std::string name((const char*)&name_u64, 8);
sys_lwmutex.Notice("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d", name.c_str(), protocol | recursive, sq_id);
Emu.GetSyncPrimManager().AddLwMutexData(sq_id, name, GetCurrentPPUThread().GetId());
return CELL_OK;
}
s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr)
{
sys_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
lwmutex.addr(), attr.addr());
sys_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr=0x%x, attr_addr=0x%x)", lwmutex.addr(), attr.addr());
switch (attr->attr_recursive.ToBE())
switch (attr->recursive.ToBE())
{
case se32(SYS_SYNC_RECURSIVE): break;
case se32(SYS_SYNC_NOT_RECURSIVE): break;
default: sys_lwmutex.Error("Unknown recursive attribute(0x%x)", (u32)attr->attr_recursive); return CELL_EINVAL;
default: sys_lwmutex.Error("Unknown recursive attribute(0x%x)", (u32)attr->recursive); return CELL_EINVAL;
}
switch (attr->attr_protocol.ToBE())
switch (attr->protocol.ToBE())
{
case se32(SYS_SYNC_PRIORITY): break;
case se32(SYS_SYNC_RETRY): break;
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_lwmutex.Error("Invalid SYS_SYNC_PRIORITY_INHERIT protocol attr"); return CELL_EINVAL;
case se32(SYS_SYNC_FIFO): break;
default: sys_lwmutex.Error("Unknown protocol attribute(0x%x)", (u32)attr->attr_protocol); return CELL_EINVAL;
default: sys_lwmutex.Error("Unknown protocol attribute(0x%x)", (u32)attr->protocol); return CELL_EINVAL;
}
lwmutex->attribute = attr->attr_protocol | attr->attr_recursive;
lwmutex->waiter = 0;
lwmutex->mutex.initialize();
//lwmutex->waiter = lwmutex->owner.GetOwner();
lwmutex->pad = 0;
lwmutex->recursive_count = 0;
u32 sq_id = sys_lwmutex.GetNewId(new SleepQueue(attr->name_u64), TYPE_LWMUTEX);
lwmutex->sleep_queue = sq_id;
sys_lwmutex.Warning("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d",
std::string(attr->name, 8).c_str(), (u32) lwmutex->attribute, sq_id);
Emu.GetSyncPrimManager().AddLwMutexData(sq_id, std::string(attr->name, 8), GetCurrentPPUThread().GetId());
return CELL_OK;
return lwmutex_create(*lwmutex, attr->protocol, attr->recursive, attr->name_u64);
}
s32 sys_lwmutex_destroy(vm::ptr<sys_lwmutex_t> lwmutex)

View File

@ -29,8 +29,8 @@ enum
struct sys_lwmutex_attribute_t
{
be_t<u32> attr_protocol;
be_t<u32> attr_recursive;
be_t<u32> protocol;
be_t<u32> recursive;
union
{
char name[8];
@ -66,19 +66,26 @@ struct SleepQueue
struct sys_lwmutex_t
{
/* volatile */ SMutexBase<be_t<u32>> mutex;
/* volatile */ be_t<u32> waiter; // not used
u64 &all_info(){return *(reinterpret_cast<u64*>(this));}
SMutexBase<be_t<u32>> mutex;
be_t<u32> waiter; // currently not used
be_t<u32> attribute;
be_t<u32> recursive_count;
be_t<u32> sleep_queue;
be_t<u32> pad;
u64& all_info()
{
return *(reinterpret_cast<u64*>(this));
}
int trylock(be_t<u32> tid);
int unlock(be_t<u32> tid);
int lock(be_t<u32> tid, u64 timeout);
};
// Aux
s32 lwmutex_create(sys_lwmutex_t& lwmutex, u32 protocol, u32 recursive, u64 name_u64);
// SysCalls
s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr);
s32 sys_lwmutex_destroy(vm::ptr<sys_lwmutex_t> lwmutex);

View File

@ -34,6 +34,7 @@ struct Mutex
, m_queue(name)
, cond_count(0)
{
m_mutex.initialize();
}
~Mutex();

View File

@ -5,13 +5,23 @@
#include "Emu/CPU/CPUThreadManager.h"
#include "Emu/Cell/PPUThread.h"
#include "sys_semaphore.h"
#include "sys_time.h"
//#include "Utilities/SMutex.h"
#include "sys_semaphore.h"
SysCallBase sys_semaphore("sys_semaphore");
s32 sys_semaphore_create(vm::ptr<be_t<u32>> sem, vm::ptr<sys_semaphore_attribute> attr, int initial_count, int max_count)
u32 semaphore_create(s32 initial_count, s32 max_count, u32 protocol, u64 name_u64)
{
LV2_LOCK(0);
const std::string name((const char*)&name_u64, 8);
const u32 id = sys_semaphore.GetNewId(new Semaphore(initial_count, max_count, protocol, name_u64), TYPE_SEMAPHORE);
sys_semaphore.Notice("*** semaphore created [%s] (protocol=0x%x): id = %d", name.c_str(), protocol, id);
Emu.GetSyncPrimManager().AddSemaphoreData(id, name, initial_count, max_count);
return id;
}
s32 sys_semaphore_create(vm::ptr<be_t<u32>> sem, vm::ptr<sys_semaphore_attribute> attr, s32 initial_count, s32 max_count)
{
sys_semaphore.Warning("sys_semaphore_create(sem_addr=0x%x, attr_addr=0x%x, initial_count=%d, max_count=%d)",
sem.addr(), attr.addr(), initial_count, max_count);
@ -37,13 +47,7 @@ s32 sys_semaphore_create(vm::ptr<be_t<u32>> sem, vm::ptr<sys_semaphore_attribute
default: sys_semaphore.Error("Unknown protocol attribute(0x%x)", (u32)attr->protocol); return CELL_EINVAL;
}
u32 id = sys_semaphore.GetNewId(new Semaphore(initial_count, max_count, attr->protocol, attr->name_u64), TYPE_SEMAPHORE);
*sem = id;
sys_semaphore.Notice("*** semaphore created [%s] (protocol=0x%x): id = %d",
std::string(attr->name, 8).c_str(), (u32)attr->protocol, id);
Emu.GetSyncPrimManager().AddSemaphoreData(id, std::string(attr->name, 8), initial_count, max_count);
*sem = semaphore_create(initial_count, max_count, attr->protocol, attr->name_u64);
return CELL_OK;
}
@ -144,7 +148,7 @@ s32 sys_semaphore_trywait(u32 sem_id)
}
}
s32 sys_semaphore_post(u32 sem_id, int count)
s32 sys_semaphore_post(u32 sem_id, s32 count)
{
sys_semaphore.Log("sys_semaphore_post(sem_id=%d, count=%d)", sem_id, count);
@ -159,7 +163,7 @@ s32 sys_semaphore_post(u32 sem_id, int count)
return CELL_EINVAL;
}
if (count + sem->m_value - (int)sem->m_queue.count() > sem->max)
if (count + sem->m_value - (s32)sem->m_queue.count() > sem->max)
{
return CELL_EBUSY;
}

View File

@ -7,7 +7,7 @@ struct sys_semaphore_attribute
be_t<u32> protocol;
be_t<u32> pshared; // undefined
be_t<u64> ipc_key; // undefined
be_t<int> flags; // undefined
be_t<s32> flags; // undefined
be_t<u32> pad; // not used
union
{
@ -20,14 +20,14 @@ struct Semaphore
{
std::mutex m_mutex;
SleepQueue m_queue;
int m_value;
s32 m_value;
u32 signal;
const int max;
const s32 max;
const u32 protocol;
const u64 name;
Semaphore(int initial_count, int max_count, u32 protocol, u64 name)
Semaphore(s32 initial_count, s32 max_count, u32 protocol, u64 name)
: m_value(initial_count)
, signal(0)
, max(max_count)
@ -37,10 +37,13 @@ struct Semaphore
}
};
// Aux
u32 semaphore_create(s32 initial_count, s32 max_count, u32 protocol, u64 name_u64);
// SysCalls
s32 sys_semaphore_create(vm::ptr<be_t<u32>> sem, vm::ptr<sys_semaphore_attribute> attr, int initial_count, int max_count);
s32 sys_semaphore_create(vm::ptr<be_t<u32>> sem, vm::ptr<sys_semaphore_attribute> attr, s32 initial_count, s32 max_count);
s32 sys_semaphore_destroy(u32 sem_id);
s32 sys_semaphore_wait(u32 sem_id, u64 timeout);
s32 sys_semaphore_trywait(u32 sem_id);
s32 sys_semaphore_post(u32 sem_id, int count);
s32 sys_semaphore_post(u32 sem_id, s32 count);
s32 sys_semaphore_get_value(u32 sem_id, vm::ptr<be_t<s32>> count);

View File

@ -5,6 +5,7 @@
#include "Emu/CPU/CPUThreadManager.h"
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/FS/vfsStreamMemory.h"
#include "Emu/FS/vfsFile.h"
#include "Loader/ELF.h"
#include "sys_spu.h"
@ -22,7 +23,20 @@ u32 LoadSpuImage(vfsStream& stream, u32& spu_ep)
return spu_offset;
}
//156
s32 spu_image_import(sys_spu_image& img, u32 src, u32 type)
{
vfsStreamMemory f(src);
u32 entry;
u32 offset = LoadSpuImage(f, entry);
img.type = SYS_SPU_IMAGE_TYPE_USER;
img.entry_point = entry;
img.addr = offset; // TODO: writing actual segment info
img.nsegs = 1; // wrong value
return CELL_OK;
}
s32 sys_spu_image_open(vm::ptr<sys_spu_image> img, vm::ptr<const char> path)
{
sys_spu.Warning("sys_spu_image_open(img_addr=0x%x, path_addr=0x%x [%s])", img.addr(), path.addr(), path.get_ptr());
@ -37,15 +51,47 @@ s32 sys_spu_image_open(vm::ptr<sys_spu_image> img, vm::ptr<const char> path)
u32 entry;
u32 offset = LoadSpuImage(f, entry);
img->type = 1;
img->type = SYS_SPU_IMAGE_TYPE_USER;
img->entry_point = entry;
img->segs_addr = offset;
img->nsegs = 0;
img->addr = offset; // TODO: writing actual segment info
img->nsegs = 1; // wrong value
return CELL_OK;
}
//172
SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4)
{
if (option)
{
sys_spu.Todo("Unsupported SPU Thread options (0x%x)", option);
}
u32 spu_ep = (u32)img.entry_point;
// Copy SPU image:
// TODO: use segment info
u32 spu_offset = (u32)Memory.Alloc(256 * 1024, 4096);
memcpy(vm::get_ptr<void>(spu_offset), vm::get_ptr<void>(img.addr), 256 * 1024);
SPUThread& new_thread = static_cast<SPUThread&>(Emu.GetCPU().AddThread(CPU_THREAD_SPU));
//initialize from new place:
new_thread.SetOffset(spu_offset);
new_thread.SetEntry(spu_ep);
new_thread.SetName(name);
new_thread.Run();
new_thread.GPR[3] = u128::from64(0, a1);
new_thread.GPR[4] = u128::from64(0, a2);
new_thread.GPR[5] = u128::from64(0, a3);
new_thread.GPR[6] = u128::from64(0, a4);
const u32 id = new_thread.GetId();
if (group) group->list[spu_num] = id;
new_thread.group = group;
sys_spu.Warning("*** New SPU Thread [%s] (ep=0x%x, opt=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d",
name.c_str(), spu_ep, option, a1, a2, a3, a4, id);
return &new_thread;
}
s32 sys_spu_thread_initialize(vm::ptr<be_t<u32>> thread, u32 group, u32 spu_num, vm::ptr<sys_spu_image> img, vm::ptr<sys_spu_thread_attribute> attr, vm::ptr<sys_spu_thread_argument> arg)
{
sys_spu.Warning("sys_spu_thread_initialize(thread_addr=0x%x, group=0x%x, spu_num=%d, img_addr=0x%x, attr_addr=0x%x, arg_addr=0x%x)",
@ -67,49 +113,23 @@ s32 sys_spu_thread_initialize(vm::ptr<be_t<u32>> thread, u32 group, u32 spu_num,
return CELL_EBUSY;
}
u32 spu_ep = (u32)img->entry_point;
std::string name = "SPUThread";
if (attr->name)
{
name = std::string(attr->name.get_ptr(), attr->name_len);
}
u64 a1 = arg->arg1;
u64 a2 = arg->arg2;
u64 a3 = arg->arg3;
u64 a4 = arg->arg4;
// Copy SPU image:
// TODO: use correct segment info
u32 spu_offset = (u32)Memory.Alloc(256 * 1024, 4096);
memcpy(vm::get_ptr<void>(spu_offset), vm::get_ptr<void>(img->segs_addr), 256 * 1024);
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
//initialize from new place:
new_thread.SetOffset(spu_offset);
new_thread.SetEntry(spu_ep);
new_thread.SetName(name);
new_thread.Run();
static_cast<SPUThread&>(new_thread).GPR[3] = u128::from64(0, a1);
static_cast<SPUThread&>(new_thread).GPR[4] = u128::from64(0, a2);
static_cast<SPUThread&>(new_thread).GPR[5] = u128::from64(0, a3);
static_cast<SPUThread&>(new_thread).GPR[6] = u128::from64(0, a4);
u32 id = new_thread.GetId();
*thread = group_info->list[spu_num] = id;
static_cast<SPUThread&>(new_thread).group = group_info;
sys_spu.Warning("*** New SPU Thread [%s] (img_offset=0x%x, ls_offset=0x%x, ep=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d",
(attr->name ? attr->name.get_ptr() : ""), (u32)img->segs_addr, ((SPUThread&)new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, id);
*thread = spu_thread_initialize(
group_info,
spu_num,
*img,
attr->name ? std::string(attr->name.get_ptr(), attr->name_len) : "SPUThread",
attr->option,
arg->arg1,
arg->arg2,
arg->arg3,
arg->arg4)->GetId();
return CELL_OK;
}
//166
s32 sys_spu_thread_set_argument(u32 id, vm::ptr<sys_spu_thread_argument> arg)
{
sys_spu.Warning("sys_spu_thread_set_argument(id=%d, arg_addr=0x%x)", id, arg.addr());
CPUThread* thr = Emu.GetCPU().GetThread(id);
if(!thr || thr->GetType() != CPU_THREAD_SPU)
@ -127,7 +147,6 @@ s32 sys_spu_thread_set_argument(u32 id, vm::ptr<sys_spu_thread_argument> arg)
return CELL_OK;
}
//165
s32 sys_spu_thread_get_exit_status(u32 id, vm::ptr<be_t<u32>> status)
{
sys_spu.Warning("sys_spu_thread_get_exit_status(id=%d, status_addr=0x%x)", id, status.addr());
@ -149,7 +168,6 @@ s32 sys_spu_thread_get_exit_status(u32 id, vm::ptr<be_t<u32>> status)
return CELL_OK;
}
//171
s32 sys_spu_thread_group_destroy(u32 id)
{
sys_spu.Warning("sys_spu_thread_group_destroy(id=%d)", id);
@ -192,7 +210,6 @@ s32 sys_spu_thread_group_destroy(u32 id)
return CELL_OK;
}
//173
s32 sys_spu_thread_group_start(u32 id)
{
sys_spu.Warning("sys_spu_thread_group_start(id=%d)", id);
@ -228,7 +245,6 @@ s32 sys_spu_thread_group_start(u32 id)
return CELL_OK;
}
//174
s32 sys_spu_thread_group_suspend(u32 id)
{
sys_spu.Log("sys_spu_thread_group_suspend(id=%d)", id);
@ -275,7 +291,6 @@ s32 sys_spu_thread_group_suspend(u32 id)
return CELL_OK;
}
//175
s32 sys_spu_thread_group_resume(u32 id)
{
sys_spu.Log("sys_spu_thread_group_resume(id=%d)", id);
@ -323,7 +338,6 @@ s32 sys_spu_thread_group_resume(u32 id)
return CELL_OK;
}
//176: Left doing nothing, indeed
s32 sys_spu_thread_group_yield(u32 id)
{
sys_spu.Error("sys_spu_thread_group_yield(id=%d)", id);
@ -366,7 +380,6 @@ s32 sys_spu_thread_group_yield(u32 id)
return CELL_OK;
}
//177: Left omit the EPERM check.
s32 sys_spu_thread_group_terminate(u32 id, int value)
{
sys_spu.Error("sys_spu_thread_group_terminate(id=%d, value=%d)", id, value);
@ -406,27 +419,37 @@ s32 sys_spu_thread_group_terminate(u32 id, int value)
return CELL_OK;
}
//170
s32 sys_spu_thread_group_create(vm::ptr<be_t<u32>> id, u32 num, int prio, vm::ptr<sys_spu_thread_group_attribute> attr)
SpuGroupInfo* spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container)
{
LV2_LOCK(0);
if (type)
{
sys_spu.Todo("Unsupported SPU Thread Group type (0x%x)", type);
}
auto group = new SpuGroupInfo(name, num, prio, type, container);
const u32 _id = sys_spu.GetNewId(group);
group->m_id = _id;
sys_spu.Notice("*** SPU Thread Group created [%s] (num=%d, prio=%d, type=0x%x, container=%d): id=%d",
name.c_str(), num, prio, type, container, _id);
return group;
}
s32 sys_spu_thread_group_create(vm::ptr<be_t<u32>> id, u32 num, s32 prio, vm::ptr<sys_spu_thread_group_attribute> attr)
{
sys_spu.Warning("sys_spu_thread_group_create(id_addr=0x%x, num=%d, prio=%d, attr_addr=0x%x)",
id.addr(), num, prio, attr.addr());
if (num > 256) return CELL_EINVAL;
if (prio < 16 || prio > 255) return CELL_EINVAL;
const std::string name(attr->name.get_ptr(), attr->nsize);
*id = sys_spu.GetNewId(new SpuGroupInfo(name, num, prio, attr->type, attr->ct));
sys_spu.Warning("*** SPU Thread Group created [%s] (type=0x%x, option.ct=0x%x): id=%d",
name.c_str(), (int)attr->type, (u32)attr->ct, (u32)*id);
if (!num || num > 6 || prio < 16 || prio > 255)
{
return CELL_EINVAL;
}
*id = spu_thread_group_create(std::string(attr->name.get_ptr(), attr->nsize - 1), num, prio, attr->type, attr->ct)->m_id;
return CELL_OK;
}
//178
s32 sys_spu_thread_group_join(u32 id, vm::ptr<be_t<u32>> cause, vm::ptr<be_t<u32>> status)
{
sys_spu.Warning("sys_spu_thread_group_join(id=%d, cause_addr=0x%x, status_addr=0x%x)", id, cause.addr(), status.addr());
@ -487,7 +510,6 @@ s32 sys_spu_thread_create(vm::ptr<be_t<u32>> thread_id, vm::ptr<be_t<u32>> entry
return CELL_OK;
}
//169
s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
{
sys_spu.Warning("sys_spu_initialize(max_usable_spu=%d, max_raw_spu=%d)", max_usable_spu, max_raw_spu);
@ -500,7 +522,6 @@ s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
return CELL_OK;
}
//181
s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type)
{
sys_spu.Log("sys_spu_thread_write_ls(id=%d, address=0x%x, value=0x%llx, type=0x%x)",
@ -533,7 +554,6 @@ s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type)
}
}
//182
s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr<be_t<u64>> value, u32 type)
{
sys_spu.Log("sys_spu_thread_read_ls(id=%d, address=0x%x, value_addr=0x%x, type=0x%x)",
@ -566,7 +586,6 @@ s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr<be_t<u64>> value, u32 ty
}
}
//190
s32 sys_spu_thread_write_spu_mb(u32 id, u32 value)
{
sys_spu.Log("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value);
@ -583,7 +602,6 @@ s32 sys_spu_thread_write_spu_mb(u32 id, u32 value)
return CELL_OK;
}
//187
s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value)
{
sys_spu.Warning("sys_spu_thread_set_spu_cfg(id=%d, value=0x%x)", id, value);
@ -605,7 +623,6 @@ s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value)
return CELL_OK;
}
//188
s32 sys_spu_thread_get_spu_cfg(u32 id, vm::ptr<be_t<u64>> value)
{
sys_spu.Warning("sys_spu_thread_get_spu_cfg(id=%d, value_addr=0x%x)", id, value.addr());
@ -622,7 +639,6 @@ s32 sys_spu_thread_get_spu_cfg(u32 id, vm::ptr<be_t<u64>> value)
return CELL_OK;
}
//184
s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
{
sys_spu.Log("sys_spu_thread_write_snr(id=%d, number=%d, value=0x%x)", id, number, value);
@ -713,7 +729,6 @@ s32 sys_spu_thread_connect_event(u32 id, u32 eq_id, u32 et, u8 spup)
return CELL_OK;
}
//
s32 sys_spu_thread_disconnect_event(u32 id, u32 et, u8 spup)
{
sys_spu.Warning("sys_spu_thread_disconnect_event(id=%d, event_type=0x%x, spup=%d)", id, et, spup);
@ -884,7 +899,6 @@ s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup)
return CELL_OK;
}
//160
s32 sys_raw_spu_create(vm::ptr<be_t<u32>> id, u32 attr_addr)
{
sys_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id.addr(), attr_addr);

View File

@ -1,6 +1,6 @@
#pragma once
enum
enum : s32
{
SYS_SPU_THREAD_GROUP_TYPE_NORMAL = 0x00,
SYS_SPU_THREAD_GROUP_TYPE_SEQUENTIAL = 0x01,
@ -8,7 +8,7 @@ enum
SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER = 0x04,
SYS_SPU_THREAD_GROUP_TYPE_NON_CONTEXT = 0x08,
SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT = 0x18,
SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM = 0x20
SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM = 0x20,
};
enum
@ -18,7 +18,8 @@ enum
SYS_SPU_THREAD_GROUP_JOIN_TERMINATED = 0x0004
};
enum {
enum
{
SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED,
SPU_THREAD_GROUP_STATUS_INITIALIZED,
SPU_THREAD_GROUP_STATUS_READY,
@ -30,11 +31,11 @@ enum {
SPU_THREAD_GROUP_STATUS_UNKNOWN
};
enum
enum : s32
{
SYS_SPU_SEGMENT_TYPE_COPY = 0x0001,
SYS_SPU_SEGMENT_TYPE_FILL = 0x0002,
SYS_SPU_SEGMENT_TYPE_INFO = 0x0004,
SYS_SPU_SEGMENT_TYPE_COPY = 1,
SYS_SPU_SEGMENT_TYPE_FILL = 2,
SYS_SPU_SEGMENT_TYPE_INFO = 4,
};
struct sys_spu_thread_group_attribute
@ -45,6 +46,13 @@ struct sys_spu_thread_group_attribute
be_t<u32> ct; // memory container id
};
enum : u32
{
SYS_SPU_THREAD_OPTION_NONE = 0,
SYS_SPU_THREAD_OPTION_ASYNC_INTR_ENABLE = 1,
SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE = 2,
};
struct sys_spu_thread_attribute
{
vm::bptr<const char> name;
@ -60,20 +68,43 @@ struct sys_spu_thread_argument
be_t<u64> arg4;
};
struct sys_spu_image
{
be_t<u32> type;
be_t<u32> entry_point;
be_t<u32> segs_addr; //temporarily used as offset of LS image after elf loading
be_t<int> nsegs;
};
struct sys_spu_segment
{
be_t<int> type;
be_t<u32> ls_start;
be_t<int> size;
be_t<u64> src;
be_t<s32> type; // copy, fill, info
be_t<u32> ls; // local storage address
be_t<s32> size;
union
{
be_t<u32> addr; // address or fill value
u64 pad;
};
};
static_assert(sizeof(sys_spu_segment) == 0x18, "Wrong sys_spu_segment size");
enum : u32
{
SYS_SPU_IMAGE_TYPE_USER = 0,
SYS_SPU_IMAGE_TYPE_KERNEL = 1,
};
struct sys_spu_image
{
be_t<u32> type; // user, kernel
be_t<u32> entry_point;
union
{
be_t<u32> addr; // temporarily used as offset of the whole LS image (should be removed)
vm::bptr<sys_spu_segment> segs;
};
be_t<s32> nsegs;
};
enum : u32
{
SYS_SPU_IMAGE_PROTECT = 0,
SYS_SPU_IMAGE_DIRECT = 1,
};
struct SpuGroupInfo
@ -81,15 +112,16 @@ struct SpuGroupInfo
std::vector<u32> list;
std::atomic<u32> lock;
std::string m_name;
int m_prio;
int m_type;
int m_ct;
u32 m_id;
s32 m_prio;
s32 m_type;
u32 m_ct;
u32 m_count;
int m_state; //SPU Thread Group State.
s32 m_state; //SPU Thread Group State.
u32 m_exit_status;
bool m_group_exit;
SpuGroupInfo(const std::string& name, u32 num, int prio, int type, u32 ct)
SpuGroupInfo(const std::string& name, u32 num, s32 prio, s32 type, u32 ct)
: m_name(name)
, m_prio(prio)
, m_type(type)
@ -107,6 +139,13 @@ struct SpuGroupInfo
}
};
class SPUThread;
// Aux
s32 spu_image_import(sys_spu_image& img, u32 src, u32 type);
SpuGroupInfo* spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type, u32 container);
SPUThread* spu_thread_initialize(SpuGroupInfo* group, u32 spu_num, sys_spu_image& img, const std::string& name, u32 option, u64 a1, u64 a2, u64 a3, u64 a4);
// SysCalls
s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
s32 sys_spu_image_open(vm::ptr<sys_spu_image> img, vm::ptr<const char> path);