vm::stackvar (experimental)

Should be convenient for small allocations which would be done on stack
on real console
This commit is contained in:
Nekotekina 2015-01-07 05:14:00 +03:00
parent 5ffc6ffca5
commit 3f44e07b7c
9 changed files with 272 additions and 44 deletions

View file

@ -1,5 +1,7 @@
#include "stdafx.h"
#include "Memory.h"
#include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/PPUThread.h"
namespace vm
{
@ -143,4 +145,84 @@ namespace vm
{
Memory.Close();
}
u32 stack_push(CPUThread& CPU, u32 size, u32 align_v, u32& old_pos)
{
switch (CPU.GetType())
{
case CPU_THREAD_PPU:
{
PPUThread& PPU = static_cast<PPUThread&>(CPU);
assert(align_v);
old_pos = (u32)PPU.GPR[1];
PPU.GPR[1] -= align(size, 8); // room minimal possible size
PPU.GPR[1] &= ~(align_v - 1); // fix stack alignment
if (PPU.GPR[1] < CPU.GetStackAddr())
{
// stack overflow
PPU.GPR[1] = old_pos;
return 0;
}
else
{
return (u32)PPU.GPR[1];
}
}
case CPU_THREAD_SPU:
case CPU_THREAD_RAW_SPU:
{
assert(!"stack_push(): SPU not supported");
return 0;
}
case CPU_THREAD_ARMv7:
{
assert(!"stack_push(): ARMv7 not supported");
return 0;
}
default:
{
assert(!"stack_push(): invalid thread type");
return 0;
}
}
}
void stack_pop(CPUThread& CPU, u32 addr, u32 old_pos)
{
switch (CPU.GetType())
{
case CPU_THREAD_PPU:
{
PPUThread& PPU = static_cast<PPUThread&>(CPU);
assert(PPU.GPR[1] == addr);
PPU.GPR[1] = old_pos;
return;
}
case CPU_THREAD_SPU:
case CPU_THREAD_RAW_SPU:
{
assert(!"stack_pop(): SPU not supported");
return;
}
case CPU_THREAD_ARMv7:
{
assert(!"stack_pop(): ARMv7 not supported");
return;
}
default:
{
assert(!"stack_pop(): invalid thread type");
return;
}
}
}
}

View file

@ -1,5 +1,10 @@
#pragma once
class CPUThread;
class PPUThread;
class SPUThread;
class ARMv7Thread;
namespace vm
{
template<typename T>
@ -495,4 +500,152 @@ namespace vm
return (NT*)(m_ptr + offset);
}
};
u32 stack_push(CPUThread& CPU, u32 size, u32 align, u32& old_pos);
void stack_pop(CPUThread& CPU, u32 addr, u32 old_pos);
template<typename T>
class stackvar
{
T* m_ptr;
u32 m_addr;
u32 m_size;
u32 m_align;
u32 m_old_pos;
CPUThread& m_thread;
void alloc()
{
m_addr = stack_push(m_thread, m_size, m_align, m_old_pos);
m_ptr = vm::get_ptr<T>(m_addr);
}
void dealloc()
{
if (m_addr)
{
stack_pop(m_thread, m_addr, m_old_pos);
m_addr = 0;
m_ptr = vm::get_ptr<T>(0u);
}
}
public:
stackvar(PPUThread& CPU, u32 size = sizeof(T), u32 align = __alignof(T))
: m_size(size)
, m_align(align)
, m_thread(CPU)
{
alloc();
}
stackvar(SPUThread& CPU, u32 size = sizeof(T), u32 align = __alignof(T))
: m_size(size)
, m_align(align)
, m_thread(CPU)
{
alloc();
}
stackvar(ARMv7Thread& CPU, u32 size = sizeof(T), u32 align = __alignof(T))
: m_size(size)
, m_align(align)
, m_thread(CPU)
{
alloc();
}
stackvar(const stackvar& r)
: m_size(r.m_size)
, m_align(r.m_align)
, m_thread(r.m_thread)
{
alloc();
*m_ptr = *r.m_ptr;
}
stackvar(stackvar&& r)
: m_ptr(r.m_ptr)
, m_addr(r.m_addr)
, m_size(r.m_size)
, m_align(r.m_align)
, m_old_pos(r.m_old_pos)
, m_thread(r.m_thread)
{
r.m_addr = 0;
r.m_ptr = vm::get_ptr<T>(0u);
}
~stackvar()
{
dealloc();
}
T* operator -> ()
{
return m_ptr;
}
const T* operator -> () const
{
return m_ptr;
}
T* get_ptr()
{
return m_ptr;
}
const T* get_ptr() const
{
return m_ptr;
}
T& value()
{
return *m_ptr;
}
const T& value() const
{
return *m_ptr;
}
u32 addr() const
{
return m_addr;
}
u32 size() const
{
return m_size;
}
/*
operator const ref<T>() const
{
return addr();
}
*/
template<typename AT> operator const ps3::ptr<T, 1, AT>() const
{
return ps3::ptr<T, 1, AT>::make(m_addr);
}
template<typename AT> operator const ps3::ptr<const T, 1, AT>() const
{
return ps3::ptr<const T, 1, AT>::make(m_addr);
}
operator T&()
{
return *m_ptr;
}
operator const T&() const
{
return *m_ptr;
}
};
}

