Added .aligned() method for vm::ptr

Added set_alignment() macro for setting alignment
Added alignof32() macro similar to sizeof32()
Added CHECK_SIZE, CHECK_ALIGN macro with static_assert
Minor refactoring
This commit is contained in:
Nekotekina 2015-06-21 17:48:21 +03:00
parent a7f77c27f7
commit e896da8064
18 changed files with 1202 additions and 1237 deletions

View File

@ -388,7 +388,7 @@ union u128
}
};
static_assert(__alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 size or alignment");
CHECK_SIZE_ALIGN(u128, 16, 16);
static force_inline u128 sync_val_compare_and_swap(volatile u128* dest, u128 comp, u128 exch)
{

View File

@ -26,6 +26,12 @@
#define force_inline __attribute__((always_inline))
#endif
#if defined(_MSC_VER)
#define set_alignment(x) _CRT_ALIGN(x)
#else
#define set_alignment(x) __attribute__((aligned(x)))
#endif
template<size_t size>
void strcpy_trunc(char(&dst)[size], const std::string& src)
{

View File

@ -453,15 +453,15 @@ s32 sceGxmDepthStencilSurfaceInitDisabled(vm::ptr<SceGxmDepthStencilSurface> sur
throw __FUNCTION__;
}
//float sceGxmDepthStencilSurfaceGetBackgroundDepth(vm::ptr<const SceGxmDepthStencilSurface> surface)
//{
// throw __FUNCTION__;
//}
float sceGxmDepthStencilSurfaceGetBackgroundDepth(vm::ptr<const SceGxmDepthStencilSurface> surface)
{
throw __FUNCTION__;
}
//void sceGxmDepthStencilSurfaceSetBackgroundDepth(vm::ptr<SceGxmDepthStencilSurface> surface, float backgroundDepth)
//{
// throw __FUNCTION__;
//}
void sceGxmDepthStencilSurfaceSetBackgroundDepth(vm::ptr<SceGxmDepthStencilSurface> surface, float backgroundDepth)
{
throw __FUNCTION__;
}
u8 sceGxmDepthStencilSurfaceGetBackgroundStencil(vm::ptr<const SceGxmDepthStencilSurface> surface)
{

View File

@ -79,10 +79,10 @@ s32 sceVoiceGetMuteFlag(u32 portId, vm::ptr<u16> bMuted)
throw __FUNCTION__;
}
//s32 sceVoiceSetVolume(u32 portId, float volume)
//{
// throw __FUNCTION__;
//}
s32 sceVoiceSetVolume(u32 portId, float volume)
{
throw __FUNCTION__;
}
s32 sceVoiceGetVolume(u32 portId, vm::ptr<float> volume)
{

View File

@ -68,6 +68,16 @@ namespace vm
return m_addr != 0;
}
bool aligned() const
{
return m_addr % alignof32(T) == 0;
}
bool operator %(to_ne_t<AT> alignment)
{
return m_addr % alignment != 0;
}
_ptr_base& operator =(const _ptr_base&) = default;
};

View File

@ -1096,7 +1096,7 @@ struct OMAHeader // OMA Header
}
};
static_assert(sizeof(OMAHeader) == 96, "Wrong OMAHeader size");
CHECK_SIZE(OMAHeader, 96);
class AudioDecoder
{

View File

@ -867,7 +867,7 @@ s32 cellAudioAddData(u32 portNum, vm::ptr<float> src, u32 samples, float volume)
return CELL_AUDIO_ERROR_NOT_INIT;
}
if (portNum >= AUDIO_PORT_COUNT || !src || src.addr() % 4)
if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned())
{
return CELL_AUDIO_ERROR_PARAM;
}
@ -900,7 +900,7 @@ s32 cellAudioAdd2chData(u32 portNum, vm::ptr<float> src, u32 samples, float volu
return CELL_AUDIO_ERROR_NOT_INIT;
}
if (portNum >= AUDIO_PORT_COUNT || !src || src.addr() % 4)
if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned())
{
return CELL_AUDIO_ERROR_PARAM;
}
@ -963,7 +963,7 @@ s32 cellAudioAdd6chData(u32 portNum, vm::ptr<float> src, float volume)
return CELL_AUDIO_ERROR_NOT_INIT;
}
if (portNum >= AUDIO_PORT_COUNT || !src || src.addr() % 4)
if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned())
{
return CELL_AUDIO_ERROR_PARAM;
}

View File

@ -1218,7 +1218,7 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
context->end = newCommandBuffer.second;
// Wait for rsx to "release" the new command buffer
while (true)
while (!Emu.IsStopped())
{
u32 getPos = ctrl.get.read_sync().value();
if (isInCommandBufferExcept(getPos, newCommandBuffer.first, newCommandBuffer.second))
@ -1232,24 +1232,24 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
return CELL_OK;
if (0)
{
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
be_t<u32> res = be_t<u32>::make(context->current - context->begin - ctrl.put.read_relaxed());
//if (0)
//{
// auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
// be_t<u32> res = be_t<u32>::make(context->current - context->begin - ctrl.put.read_relaxed());
if (res != 0)
{
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
}
// if (res != 0)
// {
// GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
// }
memmove(vm::get_ptr<void>(context->begin), vm::get_ptr<void>(context->current - res), res);
// memmove(vm::get_ptr<void>(context->begin), vm::get_ptr<void>(context->current - res), res);
context->current = context->begin + res;
ctrl.put.write_relaxed(res);
ctrl.get.write_relaxed(be_t<u32>::make(0));
// context->current = context->begin + res;
// ctrl.put.write_relaxed(res);
// ctrl.get.write_relaxed(be_t<u32>::make(0));
return CELL_OK;
}
// return CELL_OK;
//}
//auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
@ -1261,23 +1261,23 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
//cmd[3] = 0; // some incrementing by module value
//context->current += 0x10;
if (0)
{
const u32 address = context->begin;
const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits
assert(upper != 0xFFFF);
const u32 offset = (upper << 20) | (address & 0xFFFFF);
vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | offset); // set JUMP cmd
//if (0)
//{
// const u32 address = context->begin;
// const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits
// assert(upper != 0xFFFF);
// const u32 offset = (upper << 20) | (address & 0xFFFFF);
// vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | offset); // set JUMP cmd
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
ctrl.put.exchange(be_t<u32>::make(offset));
}
else
{
vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT | (0));
}
// auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
// ctrl.put.exchange(be_t<u32>::make(offset));
//}
//else
//{
// vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT | (0));
//}
context->current = context->begin; // rewind to the beginning
//context->current = context->begin; // rewind to the beginning
// TODO: something is missing
return CELL_OK;
}

View File

