1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-23 03:02:53 +01:00

Basic stack argument support for callbacks

This commit is contained in:
Nekotekina 2014-09-15 19:04:09 +04:00
parent 4243558319
commit 201f0f3a9f
4 changed files with 165 additions and 40 deletions

View File

@ -11,6 +11,11 @@ namespace cb_detail
ARG_STACK,
};
// Current implementation can handle only fixed amount of stack arguments.
// This constant can be increased if necessary.
// It's possible to calculate suitable stack frame size in template, but too complicated.
static const auto FIXED_STACK_FRAME_SIZE = 0x100;
template<typename T, _func_arg_type type, int g_count, int f_count, int v_count>
struct _func_arg;
@ -50,25 +55,29 @@ namespace cb_detail
template<typename T, int g_count, int f_count, int v_count>
struct _func_arg<T, ARG_STACK, g_count, f_count, v_count>
{
static_assert(g_count <= 8, "TODO: Unsupported stack argument type (general)");
static_assert(f_count <= 12, "TODO: Unsupported stack argument type (float)");
static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)");
static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_STACK");
__forceinline static void set_value(PPUThread& CPU, const T arg)
{
// TODO
const int stack_pos = 0x70 + (g_count - 9) * 8 - FIXED_STACK_FRAME_SIZE;
static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)");
u64 value = 0;
(T&)value = arg;
vm::write64(CPU.GPR[1] + stack_pos, value);
}
};
template<int g_count, int f_count, int v_count>
__forceinline static void _bind_func_args(PPUThread& CPU)
__forceinline static bool _bind_func_args(PPUThread& CPU)
{
// terminator
return false;
}
template<int g_count, int f_count, int v_count, typename T1, typename... T>
__forceinline static void _bind_func_args(PPUThread& CPU, T1 arg1, T... args)
__forceinline static bool _bind_func_args(PPUThread& CPU, T1 arg1, T... args)
{
static_assert(!std::is_pointer<T1>::value, "Invalid callback argument type (pointer)");
static_assert(!std::is_reference<T1>::value, "Invalid callback argument type (reference)");
@ -82,7 +91,8 @@ namespace cb_detail
const int v = v_count + (is_vector ? 1 : 0);
_func_arg<T1, t, g, f, v>::set_value(CPU, arg1);
_bind_func_args<g, f, v>(CPU, args...);
// return true if stack was used
return _bind_func_args<g, f, v>(CPU, args...) || (t == ARG_STACK);
}
template<typename RT>
@ -136,8 +146,10 @@ namespace cb_detail
{
__forceinline static RT call(PPUThread& CPU, u32 pc, u32 rtoc, T... args)
{
_bind_func_args<0, 0, 0>(CPU, args...);
const bool stack = _bind_func_args<0, 0, 0>(CPU, args...);
if (stack) CPU.GPR[1] -= FIXED_STACK_FRAME_SIZE;
CPU.FastCall2(pc, rtoc);
if (stack) CPU.GPR[1] += FIXED_STACK_FRAME_SIZE;
return _func_res<RT>::get_value(CPU);
}
};

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Callback.h"
#include "Emu/Cell/SPURSManager.h"
#include "cellSpurs.h"
@ -12,17 +13,127 @@ extern u32 libsre;
extern u32 libsre_rtoc;
#endif
s64 spursInit(
vm::ptr<CellSpurs2> spurs,
u32 arg2,
u64 arg3,
s32 nSpus,
s32 spuPriority,
s32 ppuPriority,
u32 flags,
u32 arg8,
u32 arg9,
u32 arg10,
u32 arg11,
u32 arg12,
u32 arg13)
{
// internal function
#ifdef PRX_DEBUG
return cb_caller<s32,vm::ptr<CellSpurs2>, u32, u64, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>::call(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc,
spurs, arg2, arg3, nSpus, spuPriority, ppuPriority, flags, arg8, arg9, arg10, arg11, arg12, arg13);
#else
//spurs->spurs = new SPURSManager(attr);
return CELL_OK;
#endif
}
s64 cellSpursInitialize(vm::ptr<CellSpurs> spurs, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork)
{
cellSpurs->Warning("cellSpursInitialize(spurs_addr=0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)", spurs.addr(), nSpus, spuPriority, ppuPriority, exitIfNoWork);
cellSpurs->Warning("cellSpursInitialize(spurs_addr=0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)",
spurs.addr(), nSpus, spuPriority, ppuPriority, exitIfNoWork ? 1 : 0);
#ifdef PRX_DEBUG
#ifdef PRX_DEBUG_XXX
return GetCurrentPPUThread().FastCall2(libsre + 0x8480, libsre_rtoc);
#else
SPURSManagerAttribute *attr = new SPURSManagerAttribute(nSpus, spuPriority, ppuPriority, exitIfNoWork);
spurs->spurs = new SPURSManager(attr);
return spursInit(
vm::ptr<CellSpurs2>::make(spurs.addr()),
0,
0,
nSpus,
spuPriority,
ppuPriority,
exitIfNoWork ? 1 : 0,
0,
0,
0,
0,
0,
0);
#endif
}
return CELL_OK;
s64 cellSpursInitializeWithAttribute(vm::ptr<CellSpurs> spurs, vm::ptr<const CellSpursAttribute> attr)
{
cellSpurs->Warning("cellSpursInitializeWithAttribute(spurs_addr=0x%x, attr_addr=0x%x)", spurs.addr(), attr.addr());
#ifdef PRX_DEBUG_XXX
return GetCurrentPPUThread().FastCall2(libsre + 0x839C, libsre_rtoc);
#else
if (!attr)
{
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
}
if (attr.addr() % 8)
{
return CELL_SPURS_CORE_ERROR_ALIGN;
}
if (attr->m.arg1 > 2)
{
return CELL_SPURS_CORE_ERROR_INVAL;
}
return spursInit(
vm::ptr<CellSpurs2>::make(spurs.addr()),
attr->m.arg1,
attr->m.arg2,
attr->m.nSpus,
attr->m.spuPriority,
attr->m.ppuPriority,
(u32)attr->_u32.raw[10] | (u32)attr->_u8[20],
attr.addr() + 0x15,
attr->_u32.raw[9],
attr->_u32.raw[11],
attr.addr() + 0x38,
attr->_u32.raw[16],
attr->_u32.raw[17]);
#endif
}
s64 cellSpursInitializeWithAttribute2(vm::ptr<CellSpurs2> spurs, vm::ptr<const CellSpursAttribute> attr)
{
cellSpurs->Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, attr_addr=0x%x)", spurs.addr(), attr.addr());
#ifdef PRX_DEBUG_XXX
return GetCurrentPPUThread().FastCall2(libsre + 0x82B4, libsre_rtoc);
#else
if (!attr)
{
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
}
if (attr.addr() % 8)
{
return CELL_SPURS_CORE_ERROR_ALIGN;
}
if (attr->m.arg1 > 2)
{
return CELL_SPURS_CORE_ERROR_INVAL;
}
return spursInit(
spurs,
attr->m.arg1,
attr->m.arg2,
attr->m.nSpus,
attr->m.spuPriority,
attr->m.ppuPriority,
(u32)attr->_u32.raw[10] | (u32)attr->_u8[20] | 4,
attr.addr() + 0x15,
attr->_u32.raw[9],
attr->_u32.raw[11],
attr.addr() + 0x38,
attr->_u32.raw[16],
attr->_u32.raw[17]);
#endif
}
@ -39,32 +150,6 @@ s64 cellSpursFinalize(vm::ptr<CellSpurs> spurs)
#endif
}
s64 cellSpursInitializeWithAttribute(vm::ptr<CellSpurs> spurs, vm::ptr<const CellSpursAttribute> attr)
{
cellSpurs->Warning("cellSpursInitializeWithAttribute(spurs_addr=0x%x, spurs_addr=0x%x)", spurs.addr(), attr.addr());
#ifdef PRX_DEBUG
return GetCurrentPPUThread().FastCall2(libsre + 0x839C, libsre_rtoc);
#else
spurs->spurs = new SPURSManager(attr->attr);
return CELL_OK;
#endif
}
s64 cellSpursInitializeWithAttribute2(vm::ptr<CellSpurs2> spurs, vm::ptr<const CellSpursAttribute> attr)
{
cellSpurs->Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, spurs_addr=0x%x)", spurs.addr(), attr.addr());
#ifdef PRX_DEBUG
return GetCurrentPPUThread().FastCall2(libsre + 0x82B4, libsre_rtoc);
#else
spurs->spurs = new SPURSManager(attr->attr);
return CELL_OK;
#endif
}
s64 _cellSpursAttributeInitialize(vm::ptr<CellSpursAttribute> attr, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork)
{
cellSpurs->Warning("_cellSpursAttributeInitialize(attr_addr=0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)",

View File

@ -94,7 +94,35 @@ struct CellSpurs2
struct CellSpursAttribute
{
SPURSManagerAttribute *attr;
static const auto align = 8;
static const auto size = 512;
union
{
// raw data
u8 _u8[size / sizeof(u8)];
struct
{
be_t<u32> raw[size / sizeof(u32)];
} _u32;
// real structure
struct
{
be_t<u32> arg1;
be_t<u32> arg2;
be_t<u32> nSpus;
be_t<s32> spuPriority;
be_t<s32> ppuPriority;
} m;
// alternative implementation
struct
{
SPURSManagerAttribute *attr;
} c;
};
};
struct CellSpursEventFlag

View File

@ -227,7 +227,7 @@ s32 cellFsClosedir(u32 fd)
s32 cellFsStat(vm::ptr<const char> path, vm::ptr<CellFsStat> sb)
{
sys_fs->Warning("cellFsStat(path=\"%s\", sb_addr: 0x%x)", path.get_ptr(), sb.addr());
sys_fs->Warning("cellFsStat(path=\"%s\", sb_addr=0x%x)", path.get_ptr(), sb.addr());
LV2_LOCK(0);
@ -270,7 +270,7 @@ s32 cellFsStat(vm::ptr<const char> path, vm::ptr<CellFsStat> sb)
s32 cellFsFstat(u32 fd, vm::ptr<CellFsStat> sb)
{
sys_fs->Warning("cellFsFstat(fd=%d, sb_addr: 0x%x)", fd, sb.addr());
sys_fs->Warning("cellFsFstat(fd=%d, sb_addr=0x%x)", fd, sb.addr());
LV2_LOCK(0);