diff --git a/Utilities/Atomic.h b/Utilities/Atomic.h index 9e4709c323..0153beda73 100644 --- a/Utilities/Atomic.h +++ b/Utilities/Atomic.h @@ -562,206 +562,11 @@ struct atomic_storage : atomic_storage // TODO }; -template -struct atomic_add -{ - auto operator()(T1& lhs, const T2& rhs) const - { - return lhs += rhs; - } -}; - -template -struct atomic_add::value && std::is_convertible::value>> -{ - static constexpr auto fetch_op = &atomic_storage::fetch_add; - static constexpr auto op_fetch = &atomic_storage::add_fetch; - static constexpr auto atomic_op = &atomic_storage::add_fetch; -}; - -template -struct atomic_sub -{ - auto operator()(T1& lhs, const T2& rhs) const - { - return lhs -= rhs; - } -}; - -template -struct atomic_sub::value && std::is_convertible::value>> -{ - static constexpr auto fetch_op = &atomic_storage::fetch_sub; - static constexpr auto op_fetch = &atomic_storage::sub_fetch; - static constexpr auto atomic_op = &atomic_storage::sub_fetch; -}; - -template -struct atomic_pre_inc -{ - auto operator()(T& v) const - { - return ++v; - } -}; - -template -struct atomic_pre_inc::value>> -{ - static constexpr auto atomic_op = &atomic_storage::inc_fetch; -}; - -template -struct atomic_post_inc -{ - auto operator()(T& v) const - { - return v++; - } -}; - -template -struct atomic_post_inc::value>> -{ - static constexpr auto atomic_op = &atomic_storage::fetch_inc; -}; - -template -struct atomic_pre_dec -{ - auto operator()(T& v) const - { - return --v; - } -}; - -template -struct atomic_pre_dec::value>> -{ - static constexpr auto atomic_op = &atomic_storage::dec_fetch; -}; - -template -struct atomic_post_dec -{ - auto operator()(T& v) const - { - return v--; - } -}; - -template -struct atomic_post_dec::value>> -{ - static constexpr auto atomic_op = &atomic_storage::fetch_dec; -}; - -template -struct atomic_and -{ - auto operator()(T1& lhs, const T2& rhs) const - { - return lhs &= rhs; - } -}; - -template -struct atomic_and::value && std::is_convertible::value>> -{ - static constexpr auto fetch_op = &atomic_storage::fetch_and; - static constexpr auto op_fetch = &atomic_storage::and_fetch; - static constexpr auto atomic_op = &atomic_storage::and_fetch; -}; - -template -struct atomic_or -{ - auto operator()(T1& lhs, const T2& rhs) const - { - return lhs |= rhs; - } -}; - -template -struct atomic_or::value && std::is_convertible::value>> -{ - static constexpr auto fetch_op = &atomic_storage::fetch_or; - static constexpr auto op_fetch = &atomic_storage::or_fetch; - static constexpr auto atomic_op = &atomic_storage::or_fetch; -}; - -template -struct atomic_xor -{ - auto operator()(T1& lhs, const T2& rhs) const - { - return lhs ^= rhs; - } -}; - -template -struct atomic_xor::value && std::is_convertible::value>> -{ - static constexpr auto fetch_op = &atomic_storage::fetch_xor; - static constexpr auto op_fetch = &atomic_storage::xor_fetch; - static constexpr auto atomic_op = &atomic_storage::xor_fetch; -}; - -template -struct atomic_test_and_set -{ - bool operator()(T1& lhs, const T2& rhs) const - { - return test_and_set(lhs, rhs); - } -}; - -template -struct atomic_test_and_set::value && std::is_convertible::value>> -{ - static constexpr auto fetch_op = &atomic_storage::test_and_set; - static constexpr auto op_fetch = &atomic_storage::test_and_set; - static constexpr auto atomic_op = &atomic_storage::test_and_set; -}; - -template -struct atomic_test_and_reset -{ - bool operator()(T1& lhs, const T2& rhs) const - { - return test_and_reset(lhs, rhs); - } -}; - -template -struct atomic_test_and_reset::value && std::is_convertible::value>> -{ - static constexpr auto fetch_op = &atomic_storage::test_and_reset; - static constexpr auto op_fetch = &atomic_storage::test_and_reset; - static constexpr auto atomic_op = &atomic_storage::test_and_reset; -}; - -template -struct atomic_test_and_complement -{ - bool operator()(T1& lhs, const T2& rhs) const - { - return test_and_complement(lhs, rhs); - } -}; - -template -struct atomic_test_and_complement::value && std::is_convertible::value>> -{ - static constexpr auto fetch_op = &atomic_storage::test_and_complement; - static constexpr auto op_fetch = &atomic_storage::test_and_complement; - static constexpr auto atomic_op = &atomic_storage::test_and_complement; -}; - // Atomic type with lock-free and standard layout guarantees (and appropriate limitations) -template +template class atomic_t { +protected: using type = typename std::remove_cv::type; static_assert(alignof(type) == sizeof(type), "atomic_t<> error: unexpected alignment, use alignas() if necessary"); @@ -790,7 +595,7 @@ public: } // Atomically compare data with cmp, replace with exch if equal, return previous data value anyway - simple_type compare_and_swap(const type& cmp, const type& exch) + type compare_and_swap(const type& cmp, const type& exch) { type old = cmp; atomic_storage::compare_exchange(m_data, old, exch); @@ -804,83 +609,69 @@ public: return atomic_storage::compare_exchange(m_data, old, exch); } - // Atomic operation; returns old value, discards function result value - template> - type fetch_op(F&& func, const Args&... args) + // Atomic operation; returns old value + template + std::enable_if_t>::value, type> fetch_op(F&& func) { type _new, old = atomic_storage::load(m_data); while (true) { - func((_new = old), args...); + func((_new = old)); - if (LIKELY(atomic_storage::compare_exchange(m_data, old, _new))) return old; + if (LIKELY(atomic_storage::compare_exchange(m_data, old, _new))) [[likely]] + { + return old; + } } } - // Helper overload for calling optimized implementation - template> - type fetch_op(F&&, const Args&... args) - { - return F::fetch_op(m_data, args...); - } - - // Atomic operation; returns new value, discards function result value - template> - type op_fetch(F&& func, const Args&... args) + // Atomic operation; returns new value + template + std::enable_if_t>::value, type> op_fetch(F&& func) { type _new, old = atomic_storage::load(m_data); while (true) { - func((_new = old), args...); + func((_new = old)); - if (LIKELY(atomic_storage::compare_exchange(m_data, old, _new))) return _new; + if (LIKELY(atomic_storage::compare_exchange(m_data, old, _new))) [[likely]] + { + return _new; + } } } - // Helper overload for calling optimized implementation - template> - type op_fetch(F&&, const Args&... args) - { - return F::op_fetch(m_data, args...); - } - - // Atomic operation; returns function result value - template, typename = std::enable_if_t::value>> + // Atomic operation; returns function result value (TODO: remove args) + template > RT atomic_op(F&& func, const Args&... args) { type _new, old = atomic_storage::load(m_data); while (true) { - RT&& result = func((_new = old), args...); + if constexpr(std::is_void::value) + { + func((_new = old), args...); - if (LIKELY(atomic_storage::compare_exchange(m_data, old, _new))) return std::move(result); + if (LIKELY(atomic_storage::compare_exchange(m_data, old, _new))) [[likely]] + { + return; + } + } + else + { + RT result = func((_new = old), args...); + + if (LIKELY(atomic_storage::compare_exchange(m_data, old, _new))) [[likely]] + { + return result; + } + } } } - // Overload for void return type - template, typename = std::enable_if_t::value>> - void atomic_op(F&& func, const Args&... args) - { - type _new, old = atomic_storage::load(m_data); - - while (true) - { - func((_new = old), args...); - - if (LIKELY(atomic_storage::compare_exchange(m_data, old, _new))) return; - } - } - - // Helper overload for calling optimized implementation - template> - auto atomic_op(F&&, const Args&... args) - { - return F::atomic_op(m_data, args...); - } - // Atomically read data type load() const { @@ -911,144 +702,250 @@ public: return atomic_storage::exchange(m_data, rhs); } - template - type fetch_add(const T2& rhs) + type fetch_add(const type& rhs) { - return fetch_op(atomic_add{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::fetch_add(m_data, rhs); + } + + return fetch_op([&](T& v) + { + v += rhs; + }); } - template - type add_fetch(const T2& rhs) + type add_fetch(const type& rhs) { - return op_fetch(atomic_add{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::add_fetch(m_data, rhs); + } + + return op_fetch([&](T& v) + { + v += rhs; + }); } - template - auto operator +=(const T2& rhs) + auto operator +=(const type& rhs) { - return atomic_op(atomic_add{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::add_fetch(m_data, rhs); + } + + return atomic_op([&](T& v) + { + return v += rhs; + }); } - template - type fetch_sub(const T2& rhs) + type fetch_sub(const type& rhs) { - return fetch_op(atomic_sub{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::fetch_sub(m_data, rhs); + } + + return fetch_op([&](T& v) + { + v -= rhs; + }); } - template - type sub_fetch(const T2& rhs) + type sub_fetch(const type& rhs) { - return op_fetch(atomic_sub{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::sub_fetch(m_data, rhs); + } + + return op_fetch([&](T& v) + { + v -= rhs; + }); } - template - auto operator -=(const T2& rhs) + auto operator -=(const type& rhs) { - return atomic_op(atomic_sub{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::sub_fetch(m_data, rhs); + } + + return atomic_op([&](T& v) + { + return v -= rhs; + }); } - template - type fetch_and(const T2& rhs) + type fetch_and(const type& rhs) { - return fetch_op(atomic_and{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::fetch_and(m_data, rhs); + } + + return fetch_op([&](T& v) + { + v &= rhs; + }); } - template - type and_fetch(const T2& rhs) + type and_fetch(const type& rhs) { - return op_fetch(atomic_and{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::and_fetch(m_data, rhs); + } + + return op_fetch([&](T& v) + { + v &= rhs; + }); } - template - auto operator &=(const T2& rhs) + auto operator &=(const type& rhs) { - return atomic_op(atomic_and{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::and_fetch(m_data, rhs); + } + + return atomic_op([&](T& v) + { + return v &= rhs; + }); } - template - type fetch_or(const T2& rhs) + type fetch_or(const type& rhs) { - return fetch_op(atomic_or{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::fetch_or(m_data, rhs); + } + + return fetch_op([&](T& v) + { + v |= rhs; + }); } - template - type or_fetch(const T2& rhs) + type or_fetch(const type& rhs) { - return op_fetch(atomic_or{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::or_fetch(m_data, rhs); + } + + return op_fetch([&](T& v) + { + v |= rhs; + }); } - template - auto operator |=(const T2& rhs) + auto operator |=(const type& rhs) { - return atomic_op(atomic_or{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::or_fetch(m_data, rhs); + } + + return atomic_op([&](T& v) + { + return v |= rhs; + }); } - template - type fetch_xor(const T2& rhs) + type fetch_xor(const type& rhs) { - return fetch_op(atomic_xor{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::fetch_xor(m_data, rhs); + } + + return fetch_op([&](T& v) + { + v ^= rhs; + }); } - template - type xor_fetch(const T2& rhs) + type xor_fetch(const type& rhs) { - return op_fetch(atomic_xor{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::xor_fetch(m_data, rhs); + } + + return op_fetch([&](T& v) + { + v ^= rhs; + }); } - template - auto operator ^=(const T2& rhs) + auto operator ^=(const type& rhs) { - return atomic_op(atomic_xor{}, rhs); + if constexpr(std::is_integral::value) + { + return atomic_storage::xor_fetch(m_data, rhs); + } + + return atomic_op([&](T& v) + { + return v ^= rhs; + }); } auto operator ++() { - return atomic_op(atomic_pre_inc{}); + if constexpr(std::is_integral::value) + { + return atomic_storage::inc_fetch(m_data); + } + + return atomic_op([](T& v) + { + return ++v; + }); } auto operator --() { - return atomic_op(atomic_pre_dec{}); + if constexpr(std::is_integral::value) + { + return atomic_storage::dec_fetch(m_data); + } + + return atomic_op([](T& v) + { + return --v; + }); } auto operator ++(int) { - return atomic_op(atomic_post_inc{}); + if constexpr(std::is_integral::value) + { + return atomic_storage::fetch_inc(m_data); + } + + return atomic_op([](T& v) + { + return v++; + }); } auto operator --(int) { - return atomic_op(atomic_post_dec{}); - } + if constexpr(std::is_integral::value) + { + return atomic_storage::fetch_dec(m_data); + } - template - auto test_and_set(const T2& rhs) - { - return atomic_op(atomic_test_and_set{}, rhs); - } - - template - auto test_and_reset(const T2& rhs) - { - return atomic_op(atomic_test_and_reset{}, rhs); - } - - template - auto test_and_complement(const T2& rhs) - { - return atomic_op(atomic_test_and_complement{}, rhs); - } - - // Minimal pointer support (TODO: must forward operator ->()) - type operator ->() const - { - return load(); - } - - // Minimal array support - template - auto operator [](const I& index) const -> decltype(std::declval()[std::declval()]) - { - return load()[index]; + return atomic_op([](T& v) + { + return v--; + }); } }; diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 0eb0a92d93..360266a498 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -799,34 +799,34 @@ fs::file::file(const std::string& path, bs_t mode) #ifdef _WIN32 DWORD access = 0; - if (test(mode & fs::read)) access |= GENERIC_READ; - if (test(mode & fs::write)) access |= DELETE | (test(mode & fs::append) ? FILE_APPEND_DATA : GENERIC_WRITE); + if (mode & fs::read) access |= GENERIC_READ; + if (mode & fs::write) access |= DELETE | (mode & fs::append ? FILE_APPEND_DATA : GENERIC_WRITE); DWORD disp = 0; - if (test(mode & fs::create)) + if (mode & fs::create) { disp = - test(mode & fs::excl) ? CREATE_NEW : - test(mode & fs::trunc) ? CREATE_ALWAYS : OPEN_ALWAYS; + mode & fs::excl ? CREATE_NEW : + mode & fs::trunc ? CREATE_ALWAYS : OPEN_ALWAYS; } else { - if (test(mode & fs::excl)) + if (mode & fs::excl) { g_tls_error = error::inval; return; } - disp = test(mode & fs::trunc) ? TRUNCATE_EXISTING : OPEN_EXISTING; + disp = mode & fs::trunc ? TRUNCATE_EXISTING : OPEN_EXISTING; } DWORD share = 0; - if (!test(mode, fs::unread) || !test(mode & fs::write)) + if (!(mode & fs::unread) || !(mode & fs::write)) { share |= FILE_SHARE_READ; } - if (!test(mode, fs::lock + fs::unread) || !test(mode & fs::write)) + if (!(mode & (fs::lock + fs::unread)) || !(mode & fs::write)) { share |= FILE_SHARE_WRITE | FILE_SHARE_DELETE; } @@ -949,18 +949,18 @@ fs::file::file(const std::string& path, bs_t mode) #else int flags = 0; - if (test(mode & fs::read) && test(mode & fs::write)) flags |= O_RDWR; - else if (test(mode & fs::read)) flags |= O_RDONLY; - else if (test(mode & fs::write)) flags |= O_WRONLY; + if (mode & fs::read && mode & fs::write) flags |= O_RDWR; + else if (mode & fs::read) flags |= O_RDONLY; + else if (mode & fs::write) flags |= O_WRONLY; - if (test(mode & fs::append)) flags |= O_APPEND; - if (test(mode & fs::create)) flags |= O_CREAT; - if (test(mode & fs::trunc) && !test(mode, fs::lock + fs::unread)) flags |= O_TRUNC; - if (test(mode & fs::excl)) flags |= O_EXCL; + if (mode & fs::append) flags |= O_APPEND; + if (mode & fs::create) flags |= O_CREAT; + if (mode & fs::trunc && !(mode & (fs::lock + fs::unread))) flags |= O_TRUNC; + if (mode & fs::excl) flags |= O_EXCL; int perm = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - if (test(mode & fs::write) && test(mode & fs::unread)) + if (mode & fs::write && mode & fs::unread) { perm = 0; } @@ -973,14 +973,14 @@ fs::file::file(const std::string& path, bs_t mode) return; } - if (test(mode & fs::write) && test(mode, fs::lock + fs::unread) && ::flock(fd, LOCK_EX | LOCK_NB) != 0) + if (mode & fs::write && mode & (fs::lock + fs::unread) && ::flock(fd, LOCK_EX | LOCK_NB) != 0) { g_tls_error = errno == EWOULDBLOCK ? fs::error::acces : to_error(errno); ::close(fd); return; } - if (test(mode & fs::trunc) && test(mode, fs::lock + fs::unread)) + if (mode & fs::trunc && mode & (fs::lock + fs::unread)) { // Postpone truncation in order to avoid using O_TRUNC on a locked file ::ftruncate(fd, 0); diff --git a/Utilities/bit_set.h b/Utilities/bit_set.h index f37bde7b92..3fa03067de 100644 --- a/Utilities/bit_set.h +++ b/Utilities/bit_set.h @@ -1,27 +1,8 @@ #pragma once /* -This header helps to extend scoped enum types (enum class) in two possible ways: -1) Enabling bitwise operators for enums -2) Advanced bs_t<> template (this converts enum type to another "bitset" enum type) - -To enable bitwise operators, enum scope must contain `__bitwise_ops` entry. - -enum class flags -{ - __bitwise_ops, // Not essential, but recommended to put it first - - flag1 = 1 << 0, - flag2 = 1 << 1, -}; - -Examples: -`flags::flag1 | flags::flag2` - bitwise OR -`flags::flag1 & flags::flag2` - bitwise AND -`flags::flag1 ^ flags::flag2` - bitwise XOR -`~flags::flag1` - bitwise NEG - -To enable bs_t<> template, enum scope must contain `__bitset_enum_max` entry. +This header implements bs_t<> class for scoped enum types (enum class). +To enable bs_t<>, enum scope must contain `__bitset_enum_max` entry. enum class flagzz : u32 { @@ -31,40 +12,42 @@ enum class flagzz : u32 __bitset_enum_max // It must be the last value }; -Now some operators are enabled for two enum types: `flagzz` and `bs_t`. -These are very different from previously described bitwise operators. +This also enables helper operators for this enum type. Examples: `+flagzz::flag1` - unary `+` operator convert flagzz value to bs_t `flagzz::flag1 + flagzz::flag2` - bitset union `flagzz::flag1 - flagzz::flag2` - bitset difference Intersection (&) and symmetric difference (^) is also available. - */ #include "types.h" #include "Atomic.h" -// Helper template -template -struct bs_base +template +class atomic_bs_t; + +// Bitset type for enum class with available bits [0, T::__bitset_enum_max) +template +class bs_t final { +public: // Underlying type using under = std::underlying_type_t; - // Actual bitset type - enum class type : under - { - null = 0, // Empty bitset +private: + // Underlying value + under m_data; - __bitset_set_type = 0 // SFINAE marker - }; + friend class atomic_bs_t; +public: static constexpr std::size_t bitmax = sizeof(T) * 8; static constexpr std::size_t bitsize = static_cast(T::__bitset_enum_max); static_assert(std::is_enum::value, "bs_t<> error: invalid type (must be enum)"); - static_assert(!bitsize || bitsize <= bitmax, "bs_t<> error: invalid __bitset_enum_max"); + static_assert(bitsize <= bitmax, "bs_t<> error: invalid __bitset_enum_max"); + static_assert(bitsize != bitmax || std::is_unsigned::value, "bs_t<> error: invalid __bitset_enum_max (sign bit)"); // Helper function static constexpr under shift(T value) @@ -72,662 +55,328 @@ struct bs_base return static_cast(1) << static_cast(value); } - friend type& operator +=(type& lhs, type rhs) + bs_t() = default; + + // Construct from a single bit + constexpr bs_t(T bit) + : m_data(shift(bit)) { - reinterpret_cast(lhs) |= static_cast(rhs); - return lhs; } - friend type& operator -=(type& lhs, type rhs) + // Test for empty bitset + constexpr explicit operator bool() const { - reinterpret_cast(lhs) &= ~static_cast(rhs); - return lhs; + return m_data != 0; } - friend type& operator &=(type& lhs, type rhs) + // Extract underlying data + constexpr explicit operator under() const { - reinterpret_cast(lhs) &= static_cast(rhs); - return lhs; + return m_data; } - friend type& operator ^=(type& lhs, type rhs) + // Copy + constexpr bs_t operator +() const { - reinterpret_cast(lhs) ^= static_cast(rhs); - return lhs; + return *this; } - friend type& operator +=(type& lhs, T rhs) + constexpr bs_t& operator +=(bs_t rhs) { - reinterpret_cast(lhs) |= shift(rhs); - return lhs; + m_data |= static_cast(rhs); + return *this; } - friend type& operator -=(type& lhs, T rhs) + constexpr bs_t& operator -=(bs_t rhs) { - reinterpret_cast(lhs) &= ~shift(rhs); - return lhs; + m_data &= ~static_cast(rhs); + return *this; } - friend type& operator &=(type& lhs, T rhs) + constexpr bs_t& operator &=(bs_t rhs) { - reinterpret_cast(lhs) &= shift(rhs); - return lhs; + m_data &= static_cast(rhs); + return *this; } - friend type& operator ^=(type& lhs, T rhs) + constexpr bs_t& operator ^=(bs_t rhs) { - reinterpret_cast(lhs) ^= shift(rhs); - return lhs; + m_data ^= static_cast(rhs); + return *this; } - friend constexpr type operator +(type lhs, type rhs) + constexpr bs_t operator +(bs_t rhs) const { - return static_cast(static_cast(lhs) | static_cast(rhs)); + bs_t r{}; + r.m_data = m_data | rhs.m_data; + return r; } - friend constexpr type operator -(type lhs, type rhs) + constexpr bs_t operator -(bs_t rhs) const { - return static_cast(static_cast(lhs) & ~static_cast(rhs)); + bs_t r{}; + r.m_data = m_data & ~rhs.m_data; + return r; } - friend constexpr type operator &(type lhs, type rhs) + constexpr bs_t operator &(bs_t rhs) const { - return static_cast(static_cast(lhs) & static_cast(rhs)); + bs_t r{}; + r.m_data = m_data & rhs.m_data; + return r; } - friend constexpr type operator ^(type lhs, type rhs) + constexpr bs_t operator ^(bs_t rhs) const { - return static_cast(static_cast(lhs) ^ static_cast(rhs)); + bs_t r{}; + r.m_data = m_data ^ rhs.m_data; + return r; } - friend constexpr type operator &(type lhs, T rhs) + constexpr bool operator ==(bs_t rhs) const { - return static_cast(static_cast(lhs) & shift(rhs)); + return m_data == rhs.m_data; } - friend constexpr type operator ^(type lhs, T rhs) + constexpr bool operator !=(bs_t rhs) const { - return static_cast(static_cast(lhs) ^ shift(rhs)); + return m_data != rhs.m_data; } - friend constexpr type operator &(T lhs, type rhs) + constexpr bool test(bs_t rhs) const { - return static_cast(shift(lhs) & static_cast(rhs)); + return (m_data & rhs.m_data) != 0; } - friend constexpr type operator ^(T lhs, type rhs) + constexpr bool test_and_set(T bit) { - return static_cast(shift(lhs) ^ static_cast(rhs)); + bool r = (m_data & shift(bit)) != 0; + m_data |= shift(bit); + return r; } - friend constexpr bool operator ==(T lhs, type rhs) + constexpr bool test_and_reset(T bit) { - return shift(lhs) == rhs; + bool r = (m_data & shift(bit)) != 0; + m_data &= ~shift(bit); + return r; } - friend constexpr bool operator ==(type lhs, T rhs) + constexpr bool test_and_complement(T bit) { - return lhs == shift(rhs); - } - - friend constexpr bool operator !=(T lhs, type rhs) - { - return shift(lhs) != rhs; - } - - friend constexpr bool operator !=(type lhs, T rhs) - { - return lhs != shift(rhs); - } - - friend constexpr bool test(type value) - { - return static_cast(value) != 0; - } - - friend constexpr bool test(type lhs, type rhs) - { - return (static_cast(lhs) & static_cast(rhs)) != 0; - } - - friend constexpr bool test(type lhs, T rhs) - { - return (static_cast(lhs) & shift(rhs)) != 0; - } - - friend constexpr bool test(T lhs, type rhs) - { - return (shift(lhs) & static_cast(rhs)) != 0; - } - - friend bool test_and_set(type& lhs, type rhs) - { - return test_and_set(reinterpret_cast(lhs), static_cast(rhs)); - } - - friend bool test_and_set(type& lhs, T rhs) - { - return test_and_set(reinterpret_cast(lhs), shift(rhs)); - } - - friend bool test_and_reset(type& lhs, type rhs) - { - return test_and_reset(reinterpret_cast(lhs), static_cast(rhs)); - } - - friend bool test_and_reset(type& lhs, T rhs) - { - return test_and_reset(reinterpret_cast(lhs), shift(rhs)); - } - - friend bool test_and_complement(type& lhs, type rhs) - { - return test_and_complement(reinterpret_cast(lhs), static_cast(rhs)); - } - - friend bool test_and_complement(type& lhs, T rhs) - { - return test_and_complement(reinterpret_cast(lhs), shift(rhs)); + bool r = (m_data & shift(bit)) != 0; + m_data ^= shift(bit); + return r; } }; -// Bitset type for enum class with available bits [0, T::__bitset_enum_max) -template -using bs_t = typename bs_base::type; - // Unary '+' operator: promote plain enum value to bitset value -template -constexpr bs_t operator +(T value) +template +constexpr bs_t operator +(T bit) { - return static_cast>(bs_base::shift(value)); + return bit; } // Binary '+' operator: bitset union -template +template constexpr bs_t operator +(T lhs, T rhs) { - return static_cast>(bs_base::shift(lhs) | bs_base::shift(rhs)); -} - -// Binary '+' operator: bitset union -template -constexpr bs_t operator +(typename bs_base::type lhs, T rhs) -{ - return static_cast>(static_cast::under>(lhs) | bs_base::shift(rhs)); -} - -// Binary '+' operator: bitset union -template -constexpr bs_t operator +(T lhs, typename bs_base::type rhs) -{ - return static_cast>(bs_base::shift(lhs) | static_cast::under>(rhs)); + return bs_t(lhs) + bs_t(rhs); } // Binary '-' operator: bitset difference -template +template constexpr bs_t operator -(T lhs, T rhs) { - return static_cast>(bs_base::shift(lhs) & ~bs_base::shift(rhs)); + return bs_t(lhs) - bs_t(rhs); } -// Binary '-' operator: bitset difference -template -constexpr bs_t operator -(typename bs_base::type lhs, T rhs) +// Binary '&' operator: bitset intersection +template +constexpr bs_t operator &(T lhs, T rhs) { - return static_cast>(static_cast::under>(lhs) & ~bs_base::shift(rhs)); + return bs_t(lhs) & bs_t(rhs); } -// Binary '-' operator: bitset difference -template -constexpr bs_t operator -(T lhs, typename bs_base::type rhs) +// Binary '^' operator: bitset symmetric difference +template +constexpr bs_t operator ^(T lhs, T rhs) { - return static_cast>(bs_base::shift(lhs) & ~static_cast::under>(rhs)); + return bs_t(lhs) ^ bs_t(rhs); } -template -struct atomic_add>::value>>> +// Atomic bitset specialization with optimized operations +template +class atomic_bs_t : public atomic_t<::bs_t> // TODO: true specialization { - using under = typename bs_base::under; + // Corresponding bitset type + using bs_t = ::bs_t; - static inline bs_t op1(bs_t& left, T right) + // Base class + using base = atomic_t<::bs_t>; + + // Use underlying m_data + using base::m_data; + +public: + // Underlying type + using under = typename bs_t::under; + + atomic_bs_t() = default; + + atomic_bs_t(const atomic_bs_t&) = delete; + + atomic_bs_t& operator =(const atomic_bs_t&) = delete; + + explicit constexpr atomic_bs_t(bs_t value) + : base(value) { - return static_cast>(atomic_storage::fetch_or(reinterpret_cast(left), bs_base::shift(right))); } - static constexpr auto fetch_op = &op1; - - static inline bs_t op2(bs_t& left, T right) + explicit constexpr atomic_bs_t(T bit) + : base(bit) { - return static_cast>(atomic_storage::or_fetch(reinterpret_cast(left), bs_base::shift(right))); } - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_sub>::value>>> -{ - using under = typename bs_base::under; - - static inline bs_t op1(bs_t& left, T right) - { - return static_cast>(atomic_storage::fetch_and(reinterpret_cast(left), ~bs_base::shift(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline bs_t op2(bs_t& left, T right) - { - return static_cast>(atomic_storage::and_fetch(reinterpret_cast(left), ~bs_base::shift(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_and>::value>>> -{ - using under = typename bs_base::under; - - static inline bs_t op1(bs_t& left, T right) - { - return static_cast>(atomic_storage::fetch_and(reinterpret_cast(left), bs_base::shift(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline bs_t op2(bs_t& left, T right) - { - return static_cast>(atomic_storage::and_fetch(reinterpret_cast(left), bs_base::shift(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_xor>::value>>> -{ - using under = typename bs_base::under; - - static inline bs_t op1(bs_t& left, T right) - { - return static_cast>(atomic_storage::fetch_xor(reinterpret_cast(left), bs_base::shift(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline bs_t op2(bs_t& left, T right) - { - return static_cast>(atomic_storage::xor_fetch(reinterpret_cast(left), bs_base::shift(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_add::value>> -{ - using under = std::underlying_type_t; - - static inline T op1(T& left, T right) - { - return static_cast(atomic_storage::fetch_or(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline T op2(T& left, T right) - { - return static_cast(atomic_storage::or_fetch(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_sub::value>> -{ - using under = std::underlying_type_t; - - static inline T op1(T& left, T right) - { - return static_cast(atomic_storage::fetch_and(reinterpret_cast(left), ~static_cast(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline T op2(T& left, T right) - { - return static_cast(atomic_storage::and_fetch(reinterpret_cast(left), ~static_cast(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_and::value>> -{ - using under = std::underlying_type_t; - - static inline T op1(T& left, T right) - { - return static_cast(atomic_storage::fetch_and(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline T op2(T& left, T right) - { - return static_cast(atomic_storage::and_fetch(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_xor::value>> -{ - using under = std::underlying_type_t; - - static inline T op1(T& left, T right) - { - return static_cast(atomic_storage::fetch_xor(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline T op2(T& left, T right) - { - return static_cast(atomic_storage::xor_fetch(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_test_and_set>::value>>> -{ - using under = typename bs_base::under; - - static inline bool _op(bs_t& left, T value) - { - return atomic_storage::bts(reinterpret_cast(left), static_cast(static_cast(value))); - } - - static constexpr auto fetch_op = &_op; - static constexpr auto op_fetch = &_op; - static constexpr auto atomic_op = &_op; -}; - -template -struct atomic_test_and_reset>::value>>> -{ - using under = typename bs_base::under; - - static inline bool _op(bs_t& left, T value) - { - return atomic_storage::btr(reinterpret_cast(left), static_cast(static_cast(value))); - } - - static constexpr auto fetch_op = &_op; - static constexpr auto op_fetch = &_op; - static constexpr auto atomic_op = &_op; -}; - -template -struct atomic_test_and_complement>::value>>> -{ - using under = typename bs_base::under; - - static inline bool _op(bs_t& left, T value) - { - return atomic_storage::btc(reinterpret_cast(left), static_cast(static_cast(value))); - } - - static constexpr auto fetch_op = &_op; - static constexpr auto op_fetch = &_op; - static constexpr auto atomic_op = &_op; -}; - -template -struct atomic_test_and_set::value>> -{ - using under = std::underlying_type_t; - - static inline bool _op(T& left, T value) - { - return atomic_storage::test_and_set(reinterpret_cast(left), static_cast(value)); - } - - static constexpr auto fetch_op = &_op; - static constexpr auto op_fetch = &_op; - static constexpr auto atomic_op = &_op; -}; - -template -struct atomic_test_and_reset::value>> -{ - using under = std::underlying_type_t; - - static inline bool _op(T& left, T value) - { - return atomic_storage::test_and_reset(reinterpret_cast(left), static_cast(value)); - } - - static constexpr auto fetch_op = &_op; - static constexpr auto op_fetch = &_op; - static constexpr auto atomic_op = &_op; -}; - -template -struct atomic_test_and_complement::value>> -{ - using under = std::underlying_type_t; - - static inline bool _op(T& left, T value) - { - return atomic_storage::test_and_complement(reinterpret_cast(left), static_cast(value)); - } - - static constexpr auto fetch_op = &_op; - static constexpr auto op_fetch = &_op; - static constexpr auto atomic_op = &_op; -}; - -// Binary '|' operator: bitwise OR -template -constexpr T operator |(T lhs, T rhs) -{ - return static_cast(std::underlying_type_t(lhs) | std::underlying_type_t(rhs)); -} - -// Binary '&' operator: bitwise AND -template -constexpr T operator &(T lhs, T rhs) -{ - return static_cast(std::underlying_type_t(lhs) & std::underlying_type_t(rhs)); -} - -// Binary '^' operator: bitwise XOR -template -constexpr T operator ^(T lhs, T rhs) -{ - return static_cast(std::underlying_type_t(lhs) ^ std::underlying_type_t(rhs)); -} - -// Unary '~' operator: bitwise NEG -template -constexpr T operator ~(T value) -{ - return static_cast(~std::underlying_type_t(value)); -} - -// Bitwise OR assignment -template -inline T& operator |=(T& lhs, T rhs) -{ - reinterpret_cast&>(lhs) |= std::underlying_type_t(rhs); - return lhs; -} - -// Bitwise AND assignment -template -inline T& operator &=(T& lhs, T rhs) -{ - reinterpret_cast&>(lhs) &= std::underlying_type_t(rhs); - return lhs; -} - -// Bitwise XOR assignment -template -inline T& operator ^=(T& lhs, T rhs) -{ - reinterpret_cast&>(lhs) ^= std::underlying_type_t(rhs); - return lhs; -} - -template -constexpr bool test(T value) -{ - return std::underlying_type_t(value) != 0; -} - -template -constexpr bool test(T lhs, T rhs) -{ - return (std::underlying_type_t(lhs) & std::underlying_type_t(rhs)) != 0; -} - -template -inline bool test_and_set(T& lhs, T rhs) -{ - return test_and_set(reinterpret_cast&>(lhs), std::underlying_type_t(rhs)); -} - -template -inline bool test_and_reset(T& lhs, T rhs) -{ - return test_and_reset(reinterpret_cast&>(lhs), std::underlying_type_t(rhs)); -} - -template -inline bool test_and_complement(T& lhs, T rhs) -{ - return test_and_complement(reinterpret_cast&>(lhs), std::underlying_type_t(rhs)); -} - -template -struct atomic_or::value>> -{ - using under = std::underlying_type_t; - - static inline T op1(T& left, T right) - { - return static_cast(atomic_storage::fetch_or(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline T op2(T& left, T right) - { - return static_cast(atomic_storage::or_fetch(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_and::value>> -{ - using under = std::underlying_type_t; - - static inline T op1(T& left, T right) - { - return static_cast(atomic_storage::fetch_and(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline T op2(T& left, T right) - { - return static_cast(atomic_storage::and_fetch(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_xor::value>> -{ - using under = std::underlying_type_t; - - static inline T op1(T& left, T right) - { - return static_cast(atomic_storage::fetch_xor(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto fetch_op = &op1; - - static inline T op2(T& left, T right) - { - return static_cast(atomic_storage::xor_fetch(reinterpret_cast(left), static_cast(right))); - } - - static constexpr auto op_fetch = &op2; - static constexpr auto atomic_op = &op2; -}; - -template -struct atomic_test_and_set::value>> -{ - using under = std::underlying_type_t; - - static inline bool _op(T& left, T value) - { - return atomic_storage::test_and_set(reinterpret_cast(left), static_cast(value)); - } - - static constexpr auto fetch_op = &_op; - static constexpr auto op_fetch = &_op; - static constexpr auto atomic_op = &_op; -}; - -template -struct atomic_test_and_reset::value>> -{ - using under = std::underlying_type_t; - - static inline bool _op(T& left, T value) - { - return atomic_storage::test_and_reset(reinterpret_cast(left), static_cast(value)); - } - - static constexpr auto fetch_op = &_op; - static constexpr auto op_fetch = &_op; - static constexpr auto atomic_op = &_op; -}; - -template -struct atomic_test_and_complement::value>> -{ - using under = std::underlying_type_t; - - static inline bool _op(T& left, T value) - { - return atomic_storage::test_and_complement(reinterpret_cast(left), static_cast(value)); - } - - static constexpr auto fetch_op = &_op; - static constexpr auto op_fetch = &_op; - static constexpr auto atomic_op = &_op; + explicit operator bool() const + { + return static_cast(base::load()); + } + + explicit operator under() const + { + return static_cast(base::load()); + } + + bs_t fetch_add(const bs_t& rhs) + { + bs_t r; + r.m_data = atomic_storage::fetch_or(m_data.m_data, rhs.m_data); + return r; + } + + bs_t add_fetch(const bs_t& rhs) + { + bs_t r; + r.m_data = atomic_storage::or_fetch(m_data.m_data, rhs.m_data); + return r; + } + + bs_t operator +=(const bs_t& rhs) + { + return add_fetch(rhs); + } + + bs_t fetch_sub(const bs_t& rhs) + { + bs_t r; + r.m_data = atomic_storage::fetch_and(m_data.m_data, ~rhs.m_data); + return r; + } + + bs_t sub_fetch(const bs_t& rhs) + { + bs_t r; + r.m_data = atomic_storage::and_fetch(m_data.m_data, ~rhs.m_data); + return r; + } + + bs_t operator -=(const bs_t& rhs) + { + return sub_fetch(rhs); + } + + bs_t fetch_and(const bs_t& rhs) + { + bs_t r; + r.m_data = atomic_storage::fetch_and(m_data.m_data, rhs.m_data); + return r; + } + + bs_t and_fetch(const bs_t& rhs) + { + bs_t r; + r.m_data = atomic_storage::and_fetch(m_data.m_data, rhs.m_data); + return r; + } + + bs_t operator &=(const bs_t& rhs) + { + return and_fetch(rhs); + } + + bs_t fetch_xor(const bs_t& rhs) + { + bs_t r; + r.m_data = atomic_storage::fetch_xor(m_data.m_data, rhs.m_data); + return r; + } + + bs_t xor_fetch(const bs_t& rhs) + { + bs_t r; + r.m_data = atomic_storage::xor_fetch(m_data.m_data, rhs.m_data); + return r; + } + + bs_t operator ^=(const bs_t& rhs) + { + return xor_fetch(rhs); + } + + auto fetch_or(const bs_t&) = delete; + auto or_fetch(const bs_t&) = delete; + auto operator |=(const bs_t&) = delete; + auto operator ++() = delete; + auto operator --() = delete; + auto operator ++(int) = delete; + auto operator --(int) = delete; + + bs_t operator +(bs_t rhs) const + { + bs_t r{}; + r.m_data = base::load().m_data | rhs.m_data; + return r; + } + + bs_t operator -(bs_t rhs) const + { + bs_t r{}; + r.m_data = base::load().m_data & ~rhs.m_data; + return r; + } + + bs_t operator &(bs_t rhs) const + { + bs_t r{}; + r.m_data = base::load().m_data & rhs.m_data; + return r; + } + + bs_t operator ^(bs_t rhs) const + { + bs_t r{}; + r.m_data = base::load().m_data ^ rhs.m_data; + return r; + } + + bool test(const bs_t& rhs) + { + return base::load().test(rhs); + } + + bool test_and_set(T rhs) + { + return atomic_storage::bts(m_data.m_data, static_cast(static_cast(rhs))); + } + + bool test_and_reset(T rhs) + { + return atomic_storage::btr(m_data.m_data, static_cast(static_cast(rhs))); + } + + bool test_and_complement(T rhs) + { + return atomic_storage::btc(m_data.m_data, static_cast(static_cast(rhs))); + } }; diff --git a/Utilities/types.h b/Utilities/types.h index dac2f58dfa..3d3394c285 100644 --- a/Utilities/types.h +++ b/Utilities/types.h @@ -707,42 +707,6 @@ constexpr u32 size32(const T (&)[Size], const char* msg = nullptr) return static_cast(Size); } -template ::value>> -constexpr bool test(const T1& value) -{ - return value != 0; -} - -template ::value && std::is_integral::value>> -constexpr bool test(const T1& lhs, const T2& rhs) -{ - return (lhs & rhs) != 0; -} - -template ::value && std::is_integral::value>> -inline bool test_and_set(T& lhs, const T2& rhs) -{ - const bool result = (lhs & rhs) != 0; - lhs |= rhs; - return result; -} - -template ::value && std::is_integral::value>> -inline bool test_and_reset(T& lhs, const T2& rhs) -{ - const bool result = (lhs & rhs) != 0; - lhs &= ~rhs; - return result; -} - -template ::value && std::is_integral::value>> -inline bool test_and_complement(T& lhs, const T2& rhs) -{ - const bool result = (lhs & rhs) != 0; - lhs ^= rhs; - return result; -} - // Simplified hash algorithm for pointers. May be used in std::unordered_(map|set). template struct pointer_hash diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index cc0dc8a370..78fcac747d 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -52,10 +52,10 @@ void cpu_thread::on_task() g_tls_current_cpu_thread = this; // Check thread status - while (!test(state, cpu_flag::exit + cpu_flag::dbg_global_stop)) + while (!(state & (cpu_flag::exit + cpu_flag::dbg_global_stop))) { // Check stop status - if (!test(state & cpu_flag::stop)) + if (!(state & cpu_flag::stop)) { try { @@ -100,7 +100,8 @@ cpu_thread::cpu_thread(u32 id) bool cpu_thread::check_state() { #ifdef WITH_GDB_DEBUGGER - if (test(state, cpu_flag::dbg_pause)) { + if (state & cpu_flag::dbg_pause) + { fxm::get()->pause_from(this); } #endif @@ -110,7 +111,7 @@ bool cpu_thread::check_state() while (true) { - if (test(state, cpu_flag::memory) && state.test_and_reset(cpu_flag::memory)) + if (state & cpu_flag::memory && state.test_and_reset(cpu_flag::memory)) { cpu_flag_memory = true; @@ -121,17 +122,17 @@ bool cpu_thread::check_state() } } - if (test(state, cpu_flag::exit + cpu_flag::dbg_global_stop)) + if (state & cpu_flag::exit + cpu_flag::dbg_global_stop) { return true; } - if (test(state & cpu_flag::signal) && state.test_and_reset(cpu_flag::signal)) + if (state & cpu_flag::signal && state.test_and_reset(cpu_flag::signal)) { cpu_sleep_called = false; } - if (!test(state, cpu_state_pause)) + if (!(state & cpu_state_pause)) { if (cpu_flag_memory) { @@ -140,7 +141,7 @@ bool cpu_thread::check_state() break; } - else if (!cpu_sleep_called && test(state, cpu_flag::suspend)) + else if (!cpu_sleep_called && state & cpu_flag::suspend) { cpu_sleep(); cpu_sleep_called = true; @@ -152,12 +153,12 @@ bool cpu_thread::check_state() const auto state_ = state.load(); - if (test(state_, cpu_flag::ret + cpu_flag::stop)) + if (state_ & (cpu_flag::ret + cpu_flag::stop)) { return true; } - if (test(state_, cpu_flag::dbg_step)) + if (state_ & cpu_flag::dbg_step) { state += cpu_flag::dbg_pause; state -= cpu_flag::dbg_step; @@ -168,7 +169,7 @@ bool cpu_thread::check_state() void cpu_thread::test_state() { - if (UNLIKELY(test(state))) + if (UNLIKELY(state)) { if (check_state()) { diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 8497ad4581..5110627acc 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -37,7 +37,7 @@ public: cpu_thread(u32 id); // Public thread state - atomic_t> state{+cpu_flag::stop}; + atomic_bs_t state{+cpu_flag::stop}; // Process thread state, return true if the checker must return bool check_state(); diff --git a/rpcs3/Emu/Cell/Modules/sys_lwcond_.cpp b/rpcs3/Emu/Cell/Modules/sys_lwcond_.cpp index 7e9a924c34..6ef016d39f 100644 --- a/rpcs3/Emu/Cell/Modules/sys_lwcond_.cpp +++ b/rpcs3/Emu/Cell/Modules/sys_lwcond_.cpp @@ -148,7 +148,7 @@ error_code sys_lwcond_signal_all(ppu_thread& ppu, vm::ptr lwcond) } ppu.test_state(); - lwmutex->all_info += res; + lwmutex->all_info += +res; return CELL_OK; } @@ -173,7 +173,7 @@ error_code sys_lwcond_signal_all(ppu_thread& ppu, vm::ptr lwcond) if (res > 0) { - lwmutex->all_info += res; + lwmutex->all_info += +res; res = CELL_OK; } diff --git a/rpcs3/Emu/Cell/PPUAnalyser.cpp b/rpcs3/Emu/Cell/PPUAnalyser.cpp index e129105dc2..f29be974dd 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.cpp +++ b/rpcs3/Emu/Cell/PPUAnalyser.cpp @@ -1051,7 +1051,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry) } // Get function limit - const u32 func_end = std::min(get_limit(func.addr + 1), test(func.attr, ppu_attr::known_size) ? func.addr + func.size : end); + const u32 func_end = std::min(get_limit(func.addr + 1), func.attr & ppu_attr::known_size ? func.addr + func.size : end); // Block analysis workload std::vector>> block_queue; @@ -1084,7 +1084,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry) } // TODO: lower priority? - if (test(func.attr, ppu_attr::no_size)) + if (func.attr & ppu_attr::no_size) { // Get next function const auto _next = fmap.lower_bound(func.blocks.crbegin()->first + 1); @@ -1135,12 +1135,12 @@ void ppu_module::analyse(u32 lib_toc, u32 entry) } // Add next block if necessary - if ((is_call && !test(pfunc->attr, ppu_attr::no_return)) || (type == ppu_itype::BC && (op.bo & 0x14) != 0x14)) + if ((is_call && !(pfunc->attr & ppu_attr::no_return)) || (type == ppu_itype::BC && (op.bo & 0x14) != 0x14)) { add_block(_ptr.addr()); } - if (is_call && test(pfunc->attr, ppu_attr::no_return)) + if (is_call && pfunc->attr & ppu_attr::no_return) { // Nothing } @@ -1201,7 +1201,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry) if (jt_addr != jt_end && _ptr.addr() == jt_addr) { // Acknowledge jumptable detection failure - if (!test(func.attr, ppu_attr::no_size)) + if (!(func.attr & ppu_attr::no_size)) { LOG_WARNING(PPU, "[0x%x] Jump table not found! 0x%x-0x%x", func.addr, jt_addr, jt_end); } @@ -1235,7 +1235,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry) block.second = _ptr.addr() - block.first; break; } - else if (type == ppu_itype::STDU && test(func.attr, ppu_attr::no_size) && (op.opcode == *_ptr || *_ptr == ppu_instructions::BLR())) + else if (type == ppu_itype::STDU && func.attr & ppu_attr::no_size && (op.opcode == *_ptr || *_ptr == ppu_instructions::BLR())) { // Hack LOG_SUCCESS(PPU, "[0x%x] Instruction repetition: 0x%08x", iaddr, op.opcode); @@ -1254,7 +1254,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry) } // Finalization: determine function size - if (!test(func.attr, ppu_attr::known_size)) + if (!(func.attr & ppu_attr::known_size)) { const auto last = func.blocks.crbegin(); @@ -1320,7 +1320,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry) } // Finalization: decrease known function size (TODO) - if (test(func.attr, ppu_attr::known_size)) + if (func.attr & ppu_attr::known_size) { const auto last = func.blocks.crbegin(); diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index 91a9e80264..317f163969 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -1167,7 +1167,7 @@ void ppu_load_exec(const ppu_exec_object& elf) if (info.size < sizeof(process_param_t)) { - LOG_WARNING(LOADER, "Bad process_param size! [0x%x : 0x%x]", info.size, SIZE_32(process_param_t)); + LOG_WARNING(LOADER, "Bad process_param size! [0x%x : 0x%x]", info.size, sizeof(process_param_t)); } if (info.magic != 0x13bcc5f6) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 679a5a3ae1..bdb30eb6bb 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -607,7 +607,7 @@ void ppu_thread::exec_task() { if (g_cfg.core.ppu_decoder == ppu_decoder_type::llvm) { - while (!test(state, cpu_flag::ret + cpu_flag::exit + cpu_flag::stop + cpu_flag::dbg_global_stop)) + while (!(state & (cpu_flag::ret + cpu_flag::exit + cpu_flag::stop + cpu_flag::dbg_global_stop))) { reinterpret_cast(static_cast(ppu_ref(cia)))(*this); } @@ -625,7 +625,7 @@ void ppu_thread::exec_task() while (true) { - if (UNLIKELY(test(state))) + if (UNLIKELY(state)) { if (check_state()) return; @@ -678,7 +678,7 @@ void ppu_thread::exec_task() func2 = func4; func3 = func5; - if (UNLIKELY(test(state))) + if (UNLIKELY(state)) { break; } @@ -763,9 +763,9 @@ cmd64 ppu_thread::cmd_wait() { while (true) { - if (UNLIKELY(test(state))) + if (UNLIKELY(state)) { - if (test(state, cpu_flag::stop + cpu_flag::exit)) + if (state & (cpu_flag::stop + cpu_flag::exit)) { return cmd64{}; } diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index 22a72e1ffb..8f212560f5 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -1183,7 +1183,7 @@ static void check_state_ret(SPUThread& _spu, void*, u8*) static void check_state(SPUThread* _spu, spu_function_t _ret) { - if (test(_spu->state) && _spu->check_state()) + if (_spu->state && _spu->check_state()) { _ret = &check_state_ret; } diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index b5a7bd4c6f..7a7dfae221 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -490,7 +490,7 @@ std::vector spu_recompiler_base::block(const be_t* ls, u32 entry_point } } - if (test(af, vf::is_const)) + if (af & vf::is_const) { const u32 target = spu_branch_target(av); @@ -858,7 +858,7 @@ std::vector spu_recompiler_base::block(const be_t* ls, u32 entry_point case spu_itype::HBR: { hbr_loc = spu_branch_target(pos, op.roh << 7 | op.rt); - hbr_tg = test(vflags[op.ra], vf::is_const) && !op.c ? values[op.ra] & 0x3fffc : -1; + hbr_tg = vflags[op.ra] & vf::is_const && !op.c ? values[op.ra] & 0x3fffc : -1; break; } @@ -1017,7 +1017,7 @@ std::vector spu_recompiler_base::block(const be_t* ls, u32 entry_point { const u32 r2 = op.ra == 1 ? +op.rb : +op.ra; - if (test(vflags[r2], vf::is_const) && (values[r2] % 16) == 0) + if (vflags[r2] & vf::is_const && (values[r2] % 16) == 0) { break; } diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index b82cf5b63e..780f95520e 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -521,7 +521,7 @@ void SPUThread::cpu_task() if (jit) { - while (LIKELY(!test(state) || !check_state())) + while (LIKELY(!state || !check_state())) { jit_dispatcher[pc / 4](*this, vm::_ptr(offset), nullptr); } @@ -547,7 +547,7 @@ void SPUThread::cpu_task() while (true) { - if (UNLIKELY(test(state))) + if (UNLIKELY(state)) { if (check_state()) return; @@ -594,7 +594,7 @@ void SPUThread::cpu_task() func2 = func4; func3 = func5; - if (UNLIKELY(test(state))) + if (UNLIKELY(state)) { break; } @@ -1093,7 +1093,7 @@ void SPUThread::do_mfc(bool wait) if (args.cmd & MFC_LIST_MASK) { - if (!test(ch_stall_mask, mask)) + if (!(ch_stall_mask & mask)) { if (do_list_transfer(args)) { @@ -1160,7 +1160,7 @@ bool SPUThread::process_mfc_cmd(spu_mfc_cmd args) // Stall infinitely if MFC queue is full while (UNLIKELY(mfc_size >= 16)) { - if (test(state, cpu_flag::stop)) + if (state & cpu_flag::stop) { return false; } @@ -1193,7 +1193,7 @@ bool SPUThread::process_mfc_cmd(spu_mfc_cmd args) while (rdata == data && vm::reservation_acquire(raddr, 128) == rtime) { - if (test(state, cpu_flag::stop)) + if (state & cpu_flag::stop) { break; } @@ -1400,7 +1400,7 @@ bool SPUThread::process_mfc_cmd(spu_mfc_cmd args) { if (LIKELY(args.size <= 0x4000)) { - if (LIKELY(do_dma_check(args) && !test(ch_stall_mask, 1u << args.tag))) + if (LIKELY(do_dma_check(args) && !(ch_stall_mask & 1u << args.tag))) { if (LIKELY(do_list_transfer(args))) { @@ -1558,7 +1558,7 @@ s64 SPUThread::get_ch_value(u32 ch) while (!channel.try_pop(out)) { - if (test(state, cpu_flag::stop)) + if (state & cpu_flag::stop) { return -1; } @@ -1596,7 +1596,7 @@ s64 SPUThread::get_ch_value(u32 ch) return out; } - if (test(state & cpu_flag::stop)) + if (state & cpu_flag::stop) { return -1; } @@ -1700,7 +1700,7 @@ s64 SPUThread::get_ch_value(u32 ch) while (res = get_events(), !res) { - if (test(state, cpu_flag::stop + cpu_flag::dbg_global_stop)) + if (state & (cpu_flag::stop + cpu_flag::dbg_global_stop)) { return -1; } @@ -1713,7 +1713,7 @@ s64 SPUThread::get_ch_value(u32 ch) while (res = get_events(true), !res) { - if (test(state & cpu_flag::stop)) + if (state & cpu_flag::stop) { return -1; } @@ -1753,7 +1753,7 @@ bool SPUThread::set_ch_value(u32 ch, u32 value) { while (!ch_out_intr_mbox.try_push(value)) { - if (test(state & cpu_flag::stop)) + if (state & cpu_flag::stop) { return false; } @@ -1899,7 +1899,7 @@ bool SPUThread::set_ch_value(u32 ch, u32 value) { while (!ch_out_mbox.try_push(value)) { - if (test(state & cpu_flag::stop)) + if (state & cpu_flag::stop) { return false; } @@ -2005,8 +2005,11 @@ bool SPUThread::set_ch_value(u32 ch, u32 value) case MFC_WrListStallAck: { // Reset stall status for specified tag - if (::test_and_reset(ch_stall_mask, 1u << value)) + const u32 tag_mask = 1u << value; + + if (ch_stall_mask & tag_mask) { + ch_stall_mask &= ~tag_mask; do_mfc(true); } @@ -2085,7 +2088,7 @@ bool SPUThread::stop_and_signal(u32 code) // HACK: wait for executable code while (!_ref(pc)) { - if (test(state & cpu_flag::stop)) + if (state & cpu_flag::stop) { return false; } @@ -2141,7 +2144,7 @@ bool SPUThread::stop_and_signal(u32 code) // Check group status, wait if necessary while (group->run_state >= SPU_THREAD_GROUP_STATUS_WAITING && group->run_state <= SPU_THREAD_GROUP_STATUS_SUSPENDED) { - if (test(state & cpu_flag::stop)) + if (state & cpu_flag::stop) { return false; } @@ -2210,7 +2213,7 @@ bool SPUThread::stop_and_signal(u32 code) while (true) { - if (test(state & cpu_flag::stop)) + if (state & cpu_flag::stop) { return false; } diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index ac12cd1599..6f4eab765b 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -1014,13 +1014,13 @@ void lv2_obj::sleep_timeout(named_thread& thread, u64 timeout) auto state = ppu->state.fetch_op([&](auto& val) { - if (!test(val, cpu_flag::signal)) + if (!(val & cpu_flag::signal)) { val += cpu_flag::suspend; } }); - if (test(state, cpu_flag::signal)) + if (state & cpu_flag::signal) { LOG_TRACE(PPU, "sleep() failed (signaled)"); return; @@ -1156,7 +1156,7 @@ void lv2_obj::schedule_all() { const auto target = g_ppu[i]; - if (test(target->state, cpu_flag::suspend)) + if (target->state & cpu_flag::suspend) { LOG_TRACE(PPU, "schedule(): %s", target->id); target->state ^= (cpu_flag::signal + cpu_flag::suspend); diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index 1c9b19ee9f..3cd0093311 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -275,7 +275,7 @@ error_code sys_fs_open(vm::cptr path, s32 flags, vm::ptr fd, s32 mode open_mode = {}; // error } - if (!test(open_mode)) + if (!open_mode) { fmt::throw_exception("sys_fs_open(%s): Invalid or unimplemented flags: %#o" HERE, path, flags); } @@ -307,7 +307,7 @@ error_code sys_fs_open(vm::cptr path, s32 flags, vm::ptr fd, s32 mode if (!file) { - if (test(open_mode & fs::excl) && fs::g_tls_error == fs::error::exist) + if (open_mode & fs::excl && fs::g_tls_error == fs::error::exist) { return not_an_error(CELL_EEXIST); } diff --git a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp index 86ee683de9..77c50e3c06 100644 --- a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp @@ -95,7 +95,7 @@ error_code _sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u32 int } // If interrupt thread is running, it's already established on another interrupt tag - if (!test(it->state & cpu_flag::stop)) + if (!(it->state & cpu_flag::stop)) { error = CELL_EAGAIN; return result; diff --git a/rpcs3/Emu/Cell/lv2/sys_net.cpp b/rpcs3/Emu/Cell/lv2/sys_net.cpp index aae0f1a4f0..33db225afd 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net.cpp @@ -105,7 +105,7 @@ static void network_clear_queue(ppu_thread& ppu) if (sock.queue.empty()) { - sock.events = {}; + sock.events.store({}); } }); } @@ -180,11 +180,11 @@ extern void network_thread_init() events += lv2_socket::poll::error; #endif - if (test(events)) + if (events) { semaphore_lock lock(socklist[i]->mutex); - for (auto it = socklist[i]->queue.begin(); test(events) && it != socklist[i]->queue.end();) + for (auto it = socklist[i]->queue.begin(); events && it != socklist[i]->queue.end();) { if (it->second(events)) { @@ -197,7 +197,7 @@ extern void network_thread_init() if (socklist[i]->queue.empty()) { - socklist[i]->events = {}; + socklist[i]->events.store({}); } } } @@ -226,10 +226,10 @@ extern void network_thread_init() #ifdef _WIN32 verify(HERE), 0 == WSAEventSelect(socklist[i]->socket, _eventh, FD_READ | FD_ACCEPT | FD_CLOSE | FD_WRITE | FD_CONNECT); #else - fds[i].fd = test(events) ? socklist[i]->socket : -1; + fds[i].fd = events ? socklist[i]->socket : -1; fds[i].events = - (test(events, lv2_socket::poll::read) ? POLLIN : 0) | - (test(events, lv2_socket::poll::write) ? POLLOUT : 0) | + (events & lv2_socket::poll::read ? POLLIN : 0) | + (events & lv2_socket::poll::write ? POLLOUT : 0) | 0; fds[i].revents = 0; #endif @@ -278,7 +278,7 @@ s32 sys_net_bnet_accept(ppu_thread& ppu, s32 s, vm::ptr addr, { semaphore_lock lock(sock.mutex); - //if (!test(sock.events, lv2_socket::poll::read)) + //if (!(sock.events & lv2_socket::poll::read)) { #ifdef _WIN32 sock.ev_set &= ~FD_ACCEPT; @@ -302,7 +302,7 @@ s32 sys_net_bnet_accept(ppu_thread& ppu, s32 s, vm::ptr addr, sock.events += lv2_socket::poll::read; sock.queue.emplace_back(ppu.id, [&](bs_t events) -> bool { - if (test(events, lv2_socket::poll::read)) + if (events & lv2_socket::poll::read) { #ifdef _WIN32 sock.ev_set &= ~FD_ACCEPT; @@ -472,7 +472,7 @@ s32 sys_net_bnet_connect(ppu_thread& ppu, s32 s, vm::ptr addr, sock.events += lv2_socket::poll::write; sock.queue.emplace_back(u32{0}, [&sock](bs_t events) -> bool { - if (test(events, lv2_socket::poll::write)) + if (events & lv2_socket::poll::write) { #ifdef _WIN32 sock.ev_set &= ~FD_CONNECT; @@ -503,7 +503,7 @@ s32 sys_net_bnet_connect(ppu_thread& ppu, s32 s, vm::ptr addr, sock.events += lv2_socket::poll::write; sock.queue.emplace_back(ppu.id, [&](bs_t events) -> bool { - if (test(events, lv2_socket::poll::write)) + if (events & lv2_socket::poll::write) { #ifdef _WIN32 sock.ev_set &= ~FD_CONNECT; @@ -886,7 +886,7 @@ s32 sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr buf, u32 len, s3 { semaphore_lock lock(sock.mutex); - //if (!test(sock.events, lv2_socket::poll::read)) + //if (!(sock.events & lv2_socket::poll::read)) { #ifdef _WIN32 if (!(native_flags & MSG_PEEK)) sock.ev_set &= ~FD_READ; @@ -910,7 +910,7 @@ s32 sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr buf, u32 len, s3 sock.events += lv2_socket::poll::read; sock.queue.emplace_back(ppu.id, [&](bs_t events) -> bool { - if (test(events, lv2_socket::poll::read)) + if (events & lv2_socket::poll::read) { #ifdef _WIN32 if (!(native_flags & MSG_PEEK)) sock.ev_set &= ~FD_READ; @@ -1039,7 +1039,7 @@ s32 sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr buf, u32 len, s32 { semaphore_lock lock(sock.mutex); - //if (!test(sock.events, lv2_socket::poll::write)) + //if (!(sock.events & lv2_socket::poll::write)) { #ifdef _WIN32 sock.ev_set &= ~FD_WRITE; @@ -1063,7 +1063,7 @@ s32 sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr buf, u32 len, s32 sock.events += lv2_socket::poll::write; sock.queue.emplace_back(ppu.id, [&](bs_t events) -> bool { - if (test(events, lv2_socket::poll::write)) + if (events & lv2_socket::poll::write) { #ifdef _WIN32 sock.ev_set &= ~FD_WRITE; @@ -1517,13 +1517,13 @@ s32 sys_net_bnet_poll(ppu_thread& ppu, vm::ptr fds, s32 nfds, s3 sock->events += selected; sock->queue.emplace_back(ppu.id, [sock, selected, fds, i, &signaled, &ppu](bs_t events) { - if (test(events, selected)) + if (events & selected) { - if (test(events, selected & lv2_socket::poll::read)) + if (events & selected & lv2_socket::poll::read) fds[i].revents |= SYS_NET_POLLIN; - if (test(events, selected & lv2_socket::poll::write)) + if (events & selected & lv2_socket::poll::write) fds[i].revents |= SYS_NET_POLLOUT; - if (test(events, selected & lv2_socket::poll::error)) + if (events & selected & lv2_socket::poll::error) fds[i].revents |= SYS_NET_POLLERR; signaled++; @@ -1615,7 +1615,7 @@ s32 sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr readf //if (exceptfds && exceptfds->bit(i)) // selected += lv2_socket::poll::error; - if (test(selected)) + if (selected) { selected += lv2_socket::poll::error; } @@ -1628,9 +1628,9 @@ s32 sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr readf { #ifdef _WIN32 bool sig = false; - if (sock->ev_set & (FD_READ | FD_ACCEPT | FD_CLOSE) && test(selected, lv2_socket::poll::read)) + if (sock->ev_set & (FD_READ | FD_ACCEPT | FD_CLOSE) && selected & lv2_socket::poll::read) sig = true, rread.set(i); - if (sock->ev_set & (FD_WRITE | FD_CONNECT) && test(selected, lv2_socket::poll::write)) + if (sock->ev_set & (FD_WRITE | FD_CONNECT) && selected & lv2_socket::poll::write) sig = true, rwrite.set(i); if (sig) @@ -1639,9 +1639,9 @@ s32 sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr readf } #else _fds[i].fd = sock->socket; - if (test(selected, lv2_socket::poll::read)) + if (selected & lv2_socket::poll::read) _fds[i].events |= POLLIN; - if (test(selected, lv2_socket::poll::write)) + if (selected & lv2_socket::poll::write) _fds[i].events |= POLLOUT; #endif } @@ -1691,7 +1691,7 @@ s32 sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr readf //if (exceptfds && exceptfds->bit(i)) // selected += lv2_socket::poll::error; - if (test(selected)) + if (selected) { selected += lv2_socket::poll::error; } @@ -1707,13 +1707,13 @@ s32 sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr readf sock->events += selected; sock->queue.emplace_back(ppu.id, [sock, selected, i, &rread, &rwrite, &rexcept, &signaled, &ppu](bs_t events) { - if (test(events, selected)) + if (events & selected) { - if (test(selected, lv2_socket::poll::read) && test(events, lv2_socket::poll::read + lv2_socket::poll::error)) + if (selected & lv2_socket::poll::read && events & (lv2_socket::poll::read + lv2_socket::poll::error)) rread.set(i); - if (test(selected, lv2_socket::poll::write) && test(events, lv2_socket::poll::write + lv2_socket::poll::error)) + if (selected & lv2_socket::poll::write && events & (lv2_socket::poll::write + lv2_socket::poll::error)) rwrite.set(i); - //if (test(events, selected & lv2_socket::poll::error)) + //if (events & (selected & lv2_socket::poll::error)) // rexcept.set(i); signaled++; diff --git a/rpcs3/Emu/Cell/lv2/sys_net.h b/rpcs3/Emu/Cell/lv2/sys_net.h index 7a408321fa..bc02c27734 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net.h +++ b/rpcs3/Emu/Cell/lv2/sys_net.h @@ -335,7 +335,7 @@ struct lv2_socket final socket_type socket; // Events selected for polling - atomic_t> events{}; + atomic_bs_t events{}; // Non-blocking IO option s32 so_nbio = 0; diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 8574204101..32e54fad4d 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -114,7 +114,7 @@ namespace vm *ptr = nullptr; ptr = nullptr; - if (test(cpu.state, cpu_flag::memory)) + if (cpu.state & cpu_flag::memory) { cpu.state -= cpu_flag::memory; } @@ -221,7 +221,7 @@ namespace vm { while (cpu_thread* ptr = lock) { - if (test(ptr->state, cpu_flag::dbg_global_stop + cpu_flag::exit)) + if (ptr->state & (cpu_flag::dbg_global_stop + cpu_flag::exit)) { break; } diff --git a/rpcs3/Loader/ELF.h b/rpcs3/Loader/ELF.h index de1af42ccd..11de860f87 100644 --- a/rpcs3/Loader/ELF.h +++ b/rpcs3/Loader/ELF.h @@ -243,8 +243,8 @@ public: // Load program headers std::vector _phdrs; - - if (!test(opts, elf_opt::no_programs)) + + if (!(opts & elf_opt::no_programs)) { _phdrs.resize(header.e_phnum); stream.seek(offset + header.e_phoff); @@ -252,7 +252,7 @@ public: return set_error(elf_error::stream_phdrs); } - if (!test(opts, elf_opt::no_sections)) + if (!(opts & elf_opt::no_sections)) { shdrs.resize(header.e_shnum); stream.seek(offset + header.e_shoff); @@ -268,7 +268,7 @@ public: static_cast(progs.back()) = hdr; - if (!test(opts, elf_opt::no_data)) + if (!(opts & elf_opt::no_data)) { progs.back().bin.resize(hdr.p_filesz); stream.seek(offset + hdr.p_offset); diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index b208b3c54e..3ddc90a7ed 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -112,7 +112,7 @@ debugger_frame::debugger_frame(std::shared_ptr settings, QWidget * { if (m_btn_run->text() == RunString && cpu->state.test_and_reset(cpu_flag::dbg_pause)) { - if (!test(cpu->state, cpu_flag::dbg_pause + cpu_flag::dbg_global_pause)) + if (!(cpu->state & (cpu_flag::dbg_pause + cpu_flag::dbg_global_pause))) { cpu->notify(); } @@ -293,7 +293,7 @@ void debugger_frame::UpdateUI() m_last_stat = static_cast(state); DoUpdate(); - if (test(state & cpu_flag::dbg_pause)) + if (state & cpu_flag::dbg_pause) { m_btn_run->setText(RunString); m_btn_step->setEnabled(true); @@ -570,13 +570,13 @@ void debugger_frame::DoStep(bool stepOver) { bool should_step_over = stepOver && cpu->id_type() == 1; - if (test(cpu_flag::dbg_pause, cpu->state.fetch_op([&](bs_t& state) + if (+cpu_flag::dbg_pause & +cpu->state.fetch_op([&](bs_t& state) { if (!should_step_over) state += cpu_flag::dbg_step; state -= cpu_flag::dbg_pause; - }))) + })) { if (should_step_over) { @@ -592,7 +592,7 @@ void debugger_frame::DoStep(bool stepOver) { m_breakpoint_handler->RemoveBreakpoint(next_instruction_pc); } - + m_last_step_over_breakpoint = next_instruction_pc; } diff --git a/rpcs3/rpcs3qt/debugger_list.cpp b/rpcs3/rpcs3qt/debugger_list.cpp index a3b8a454c2..5aa6ca590b 100644 --- a/rpcs3/rpcs3qt/debugger_list.cpp +++ b/rpcs3/rpcs3qt/debugger_list.cpp @@ -90,7 +90,7 @@ void debugger_list::ShowAddress(u32 addr) item(i)->setText((IsBreakpoint(m_pc) ? ">>> " : " ") + qstr(m_disasm->last_opcode)); - if (test(cpu->state & cpu_state_pause) && m_pc == GetPc()) + if (cpu->state & cpu_state_pause && m_pc == GetPc()) { item(i)->setTextColor(m_text_color_pc); item(i)->setBackgroundColor(m_color_pc); diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp index 80939cf43c..7b327a2bc8 100644 --- a/rpcs3/rpcs3qt/log_frame.cpp +++ b/rpcs3/rpcs3qt/log_frame.cpp @@ -94,7 +94,7 @@ struct gui_listener : logs::listener void pop() { - if (const auto head = read->next.exchange(nullptr)) + if (const auto head = read.load()->next.exchange(nullptr)) { delete read.exchange(head); } @@ -102,7 +102,7 @@ struct gui_listener : logs::listener void clear() { - while (read->next) + while (read.load()->next) { pop(); } @@ -502,7 +502,7 @@ void log_frame::UpdateUI() } // Check main logs - while (const auto packet = s_gui_listener.read->next.load()) + while (const auto packet = s_gui_listener.read.load()->next.load()) { // Confirm log level if (packet->sev <= s_gui_listener.enabled)