diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 8b2128196c..2135be0b4d 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -29,6 +29,8 @@ namespace vm using type = T; using addr_type = std::remove_cv_t; + static constexpr bool enable_bitcopy = true; + _ptr_base() = default; _ptr_base(vm::addr_t addr) @@ -226,6 +228,7 @@ namespace vm public: using addr_type = std::remove_cv_t; + static constexpr bool enable_bitcopy = true; _ptr_base() = default; diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index 8d8202fcc2..267e8a475f 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -46,6 +46,8 @@ namespace vm _var_base& operator=(const _var_base&) = delete; + static constexpr bool enable_bitcopy = false; + _var_base() : pointer(A::alloc(sizeof(T), alignof(T))) { @@ -79,6 +81,8 @@ namespace vm _var_base& operator=(const _var_base&) = delete; + static constexpr bool enable_bitcopy = false; + _var_base(u32 count) : pointer(A::alloc(u32{sizeof(T)} * count, alignof(T))) , m_size(u32{sizeof(T)} * count) diff --git a/rpcs3/util/atomic.hpp b/rpcs3/util/atomic.hpp index b6c38250c2..6a11819cd8 100644 --- a/rpcs3/util/atomic.hpp +++ b/rpcs3/util/atomic.hpp @@ -1112,6 +1112,7 @@ protected: public: static constexpr usz align = Align; + static constexpr bool enable_bitcopy = true; atomic_t() noexcept = default; diff --git a/rpcs3/util/endian.hpp b/rpcs3/util/endian.hpp index f7a0542f39..889a7c1f8f 100644 --- a/rpcs3/util/endian.hpp +++ b/rpcs3/util/endian.hpp @@ -180,6 +180,8 @@ namespace stx using under = decltype(int_or_enum()); public: + static constexpr bool enable_bitcopy = true; + se_t() noexcept = default; constexpr se_t(type value) noexcept diff --git a/rpcs3/util/serialization.hpp b/rpcs3/util/serialization.hpp index 79d5845579..2f6d63c555 100644 --- a/rpcs3/util/serialization.hpp +++ b/rpcs3/util/serialization.hpp @@ -33,7 +33,7 @@ namespace utils }; template - concept Bitcopy = (std::is_arithmetic_v) || (std::is_enum_v) || requires (T& obj) + concept Bitcopy = (std::is_arithmetic_v) || (std::is_enum_v) || Integral || requires (T& obj) { std::enable_if_t(std::remove_cv_t::enable_bitcopy)>(); }; @@ -82,6 +82,49 @@ namespace utils return true; } + template requires Integral + bool serialize_vle(T&& value) + { + for (auto i = value;;) + { + const auto i_old = std::exchange(i, i >> 7); + const u8 to_write = static_cast((static_cast(i_old) % 0x80) | (i ? 0x80 : 0)); + raw_serialize(&to_write, 1); + + if (!i) + { + break; + } + } + + return true; + } + + template requires Integral + bool deserialize_vle(T& value) + { + value = {}; + + for (u32 i = 0;; i += 7) + { + u8 byte_data = 0; + + if (!raw_serialize(&byte_data, 1)) + { + return false; + } + + value |= static_cast(byte_data % 0x80) << i; + + if (!(byte_data & 0x80)) + { + break; + } + } + + return true; + } + // (De)serialization function template bool serialize(T& obj) @@ -103,13 +146,7 @@ namespace utils { if (is_writing()) { - for (usz i = obj.size();;) - { - const usz i_old = std::exchange(i, i >> 7); - operator()(static_cast(i_old % 0x80) | (u8{!!i} << 7)); - if (!i) - break; - } + serialize_vle(obj.size()); if constexpr (Bitcopy::value_type>) { @@ -132,22 +169,9 @@ namespace utils obj.clear(); usz size = 0; - - for (u32 i = 0;; i += 7) + if (!deserialize_vle(size)) { - u8 byte_data = 0; - - if (!raw_serialize(&byte_data, 1)) - { - return false; - } - - size |= static_cast(byte_data % 0x80) << i; - - if (!(byte_data >> 7)) - { - break; - } + return false; } obj.resize(size); @@ -175,7 +199,7 @@ namespace utils return true; } - // C-array, std::array, std::span + // C-array, std::array, std::span (span must be supplied with size and address, this function does not modify it) template requires FastRandomAccess && (!ListAlike) && (!Bitcopy) bool serialize(T& obj) { @@ -203,13 +227,7 @@ namespace utils { if (is_writing()) { - for (usz i = obj.size();;) - { - const usz i_old = std::exchange(i, i >> 7); - operator()(static_cast(i_old % 0x80) | (u8{!!i} << 7)); - if (!i) - break; - } + serialize_vle(obj.size()); for (auto&& value : obj) { @@ -225,22 +243,9 @@ namespace utils obj.clear(); usz size = 0; - - for (u32 i = 0;; i += 7) + if (!deserialize_vle(size)) { - u8 byte_data = 0; - - if (!raw_serialize(&byte_data, 1)) - { - return false; - } - - size |= static_cast(byte_data % 0x80) << i; - - if (!(byte_data >> 7)) - { - break; - } + return false; } if constexpr (Reservable) @@ -290,7 +295,7 @@ namespace utils bool operator()(Args&&... args) { return ((AUDIT(!std::is_const_v> || is_writing()) - , serialize(const_cast(static_cast(args)))), ...); + , serialize(const_cast&>(static_cast(args)))), ...); } // Convert serialization manager to deserializion manager (can't go the other way) @@ -305,7 +310,7 @@ namespace utils pos = 0; } - template requires (std::is_constructible_v> || Bitcopy> || + template requires (std::is_copy_constructible_v>) && (std::is_constructible_v> || Bitcopy> || std::is_constructible_v, stx::exact_t> || TupleAlike>) operator T() { diff --git a/rpcs3/util/types.hpp b/rpcs3/util/types.hpp index e814bb2bf5..f2600fe465 100644 --- a/rpcs3/util/types.hpp +++ b/rpcs3/util/types.hpp @@ -520,6 +520,9 @@ concept SignedInt = (std::is_signed_v> && std::is_integral template concept FPInt = std::is_floating_point_v> || std::is_same_v, f16>; +template +concept Integral = std::is_integral_v> || std::is_same_v, u128> || std::is_same_v, s128>; + template constexpr T min_v; diff --git a/rpcs3/util/v128.hpp b/rpcs3/util/v128.hpp index 8707bbc95e..92def16ae3 100644 --- a/rpcs3/util/v128.hpp +++ b/rpcs3/util/v128.hpp @@ -92,6 +92,8 @@ union alignas(16) v128 __m128d vd; #endif + static constexpr bool enable_bitcopy = true; + static v128 from64(u64 _0, u64 _1 = 0) { v128 ret;