@ -200,7 +200,7 @@ struct CellPamfAvcInfo
u8 maxMeanBitrate;
};
static_assert(sizeof(CellPamfAvcInfo) == 0x20, "Invalid CellPamfAvcInfo size");
CHECK_SIZE(CellPamfAvcInfo, 0x20);
// M2V (MPEG2 Video) Specific Information
struct CellPamfM2vInfo
@ -223,7 +223,7 @@ struct CellPamfM2vInfo
u8 matrixCoefficients;
};
static_assert(sizeof(CellPamfM2vInfo) == 0x18, "Invalid CellPamfM2vInfo size");
CHECK_SIZE(CellPamfM2vInfo, 0x18);
// ATRAC3+ Audio Specific Information
struct CellPamfAtrac3plusInfo
@ -232,7 +232,7 @@ struct CellPamfAtrac3plusInfo
u8 numberOfChannels;
};
static_assert(sizeof(CellPamfAtrac3plusInfo) == 8, "Invalid CellPamfAtrac3plusInfo size");
CHECK_SIZE(CellPamfAtrac3plusInfo, 8);
// AC3 Audio Specific Information
struct CellPamfAc3Info
@ -241,7 +241,7 @@ struct CellPamfAc3Info
u8 numberOfChannels;
};
static_assert(sizeof(CellPamfAc3Info) == 8, "Invalid CellPamfAc3Info size");
CHECK_SIZE(CellPamfAc3Info, 8);
// LPCM Audio Specific Information
struct CellPamfLpcmInfo
@ -337,7 +337,7 @@ struct PamfStreamHeader
};
};
static_assert(sizeof(PamfStreamHeader) == 48, "Invalid PamfStreamHeader size");
CHECK_SIZE(PamfStreamHeader, 48);
struct PamfHeader
{
@ -379,7 +379,7 @@ struct PamfEpHeader
be_t<u32> rpnOffset;
};
static_assert(sizeof(PamfEpHeader) == 12, "Invalid PamfEpHeader size");
CHECK_SIZE(PamfEpHeader, 12);
#pragma pack(pop)
@ -392,6 +392,6 @@ struct CellPamfReader
u32 internalData[28];
};
static_assert(sizeof(CellPamfReader) == 128, "Invalid CellPamfReader size");
CHECK_SIZE(CellPamfReader, 128);
s32 cellPamfReaderInitialize(vm::ptr<CellPamfReader> pSelf, vm::ptr<const PamfHeader> pAddr, u64 fileSize, u32 attribute);

View File

