rpcsx/rpcs3/Emu/Cell/Modules/cellSync.h

361 lines
6.2 KiB
C
Raw Normal View History

2014-07-20 19:14:04 +02:00
#pragma once
#include "Utilities/BitField.h"
2014-07-20 19:14:04 +02:00
// Return Codes
2016-08-15 18:18:05 +02:00
enum CellSyncError : u32
2014-07-20 19:14:04 +02:00
{
2016-08-15 18:18:05 +02:00
CELL_SYNC_ERROR_AGAIN = 0x80410101,
CELL_SYNC_ERROR_INVAL = 0x80410102,
CELL_SYNC_ERROR_NOSYS = 0x80410103,
CELL_SYNC_ERROR_NOMEM = 0x80410104,
CELL_SYNC_ERROR_SRCH = 0x80410105,
CELL_SYNC_ERROR_NOENT = 0x80410106,
CELL_SYNC_ERROR_NOEXEC = 0x80410107,
CELL_SYNC_ERROR_DEADLK = 0x80410108,
CELL_SYNC_ERROR_PERM = 0x80410109,
CELL_SYNC_ERROR_BUSY = 0x8041010A,
CELL_SYNC_ERROR_ABORT = 0x8041010C,
CELL_SYNC_ERROR_FAULT = 0x8041010D,
CELL_SYNC_ERROR_CHILD = 0x8041010E,
CELL_SYNC_ERROR_STAT = 0x8041010F,
CELL_SYNC_ERROR_ALIGN = 0x80410110,
CELL_SYNC_ERROR_NULL_POINTER = 0x80410111,
CELL_SYNC_ERROR_NOT_SUPPORTED_THREAD = 0x80410112,
CELL_SYNC_ERROR_NO_NOTIFIER = 0x80410113,
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114,
2014-07-20 19:14:04 +02:00
};
2016-08-15 18:18:05 +02:00
enum CellSyncError1 : u32
2016-03-21 20:43:03 +01:00
{
2016-08-15 18:18:05 +02:00
CELL_SYNC_ERROR_SHOTAGE = 0x80410112,
CELL_SYNC_ERROR_UNKNOWNKEY = 0x80410113,
2016-03-21 20:43:03 +01:00
};
2016-08-17 18:50:20 +02:00
struct CellSyncMutex
2014-07-20 19:14:04 +02:00
{
struct alignas(4) Counter
{
be_t<u16> rel;
be_t<u16> acq;
2016-08-17 18:50:20 +02:00
auto lock_begin()
{
return acq++;
}
2016-08-17 18:50:20 +02:00
bool try_lock()
2016-08-17 18:50:20 +02:00
{
if (UNLIKELY(rel != acq))
{
return false;
}
acq++;
return true;
2016-08-17 18:50:20 +02:00
}
void unlock()
{
rel++;
}
};
2016-08-17 18:50:20 +02:00
atomic_t<Counter> ctrl;
};
CHECK_SIZE_ALIGN(CellSyncMutex, 4, 4);
2014-09-20 23:00:55 +02:00
2016-08-17 18:50:20 +02:00
struct CellSyncBarrier
{
2016-08-17 18:50:20 +02:00
struct alignas(4) ctrl_t
{
be_t<s16> value;
be_t<u16> count;
2016-08-17 18:50:20 +02:00
};
atomic_t<ctrl_t> ctrl;
2016-08-17 18:50:20 +02:00
static inline bool try_notify(ctrl_t& ctrl)
{
if (ctrl.value & 0x8000)
{
2016-08-17 18:50:20 +02:00
return false;
}
2016-08-17 18:50:20 +02:00
if (++ctrl.value == ctrl.count)
{
ctrl.value |= 0x8000;
}
2016-08-17 18:50:20 +02:00
return true;
}
2016-08-17 18:50:20 +02:00
static inline bool try_wait(ctrl_t& ctrl)
{
if ((ctrl.value & 0x8000) == 0)
{
2016-08-17 18:50:20 +02:00
return false;
}
2016-08-17 18:50:20 +02:00
if (--ctrl.value == -0x8000)
{
ctrl.value = 0;
}
2014-07-20 19:14:04 +02:00
2016-08-17 18:50:20 +02:00
return true;
}
};
CHECK_SIZE_ALIGN(CellSyncBarrier, 4, 4);
2016-08-17 18:50:20 +02:00
struct alignas(16) CellSyncRwm
{
2016-08-17 18:50:20 +02:00
struct alignas(4) ctrl_t
{
be_t<u16> readers;
be_t<u16> writers;
2016-08-17 18:50:20 +02:00
};
2016-08-17 18:50:20 +02:00
atomic_t<ctrl_t> ctrl;
2016-08-17 18:50:20 +02:00
be_t<u32> size;
vm::bptr<void, u64> buffer;
2016-08-17 18:50:20 +02:00
static inline bool try_read_begin(ctrl_t& ctrl)
{
if (ctrl.writers)
{
2016-08-17 18:50:20 +02:00
return false;
}
2016-08-17 18:50:20 +02:00
ctrl.readers++;
return true;
}
2016-08-17 18:50:20 +02:00
static inline bool try_read_end(ctrl_t& ctrl)
{
if (ctrl.readers == 0)
{
return false;
}
2016-08-17 18:50:20 +02:00
ctrl.readers--;
return true;
}
2016-08-17 18:50:20 +02:00
static inline bool try_write_begin(ctrl_t& ctrl)
{
if (ctrl.writers)
{
return false;
}
ctrl.writers = 1;
return true;
}
};
CHECK_SIZE_ALIGN(CellSyncRwm, 16, 16);
2014-07-22 21:02:45 +02:00
2016-08-17 18:50:20 +02:00
struct alignas(32) CellSyncQueue
2014-07-22 21:02:45 +02:00
{
2016-08-17 18:50:20 +02:00
struct alignas(8) ctrl_t
{
union
{
be_t<u32> x0;
2016-03-21 20:43:03 +01:00
bf_t<be_t<u32>, 0, 24> next;
bf_t<be_t<u32>, 24, 8> _pop;
};
union
{
be_t<u32> x4;
2016-03-21 20:43:03 +01:00
bf_t<be_t<u32>, 0, 24> count;
bf_t<be_t<u32>, 24, 8> _push;
};
2016-08-17 18:50:20 +02:00
};
atomic_t<ctrl_t> ctrl;
be_t<u32> size;
be_t<u32> depth;
vm::bptr<u8, u64> buffer;
be_t<u64> reserved;
u32 check_depth() const
{
const auto data = ctrl.load();
2016-08-17 18:50:20 +02:00
if (data.next > depth || data.count > depth)
{
2016-08-17 18:50:20 +02:00
fmt::throw_exception("Invalid queue pointers" HERE);
}
2016-08-17 18:50:20 +02:00
return depth;
}
2016-08-17 18:50:20 +02:00
static inline bool try_push_begin(ctrl_t& ctrl, u32 depth, u32* position)
{
const u32 count = ctrl.count;
2016-08-17 18:50:20 +02:00
if (ctrl._push || count + ctrl._pop >= depth)
{
return false;
}
2015-06-26 16:45:13 +02:00
2016-08-17 18:50:20 +02:00
*position = ctrl.next;
ctrl.next = *position + 1 != depth ? *position + 1 : 0;
ctrl.count = count + 1;
ctrl._push = 1;
return true;
}
2015-06-26 16:45:13 +02:00
2016-08-17 18:50:20 +02:00
static inline void push_end(ctrl_t& ctrl)
{
ctrl._push = 0;
}
2015-06-26 16:45:13 +02:00
2016-08-17 18:50:20 +02:00
static inline bool try_pop_begin(ctrl_t& ctrl, u32 depth, u32* position)
{
const u32 count = ctrl.count;
2015-06-26 16:45:13 +02:00
2016-08-17 18:50:20 +02:00
if (ctrl._pop || count <= ctrl._push)
2015-06-26 16:45:13 +02:00
{
2016-08-17 18:50:20 +02:00
return false;
2015-06-26 16:45:13 +02:00
}
2016-08-17 18:50:20 +02:00
ctrl._pop = 1;
*position = ctrl.next + depth - count;
ctrl.count = count - 1;
return true;
}
2015-06-26 16:45:13 +02:00
2016-08-17 18:50:20 +02:00
static inline bool try_peek_begin(ctrl_t& ctrl, u32 depth, u32* position)
{
const u32 count = ctrl.count;
if (ctrl._pop || count <= ctrl._push)
{
return false;
}
2016-08-17 18:50:20 +02:00
ctrl._pop = 1;
*position = ctrl.next + depth - count;
return true;
}
2016-08-17 18:50:20 +02:00
static inline void pop_end(ctrl_t& ctrl)
{
ctrl._pop = 0;
}
2016-08-17 18:50:20 +02:00
static inline bool try_clear_begin_1(ctrl_t& ctrl)
{
2016-08-17 18:50:20 +02:00
if (ctrl._pop)
{
return false;
}
2016-08-17 18:50:20 +02:00
ctrl._pop = 1;
return true;
}
static inline bool try_clear_begin_2(ctrl_t& ctrl)
{
if (ctrl._push)
{
2016-08-17 18:50:20 +02:00
return false;
}
2016-08-17 18:50:20 +02:00
ctrl._push = 1;
return true;
}
2014-07-22 21:02:45 +02:00
};
CHECK_SIZE_ALIGN(CellSyncQueue, 32, 32);
2014-08-09 18:23:53 +02:00
2014-08-11 20:35:34 +02:00
enum CellSyncQueueDirection : u32 // CellSyncLFQueueDirection
2014-08-09 18:23:53 +02:00
{
CELL_SYNC_QUEUE_SPU2SPU = 0, // SPU to SPU
CELL_SYNC_QUEUE_SPU2PPU = 1, // SPU to PPU
CELL_SYNC_QUEUE_PPU2SPU = 2, // PPU to SPU
CELL_SYNC_QUEUE_ANY2ANY = 3, // SPU/PPU to SPU/PPU
};
struct alignas(128) CellSyncLFQueue
2014-08-09 18:23:53 +02:00
{
2016-03-21 20:43:03 +01:00
struct alignas(8) pop1_t
2014-09-21 15:02:05 +02:00
{
be_t<u16> m_h1;
be_t<u16> m_h2;
be_t<u16> m_h3;
be_t<u16> m_h4;
};
2014-09-23 16:27:18 +02:00
struct pop2_t
{
be_t<u16> pack;
};
2016-03-21 20:43:03 +01:00
struct alignas(4) pop3_t
2014-09-23 01:07:40 +02:00
{
be_t<u16> m_h1;
be_t<u16> m_h2;
};
2016-03-21 20:43:03 +01:00
struct alignas(8) push1_t
2014-09-21 15:02:05 +02:00
{
be_t<u16> m_h5;
be_t<u16> m_h6;
be_t<u16> m_h7;
be_t<u16> m_h8;
};
2014-09-23 16:27:18 +02:00
struct push2_t
{
be_t<u16> pack;
};
2016-03-21 20:43:03 +01:00
struct alignas(4) push3_t
2014-09-21 15:02:05 +02:00
{
2014-09-23 01:07:40 +02:00
be_t<u16> m_h5;
be_t<u16> m_h6;
2014-09-21 15:02:05 +02:00
};
2015-02-19 14:47:53 +01:00
union // 0x0
2014-09-23 01:07:40 +02:00
{
atomic_t<pop1_t> pop1;
atomic_t<pop3_t> pop3;
2014-09-23 01:07:40 +02:00
};
2015-02-19 14:47:53 +01:00
union // 0x8
2014-09-23 01:07:40 +02:00
{
atomic_t<push1_t> push1;
atomic_t<push3_t> push3;
2014-09-23 01:07:40 +02:00
};
2015-02-19 14:47:53 +01:00
2014-09-23 16:27:18 +02:00
be_t<u32> m_size; // 0x10
be_t<u32> m_depth; // 0x14
vm::bcptr<void, u64> m_buffer; // 0x18
2014-09-23 16:27:18 +02:00
u8 m_bs[4]; // 0x20
be_t<u32> m_direction; // 0x24 CellSyncQueueDirection
2014-09-23 16:27:18 +02:00
be_t<u32> m_v1; // 0x28
2015-06-26 16:45:13 +02:00
atomic_be_t<s32> init; // 0x2C
atomic_t<push2_t> push2; // 0x30
2014-09-23 16:27:18 +02:00
be_t<u16> m_hs1[15]; // 0x32
atomic_t<pop2_t> pop2; // 0x50
2014-09-23 16:27:18 +02:00
be_t<u16> m_hs2[15]; // 0x52
vm::bptr<void, u64> m_eaSignal; // 0x70
2014-09-23 16:27:18 +02:00
be_t<u32> m_v2; // 0x78
be_t<u32> m_eq_id; // 0x7C
2014-08-09 18:23:53 +02:00
};
CHECK_SIZE_ALIGN(CellSyncLFQueue, 128, 128);
// Prototypes
error_code cellSyncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::cptr<void> buffer, u32 size, u32 depth, u32 direction, vm::ptr<void> eaSignal);