1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2025-02-25 03:40:37 +00:00

vm::atomic update, be_t update

1) MakeFromLE replaced with make(), MakeFromBE removed. Compiler seems
to be able to optimize it anyway.
2) be_t<> conversion operator temporarily replaced with conversion
through LE because it can't work with all possible numeric conversions
(float<>int for example)
This commit is contained in:
Nekotekina 2014-09-20 03:16:11 +04:00
parent 0baf295c1b
commit 66000240ac
16 changed files with 98 additions and 89 deletions

@ -306,17 +306,12 @@ public:
m_data = se_t<T, sizeof(T2)>::func(value);
}
static be_t MakeFromLE(const T value)
static be_t make(const T value)
{
T data = se_t<T, sizeof(T2)>::func(value);
return (be_t&)data;
}
static be_t MakeFromBE(const T value)
{
return (be_t&)value;
}
//template<typename T1>
operator const T() const
{
@ -335,7 +330,8 @@ public:
template<typename T1>
operator const be_t<T1>() const
{
return _convert<T1, T, ((sizeof(T1) > sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data);
return be_t<T1>::make(ToLE());
//return _convert<T1, T, ((sizeof(T1) > sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data);
}
template<typename T1> be_t& operator += (T1 right) { return *this = T(*this) + right; }
@ -401,17 +397,12 @@ public:
return se_t<const T, sizeof(T2)>::func(m_data);
}
static be_t MakeFromLE(const T value)
static be_t make(const T value)
{
const T data = se_t<const T, sizeof(T2)>::func(value);
return (be_t&)data;
}
static be_t MakeFromBE(const T value)
{
return (be_t&)value;
}
//template<typename T1>
operator const T() const
{
@ -421,21 +412,7 @@ public:
template<typename T1>
operator const be_t<T1>() const
{
if (sizeof(T1) > sizeof(T) || std::is_floating_point<T>::value || std::is_floating_point<T1>::value)
{
T1 res = se_t<T1, sizeof(T1)>::func(ToLE());
return (be_t<T1>&)res;
}
else if (sizeof(T1) < sizeof(T))
{
T1 res = ToBE() >> ((sizeof(T) - sizeof(T1)) * 8);
return (be_t<T1>&)res;
}
else
{
T1 res = ToBE();
return (be_t<T1>&)res;
}
return be_t<T1>::make(ToLE());
}
template<typename T1> be_t operator & (const be_t<T1>& right) const { const T res = ToBE() & right.ToBE(); return (be_t&)res; }
@ -540,12 +517,6 @@ template<typename T, typename T1, T1 value> struct _se<be_t<T>, T1, value> : pub
#define se32(x) _se<u32, decltype(x), x>::value
#define se64(x) _se<u64, decltype(x), x>::value
template<typename T>
__forceinline static const be_t<T> to_be(const T value)
{
return be_t<T>::MakeFromLE(value);
}
template<typename T> __forceinline static u8 Read8(T& f)
{
u8 ret;

@ -45,7 +45,7 @@ void strcpy_trunc(char(&dst)[size], const char(&src)[rsize])
#define INFINITE 0xFFFFFFFF
#define _CRT_ALIGN(x) __attribute__((aligned(x)))
#define InterlockedCompareExchange(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val)
#define InterlockedCompareExchange64(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val)
#define InterlockedExchange(ptr, value) __sync_lock_test_and_set(ptr, value)
inline int64_t InterlockedOr64(volatile int64_t *dest, int64_t val)
{
@ -54,7 +54,7 @@ inline int64_t InterlockedOr64(volatile int64_t *dest, int64_t val)
do
{
olderval = oldval;
oldval = InterlockedCompareExchange64(dest, olderval | val, olderval);
oldval = __sync_val_compare_and_swap(dest, olderval | val, olderval);
} while (olderval != oldval);
return oldval;
}
@ -100,4 +100,15 @@ static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest
{
return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp);
}
#endif
#endif
#ifndef InterlockedExchange
static __forceinline uint32_t InterlockedExchange(volatile uint32_t* dest, uint32_t value)
{
return _InterlockedExchange((volatile long*)dest, value);
}
static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint64_t value)
{
return _InterlockedExchange64((volatile long long*)dest, value);
}
#endif

@ -120,8 +120,8 @@ int Decrypt(rFile& pkg_f, rFile& dec_pkg_f, PKGHeader* m_header)
{
aes_crypt_ecb(&c, AES_ENCRYPT, iv, ctr+j*HASH_LEN);
be_t<u64> hi = be_t<u64>::MakeFromBE(*(u64*)&iv[0]);
be_t<u64> lo = be_t<u64>::MakeFromBE(*(u64*)&iv[8]);
be_t<u64> hi = *(be_t<u64>*)&iv[0];
be_t<u64> lo = *(be_t<u64>*)&iv[8];
lo++;
if (lo == 0)

@ -109,7 +109,7 @@ public:
virtual std::string GetThreadName() const
{
std::string temp = (GetFName() + fmt::Format("[0x%08llx]", PC));
std::string temp = (GetFName() + fmt::Format("[0x%08x]", PC));
return temp;
}

@ -25,16 +25,27 @@ namespace vm
template<typename T>
class _atomic_base
{
T data;
volatile T data;
typedef typename _to_atomic<T, sizeof(T)>::type atomic_type;
public:
T compare_and_swap(T cmp, T exch)
__forceinline const T compare_and_swap(const T cmp, const T exch) volatile
{
const atomic_type res = InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp);
return (T&)res;
}
__forceinline const T exchange(const T value) volatile
{
const atomic_type res = InterlockedExchange((volatile atomic_type*)&data, (atomic_type&)value);
return (T&)res;
}
__forceinline const T read_relaxed() const volatile
{
return (T&)data;
}
};
template<typename T> struct atomic_le : public _atomic_base<T>

@ -228,15 +228,15 @@ enum CellVideoOutRGBOutputRange
static const CellVideoOutResolution ResolutionTable[] =
{
{ be_t<u16>::MakeFromBE(se16(0xffff)), be_t<u16>::MakeFromBE(se16(0xffff)) }, //0 - 0
{ be_t<u16>::MakeFromBE(se16(1920)), be_t<u16>::MakeFromBE(se16(1080)) }, //1 - 1
{ be_t<u16>::MakeFromBE(se16(1280)), be_t<u16>::MakeFromBE(se16(720)) }, //2 - 2
{ be_t<u16>::MakeFromBE(se16(720)), be_t<u16>::MakeFromBE(se16(480)) }, //4 - 3
{ be_t<u16>::MakeFromBE(se16(720)), be_t<u16>::MakeFromBE(se16(576)) }, //5 - 4
{ be_t<u16>::MakeFromBE(se16(1600)), be_t<u16>::MakeFromBE(se16(1080)) }, //10 - 5
{ be_t<u16>::MakeFromBE(se16(1440)), be_t<u16>::MakeFromBE(se16(1080)) }, //11 - 6
{ be_t<u16>::MakeFromBE(se16(1280)), be_t<u16>::MakeFromBE(se16(1080)) }, //12 - 7
{ be_t<u16>::MakeFromBE(se16(960)), be_t<u16>::MakeFromBE(se16(1080)) }, //13 - 8
{ be_t<u16>::make(0xffff), be_t<u16>::make(0xffff) }, //0 - 0
{ be_t<u16>::make(1920), be_t<u16>::make(1080) }, //1 - 1
{ be_t<u16>::make(1280), be_t<u16>::make(720) }, //2 - 2
{ be_t<u16>::make(720), be_t<u16>::make(480) }, //4 - 3
{ be_t<u16>::make(720), be_t<u16>::make(576) }, //5 - 4
{ be_t<u16>::make(1600), be_t<u16>::make(1080) }, //10 - 5
{ be_t<u16>::make(1440), be_t<u16>::make(1080) }, //11 - 6
{ be_t<u16>::make(1280), be_t<u16>::make(1080) }, //12 - 7
{ be_t<u16>::make(960), be_t<u16>::make(1080) }, //13 - 8
};
inline static u32 ResolutionIdToNum(u32 id)

@ -210,7 +210,7 @@ void getSaveDataStat(SaveDataEntry entry, vm::ptr<CellSaveDataStatGet> statGet)
}
}
statGet->fileList = vm::bptr<CellSaveDataFileStat>::make(be_t<u32>::MakeFromLE((u32)Memory.Alloc(sizeof(CellSaveDataFileStat) * (u32)fileEntries.size(), sizeof(CellSaveDataFileStat))));
statGet->fileList = vm::bptr<CellSaveDataFileStat>::make(be_t<u32>::make((u32)Memory.Alloc(sizeof(CellSaveDataFileStat) * (u32)fileEntries.size(), sizeof(CellSaveDataFileStat))));
for (u32 i=0; i<fileEntries.size(); i++)
memcpy(&statGet->fileList[i], &fileEntries[i], sizeof(CellSaveDataFileStat));
}