@ -1043,7 +1043,7 @@ struct CellSailDescriptor
be_t<u64> internalData[31];
};
static_assert(sizeof(CellSailDescriptor) == 0x100, "Invalid CellSailDescriptor size");
CHECK_SIZE(CellSailDescriptor, 0x100);
struct CellSailStartCommand
{
@ -1110,4 +1110,4 @@ struct CellSailPlayer
be_t<u64> internalData[26];
};
static_assert(sizeof(CellSailPlayer) == 0x100, "Invalid CellSailPlayer size");
CHECK_SIZE(CellSailPlayer, 0x100);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -83,7 +83,7 @@ u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status) {
auto ctxt = vm::get_ptr<SpursKernelContext>(spu.offset + 0x100);
spu.GPR[3]._u32[3] = 1;
if (ctxt->spurs->m.flags1 & SF1_32_WORKLOADS) {
if (ctxt->spurs->flags1 & SF1_32_WORKLOADS) {
spursKernel2SelectWorkload(spu);
} else {
spursKernel1SelectWorkload(spu);
@ -168,12 +168,12 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
u8 contention[CELL_SPURS_MAX_WORKLOAD];
u8 pendingContention[CELL_SPURS_MAX_WORKLOAD];
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
contention[i] = spurs->m.wklCurrentContention[i] - ctxt->wklLocContention[i];
contention[i] = spurs->wklCurrentContention[i] - ctxt->wklLocContention[i];
// If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably
// to prevent unnecessary jumps to the kernel
if (isPoll) {
pendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i];
pendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i];
if (i != ctxt->wklCurrentId) {
contention[i] += pendingContention[i];
}
@ -185,21 +185,21 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
// The system service has the highest priority. Select the system service if
// the system service message bit for this SPU is set.
if (spurs->m.sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) {
if (spurs->sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) {
ctxt->spuIdling = 0;
if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) {
// Clear the message bit
spurs->m.sysSrvMessage.write_relaxed(spurs->m.sysSrvMessage.read_relaxed() & ~(1 << ctxt->spuNum));
spurs->sysSrvMessage.write_relaxed(spurs->sysSrvMessage.read_relaxed() & ~(1 << ctxt->spuNum));
}
} else {
// Caclulate the scheduling weight for each workload
u16 maxWeight = 0;
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i);
u16 wklSignal = spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i);
u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0;
u8 readyCount = spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklReadyCount1[i].read_relaxed();
u8 idleSpuCount = spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed();
u16 wklSignal = spurs->wklSignal1.read_relaxed() & (0x8000 >> i);
u8 wklFlag = spurs->wklFlag.flag.read_relaxed() == 0 ? spurs->wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0;
u8 readyCount = spurs->wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].read_relaxed();
u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].read_relaxed();
u8 requestCount = readyCount + idleSpuCount;
// For a workload to be considered for scheduling:
@ -209,7 +209,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
// 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount)
// OR the workload must be signalled
// OR the workload flag is 0 and the workload is configured as the wokload flag receiver
if (runnable && ctxt->priority[i] != 0 && spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) {
if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i].read_relaxed() > contention[i]) {
if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) {
// The scheduling weight of the workload is formed from the following parameters in decreasing order of priority:
// 1. Wokload signal set or workload flag or ready count > contention
@ -222,7 +222,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
u16 weight = (wklFlag || wklSignal || (readyCount > contention[i])) ? 0x8000 : 0;
weight |= (u16)(ctxt->priority[i] & 0x7F) << 16;
weight |= i == ctxt->wklCurrentId ? 0x80 : 0x00;
weight |= (contention[i] > 0 && spurs->m.wklMinContention[i] > contention[i]) ? 0x40 : 0x00;
weight |= (contention[i] > 0 && spurs->wklMinContention[i] > contention[i]) ? 0x40 : 0x00;
weight |= ((CELL_SPURS_MAX_SPU - contention[i]) & 0x0F) << 2;
weight |= ctxt->wklUniqueId[i] == ctxt->wklCurrentId ? 0x02 : 0x00;
weight |= 0x01;
@ -244,12 +244,12 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
if (!isPoll || wklSelectedId == ctxt->wklCurrentId) {
// Clear workload signal for the selected workload
spurs->m.wklSignal1.write_relaxed(be_t<u16>::make(spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId)));
spurs->m.wklSignal2.write_relaxed(be_t<u16>::make(spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId)));
spurs->wklSignal1.write_relaxed(be_t<u16>::make(spurs->wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId)));
spurs->wklSignal2.write_relaxed(be_t<u16>::make(spurs->wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId)));
// If the selected workload is the wklFlag workload then pull the wklFlag to all 1s
if (wklSelectedId == spurs->m.wklFlagReceiver.read_relaxed()) {
spurs->m.wklFlag.flag.write_relaxed(be_t<u32>::make(0xFFFFFFFF));
if (wklSelectedId == spurs->wklFlagReceiver.read_relaxed()) {
spurs->wklFlag.flag.write_relaxed(be_t<u32>::make(0xFFFFFFFF));
}
}
}
@ -262,8 +262,8 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
}
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
spurs->m.wklCurrentContention[i] = contention[i];
spurs->m.wklPendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i];
spurs->wklCurrentContention[i] = contention[i];
spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i];
ctxt->wklLocContention[i] = 0;
ctxt->wklLocPendingContention[i] = 0;
}
@ -281,7 +281,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
}
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
spurs->m.wklPendingContention[i] = pendingContention[i];
spurs->wklPendingContention[i] = pendingContention[i];
ctxt->wklLocPendingContention[i] = 0;
}
@ -291,7 +291,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) {
} else {
// Not called by kernel and no context switch is required
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
spurs->m.wklPendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i];
spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i];
ctxt->wklLocPendingContention[i] = 0;
}
}
@ -325,13 +325,13 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
u8 contention[CELL_SPURS_MAX_WORKLOAD2];
u8 pendingContention[CELL_SPURS_MAX_WORKLOAD2];
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) {
contention[i] = spurs->m.wklCurrentContention[i & 0x0F] - ctxt->wklLocContention[i & 0x0F];
contention[i] = spurs->wklCurrentContention[i & 0x0F] - ctxt->wklLocContention[i & 0x0F];
contention[i] = i < CELL_SPURS_MAX_WORKLOAD ? contention[i] & 0x0F : contention[i] >> 4;
// If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably
// to prevent unnecessary jumps to the kernel
if (isPoll) {
pendingContention[i] = spurs->m.wklPendingContention[i & 0x0F] - ctxt->wklLocPendingContention[i & 0x0F];
pendingContention[i] = spurs->wklPendingContention[i & 0x0F] - ctxt->wklLocPendingContention[i & 0x0F];
pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4;
if (i != ctxt->wklCurrentId) {
contention[i] += pendingContention[i];
@ -344,12 +344,12 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
// The system service has the highest priority. Select the system service if
// the system service message bit for this SPU is set.
if (spurs->m.sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) {
if (spurs->sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) {
// Not sure what this does. Possibly Mark the SPU as in use.
ctxt->spuIdling = 0;
if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) {
// Clear the message bit
spurs->m.sysSrvMessage.write_relaxed(spurs->m.sysSrvMessage.read_relaxed() & ~(1 << ctxt->spuNum));
spurs->sysSrvMessage.write_relaxed(spurs->sysSrvMessage.read_relaxed() & ~(1 << ctxt->spuNum));
}
} else {
// Caclulate the scheduling weight for each workload
@ -358,10 +358,10 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
auto j = i & 0x0F;
u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j);
u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4;
u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : spurs->m.wklMaxContention[j].read_relaxed() >> 4;
u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j);
u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0;
u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[j].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed();
u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j].read_relaxed() & 0x0F : spurs->wklMaxContention[j].read_relaxed() >> 4;
u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->wklSignal2.read_relaxed() & (0x8000 >> j);
u8 wklFlag = spurs->wklFlag.flag.read_relaxed() == 0 ? spurs->wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0;
u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j].read_relaxed() : spurs->wklIdleSpuCountOrReadyCount2[j].read_relaxed();
// For a workload to be considered for scheduling:
// 1. Its priority must be greater than 0
@ -396,12 +396,12 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
if (!isPoll || wklSelectedId == ctxt->wklCurrentId) {
// Clear workload signal for the selected workload
spurs->m.wklSignal1.write_relaxed(be_t<u16>::make(spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId)));
spurs->m.wklSignal2.write_relaxed(be_t<u16>::make(spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId)));
spurs->wklSignal1.write_relaxed(be_t<u16>::make(spurs->wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId)));
spurs->wklSignal2.write_relaxed(be_t<u16>::make(spurs->wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId)));
// If the selected workload is the wklFlag workload then pull the wklFlag to all 1s
if (wklSelectedId == spurs->m.wklFlagReceiver.read_relaxed()) {
spurs->m.wklFlag.flag.write_relaxed(be_t<u32>::make(0xFFFFFFFF));
if (wklSelectedId == spurs->wklFlagReceiver.read_relaxed()) {
spurs->wklFlag.flag.write_relaxed(be_t<u32>::make(0xFFFFFFFF));
}
}
}
@ -414,8 +414,8 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
}
for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) {
spurs->m.wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4);
spurs->m.wklPendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i];
spurs->wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4);
spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i];
ctxt->wklLocContention[i] = 0;
ctxt->wklLocPendingContention[i] = 0;
}
@ -430,7 +430,7 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
}
for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) {
spurs->m.wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4);
spurs->wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4);
ctxt->wklLocPendingContention[i] = 0;
}
@ -438,7 +438,7 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
} else {
// Not called by kernel and no context switch is required
for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
spurs->m.wklPendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i];
spurs->wklPendingContention[i] = spurs->wklPendingContention[i] - ctxt->wklLocPendingContention[i];
ctxt->wklLocPendingContention[i] = 0;
}
}
@ -455,15 +455,15 @@ bool spursKernel2SelectWorkload(SPUThread & spu) {
/// SPURS kernel dispatch workload
void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) {
auto ctxt = vm::get_ptr<SpursKernelContext>(spu.offset + 0x100);
auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false;
auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false;
auto pollStatus = (u32)widAndPollStatus;
auto wid = (u32)(widAndPollStatus >> 32);
// DMA in the workload info for the selected workload
auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? &ctxt->spurs->m.wklInfo1[wid] :
wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &ctxt->spurs->m.wklInfo2[wid & 0xf] :
&ctxt->spurs->m.wklInfoSysSrv;
auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? &ctxt->spurs->wklInfo1[wid] :
wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &ctxt->spurs->wklInfo2[wid & 0xf] :
&ctxt->spurs->wklInfoSysSrv;
memcpy(vm::get_ptr(spu.offset + 0x3FFE0), wklInfoOffset, 0x20);
@ -503,7 +503,7 @@ void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) {
/// SPURS kernel workload exit
bool spursKernelWorkloadExit(SPUThread & spu) {
auto ctxt = vm::get_ptr<SpursKernelContext>(spu.offset + 0x100);
auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false;
auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false;
// Select next workload to run
spu.GPR[3].clear();
@ -533,7 +533,7 @@ bool spursKernelEntry(SPUThread & spu) {
ctxt->spuNum = spu.GPR[3]._u32[3];
ctxt->spurs.set(spu.GPR[4]._u64[1]);
auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false;
auto isKernel2 = ctxt->spurs->flags1 & SF1_32_WORKLOADS ? true : false;
// Initialise the SPURS context to its initial values
ctxt->dmaTagId = CELL_SPURS_KERNEL_DMA_TAG_ID;
@ -598,30 +598,30 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) {
// Find the number of SPUs that are idling in this SPURS instance
u32 nIdlingSpus = 0;
for (u32 i = 0; i < 8; i++) {
if (spurs->m.spuIdling & (1 << i)) {
if (spurs->spuIdling & (1 << i)) {
nIdlingSpus++;
}
}
bool allSpusIdle = nIdlingSpus == spurs->m.nSpus ? true: false;
bool exitIfNoWork = spurs->m.flags1 & SF1_EXIT_IF_NO_WORK ? true : false;
bool allSpusIdle = nIdlingSpus == spurs->nSpus ? true: false;
bool exitIfNoWork = spurs->flags1 & SF1_EXIT_IF_NO_WORK ? true : false;
shouldExit = allSpusIdle && exitIfNoWork;
// Check if any workloads can be scheduled
bool foundReadyWorkload = false;
if (spurs->m.sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) {
if (spurs->sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) {
foundReadyWorkload = true;
} else {
if (spurs->m.flags1 & SF1_32_WORKLOADS) {
if (spurs->flags1 & SF1_32_WORKLOADS) {
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) {
u32 j = i & 0x0F;
u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j);
u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4;
u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : spurs->m.wklMaxContention[j].read_relaxed() >> 4;
u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklCurrentContention[j] & 0x0F : spurs->m.wklCurrentContention[j] >> 4;
u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j);
u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0;
u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[j].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed();
u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklMaxContention[j].read_relaxed() & 0x0F : spurs->wklMaxContention[j].read_relaxed() >> 4;
u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklCurrentContention[j] & 0x0F : spurs->wklCurrentContention[j] >> 4;
u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->wklSignal2.read_relaxed() & (0x8000 >> j);
u8 wklFlag = spurs->wklFlag.flag.read_relaxed() == 0 ? spurs->wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0;
u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[j].read_relaxed() : spurs->wklIdleSpuCountOrReadyCount2[j].read_relaxed();
if (runnable && priority > 0 && maxContention > contention) {
if (wklFlag || wklSignal || readyCount > contention) {
@ -633,14 +633,14 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) {
} else {
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i);
u16 wklSignal = spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i);
u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0;
u8 readyCount = spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklReadyCount1[i].read_relaxed();
u8 idleSpuCount = spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed();
u16 wklSignal = spurs->wklSignal1.read_relaxed() & (0x8000 >> i);
u8 wklFlag = spurs->wklFlag.flag.read_relaxed() == 0 ? spurs->wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0;
u8 readyCount = spurs->wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklReadyCount1[i].read_relaxed();
u8 idleSpuCount = spurs->wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->wklIdleSpuCountOrReadyCount2[i].read_relaxed();
u8 requestCount = readyCount + idleSpuCount;
if (runnable && ctxt->priority[i] != 0 && spurs->m.wklMaxContention[i].read_relaxed() > spurs->m.wklCurrentContention[i]) {
if (wklFlag || wklSignal || (readyCount != 0 && requestCount > spurs->m.wklCurrentContention[i])) {
if (runnable && ctxt->priority[i] != 0 && spurs->wklMaxContention[i].read_relaxed() > spurs->wklCurrentContention[i]) {
if (wklFlag || wklSignal || (readyCount != 0 && requestCount > spurs->wklCurrentContention[i])) {
foundReadyWorkload = true;
break;
}
@ -649,11 +649,11 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) {
}
}
bool spuIdling = spurs->m.spuIdling & (1 << ctxt->spuNum) ? true : false;
bool spuIdling = spurs->spuIdling & (1 << ctxt->spuNum) ? true : false;
if (foundReadyWorkload && shouldExit == false) {
spurs->m.spuIdling &= ~(1 << ctxt->spuNum);
spurs->spuIdling &= ~(1 << ctxt->spuNum);
} else {
spurs->m.spuIdling |= 1 << ctxt->spuNum;
spurs->spuIdling |= 1 << ctxt->spuNum;
}
// If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events.
@ -677,7 +677,7 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) {
void spursSysServiceMain(SPUThread & spu, u32 pollStatus) {
auto ctxt = vm::get_ptr<SpursKernelContext>(spu.offset + 0x100);
if (ctxt->spurs.addr() % CellSpurs::align) {
if (!ctxt->spurs.aligned()) {
assert(!"spursSysServiceMain(): invalid spurs alignment");
//spursHalt(spu);
//return;
@ -689,19 +689,19 @@ void spursSysServiceMain(SPUThread & spu, u32 pollStatus) {
vm::reservation_acquire(vm::get_ptr(spu.offset + 0x100), vm::cast(ctxt->spurs.addr()), 128);
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.priv_ptr();
// Halt if already initialised
if (spurs->m.sysSrvOnSpu & (1 << ctxt->spuNum)) {
if (spurs->sysSrvOnSpu & (1 << ctxt->spuNum)) {
assert(!"spursSysServiceMain(): already initialized");
//spursHalt(spu);
//return;
}
spurs->m.sysSrvOnSpu |= 1 << ctxt->spuNum;
spurs->sysSrvOnSpu |= 1 << ctxt->spuNum;
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->m.wklState1, 128);
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->wklState1, 128);
});
ctxt->traceBuffer = 0;
@ -779,27 +779,27 @@ void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt)
bool updateWorkload = false;
bool terminate = false;
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.priv_ptr();
// Terminate request
if (spurs->m.sysSrvMsgTerminate & (1 << ctxt->spuNum)) {
spurs->m.sysSrvOnSpu &= ~(1 << ctxt->spuNum);
if (spurs->sysSrvMsgTerminate & (1 << ctxt->spuNum)) {
spurs->sysSrvOnSpu &= ~(1 << ctxt->spuNum);
terminate = true;
}
// Update workload message
if (spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << ctxt->spuNum)) {
spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << ctxt->spuNum);
if (spurs->sysSrvMsgUpdateWorkload.read_relaxed() & (1 << ctxt->spuNum)) {
spurs->sysSrvMsgUpdateWorkload &= ~(1 << ctxt->spuNum);
updateWorkload = true;
}
// Update trace message
if (spurs->m.sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) {
if (spurs->sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) {
updateTrace = true;
}
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->m.wklState1, 128);
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->wklState1, 128);
});
// Process update workload message
@ -821,9 +821,9 @@ void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt)
/// Activate a workload
void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt) {
auto spurs = vm::get_ptr<CellSpurs>(spu.offset + 0x100);
memcpy(vm::get_ptr(spu.offset + 0x30000), vm::get_ptr(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklInfo1))), 0x200);
if (spurs->m.flags1 & SF1_32_WORKLOADS) {
memcpy(vm::get_ptr(spu.offset + 0x30200), vm::get_ptr(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklInfo2))), 0x200);
memcpy(vm::get_ptr(spu.offset + 0x30000), vm::get_ptr(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklInfo1))), 0x200);
if (spurs->flags1 & SF1_32_WORKLOADS) {
memcpy(vm::get_ptr(spu.offset + 0x30200), vm::get_ptr(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklInfo2))), 0x200);
}
u32 wklShutdownBitSet = 0;
@ -836,7 +836,7 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt)
ctxt->priority[i] = wklInfo1[i].priority[ctxt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[ctxt->spuNum];
ctxt->wklUniqueId[i] = wklInfo1[i].uniqueId.read_relaxed();
if (spurs->m.flags1 & SF1_32_WORKLOADS) {
if (spurs->flags1 & SF1_32_WORKLOADS) {
auto wklInfo2 = vm::get_ptr<CellSpurs::WorkloadInfo>(spu.offset + 0x30200);
// Copy the priority of the workload for this SPU to the LS
@ -846,50 +846,50 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt)
}
}
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.priv_ptr();
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
// Update workload status and runnable flag based on the workload state
auto wklStatus = spurs->m.wklStatus1[i];
if (spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) {
spurs->m.wklStatus1[i] |= 1 << ctxt->spuNum;
auto wklStatus = spurs->wklStatus1[i];
if (spurs->wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) {
spurs->wklStatus1[i] |= 1 << ctxt->spuNum;
ctxt->wklRunnable1 |= 0x8000 >> i;
} else {
spurs->m.wklStatus1[i] &= ~(1 << ctxt->spuNum);
spurs->wklStatus1[i] &= ~(1 << ctxt->spuNum);
}
// If the workload is shutting down and if this is the last SPU from which it is being removed then
// add it to the shutdown bit set
if (spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) {
if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->m.wklStatus1[i] == 0)) {
spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE);
if (spurs->wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) {
if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus1[i] == 0)) {
spurs->wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE);
wklShutdownBitSet |= 0x80000000u >> i;
}
}
if (spurs->m.flags1 & SF1_32_WORKLOADS) {
if (spurs->flags1 & SF1_32_WORKLOADS) {
// Update workload status and runnable flag based on the workload state
wklStatus = spurs->m.wklStatus2[i];
if (spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) {
spurs->m.wklStatus2[i] |= 1 << ctxt->spuNum;
wklStatus = spurs->wklStatus2[i];
if (spurs->wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) {
spurs->wklStatus2[i] |= 1 << ctxt->spuNum;
ctxt->wklRunnable2 |= 0x8000 >> i;
} else {
spurs->m.wklStatus2[i] &= ~(1 << ctxt->spuNum);
spurs->wklStatus2[i] &= ~(1 << ctxt->spuNum);
}
// If the workload is shutting down and if this is the last SPU from which it is being removed then
// add it to the shutdown bit set
if (spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) {
if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->m.wklStatus2[i] == 0)) {
spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE);
if (spurs->wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) {
if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->wklStatus2[i] == 0)) {
spurs->wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE);
wklShutdownBitSet |= 0x8000 >> i;
}
}
}
}
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->m.wklState1, 128);
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->wklState1, 128);
});
if (wklShutdownBitSet) {
@ -903,28 +903,28 @@ void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelC
// workloads that have a shutdown completion hook registered
u32 wklNotifyBitSet;
u8 spuPort;
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.priv_ptr();
wklNotifyBitSet = 0;
spuPort = spurs->m.spuPort;;
spuPort = spurs->spuPort;;
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) {
if (wklShutdownBitSet & (0x80000000u >> i)) {
spurs->m.wklEvent1[i] |= 0x01;
if (spurs->m.wklEvent1[i] & 0x02 || spurs->m.wklEvent1[i] & 0x10) {
spurs->wklEvent1[i] |= 0x01;
if (spurs->wklEvent1[i] & 0x02 || spurs->wklEvent1[i] & 0x10) {
wklNotifyBitSet |= 0x80000000u >> i;
}
}
if (wklShutdownBitSet & (0x8000 >> i)) {
spurs->m.wklEvent2[i] |= 0x01;
if (spurs->m.wklEvent2[i] & 0x02 || spurs->m.wklEvent2[i] & 0x10) {
spurs->wklEvent2[i] |= 0x01;
if (spurs->wklEvent2[i] & 0x02 || spurs->wklEvent2[i] & 0x10) {
wklNotifyBitSet |= 0x8000 >> i;
}
}
}
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->m.wklState1, 128);
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->wklState1, 128);
});
if (wklNotifyBitSet) {
@ -935,7 +935,7 @@ void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelC
/// Update the trace count for this SPU
void spursSysServiceTraceSaveCount(SPUThread & spu, SpursKernelContext * ctxt) {
if (ctxt->traceBuffer) {
auto traceInfo = vm::ptr<CellSpursTraceInfo>::make((u32)(ctxt->traceBuffer - (ctxt->spurs->m.traceStartIndex[ctxt->spuNum] << 4)));
auto traceInfo = vm::ptr<CellSpursTraceInfo>::make((u32)(ctxt->traceBuffer - (ctxt->spurs->traceStartIndex[ctxt->spuNum] << 4)));
traceInfo->count[ctxt->spuNum] = ctxt->traceMsgCount;
}
}
@ -945,51 +945,51 @@ void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32
bool notify;
u8 sysSrvMsgUpdateTrace;
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.priv_ptr();
sysSrvMsgUpdateTrace = spurs->m.sysSrvMsgUpdateTrace;
spurs->m.sysSrvMsgUpdateTrace &= ~(1 << ctxt->spuNum);
spurs->m.xCC &= ~(1 << ctxt->spuNum);
spurs->m.xCC |= arg2 << ctxt->spuNum;
sysSrvMsgUpdateTrace = spurs->sysSrvMsgUpdateTrace;
spurs->sysSrvMsgUpdateTrace &= ~(1 << ctxt->spuNum);
spurs->xCC &= ~(1 << ctxt->spuNum);
spurs->xCC |= arg2 << ctxt->spuNum;
notify = false;
if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) && (spurs->m.sysSrvMsgUpdateTrace == 0) && (spurs->m.xCD != 0)) {
spurs->m.xCD = 0;
if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) && (spurs->sysSrvMsgUpdateTrace == 0) && (spurs->xCD != 0)) {
spurs->xCD = 0;
notify = true;
}
if (arg4 && spurs->m.xCD != 0) {
spurs->m.xCD = 0;
if (arg4 && spurs->xCD != 0) {
spurs->xCD = 0;
notify = true;
}
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->m.wklState1, 128);
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->wklState1, 128);
});
// Get trace parameters from CellSpurs and store them in the LS
if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) || (arg3 != 0)) {
vm::reservation_acquire(vm::get_ptr(spu.offset + 0x80), vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.traceBuffer)), 128);
auto spurs = vm::get_ptr<CellSpurs>(spu.offset + 0x80 - offsetof(CellSpurs, m.traceBuffer));
vm::reservation_acquire(vm::get_ptr(spu.offset + 0x80), vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, traceBuffer)), 128);
auto spurs = vm::get_ptr<CellSpurs>(spu.offset + 0x80 - offsetof(CellSpurs, traceBuffer));
if (ctxt->traceMsgCount != 0xFF || spurs->m.traceBuffer.addr() == 0) {
if (ctxt->traceMsgCount != 0xFF || spurs->traceBuffer.addr() == 0) {
spursSysServiceTraceSaveCount(spu, ctxt);
} else {
memcpy(vm::get_ptr(spu.offset + 0x2C00), vm::get_ptr(spurs->m.traceBuffer.addr() & -0x4), 0x80);
memcpy(vm::get_ptr(spu.offset + 0x2C00), vm::get_ptr(spurs->traceBuffer.addr() & -0x4), 0x80);
auto traceBuffer = vm::get_ptr<CellSpursTraceInfo>(spu.offset + 0x2C00);
ctxt->traceMsgCount = traceBuffer->count[ctxt->spuNum];
}
ctxt->traceBuffer = spurs->m.traceBuffer.addr() + (spurs->m.traceStartIndex[ctxt->spuNum] << 4);
ctxt->traceMaxCount = spurs->m.traceStartIndex[1] - spurs->m.traceStartIndex[0];
ctxt->traceBuffer = spurs->traceBuffer.addr() + (spurs->traceStartIndex[ctxt->spuNum] << 4);
ctxt->traceMaxCount = spurs->traceStartIndex[1] - spurs->traceStartIndex[0];
if (ctxt->traceBuffer == 0) {
ctxt->traceMsgCount = 0;
}
}
if (notify) {
auto spurs = vm::get_ptr<CellSpurs>(spu.offset + 0x2D80 - offsetof(CellSpurs, m.wklState1));
sys_spu_thread_send_event(spu, spurs->m.spuPort, 2, 0);
auto spurs = vm::get_ptr<CellSpurs>(spu.offset + 0x2D80 - offsetof(CellSpurs, wklState1));
sys_spu_thread_send_event(spu, spurs->spuPort, 2, 0);
}
}
@ -999,18 +999,18 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte
bool do_return = false;
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() {
vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, wklState1)), 128, [&]() {
auto spurs = ctxt->spurs.priv_ptr();
if (spurs->m.sysSrvWorkload[ctxt->spuNum] == 0xFF) {
if (spurs->sysSrvWorkload[ctxt->spuNum] == 0xFF) {
do_return = true;
return;
}
wklId = spurs->m.sysSrvWorkload[ctxt->spuNum];
spurs->m.sysSrvWorkload[ctxt->spuNum] = 0xFF;
wklId = spurs->sysSrvWorkload[ctxt->spuNum];
spurs->sysSrvWorkload[ctxt->spuNum] = 0xFF;
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->m.wklState1, 128);
memcpy(vm::get_ptr(spu.offset + 0x2D80), spurs->wklState1, 128);
});
if (do_return) return;
@ -1021,11 +1021,11 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte
auto spurs = ctxt->spurs.priv_ptr();
if (wklId >= CELL_SPURS_MAX_WORKLOAD) {
spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10;
spurs->m.wklReadyCount1[wklId & 0x0F].write_relaxed(spurs->m.wklReadyCount1[wklId & 0x0F].read_relaxed() - 1);
spurs->wklCurrentContention[wklId & 0x0F] -= 0x10;
spurs->wklReadyCount1[wklId & 0x0F].write_relaxed(spurs->wklReadyCount1[wklId & 0x0F].read_relaxed() - 1);
} else {
spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x01;
spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1);
spurs->wklCurrentContention[wklId & 0x0F] -= 0x01;
spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(spurs->wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1);
}
memcpy(vm::get_ptr(spu.offset + 0x100), spurs, 128);
@ -1135,8 +1135,8 @@ void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs) {
spu.GPR[2].clear();
spu.GPR[3] = u128::from64r(taskArgs._u64[0], taskArgs._u64[1]);
spu.GPR[4]._u64[1] = taskset->m.args;
spu.GPR[4]._u64[0] = taskset->m.spurs.addr();
spu.GPR[4]._u64[1] = taskset->args;
spu.GPR[4]._u64[0] = taskset->spurs.addr();
for (auto i = 5; i < 128; i++) {
spu.GPR[i].clear();
}
@ -1156,15 +1156,15 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
// Verify taskset state is valid
auto _0 = be_t<u128>::make(u128::from32(0));
if ((taskset->m.waiting & taskset->m.running) != _0 || (taskset->m.ready & taskset->m.pending_ready) != _0 ||
((taskset->m.running | taskset->m.ready | taskset->m.pending_ready | taskset->m.signalled | taskset->m.waiting) & be_t<u128>::make(~taskset->m.enabled.value())) != _0) {
if ((taskset->waiting & taskset->running) != _0 || (taskset->ready & taskset->pending_ready) != _0 ||
((taskset->running | taskset->ready | taskset->pending_ready | taskset->signalled | taskset->waiting) & be_t<u128>::make(~taskset->enabled.value())) != _0) {
assert(!"Invalid taskset state");
//spursHalt(spu);
//return CELL_OK;
}
// Find the number of tasks that have become ready since the last iteration
auto newlyReadyTasks = (taskset->m.signalled | taskset->m.pending_ready).value() & ~taskset->m.ready.value();
auto newlyReadyTasks = (taskset->signalled | taskset->pending_ready).value() & ~taskset->ready.value();
numNewlyReadyTasks = 0;
for (auto i = 0; i < 128; i++) {
if (newlyReadyTasks._bit[i]) {
@ -1174,11 +1174,11 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
u128 readyButNotRunning;
u8 selectedTaskId;
auto running = taskset->m.running.value();
auto waiting = taskset->m.waiting.value();
auto enabled = taskset->m.enabled.value();
auto signalled = (taskset->m.signalled & (taskset->m.ready | taskset->m.pending_ready)).value();
auto ready = (taskset->m.signalled | taskset->m.ready | taskset->m.pending_ready).value();
auto running = taskset->running.value();
auto waiting = taskset->waiting.value();
auto enabled = taskset->enabled.value();
auto signalled = (taskset->signalled & (taskset->ready | taskset->pending_ready)).value();
auto ready = (taskset->signalled | taskset->ready | taskset->pending_ready).value();
switch (request) {
case SPURS_TASKSET_REQUEST_POLL_SIGNAL:
@ -1207,20 +1207,20 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
break;
case SPURS_TASKSET_REQUEST_POLL:
readyButNotRunning = ready & ~running;
if (taskset->m.wkl_flag_wait_task < CELL_SPURS_MAX_TASK) {
readyButNotRunning = readyButNotRunning & ~(u128::fromBit(taskset->m.wkl_flag_wait_task));
if (taskset->wkl_flag_wait_task < CELL_SPURS_MAX_TASK) {
readyButNotRunning = readyButNotRunning & ~(u128::fromBit(taskset->wkl_flag_wait_task));
}
rc = readyButNotRunning != _0 ? 1 : 0;
break;
case SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG:
if (taskset->m.wkl_flag_wait_task == 0x81) {
if (taskset->wkl_flag_wait_task == 0x81) {
// A workload flag is already pending so consume it
taskset->m.wkl_flag_wait_task = 0x80;
taskset->wkl_flag_wait_task = 0x80;
rc = 0;
} else if (taskset->m.wkl_flag_wait_task == 0x80) {
} else if (taskset->wkl_flag_wait_task == 0x80) {
// No tasks are waiting for the workload flag. Mark this task as waiting for the workload flag.
taskset->m.wkl_flag_wait_task = ctxt->taskId;
taskset->wkl_flag_wait_task = ctxt->taskId;
running._bit[ctxt->taskId] = false;
waiting._bit[ctxt->taskId] = true;
rc = 1;
@ -1232,25 +1232,25 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
break;
case SPURS_TASKSET_REQUEST_SELECT_TASK:
readyButNotRunning = ready & ~running;
if (taskset->m.wkl_flag_wait_task < CELL_SPURS_MAX_TASK) {
readyButNotRunning = readyButNotRunning & ~(u128::fromBit(taskset->m.wkl_flag_wait_task));
if (taskset->wkl_flag_wait_task < CELL_SPURS_MAX_TASK) {
readyButNotRunning = readyButNotRunning & ~(u128::fromBit(taskset->wkl_flag_wait_task));
}
// Select a task from the readyButNotRunning set to run. Start from the task after the last scheduled task to ensure fairness.
for (selectedTaskId = taskset->m.last_scheduled_task + 1; selectedTaskId < 128; selectedTaskId++) {
for (selectedTaskId = taskset->last_scheduled_task + 1; selectedTaskId < 128; selectedTaskId++) {
if (readyButNotRunning._bit[selectedTaskId]) {
break;
}
}
if (selectedTaskId == 128) {
for (selectedTaskId = 0; selectedTaskId < taskset->m.last_scheduled_task + 1; selectedTaskId++) {
for (selectedTaskId = 0; selectedTaskId < taskset->last_scheduled_task + 1; selectedTaskId++) {
if (readyButNotRunning._bit[selectedTaskId]) {
break;
}
}
if (selectedTaskId == taskset->m.last_scheduled_task + 1) {
if (selectedTaskId == taskset->last_scheduled_task + 1) {
selectedTaskId = CELL_SPURS_MAX_TASK;
}
}
@ -1258,20 +1258,20 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
*taskId = selectedTaskId;
*isWaiting = waiting._bit[selectedTaskId < CELL_SPURS_MAX_TASK ? selectedTaskId : 0] ? 1 : 0;
if (selectedTaskId != CELL_SPURS_MAX_TASK) {
taskset->m.last_scheduled_task = selectedTaskId;
taskset->last_scheduled_task = selectedTaskId;
running._bit[selectedTaskId] = true;
waiting._bit[selectedTaskId] = false;
}
break;
case SPURS_TASKSET_REQUEST_RECV_WKL_FLAG:
if (taskset->m.wkl_flag_wait_task < CELL_SPURS_MAX_TASK) {
if (taskset->wkl_flag_wait_task < CELL_SPURS_MAX_TASK) {
// There is a task waiting for the workload flag
taskset->m.wkl_flag_wait_task = 0x80;
taskset->wkl_flag_wait_task = 0x80;
rc = 1;
numNewlyReadyTasks++;
} else {
// No tasks are waiting for the workload flag
taskset->m.wkl_flag_wait_task = 0x81;
taskset->wkl_flag_wait_task = 0x81;
rc = 0;
}
break;
@ -1281,12 +1281,12 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
//return CELL_OK;
}
taskset->m.pending_ready = _0;
taskset->m.running = running;
taskset->m.waiting = waiting;
taskset->m.enabled = enabled;
taskset->m.signalled = signalled;
taskset->m.ready = ready;
taskset->pending_ready = _0;
taskset->running = running;
taskset->waiting = waiting;
taskset->enabled = enabled;
taskset->signalled = signalled;
taskset->ready = ready;
memcpy(vm::get_ptr(spu.offset + 0x2700), taskset, 128);
});
@ -1295,14 +1295,14 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
vm::reservation_op(vm::cast(kernelCtxt->spurs.addr()), 128, [&]() {
auto spurs = kernelCtxt->spurs.priv_ptr();
s32 readyCount = kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[kernelCtxt->wklCurrentId].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].read_relaxed();
s32 readyCount = kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->wklReadyCount1[kernelCtxt->wklCurrentId].read_relaxed() : spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].read_relaxed();
readyCount += numNewlyReadyTasks;
readyCount = readyCount < 0 ? 0 : readyCount > 0xFF ? 0xFF : readyCount;
if (kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD) {
spurs->m.wklReadyCount1[kernelCtxt->wklCurrentId].write_relaxed(readyCount);
spurs->wklReadyCount1[kernelCtxt->wklCurrentId].write_relaxed(readyCount);
} else {
spurs->m.wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].write_relaxed(readyCount);
spurs->wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].write_relaxed(readyCount);
}
memcpy(vm::get_ptr(spu.offset + 0x100), spurs, 128);
@ -1433,7 +1433,7 @@ void spursTasksetDispatch(SPUThread & spu) {
ctxt->taskId = taskId;
// DMA in the task info for the selected task
memcpy(vm::get_ptr(spu.offset + 0x2780), &ctxt->taskset->m.task_info[taskId], sizeof(CellSpursTaskset::TaskInfo));
memcpy(vm::get_ptr(spu.offset + 0x2780), &ctxt->taskset->task_info[taskId], sizeof(CellSpursTaskset::TaskInfo));
auto taskInfo = vm::get_ptr<CellSpursTaskset::TaskInfo>(spu.offset + 0x2780);
auto elfAddr = taskInfo->elf_addr.addr().value();
taskInfo->elf_addr.set(taskInfo->elf_addr.addr() & 0xFFFFFFFFFFFFFFF8ull);
@ -1469,7 +1469,7 @@ void spursTasksetDispatch(SPUThread & spu) {
ctxt->x2FD4 = elfAddr & 5; // TODO: Figure this out
if ((elfAddr & 5) == 1) {
memcpy(vm::get_ptr(spu.offset + 0x2FC0), &((CellSpursTaskset2*)(ctxt->taskset.get_ptr()))->m.task_exit_code[taskId], 0x10);
memcpy(vm::get_ptr(spu.offset + 0x2FC0), &((CellSpursTaskset2*)(ctxt->taskset.get_ptr()))->task_exit_code[taskId], 0x10);
}
// Trace - GUID
@ -1486,7 +1486,7 @@ void spursTasksetDispatch(SPUThread & spu) {
spursTasksetStartTask(spu, taskInfo->args);
} else {
if (taskset->m.enable_clear_ls) {
if (taskset->enable_clear_ls) {
memset(vm::get_ptr<void>(spu.offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP);
}
@ -1557,7 +1557,7 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) {
spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_DESTROY_TASK, nullptr, nullptr);
}
auto addr = ctxt->x2FD4 == 4 ? taskset->m.x78 : ctxt->x2FC0;
auto addr = ctxt->x2FD4 == 4 ? taskset->x78 : ctxt->x2FC0;
auto args = ctxt->x2FD4 == 4 ? 0 : ctxt->x2FC8;
spursTasksetOnTaskExit(spu, addr, ctxt->taskId, ctxt->taskExitCode, args);
}

View File

@ -26,7 +26,7 @@ s32 syncMutexInitialize(vm::ptr<CellSyncMutex> mutex)
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (mutex.addr() % 4)
if (!mutex.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -52,7 +52,7 @@ s32 cellSyncMutexLock(vm::ptr<CellSyncMutex> mutex)
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (mutex.addr() % 4)
if (!mutex.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -80,7 +80,7 @@ s32 cellSyncMutexTryLock(vm::ptr<CellSyncMutex> mutex)
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (mutex.addr() % 4)
if (!mutex.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -100,7 +100,7 @@ s32 cellSyncMutexUnlock(vm::ptr<CellSyncMutex> mutex)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (mutex.addr() % 4)
if (!mutex.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -119,7 +119,7 @@ s32 syncBarrierInitialize(vm::ptr<CellSyncBarrier> barrier, u16 total_count)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (barrier.addr() % 4)
if (!barrier.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -169,7 +169,7 @@ s32 cellSyncBarrierNotify(vm::ptr<CellSyncBarrier> barrier)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (barrier.addr() % 4)
if (!barrier.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -192,7 +192,7 @@ s32 cellSyncBarrierTryNotify(vm::ptr<CellSyncBarrier> barrier)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (barrier.addr() % 4)
if (!barrier.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -235,7 +235,7 @@ s32 cellSyncBarrierWait(vm::ptr<CellSyncBarrier> barrier)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (barrier.addr() % 4)
if (!barrier.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -258,7 +258,7 @@ s32 cellSyncBarrierTryWait(vm::ptr<CellSyncBarrier> barrier)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (barrier.addr() % 4)
if (!barrier.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -279,7 +279,7 @@ s32 syncRwmInitialize(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer, u32 buffer
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (rwm.addr() % 16 || buffer.addr() % 128)
if (!rwm.aligned() || buffer % 128)
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -335,7 +335,7 @@ s32 cellSyncRwmRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (rwm.addr() % 16)
if (!rwm.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -369,7 +369,7 @@ s32 cellSyncRwmTryRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (rwm.addr() % 16)
if (!rwm.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -411,7 +411,7 @@ s32 cellSyncRwmWrite(vm::ptr<CellSyncRwm> rwm, vm::ptr<const void> buffer)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (rwm.addr() % 16)
if (!rwm.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -446,7 +446,7 @@ s32 cellSyncRwmTryWrite(vm::ptr<CellSyncRwm> rwm, vm::ptr<const void> buffer)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (rwm.addr() % 16)
if (!rwm.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -478,7 +478,7 @@ s32 syncQueueInitialize(vm::ptr<CellSyncQueue> queue, vm::ptr<u8> buffer, u32 si
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 32 || buffer.addr() % 16)
if (!queue.aligned() || buffer % 16)
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -533,7 +533,7 @@ s32 cellSyncQueuePush(vm::ptr<CellSyncQueue> queue, vm::ptr<const void> buffer)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 32)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -571,7 +571,7 @@ s32 cellSyncQueueTryPush(vm::ptr<CellSyncQueue> queue, vm::ptr<const void> buffe
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 32)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -630,7 +630,7 @@ s32 cellSyncQueuePop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 32)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -668,7 +668,7 @@ s32 cellSyncQueueTryPop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 32)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -721,7 +721,7 @@ s32 cellSyncQueuePeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 32)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -757,7 +757,7 @@ s32 cellSyncQueueTryPeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 32)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -794,7 +794,7 @@ s32 cellSyncQueueSize(vm::ptr<CellSyncQueue> queue)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 32)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -815,7 +815,7 @@ s32 cellSyncQueueClear(vm::ptr<CellSyncQueue> queue)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 32)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -931,7 +931,7 @@ s32 syncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u3
{
return CELL_SYNC_ERROR_INVAL;
}
if (queue.addr() % 128 || buffer.addr() % 16)
if (!queue.aligned() || buffer % 16)
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1144,7 +1144,7 @@ s32 _cellSyncLFQueueGetPushPointer2(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32>
return result;
}
s32 syncLFQueueCompletePushPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, const std::function<s32(u32 addr, u32 arg)> fpSendSignal)
s32 syncLFQueueCompletePushPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, std::function<s32(u32 addr, u32 arg)> fpSendSignal)
{
if (queue->m_direction != CELL_SYNC_QUEUE_PPU2SPU)
{
@ -1285,7 +1285,7 @@ s32 _cellSyncLFQueueCompletePushPointer(vm::ptr<CellSyncLFQueue> queue, s32 poin
return syncLFQueueCompletePushPointer(queue, pointer, fpSendSignal);
}
s32 syncLFQueueCompletePushPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, const std::function<s32(u32 addr, u32 arg)> fpSendSignal)
s32 syncLFQueueCompletePushPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, std::function<s32(u32 addr, u32 arg)> fpSendSignal)
{
throw __FUNCTION__;
}
@ -1307,7 +1307,7 @@ s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm:
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 128 || buffer.addr() % 16)
if (!queue.aligned() || buffer % 16)
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1490,7 +1490,7 @@ s32 _cellSyncLFQueueGetPopPointer2(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32>
return result;
}
s32 syncLFQueueCompletePopPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, const std::function<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull)
s32 syncLFQueueCompletePopPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, std::function<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull)
{
if (queue->m_direction != CELL_SYNC_QUEUE_SPU2PPU)
{
@ -1631,7 +1631,7 @@ s32 _cellSyncLFQueueCompletePopPointer(vm::ptr<CellSyncLFQueue> queue, s32 point
return syncLFQueueCompletePopPointer(queue, pointer, fpSendSignal, noQueueFull);
}
s32 syncLFQueueCompletePopPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, const std::function<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull)
s32 syncLFQueueCompletePopPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, std::function<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull)
{
throw __FUNCTION__;
}
@ -1653,7 +1653,7 @@ s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm::
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 128 || buffer.addr() % 16)
if (!queue.aligned() || buffer % 16)
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1717,7 +1717,7 @@ s32 cellSyncLFQueueClear(vm::ptr<CellSyncLFQueue> queue)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 128)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1767,7 +1767,7 @@ s32 cellSyncLFQueueSize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> size)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 128)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1802,7 +1802,7 @@ s32 cellSyncLFQueueDepth(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> depth)
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 128)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1819,7 +1819,7 @@ s32 _cellSyncLFQueueGetSignalAddress(vm::ptr<const CellSyncLFQueue> queue, vm::p
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 128)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1837,7 +1837,7 @@ s32 cellSyncLFQueueGetDirection(vm::ptr<const CellSyncLFQueue> queue, vm::ptr<Ce
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 128)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1854,7 +1854,7 @@ s32 cellSyncLFQueueGetEntrySize(vm::ptr<const CellSyncLFQueue> queue, vm::ptr<u3
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (queue.addr() % 128)
if (!queue.aligned())
{
return CELL_SYNC_ERROR_ALIGN;
}

View File

@ -31,7 +31,7 @@ enum
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, // ???
};
union CellSyncMutex
union set_alignment(4) CellSyncMutex
{
struct sync_t
{
@ -48,9 +48,9 @@ union CellSyncMutex
atomic_be_t<sync_t> sync_var;
};
static_assert(sizeof(CellSyncMutex) == 4, "CellSyncMutex: wrong size");
CHECK_SIZE_ALIGN(CellSyncMutex, 4, 4);
struct CellSyncBarrier
struct set_alignment(4) CellSyncBarrier
{
struct data_t
{
@ -61,9 +61,9 @@ struct CellSyncBarrier
atomic_be_t<data_t> data;
};
static_assert(sizeof(CellSyncBarrier) == 4, "CellSyncBarrier: wrong size");
CHECK_SIZE_ALIGN(CellSyncBarrier, 4, 4);
struct CellSyncRwm
struct set_alignment(16) CellSyncRwm
{
struct data_t
{
@ -76,9 +76,9 @@ struct CellSyncRwm
vm::bptr<void, u64> m_buffer;
};
static_assert(sizeof(CellSyncRwm) == 16, "CellSyncRwm: wrong size");
CHECK_SIZE_ALIGN(CellSyncRwm, 16, 16);
struct CellSyncQueue
struct set_alignment(32) CellSyncQueue
{
struct data_t
{
@ -93,7 +93,7 @@ struct CellSyncQueue
be_t<u64> reserved;
};
static_assert(sizeof(CellSyncQueue) == 32, "CellSyncQueue: wrong size");
CHECK_SIZE_ALIGN(CellSyncQueue, 32, 32);
enum CellSyncQueueDirection : u32 // CellSyncLFQueueDirection
{
@ -103,7 +103,7 @@ enum CellSyncQueueDirection : u32 // CellSyncLFQueueDirection
CELL_SYNC_QUEUE_ANY2ANY = 3, // SPU/PPU to SPU/PPU
};
struct CellSyncLFQueue
struct set_alignment(128) CellSyncLFQueue
{
struct pop1_t
{
@ -188,7 +188,7 @@ struct CellSyncLFQueue
}
};
static_assert(sizeof(CellSyncLFQueue) == 128, "CellSyncLFQueue: wrong size");
CHECK_SIZE_ALIGN(CellSyncLFQueue, 128, 128);
s32 syncMutexInitialize(vm::ptr<CellSyncMutex> mutex);
@ -201,11 +201,11 @@ s32 syncQueueInitialize(vm::ptr<CellSyncQueue> queue, vm::ptr<u8> buffer, u32 si
s32 syncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr<void> eaSignal);
s32 syncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 isBlocking, u32 useEventQueue);
s32 syncLFQueueGetPushPointer2(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 isBlocking, u32 useEventQueue);
s32 syncLFQueueCompletePushPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, const std::function<s32(u32 addr, u32 arg)> fpSendSignal);
s32 syncLFQueueCompletePushPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, const std::function<s32(u32 addr, u32 arg)> fpSendSignal);
s32 syncLFQueueCompletePushPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, std::function<s32(u32 addr, u32 arg)> fpSendSignal);
s32 syncLFQueueCompletePushPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, std::function<s32(u32 addr, u32 arg)> fpSendSignal);
s32 syncLFQueueGetPopPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 isBlocking, u32, u32 useEventQueue);
s32 syncLFQueueGetPopPointer2(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 isBlocking, u32 useEventQueue);
s32 syncLFQueueCompletePopPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, const std::function<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull);
s32 syncLFQueueCompletePopPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, const std::function<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull);
s32 syncLFQueueCompletePopPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, std::function<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull);
s32 syncLFQueueCompletePopPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, std::function<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull);
s32 syncLFQueueAttachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncLFQueue> queue);
s32 syncLFQueueDetachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncLFQueue> queue);