View file

@ -36,11 +36,11 @@ int cellFontGetRevisionFlags(vm::ptr<be_t<u64>> revisionFlags)
return CELL_FONT_OK;
}
int cellFontInit(vm::ptr<CellFontConfig> config)
int cellFontInit(PPUThread& CPU, vm::ptr<CellFontConfig> config)
{
cellFont->Log("cellFontInit(config=0x%x)", config.addr());
vm::var<be_t<u64>> revisionFlags;
vm::stackvar<be_t<u64>> revisionFlags(CPU);
revisionFlags.value() = 0;
cellFontGetRevisionFlags(revisionFlags);
return cellFontInitializeWithRevision(revisionFlags.value(), config);
@ -101,7 +101,7 @@ int cellFontOpenFontFile(vm::ptr<CellFontLibrary> library, vm::ptr<const char> f
return ret;
}
int cellFontOpenFontset(vm::ptr<CellFontLibrary> library, vm::ptr<CellFontType> fontType, vm::ptr<CellFont> font)
int cellFontOpenFontset(PPUThread& CPU, vm::ptr<CellFontLibrary> library, vm::ptr<CellFontType> fontType, vm::ptr<CellFont> font)
{
cellFont->Log("cellFontOpenFontset(library_addr=0x%x, fontType_addr=0x%x, font_addr=0x%x)",
library.addr(), fontType.addr(), font.addr());
@ -177,7 +177,7 @@ int cellFontOpenFontset(vm::ptr<CellFontLibrary> library, vm::ptr<CellFontType>
return CELL_FONT_ERROR_NO_SUPPORT_FONTSET;
}
vm::var<char> f((u32)file.length() + 1, 1);
vm::stackvar<char> f(CPU, (u32)file.length() + 1, 1);
memcpy(f.get_ptr(), file.c_str(), file.size() + 1);
int ret = cellFontOpenFontFile(library, f, 0, 0, font); //TODO: Find the correct values of subNum, uniqueId
font->origin = CELL_FONT_OPEN_FONTSET;

View file

@ -201,7 +201,7 @@ int cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPath, vm:
return CELL_GAME_RET_OK;
}
int cellGameDataCheckCreate2(u32 version, vm::ptr<const char> dirName, u32 errDialog,
int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog,
vm::ptr<void(*)(vm::ptr<CellGameDataCBResult> cbResult, vm::ptr<CellGameDataStatGet> get, vm::ptr<CellGameDataStatSet> set)> funcStat, u32 container)
{
cellGame->Warning("cellGameDataCheckCreate(2)(version=0x%x, dirName_addr=0x%x, errDialog=0x%x, funcStat_addr=0x%x, container=%d)",
@ -238,10 +238,9 @@ int cellGameDataCheckCreate2(u32 version, vm::ptr<const char> dirName, u32 errDi
return CELL_GAMEDATA_ERROR_BROKEN;
}
// TODO: use memory container
vm::var<CellGameDataCBResult> cbResult;
vm::var<CellGameDataStatGet> cbGet;
vm::var<CellGameDataStatSet> cbSet;
vm::stackvar<CellGameDataCBResult> cbResult(CPU);
vm::stackvar<CellGameDataStatGet> cbGet(CPU);
vm::stackvar<CellGameDataStatSet> cbSet(CPU);
cbGet.value() = {};
@ -307,11 +306,11 @@ int cellGameDataCheckCreate2(u32 version, vm::ptr<const char> dirName, u32 errDi
}
}
int cellGameDataCheckCreate(u32 version, vm::ptr<const char> dirName, u32 errDialog,
int cellGameDataCheckCreate(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog,
vm::ptr<void(*)(vm::ptr<CellGameDataCBResult> cbResult, vm::ptr<CellGameDataStatGet> get, vm::ptr<CellGameDataStatSet> set)> funcStat, u32 container)
{
// TODO: almost identical, the only difference is that this function will always calculate the size of game data
return cellGameDataCheckCreate2(version, dirName, errDialog, funcStat, container);
return cellGameDataCheckCreate2(CPU, version, dirName, errDialog, funcStat, container);
}
int cellGameCreateGameData(vm::ptr<CellGameSetInitParams> init, vm::ptr<char> tmp_contentInfoPath, vm::ptr<char> tmp_usrdirPath)

View file

@ -199,4 +199,4 @@ struct CellGameDataStatSet
{
vm::bptr<CellGameDataSystemFileParam> setParam;
be_t<u32> reserved;
};
};

View file

@ -1287,7 +1287,7 @@ s32 _cellSyncLFQueueCompletePushPointer2(vm::ptr<CellSyncLFQueue> queue, s32 poi
return syncLFQueueCompletePushPointer2(queue, pointer, fpSendSignal);
}
s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void> buffer, u32 isBlocking)
s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void> buffer, u32 isBlocking)
{
// cellSyncLFQueuePush has 1 in isBlocking param, cellSyncLFQueueTryPush has 0
cellSync->Warning("_cellSyncLFQueuePushBody(queue_addr=0x%x, buffer_addr=0x%x, isBlocking=%d)", queue.addr(), buffer.addr(), isBlocking);
@ -1302,10 +1302,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
}
s32 position;
//syncLFQueueDump(queue);
#ifdef PRX_DEBUG
vm::var<be_t<s32>> position_v;
vm::stackvar<be_t<s32>> position_v(CPU);
#endif
while (true)
{
@ -1314,7 +1312,7 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY)
{
#ifdef PRX_DEBUG_XXX
res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x24B0, libsre_rtoc,
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64>(CPU, libsre + 0x24B0, libsre_rtoc,
queue, position_v.addr(), isBlocking, 0);
position = position_v->ToLE();
#else
@ -1324,7 +1322,7 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
else
{
#ifdef PRX_DEBUG
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64>(GetCurrentPPUThread(), libsre + 0x3050, libsre_rtoc,
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64>(CPU, libsre + 0x3050, libsre_rtoc,
queue, position_v.addr(), isBlocking, 0);
position = position_v->ToLE();
#else
@ -1332,9 +1330,6 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
#endif
}
//LOG_NOTICE(HLE, "... position = %d", position);
//syncLFQueueDump(queue);
if (!isBlocking || res != CELL_SYNC_ERROR_AGAIN)
{
if (res)
@ -1360,7 +1355,7 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY)
{
#ifdef PRX_DEBUG_XXX
res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, s32, u64>::call(GetCurrentPPUThread(), libsre + 0x26C0, libsre_rtoc,
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, s32, u64>(CPU, libsre + 0x26C0, libsre_rtoc,
queue, position, 0);
#else
res = syncLFQueueCompletePushPointer(queue, position, nullptr);
@ -1369,14 +1364,13 @@ s32 _cellSyncLFQueuePushBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void>
else
{
#ifdef PRX_DEBUG
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, s32, u64>(GetCurrentPPUThread(), libsre + 0x355C, libsre_rtoc,
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, s32, u64>(CPU, libsre + 0x355C, libsre_rtoc,
queue, position, 0);
#else
res = syncLFQueueCompletePushPointer2(queue, position, nullptr);
#endif
}
//syncLFQueueDump(queue);
return res;
}
@ -1669,7 +1663,7 @@ s32 _cellSyncLFQueueCompletePopPointer2(vm::ptr<CellSyncLFQueue> queue, s32 poin
return syncLFQueueCompletePopPointer2(queue, pointer, fpSendSignal, noQueueFull);
}
s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer, u32 isBlocking)
s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer, u32 isBlocking)
{
// cellSyncLFQueuePop has 1 in isBlocking param, cellSyncLFQueueTryPop has 0
cellSync->Warning("_cellSyncLFQueuePopBody(queue_addr=0x%x, buffer_addr=0x%x, isBlocking=%d)", queue.addr(), buffer.addr(), isBlocking);
@ -1685,7 +1679,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
s32 position;
#ifdef PRX_DEBUG
vm::var<be_t<s32>> position_v;
vm::stackvar<be_t<s32>> position_v(CPU);
#endif
while (true)
{
@ -1693,7 +1687,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY)
{
#ifdef PRX_DEBUG_XXX
res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x2A90, libsre_rtoc,
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64, u64>(CPU, libsre + 0x2A90, libsre_rtoc,
queue, position_v.addr(), isBlocking, 0, 0);
position = position_v->ToLE();
#else
@ -1703,7 +1697,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
else
{
#ifdef PRX_DEBUG
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64>(GetCurrentPPUThread(), libsre + 0x39AC, libsre_rtoc,
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, u32, u32, u64>(CPU, libsre + 0x39AC, libsre_rtoc,
queue, position_v.addr(), isBlocking, 0);
position = position_v->ToLE();
#else
@ -1736,7 +1730,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
if (queue->m_direction != CELL_SYNC_QUEUE_ANY2ANY)
{
#ifdef PRX_DEBUG_XXX
res = cb_caller<s32, vm::ptr<CellSyncLFQueue>, s32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x2CA8, libsre_rtoc,
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, s32, u64, u64>(CPU, libsre + 0x2CA8, libsre_rtoc,
queue, position, 0, 0);
#else
res = syncLFQueueCompletePopPointer(queue, position, nullptr, 0);
@ -1745,7 +1739,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer
else
{
#ifdef PRX_DEBUG
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, s32, u64, u64>(GetCurrentPPUThread(), libsre + 0x3EB8, libsre_rtoc,
res = cb_call<s32, vm::ptr<CellSyncLFQueue>, s32, u64, u64>(CPU, libsre + 0x3EB8, libsre_rtoc,
queue, position, 0, 0);
#else
res = syncLFQueueCompletePopPointer2(queue, position, nullptr, 0);
@ -1926,10 +1920,10 @@ s32 _cellSyncLFQueueAttachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<Cell
return syncLFQueueAttachLv2EventQueue(spus, num, queue);
}
s32 syncLFQueueDetachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncLFQueue> queue)
s32 syncLFQueueDetachLv2EventQueue(PPUThread& CPU, vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncLFQueue> queue)
{
#ifdef PRX_DEBUG
return cb_call<s32, vm::ptr<u32>, u32, vm::ptr<CellSyncLFQueue>>(GetCurrentPPUThread(), libsre + 0x1DA0, libsre_rtoc,
return cb_call<s32, vm::ptr<u32>, u32, vm::ptr<CellSyncLFQueue>>(CPU, libsre + 0x1DA0, libsre_rtoc,
spus, num, queue);
#endif

View file

@ -835,10 +835,10 @@ int cellWebBrowserEstimate2(const vm::ptr<const CellWebBrowserConfig2> config, v
return CELL_OK;
}
extern int cellGameDataCheckCreate2(u32 version, vm::ptr<const char> dirName, u32 errDialog,
extern int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog,
vm::ptr<void(*)(vm::ptr<CellGameDataCBResult> cbResult, vm::ptr<CellGameDataStatGet> get, vm::ptr<CellGameDataStatSet> set)> funcStat, u32 container);
extern int cellGameDataCheckCreate(u32 version, vm::ptr<const char> dirName, u32 errDialog,
extern int cellGameDataCheckCreate(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog,
vm::ptr<void(*)(vm::ptr<CellGameDataCBResult> cbResult, vm::ptr<CellGameDataStatGet> get, vm::ptr<CellGameDataStatSet> set)> funcStat, u32 container);
extern void cellSysutil_SaveData_init();

View file

@ -286,7 +286,7 @@ s32 _sys_spu_printf_finalize()
return CELL_OK;
}
s64 _sys_spu_printf_attach_group(u32 group)
s32 _sys_spu_printf_attach_group(PPUThread& CPU, u32 group)
{
sysPrxForUser->Warning("_sys_spu_printf_attach_group(group=%d)", group);
@ -295,10 +295,10 @@ s64 _sys_spu_printf_attach_group(u32 group)
return CELL_ESTAT;
}
return spu_printf_agcb(group);
return spu_printf_agcb.call(CPU, group);
}
s64 _sys_spu_printf_detach_group(u32 group)
s32 _sys_spu_printf_detach_group(PPUThread& CPU, u32 group)
{
sysPrxForUser->Warning("_sys_spu_printf_detach_group(group=%d)", group);
@ -307,10 +307,10 @@ s64 _sys_spu_printf_detach_group(u32 group)
return CELL_ESTAT;
}
return spu_printf_dgcb(group);
return spu_printf_dgcb.call(CPU, group);
}
s64 _sys_spu_printf_attach_thread(u32 thread)
s32 _sys_spu_printf_attach_thread(PPUThread& CPU, u32 thread)
{
sysPrxForUser->Warning("_sys_spu_printf_attach_thread(thread=%d)", thread);
@ -319,10 +319,10 @@ s64 _sys_spu_printf_attach_thread(u32 thread)
return CELL_ESTAT;
}
return spu_printf_atcb(thread);
return spu_printf_atcb.call(CPU, thread);
}
s64 _sys_spu_printf_detach_thread(u32 thread)
s32 _sys_spu_printf_detach_thread(PPUThread& CPU, u32 thread)
{
sysPrxForUser->Warning("_sys_spu_printf_detach_thread(thread=%d)", thread);
@ -331,7 +331,7 @@ s64 _sys_spu_printf_detach_thread(u32 thread)
return CELL_ESTAT;
}
return spu_printf_dtcb(thread);
return spu_printf_dtcb.call(CPU, thread);
}
s32 _sys_snprintf(vm::ptr<char> dst, u32 count, vm::ptr<const char> fmt) // va_args...

View file

@ -1000,13 +1000,13 @@ int cellFsAioFinish(vm::ptr<const char> mount_point)
return CELL_OK;
}
int cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size, vm::ptr<be_t<u64>> nread)
int cellFsReadWithOffset(PPUThread& CPU, u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size, vm::ptr<be_t<u64>> nread)
{
sys_fs->Warning("cellFsReadWithOffset(fd=%d, offset=0x%llx, buf_addr=0x%x, buffer_size=%lld nread=0x%llx)",
fd, offset, buf.addr(), buffer_size, nread.addr());
int ret;
vm::var<be_t<u64>> oldPos, newPos;
vm::stackvar<be_t<u64>> oldPos(CPU), newPos(CPU);
ret = cellFsLseek(fd, 0, CELL_SEEK_CUR, oldPos); // Save the current position
if (ret) return ret;
ret = cellFsLseek(fd, offset, CELL_SEEK_SET, newPos); // Move to the specified offset