diff --git a/rpcs3/util/atomic.hpp b/rpcs3/util/atomic.hpp index 18b80007dc..a79c1acbbc 100644 --- a/rpcs3/util/atomic.hpp +++ b/rpcs3/util/atomic.hpp @@ -235,58 +235,58 @@ struct atomic_storage : atomic_storage #ifdef _MSC_VER static inline bool compare_exchange(T& dest, T& comp, T exch) { - char v = *(char*)∁ - char r = _InterlockedCompareExchange8((volatile char*)&dest, (char&)exch, v); - comp = (T&)r; + const char v = std::bit_cast(comp); + const char r = _InterlockedCompareExchange8(reinterpret_cast(&dest), std::bit_cast(exch), v); + comp = std::bit_cast(r); return r == v; } static inline T load(const T& dest) { - char value = *(const volatile char*)&dest; + const char value = *reinterpret_cast(&dest); std::atomic_thread_fence(std::memory_order_acquire); - return (T&)value; - } - - static inline void store(T& dest, T value) - { - _InterlockedExchange8((volatile char*)&dest, (char&)value); + return std::bit_cast(value); } static inline void release(T& dest, T value) { std::atomic_thread_fence(std::memory_order_release); - *(volatile char*)&dest = (char&)value; + *reinterpret_cast(&dest) = std::bit_cast(value); } static inline T exchange(T& dest, T value) { - char r = _InterlockedExchange8((volatile char*)&dest, (char&)value); - return (T&)r; + const char r = _InterlockedExchange8(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); + } + + static inline void store(T& dest, T value) + { + exchange(dest, value); } static inline T fetch_add(T& dest, T value) { - char r = _InterlockedExchangeAdd8((volatile char*)&dest, (char&)value); - return (T&)r; + const char r = _InterlockedExchangeAdd8(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_and(T& dest, T value) { - char r = _InterlockedAnd8((volatile char*)&dest, (char&)value); - return (T&)r; + const char r = _InterlockedAnd8(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_or(T& dest, T value) { - char r = _InterlockedOr8((volatile char*)&dest, (char&)value); - return (T&)r; + const char r = _InterlockedOr8(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_xor(T& dest, T value) { - char r = _InterlockedXor8((volatile char*)&dest, (char&)value); - return (T&)r; + const char r = _InterlockedXor8(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } #endif }; @@ -297,70 +297,70 @@ struct atomic_storage : atomic_storage #ifdef _MSC_VER static inline bool compare_exchange(T& dest, T& comp, T exch) { - short v = *(short*)∁ - short r = _InterlockedCompareExchange16((volatile short*)&dest, (short&)exch, v); - comp = (T&)r; + const short v = std::bit_cast(comp); + const short r = _InterlockedCompareExchange16(reinterpret_cast(&dest), std::bit_cast(exch), v); + comp = std::bit_cast(r); return r == v; } static inline T load(const T& dest) { - short value = *(const volatile short*)&dest; + const short value = *reinterpret_cast(&dest); std::atomic_thread_fence(std::memory_order_acquire); - return (T&)value; - } - - static inline void store(T& dest, T value) - { - _InterlockedExchange16((volatile short*)&dest, (short&)value); + return std::bit_cast(value); } static inline void release(T& dest, T value) { std::atomic_thread_fence(std::memory_order_release); - *(volatile short*)&dest = (short&)value; + *reinterpret_cast(&dest) = std::bit_cast(value); } static inline T exchange(T& dest, T value) { - short r = _InterlockedExchange16((volatile short*)&dest, (short&)value); - return (T&)r; + const short r = _InterlockedExchange16(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); + } + + static inline void store(T& dest, T value) + { + exchange(dest, value); } static inline T fetch_add(T& dest, T value) { - short r = _InterlockedExchangeAdd16((volatile short*)&dest, (short&)value); - return (T&)r; + const short r = _InterlockedExchangeAdd16(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_and(T& dest, T value) { - short r = _InterlockedAnd16((volatile short*)&dest, (short&)value); - return (T&)r; + const short r = _InterlockedAnd16(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_or(T& dest, T value) { - short r = _InterlockedOr16((volatile short*)&dest, (short&)value); - return (T&)r; + const short r = _InterlockedOr16(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_xor(T& dest, T value) { - short r = _InterlockedXor16((volatile short*)&dest, (short&)value); - return (T&)r; + const short r = _InterlockedXor16(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T inc_fetch(T& dest) { - short r = _InterlockedIncrement16((volatile short*)&dest); - return (T&)r; + const short r = _InterlockedIncrement16(reinterpret_cast(&dest)); + return std::bit_cast(r); } static inline T dec_fetch(T& dest) { - short r = _InterlockedDecrement16((volatile short*)&dest); - return (T&)r; + const short r = _InterlockedDecrement16(reinterpret_cast(&dest)); + return std::bit_cast(r); } #else static inline bool bts(T& dest, uint bit) @@ -395,94 +395,94 @@ struct atomic_storage : atomic_storage #ifdef _MSC_VER static inline bool compare_exchange(T& dest, T& comp, T exch) { - long v = *(long*)∁ - long r = _InterlockedCompareExchange((volatile long*)&dest, (long&)exch, v); - comp = (T&)r; + const long v = std::bit_cast(comp); + const long r = _InterlockedCompareExchange(reinterpret_cast(&dest), std::bit_cast(exch), v); + comp = std::bit_cast(r); return r == v; } static inline bool compare_exchange_hle_acq(T& dest, T& comp, T exch) { - long v = *(long*)∁ - long r = _InterlockedCompareExchange_HLEAcquire((volatile long*)&dest, (long&)exch, v); - comp = (T&)r; + const long v = std::bit_cast(comp); + const long r = _InterlockedCompareExchange_HLEAcquire(reinterpret_cast(&dest), std::bit_cast(exch), v); + comp = std::bit_cast(r); return r == v; } static inline T load(const T& dest) { - long value = *(const volatile long*)&dest; + const long value = *reinterpret_cast(&dest); std::atomic_thread_fence(std::memory_order_acquire); - return (T&)value; - } - - static inline void store(T& dest, T value) - { - _InterlockedExchange((volatile long*)&dest, (long&)value); + return std::bit_cast(value); } static inline void release(T& dest, T value) { std::atomic_thread_fence(std::memory_order_release); - *(volatile long*)&dest = (long&)value; + *reinterpret_cast(&dest) = std::bit_cast(value); } static inline T exchange(T& dest, T value) { - long r = _InterlockedExchange((volatile long*)&dest, (long&)value); - return (T&)r; + const long r = _InterlockedExchange(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); + } + + static inline void store(T& dest, T value) + { + exchange(dest, value); } static inline T fetch_add(T& dest, T value) { - long r = _InterlockedExchangeAdd((volatile long*)&dest, (long&)value); - return (T&)r; + const long r = _InterlockedExchangeAdd(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_add_hle_rel(T& dest, T value) { - long r = _InterlockedExchangeAdd_HLERelease((volatile long*)&dest, (long&)value); - return (T&)r; + const long r = _InterlockedExchangeAdd_HLERelease(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_and(T& dest, T value) { - long r = _InterlockedAnd((volatile long*)&dest, (long&)value); - return (T&)r; + long r = _InterlockedAnd(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_or(T& dest, T value) { - long r = _InterlockedOr((volatile long*)&dest, (long&)value); - return (T&)r; + const long r = _InterlockedOr(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_xor(T& dest, T value) { - long r = _InterlockedXor((volatile long*)&dest, (long&)value); - return (T&)r; + const long r = _InterlockedXor(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T inc_fetch(T& dest) { - long r = _InterlockedIncrement((volatile long*)&dest); - return (T&)r; + const long r = _InterlockedIncrement(reinterpret_cast(&dest)); + return std::bit_cast(r); } static inline T dec_fetch(T& dest) { - long r = _InterlockedDecrement((volatile long*)&dest); - return (T&)r; + const long r = _InterlockedDecrement(reinterpret_cast(&dest)); + return std::bit_cast(r); } static inline bool bts(T& dest, uint bit) { - return _interlockedbittestandset((volatile long*)&dest, bit) != 0; + return _interlockedbittestandset(reinterpret_cast(&dest), bit) != 0; } static inline bool btr(T& dest, uint bit) { - return _interlockedbittestandreset((volatile long*)&dest, bit) != 0; + return _interlockedbittestandreset(reinterpret_cast(&dest), bit) != 0; } #else static inline bool bts(T& dest, uint bit) @@ -514,94 +514,94 @@ struct atomic_storage : atomic_storage #ifdef _MSC_VER static inline bool compare_exchange(T& dest, T& comp, T exch) { - llong v = *(llong*)∁ - llong r = _InterlockedCompareExchange64((volatile llong*)&dest, (llong&)exch, v); - comp = (T&)r; + const llong v = std::bit_cast(comp); + const llong r = _InterlockedCompareExchange64(reinterpret_cast(&dest), std::bit_cast(exch), v); + comp = std::bit_cast(r); return r == v; } static inline bool compare_exchange_hle_acq(T& dest, T& comp, T exch) { - llong v = *(llong*)∁ - llong r = _InterlockedCompareExchange64_HLEAcquire((volatile llong*)&dest, (llong&)exch, v); - comp = (T&)r; + const llong v = std::bit_cast(comp); + const llong r = _InterlockedCompareExchange64_HLEAcquire(reinterpret_cast(&dest), std::bit_cast(exch), v); + comp = std::bit_cast(r); return r == v; } static inline T load(const T& dest) { - llong value = *(const volatile llong*)&dest; + const llong value = *reinterpret_cast(&dest); std::atomic_thread_fence(std::memory_order_acquire); - return (T&)value; - } - - static inline void store(T& dest, T value) - { - _InterlockedExchange64((volatile llong*)&dest, (llong&)value); + return std::bit_cast(value); } static inline void release(T& dest, T value) { std::atomic_thread_fence(std::memory_order_release); - *(volatile llong*)&dest = (llong&)value; + *reinterpret_cast(&dest) = std::bit_cast(value); } static inline T exchange(T& dest, T value) { - llong r = _InterlockedExchange64((volatile llong*)&dest, (llong&)value); - return (T&)r; + const llong r = _InterlockedExchange64(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); + } + + static inline void store(T& dest, T value) + { + exchange(dest, value); } static inline T fetch_add(T& dest, T value) { - llong r = _InterlockedExchangeAdd64((volatile llong*)&dest, (llong&)value); - return (T&)r; + const llong r = _InterlockedExchangeAdd64(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_add_hle_rel(T& dest, T value) { - llong r = _InterlockedExchangeAdd64_HLERelease((volatile llong*)&dest, (llong&)value); - return (T&)r; + const llong r = _InterlockedExchangeAdd64_HLERelease(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_and(T& dest, T value) { - llong r = _InterlockedAnd64((volatile llong*)&dest, (llong&)value); - return (T&)r; + const llong r = _InterlockedAnd64(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_or(T& dest, T value) { - llong r = _InterlockedOr64((volatile llong*)&dest, (llong&)value); - return (T&)r; + const llong r = _InterlockedOr64(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T fetch_xor(T& dest, T value) { - llong r = _InterlockedXor64((volatile llong*)&dest, (llong&)value); - return (T&)r; + const llong r = _InterlockedXor64(reinterpret_cast(&dest), std::bit_cast(value)); + return std::bit_cast(r); } static inline T inc_fetch(T& dest) { - llong r = _InterlockedIncrement64((volatile llong*)&dest); - return (T&)r; + const llong r = _InterlockedIncrement64(reinterpret_cast(&dest)); + return std::bit_cast(r); } static inline T dec_fetch(T& dest) { - llong r = _InterlockedDecrement64((volatile llong*)&dest); - return (T&)r; + const llong r = _InterlockedDecrement64(reinterpret_cast(&dest)); + return std::bit_cast(r); } static inline bool bts(T& dest, uint bit) { - return _interlockedbittestandset64((volatile llong*)&dest, bit) != 0; + return _interlockedbittestandset64(reinterpret_cast(&dest), bit) != 0; } static inline bool btr(T& dest, uint bit) { - return _interlockedbittestandreset64((volatile llong*)&dest, bit) != 0; + return _interlockedbittestandreset64(reinterpret_cast(&dest), bit) != 0; } #else static inline bool bts(T& dest, uint bit) @@ -636,40 +636,37 @@ struct atomic_storage : atomic_storage #ifdef _MSC_VER static inline bool compare_exchange(T& dest, T& comp, T exch) { - llong* _exch = (llong*)&exch; - return _InterlockedCompareExchange128((volatile llong*)&dest, _exch[1], _exch[0], (llong*)&comp) != 0; + struct alignas(16) llong2 { llong ll[2]; }; + const llong2 _exch = std::bit_cast(comp); + return _InterlockedCompareExchange128(reinterpret_cast(&dest), _exch.ll[1], _exch.ll[0], reinterpret_cast(&comp)) != 0; } static inline T load(const T& dest) { - llong result[2]{0, 0}; - _InterlockedCompareExchange128((volatile llong*)&dest, 0, 0, result); - return *(T*)+result; - } - - static inline void store(T& dest, T value) - { - llong lo = *(llong*)&value; - llong hi = *((llong*)&value + 1); - llong cmp[2]{ *(volatile llong*)&dest, *((volatile llong*)&dest + 1) }; - while (!_InterlockedCompareExchange128((volatile llong*)&dest, hi, lo, cmp)); - } - - static inline void release(T& dest, T value) - { - llong lo = *(llong*)&value; - llong hi = *((llong*)&value + 1); - llong cmp[2]{ *(volatile llong*)&dest, *((volatile llong*)&dest + 1) }; - while (!_InterlockedCompareExchange128((volatile llong*)&dest, hi, lo, cmp)); + struct alignas(16) llong2 { llong ll[2]; } result{}; + _InterlockedCompareExchange128(reinterpret_cast(&const_cast(dest)), result.ll[1], result.ll[0], result.ll); + return std::bit_cast(result); } static inline T exchange(T& dest, T value) { - llong lo = *(llong*)&value; - llong hi = *((llong*)&value + 1); - llong cmp[2]{ *(volatile llong*)&dest, *((volatile llong*)&dest + 1) }; - while (!_InterlockedCompareExchange128((volatile llong*)&dest, hi, lo, cmp)); - return *(T*)+cmp; + struct alignas(16) llong2 { llong ll[2]; }; + const llong2 _value = std::bit_cast(value); + + const auto llptr = reinterpret_cast(&dest); + llong2 cmp{ llptr[0], llptr[1] }; + while (!_InterlockedCompareExchange128(llptr, _value.ll[1], _value.ll[0], cmp.ll)); + return std::bit_cast(cmp); + } + + static inline void store(T& dest, T value) + { + exchange(dest, value); + } + + static inline void release(T& dest, T value) + { + exchange(dest, value); } #endif