View File

@ -41,7 +41,7 @@ struct CellSync2MutexAttribute
u8 reserved[86];
};
static_assert(sizeof(CellSync2MutexAttribute) == 128, "Wrong CellSync2MutexAttribute size");
CHECK_SIZE(CellSync2MutexAttribute, 128);
struct CellSync2CondAttribute
{
@ -51,7 +51,7 @@ struct CellSync2CondAttribute
u8 reserved[90];
};
static_assert(sizeof(CellSync2CondAttribute) == 128, "Wrong CellSync2CondAttribute size");
CHECK_SIZE(CellSync2CondAttribute, 128);
struct CellSync2SemaphoreAttribute
{
@ -62,7 +62,7 @@ struct CellSync2SemaphoreAttribute
u8 reserved[88];
};
static_assert(sizeof(CellSync2SemaphoreAttribute) == 128, "Wrong CellSync2SemaphoreAttribute size");
CHECK_SIZE(CellSync2SemaphoreAttribute, 128);
struct CellSync2QueueAttribute
{
@ -76,4 +76,4 @@ struct CellSync2QueueAttribute
u8 reserved[76];
};
static_assert(sizeof(CellSync2QueueAttribute) == 128, "Wrong CellSync2QueueAttribute size");
CHECK_SIZE(CellSync2QueueAttribute, 128);