@ -208,7 +208,7 @@ s64 spursInit(
spurs->m.ppu1 = ppu1->GetId();
// enable exception event handler
if (spurs->m.enableEH.compare_and_swap(be_t<u32>::MakeFromBE(0), be_t<u32>::MakeFromBE(se32(1))).ToBE() != 0)
if (spurs->m.enableEH.compare_and_swap(be_t<u32>::make(0), be_t<u32>::make(1)).ToBE() == 0)
{
assert(sys_spu_thread_group_connect_event(spurs->m.spuTG, spurs->m.queue, SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION) == CELL_OK);
}

@ -16,7 +16,7 @@ u32 libsre;
u32 libsre_rtoc;
#endif
s32 syncMutexInitialize(vm::ptr<CellSyncMutex> mutex)
s32 syncMutexInitialize(vm::ptr<vm::atomic<CellSyncMutex>> mutex)
{
if (!mutex)
{
@ -28,12 +28,11 @@ s32 syncMutexInitialize(vm::ptr<CellSyncMutex> mutex)
}
// prx: set zero and sync
mutex->m_data() = 0;
InterlockedCompareExchange(&mutex->m_data(), 0, 0);
mutex->exchange({});
return CELL_OK;
}
s32 cellSyncMutexInitialize(vm::ptr<CellSyncMutex> mutex)
s32 cellSyncMutexInitialize(vm::ptr<vm::atomic<CellSyncMutex>> mutex)
{
cellSync->Log("cellSyncMutexInitialize(mutex_addr=0x%x)", mutex.addr());

@ -155,7 +155,7 @@ struct CellSyncLFQueue
static_assert(sizeof(CellSyncLFQueue) == 128, "CellSyncLFQueue: wrong size");
s32 syncMutexInitialize(vm::ptr<CellSyncMutex> mutex);
s32 syncMutexInitialize(vm::ptr<vm::atomic<CellSyncMutex>> mutex);
s32 syncBarrierInitialize(vm::ptr<CellSyncBarrier> barrier, u16 total_count);

@ -13,7 +13,7 @@ s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64)
{
u32 id = sys_lwcond.GetNewId(new Lwcond(name_u64), TYPE_LWCOND);
u32 addr = Memory.RealToVirtualAddr(&lwmutex);
lwcond.lwmutex.set(be_t<u32>::MakeFromLE(addr));
lwcond.lwmutex.set(be_t<u32>::make(addr));
lwcond.lwcond_queue = id;
std::string name((const char*)&name_u64, 8);
@ -154,7 +154,7 @@ s32 sys_lwcond_wait(vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
auto mutex = vm::ptr<sys_lwmutex_t>::make(lwcond->lwmutex.addr());
u32 tid_le = GetCurrentPPUThread().GetId();
be_t<u32> tid = be_t<u32>::MakeFromLE(tid_le);
be_t<u32> tid = be_t<u32>::make(tid_le);
SleepQueue* sq = nullptr;
Emu.GetIdManager().GetIDData((u32)mutex->sleep_queue, sq);
@ -176,7 +176,7 @@ s32 sys_lwcond_wait(vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
if (sq)
{
mutex->mutex.unlock(tid, be_t<u32>::MakeFromLE(mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop()));
mutex->mutex.unlock(tid, be_t<u32>::make(mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop()));
}
else if (mutex->attribute.ToBE() == se32(SYS_SYNC_RETRY))
{

@ -79,14 +79,14 @@ s32 sys_lwmutex_lock(vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout)
//ConLog.Write("*** lock mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)",
//lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter);
return lwmutex->lock(be_t<u32>::MakeFromLE(GetCurrentPPUThread().GetId()), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0);
return lwmutex->lock(be_t<u32>::make(GetCurrentPPUThread().GetId()), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0);
}
s32 sys_lwmutex_trylock(vm::ptr<sys_lwmutex_t> lwmutex)
{
sys_lwmutex.Log("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.addr());
return lwmutex->trylock(be_t<u32>::MakeFromLE(GetCurrentPPUThread().GetId()));
return lwmutex->trylock(be_t<u32>::make(GetCurrentPPUThread().GetId()));
}
s32 sys_lwmutex_unlock(vm::ptr<sys_lwmutex_t> lwmutex)
@ -96,7 +96,7 @@ s32 sys_lwmutex_unlock(vm::ptr<sys_lwmutex_t> lwmutex)
//ConLog.Write("*** unlocking mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)",
//lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, (u32)lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter);
return lwmutex->unlock(be_t<u32>::MakeFromLE(GetCurrentPPUThread().GetId()));
return lwmutex->unlock(be_t<u32>::make(GetCurrentPPUThread().GetId()));
}
void SleepQueue::push(u32 tid)
@ -292,7 +292,7 @@ int sys_lwmutex_t::unlock(be_t<u32> tid)
recursive_count -= 1;
if (!recursive_count.ToBE())
{
be_t<u32> target = be_t<u32>::MakeFromBE(se32(0));
be_t<u32> target = be_t<u32>::make(0);
switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
{
case se32(SYS_SYNC_FIFO):

@ -214,8 +214,8 @@ void sys_ppu_thread_once(PPUThread& CPU, vm::ptr<vm::atomic<u32>> once_ctrl, vm:
{
sys_ppu_thread.Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, init_addr=0x%x)", once_ctrl.addr(), init.addr());
auto cmp = to_be<u32>(SYS_PPU_THREAD_ONCE_INIT);
if (once_ctrl->compare_and_swap(cmp, to_be<u32>(SYS_PPU_THREAD_DONE_INIT)) == cmp)
be_t<u32> cmp = be_t<u32>::make(SYS_PPU_THREAD_ONCE_INIT);
if (once_ctrl->compare_and_swap(cmp, be_t<u32>::make(SYS_PPU_THREAD_DONE_INIT)) == cmp)
{
init.call(CPU);
}

@ -7,22 +7,22 @@
SysCallBase sys_spinlock("sys_spinlock");
void sys_spinlock_initialize(vm::ptr<std::atomic<be_t<u32>>> lock)
void sys_spinlock_initialize(vm::ptr<vm::atomic<u32>> lock)
{
sys_spinlock.Log("sys_spinlock_initialize(lock_addr=0x%x)", lock.addr());
// prx: set 0 and sync
*lock = be_t<u32>::MakeFromBE(0);
lock->exchange(be_t<u32>::make(0));
}
void sys_spinlock_lock(vm::ptr<std::atomic<be_t<u32>>> lock)
void sys_spinlock_lock(vm::ptr<vm::atomic<u32>> lock)
{
sys_spinlock.Log("sys_spinlock_lock(lock_addr=0x%x)", lock.addr());
// prx: exchange with 0xabadcafe, repeat until exchanged with 0
while (lock->exchange(be_t<u32>::MakeFromBE(se32(0xabadcafe))).ToBE())
while (lock->exchange(be_t<u32>::make(0xabadcafe)).ToBE())
{
while (lock->load(std::memory_order_relaxed).ToBE())
while (lock->read_relaxed().ToBE())
{
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
if (Emu.IsStopped())
@ -39,12 +39,12 @@ void sys_spinlock_lock(vm::ptr<std::atomic<be_t<u32>>> lock)
}
}
s32 sys_spinlock_trylock(vm::ptr<std::atomic<be_t<u32>>> lock)
s32 sys_spinlock_trylock(vm::ptr<vm::atomic<u32>> lock)
{
sys_spinlock.Log("sys_spinlock_trylock(lock_addr=0x%x)", lock.addr());
// prx: exchange with 0xabadcafe, translate exchanged value
if (lock->exchange(be_t<u32>::MakeFromBE(se32(0xabadcafe))).ToBE())
if (lock->exchange(be_t<u32>::make(0xabadcafe)).ToBE())
{
return CELL_EBUSY;
}
@ -52,10 +52,10 @@ s32 sys_spinlock_trylock(vm::ptr<std::atomic<be_t<u32>>> lock)
return CELL_OK;
}
void sys_spinlock_unlock(vm::ptr<std::atomic<be_t<u32>>> lock)
void sys_spinlock_unlock(vm::ptr<vm::atomic<u32>> lock)
{
sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.addr());
// prx: sync and set 0
*lock = be_t<u32>::MakeFromBE(0);
lock->exchange(be_t<u32>::make(0));
}

@ -1,7 +1,7 @@
#pragma once
// SysCalls
void sys_spinlock_initialize(vm::ptr<std::atomic<be_t<u32>>> lock);
void sys_spinlock_lock(vm::ptr<std::atomic<be_t<u32>>> lock);
s32 sys_spinlock_trylock(vm::ptr<std::atomic<be_t<u32>>> lock);
void sys_spinlock_unlock(vm::ptr<std::atomic<be_t<u32>>> lock);
void sys_spinlock_initialize(vm::ptr<vm::atomic<u32>> lock);
void sys_spinlock_lock(vm::ptr<vm::atomic<u32>> lock);
s32 sys_spinlock_trylock(vm::ptr<vm::atomic<u32>> lock);
void sys_spinlock_unlock(vm::ptr<vm::atomic<u32>> lock);

@ -144,11 +144,20 @@ bool TROPUSRLoader::Generate(const std::string& filepath, const std::string& con
default: trophy_grade = 0;
}
TROPUSREntry4 entry4 = { be_t<u32>::MakeFromBE(se32(4)), be_t<u32>::MakeFromBE(se32(sizeof(TROPUSREntry4) - 0x10)),
be_t<u32>::MakeFromLE((u32)m_table4.size()), be_t<u32>::MakeFromBE(se32(0)), be_t<u32>::MakeFromLE(trophy_id),
be_t<u32>::MakeFromLE(trophy_grade), be_t<u32>::MakeFromBE(se32(0xFFFFFFFF)) };
TROPUSREntry6 entry6 = { be_t<u32>::MakeFromBE(se32(6)), be_t<u32>::MakeFromBE(se32(sizeof(TROPUSREntry6) - 0x10)),
be_t<u32>::MakeFromLE((u32)m_table6.size()), be_t<u32>::MakeFromBE(0), be_t<u32>::MakeFromLE(trophy_id) };
TROPUSREntry4 entry4 = {
be_t<u32>::make(4),
be_t<u32>::make(sizeof(TROPUSREntry4) - 0x10),
be_t<u32>::make((u32)m_table4.size()),
be_t<u32>::make(0),
be_t<u32>::make(trophy_id),
be_t<u32>::make(trophy_grade),
be_t<u32>::make(0xFFFFFFFF) };
TROPUSREntry6 entry6 = {
be_t<u32>::make(6),
be_t<u32>::make(sizeof(TROPUSREntry6) - 0x10),
be_t<u32>::make((u32)m_table6.size()),
be_t<u32>::make(0),
be_t<u32>::make(trophy_id) };
m_table4.push_back(entry4);
m_table6.push_back(entry6);
@ -156,11 +165,19 @@ bool TROPUSRLoader::Generate(const std::string& filepath, const std::string& con
}
u64 offset = sizeof(TROPUSRHeader) + 2 * sizeof(TROPUSRTableHeader);
TROPUSRTableHeader table4header = { be_t<u32>::MakeFromBE(se32(4)), be_t<u32>::MakeFromBE(se32(sizeof(TROPUSREntry4)-0x10)),
be_t<u32>::MakeFromBE(se32(1)), be_t<u32>::MakeFromLE((u32)m_table4.size()), be_t<u64>::MakeFromLE(offset) };
TROPUSRTableHeader table4header = {
be_t<u32>::make(4),
be_t<u32>::make(sizeof(TROPUSREntry4) - 0x10),
be_t<u32>::make(1),
be_t<u32>::make((u32)m_table4.size()),
be_t<u64>::make(offset) };
offset += m_table4.size() * sizeof(TROPUSREntry4);
TROPUSRTableHeader table6header = { be_t<u32>::MakeFromBE(se32(6)), be_t<u32>::MakeFromBE(se32(sizeof(TROPUSREntry6)-0x10)),
be_t<u32>::MakeFromBE(se32(1)), be_t<u32>::MakeFromLE((u32)m_table6.size()), be_t<u64>::MakeFromLE(offset) };
TROPUSRTableHeader table6header = {
be_t<u32>::make(6),
be_t<u32>::make(sizeof(TROPUSREntry6) - 0x10),
be_t<u32>::make(1),
be_t<u32>::make((u32)m_table6.size()),
be_t<u64>::make(offset) };
offset += m_table6.size() * sizeof(TROPUSREntry6);
m_tableHeaders.clear();