diff --git a/Utilities/Atomic.h b/Utilities/Atomic.h index e0656b674b..49948c2744 100644 --- a/Utilities/Atomic.h +++ b/Utilities/Atomic.h @@ -161,11 +161,7 @@ inline u128 sync_fetch_and_add(volatile u128* dest, u128 value) old.lo = dest->lo; old.hi = dest->hi; - u128 _new; - _new.lo = old.lo + value.lo; - _new.hi = old.hi + value.hi + (_new.lo < value.lo); - - if (sync_bool_compare_and_swap(dest, old, _new)) return old; + if (sync_bool_compare_and_swap(dest, old, old + value)) return old; } } @@ -199,11 +195,7 @@ inline u128 sync_fetch_and_sub(volatile u128* dest, u128 value) old.lo = dest->lo; old.hi = dest->hi; - u128 _new; - _new.lo = old.lo - value.lo; - _new.hi = old.hi - value.hi - (old.lo < value.lo); - - if (sync_bool_compare_and_swap(dest, old, _new)) return old; + if (sync_bool_compare_and_swap(dest, old, old - value)) return old; } } @@ -237,11 +229,7 @@ inline u128 sync_fetch_and_or(volatile u128* dest, u128 value) old.lo = dest->lo; old.hi = dest->hi; - u128 _new; - _new.lo = old.lo | value.lo; - _new.hi = old.hi | value.hi; - - if (sync_bool_compare_and_swap(dest, old, _new)) return old; + if (sync_bool_compare_and_swap(dest, old, old | value)) return old; } } @@ -275,11 +263,7 @@ inline u128 sync_fetch_and_and(volatile u128* dest, u128 value) old.lo = dest->lo; old.hi = dest->hi; - u128 _new; - _new.lo = old.lo & value.lo; - _new.hi = old.hi & value.hi; - - if (sync_bool_compare_and_swap(dest, old, _new)) return old; + if (sync_bool_compare_and_swap(dest, old, old & value)) return old; } } @@ -313,11 +297,7 @@ inline u128 sync_fetch_and_xor(volatile u128* dest, u128 value) old.lo = dest->lo; old.hi = dest->hi; - u128 _new; - _new.lo = old.lo ^ value.lo; - _new.hi = old.hi ^ value.hi; - - if (sync_bool_compare_and_swap(dest, old, _new)) return old; + if (sync_bool_compare_and_swap(dest, old, old ^ value)) return old; } } @@ -355,17 +335,17 @@ template struct atomic_storage template using atomic_storage_t = typename atomic_storage::type; -// result wrapper to deal with void result type +// atomic result wrapper; implements special behaviour for void result type template struct atomic_op_result_t { RT result; - template inline atomic_op_result_t(T func, VT& var, Args&&... args) + template atomic_op_result_t(T func, VT& var, Args&&... args) : result(std::move(func(var, std::forward(args)...))) { } - inline RT move() + RT move() { return std::move(result); } @@ -376,13 +356,13 @@ template struct atomic_op_result_t { VT result; - template inline atomic_op_result_t(T func, VT& var, Args&&... args) + template atomic_op_result_t(T func, VT& var, Args&&... args) : result(var) { func(var, std::forward(args)...); } - inline VT move() + VT move() { return std::move(result); } @@ -393,12 +373,12 @@ template struct atomic { RT result; - template inline atomic_op_result_t(RT(CT::*func)(FArgs...), VT& var, Args&&... args) + template atomic_op_result_t(RT(CT::*func)(FArgs...), VT& var, Args&&... args) : result(std::move((var.*func)(std::forward(args)...))) { } - inline RT move() + RT move() { return std::move(result); } @@ -409,18 +389,19 @@ template struct atomic_op_result_t< { VT result; - template inline atomic_op_result_t(void(CT::*func)(FArgs...), VT& var, Args&&... args) + template atomic_op_result_t(void(CT::*func)(FArgs...), VT& var, Args&&... args) : result(var) { (var.*func)(std::forward(args)...); } - inline VT move() + VT move() { return std::move(result); } }; +// Atomic type with lock-free and standard layout guarantees (and appropriate limitations) template class atomic_t { using type = std::remove_cv_t; @@ -466,18 +447,14 @@ public: atomic_t(const atomic_t&) = delete; - atomic_t(atomic_t&&) = delete; - - inline atomic_t(type value) + atomic_t(type value) : m_data(to_subtype(value)) { } atomic_t& operator =(const atomic_t&) = delete; - atomic_t& operator =(atomic_t&&) = delete; - - inline atomic_t& operator =(type value) + atomic_t& operator =(type value) { return write_relaxed(m_data, to_subtype(value)), *this; } @@ -500,31 +477,31 @@ public: } // Atomically compare data with cmp, replace with exch if equal, return previous data value anyway - inline const type compare_and_swap(const type& cmp, const type& exch) volatile + type compare_and_swap(const type& cmp, const type& exch) volatile { return from_subtype(sync_val_compare_and_swap(&m_data, to_subtype(cmp), to_subtype(exch))); } // Atomically compare data with cmp, replace with exch if equal, return true if data was replaced - inline bool compare_and_swap_test(const type& cmp, const type& exch) volatile + bool compare_and_swap_test(const type& cmp, const type& exch) volatile { return sync_bool_compare_and_swap(&m_data, to_subtype(cmp), to_subtype(exch)); } // Atomically replace data with exch, return previous data value - inline const type exchange(const type& exch) volatile + type exchange(const type& exch) volatile { return from_subtype(sync_lock_test_and_set(&m_data, to_subtype(exch))); } // Atomically read data, possibly without memory barrier (not for 128 bit) - inline const type load() const volatile + type load() const volatile { return from_subtype(read_relaxed(m_data)); } // Atomically write data, possibly without memory barrier (not for 128 bit) - inline void store(const type& value) volatile + void store(const type& value) volatile { write_relaxed(m_data, to_subtype(value)); } @@ -550,40 +527,40 @@ public: } // Atomic bitwise OR, returns previous data - inline const type _or(const type& right) volatile + type _or(const type& right) volatile { return from_subtype(sync_fetch_and_or(&m_data, to_subtype(right))); } // Atomic bitwise AND, returns previous data - inline const type _and(const type& right) volatile + type _and(const type& right) volatile { return from_subtype(sync_fetch_and_and(&m_data, to_subtype(right))); } // Atomic bitwise AND NOT (inverts right argument), returns previous data - inline const type _and_not(const type& right) volatile + type _and_not(const type& right) volatile { return from_subtype(sync_fetch_and_and(&m_data, ~to_subtype(right))); } // Atomic bitwise XOR, returns previous data - inline const type _xor(const type& right) volatile + type _xor(const type& right) volatile { return from_subtype(sync_fetch_and_xor(&m_data, to_subtype(right))); } - inline const type operator |=(const type& right) volatile + type operator |=(const type& right) volatile { return from_subtype(sync_fetch_and_or(&m_data, to_subtype(right)) | to_subtype(right)); } - inline const type operator &=(const type& right) volatile + type operator &=(const type& right) volatile { return from_subtype(sync_fetch_and_and(&m_data, to_subtype(right)) & to_subtype(right)); } - inline const type operator ^=(const type& right) volatile + type operator ^=(const type& right) volatile { return from_subtype(sync_fetch_and_xor(&m_data, to_subtype(right)) ^ to_subtype(right)); } @@ -697,9 +674,11 @@ template inline std::enable_if_t using atomic_be_t = atomic_t>; // Atomic BE Type (for PS3 virtual memory) +// Atomic BE Type (for PS3 virtual memory) +template using atomic_be_t = atomic_t>; -template using atomic_le_t = atomic_t>; // Atomic LE Type (for PSV virtual memory) +// Atomic LE Type (for PSV virtual memory) +template using atomic_le_t = atomic_t>; // Algorithm for std::atomic; similar to atomic_t::atomic_op() template> auto atomic_op(std::atomic& var, F func, Args&&... args) -> decltype(atomic_op_result_t::result) diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 916b52eb64..ba2cb3a0da 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -8,34 +8,34 @@ #define IS_LE_MACHINE // only draft -template class masked_array_t // array type accessed as (index ^ M) -{ - T m_data[N]; - -public: - T& operator [](std::size_t index) - { - return m_data[index ^ M]; - } - - const T& operator [](std::size_t index) const - { - return m_data[index ^ M]; - } - - T& at(std::size_t index) - { - return (index ^ M) < N ? m_data[index ^ M] : throw std::out_of_range("Masked array"); - } - - const T& at(std::size_t index) const - { - return (index ^ M) < N ? m_data[index ^ M] : throw std::out_of_range("Masked array"); - } -}; - union v128 { + template class masked_array_t // array type accessed as (index ^ M) + { + T m_data[N]; + + public: + T& operator [](std::size_t index) + { + return m_data[index ^ M]; + } + + const T& operator [](std::size_t index) const + { + return m_data[index ^ M]; + } + + T& at(std::size_t index) + { + return (index ^ M) < N ? m_data[index ^ M] : throw std::out_of_range(__FUNCTION__); + } + + const T& at(std::size_t index) const + { + return (index ^ M) < N ? m_data[index ^ M] : throw std::out_of_range(__FUNCTION__); + } + }; + #ifdef IS_LE_MACHINE template using normal_array_t = masked_array_t; template using reversed_array_t = masked_array_t; @@ -90,12 +90,12 @@ union v128 { } - inline operator bool() const + operator bool() const { return (data & mask) != 0; } - inline bit_element& operator =(const bool right) + bit_element& operator =(const bool right) { if (right) { @@ -108,7 +108,7 @@ union v128 return *this; } - inline bit_element& operator =(const bit_element& right) + bit_element& operator =(const bit_element& right) { if (right) { @@ -144,14 +144,14 @@ union v128 bit_element at(u32 index) { - if (index >= 128) throw std::out_of_range("Bit element"); + if (index >= 128) throw std::out_of_range(__FUNCTION__); return operator[](index); } bool at(u32 index) const { - if (index >= 128) throw std::out_of_range("Bit element"); + if (index >= 128) throw std::out_of_range(__FUNCTION__); return operator[](index); } @@ -320,12 +320,12 @@ union v128 return _u64[0] != right._u64[0] || _u64[1] != right._u64[1]; } - inline bool is_any_1() const // check if any bit is 1 + bool is_any_1() const // check if any bit is 1 { return _u64[0] || _u64[1]; } - inline bool is_any_0() const // check if any bit is 0 + bool is_any_0() const // check if any bit is 0 { return ~_u64[0] || ~_u64[1]; } @@ -486,14 +486,14 @@ template struct se_convert } }; -static struct se_raw_tag_t {} const se_raw{}; +static struct se_raw_tag_t {} constexpr se_raw{}; template class se_t; // se_t with switched endianness template class se_t { - using type = std::remove_cv_t; + using type = typename std::remove_cv::type; using stype = se_storage_t; using storage = se_storage; @@ -506,7 +506,7 @@ template class se_t static_assert(!std::is_enum::value, "se_t<> error: invalid type (enumeration), use integral type instead"); static_assert(alignof(type) == alignof(stype), "se_t<> error: unexpected alignment"); - template::value> struct bool_converter + template struct bool_converter { static inline bool to_bool(const se_t& value) { @@ -514,7 +514,7 @@ template class se_t } }; - template struct bool_converter + template struct bool_converter::value>> { static inline bool to_bool(const se_t& value) { @@ -527,78 +527,78 @@ public: se_t(const se_t& right) = default; - inline se_t(type value) + se_t(type value) : m_data(storage::to(value)) { } // construct directly from raw data (don't use) - inline se_t(const stype& raw_value, const se_raw_tag_t&) + constexpr se_t(const stype& raw_value, const se_raw_tag_t&) : m_data(raw_value) { } - inline type value() const + type value() const { return storage::from(m_data); } // access underlying raw data (don't use) - inline const stype& raw_data() const noexcept + constexpr const stype& raw_data() const noexcept { return m_data; } se_t& operator =(const se_t&) = default; - inline se_t& operator =(type value) + se_t& operator =(type value) { return m_data = storage::to(value), *this; } - inline operator type() const + operator type() const { return storage::from(m_data); } // optimization - explicit inline operator bool() const + explicit operator bool() const { return bool_converter::to_bool(*this); } // optimization - template inline std::enable_if_t operator &=(const se_t& right) + template std::enable_if_t operator &=(const se_t& right) { return m_data &= right.raw_data(), *this; } // optimization - template inline std::enable_if_t::value, se_t&> operator &=(CT right) + template std::enable_if_t::value, se_t&> operator &=(CT right) { return m_data &= storage::to(right), *this; } // optimization - template inline std::enable_if_t operator |=(const se_t& right) + template std::enable_if_t operator |=(const se_t& right) { return m_data |= right.raw_data(), *this; } // optimization - template inline std::enable_if_t::value, se_t&> operator |=(CT right) + template std::enable_if_t::value, se_t&> operator |=(CT right) { return m_data |= storage::to(right), *this; } // optimization - template inline std::enable_if_t operator ^=(const se_t& right) + template std::enable_if_t operator ^=(const se_t& right) { return m_data ^= right.raw_data(), *this; } // optimization - template inline std::enable_if_t::value, se_t&> operator ^=(CT right) + template std::enable_if_t::value, se_t&> operator ^=(CT right) { return m_data ^= storage::to(right), *this; } @@ -607,7 +607,7 @@ public: // se_t with native endianness template class se_t { - using type = std::remove_cv_t; + using type = typename std::remove_cv::type; type m_data; @@ -622,39 +622,39 @@ public: se_t(const se_t&) = default; - inline se_t(type value) + constexpr se_t(type value) : m_data(value) { } - inline type value() const + type value() const { return m_data; } se_t& operator =(const se_t& value) = default; - inline se_t& operator =(type value) + se_t& operator =(type value) { return m_data = value, *this; } - inline operator type() const + operator type() const { return m_data; } - template inline std::enable_if_t::value, se_t&> operator &=(const CT& right) + template std::enable_if_t::value, se_t&> operator &=(const CT& right) { return m_data &= right, *this; } - template inline std::enable_if_t::value, se_t&> operator |=(const CT& right) + template std::enable_if_t::value, se_t&> operator |=(const CT& right) { return m_data |= right, *this; } - template inline std::enable_if_t::value, se_t&> operator ^=(const CT& right) + template std::enable_if_t::value, se_t&> operator ^=(const CT& right) { return m_data ^= right, *this; } @@ -837,107 +837,77 @@ template using be_t = se_t; template using le_t = se_t; #endif -template struct is_be_t : public std::integral_constant + +template struct to_se { + using type = typename std::conditional::value || std::is_enum::value, se_t, T>::type; }; -template struct is_be_t> : public std::integral_constant +template struct to_se::value>> // move const qualifier { + using type = const typename to_se::type; }; -template struct is_be_t : public std::integral_constant::value> +template struct to_se::value && !std::is_const::value>> // move volatile qualifier { + using type = volatile typename to_se::type; }; -template struct is_be_t : public std::integral_constant::value> +template struct to_se { + using type = typename to_se::type[]; }; -// to_be_t helper struct -template struct to_be +template struct to_se { - using type = std::conditional_t::value || std::is_enum::value || std::is_same::value || std::is_same::value, be_t, T>; + using type = typename to_se::type[N]; }; -// be_t if possible, T otherwise -template using to_be_t = typename to_be::type; +template struct to_se { using type = se_t; }; +template struct to_se { using type = se_t; }; +template struct to_se { using type = bool; }; +template struct to_se { using type = char; }; +template struct to_se { using type = u8; }; +template struct to_se { using type = s8; }; -template struct to_be // move const qualifier -{ - using type = const to_be_t; -}; +#ifdef IS_LE_MACHINE +template using to_be_t = typename to_se::type; +template using to_le_t = typename to_se::type; +#else +template using to_be_t = typename to_se::type; +template using to_le_t = typename to_se::type; +#endif -template struct to_be // move volatile qualifier -{ - using type = volatile to_be_t; -}; -template<> struct to_be { using type = void; }; -template<> struct to_be { using type = bool; }; -template<> struct to_be { using type = char; }; -template<> struct to_be { using type = u8; }; -template<> struct to_be { using type = s8; }; - -template struct is_le_t : public std::integral_constant -{ -}; - -template struct is_le_t> : public std::integral_constant -{ -}; - -template struct is_le_t : public std::integral_constant::value> -{ -}; - -template struct is_le_t : public std::integral_constant::value> -{ -}; - -template struct to_le -{ - using type = std::conditional_t::value || std::is_enum::value || std::is_same::value || std::is_same::value, le_t, T>; -}; - -// le_t if possible, T otherwise -template using to_le_t = typename to_le::type; - -template struct to_le // move const qualifier -{ - using type = const to_le_t; -}; - -template struct to_le // move volatile qualifier -{ - using type = volatile to_le_t; -}; - -template<> struct to_le { using type = void; }; -template<> struct to_le { using type = bool; }; -template<> struct to_le { using type = char; }; -template<> struct to_le { using type = u8; }; -template<> struct to_le { using type = s8; }; - -// to_ne_t helper struct -template struct to_ne +template struct to_ne { using type = T; }; template struct to_ne> { - using type = T; + using type = typename std::remove_cv::type; +}; + +template struct to_ne::value>> // move const qualifier +{ + using type = const typename to_ne::type; +}; + +template struct to_ne::value && !std::is_const::value>> // move volatile qualifier +{ + using type = volatile typename to_ne::type; +}; + +template struct to_ne +{ + using type = typename to_ne::type[]; +}; + +template struct to_ne +{ + using type = typename to_ne::type[N]; }; // restore native endianness for T: returns T for be_t or le_t, T otherwise template using to_ne_t = typename to_ne::type; - -template struct to_ne // move const qualifier -{ - using type = const to_ne_t; -}; - -template struct to_ne // move volatile qualifier -{ - using type = volatile to_ne_t; -}; diff --git a/Utilities/BitField.h b/Utilities/BitField.h new file mode 100644 index 0000000000..7c7ad0704f --- /dev/null +++ b/Utilities/BitField.h @@ -0,0 +1,140 @@ +#pragma once + +// BitField access helper class (N bits from I position), intended to be put in union +template class bf_t +{ + // Checks + static_assert(I < sizeof(T) * 8, "bf_t<> error: I out of bounds"); + static_assert(N < sizeof(T) * 8, "bf_t<> error: N out of bounds"); + static_assert(I + N <= sizeof(T) * 8, "bf_t<> error: values out of bounds"); + + // Underlying data type + using type = typename std::remove_cv::type; + + // Underlying value type (native endianness) + using vtype = typename to_ne::type; + + // Mask of size N + constexpr static vtype s_mask = (static_cast(1) << N) - 1; + + // Underlying data member + type m_data; + + // Conversion operator helper (uses SFINAE) + template struct converter {}; + + template struct converter::value>> + { + // Load unsigned value + static inline T2 convert(const type& data) + { + return (data >> I) & s_mask; + } + }; + + template struct converter::value>> + { + // Load signed value (sign-extended) + static inline T2 convert(const type& data) + { + return data << (sizeof(T) * 8 - I - N) >> (sizeof(T) * 8 - N); + } + }; + +public: + // Assignment operator (store bitfield value) + bf_t& operator =(vtype value) + { + m_data = (m_data & ~(s_mask << I)) | (value & s_mask) << I; + return *this; + } + + // Conversion operator (load bitfield value) + operator vtype() const + { + return converter::convert(m_data); + } + + // Get raw data with mask applied + type unshifted() const + { + return (m_data & (s_mask << I)); + } + + // Optimized bool conversion + explicit operator bool() const + { + return unshifted() != 0; + } + + // Postfix increment operator + vtype operator ++(int) + { + vtype result = *this; + *this = result + 1; + return result; + } + + // Prefix increment operator + bf_t& operator ++() + { + return *this = *this + 1; + } + + // Postfix decrement operator + vtype operator --(int) + { + vtype result = *this; + *this = result - 1; + return result; + } + + // Prefix decrement operator + bf_t& operator --() + { + return *this = *this - 1; + } + + // Addition assignment operator + bf_t& operator +=(vtype right) + { + return *this = *this + right; + } + + // Subtraction assignment operator + bf_t& operator -=(vtype right) + { + return *this = *this - right; + } + + // Multiplication assignment operator + bf_t& operator *=(vtype right) + { + return *this = *this * right; + } + + // Bitwise AND assignment operator + bf_t& operator &=(vtype right) + { + m_data &= (right & s_mask) << I; + return *this; + } + + // Bitwise OR assignment operator + bf_t& operator |=(vtype right) + { + m_data |= (right & s_mask) << I; + return *this; + } + + // Bitwise XOR assignment operator + bf_t& operator ^=(vtype right) + { + m_data ^= (right & s_mask) << I; + return *this; + } +}; + +template using bf_be_t = bf_t, I, N>; + +template using bf_le_t = bf_t, I, N>; diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 02e61f5028..8ef949a65e 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -7,8 +7,6 @@ #define GET_API_ERROR static_cast(GetLastError()) -static_assert(fs::file::null == intptr_t(INVALID_HANDLE_VALUE) && fs::dir::null == fs::file::null, "Check fs::file::null definition"); - std::unique_ptr to_wchar(const std::string& source) { const auto length = source.size() + 1; // size + null terminator @@ -443,7 +441,7 @@ bool fs::file::open(const std::string& filename, u32 mode) return false; } - m_fd = (intptr_t)CreateFileW(to_wchar(filename).get(), access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL); + m_fd = (std::intptr_t)CreateFileW(to_wchar(filename).get(), access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL); #else int flags = 0; @@ -598,11 +596,6 @@ u64 fs::file::write(const void* buffer, u64 count) const #endif } -u64 fs::file::write(const std::string &string) const -{ - return write(string.data(), string.size()); -} - u64 fs::file::seek(s64 offset, fsm seek_mode) const { g_tls_error = fse::ok; @@ -659,66 +652,34 @@ u64 fs::file::size() const fs::dir::~dir() { - if (m_dd != null) + if (m_path) { #ifdef _WIN32 - FindClose((HANDLE)m_dd); + if (m_dd != -1) FindClose((HANDLE)m_dd); #else ::closedir((DIR*)m_dd); #endif } } -void fs::dir::import(handle_type dd, const std::string& path) -{ - if (m_dd != null) - { -#ifdef _WIN32 - FindClose((HANDLE)m_dd); -#else - ::closedir((DIR*)m_dd); -#endif - } - - g_tls_error = fse::ok; - - m_dd = dd; - -#ifdef _WIN32 - m_path = to_wchar(path); -#else - m_path.reset(new char[path.size() + 1]); - memcpy(m_path.get(), path.c_str(), path.size() + 1); -#endif -} - bool fs::dir::open(const std::string& dirname) { - if (m_dd != null) - { -#ifdef _WIN32 - FindClose((HANDLE)m_dd); -#else - ::closedir((DIR*)m_dd); -#endif - } + this->close(); g_tls_error = fse::ok; - m_dd = null; - - m_path.reset(); - if (!is_dir(dirname)) { return false; } -#ifdef _WIN32 - m_path = to_wchar(dirname + "/*"); -#else m_path.reset(new char[dirname.size() + 1]); - memcpy(m_path.get(), dirname.c_str(), dirname.size() + 1); + std::memcpy(m_path.get(), dirname.c_str(), dirname.size() + 1); + +#ifdef _WIN32 + m_dd = -1; +#else + m_dd = (std::intptr_t)::opendir(m_path.get()); #endif return true; @@ -728,46 +689,26 @@ bool fs::dir::close() { g_tls_error = fse::ok; - if (m_dd == null) + if (!m_path) { - if (m_path) - { - m_path.reset(); - return true; - } - else - { - return false; - } + return false; } - auto dd = m_dd; - m_dd = null; - m_path.reset(); #ifdef _WIN32 - return FindClose((HANDLE)dd); + CHECK_ASSERTION(m_dd == -1 || FindClose((HANDLE)m_dd)); #else - return !::closedir((DIR*)dd); + CHECK_ASSERTION(!::closedir((DIR*)m_dd)); #endif + + return true; } -bool fs::dir::get_first(std::string& name, stat_t& info) +bool fs::dir::read(std::string& name, stat_t& info) { - if (m_dd != null) // close previous handle - { -#ifdef _WIN32 - FindClose((HANDLE)m_dd); -#else - ::closedir((DIR*)m_dd); -#endif - } - g_tls_error = fse::ok; - m_dd = null; - if (!m_path) { return false; @@ -776,43 +717,16 @@ bool fs::dir::get_first(std::string& name, stat_t& info) #ifdef _WIN32 WIN32_FIND_DATAW found; - m_dd = (intptr_t)FindFirstFileW(m_path.get(), &found); - - if (m_dd == null) + if (m_dd == -1) { - return false; + m_dd = (std::intptr_t)FindFirstFileW(to_wchar(m_path.get() + "/*"s).get(), &found); + + if (m_dd == -1) + { + return false; + } } - - to_utf8(name, found.cFileName); - - info.is_directory = (found.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - info.is_writable = (found.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0; - info.size = ((u64)found.nFileSizeHigh << 32) | (u64)found.nFileSizeLow; - info.atime = to_time_t(found.ftLastAccessTime); - info.mtime = to_time_t(found.ftLastWriteTime); - info.ctime = to_time_t(found.ftCreationTime); - - return true; -#else - m_dd = (intptr_t)::opendir(m_path.get()); - - return get_next(name, info); -#endif -} - -bool fs::dir::get_next(std::string& name, stat_t& info) -{ - g_tls_error = fse::ok; - - if (m_dd == null) - { - return false; - } - -#ifdef _WIN32 - WIN32_FIND_DATAW found; - - if (!FindNextFileW((HANDLE)m_dd, &found)) + else if (!FindNextFileW((HANDLE)m_dd, &found)) { return false; } diff --git a/Utilities/File.h b/Utilities/File.h index 38c7bf4140..a963fd79f9 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -26,16 +26,6 @@ enum class fse : u32 // filesystem (file or dir) error invalid_arguments, }; -enum : u32 // obsolete flags -{ - o_read = fom::read, - o_write = fom::write, - o_append = fom::append, - o_create = fom::create, - o_trunc = fom::trunc, - o_excl = fom::excl, -}; - namespace fs { thread_local extern fse g_tls_error; @@ -50,95 +40,156 @@ namespace fs s64 ctime; }; + // Get file information bool stat(const std::string& path, stat_t& info); + + // Check whether a file or a directory exists (not recommended, use is_file() or is_dir() instead) bool exists(const std::string& path); + + // Check whether the file exists and is NOT a directory bool is_file(const std::string& file); + + // Check whether the directory exists and is NOT a file bool is_dir(const std::string& dir); + + // Delete empty directory bool remove_dir(const std::string& dir); + + // Create directory bool create_dir(const std::string& dir); + + // Create directories bool create_path(const std::string& path); + + // Rename (move) file or directory bool rename(const std::string& from, const std::string& to); + + // Copy file contents bool copy_file(const std::string& from, const std::string& to, bool overwrite); + + // Delete file bool remove_file(const std::string& file); + + // Change file size (possibly appending zeros) bool truncate_file(const std::string& file, u64 length); - struct file final + class file final { using handle_type = std::intptr_t; - static const handle_type null = -1; + constexpr static handle_type null = -1; - private: handle_type m_fd = null; public: file() = default; + + explicit file(const std::string& filename, u32 mode = fom::read) + { + open(filename, mode); + } + + file(file&& other) + : m_fd(other.m_fd) + { + other.m_fd = null; + } + + file& operator =(file&& right) + { + std::swap(m_fd, right.m_fd); + return *this; + } + ~file(); - explicit file(const std::string& filename, u32 mode = fom::read) { open(filename, mode); } - file(const file&) = delete; - file(file&&) = delete; // possibly TODO + // Check whether the handle is valid (opened file) + bool is_opened() const + { + return m_fd != null; + } - file& operator =(const file&) = delete; - file& operator =(file&&) = delete; // possibly TODO - - operator bool() const { return m_fd != null; } - - void import(handle_type fd) { this->~file(); m_fd = fd; } + // Check whether the handle is valid (opened file) + explicit operator bool() const + { + return is_opened(); + } + // Open specified file with specified mode bool open(const std::string& filename, u32 mode = fom::read); - bool is_opened() const { return m_fd != null; } - bool trunc(u64 size) const; // change file size (possibly appending zero bytes) - bool stat(stat_t& info) const; // get file info + + // Change file size (possibly appending zero bytes) + bool trunc(u64 size) const; + + // Get file information + bool stat(stat_t& info) const; + + // Close the file explicitly (destructor automatically closes the file) bool close(); + // Read the data from the file and return the amount of data written in buffer u64 read(void* buffer, u64 count) const; + + // Write the data to the file and return the amount of data actually written u64 write(const void* buffer, u64 count) const; - u64 write(const std::string &string) const; + + // Write std::string + u64 write(const std::string& string) const { return write(string.data(), string.size()); } + + // Move file pointer u64 seek(s64 offset, fsm seek_mode = fsm::begin) const; + + // Get file size u64 size() const; }; - struct dir final + class dir final { -#ifdef _WIN32 - using handle_type = intptr_t; - using name_type = std::unique_ptr; - - static const handle_type null = -1; -#else - using handle_type = intptr_t; - using name_type = std::unique_ptr; - - static const handle_type null = 0; -#endif - - private: - handle_type m_dd = null; - name_type m_path; + std::unique_ptr m_path; + std::intptr_t m_dd; // handle (aux) public: dir() = default; + + explicit dir(const std::string& dirname) + { + open(dirname); + } + + dir(dir&& other) + : m_dd(other.m_dd) + , m_path(std::move(other.m_path)) + { + } + + dir& operator =(dir&& right) + { + m_dd = right.m_dd; + m_path = std::move(right.m_path); + return *this; + } + ~dir(); - explicit dir(const std::string& dirname) { open(dirname); } - dir(const dir&) = delete; - dir(dir&&) = delete; // possibly TODO + // Check whether the handle is valid (opened directory) + bool is_opened() const + { + return m_path.operator bool(); + } - dir& operator =(const dir&) = delete; - dir& operator =(dir&&) = delete; // possibly TODO - - operator bool() const { return m_path.operator bool(); } - - void import(handle_type dd, const std::string& path); + // Check whether the handle is valid (opened directory) + explicit operator bool() const + { + return is_opened(); + } + // Open specified directory bool open(const std::string& dirname); - bool is_opened() const { return *this; } + + // Close the directory explicitly (destructor automatically closes the directory) bool close(); - bool get_first(std::string& name, stat_t& info); - //bool get_first(std::string& name); - bool get_next(std::string& name, stat_t& info); - //bool get_next(std::string& name); + // Get next directory entry (UTF-8 name and file stat) + bool read(std::string& name, stat_t& info); }; } diff --git a/Utilities/GNU.h b/Utilities/GNU.h index c8d5c74cb4..fd41c69269 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -45,16 +45,16 @@ #define _byteswap_uint64(x) __builtin_bswap64(x) #define INFINITE 0xFFFFFFFF -inline uint64_t __umulh(uint64_t a, uint64_t b) +inline std::uint64_t __umulh(std::uint64_t a, std::uint64_t b) { - uint64_t result; + std::uint64_t result; __asm__("mulq %[b]" : "=d" (result) : [a] "a" (a), [b] "rm" (b)); return result; } -inline int64_t __mulh(int64_t a, int64_t b) +inline std::int64_t __mulh(std::int64_t a, std::int64_t b) { - int64_t result; + std::int64_t result; __asm__("imulq %[b]" : "=d" (result) : [a] "a" (a), [b] "rm" (b)); return result; } @@ -81,202 +81,186 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp); #endif /* __GNUG__ */ #if defined(_MSC_VER) + // Unsigned 128-bit integer implementation -struct alignas(16) uint128_t +struct alignas(16) u128 { - uint64_t lo, hi; + std::uint64_t lo, hi; - uint128_t() = default; + u128() = default; - uint128_t(uint64_t l) + u128(const u128&) = default; + + u128(std::uint64_t l) : lo(l) , hi(0) { } - [[deprecated("Not implemented")]] inline uint128_t operator +(const uint128_t& r) const + u128 operator +(const u128& r) const { - return{}; - } - - inline uint128_t operator +(uint64_t r) const - { - uint128_t value; - value.lo = lo + r; - value.hi = value.lo < r ? hi + 1 : hi; + u128 value; + _addcarry_u64(_addcarry_u64(0, r.lo, lo, &value.lo), r.hi, hi, &value.hi); return value; } - [[deprecated("Not implemented")]] inline uint128_t operator -(const uint128_t& r) const + friend u128 operator +(const u128& l, std::uint64_t r) { - return{}; - } - - inline uint128_t operator -(uint64_t r) const - { - uint128_t value; - value.lo = lo - r; - value.hi = lo < r ? hi - 1 : hi; + u128 value; + _addcarry_u64(_addcarry_u64(0, r, l.lo, &value.lo), l.hi, 0, &value.hi); return value; } - inline uint128_t operator +() const + friend u128 operator +(std::uint64_t l, const u128& r) + { + u128 value; + _addcarry_u64(_addcarry_u64(0, r.lo, l, &value.lo), 0, r.hi, &value.hi); + return value; + } + + u128 operator -(const u128& r) const + { + u128 value; + _subborrow_u64(_subborrow_u64(0, r.lo, lo, &value.lo), r.hi, hi, &value.hi); + return value; + } + + friend u128 operator -(const u128& l, std::uint64_t r) + { + u128 value; + _subborrow_u64(_subborrow_u64(0, r, l.lo, &value.lo), 0, l.hi, &value.hi); + return value; + } + + friend u128 operator -(std::uint64_t l, const u128& r) + { + u128 value; + _subborrow_u64(_subborrow_u64(0, r.lo, l, &value.lo), r.hi, 0, &value.hi); + return value; + } + + u128 operator +() const { return *this; } - inline uint128_t operator -() const + u128 operator -() const { - uint128_t value; - value.lo = ~lo + 1; - value.hi = lo ? ~hi : ~hi + 1; + u128 value; + _subborrow_u64(_subborrow_u64(0, lo, 0, &value.lo), hi, 0, &value.hi); return value; } - inline uint128_t& operator ++() + u128& operator ++() { - if (!++lo) ++hi; + _addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi); return *this; } - inline uint128_t operator ++(int) + u128 operator ++(int) { - uint128_t value = *this; - if (!++lo) ++hi; + u128 value = *this; + _addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi); return value; } - inline uint128_t& operator --() + u128& operator --() { - if (!lo--) hi--; + _subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi); return *this; } - inline uint128_t operator --(int) + u128 operator --(int) { - uint128_t value = *this; - if (!lo--) hi--; + u128 value = *this; + _subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi); return value; } - inline uint128_t operator ~() const + u128 operator ~() const { - uint128_t value; + u128 value; value.lo = ~lo; value.hi = ~hi; return value; } - inline uint128_t operator &(const uint128_t& r) const + u128 operator &(const u128& r) const { - uint128_t value; + u128 value; value.lo = lo & r.lo; value.hi = hi & r.hi; return value; } - inline uint128_t operator |(const uint128_t& r) const + u128 operator |(const u128& r) const { - uint128_t value; + u128 value; value.lo = lo | r.lo; value.hi = hi | r.hi; return value; } - inline uint128_t operator ^(const uint128_t& r) const + u128 operator ^(const u128& r) const { - uint128_t value; + u128 value; value.lo = lo ^ r.lo; value.hi = hi ^ r.hi; return value; } - [[deprecated("Not implemented")]] inline uint128_t& operator +=(const uint128_t& r) + u128& operator +=(const u128& r) { + _addcarry_u64(_addcarry_u64(0, r.lo, lo, &lo), r.hi, hi, &hi); return *this; } - inline uint128_t& operator +=(uint64_t r) + u128& operator +=(uint64_t r) { - hi = (lo += r) < r ? hi + 1 : hi; + _addcarry_u64(_addcarry_u64(0, r, lo, &lo), 0, hi, &hi); return *this; } - [[deprecated("Not implemented")]] inline uint128_t& operator -=(const uint128_t& r) - { - return *this; - } - - inline uint128_t& operator &=(const uint128_t& r) + u128& operator &=(const u128& r) { lo &= r.lo; hi &= r.hi; return *this; } - inline uint128_t& operator |=(const uint128_t& r) + u128& operator |=(const u128& r) { lo |= r.lo; hi |= r.hi; return *this; } - inline uint128_t& operator ^=(const uint128_t& r) + u128& operator ^=(const u128& r) { lo ^= r.lo; hi ^= r.hi; return *this; } }; - -using __uint128_t = uint128_t; #endif -inline uint32_t cntlz32(uint32_t arg) +inline std::uint32_t cntlz32(std::uint32_t arg) { #if defined(_MSC_VER) unsigned long res; - if (!_BitScanReverse(&res, arg)) - { - return 32; - } - else - { - return res ^ 31; - } + return _BitScanReverse(&res, arg) ? res ^ 31 : 32; #else - if (arg) - { - return __builtin_clzll((uint64_t)arg) - 32; - } - else - { - return 32; - } + return arg ? __builtin_clzll(arg) - 32 : 32; #endif } -inline uint64_t cntlz64(uint64_t arg) +inline std::uint64_t cntlz64(std::uint64_t arg) { #if defined(_MSC_VER) unsigned long res; - if (!_BitScanReverse64(&res, arg)) - { - return 64; - } - else - { - return res ^ 63; - } + return _BitScanReverse64(&res, arg) ? res ^ 63 : 64; #else - if (arg) - { - return __builtin_clzll(arg); - } - else - { - return 64; - } + return arg ? __builtin_clzll(arg) : 64; #endif } diff --git a/Utilities/Log.h b/Utilities/Log.h index f04f2323cb..a0e3b268b9 100644 --- a/Utilities/Log.h +++ b/Utilities/Log.h @@ -79,7 +79,6 @@ namespace Log LogChannel(); LogChannel(const std::string& name); LogChannel(LogChannel& other) = delete; - LogChannel& operator = (LogChannel& other) = delete; void log(const LogMessage &msg); void addListener(std::shared_ptr listener); void removeListener(std::shared_ptr listener); diff --git a/Utilities/SleepQueue.h b/Utilities/SleepQueue.h index ad6404e4fe..db54602038 100644 --- a/Utilities/SleepQueue.h +++ b/Utilities/SleepQueue.h @@ -27,19 +27,19 @@ public: ~sleep_queue_entry_t(); // add thread to the sleep queue - inline void enter() + void enter() { add_entry(); } // remove thread from the sleep queue - inline void leave() + void leave() { remove_entry(); } // check whether the thread exists in the sleep queue - inline explicit operator bool() const + explicit operator bool() const { return find(); } diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 74a571db55..f98e20f39e 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -15,9 +15,13 @@ std::string v128::to_xyzw() const return fmt::format("x: %g y: %g z: %g w: %g", _f[3], _f[2], _f[1], _f[0]); } -std::string fmt::to_hex(u64 value, size_t count) +std::string fmt::to_hex(u64 value, u64 count) { - assert(count - 1 < 16); + if (count - 1 >= 16) + { + throw EXCEPTION("Invalid count: 0x%llx", count); + } + count = std::max(count, 16 - cntlz64(value) / 4); char res[16] = {}; diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 5f1376860c..efaf02f66f 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -141,7 +141,7 @@ namespace fmt return src; } - std::string to_hex(u64 value, size_t count = 1); + std::string to_hex(u64 value, u64 count = 1); std::string to_udec(u64 value); std::string to_sdec(s64 value); diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 100bf3d7e4..95906075f8 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -901,7 +901,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) return false; } - memcpy(vm::priv_ptr(addr), XMMREG(context, reg - X64R_XMM0), 16); + std::memcpy(vm::base_priv(addr), XMMREG(context, reg - X64R_XMM0), 16); break; } @@ -911,7 +911,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) return false; } - memcpy(vm::priv_ptr(addr), ®_value, d_size); + std::memcpy(vm::base_priv(addr), ®_value, d_size); break; } case X64OP_MOVS: @@ -922,7 +922,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) return false; } - if (vm::get_ptr(addr) != (void*)RDI(context)) + if (vm::base(addr) != (void*)RDI(context)) { LOG_ERROR(MEMORY, "X64OP_MOVS: rdi=0x%llx, rsi=0x%llx, addr=0x%x", (u64)RDI(context), (u64)RSI(context), addr); return false; @@ -935,8 +935,8 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) u64 value; // copy data - memcpy(&value, (void*)RSI(context), d_size); - memcpy(vm::priv_ptr(a_addr), &value, d_size); + std::memcpy(&value, (void*)RSI(context), d_size); + std::memcpy(vm::base_priv(a_addr), &value, d_size); // shift pointers if (EFLAGS(context) & 0x400 /* direction flag */) @@ -977,7 +977,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) return false; } - if (vm::get_ptr(addr) != (void*)RDI(context)) + if (vm::base(addr) != (void*)RDI(context)) { LOG_ERROR(MEMORY, "X64OP_STOS: rdi=0x%llx, addr=0x%x", (u64)RDI(context), addr); return false; @@ -994,7 +994,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) while (a_addr >> 12 == addr >> 12) { // fill data with value - memcpy(vm::priv_ptr(a_addr), &value, d_size); + std::memcpy(vm::base_priv(a_addr), &value, d_size); // shift pointers if (EFLAGS(context) & 0x400 /* direction flag */) @@ -1035,10 +1035,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) switch (d_size) { - case 1: reg_value = vm::priv_ref>(addr).exchange((u8)reg_value); break; - case 2: reg_value = vm::priv_ref>(addr).exchange((u16)reg_value); break; - case 4: reg_value = vm::priv_ref>(addr).exchange((u32)reg_value); break; - case 8: reg_value = vm::priv_ref>(addr).exchange((u64)reg_value); break; + case 1: reg_value = sync_lock_test_and_set((u8*)vm::base_priv(addr), (u8)reg_value); break; + case 2: reg_value = sync_lock_test_and_set((u16*)vm::base_priv(addr), (u16)reg_value); break; + case 4: reg_value = sync_lock_test_and_set((u32*)vm::base_priv(addr), (u32)reg_value); break; + case 8: reg_value = sync_lock_test_and_set((u64*)vm::base_priv(addr), (u64)reg_value); break; default: return false; } @@ -1058,10 +1058,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) switch (d_size) { - case 1: old_value = vm::priv_ref>(addr).compare_and_swap((u8)cmp_value, (u8)reg_value); break; - case 2: old_value = vm::priv_ref>(addr).compare_and_swap((u16)cmp_value, (u16)reg_value); break; - case 4: old_value = vm::priv_ref>(addr).compare_and_swap((u32)cmp_value, (u32)reg_value); break; - case 8: old_value = vm::priv_ref>(addr).compare_and_swap((u64)cmp_value, (u64)reg_value); break; + case 1: old_value = sync_val_compare_and_swap((u8*)vm::base_priv(addr), (u8)cmp_value, (u8)reg_value); break; + case 2: old_value = sync_val_compare_and_swap((u16*)vm::base_priv(addr), (u16)cmp_value, (u16)reg_value); break; + case 4: old_value = sync_val_compare_and_swap((u32*)vm::base_priv(addr), (u32)cmp_value, (u32)reg_value); break; + case 8: old_value = sync_val_compare_and_swap((u64*)vm::base_priv(addr), (u64)cmp_value, (u64)reg_value); break; default: return false; } @@ -1081,10 +1081,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) switch (d_size) { - case 1: value = vm::priv_ref>(addr) &= (u8)value; break; - case 2: value = vm::priv_ref>(addr) &= (u16)value; break; - case 4: value = vm::priv_ref>(addr) &= (u32)value; break; - case 8: value = vm::priv_ref>(addr) &= value; break; + case 1: value &= sync_fetch_and_and((u8*)vm::base_priv(addr), (u8)value); break; + case 2: value &= sync_fetch_and_and((u16*)vm::base_priv(addr), (u16)value); break; + case 4: value &= sync_fetch_and_and((u32*)vm::base_priv(addr), (u32)value); break; + case 8: value &= sync_fetch_and_and((u64*)vm::base_priv(addr), (u64)value); break; default: return false; } @@ -1114,7 +1114,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) { - const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr; + const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::base(0); const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0; if (u == EXCEPTION_ACCESS_VIOLATION && (u32)addr64 == addr64) @@ -1122,12 +1122,14 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) throw EXCEPTION("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64); } - //__int2c(); // if it crashed there, check the callstack for the actual source of the crash + __debugbreak(); // if it reached there, there should probably be a possibility to check the callstack + + throw EXCEPTION("Fatal error occured %s location %p at %p", is_writing ? "writing" : "reading", pExp->ExceptionRecord->ExceptionInformation[1], pExp->ExceptionRecord->ExceptionAddress); } const PVOID exception_handler = (atexit([]{ RemoveVectoredExceptionHandler(exception_handler); }), AddVectoredExceptionHandler(1, [](PEXCEPTION_POINTERS pExp) -> LONG { - const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr; + const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::base(0); const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0; if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && @@ -1154,7 +1156,7 @@ const auto exception_filter = SetUnhandledExceptionFilter([](PEXCEPTION_POINTERS void signal_handler(int sig, siginfo_t* info, void* uct) { - const u64 addr64 = (u64)info->si_addr - (u64)vm::g_base_addr; + const u64 addr64 = (u64)info->si_addr - (u64)vm::base(0); #ifdef __APPLE__ const bool is_writing = ((ucontext_t*)uct)->uc_mcontext->__es.__err & 0x2; @@ -1203,14 +1205,14 @@ std::string thread_ctrl_t::get_name() const named_thread_t::named_thread_t(std::function name, std::function func) { - start(std::move(name), func); + start(std::move(name), std::move(func)); } named_thread_t::~named_thread_t() { if (m_thread) { - std::printf("Fatal: thread '%s' is neither joined nor detached\n", this->get_name().c_str()); + std::printf("Fatal: thread neither joined nor detached\n"); std::terminate(); } } diff --git a/Utilities/Thread.h b/Utilities/Thread.h index d1d73dba92..34b65e4763 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -2,20 +2,20 @@ const class thread_ctrl_t* get_current_thread_ctrl(); -// named thread control class +// Named thread control class class thread_ctrl_t final { friend class named_thread_t; template friend void current_thread_register_atexit(T); - // thread handler + // Thread handler std::thread m_thread; - // name getter + // Name getter const std::function m_name; - // functions executed at thread exit (temporarily) + // Functions executed at thread exit (temporarily) std::vector> m_atexit; public: @@ -24,11 +24,13 @@ public: { } - // get thread name + thread_ctrl_t(const thread_ctrl_t&) = delete; + + // Get thread name std::string get_name() const; }; -// register function at thread exit (temporarily) +// Register function at thread exit (temporarily) template void current_thread_register_atexit(T func) { extern thread_local thread_ctrl_t* g_tls_this_thread; @@ -38,73 +40,69 @@ template void current_thread_register_atexit(T func) class named_thread_t { - // pointer to managed resource (shared with actual thread) + // Pointer to managed resource (shared with actual thread) std::shared_ptr m_thread; public: - // thread mutex for external use + // Thread mutex for external use std::mutex mutex; - // thread condition variable for external use + // Thread condition variable for external use std::condition_variable cv; public: - // initialize in empty state + // Initialize in empty state named_thread_t() = default; - // create named thread + // Create named thread named_thread_t(std::function name, std::function func); - // destructor, will terminate if thread is neither joined nor detached - virtual ~named_thread_t(); - + // Deleted copy/move constructors + copy/move operators named_thread_t(const named_thread_t&) = delete; - named_thread_t& operator =(const named_thread_t&) = delete; + // Destructor, calls std::terminate if the thread is neither joined nor detached + virtual ~named_thread_t(); public: - // get thread name + // Get thread name std::string get_name() const; - // create named thread (current state must be empty) + // Create named thread (current state must be empty) void start(std::function name, std::function func); - // detach thread -> empty state + // Detach thread -> empty state void detach(); - // join thread -> empty state + // Join thread -> empty state void join(); - // check if not empty + // Check whether the thread is not in "empty state" bool joinable() const { return m_thread.operator bool(); } - // check whether it is the current running thread + // Check whether it is the currently running thread bool is_current() const; - // get internal thread pointer + // Get internal thread pointer const thread_ctrl_t* get_thread_ctrl() const { return m_thread.get(); } }; -class autojoin_thread_t final : private named_thread_t +// Wrapper for named_thread_t, joins automatically in the destructor +class autojoin_thread_t final { -public: - using named_thread_t::mutex; - using named_thread_t::cv; + named_thread_t m_thread; public: - autojoin_thread_t() = delete; - autojoin_thread_t(std::function name, std::function func) + : m_thread(std::move(name), std::move(func)) { - start(std::move(name), std::move(func)); } - virtual ~autojoin_thread_t() override - { - join(); - } + autojoin_thread_t(const autojoin_thread_t&) = delete; - using named_thread_t::is_current; + ~autojoin_thread_t() noexcept(false) // Allow exceptions + { + m_thread.join(); + } }; extern const std::function SQUEUE_ALWAYS_EXIT; diff --git a/Utilities/VirtualMemory.cpp b/Utilities/VirtualMemory.cpp index 54e6c6adb4..05614b714b 100644 --- a/Utilities/VirtualMemory.cpp +++ b/Utilities/VirtualMemory.cpp @@ -38,4 +38,4 @@ namespace memory_helper munmap(pointer, size); #endif } -} \ No newline at end of file +} diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index 5a0dcd62aa..b2400f509a 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -61,6 +61,8 @@ static bool CheckHeader(const fs::file& pkg_f, PKGHeader& header) // PKG Decryption bool UnpackPKG(const fs::file& pkg_f, const std::string& dir, volatile f64& progress) { + const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB + // Save current file offset (probably zero) const u64 start_offset = pkg_f.seek(0, fsm::cur); @@ -108,13 +110,9 @@ bool UnpackPKG(const fs::file& pkg_f, const std::string& dir, volatile f64& prog // Initialize "debug key" for current position input[7] = offset / 16 + i; - union - { - u8 _key[0x14]; - u128 key; - }; + u128 key; - sha1(reinterpret_cast(input), sizeof(input), _key); + sha1(reinterpret_cast(input), sizeof(input), reinterpret_cast(&key)); buf[i] ^= key; } @@ -133,13 +131,9 @@ bool UnpackPKG(const fs::file& pkg_f, const std::string& dir, volatile f64& prog // Increment "release key" for every block for (u64 i = 0; i < blocks; i++, input++) { - union - { - u8 _key[16]; - u128 key; - }; + u128 key; - aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast(&input), _key); + aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast(&input), reinterpret_cast(&key)); buf[i] ^= key; } diff --git a/rpcs3/Crypto/unpkg.h b/rpcs3/Crypto/unpkg.h index 4983525ebf..8bdfe04b06 100644 --- a/rpcs3/Crypto/unpkg.h +++ b/rpcs3/Crypto/unpkg.h @@ -3,7 +3,6 @@ // Constants enum { - BUF_SIZE = 8192 * 1024, // 8 MB PKG_HEADER_SIZE = 0xC0, //sizeof(pkg_header) + sizeof(pkg_unk_checksum) PKG_HEADER_SIZE2 = 0x280, }; @@ -58,4 +57,4 @@ struct PKGEntry be_t pad; // Padding (zeros) }; -bool UnpackPKG(const struct fs::file& pkg_f, const std::string& dir, volatile f64& progress); +bool UnpackPKG(const class fs::file& pkg_f, const std::string& dir, volatile f64& progress); diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index eca7bb67cd..3d8f6bc77e 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -1963,7 +1963,7 @@ void ARMv7_instrs::LDM(ARMv7Context& context, const ARMv7Code code, const ARMv7_ if (ConditionPassed(context, cond)) { - auto memory = vm::ptr::make(context.read_gpr(n)); + vm::ptr memory{ context.read_gpr(n), vm::addr }; for (u32 i = 0; i < 16; i++) { @@ -3540,7 +3540,7 @@ void ARMv7_instrs::PUSH(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (ConditionPassed(context, cond)) { - auto memory = vm::ptr::make(context.SP); + vm::ptr memory{ context.SP, vm::addr }; for (u32 i = 15; ~i; i--) { diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index fd9c4ba632..c104182a52 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -53,8 +53,8 @@ u32 armv7_get_tls(u32 thread) if (g_armv7_tls_owners[i].compare_exchange_strong(old, thread)) { const u32 addr = g_armv7_tls_start + i * Emu.GetTLSMemsz(); // get TLS address - std::memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image - std::memset(vm::get_ptr(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros + std::memcpy(vm::base(addr), vm::base(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image + std::memset(vm::base(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros return addr; } } @@ -290,7 +290,7 @@ cpu_thread& armv7_thread::args(std::initializer_list values) } argv = vm::alloc(argv_size, vm::main); // allocate arg list - memcpy(vm::get_ptr(argv), argv_data.data(), argv_size); // copy arg list + std::memcpy(vm::base(argv), argv_data.data(), argv_size); // copy arg list return *this; } diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index eb403ddf9f..3354d3c779 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -66,7 +66,7 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::cptr pArgBlock) // push arg block onto the stack const u32 pos = (thread->SP -= argSize); - memcpy(vm::get_ptr(pos), pArgBlock.get_ptr(), argSize); + std::memcpy(vm::base(pos), pArgBlock.get_ptr(), argSize); // set SceKernelThreadEntry function arguments thread->GPR[0] = argSize; diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index bac1572107..4c06ff6476 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -128,7 +128,7 @@ std::string armv7_fmt(ARMv7Context& context, vm::cptr fmt, u32 g_count, u3 case 's': { // string - auto string = vm::cptr::make(context.get_next_gpr_arg(g_count, f_count, v_count)); + const vm::cptr string{ context.get_next_gpr_arg(g_count, f_count, v_count), vm::addr }; if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break; diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h index 87fe194bae..97e98ffd75 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.h +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -35,7 +35,7 @@ public: } // check if UID is potentially valid (will return true even if the object doesn't exist) - inline static bool check(s32 uid) + static inline bool check(s32 uid) { const psv_uid_t id = psv_uid_t::make(uid); @@ -44,7 +44,7 @@ public: } // share object with UID specified - inline std::shared_ptr get(s32 uid) + std::shared_ptr get(s32 uid) { if (!check(uid)) { @@ -56,7 +56,7 @@ public: return m_data[psv_uid_t::make(uid).number]; } - inline std::shared_ptr operator [](s32 uid) + std::shared_ptr operator [](s32 uid) { return this->get(uid); } diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 7cc5ba39e5..f74d154f94 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -8,6 +8,8 @@ #include "CPUDecoder.h" #include "CPUThread.h" +thread_local CPUThread* g_tls_current_cpu_thread = nullptr; + CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function thread_name) : m_id(idm::get_last_id()) , m_type(type) @@ -15,6 +17,8 @@ CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function< { start(std::move(thread_name), [this] { + g_tls_current_cpu_thread = this; + Emu.SendDbgCommand(DID_CREATE_THREAD, this); std::unique_lock lock(mutex); @@ -197,13 +201,13 @@ void CPUThread::sleep() void CPUThread::awake() { - // must be called after the balanced Sleep() call + // must be called after the balanced sleep() call if (m_state.atomic_op([](u64& state) -> bool { if (state < CPU_STATE_MAX) { - throw EXCEPTION("Sleep()/Awake() inconsistency"); + throw EXCEPTION("sleep()/awake() inconsistency"); } if ((state -= CPU_STATE_MAX) < CPU_STATE_MAX) diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 079da43f16..25e4d4d914 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -165,6 +165,13 @@ public: virtual bool WriteRegString(const std::string& reg, std::string value) = 0; }; +inline CPUThread* get_current_cpu_thread() +{ + extern thread_local CPUThread* g_tls_current_cpu_thread; + + return g_tls_current_cpu_thread; +} + class cpu_thread { protected: diff --git a/rpcs3/Emu/Cell/PPUInterpreter.cpp b/rpcs3/Emu/Cell/PPUInterpreter.cpp index 5d94b04a3c..861cd45468 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/PPUInterpreter.cpp @@ -1968,7 +1968,7 @@ void ppu_interpreter::LBZX(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::LVX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = (op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]) & ~0xfull; - CPU.VPR[op.vd] = vm::read128(VM_CAST(addr)); + CPU.VPR[op.vd] = vm::_ref(VM_CAST(addr)); } void ppu_interpreter::NEG(PPUThread& CPU, ppu_opcode_t op) @@ -2152,7 +2152,7 @@ void ppu_interpreter::STBX(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::STVX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = (op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]) & ~0xfull; - vm::write128(VM_CAST(addr), CPU.VPR[op.vs]); + vm::_ref(VM_CAST(addr)) = CPU.VPR[op.vs]; } void ppu_interpreter::MULLD(PPUThread& CPU, ppu_opcode_t op) @@ -2295,7 +2295,7 @@ void ppu_interpreter::LHAX(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::LVXL(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = (op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]) & ~0xfull; - CPU.VPR[op.vd] = vm::read128(VM_CAST(addr)); + CPU.VPR[op.vd] = vm::_ref(VM_CAST(addr)); } void ppu_interpreter::MFTB(PPUThread& CPU, ppu_opcode_t op) @@ -2435,7 +2435,7 @@ void ppu_interpreter::NAND(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::STVXL(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = (op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]) & ~0xfull; - vm::write128(VM_CAST(addr), CPU.VPR[op.vs]); + vm::_ref(VM_CAST(addr)) = CPU.VPR[op.vs]; } void ppu_interpreter::DIVD(PPUThread& CPU, ppu_opcode_t op) @@ -2488,7 +2488,7 @@ void ppu_interpreter::LVLX(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::LDBRX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - CPU.GPR[op.rd] = vm::get_ref>(VM_CAST(addr)); + CPU.GPR[op.rd] = vm::_ref>(VM_CAST(addr)); } void ppu_interpreter::LSWX(PPUThread& CPU, ppu_opcode_t op) @@ -2497,14 +2497,14 @@ void ppu_interpreter::LSWX(PPUThread& CPU, ppu_opcode_t op) u32 count = CPU.XER.XER & 0x7F; for (; count >= 4; count -= 4, addr += 4, op.rd = (op.rd + 1) & 31) { - CPU.GPR[op.rd] = vm::get_ref>(VM_CAST(addr)); + CPU.GPR[op.rd] = vm::_ref(VM_CAST(addr)); } if (count) { u32 value = 0; for (u32 byte = 0; byte < count; byte++) { - u32 byte_value = vm::get_ref(VM_CAST(addr + byte)); + u32 byte_value = vm::_ref(VM_CAST(addr + byte)); value |= byte_value << ((3 ^ byte) * 8); } CPU.GPR[op.rd] = value; @@ -2514,13 +2514,13 @@ void ppu_interpreter::LSWX(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::LWBRX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - CPU.GPR[op.rd] = vm::get_ref>(VM_CAST(addr)); + CPU.GPR[op.rd] = vm::_ref>(VM_CAST(addr)); } void ppu_interpreter::LFSX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - CPU.FPR[op.frd]._double = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[op.frd]._double = vm::_ref(VM_CAST(addr)); } void ppu_interpreter::SRW(PPUThread& CPU, ppu_opcode_t op) @@ -2586,7 +2586,7 @@ void ppu_interpreter::LSWI(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::LFSUX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = CPU.GPR[op.ra] + CPU.GPR[op.rb]; - CPU.FPR[op.frd]._double = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[op.frd]._double = vm::_ref(VM_CAST(addr)); CPU.GPR[op.ra] = addr; } @@ -2598,13 +2598,13 @@ void ppu_interpreter::SYNC(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::LFDX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - CPU.FPR[op.frd]._double = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[op.frd]._double = vm::_ref(VM_CAST(addr)); } void ppu_interpreter::LFDUX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = CPU.GPR[op.ra] + CPU.GPR[op.rb]; - CPU.FPR[op.frd]._double = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[op.frd]._double = vm::_ref(VM_CAST(addr)); CPU.GPR[op.ra] = addr; } @@ -2619,7 +2619,7 @@ void ppu_interpreter::STVLX(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::STDBRX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - vm::get_ref>(VM_CAST(addr)) = CPU.GPR[op.rs]; + vm::_ref>(VM_CAST(addr)) = CPU.GPR[op.rs]; } void ppu_interpreter::STSWX(PPUThread& CPU, ppu_opcode_t op) @@ -2644,13 +2644,13 @@ void ppu_interpreter::STSWX(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::STWBRX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - vm::get_ref>(VM_CAST(addr)) = (u32)CPU.GPR[op.rs]; + vm::_ref>(VM_CAST(addr)) = (u32)CPU.GPR[op.rs]; } void ppu_interpreter::STFSX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - vm::get_ref>(VM_CAST(addr)) = static_cast(CPU.FPR[op.frs]); + vm::_ref(VM_CAST(addr)) = static_cast(CPU.FPR[op.frs]); } void ppu_interpreter::STVRX(PPUThread& CPU, ppu_opcode_t op) @@ -2664,7 +2664,7 @@ void ppu_interpreter::STVRX(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::STFSUX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = CPU.GPR[op.ra] + CPU.GPR[op.rb]; - vm::get_ref>(VM_CAST(addr)) = static_cast(CPU.FPR[op.frs]); + vm::_ref(VM_CAST(addr)) = static_cast(CPU.FPR[op.frs]); CPU.GPR[op.ra] = addr; } @@ -2700,13 +2700,13 @@ void ppu_interpreter::STSWI(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::STFDX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - vm::get_ref>(VM_CAST(addr)) = CPU.FPR[op.frs]; + vm::_ref(VM_CAST(addr)) = CPU.FPR[op.frs]; } void ppu_interpreter::STFDUX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = CPU.GPR[op.ra] + CPU.GPR[op.rb]; - vm::get_ref>(VM_CAST(addr)) = CPU.FPR[op.frs]; + vm::_ref(VM_CAST(addr)) = CPU.FPR[op.frs]; CPU.GPR[op.ra] = addr; } @@ -2722,7 +2722,7 @@ void ppu_interpreter::LVLXL(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::LHBRX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - CPU.GPR[op.rd] = vm::get_ref>(VM_CAST(addr)); + CPU.GPR[op.rd] = vm::_ref>(VM_CAST(addr)); } void ppu_interpreter::SRAW(PPUThread& CPU, ppu_opcode_t op) @@ -2809,7 +2809,7 @@ void ppu_interpreter::STVLXL(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::STHBRX(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - vm::get_ref>(VM_CAST(addr)) = (u16)CPU.GPR[op.rs]; + vm::_ref>(VM_CAST(addr)) = (u16)CPU.GPR[op.rs]; } void ppu_interpreter::EXTSH(PPUThread& CPU, ppu_opcode_t op) @@ -2852,7 +2852,7 @@ void ppu_interpreter::DCBZ(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb]; - memset(vm::get_ptr(VM_CAST(addr) & ~127), 0, 128); + std::memset(vm::base(VM_CAST(addr) & ~127), 0, 128); } void ppu_interpreter::LWZ(PPUThread& CPU, ppu_opcode_t op) @@ -2967,52 +2967,52 @@ void ppu_interpreter::STMW(PPUThread& CPU, ppu_opcode_t op) void ppu_interpreter::LFS(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + op.simm16 : op.simm16; - CPU.FPR[op.frd]._double = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[op.frd]._double = vm::_ref(VM_CAST(addr)); } void ppu_interpreter::LFSU(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = CPU.GPR[op.ra] + op.simm16; - CPU.FPR[op.frd]._double = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[op.frd]._double = vm::_ref(VM_CAST(addr)); CPU.GPR[op.ra] = addr; } void ppu_interpreter::LFD(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + op.simm16 : op.simm16; - CPU.FPR[op.frd]._double = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[op.frd]._double = vm::_ref(VM_CAST(addr)); } void ppu_interpreter::LFDU(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = CPU.GPR[op.ra] + op.simm16; - CPU.FPR[op.frd]._double = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[op.frd]._double = vm::_ref(VM_CAST(addr)); CPU.GPR[op.ra] = addr; } void ppu_interpreter::STFS(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + op.simm16 : op.simm16; - vm::get_ref>(VM_CAST(addr)) = static_cast(CPU.FPR[op.frs]); + vm::_ref(VM_CAST(addr)) = static_cast(CPU.FPR[op.frs]); } void ppu_interpreter::STFSU(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = CPU.GPR[op.ra] + op.simm16; - vm::get_ref>(VM_CAST(addr)) = static_cast(CPU.FPR[op.frs]); + vm::_ref(VM_CAST(addr)) = static_cast(CPU.FPR[op.frs]); CPU.GPR[op.ra] = addr; } void ppu_interpreter::STFD(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = op.ra ? CPU.GPR[op.ra] + op.simm16 : op.simm16; - vm::get_ref>(VM_CAST(addr)) = CPU.FPR[op.frs]; + vm::_ref(VM_CAST(addr)) = CPU.FPR[op.frs]; } void ppu_interpreter::STFDU(PPUThread& CPU, ppu_opcode_t op) { const u64 addr = CPU.GPR[op.ra] + op.simm16; - vm::get_ref>(VM_CAST(addr)) = CPU.FPR[op.frs]; + vm::_ref(VM_CAST(addr)) = CPU.FPR[op.frs]; CPU.GPR[op.ra] = addr; } diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 1692fb76e9..2f2e55404a 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2440,7 +2440,7 @@ private: { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; CPU.VPR[vd]._u8[15 - (addr & 0xf)] = vm::read8(VM_CAST(addr)); - // check LVEWX comments + // It's bad idea to read 128 bit there } void SUBFC(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { @@ -2566,7 +2566,7 @@ private: { const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; CPU.VPR[vd]._u16[7 - ((addr >> 1) & 0x7)] = vm::ps3::read16(VM_CAST(addr)); - // check LVEWX comments + // It's bad idea to read 128 bit there } void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { @@ -2615,9 +2615,7 @@ private: { const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; CPU.VPR[vd]._u32[3 - ((addr >> 2) & 0x3)] = vm::ps3::read32(VM_CAST(addr)); - // It's not very good idea to implement it using read128(), - // because it can theoretically read RawSPU 32-bit MMIO register (read128() will fail) - //CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + // It's bad idea to read 128 bit there } void MULHD(u32 rd, u32 ra, u32 rb, u32 rc) { @@ -2651,7 +2649,7 @@ private: void LVX(u32 vd, u32 ra, u32 rb) { const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull; - CPU.VPR[vd] = vm::ps3::read128(VM_CAST(addr)); + CPU.VPR[vd] = vm::ps3::_ref(VM_CAST(addr)); } void NEG(u32 rd, u32 ra, u32 oe, u32 rc) { @@ -2816,7 +2814,7 @@ private: void STVX(u32 vs, u32 ra, u32 rb) { const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull; - vm::ps3::write128(VM_CAST(addr), CPU.VPR[vs]); + vm::ps3::_ref(VM_CAST(addr)) = CPU.VPR[vs]; } void MULLD(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { @@ -2918,7 +2916,7 @@ private: void LVXL(u32 vd, u32 ra, u32 rb) { const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull; - CPU.VPR[vd] = vm::ps3::read128(VM_CAST(addr)); + CPU.VPR[vd] = vm::ps3::_ref(VM_CAST(addr)); } void MFTB(u32 rd, u32 spr) { @@ -3024,7 +3022,7 @@ private: void STVXL(u32 vs, u32 ra, u32 rb) { const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull; - vm::ps3::write128(VM_CAST(addr), CPU.VPR[vs]); + vm::ps3::_ref(VM_CAST(addr)) = CPU.VPR[vs]; } void DIVD(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { @@ -3073,7 +3071,7 @@ private: void LDBRX(u32 rd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.GPR[rd] = vm::get_ref>(VM_CAST(addr)); + CPU.GPR[rd] = vm::ps3::_ref>(VM_CAST(addr)); } void LSWX(u32 rd, u32 ra, u32 rb) { @@ -3081,14 +3079,14 @@ private: u32 count = CPU.XER.XER & 0x7F; for (; count >= 4; count -= 4, addr += 4, rd = (rd+1) & 31) { - CPU.GPR[rd] = vm::get_ref>(VM_CAST(addr)); + CPU.GPR[rd] = vm::ps3::_ref(VM_CAST(addr)); } if (count) { u32 value = 0; for (u32 byte = 0; byte < count; byte++) { - u32 byte_value = vm::get_ref(VM_CAST(addr+byte)); + u32 byte_value = vm::ps3::_ref(VM_CAST(addr+byte)); value |= byte_value << ((3^byte)*8); } CPU.GPR[rd] = value; @@ -3097,12 +3095,12 @@ private: void LWBRX(u32 rd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.GPR[rd] = vm::get_ref>(VM_CAST(addr)); + CPU.GPR[rd] = vm::ps3::_ref>(VM_CAST(addr)); } void LFSX(u32 frd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - float val = vm::get_ref>(VM_CAST(addr)).value(); + const f32 val = vm::ps3::_ref(VM_CAST(addr)); if (!FPRdouble::IsNaN(val)) { CPU.FPR[frd] = val; @@ -3172,7 +3170,7 @@ private: void LFSUX(u32 frd, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - float val = vm::get_ref>(VM_CAST(addr)).value(); + const f32 val = vm::ps3::_ref(VM_CAST(addr)); if (!FPRdouble::IsNaN(val)) { CPU.FPR[frd] = val; @@ -3191,12 +3189,12 @@ private: void LFDX(u32 frd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.FPR[frd] = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[frd]._double = vm::ps3::_ref(VM_CAST(addr)); } void LFDUX(u32 frd, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - CPU.FPR[frd] = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[frd]._double = vm::ps3::_ref(VM_CAST(addr)); CPU.GPR[ra] = addr; } void STVLX(u32 vs, u32 ra, u32 rb) @@ -3209,7 +3207,7 @@ private: void STDBRX(u32 rs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - vm::get_ref>(VM_CAST(addr)) = CPU.GPR[rs]; + vm::ps3::_ref>(VM_CAST(addr)) = CPU.GPR[rs]; } void STSWX(u32 rs, u32 ra, u32 rb) { @@ -3232,7 +3230,7 @@ private: void STWBRX(u32 rs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - vm::get_ref>(VM_CAST(addr)) = (u32)CPU.GPR[rs]; + vm::ps3::_ref>(VM_CAST(addr)) = (u32)CPU.GPR[rs]; } void STFSX(u32 frs, u32 ra, u32 rb) { @@ -3240,13 +3238,13 @@ private: double val = CPU.FPR[frs]; if (!FPRdouble::IsNaN(val)) { - vm::get_ref>(VM_CAST(addr)) = (float)val; + vm::ps3::_ref(VM_CAST(addr)) = (float)val; } else { u64 bits = (u64&)val; u32 bits32 = (bits>>32 & 0x80000000) | (bits>>29 & 0x7fffffff); - vm::get_ref>(VM_CAST(addr)) = bits32; + vm::ps3::_ref(VM_CAST(addr)) = bits32; } } void STVRX(u32 vs, u32 ra, u32 rb) @@ -3262,13 +3260,13 @@ private: double val = CPU.FPR[frs]; if (!FPRdouble::IsNaN(val)) { - vm::get_ref>(VM_CAST(addr)) = (float)val; + vm::ps3::_ref(VM_CAST(addr)) = (float)val; } else { u64 bits = (u64&)val; u32 bits32 = (bits>>32 & 0x80000000) | (bits>>29 & 0x7fffffff); - vm::get_ref>(VM_CAST(addr)) = bits32; + vm::ps3::_ref(VM_CAST(addr)) = bits32; } CPU.GPR[ra] = addr; } @@ -3303,12 +3301,12 @@ private: void STFDX(u32 frs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - vm::get_ref>(VM_CAST(addr)) = CPU.FPR[frs]; + vm::ps3::_ref(VM_CAST(addr)) = CPU.FPR[frs]; } void STFDUX(u32 frs, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - vm::get_ref>(VM_CAST(addr)) = CPU.FPR[frs]; + vm::ps3::_ref(VM_CAST(addr)) = CPU.FPR[frs]; CPU.GPR[ra] = addr; } void LVLXL(u32 vd, u32 ra, u32 rb) @@ -3322,7 +3320,7 @@ private: void LHBRX(u32 rd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.GPR[rd] = vm::get_ref>(VM_CAST(addr)); + CPU.GPR[rd] = vm::ps3::_ref>(VM_CAST(addr)); } void SRAW(u32 ra, u32 rs, u32 rb, u32 rc) { @@ -3403,7 +3401,7 @@ private: void STHBRX(u32 rs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - vm::get_ref>(VM_CAST(addr)) = (u16)CPU.GPR[rs]; + vm::ps3::_ref>(VM_CAST(addr)) = (u16)CPU.GPR[rs]; } void EXTSH(u32 ra, u32 rs, u32 rc) { @@ -3440,7 +3438,7 @@ private: { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - memset(vm::get_ptr(VM_CAST(addr) & ~127), 0, 128); + std::memset(vm::base(VM_CAST(addr) & ~127), 0, 128); } void LWZ(u32 rd, u32 ra, s32 d) { @@ -3538,7 +3536,7 @@ private: void LFS(u32 frd, u32 ra, s32 d) { const u64 addr = ra ? CPU.GPR[ra] + d : d; - float val = vm::get_ref>(VM_CAST(addr)).value(); + const f32 val = vm::ps3::_ref(VM_CAST(addr)); if (!FPRdouble::IsNaN(val)) { CPU.FPR[frd] = val; @@ -3552,7 +3550,7 @@ private: void LFSU(u32 frd, u32 ra, s32 ds) { const u64 addr = CPU.GPR[ra] + ds; - float val = vm::get_ref>(VM_CAST(addr)).value(); + const f32 val = vm::ps3::_ref(VM_CAST(addr)); if (!FPRdouble::IsNaN(val)) { CPU.FPR[frd] = val; @@ -3567,12 +3565,12 @@ private: void LFD(u32 frd, u32 ra, s32 d) { const u64 addr = ra ? CPU.GPR[ra] + d : d; - CPU.FPR[frd] = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[frd]._double = vm::ps3::_ref(VM_CAST(addr)); } void LFDU(u32 frd, u32 ra, s32 ds) { const u64 addr = CPU.GPR[ra] + ds; - CPU.FPR[frd] = vm::get_ref>(VM_CAST(addr)).value(); + CPU.FPR[frd]._double = vm::ps3::_ref(VM_CAST(addr)); CPU.GPR[ra] = addr; } void STFS(u32 frs, u32 ra, s32 d) @@ -3581,13 +3579,13 @@ private: double val = CPU.FPR[frs]; if (!FPRdouble::IsNaN(val)) { - vm::get_ref>(VM_CAST(addr)) = (float)val; + vm::ps3::_ref(VM_CAST(addr)) = (float)val; } else { u64 bits = (u64&)val; u32 bits32 = (bits>>32 & 0x80000000) | (bits>>29 & 0x7fffffff); - vm::get_ref>(VM_CAST(addr)) = bits32; + vm::ps3::_ref(VM_CAST(addr)) = bits32; } } void STFSU(u32 frs, u32 ra, s32 d) @@ -3596,25 +3594,25 @@ private: double val = CPU.FPR[frs]; if (!FPRdouble::IsNaN(val)) { - vm::get_ref>(VM_CAST(addr)) = (float)val; + vm::ps3::_ref(VM_CAST(addr)) = (float)val; } else { u64 bits = (u64&)val; u32 bits32 = (bits>>32 & 0x80000000) | (bits>>29 & 0x7fffffff); - vm::get_ref>(VM_CAST(addr)) = bits32; + vm::ps3::_ref(VM_CAST(addr)) = bits32; } CPU.GPR[ra] = addr; } void STFD(u32 frs, u32 ra, s32 d) { const u64 addr = ra ? CPU.GPR[ra] + d : d; - vm::get_ref>(VM_CAST(addr)) = CPU.FPR[frs]; + vm::ps3::_ref(VM_CAST(addr)) = CPU.FPR[frs]; } void STFDU(u32 frs, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; - vm::get_ref>(VM_CAST(addr)) = CPU.FPR[frs]; + vm::ps3::_ref(VM_CAST(addr)) = CPU.FPR[frs]; CPU.GPR[ra] = addr; } void LD(u32 rd, u32 ra, s32 ds) diff --git a/rpcs3/Emu/Cell/PPUInterpreter2.h b/rpcs3/Emu/Cell/PPUInterpreter2.h index c73dc6638f..051c70b3dd 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter2.h +++ b/rpcs3/Emu/Cell/PPUInterpreter2.h @@ -1,4 +1,5 @@ #pragma once + #include "PPUOpcodes.h" class PPUThread; @@ -7,133 +8,51 @@ union ppu_opcode_t { u32 opcode; - struct - { - u32 : 1; // 31 - u32 shh : 1; // 30 - u32 : 3; // 27..29 - u32 mbmeh : 1; // 26 - u32 mbmel : 5; // 21..25 - u32 shl : 5; // 16..20 - u32 vuimm : 5; // 11..15 - u32 vs : 5; // 6..10 - u32 : 6; - }; - - struct - { - u32 : 6; // 26..31 - u32 vsh : 4; // 22..25 - u32 oe : 1; // 21 - u32 spr : 10; // 11..20 - u32 : 11; - }; - - struct - { - u32 : 6; // 26..31 - u32 vc : 5; // 21..25 - u32 vb : 5; // 16..20 - u32 va : 5; // 11..15 - u32 vd : 5; // 6..10 - u32 : 6; - }; - - struct - { - u32 lk : 1; // 31 - u32 aa : 1; // 30 - u32 : 4; // 26..29 - u32 : 5; // 21..25 - u32 rb : 5; // 16..20 - u32 ra : 5; // 11..15 - u32 rd : 5; // 6..10 - u32 : 6; - }; - - struct - { - u32 uimm16 : 16; // 16..31 - u32 : 4; // 12..15 - u32 l11 : 1; // 11 - u32 rs : 5; // 6..10 - u32 : 6; - }; - - struct - { - s32 simm16 : 16; // 16..31 - s32 vsimm : 5; // 11..15 - s32 : 11; - }; - - struct - { - s32 ll : 26; // 6..31 - s32 : 6; - }; - - struct - { - u32 : 5; // 27..31 - u32 lev : 7; // 20..26 - u32 i : 4; // 16..19 - u32 : 2; // 14..15 - u32 crfs : 3; // 11..13 - u32 l10 : 1; // 10 - u32 : 1; // 9 - u32 crfd : 3; // 6..8 - u32 : 6; - }; - - struct - { - u32 : 1; // 31 - u32 : 1; // 30 - u32 : 4; // 26..29 - u32 : 5; // 21..25 - u32 crbb : 5; // 16..20 - u32 crba : 5; // 11..15 - u32 crbd : 5; // 6..10 - u32 : 6; - }; - - struct - { - u32 rc : 1; // 31 - u32 me : 5; // 26..30 - u32 mb : 5; // 21..25 - u32 sh : 5; // 16..20 - u32 bi : 5; // 11..15 - u32 bo : 5; // 6..10 - u32 : 6; - }; - - struct - { - u32 : 6; // 26..31 - u32 frc : 5; // 21..25 - u32 frb : 5; // 16..20 - u32 fra : 5; // 11..15 - u32 frd : 5; // 6..10 - u32 : 6; - }; - - struct - { - u32 : 12; // 20..31 - u32 crm : 8; // 12..19 - u32 : 1; // 11 - u32 frs : 5; // 6..10 - u32 : 6; - }; - - struct - { - u32 : 17; // 15..31 - u32 flm : 8; // 7..14 - u32 : 7; - }; + bf_t shh; // 30 + bf_t mbmeh; // 26 + bf_t mbmel; // 21..25 + bf_t shl; // 16..20 + bf_t vuimm; // 11..15 + bf_t vs; // 6..10 + bf_t vsh; // 22..25 + bf_t oe; // 21 + bf_t spr; // 11..20 + bf_t vc; // 21..25 + bf_t vb; // 16..20 + bf_t va; // 11..15 + bf_t vd; // 6..10 + bf_t lk; // 31 + bf_t aa; // 30 + bf_t rb; // 16..20 + bf_t ra; // 11..15 + bf_t rd; // 6..10 + bf_t uimm16; // 16..31 + bf_t l11; // 11 + bf_t rs; // 6..10 + bf_t simm16; // 16..31, signed + bf_t vsimm; // 11..15, signed + bf_t ll; // 6..31, signed + bf_t lev; // 20..26 + bf_t i; // 16..19 + bf_t crfs; // 11..13 + bf_t l10; // 10 + bf_t crfd; // 6..8 + bf_t crbb; // 16..20 + bf_t crba; // 11..15 + bf_t crbd; // 6..10 + bf_t rc; // 31 + bf_t me; // 26..30 + bf_t mb; // 21..25 + bf_t sh; // 16..20 + bf_t bi; // 11..15 + bf_t bo; // 6..10 + bf_t frc; // 21..25 + bf_t frb; // 16..20 + bf_t fra; // 11..15 + bf_t frd; // 6..10 + bf_t crm; // 12..19 + bf_t frs; // 6..10 + bf_t flm; // 7..14 }; namespace ppu_interpreter diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index f0cf394d40..eea5b225e2 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -133,7 +133,7 @@ std::pair Compiler::Compile(const std::stri // Used to decode instructions PPUDisAsm dis_asm(CPUDisAsm_DumpMode); - dis_asm.offset = vm::get_ptr(start_address); + dis_asm.offset = vm::ps3::_ptr(start_address); m_recompilation_engine.Log() << "Recompiling block :\n\n"; diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.h b/rpcs3/Emu/Cell/PPULLVMRecompiler.h index 281537badd..c9094311ee 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.h +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.h @@ -66,14 +66,10 @@ namespace ppu_recompiler_llvm { Compiler(RecompilationEngine & recompilation_engine, const Executable execute_unknown_function, const Executable execute_unknown_block, bool(*poll_status_function)(PPUThread * ppu_state)); - Compiler(const Compiler & other) = delete; - Compiler(Compiler && other) = delete; + Compiler(const Compiler&) = delete; // Delete copy/move constructors and copy/move operators virtual ~Compiler(); - Compiler & operator = (const Compiler & other) = delete; - Compiler & operator = (Compiler && other) = delete; - /** * Compile a code fragment described by a cfg and return an executable and the ExecutionEngine storing it * Pointer to function can be retrieved with getPointerToFunction @@ -883,11 +879,7 @@ namespace ppu_recompiler_llvm { RecompilationEngine(); - RecompilationEngine(const RecompilationEngine & other) = delete; - RecompilationEngine(RecompilationEngine && other) = delete; - - RecompilationEngine & operator = (const RecompilationEngine & other) = delete; - RecompilationEngine & operator = (RecompilationEngine && other) = delete; + RecompilationEngine(const RecompilationEngine&) = delete; // Delete copy/move constructors and copy/move operators /// Increase usage counter for block starting at addr and compile it if threshold was reached. /// Returns true if block was compiled @@ -921,16 +913,11 @@ namespace ppu_recompiler_llvm { friend class Compiler; public: CPUHybridDecoderRecompiler(PPUThread & ppu); - CPUHybridDecoderRecompiler() = delete; - CPUHybridDecoderRecompiler(const CPUHybridDecoderRecompiler & other) = delete; - CPUHybridDecoderRecompiler(CPUHybridDecoderRecompiler && other) = delete; + CPUHybridDecoderRecompiler(const CPUHybridDecoderRecompiler&) = delete; // Delete copy/move constructors and copy/move operators virtual ~CPUHybridDecoderRecompiler(); - CPUHybridDecoderRecompiler & operator = (const ExecutionEngine & other) = delete; - CPUHybridDecoderRecompiler & operator = (ExecutionEngine && other) = delete; - u32 DecodeMemory(const u32 address) override; private: diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp index 17c2c22313..8074eb652f 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp @@ -3502,7 +3502,7 @@ void Compiler::STVLX(u32 vs, u32 ra, u32 rb) { auto index_i64 = m_ir_builder->CreateAnd(addr_i64, 0xf); auto size_i64 = m_ir_builder->CreateSub(m_ir_builder->getInt64(16), index_i64); addr_i64 = m_ir_builder->CreateAnd(addr_i64, 0xFFFFFFFF); - addr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + addr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::base(0))); auto addr_i8_ptr = m_ir_builder->CreateIntToPtr(addr_i64, m_ir_builder->getInt8PtrTy()); auto vs_i128 = GetVr(vs); @@ -3562,7 +3562,7 @@ void Compiler::STVRX(u32 vs, u32 ra, u32 rb) { auto size_i64 = m_ir_builder->CreateAnd(addr_i64, 0xf); auto index_i64 = m_ir_builder->CreateSub(m_ir_builder->getInt64(16), size_i64); addr_i64 = m_ir_builder->CreateAnd(addr_i64, 0xFFFFFFF0); - addr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + addr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::base(0))); auto addr_i8_ptr = m_ir_builder->CreateIntToPtr(addr_i64, m_ir_builder->getInt8PtrTy()); auto vs_i128 = GetVr(vs); @@ -3834,7 +3834,7 @@ void Compiler::DCBZ(u32 ra, u32 rb) { } addr_i64 = m_ir_builder->CreateAnd(addr_i64, ~(127ULL)); - addr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + addr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::base(0))); auto addr_i8_ptr = m_ir_builder->CreateIntToPtr(addr_i64, m_ir_builder->getInt8PtrTy()); std::vector types = { (Type *)m_ir_builder->getInt8PtrTy(), (Type *)m_ir_builder->getInt32Ty() }; @@ -5312,7 +5312,7 @@ void Compiler::CreateBranch(llvm::Value * cmp_i1, llvm::Value * target_i32, bool Value * Compiler::ReadMemory(Value * addr_i64, u32 bits, u32 alignment, bool bswap, bool could_be_mmio) { addr_i64 = m_ir_builder->CreateAnd(addr_i64, 0xFFFFFFFF); - auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::base(0))); auto eaddr_ix_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, m_ir_builder->getIntNTy(bits)->getPointerTo()); auto val_ix = (Value *)m_ir_builder->CreateLoad(eaddr_ix_ptr, alignment); if (bits > 8 && bswap) { @@ -5328,7 +5328,7 @@ void Compiler::WriteMemory(Value * addr_i64, Value * val_ix, u32 alignment, bool } addr_i64 = m_ir_builder->CreateAnd(addr_i64, 0xFFFFFFFF); - auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + auto eaddr_i64 = m_ir_builder->CreateAdd(addr_i64, m_ir_builder->getInt64((u64)vm::base(0))); auto eaddr_ix_ptr = m_ir_builder->CreateIntToPtr(eaddr_i64, val_ix->getType()->getPointerTo()); m_ir_builder->CreateAlignedStore(val_ix, eaddr_ix_ptr, alignment); } diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 106f0bf923..fa9bd6e032 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -363,7 +363,7 @@ cpu_thread& ppu_thread::args(std::initializer_list values) const u32 arg_size = align(u32(arg.size() + 1), stack_align); const u32 arg_addr = vm::alloc(arg_size, vm::main); - std::memcpy(vm::get_ptr(arg_addr), arg.c_str(), arg.size() + 1); + std::memcpy(vm::base(arg_addr), arg.c_str(), arg.size() + 1); argv[argc++] = arg_addr; } diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index bfad145322..611d60b34a 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -536,9 +536,7 @@ public: std::function custom_task; - /// When a thread has met an exception, this variable is used to retro propagate it through stack call. - /// Note that exception_ptr is similar to shared_ptr and doesn't need to be freed, but need a nullptr - /// to be assigned. + // When a thread has met an exception, this variable is used to retro propagate it through stack call. std::exception_ptr pending_exception; public: @@ -557,7 +555,7 @@ public: virtual bool handle_interrupt() override; - inline u8 GetCR(const u8 n) const + u8 GetCR(const u8 n) const { switch(n) { @@ -574,7 +572,7 @@ public: return 0; } - inline void SetCR(const u8 n, const u32 value) + void SetCR(const u8 n, const u32 value) { switch(n) { @@ -589,7 +587,7 @@ public: } } - inline void SetCRBit(const u8 n, const u32 bit, const bool value) + void SetCRBit(const u8 n, const u32 bit, const bool value) { switch(n) { @@ -604,14 +602,14 @@ public: } } - inline void SetCR_EQ(const u8 n, const bool value) { SetCRBit(n, CR_EQ, value); } - inline void SetCR_GT(const u8 n, const bool value) { SetCRBit(n, CR_GT, value); } - inline void SetCR_LT(const u8 n, const bool value) { SetCRBit(n, CR_LT, value); } - inline void SetCR_SO(const u8 n, const bool value) { SetCRBit(n, CR_SO, value); } + void SetCR_EQ(const u8 n, const bool value) { SetCRBit(n, CR_EQ, value); } + void SetCR_GT(const u8 n, const bool value) { SetCRBit(n, CR_GT, value); } + void SetCR_LT(const u8 n, const bool value) { SetCRBit(n, CR_LT, value); } + void SetCR_SO(const u8 n, const bool value) { SetCRBit(n, CR_SO, value); } - inline bool IsCR_EQ(const u8 n) const { return (GetCR(n) & CR_EQ) ? 1 : 0; } - inline bool IsCR_GT(const u8 n) const { return (GetCR(n) & CR_GT) ? 1 : 0; } - inline bool IsCR_LT(const u8 n) const { return (GetCR(n) & CR_LT) ? 1 : 0; } + bool IsCR_EQ(const u8 n) const { return (GetCR(n) & CR_EQ) ? 1 : 0; } + bool IsCR_GT(const u8 n) const { return (GetCR(n) & CR_GT) ? 1 : 0; } + bool IsCR_LT(const u8 n) const { return (GetCR(n) & CR_LT) ? 1 : 0; } template void UpdateCRn(const u8 n, const T a, const T b) { diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index 71d7631589..f5ba1a5942 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -223,10 +223,7 @@ spu_recompiler::XmmLink spu_recompiler::XmmAlloc() // get empty xmm register { for (auto& v : vec) { - if (v) - { - return XmmLink{ v }; - } + if (v) return{ v }; } throw EXCEPTION("Out of Xmm Vars"); @@ -699,7 +696,7 @@ void spu_recompiler::SHLH(spu_opcode_t op) void spu_recompiler::ROTI(spu_opcode_t op) { // rotate left - const int s = op.si7 & 0x1f; + const int s = op.i7 & 0x1f; const XmmLink& va = XmmGet(op.ra, XmmType::Int); const XmmLink& v1 = XmmAlloc(); c->movdqa(v1, va); @@ -712,7 +709,7 @@ void spu_recompiler::ROTI(spu_opcode_t op) void spu_recompiler::ROTMI(spu_opcode_t op) { // shift right logical - const int s = (0 - op.si7) & 0x3f; + const int s = 0-op.i7 & 0x3f; const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->psrld(va, s); c->movdqa(SPU_OFF_128(gpr[op.rt]), va); @@ -721,7 +718,7 @@ void spu_recompiler::ROTMI(spu_opcode_t op) void spu_recompiler::ROTMAI(spu_opcode_t op) { // shift right arithmetical - const int s = (0 - op.si7) & 0x3f; + const int s = 0-op.i7 & 0x3f; const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->psrad(va, s); c->movdqa(SPU_OFF_128(gpr[op.rt]), va); @@ -730,7 +727,7 @@ void spu_recompiler::ROTMAI(spu_opcode_t op) void spu_recompiler::SHLI(spu_opcode_t op) { // shift left - const int s = op.si7 & 0x3f; + const int s = op.i7 & 0x3f; const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->pslld(va, s); c->movdqa(SPU_OFF_128(gpr[op.rt]), va); @@ -739,7 +736,7 @@ void spu_recompiler::SHLI(spu_opcode_t op) void spu_recompiler::ROTHI(spu_opcode_t op) { // rotate left (halfword) - const int s = op.si7 & 0xf; + const int s = op.i7 & 0xf; const XmmLink& va = XmmGet(op.ra, XmmType::Int); const XmmLink& v1 = XmmAlloc(); c->movdqa(v1, va); @@ -752,7 +749,7 @@ void spu_recompiler::ROTHI(spu_opcode_t op) void spu_recompiler::ROTHMI(spu_opcode_t op) { // shift right logical - const int s = (0 - op.si7) & 0x1f; + const int s = 0-op.i7 & 0x1f; const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->psrlw(va, s); c->movdqa(SPU_OFF_128(gpr[op.rt]), va); @@ -761,7 +758,7 @@ void spu_recompiler::ROTHMI(spu_opcode_t op) void spu_recompiler::ROTMAHI(spu_opcode_t op) { // shift right arithmetical (halfword) - const int s = (0 - op.si7) & 0x1f; + const int s = 0-op.i7 & 0x1f; const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->psraw(va, s); c->movdqa(SPU_OFF_128(gpr[op.rt]), va); @@ -770,7 +767,7 @@ void spu_recompiler::ROTMAHI(spu_opcode_t op) void spu_recompiler::SHLHI(spu_opcode_t op) { // shift left (halfword) - const int s = op.si7 & 0x1f; + const int s = op.i7 & 0x1f; const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->psllw(va, s); c->movdqa(SPU_OFF_128(gpr[op.rt]), va); @@ -914,7 +911,7 @@ void spu_recompiler::BISL(spu_opcode_t op) const XmmLink& vr = XmmAlloc(); c->movdqa(vr, XmmConst(_mm_set_epi32(spu_branch_target(m_pos + 4), 0, 0, 0))); c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); - c->unuse(*vr.m_var); + c->unuse(vr); FunctionCall(); } @@ -1243,14 +1240,14 @@ void spu_recompiler::CBD(spu_opcode_t op) // // assuming that SP % 16 is always zero // const XmmLink& vr = XmmAlloc(); // v128 value = v128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); - // value.u8r[op.si7 & 0xf] = 0x03; + // value.u8r[op.i7 & 0xf] = 0x03; // c->movdqa(vr, XmmConst(value)); // c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); // return; //} c->mov(*addr, SPU_OFF_32(gpr[op.ra]._u32[3])); - if (op.si7) c->add(*addr, op.si7); + if (op.i7) c->add(*addr, op.i7); c->not_(*addr); c->and_(*addr, 0xf); @@ -1268,14 +1265,14 @@ void spu_recompiler::CHD(spu_opcode_t op) // // assuming that SP % 16 is always zero // const XmmLink& vr = XmmAlloc(); // v128 value = v128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); - // value.u16r[(op.si7 >> 1) & 0x7] = 0x0203; + // value.u16r[(op.i7 >> 1) & 0x7] = 0x0203; // c->movdqa(vr, XmmConst(value)); // c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); // return; //} c->mov(*addr, SPU_OFF_32(gpr[op.ra]._u32[3])); - if (op.si7) c->add(*addr, op.si7); + if (op.i7) c->add(*addr, op.i7); c->not_(*addr); c->and_(*addr, 0xe); @@ -1293,14 +1290,14 @@ void spu_recompiler::CWD(spu_opcode_t op) // // assuming that SP % 16 is always zero // const XmmLink& vr = XmmAlloc(); // v128 value = v128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); - // value.u32r[(op.si7 >> 2) & 0x3] = 0x00010203; + // value.u32r[(op.i7 >> 2) & 0x3] = 0x00010203; // c->movdqa(vr, XmmConst(value)); // c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); // return; //} c->mov(*addr, SPU_OFF_32(gpr[op.ra]._u32[3])); - if (op.si7) c->add(*addr, op.si7); + if (op.i7) c->add(*addr, op.i7); c->not_(*addr); c->and_(*addr, 0xc); @@ -1318,14 +1315,14 @@ void spu_recompiler::CDD(spu_opcode_t op) // // assuming that SP % 16 is always zero // const XmmLink& vr = XmmAlloc(); // v128 value = v128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); - // value.u64r[(op.si7 >> 3) & 0x1] = 0x0001020304050607ull; + // value.u64r[(op.i7 >> 3) & 0x1] = 0x0001020304050607ull; // c->movdqa(vr, XmmConst(value)); // c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); // return; //} c->mov(*addr, SPU_OFF_32(gpr[op.ra]._u32[3])); - if (op.si7) c->add(*addr, op.si7); + if (op.i7) c->add(*addr, op.i7); c->not_(*addr); c->and_(*addr, 0x8); @@ -1343,8 +1340,8 @@ void spu_recompiler::ROTQBII(spu_opcode_t op) c->mov(*qw0, SPU_OFF_64(gpr[op.ra]._u64[0])); c->mov(*qw1, SPU_OFF_64(gpr[op.ra]._u64[1])); c->mov(*qw2, *qw0); - c->shld(*qw0, *qw1, op.si7 & 0x7); - c->shld(*qw1, *qw2, op.si7 & 0x7); + c->shld(*qw0, *qw1, op.i7 & 0x7); + c->shld(*qw1, *qw2, op.i7 & 0x7); c->mov(SPU_OFF_64(gpr[op.rt]._u64[0]), *qw0); c->mov(SPU_OFF_64(gpr[op.rt]._u64[1]), *qw1); c->unuse(*qw0); @@ -1356,8 +1353,8 @@ void spu_recompiler::ROTQMBII(spu_opcode_t op) { c->mov(*qw0, SPU_OFF_64(gpr[op.ra]._u64[0])); c->mov(*qw1, SPU_OFF_64(gpr[op.ra]._u64[1])); - c->shrd(*qw0, *qw1, (0 - op.si7) & 0x7); - c->shr(*qw1, (0 - op.si7) & 0x7); + c->shrd(*qw0, *qw1, 0-op.i7 & 0x7); + c->shr(*qw1, 0-op.i7 & 0x7); c->mov(SPU_OFF_64(gpr[op.rt]._u64[0]), *qw0); c->mov(SPU_OFF_64(gpr[op.rt]._u64[1]), *qw1); c->unuse(*qw0); @@ -1368,8 +1365,8 @@ void spu_recompiler::SHLQBII(spu_opcode_t op) { c->mov(*qw0, SPU_OFF_64(gpr[op.ra]._u64[0])); c->mov(*qw1, SPU_OFF_64(gpr[op.ra]._u64[1])); - c->shld(*qw1, *qw0, op.si7 & 0x7); - c->shl(*qw0, op.si7 & 0x7); + c->shld(*qw1, *qw0, op.i7 & 0x7); + c->shl(*qw0, op.i7 & 0x7); c->mov(SPU_OFF_64(gpr[op.rt]._u64[0]), *qw0); c->mov(SPU_OFF_64(gpr[op.rt]._u64[1]), *qw1); c->unuse(*qw0); @@ -1378,7 +1375,7 @@ void spu_recompiler::SHLQBII(spu_opcode_t op) void spu_recompiler::ROTQBYI(spu_opcode_t op) { - const int s = op.si7 & 0xf; + const int s = op.i7 & 0xf; const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->palignr(va, va, 16 - s); c->movdqa(SPU_OFF_128(gpr[op.rt]), va); @@ -1386,7 +1383,7 @@ void spu_recompiler::ROTQBYI(spu_opcode_t op) void spu_recompiler::ROTQMBYI(spu_opcode_t op) { - const int s = (0 - op.si7) & 0x1f; + const int s = 0-op.i7 & 0x1f; const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->psrldq(va, s); c->movdqa(SPU_OFF_128(gpr[op.rt]), va); @@ -1394,7 +1391,7 @@ void spu_recompiler::ROTQMBYI(spu_opcode_t op) void spu_recompiler::SHLQBYI(spu_opcode_t op) { - const int s = op.si7 & 0x1f; + const int s = op.i7 & 0x1f; const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->pslldq(va, s); c->movdqa(SPU_OFF_128(gpr[op.rt]), va); @@ -1968,7 +1965,7 @@ void spu_recompiler::CFLTS(spu_opcode_t op) { const XmmLink& va = XmmGet(op.ra, XmmType::Float); const XmmLink& vi = XmmAlloc(); - if (op.si8 != 173) c->mulps(va, XmmConst(_mm_set1_ps(exp2f(static_cast(173 - (op.si8 & 0xff)))))); // scale + if (op.i8 != 173) c->mulps(va, XmmConst(_mm_set1_ps(exp2f(static_cast(173 - op.i8))))); // scale c->movaps(vi, XmmConst(_mm_set1_ps(exp2f(31)))); c->cmpps(vi, va, 2); c->cvttps2dq(va, va); // convert to ints with truncation @@ -1982,7 +1979,7 @@ void spu_recompiler::CFLTU(spu_opcode_t op) const XmmLink& vs = XmmAlloc(); const XmmLink& vs2 = XmmAlloc(); const XmmLink& vs3 = XmmAlloc(); - if (op.si8 != 173) c->mulps(va, XmmConst(_mm_set1_ps(exp2f(static_cast(173 - (op.si8 & 0xff)))))); // scale + if (op.i8 != 173) c->mulps(va, XmmConst(_mm_set1_ps(exp2f(static_cast(173 - op.i8))))); // scale c->maxps(va, XmmConst(_mm_set1_ps(0.0f))); // saturate c->movaps(vs, va); // copy scaled value c->movaps(vs2, va); @@ -2002,7 +1999,7 @@ void spu_recompiler::CSFLT(spu_opcode_t op) { const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->cvtdq2ps(va, va); // convert to floats - if (op.si8 != 155) c->mulps(va, XmmConst(_mm_set1_ps(exp2f(static_cast((op.si8 & 0xff) - 155))))); // scale + if (op.i8 != 155) c->mulps(va, XmmConst(_mm_set1_ps(exp2f(static_cast(op.i8 - 155))))); // scale c->movaps(SPU_OFF_128(gpr[op.rt]), va); } @@ -2016,13 +2013,15 @@ void spu_recompiler::CUFLT(spu_opcode_t op) c->psrad(v1, 31); // generate mask from sign bit c->andps(v1, XmmConst(_mm_set1_ps(exp2f(31)))); // generate correction component c->addps(va, v1); // add correction component - if (op.si8 != 155) c->mulps(va, XmmConst(_mm_set1_ps(exp2f(static_cast((op.si8 & 0xff) - 155))))); // scale + if (op.i8 != 155) c->mulps(va, XmmConst(_mm_set1_ps(exp2f(static_cast(op.i8 - 155))))); // scale c->movaps(SPU_OFF_128(gpr[op.rt]), va); } void spu_recompiler::BRZ(spu_opcode_t op) { - const u32 target = spu_branch_target(m_pos, op.si16); + const u32 target = spu_branch_target(m_pos, op.i16); + + if (target == m_pos) throw EXCEPTION("Branch-to-self (0x%05x)", target); c->cmp(SPU_OFF_32(gpr[op.rt]._u32[3]), 0); @@ -2045,16 +2044,16 @@ void spu_recompiler::BRZ(spu_opcode_t op) void spu_recompiler::STQA(spu_opcode_t op) { - const u32 lsa = (op.si16 << 2) & 0x3fff0; - const XmmLink& vt = XmmGet(op.rt, XmmType::Int); c->pshufb(vt, XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - c->movdqa(asmjit::host::oword_ptr(*ls, lsa), vt); + c->movdqa(asmjit::host::oword_ptr(*ls, spu_ls_target(0, op.i16)), vt); } void spu_recompiler::BRNZ(spu_opcode_t op) { - const u32 target = spu_branch_target(m_pos, op.si16); + const u32 target = spu_branch_target(m_pos, op.i16); + + if (target == m_pos) throw EXCEPTION("Branch-to-self (0x%05x)", target); c->cmp(SPU_OFF_32(gpr[op.rt]._u32[3]), 0); @@ -2077,7 +2076,9 @@ void spu_recompiler::BRNZ(spu_opcode_t op) void spu_recompiler::BRHZ(spu_opcode_t op) { - const u32 target = spu_branch_target(m_pos, op.si16); + const u32 target = spu_branch_target(m_pos, op.i16); + + if (target == m_pos) throw EXCEPTION("Branch-to-self (0x%05x)", target); c->cmp(SPU_OFF_16(gpr[op.rt]._u16[6]), 0); @@ -2100,7 +2101,9 @@ void spu_recompiler::BRHZ(spu_opcode_t op) void spu_recompiler::BRHNZ(spu_opcode_t op) { - const u32 target = spu_branch_target(m_pos, op.si16); + const u32 target = spu_branch_target(m_pos, op.i16); + + if (target == m_pos) throw EXCEPTION("Branch-to-self (0x%05x)", target); c->cmp(SPU_OFF_16(gpr[op.rt]._u16[6]), 0); @@ -2123,16 +2126,16 @@ void spu_recompiler::BRHNZ(spu_opcode_t op) void spu_recompiler::STQR(spu_opcode_t op) { - const u32 lsa = spu_branch_target(m_pos, op.si16) & 0x3fff0; - const XmmLink& vt = XmmGet(op.rt, XmmType::Int); c->pshufb(vt, XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - c->movdqa(asmjit::host::oword_ptr(*ls, lsa), vt); + c->movdqa(asmjit::host::oword_ptr(*ls, spu_ls_target(m_pos, op.i16)), vt); } void spu_recompiler::BRA(spu_opcode_t op) { - const u32 target = spu_branch_target(0, op.si16); + const u32 target = spu_branch_target(0, op.i16); + + if (target == m_pos) throw EXCEPTION("Branch-to-self (0x%05x)", target); if (labels[target / 4].isInitialized()) { @@ -2153,22 +2156,22 @@ void spu_recompiler::BRA(spu_opcode_t op) void spu_recompiler::LQA(spu_opcode_t op) { - const u32 lsa = (op.si16 << 2) & 0x3fff0; - const XmmLink& vt = XmmAlloc(); - c->movdqa(vt, asmjit::host::oword_ptr(*ls, lsa)); + c->movdqa(vt, asmjit::host::oword_ptr(*ls, spu_ls_target(0, op.i16))); c->pshufb(vt, XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); c->movdqa(SPU_OFF_128(gpr[op.rt]), vt); } void spu_recompiler::BRASL(spu_opcode_t op) { - const u32 target = spu_branch_target(0, op.si16); + const u32 target = spu_branch_target(0, op.i16); + + if (target == m_pos) throw EXCEPTION("Branch-to-self (0x%05x)", target); const XmmLink& vr = XmmAlloc(); c->movdqa(vr, XmmConst(_mm_set_epi32(spu_branch_target(m_pos + 4), 0, 0, 0))); c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); - c->unuse(*vr.m_var); + c->unuse(vr); c->mov(SPU_OFF_32(pc), target); @@ -2177,7 +2180,18 @@ void spu_recompiler::BRASL(spu_opcode_t op) void spu_recompiler::BR(spu_opcode_t op) { - const u32 target = spu_branch_target(m_pos, op.si16); + const u32 target = spu_branch_target(m_pos, op.i16); + + if (target == m_pos) + { + c->mov(*addr, target | 0x2000000); + //c->cmp(asmjit::host::dword_ptr(*ls, m_pos), 0x32); // compare instruction opcode with BR-to-self + //c->je(labels[target / 4]); + c->lock().or_(SPU_OFF_64(m_state), CPU_STATE_RETURN | CPU_STATE_STOPPED); + c->jmp(*end); + c->unuse(*addr); + return; + } if (labels[target / 4].isInitialized()) { @@ -2199,18 +2213,20 @@ void spu_recompiler::BR(spu_opcode_t op) void spu_recompiler::FSMBI(spu_opcode_t op) { const XmmLink& vr = XmmAlloc(); - c->movdqa(vr, XmmConst(g_spu_imm.fsmb[op.si16 & 0xffff])); + c->movdqa(vr, XmmConst(g_spu_imm.fsmb[op.i16])); c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); } void spu_recompiler::BRSL(spu_opcode_t op) { - const u32 target = spu_branch_target(m_pos, op.si16); + const u32 target = spu_branch_target(m_pos, op.i16); + + if (target == m_pos) throw EXCEPTION("Branch-to-self (0x%05x)", target); const XmmLink& vr = XmmAlloc(); c->movdqa(vr, XmmConst(_mm_set_epi32(spu_branch_target(m_pos + 4), 0, 0, 0))); c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); - c->unuse(*vr.m_var); + c->unuse(vr); if (target == spu_branch_target(m_pos + 4)) { @@ -2225,10 +2241,8 @@ void spu_recompiler::BRSL(spu_opcode_t op) void spu_recompiler::LQR(spu_opcode_t op) { - const u32 lsa = spu_branch_target(m_pos, op.si16) & 0x3fff0; - const XmmLink& vt = XmmAlloc(); - c->movdqa(vt, asmjit::host::oword_ptr(*ls, lsa)); + c->movdqa(vt, asmjit::host::oword_ptr(*ls, spu_ls_target(m_pos, op.i16))); c->pshufb(vt, XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); c->movdqa(SPU_OFF_128(gpr[op.rt]), vt); } @@ -2243,14 +2257,14 @@ void spu_recompiler::IL(spu_opcode_t op) void spu_recompiler::ILHU(spu_opcode_t op) { const XmmLink& vr = XmmAlloc(); - c->movdqa(vr, XmmConst(_mm_set1_epi32(op.si16 << 16))); + c->movdqa(vr, XmmConst(_mm_set1_epi32(op.i16 << 16))); c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); } void spu_recompiler::ILH(spu_opcode_t op) { const XmmLink& vr = XmmAlloc(); - c->movdqa(vr, XmmConst(_mm_set1_epi16(op.si16))); + c->movdqa(vr, XmmConst(_mm_set1_epi16(op.i16))); c->movdqa(SPU_OFF_128(gpr[op.rt]), vr); } @@ -2516,16 +2530,16 @@ void spu_recompiler::ILA(spu_opcode_t op) void spu_recompiler::SELB(spu_opcode_t op) { const XmmLink& vb = XmmGet(op.rb, XmmType::Int); - const XmmLink& vc = XmmGet(op.rt, XmmType::Int); + const XmmLink& vc = XmmGet(op.rc, XmmType::Int); c->pand(vb, vc); c->pandn(vc, SPU_OFF_128(gpr[op.ra])); c->por(vb, vc); - c->movdqa(SPU_OFF_128(gpr[op.rc]), vb); + c->movdqa(SPU_OFF_128(gpr[op.rt4]), vb); } void spu_recompiler::SHUFB(spu_opcode_t op) { - const XmmLink& v0 = XmmGet(op.rt, XmmType::Int); // v0 = mask + const XmmLink& v0 = XmmGet(op.rc, XmmType::Int); // v0 = mask const XmmLink& v1 = XmmAlloc(); const XmmLink& v2 = XmmAlloc(); const XmmLink& v3 = XmmAlloc(); @@ -2559,7 +2573,7 @@ void spu_recompiler::SHUFB(spu_opcode_t op) c->por(v1, v3); // v1 = select(op.rb, 00001111 - ((mask & 00011111) ^ 00010000)) | (v3) c->pandn(v4, v1); // filter result v4 = v1 & ((mask & 10000000 == 10000000) ? 0 : 0xff) c->por(vFF, v4); // final merge vFF = (mask & 10000000 == 10000000) ? ((mask & 11100000 == 11000000) ? 0xff : (mask & 11100000 == 11100000) ? 0x80 : 0) : (v1) - c->movdqa(SPU_OFF_128(gpr[op.rc]), vFF); + c->movdqa(SPU_OFF_128(gpr[op.rt4]), vFF); } void spu_recompiler::MPYA(spu_opcode_t op) @@ -2571,33 +2585,33 @@ void spu_recompiler::MPYA(spu_opcode_t op) c->pand(va, vi); c->pand(vb, vi); c->pmaddwd(va, vb); - c->paddd(va, SPU_OFF_128(gpr[op.rt])); - c->movdqa(SPU_OFF_128(gpr[op.rc]), va); + c->paddd(va, SPU_OFF_128(gpr[op.rc])); + c->movdqa(SPU_OFF_128(gpr[op.rt4]), va); } void spu_recompiler::FNMS(spu_opcode_t op) { const XmmLink& va = XmmGet(op.ra, XmmType::Float); - const XmmLink& vc = XmmGet(op.rt, XmmType::Float); + const XmmLink& vc = XmmGet(op.rc, XmmType::Float); c->mulps(va, SPU_OFF_128(gpr[op.rb])); c->subps(vc, va); - c->movaps(SPU_OFF_128(gpr[op.rc]), vc); + c->movaps(SPU_OFF_128(gpr[op.rt4]), vc); } void spu_recompiler::FMA(spu_opcode_t op) { const XmmLink& va = XmmGet(op.ra, XmmType::Float); c->mulps(va, SPU_OFF_128(gpr[op.rb])); - c->addps(va, SPU_OFF_128(gpr[op.rt])); - c->movaps(SPU_OFF_128(gpr[op.rc]), va); + c->addps(va, SPU_OFF_128(gpr[op.rc])); + c->movaps(SPU_OFF_128(gpr[op.rt4]), va); } void spu_recompiler::FMS(spu_opcode_t op) { const XmmLink& va = XmmGet(op.ra, XmmType::Float); c->mulps(va, SPU_OFF_128(gpr[op.rb])); - c->subps(va, SPU_OFF_128(gpr[op.rt])); - c->movaps(SPU_OFF_128(gpr[op.rc]), va); + c->subps(va, SPU_OFF_128(gpr[op.rc])); + c->movaps(SPU_OFF_128(gpr[op.rt4]), va); } void spu_recompiler::UNK(spu_opcode_t op) diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.h b/rpcs3/Emu/Cell/SPUASMJITRecompiler.h index 40a05e14e3..9655b19ce9 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.h +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.h @@ -44,27 +44,18 @@ private: class XmmLink { - friend class spu_recompiler; - - asmjit::X86XmmVar* const m_var; + asmjit::X86XmmVar* m_var; + public: XmmLink(asmjit::X86XmmVar*& xmm_var) : m_var(xmm_var) { xmm_var = nullptr; } - public: - XmmLink() = delete; + XmmLink(XmmLink&&) = default; // MoveConstructible + delete copy constructor and copy/move operators - XmmLink(const XmmLink&) = delete; - - XmmLink(XmmLink&& right) - : m_var(right.m_var) - { - } - - inline operator const asmjit::X86XmmVar&() const + operator asmjit::X86XmmVar&() const { return *m_var; } diff --git a/rpcs3/Emu/Cell/SPUAnalyser.cpp b/rpcs3/Emu/Cell/SPUAnalyser.cpp index a6dcbb5051..2f8ef5476a 100644 --- a/rpcs3/Emu/Cell/SPUAnalyser.cpp +++ b/rpcs3/Emu/Cell/SPUAnalyser.cpp @@ -9,7 +9,7 @@ const spu_opcode_table_t g_spu_itype{ DEFINE_SPU_OPCODES(spu_itype: std::shared_ptr SPUDatabase::find(const be_t* data, u64 key, u32 max_size) { - for (auto found = m_db.find(key); found != m_db.end(); found++) + for (auto found = m_db.find(key); found != m_db.end() && found->first == key; found++) { if (found->second->size > max_size) { @@ -249,7 +249,7 @@ std::shared_ptr SPUDatabase::analyse(const be_t* ls, u32 en } else // Other instructions (writing rt reg) { - const u32 rt = type == SELB || type == SHUFB || type == MPYA || type == FNMS || type == FMA || type == FMS ? op.rc : op.rt; + const u32 rt = type == SELB || type == SHUFB || type == MPYA || type == FNMS || type == FMA || type == FMS ? +op.rc : +op.rt; // Analyse link register access if (rt == 0) diff --git a/rpcs3/Emu/Cell/SPUDisAsm.h b/rpcs3/Emu/Cell/SPUDisAsm.h index d65eb1f369..0583d9fa04 100644 --- a/rpcs3/Emu/Cell/SPUDisAsm.h +++ b/rpcs3/Emu/Cell/SPUDisAsm.h @@ -300,7 +300,7 @@ private: } void STOPD(spu_opcode_t op) { - DisAsm("bihnz", spu_reg_name[op.rc], spu_reg_name[op.ra], spu_reg_name[op.rb]); + DisAsm("stopd", spu_reg_name[op.rc], spu_reg_name[op.ra], spu_reg_name[op.rb]); } void STQX(spu_opcode_t op) { @@ -698,73 +698,73 @@ private: //0 - 9 void CFLTS(spu_opcode_t op) { - DisAsm("cflts", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si8); + DisAsm("cflts", spu_reg_name[op.rt], spu_reg_name[op.ra], op.i8); } void CFLTU(spu_opcode_t op) { - DisAsm("cfltu", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si8); + DisAsm("cfltu", spu_reg_name[op.rt], spu_reg_name[op.ra], op.i8); } void CSFLT(spu_opcode_t op) { - DisAsm("csflt", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si8); + DisAsm("csflt", spu_reg_name[op.rt], spu_reg_name[op.ra], op.i8); } void CUFLT(spu_opcode_t op) { - DisAsm("cuflt", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si8); + DisAsm("cuflt", spu_reg_name[op.rt], spu_reg_name[op.ra], op.i8); } //0 - 8 void BRZ(spu_opcode_t op) { - DisAsm("brz", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("brz", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void STQA(spu_opcode_t op) { - DisAsm("stqa", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("stqa", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void BRNZ(spu_opcode_t op) { - DisAsm("brnz", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("brnz", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void BRHZ(spu_opcode_t op) { - DisAsm("brhz", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("brhz", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void BRHNZ(spu_opcode_t op) { - DisAsm("brhnz", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("brhnz", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void STQR(spu_opcode_t op) { - DisAsm("stqr", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("stqr", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void BRA(spu_opcode_t op) { - DisAsm("bra", DisAsmBranchTarget(op.si16)); + DisAsm("bra", DisAsmBranchTarget(op.i16)); } void LQA(spu_opcode_t op) { - DisAsm("lqa", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("lqa", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void BRASL(spu_opcode_t op) { - DisAsm("brasl", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("brasl", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void BR(spu_opcode_t op) { - DisAsm("br", DisAsmBranchTarget(op.si16)); + DisAsm("br", DisAsmBranchTarget(op.i16)); } void FSMBI(spu_opcode_t op) { - DisAsm("fsmbi", spu_reg_name[op.rt], op.si16); + DisAsm("fsmbi", spu_reg_name[op.rt], op.i16); } void BRSL(spu_opcode_t op) { - DisAsm("brsl", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("brsl", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void LQR(spu_opcode_t op) { - DisAsm("lqr", spu_reg_name[op.rt], DisAsmBranchTarget(op.si16)); + DisAsm("lqr", spu_reg_name[op.rt], DisAsmBranchTarget(op.i16)); } void IL(spu_opcode_t op) { @@ -772,15 +772,15 @@ private: } void ILHU(spu_opcode_t op) { - DisAsm("ilhu", spu_reg_name[op.rt], op.si16); + DisAsm("ilhu", spu_reg_name[op.rt], op.i16); } void ILH(spu_opcode_t op) { - DisAsm("ilh", spu_reg_name[op.rt], op.si16); + DisAsm("ilh", spu_reg_name[op.rt], op.i16); } void IOHL(spu_opcode_t op) { - DisAsm("iohl", spu_reg_name[op.rt], op.si16); + DisAsm("iohl", spu_reg_name[op.rt], op.i16); } //0 - 7 @@ -904,41 +904,41 @@ private: //0 - 6 void HBRA(spu_opcode_t op) { - DisAsm("hbra", DisAsmBranchTarget((op.r0h << 7) | op.rt), DisAsmBranchTarget(op.si16)); + DisAsm("hbra", DisAsmBranchTarget((op.r0h << 7) | op.rt), DisAsmBranchTarget(op.i16)); } void HBRR(spu_opcode_t op) { - DisAsm("hbrr", DisAsmBranchTarget((op.r0h << 7) | op.rt), DisAsmBranchTarget(op.si16)); + DisAsm("hbrr", DisAsmBranchTarget((op.r0h << 7) | op.rt), DisAsmBranchTarget(op.i16)); } void ILA(spu_opcode_t op) { DisAsm("ila", spu_reg_name[op.rt], op.i18); } - //0 - 3, rt <> rc + //0 - 3 void SELB(spu_opcode_t op) { - DisAsm("selb", spu_reg_name[op.rc], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rt]); + DisAsm("selb", spu_reg_name[op.rt4], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rc]); } void SHUFB(spu_opcode_t op) { - DisAsm("shufb", spu_reg_name[op.rc], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rt]); + DisAsm("shufb", spu_reg_name[op.rt4], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rc]); } void MPYA(spu_opcode_t op) { - DisAsm("mpya", spu_reg_name[op.rc], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rt]); + DisAsm("mpya", spu_reg_name[op.rt4], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rc]); } void FNMS(spu_opcode_t op) { - DisAsm("fnms", spu_reg_name[op.rc], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rt]); + DisAsm("fnms", spu_reg_name[op.rt4], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rc]); } void FMA(spu_opcode_t op) { - DisAsm("fma", spu_reg_name[op.rc], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rt]); + DisAsm("fma", spu_reg_name[op.rt4], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rc]); } void FMS(spu_opcode_t op) { - DisAsm("fms", spu_reg_name[op.rc], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rt]); + DisAsm("fms", spu_reg_name[op.rt4], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rc]); } void UNK(spu_opcode_t op) @@ -949,7 +949,7 @@ private: static const spu_opcode_table_t opcodes; public: - inline void do_disasm(u32 opcode) + void do_disasm(u32 opcode) { (this->*opcodes[opcode])({ opcode }); } diff --git a/rpcs3/Emu/Cell/SPUInterpreter.cpp b/rpcs3/Emu/Cell/SPUInterpreter.cpp index b94a57e7e5..9f20f09b67 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/SPUInterpreter.cpp @@ -210,45 +210,45 @@ void spu_interpreter::SHLH(SPUThread& spu, spu_opcode_t op) void spu_interpreter::ROTI(SPUThread& spu, spu_opcode_t op) { const auto a = spu.gpr[op.ra].vi; - const s32 n = op.si7 & 0x1f; + const s32 n = op.i7 & 0x1f; spu.gpr[op.rt].vi = _mm_or_si128(_mm_slli_epi32(a, n), _mm_srli_epi32(a, 32 - n)); } void spu_interpreter::ROTMI(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt].vi = _mm_srli_epi32(spu.gpr[op.ra].vi, -op.si7 & 0x3f); + spu.gpr[op.rt].vi = _mm_srli_epi32(spu.gpr[op.ra].vi, 0-op.i7 & 0x3f); } void spu_interpreter::ROTMAI(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt].vi = _mm_srai_epi32(spu.gpr[op.ra].vi, -op.si7 & 0x3f); + spu.gpr[op.rt].vi = _mm_srai_epi32(spu.gpr[op.ra].vi, 0-op.i7 & 0x3f); } void spu_interpreter::SHLI(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt].vi = _mm_slli_epi32(spu.gpr[op.ra].vi, op.si7 & 0x3f); + spu.gpr[op.rt].vi = _mm_slli_epi32(spu.gpr[op.ra].vi, op.i7 & 0x3f); } void spu_interpreter::ROTHI(SPUThread& spu, spu_opcode_t op) { const auto a = spu.gpr[op.ra].vi; - const s32 n = op.si7 & 0xf; + const s32 n = op.i7 & 0xf; spu.gpr[op.rt].vi = _mm_or_si128(_mm_slli_epi16(a, n), _mm_srli_epi16(a, 16 - n)); } void spu_interpreter::ROTHMI(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt].vi = _mm_srli_epi16(spu.gpr[op.ra].vi, -op.si7 & 0x1f); + spu.gpr[op.rt].vi = _mm_srli_epi16(spu.gpr[op.ra].vi, 0-op.i7 & 0x1f); } void spu_interpreter::ROTMAHI(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt].vi = _mm_srai_epi16(spu.gpr[op.ra].vi, -op.si7 & 0x1f); + spu.gpr[op.rt].vi = _mm_srai_epi16(spu.gpr[op.ra].vi, 0-op.i7 & 0x1f); } void spu_interpreter::SHLHI(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt].vi = _mm_slli_epi16(spu.gpr[op.ra].vi, op.si7 & 0x1f); + spu.gpr[op.rt].vi = _mm_slli_epi16(spu.gpr[op.ra].vi, op.i7 & 0x1f); } void spu_interpreter::A(SPUThread& spu, spu_opcode_t op) @@ -336,7 +336,7 @@ void spu_interpreter::STOPD(SPUThread& spu, spu_opcode_t op) void spu_interpreter::STQX(SPUThread& spu, spu_opcode_t op) { - spu.write128((spu.gpr[op.ra]._u32[3] + spu.gpr[op.rb]._u32[3]) & 0x3fff0, spu.gpr[op.rt]); + spu._ref((spu.gpr[op.ra]._u32[3] + spu.gpr[op.rb]._u32[3]) & 0x3fff0) = spu.gpr[op.rt]; } void spu_interpreter::BI(SPUThread& spu, spu_opcode_t op) @@ -410,7 +410,7 @@ void spu_interpreter::fast::FRSQEST(SPUThread& spu, spu_opcode_t op) void spu_interpreter::LQX(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt] = spu.read128((spu.gpr[op.ra]._u32[3] + spu.gpr[op.rb]._u32[3]) & 0x3fff0); + spu.gpr[op.rt] = spu._ref((spu.gpr[op.ra]._u32[3] + spu.gpr[op.rb]._u32[3]) & 0x3fff0); } void spu_interpreter::ROTQBYBI(SPUThread& spu, spu_opcode_t op) @@ -575,7 +575,7 @@ void spu_interpreter::ROTQBII(SPUThread& spu, spu_opcode_t op) void spu_interpreter::ROTQMBII(SPUThread& spu, spu_opcode_t op) { const auto a = spu.gpr[op.ra].vi; - const s32 n = -op.si7 & 0x7; + const s32 n = 0-op.i7 & 0x7; spu.gpr[op.rt].vi = _mm_or_si128(_mm_srli_epi64(a, n), _mm_slli_epi64(_mm_srli_si128(a, 8), 64 - n)); } @@ -593,7 +593,7 @@ void spu_interpreter::ROTQBYI(SPUThread& spu, spu_opcode_t op) void spu_interpreter::ROTQMBYI(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt].vi = _mm_shuffle_epi8(spu.gpr[op.ra].vi, g_spu_imm.srdq_pshufb[-op.si7 & 0x1f].vi); + spu.gpr[op.rt].vi = _mm_shuffle_epi8(spu.gpr[op.ra].vi, g_spu_imm.srdq_pshufb[0-op.i7 & 0x1f].vi); } void spu_interpreter::SHLQBYI(SPUThread& spu, spu_opcode_t op) @@ -977,7 +977,7 @@ void spu_interpreter::BRZ(SPUThread& spu, spu_opcode_t op) void spu_interpreter::STQA(SPUThread& spu, spu_opcode_t op) { - spu.write128((op.i16 << 2) & 0x3fff0, spu.gpr[op.rt]); + spu._ref(spu_ls_target(0, op.i16)) = spu.gpr[op.rt]; } void spu_interpreter::BRNZ(SPUThread& spu, spu_opcode_t op) @@ -1006,7 +1006,7 @@ void spu_interpreter::BRHNZ(SPUThread& spu, spu_opcode_t op) void spu_interpreter::STQR(SPUThread& spu, spu_opcode_t op) { - spu.write128(spu_branch_target(spu.pc, op.i16) & 0x3fff0, spu.gpr[op.rt]); + spu._ref(spu_ls_target(spu.pc, op.i16)) = spu.gpr[op.rt]; } void spu_interpreter::BRA(SPUThread& spu, spu_opcode_t op) @@ -1016,7 +1016,7 @@ void spu_interpreter::BRA(SPUThread& spu, spu_opcode_t op) void spu_interpreter::LQA(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt] = spu.read128((op.i16 << 2) & 0x3fff0); + spu.gpr[op.rt] = spu._ref(spu_ls_target(0, op.i16)); } void spu_interpreter::BRASL(SPUThread& spu, spu_opcode_t op) @@ -1045,7 +1045,7 @@ void spu_interpreter::BRSL(SPUThread& spu, spu_opcode_t op) void spu_interpreter::LQR(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt] = spu.read128(spu_branch_target(spu.pc, op.i16) & 0x3fff0); + spu.gpr[op.rt] = spu._ref(spu_ls_target(spu.pc, op.i16)); } void spu_interpreter::IL(SPUThread& spu, spu_opcode_t op) @@ -1121,12 +1121,12 @@ void spu_interpreter::AHI(SPUThread& spu, spu_opcode_t op) void spu_interpreter::STQD(SPUThread& spu, spu_opcode_t op) { - spu.write128((spu.gpr[op.ra]._s32[3] + (op.si10 << 4)) & 0x3fff0, spu.gpr[op.rt]); + spu._ref((spu.gpr[op.ra]._s32[3] + (op.si10 << 4)) & 0x3fff0) = spu.gpr[op.rt]; } void spu_interpreter::LQD(SPUThread& spu, spu_opcode_t op) { - spu.gpr[op.rt] = spu.read128((spu.gpr[op.ra]._s32[3] + (op.si10 << 4)) & 0x3fff0); + spu.gpr[op.rt] = spu._ref((spu.gpr[op.ra]._s32[3] + (op.si10 << 4)) & 0x3fff0); } void spu_interpreter::XORI(SPUThread& spu, spu_opcode_t op) @@ -1242,14 +1242,12 @@ void spu_interpreter::ILA(SPUThread& spu, spu_opcode_t op) void spu_interpreter::SELB(SPUThread& spu, spu_opcode_t op) { - // rt <> rc - spu.gpr[op.rc] = (spu.gpr[op.rt] & spu.gpr[op.rb]) | v128::andnot(spu.gpr[op.rt], spu.gpr[op.ra]); + spu.gpr[op.rt4] = (spu.gpr[op.rc] & spu.gpr[op.rb]) | v128::andnot(spu.gpr[op.rc], spu.gpr[op.ra]); } void spu_interpreter::SHUFB(SPUThread& spu, spu_opcode_t op) { - // rt <> rc - const auto index = _mm_xor_si128(spu.gpr[op.rt].vi, _mm_set1_epi32(0x0f0f0f0f)); + const auto index = _mm_xor_si128(spu.gpr[op.rc].vi, _mm_set1_epi32(0x0f0f0f0f)); const auto res1 = _mm_shuffle_epi8(spu.gpr[op.ra].vi, index); const auto bit4 = _mm_set1_epi32(0x10101010); const auto k1 = _mm_cmpeq_epi8(_mm_and_si128(index, bit4), bit4); @@ -1259,32 +1257,28 @@ void spu_interpreter::SHUFB(SPUThread& spu, spu_opcode_t op) const auto res3 = _mm_or_si128(res2, k2); const auto bit567 = _mm_set1_epi32(0xe0e0e0e0); const auto k3 = _mm_cmpeq_epi8(_mm_and_si128(index, bit567), bit567); - spu.gpr[op.rc].vi = _mm_sub_epi8(res3, _mm_and_si128(k3, _mm_set1_epi32(0x7f7f7f7f))); + spu.gpr[op.rt4].vi = _mm_sub_epi8(res3, _mm_and_si128(k3, _mm_set1_epi32(0x7f7f7f7f))); } void spu_interpreter::MPYA(SPUThread& spu, spu_opcode_t op) { - // rt <> rc const auto mask = _mm_set1_epi32(0xffff); - spu.gpr[op.rc].vi = _mm_add_epi32(spu.gpr[op.rt].vi, _mm_madd_epi16(_mm_and_si128(spu.gpr[op.ra].vi, mask), _mm_and_si128(spu.gpr[op.rb].vi, mask))); + spu.gpr[op.rt4].vi = _mm_add_epi32(spu.gpr[op.rc].vi, _mm_madd_epi16(_mm_and_si128(spu.gpr[op.ra].vi, mask), _mm_and_si128(spu.gpr[op.rb].vi, mask))); } void spu_interpreter::fast::FNMS(SPUThread& spu, spu_opcode_t op) { - // rt <> rc - spu.gpr[op.rc].vf = _mm_sub_ps(spu.gpr[op.rt].vf, _mm_mul_ps(spu.gpr[op.ra].vf, spu.gpr[op.rb].vf)); + spu.gpr[op.rt4].vf = _mm_sub_ps(spu.gpr[op.rc].vf, _mm_mul_ps(spu.gpr[op.ra].vf, spu.gpr[op.rb].vf)); } void spu_interpreter::fast::FMA(SPUThread& spu, spu_opcode_t op) { - // rt <> rc - spu.gpr[op.rc].vf = _mm_add_ps(_mm_mul_ps(spu.gpr[op.ra].vf, spu.gpr[op.rb].vf), spu.gpr[op.rt].vf); + spu.gpr[op.rt4].vf = _mm_add_ps(_mm_mul_ps(spu.gpr[op.ra].vf, spu.gpr[op.rb].vf), spu.gpr[op.rc].vf); } void spu_interpreter::fast::FMS(SPUThread& spu, spu_opcode_t op) { - // rt <> rc - spu.gpr[op.rc].vf = _mm_sub_ps(_mm_mul_ps(spu.gpr[op.ra].vf, spu.gpr[op.rb].vf), spu.gpr[op.rt].vf); + spu.gpr[op.rt4].vf = _mm_sub_ps(_mm_mul_ps(spu.gpr[op.ra].vf, spu.gpr[op.rb].vf), spu.gpr[op.rc].vf); } static void SetHostRoundingMode(u32 rn) @@ -1932,14 +1926,12 @@ void spu_interpreter::precise::CUFLT(SPUThread& spu, spu_opcode_t op) static void FMA(SPUThread& spu, spu_opcode_t op, bool neg, bool sub) { - // rt <> rc - SetHostRoundingMode(FPSCR_RN_ZERO); for (int w = 0; w < 4; w++) { float a = spu.gpr[op.ra]._f[w]; float b = neg ? -spu.gpr[op.rb]._f[w] : spu.gpr[op.rb]._f[w]; - float c = (neg != sub) ? -spu.gpr[op.rt]._f[w] : spu.gpr[op.rt]._f[w]; + float c = (neg != sub) ? -spu.gpr[op.rc]._f[w] : spu.gpr[op.rc]._f[w]; if (isdenormal(a)) { spu.fpscr.setSinglePrecisionExceptionFlags(w, FPSCR_SDIFF); @@ -2073,7 +2065,7 @@ static void FMA(SPUThread& spu, spu_opcode_t op, bool neg, bool sub) { result = +0.0f; } - spu.gpr[op.rc]._f[w] = result; + spu.gpr[op.rt4]._f[w] = result; } } diff --git a/rpcs3/Emu/Cell/SPUOpcodes.h b/rpcs3/Emu/Cell/SPUOpcodes.h index d2561317fb..25c02fb604 100644 --- a/rpcs3/Emu/Cell/SPUOpcodes.h +++ b/rpcs3/Emu/Cell/SPUOpcodes.h @@ -4,76 +4,23 @@ union spu_opcode_t { u32 opcode; - struct - { - u32 rt : 7; // 25..31, it's actually RC in 4-op instructions - u32 ra : 7; // 18..24 - u32 rb : 7; // 11..17 - u32 rc : 7; // 4..10, it's actually RT in 4-op instructions - }; - - struct - { - u32 : 14; // 18..31 - u32 i7 : 7; // 11..17 - }; - - struct - { - u32 : 14; // 18..31 - u32 i8 : 8; // 10..17 - }; - - struct - { - u32 : 7; // 25..31 - u32 i16 : 16; // 9..24 - }; - - struct - { - u32 : 7; // 25..31 - u32 i18 : 18; // 7..24 - }; - - struct - { - s32 : 14; // 18..31 - s32 si7 : 7; // 11..17 - }; - - struct - { - s32 : 14; // 18..31 - s32 si8 : 8; // 10..17 - }; - - struct - { - s32 : 14; // 18..31 - s32 si10 : 10; // 8..17 - }; - - struct - { - s32 : 7; // 25..31 - s32 si16 : 16; // 9..24 - s32 r0h : 2; // 7..8 - }; - - struct - { - s32 : 14; // 18..31 - s32 roh : 2; // 16..17 - }; - - struct - { - u32 : 18; // 14..31 - u32 e : 1; // 13, "enable interrupts" bit - u32 d : 1; // 12, "disable interrupts" bit - u32 c : 1; // 11, "C" bit for SYNC instruction - }; + bf_t rt; // 25..31, for 3-op instructions + bf_t rc; // 25..31 + bf_t ra; // 18..24 + bf_t rb; // 11..17 + bf_t rt4; // 4..10, for 4-op instructions + bf_t e; // 13, "enable interrupts" bit + bf_t d; // 12, "disable interrupts" bit + bf_t c; // 11, "C" bit for SYNC instruction + bf_t r0h; // 7..8, signed + bf_t roh; // 16..17, signed + bf_t i7; // 11..17 + bf_t si7; // 11..17, signed + bf_t i8; // 10..17 + bf_t si10; // 8..17, signed + bf_t i16; // 9..24 + bf_t si16; // 9..24, signed + bf_t i18; // 7..24 }; #define DEFINE_SPU_OPCODES(ns) { \ @@ -309,14 +256,19 @@ public: } // access opcode table - inline T operator [](u32 opcode_data) const + T operator [](u32 opcode_data) const { // the whole decoding process is shifting opcode data return m_data[opcode_data >> 21]; } }; -inline u32 spu_branch_target(u32 pc, s32 imm = 0) +inline u32 spu_branch_target(u32 pc, u32 imm = 0) { return (pc + (imm << 2)) & 0x3fffc; } + +inline u32 spu_ls_target(u32 pc, u32 imm = 0) +{ + return (pc + (imm << 2)) & 0x3fff0; +} diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 9c4be24cff..d1086897ff 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -24,7 +24,7 @@ u32 SPURecompilerDecoder::DecodeMemory(const u32 address) } // get SPU LS pointer - const auto _ls = vm::get_ptr>(spu.offset); + const auto _ls = vm::ps3::_ptr(spu.offset); // always validate (TODO) const auto func = db->analyse(_ls, spu.pc); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 252e95cf02..39799ea018 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -114,7 +114,7 @@ void SPUThread::task() const auto& table = Ini.SPUDecoderMode.GetValue() == 0 ? spu_interpreter::precise::g_spu_opcode_table : spu_interpreter::fast::g_spu_opcode_table; // LS base address - const auto base = vm::get_ptr>(offset); + const auto base = vm::_ptr(offset); while (true) { @@ -238,7 +238,7 @@ void SPUThread::fast_call(u32 ls_addr) } // LS:0x0: this is originally the entry point of the interrupt handler, but interrupts are not implemented - write32(0x0, 2); + _ref(0) = 0x00000002; // STOP 2 auto old_pc = pc; auto old_lr = gpr[0]._u32[3]; @@ -291,7 +291,7 @@ void SPUThread::do_dma_transfer(u32 cmd, spu_mfc_arg_t args) } else if ((cmd & MFC_PUT_CMD) && args.size == 4 && (offset == SYS_SPU_THREAD_SNR1 || offset == SYS_SPU_THREAD_SNR2)) { - spu.push_snr(SYS_SPU_THREAD_SNR2 == offset, read32(args.lsa)); + spu.push_snr(SYS_SPU_THREAD_SNR2 == offset, _ref(args.lsa)); return; } else @@ -310,13 +310,13 @@ void SPUThread::do_dma_transfer(u32 cmd, spu_mfc_arg_t args) case MFC_PUT_CMD: case MFC_PUTR_CMD: { - memcpy(vm::get_ptr(eal), vm::get_ptr(offset + args.lsa), args.size); + std::memcpy(vm::base(eal), vm::base(offset + args.lsa), args.size); return; } case MFC_GET_CMD: { - memcpy(vm::get_ptr(offset + args.lsa), vm::get_ptr(eal), args.size); + std::memcpy(vm::base(offset + args.lsa), vm::base(eal), args.size); return; } } @@ -422,7 +422,7 @@ void SPUThread::process_mfc_cmd(u32 cmd) const u32 raddr = VM_CAST(ch_mfc_args.ea); - vm::reservation_acquire(vm::get_ptr(offset + ch_mfc_args.lsa), raddr, 128); + vm::reservation_acquire(vm::base(offset + ch_mfc_args.lsa), raddr, 128); if (last_raddr) { @@ -441,7 +441,7 @@ void SPUThread::process_mfc_cmd(u32 cmd) break; } - if (vm::reservation_update(VM_CAST(ch_mfc_args.ea), vm::get_ptr(offset + ch_mfc_args.lsa), 128)) + if (vm::reservation_update(VM_CAST(ch_mfc_args.ea), vm::base(offset + ch_mfc_args.lsa), 128)) { if (last_raddr == 0) { @@ -475,7 +475,7 @@ void SPUThread::process_mfc_cmd(u32 cmd) vm::reservation_op(VM_CAST(ch_mfc_args.ea), 128, [this]() { - std::memcpy(vm::priv_ptr(VM_CAST(ch_mfc_args.ea)), vm::get_ptr(offset + ch_mfc_args.lsa), 128); + std::memcpy(vm::base_priv(VM_CAST(ch_mfc_args.ea)), vm::base(offset + ch_mfc_args.lsa), 128); }); if (last_raddr != 0 && vm::g_tls_did_break_reservation) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 726ad61ad1..e74ddcccb0 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -618,27 +618,22 @@ public: void stop_and_signal(u32 code); void halt(); - u8 read8(u32 lsa) const { return vm::read8(lsa + offset); } - u16 read16(u32 lsa) const { return vm::ps3::read16(lsa + offset); } - u32 read32(u32 lsa) const { return vm::ps3::read32(lsa + offset); } - u64 read64(u32 lsa) const { return vm::ps3::read64(lsa + offset); } - v128 read128(u32 lsa) const { return vm::ps3::read128(lsa + offset); } + // Convert specified SPU LS address to a pointer of specified (possibly converted to BE) type + template inline to_be_t* _ptr(u32 lsa) + { + return static_cast*>(vm::base(offset + lsa)); + } - void write8(u32 lsa, u8 data) const { vm::write8(lsa + offset, data); } - void write16(u32 lsa, u16 data) const { vm::ps3::write16(lsa + offset, data); } - void write32(u32 lsa, u32 data) const { vm::ps3::write32(lsa + offset, data); } - void write64(u32 lsa, u64 data) const { vm::ps3::write64(lsa + offset, data); } - void write128(u32 lsa, v128 data) const { vm::ps3::write128(lsa + offset, data); } - - void write16(u32 lsa, be_t data) const { vm::ps3::write16(lsa + offset, data); } - void write32(u32 lsa, be_t data) const { vm::ps3::write32(lsa + offset, data); } - void write64(u32 lsa, be_t data) const { vm::ps3::write64(lsa + offset, data); } - void write128(u32 lsa, be_t data) const { vm::ps3::write128(lsa + offset, data); } + // Convert specified SPU LS address to a reference of specified (possibly converted to BE) type + template inline to_be_t& _ref(u32 lsa) + { + return *_ptr(lsa); + } void RegisterHleFunction(u32 addr, std::function function) { m_addr_to_hle_function_map[addr] = function; - write32(addr, 0x00000003); // STOP 3 + _ref(addr) = 0x00000003; // STOP 3 } void UnregisterHleFunction(u32 addr) diff --git a/rpcs3/Emu/FS/vfsLocalDir.cpp b/rpcs3/Emu/FS/vfsLocalDir.cpp index 063b7d5427..5048550061 100644 --- a/rpcs3/Emu/FS/vfsLocalDir.cpp +++ b/rpcs3/Emu/FS/vfsLocalDir.cpp @@ -20,7 +20,7 @@ bool vfsLocalDir::Open(const std::string& path) std::string name; fs::stat_t file_info; - for (bool is_ok = m_dir.get_first(name, file_info); is_ok; is_ok = m_dir.get_next(name, file_info)) + while (m_dir.read(name, file_info)) { m_entries.emplace_back(); diff --git a/rpcs3/Emu/FS/vfsStreamMemory.cpp b/rpcs3/Emu/FS/vfsStreamMemory.cpp index c05196adaf..35dd1830af 100644 --- a/rpcs3/Emu/FS/vfsStreamMemory.cpp +++ b/rpcs3/Emu/FS/vfsStreamMemory.cpp @@ -10,7 +10,7 @@ u64 vfsStreamMemory::Write(const void* src, u64 count) count = m_size - m_pos; } - memcpy(vm::get_ptr(VM_CAST(m_addr + m_pos)), src, count); + std::memcpy(vm::base(VM_CAST(m_addr + m_pos)), src, count); m_pos += count; return count; } @@ -23,7 +23,7 @@ u64 vfsStreamMemory::Read(void* dst, u64 count) count = m_size - m_pos; } - memcpy(dst, vm::get_ptr(VM_CAST(m_addr + m_pos)), count); + std::memcpy(dst, vm::base(VM_CAST(m_addr + m_pos)), count); m_pos += count; return count; } diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index f35e01a7c8..a50dc7c51d 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -53,7 +53,7 @@ namespace idm thread_local extern u32 g_tls_last_id; // can be called from the constructor called through make() or make_ptr() to get the ID of the object being created - inline static u32 get_last_id() + static inline u32 get_last_id() { return g_tls_last_id; } diff --git a/rpcs3/Emu/Io/KeyboardHandler.h b/rpcs3/Emu/Io/KeyboardHandler.h index c2acaa3941..236896fb2d 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.h +++ b/rpcs3/Emu/Io/KeyboardHandler.h @@ -326,4 +326,4 @@ public: std::vector& GetButtons(const u32 keyboard) { return m_keyboards[keyboard].m_buttons; } KbData& GetData(const u32 keyboard) { return m_keyboards[keyboard].m_data; } KbConfig& GetConfig(const u32 keyboard) { return m_keyboards[keyboard].m_config; } -}; \ No newline at end of file +}; diff --git a/rpcs3/Emu/Io/MouseHandler.h b/rpcs3/Emu/Io/MouseHandler.h index a2aeeede32..2e6167b676 100644 --- a/rpcs3/Emu/Io/MouseHandler.h +++ b/rpcs3/Emu/Io/MouseHandler.h @@ -157,4 +157,4 @@ public: std::vector& GetMice() { return m_mice; } MouseData& GetData(const u32 mouse) { return m_mice[mouse].m_data; } MouseRawData& GetRawData(const u32 mouse) { return m_mice[mouse].m_rawdata; } -}; \ No newline at end of file +}; diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index 4937d90cbb..47a27d190e 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -277,4 +277,4 @@ public: std::vector& GetPads() { return m_pads; } std::vector