View File

@ -99,7 +99,7 @@ struct sys_spu_segment
};
};
static_assert(sizeof(sys_spu_segment) == 0x18, "Wrong sys_spu_segment size");
CHECK_SIZE(sys_spu_segment, 0x18);
enum : u32
{

View File

@ -64,20 +64,25 @@ template<typename T, typename = std::enable_if_t<std::is_integral<T>::value>> in
// return 32 bit sizeof() to avoid widening/narrowing conversions with size_t
#define sizeof32(type) sizeof32_t<sizeof(type)>::value
// return 32 bit alignof() to avoid widening/narrowing conversions with size_t
#define alignof32(type) alignof32_t<__alignof(type)>::value
template<std::size_t Size> struct sizeof32_t
{
static_assert(Size <= UINT32_MAX, "sizeof32() error: sizeof() is too big");
static_assert(Size <= UINT32_MAX, "sizeof32() error: size is too big");
static const u32 value = static_cast<u32>(Size);
};
template<std::size_t Align> struct alignof32_t
{
static_assert(Align <= UINT32_MAX, "alignof32() error: alignment is too big");
static const u32 value = static_cast<u32>(Align);
};
template<typename T> using func_def = T; // workaround for MSVC bug: `using X = func_def<void()>;` instead of `using X = void();`
#include "Utilities/BEType.h"
#include "Utilities/StrFmt.h"
#include "Emu/Memory/atomic.h"
template<typename T> struct ID_type;
#define REG_ID_TYPE(t, id) template<> struct ID_type<t> { static const u32 type = id; }
@ -89,3 +94,7 @@ template<typename T> struct ID_type;
#define _PRGNAME_ "RPCS3"
#define _PRGVER_ "0.0.0.5"
#include "Utilities/BEType.h"
#include "Utilities/StrFmt.h"
#include "Emu/Memory/atomic.h"