diff --git a/Utilities/BEType.h b/Utilities/BEType.h index ec2ba15605..38d01a9952 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -2,7 +2,7 @@ #define IS_LE_MACHINE -union _CRT_ALIGN(16) u128 +union u128 { u64 _u64[2]; s64 _s64[2]; @@ -107,12 +107,12 @@ union _CRT_ALIGN(16) u128 { } - __forceinline operator bool() const + force_inline operator bool() const { return (data & mask) != 0; } - __forceinline bit_element& operator = (const bool right) + force_inline bit_element& operator = (const bool right) { if (right) { @@ -125,7 +125,7 @@ union _CRT_ALIGN(16) u128 return *this; } - __forceinline bit_element& operator = (const bit_element& right) + force_inline bit_element& operator = (const bit_element& right) { if (right) { @@ -249,77 +249,77 @@ union _CRT_ALIGN(16) u128 return ret; } - static __forceinline u128 add8(const u128& left, const u128& right) + static force_inline u128 add8(const u128& left, const u128& right) { return fromV(_mm_add_epi8(left.vi, right.vi)); } - static __forceinline u128 add16(const u128& left, const u128& right) + static force_inline u128 add16(const u128& left, const u128& right) { return fromV(_mm_add_epi16(left.vi, right.vi)); } - static __forceinline u128 add32(const u128& left, const u128& right) + static force_inline u128 add32(const u128& left, const u128& right) { return fromV(_mm_add_epi32(left.vi, right.vi)); } - static __forceinline u128 addfs(const u128& left, const u128& right) + static force_inline u128 addfs(const u128& left, const u128& right) { return fromF(_mm_add_ps(left.vf, right.vf)); } - static __forceinline u128 addfd(const u128& left, const u128& right) + static force_inline u128 addfd(const u128& left, const u128& right) { return fromD(_mm_add_pd(left.vd, right.vd)); } - static __forceinline u128 sub8(const u128& left, const u128& right) + static force_inline u128 sub8(const u128& left, const u128& right) { return fromV(_mm_sub_epi8(left.vi, right.vi)); } - static __forceinline u128 sub16(const u128& left, const u128& right) + static force_inline u128 sub16(const u128& left, const u128& right) { return fromV(_mm_sub_epi16(left.vi, right.vi)); } - static __forceinline u128 sub32(const u128& left, const u128& right) + static force_inline u128 sub32(const u128& left, const u128& right) { return fromV(_mm_sub_epi32(left.vi, right.vi)); } - static __forceinline u128 subfs(const u128& left, const u128& right) + static force_inline u128 subfs(const u128& left, const u128& right) { return fromF(_mm_sub_ps(left.vf, right.vf)); } - static __forceinline u128 subfd(const u128& left, const u128& right) + static force_inline u128 subfd(const u128& left, const u128& right) { return fromD(_mm_sub_pd(left.vd, right.vd)); } - static __forceinline u128 maxu8(const u128& left, const u128& right) + static force_inline u128 maxu8(const u128& left, const u128& right) { return fromV(_mm_max_epu8(left.vi, right.vi)); } - static __forceinline u128 minu8(const u128& left, const u128& right) + static force_inline u128 minu8(const u128& left, const u128& right) { return fromV(_mm_min_epu8(left.vi, right.vi)); } - static __forceinline u128 eq8(const u128& left, const u128& right) + static force_inline u128 eq8(const u128& left, const u128& right) { return fromV(_mm_cmpeq_epi8(left.vi, right.vi)); } - static __forceinline u128 eq16(const u128& left, const u128& right) + static force_inline u128 eq16(const u128& left, const u128& right) { return fromV(_mm_cmpeq_epi16(left.vi, right.vi)); } - static __forceinline u128 eq32(const u128& left, const u128& right) + static force_inline u128 eq32(const u128& left, const u128& right) { return fromV(_mm_cmpeq_epi32(left.vi, right.vi)); } @@ -334,17 +334,17 @@ union _CRT_ALIGN(16) u128 return (_u64[0] != right._u64[0]) || (_u64[1] != right._u64[1]); } - __forceinline u128 operator | (const u128& right) const + force_inline u128 operator | (const u128& right) const { return fromV(_mm_or_si128(vi, right.vi)); } - __forceinline u128 operator & (const u128& right) const + force_inline u128 operator & (const u128& right) const { return fromV(_mm_and_si128(vi, right.vi)); } - __forceinline u128 operator ^ (const u128& right) const + force_inline u128 operator ^ (const u128& right) const { return fromV(_mm_xor_si128(vi, right.vi)); } @@ -354,18 +354,18 @@ union _CRT_ALIGN(16) u128 return from64(~_u64[0], ~_u64[1]); } - __forceinline bool is_any_1() const // check if any bit is 1 + force_inline bool is_any_1() const // check if any bit is 1 { return _u64[0] || _u64[1]; } - __forceinline bool is_any_0() const // check if any bit is 0 + force_inline bool is_any_0() const // check if any bit is 0 { return ~_u64[0] || ~_u64[1]; } // result = (~left) & (right) - static __forceinline u128 andnot(const u128& left, const u128& right) + static force_inline u128 andnot(const u128& left, const u128& right) { return fromV(_mm_andnot_si128(left.vi, right.vi)); } @@ -379,7 +379,7 @@ union _CRT_ALIGN(16) u128 std::string to_xyzw() const; - static __forceinline u128 byteswap(const u128 val) + static force_inline u128 byteswap(const u128 val) { u128 ret; ret._u64[0] = _byteswap_uint64(val._u64[1]); @@ -388,10 +388,11 @@ union _CRT_ALIGN(16) u128 } }; -#ifndef InterlockedCompareExchange -static __forceinline u128 InterlockedCompareExchange(volatile u128* dest, u128 exch, u128 comp) +static_assert(__alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 size or alignment"); + +static force_inline u128 sync_val_compare_and_swap(volatile u128* dest, u128 comp, u128 exch) { -#if defined(__GNUG__) +#if !defined(_MSC_VER) auto res = __sync_val_compare_and_swap((volatile __int128_t*)dest, (__int128_t&)comp, (__int128_t&)exch); return (u128&)res; #else @@ -399,60 +400,51 @@ static __forceinline u128 InterlockedCompareExchange(volatile u128* dest, u128 e return comp; #endif } -#endif -static __forceinline bool InterlockedCompareExchangeTest(volatile u128* dest, u128 exch, u128 comp) +static force_inline bool sync_bool_compare_and_swap(volatile u128* dest, u128 comp, u128 exch) { -#if defined(__GNUG__) +#if !defined(_MSC_VER) return __sync_bool_compare_and_swap((volatile __int128_t*)dest, (__int128_t&)comp, (__int128_t&)exch); #else return _InterlockedCompareExchange128((volatile long long*)dest, exch._u64[1], exch._u64[0], (long long*)&comp) != 0; #endif } -#ifndef InterlockedExchange -static __forceinline u128 InterlockedExchange(volatile u128* dest, u128 value) +static force_inline u128 sync_lock_test_and_set(volatile u128* dest, u128 value) { while (true) { const u128 old = *(u128*)dest; - if (InterlockedCompareExchangeTest(dest, value, old)) return old; + if (sync_bool_compare_and_swap(dest, old, value)) return old; } } -#endif -#ifndef InterlockedOr -static __forceinline u128 InterlockedOr(volatile u128* dest, u128 value) +static force_inline u128 sync_fetch_and_or(volatile u128* dest, u128 value) { while (true) { const u128 old = *(u128*)dest; - if (InterlockedCompareExchangeTest(dest, old | value, old)) return old; + if (sync_bool_compare_and_swap(dest, old, value | old)) return old; } } -#endif -#ifndef InterlockedAnd -static __forceinline u128 InterlockedAnd(volatile u128* dest, u128 value) +static force_inline u128 sync_fetch_and_and(volatile u128* dest, u128 value) { while (true) { const u128 old = *(u128*)dest; - if (InterlockedCompareExchangeTest(dest, old & value, old)) return old; + if (sync_bool_compare_and_swap(dest, old, value & old)) return old; } } -#endif -#ifndef InterlockedXor -static __forceinline u128 InterlockedXor(volatile u128* dest, u128 value) +static force_inline u128 sync_fetch_and_xor(volatile u128* dest, u128 value) { while (true) { const u128 old = *(u128*)dest; - if (InterlockedCompareExchangeTest(dest, old ^ value, old)) return old; + if (sync_bool_compare_and_swap(dest, old, value ^ old)) return old; } } -#endif #define re16(val) _byteswap_ushort(val) #define re32(val) _byteswap_ulong(val) @@ -463,12 +455,12 @@ template struct se_t; template struct se_t { - static __forceinline u8 to_be(const T& src) + static force_inline u8 to_be(const T& src) { return (u8&)src; } - static __forceinline T from_be(const u8 src) + static force_inline T from_be(const u8 src) { return (T&)src; } @@ -476,12 +468,12 @@ template struct se_t template struct se_t { - static __forceinline u16 to_be(const T& src) + static force_inline u16 to_be(const T& src) { return _byteswap_ushort((u16&)src); } - static __forceinline T from_be(const u16 src) + static force_inline T from_be(const u16 src) { const u16 res = _byteswap_ushort(src); return (T&)res; @@ -490,12 +482,12 @@ template struct se_t template struct se_t { - static __forceinline u32 to_be(const T& src) + static force_inline u32 to_be(const T& src) { return _byteswap_ulong((u32&)src); } - static __forceinline T from_be(const u32 src) + static force_inline T from_be(const u32 src) { const u32 res = _byteswap_ulong(src); return (T&)res; @@ -504,12 +496,12 @@ template struct se_t template struct se_t { - static __forceinline u64 to_be(const T& src) + static force_inline u64 to_be(const T& src) { return _byteswap_uint64((u64&)src); } - static __forceinline T from_be(const u64 src) + static force_inline T from_be(const u64 src) { const u64 res = _byteswap_uint64(src); return (T&)res; @@ -518,12 +510,12 @@ template struct se_t template struct se_t { - static __forceinline u128 to_be(const T& src) + static force_inline u128 to_be(const T& src) { return u128::byteswap((u128&)src); } - static __forceinline T from_be(const u128& src) + static force_inline T from_be(const u128& src) { const u128 res = u128::byteswap(src); return (T&)res; @@ -613,7 +605,7 @@ private: template struct _convert { - static __forceinline be_t& func(Tfrom& be_value) + static force_inline be_t& func(Tfrom& be_value) { Tto res = be_value; return (be_t&)res; @@ -623,7 +615,7 @@ private: template struct _convert { - static __forceinline be_t& func(Tfrom& be_value) + static force_inline be_t& func(Tfrom& be_value) { Tto res = se_t::func(se_t::func(be_value)); return (be_t&)res; @@ -633,7 +625,7 @@ private: template struct _convert { - static __forceinline be_t& func(Tfrom& be_value) + static force_inline be_t& func(Tfrom& be_value) { Tto res = be_value >> ((sizeof(Tfrom)-sizeof(Tto)) * 8); return (be_t&)res; @@ -683,7 +675,7 @@ public: } //get value in current machine byte ordering - __forceinline type value() const + force_inline type value() const { #ifdef IS_LE_MACHINE return ToLE(); @@ -882,7 +874,7 @@ template struct _se, T1, value> : pub template struct convert_le_be_t { - static Tto func(Tfrom&& value) + static Tto func(Tfrom value) { return (Tto)value; } @@ -891,7 +883,7 @@ struct convert_le_be_t template struct convert_le_be_t, Tfrom> { - static be_t func(Tfrom&& value) + static be_t func(Tfrom value) { return be_t::make(value); } @@ -900,7 +892,7 @@ struct convert_le_be_t, Tfrom> template struct convert_le_be_t, be_t> { - static be_t func(be_t&& value) + static be_t func(be_t value) { return value; } @@ -909,20 +901,24 @@ struct convert_le_be_t, be_t> template struct convert_le_be_t> { - static Tto func(be_t&& value) + static Tto func(be_t value) { return value.value(); } }; template -__forceinline Tto convert_le_be(Tfrom&& value) +force_inline Tto convert_le_be(Tfrom value) { return convert_le_be_t::func(value); } template -__forceinline void convert_le_be(Tto& dst, Tfrom&& src) +force_inline void convert_le_be(Tto& dst, Tfrom src) { dst = convert_le_be_t::func(src); } + +template using le_t = T; + +template struct to_le_t { using type = T; }; diff --git a/Utilities/File.cpp b/Utilities/File.cpp index b11e115d81..d79cdb2718 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -136,8 +136,8 @@ bool fs::stat(const std::string& path, stat_t& info) info.mtime = to_time_t(attrs.ftLastWriteTime); info.ctime = to_time_t(attrs.ftCreationTime); #else - struct stat64 file_info; - if (stat64(path.c_str(), &file_info) < 0) + struct stat file_info; + if (stat(path.c_str(), &file_info) < 0) { return false; } @@ -174,8 +174,8 @@ bool fs::is_file(const std::string& file) return (attrs & FILE_ATTRIBUTE_DIRECTORY) == 0; #else - struct stat64 file_info; - if (stat64(file.c_str(), &file_info) < 0) + struct stat file_info; + if (stat(file.c_str(), &file_info) < 0) { return false; } @@ -195,8 +195,8 @@ bool fs::is_dir(const std::string& dir) return (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0; #else - struct stat64 file_info; - if (stat64(dir.c_str(), &file_info) < 0) + struct stat file_info; + if (stat(dir.c_str(), &file_info) < 0) { return false; } @@ -364,7 +364,7 @@ bool fs::truncate_file(const std::string& file, u64 length) #ifdef _WIN32 if (!::truncate_file(file, length)) #else - if (truncate64(file.c_str(), length)) + if (::truncate(file.c_str(), length)) #endif { LOG_WARNING(GENERAL, "Error resizing file '%s' to 0x%llx: 0x%llx", file, length, GET_API_ERROR); @@ -480,7 +480,7 @@ bool fs::file::trunc(u64 size) const return true; // TODO #else - return !ftruncate64(m_fd, size); + return !::ftruncate(m_fd, size); #endif } @@ -501,8 +501,8 @@ bool fs::file::stat(stat_t& info) const info.mtime = to_time_t(basic_info.ChangeTime); info.ctime = to_time_t(basic_info.CreationTime); #else - struct stat64 file_info; - if (fstat64(m_fd, &file_info) < 0) + struct stat file_info; + if (fstat(m_fd, &file_info) < 0) { return false; } @@ -580,7 +580,7 @@ u64 fs::file::seek(u64 offset, u32 mode) const return pos.QuadPart; #else - return lseek64(m_fd, offset, mode); + return ::lseek(m_fd, offset, mode); #endif } @@ -595,8 +595,8 @@ u64 fs::file::size() const return size.QuadPart; #else - struct stat64 file_info; - if (fstat64(m_fd, &file_info) < 0) + struct stat file_info; + if (::fstat(m_fd, &file_info) < 0) { return -1; } @@ -766,8 +766,8 @@ bool fs::dir::get_next(std::string& name, stat_t& info) #else const auto found = ::readdir((DIR*)m_dd); - struct stat64 file_info; - if (!found || fstatat64(::dirfd((DIR*)m_dd), found->d_name, &file_info, 0) < 0) + struct stat file_info; + if (!found || ::fstatat(::dirfd((DIR*)m_dd), found->d_name, &file_info, 0) < 0) { return false; } diff --git a/Utilities/GNU.h b/Utilities/GNU.h index 9d876d8ce8..d592131297 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -2,22 +2,28 @@ #include -#ifdef _WIN32 +#if defined(_MSC_VER) #define thread_local __declspec(thread) #elif __APPLE__ #define thread_local __thread #endif -#ifdef _WIN32 -#define __noinline __declspec(noinline) +#if defined(_MSC_VER) +#define never_inline __declspec(noinline) #else -#define __noinline __attribute__((noinline)) +#define never_inline __attribute__((noinline)) #endif -#ifdef _WIN32 -#define __safebuffers __declspec(safebuffers) +#if defined(_MSC_VER) +#define safe_buffers __declspec(safebuffers) #else -#define __safebuffers +#define safe_buffers +#endif + +#if defined(_MSC_VER) +#define force_inline __forceinline +#else +#define force_inline __attribute__((always_inline)) #endif template @@ -37,7 +43,7 @@ void strcpy_trunc(char(&dst)[size], const char(&src)[rsize]) } #if defined(__GNUG__) -#include + #include #include @@ -46,12 +52,10 @@ void strcpy_trunc(char(&dst)[size], const char(&src)[rsize]) #endif #define _fpclass(x) std::fpclassify(x) -#define __forceinline __attribute__((always_inline)) #define _byteswap_ushort(x) __builtin_bswap16(x) #define _byteswap_ulong(x) __builtin_bswap32(x) #define _byteswap_uint64(x) __builtin_bswap64(x) #define INFINITE 0xFFFFFFFF -#define _CRT_ALIGN(x) __attribute__((aligned(x))) inline uint64_t __umulh(uint64_t a, uint64_t b) { @@ -67,10 +71,8 @@ inline int64_t __mulh(int64_t a, int64_t b) return result; } - -void * _aligned_malloc(size_t size, size_t alignment); - #ifdef __APPLE__ + int clock_gettime(int foo, struct timespec *ts); #define wxIsNaN(x) ((x) != (x)) @@ -80,220 +82,227 @@ int clock_gettime(int foo, struct timespec *ts); #endif /* __APPLE__ */ -#define _aligned_free free - -#define DWORD int32_t -#endif - -#ifndef InterlockedCompareExchange -static __forceinline uint8_t InterlockedCompareExchange(volatile uint8_t* dest, uint8_t exch, uint8_t comp) +template static inline typename std::enable_if::value, T>::type sync_val_compare_and_swap(volatile T* dest, T2 comp, T2 exch) { -#if defined(__GNUG__) return __sync_val_compare_and_swap(dest, comp, exch); -#else +} + +template static inline typename std::enable_if::value, bool>::type sync_bool_compare_and_swap(volatile T* dest, T2 comp, T2 exch) +{ + return __sync_bool_compare_and_swap(dest, comp, exch); +} + +template static inline typename std::enable_if::value, T>::type sync_lock_test_and_set(volatile T* dest, T2 value) +{ + return __sync_lock_test_and_set(dest, value); +} + +template static inline typename std::enable_if::value, T>::type sync_fetch_and_add(volatile T* dest, T2 value) +{ + return __sync_fetch_and_add(dest, value); +} + +template static inline typename std::enable_if::value, T>::type sync_fetch_and_sub(volatile T* dest, T2 value) +{ + return __sync_fetch_and_sub(dest, value); +} + +template static inline typename std::enable_if::value, T>::type sync_fetch_and_or(volatile T* dest, T2 value) +{ + return __sync_fetch_and_or(dest, value); +} + +template static inline typename std::enable_if::value, T>::type sync_fetch_and_and(volatile T* dest, T2 value) +{ + return __sync_fetch_and_and(dest, value); +} + +template static inline typename std::enable_if::value, T>::type sync_fetch_and_xor(volatile T* dest, T2 value) +{ + return __sync_fetch_and_xor(dest, value); +} + +#endif /* __GNUG__ */ + +#if defined(_MSC_VER) + +// atomic compare and swap functions + +static force_inline uint8_t sync_val_compare_and_swap(volatile uint8_t* dest, uint8_t comp, uint8_t exch) +{ return _InterlockedCompareExchange8((volatile char*)dest, exch, comp); -#endif } -static __forceinline uint16_t InterlockedCompareExchange(volatile uint16_t* dest, uint16_t exch, uint16_t comp) + +static force_inline uint16_t sync_val_compare_and_swap(volatile uint16_t* dest, uint16_t comp, uint16_t exch) { -#if defined(__GNUG__) - return __sync_val_compare_and_swap(dest, comp, exch); -#else return _InterlockedCompareExchange16((volatile short*)dest, exch, comp); -#endif } -static __forceinline uint32_t InterlockedCompareExchange(volatile uint32_t* dest, uint32_t exch, uint32_t comp) + +static force_inline uint32_t sync_val_compare_and_swap(volatile uint32_t* dest, uint32_t comp, uint32_t exch) { -#if defined(__GNUG__) - return __sync_val_compare_and_swap(dest, comp, exch); -#else return _InterlockedCompareExchange((volatile long*)dest, exch, comp); -#endif } -static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest, uint64_t exch, uint64_t comp) + +static force_inline uint64_t sync_val_compare_and_swap(volatile uint64_t* dest, uint64_t comp, uint64_t exch) { -#if defined(__GNUG__) - return __sync_val_compare_and_swap(dest, comp, exch); -#else return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp); -#endif } -#endif -static __forceinline bool InterlockedCompareExchangeTest(volatile uint8_t* dest, uint8_t exch, uint8_t comp) +static force_inline bool sync_bool_compare_and_swap(volatile uint8_t* dest, uint8_t comp, uint8_t exch) { -#if defined(__GNUG__) - return __sync_bool_compare_and_swap(dest, comp, exch); -#else return (uint8_t)_InterlockedCompareExchange8((volatile char*)dest, exch, comp) == comp; -#endif } -static __forceinline bool InterlockedCompareExchangeTest(volatile uint16_t* dest, uint16_t exch, uint16_t comp) + +static force_inline bool sync_bool_compare_and_swap(volatile uint16_t* dest, uint16_t comp, uint16_t exch) { -#if defined(__GNUG__) - return __sync_bool_compare_and_swap(dest, comp, exch); -#else return (uint16_t)_InterlockedCompareExchange16((volatile short*)dest, exch, comp) == comp; -#endif } -static __forceinline bool InterlockedCompareExchangeTest(volatile uint32_t* dest, uint32_t exch, uint32_t comp) + +static force_inline bool sync_bool_compare_and_swap(volatile uint32_t* dest, uint32_t comp, uint32_t exch) { -#if defined(__GNUG__) - return __sync_bool_compare_and_swap(dest, comp, exch); -#else return (uint32_t)_InterlockedCompareExchange((volatile long*)dest, exch, comp) == comp; -#endif } -static __forceinline bool InterlockedCompareExchangeTest(volatile uint64_t* dest, uint64_t exch, uint64_t comp) + +static force_inline bool sync_bool_compare_and_swap(volatile uint64_t* dest, uint64_t comp, uint64_t exch) { -#if defined(__GNUG__) - return __sync_bool_compare_and_swap(dest, comp, exch); -#else return (uint64_t)_InterlockedCompareExchange64((volatile long long*)dest, exch, comp) == comp; -#endif } -#ifndef InterlockedExchange -static __forceinline uint8_t InterlockedExchange(volatile uint8_t* dest, uint8_t value) +// atomic exchange functions + +static force_inline uint8_t sync_lock_test_and_set(volatile uint8_t* dest, uint8_t value) { -#if defined(__GNUG__) - return __sync_lock_test_and_set(dest, value); -#else return _InterlockedExchange8((volatile char*)dest, value); -#endif } -static __forceinline uint16_t InterlockedExchange(volatile uint16_t* dest, uint16_t value) + +static force_inline uint16_t sync_lock_test_and_set(volatile uint16_t* dest, uint16_t value) { -#if defined(__GNUG__) - return __sync_lock_test_and_set(dest, value); -#else return _InterlockedExchange16((volatile short*)dest, value); -#endif } -static __forceinline uint32_t InterlockedExchange(volatile uint32_t* dest, uint32_t value) + +static force_inline uint32_t sync_lock_test_and_set(volatile uint32_t* dest, uint32_t value) { -#if defined(__GNUG__) - return __sync_lock_test_and_set(dest, value); -#else return _InterlockedExchange((volatile long*)dest, value); -#endif } -static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint64_t value) + +static force_inline uint64_t sync_lock_test_and_set(volatile uint64_t* dest, uint64_t value) { -#if defined(__GNUG__) - return __sync_lock_test_and_set(dest, value); -#else return _InterlockedExchange64((volatile long long*)dest, value); -#endif } -#endif -#ifndef InterlockedOr -static __forceinline uint8_t InterlockedOr(volatile uint8_t* dest, uint8_t value) +// atomic add functions + +static force_inline uint8_t sync_fetch_and_add(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedExchangeAdd8((volatile char*)dest, value); +} + +static force_inline uint16_t sync_fetch_and_add(volatile uint16_t* dest, uint16_t value) +{ + return _InterlockedExchangeAdd16((volatile short*)dest, value); +} + +static force_inline uint32_t sync_fetch_and_add(volatile uint32_t* dest, uint32_t value) +{ + return _InterlockedExchangeAdd((volatile long*)dest, value); +} + +static force_inline uint64_t sync_fetch_and_add(volatile uint64_t* dest, uint64_t value) +{ + return _InterlockedExchangeAdd64((volatile long long*)dest, value); +} + +// atomic sub functions + +static force_inline uint8_t sync_fetch_and_sub(volatile uint8_t* dest, uint8_t value) +{ + return _InterlockedExchangeAdd8((volatile char*)dest, -(char)value); +} + +static force_inline uint16_t sync_fetch_and_sub(volatile uint16_t* dest, uint16_t value) +{ + return _InterlockedExchangeAdd16((volatile short*)dest, -(short)value); +} + +static force_inline uint32_t sync_fetch_and_sub(volatile uint32_t* dest, uint32_t value) +{ + return _InterlockedExchangeAdd((volatile long*)dest, -(long)value); +} + +static force_inline uint64_t sync_fetch_and_sub(volatile uint64_t* dest, uint64_t value) +{ + return _InterlockedExchangeAdd64((volatile long long*)dest, -(long long)value); +} + +// atomic bitwise or functions + +static force_inline uint8_t sync_fetch_and_or(volatile uint8_t* dest, uint8_t value) { -#if defined(__GNUG__) - return __sync_fetch_and_or(dest, value); -#else return _InterlockedOr8((volatile char*)dest, value); -#endif } -static __forceinline uint16_t InterlockedOr(volatile uint16_t* dest, uint16_t value) + +static force_inline uint16_t sync_fetch_and_or(volatile uint16_t* dest, uint16_t value) { -#if defined(__GNUG__) - return __sync_fetch_and_or(dest, value); -#else return _InterlockedOr16((volatile short*)dest, value); -#endif } -static __forceinline uint32_t InterlockedOr(volatile uint32_t* dest, uint32_t value) + +static force_inline uint32_t sync_fetch_and_or(volatile uint32_t* dest, uint32_t value) { -#if defined(__GNUG__) - return __sync_fetch_and_or(dest, value); -#else return _InterlockedOr((volatile long*)dest, value); -#endif } -static __forceinline uint64_t InterlockedOr(volatile uint64_t* dest, uint64_t value) + +static force_inline uint64_t sync_fetch_and_or(volatile uint64_t* dest, uint64_t value) { -#if defined(__GNUG__) - return __sync_fetch_and_or(dest, value); -#else return _InterlockedOr64((volatile long long*)dest, value); -#endif } -#endif -#ifndef InterlockedAnd -static __forceinline uint8_t InterlockedAnd(volatile uint8_t* dest, uint8_t value) +// atomic bitwise and functions + +static force_inline uint8_t sync_fetch_and_and(volatile uint8_t* dest, uint8_t value) { -#if defined(__GNUG__) - return __sync_fetch_and_and(dest, value); -#else return _InterlockedAnd8((volatile char*)dest, value); -#endif } -static __forceinline uint16_t InterlockedAnd(volatile uint16_t* dest, uint16_t value) + +static force_inline uint16_t sync_fetch_and_and(volatile uint16_t* dest, uint16_t value) { -#if defined(__GNUG__) - return __sync_fetch_and_and(dest, value); -#else return _InterlockedAnd16((volatile short*)dest, value); -#endif } -static __forceinline uint32_t InterlockedAnd(volatile uint32_t* dest, uint32_t value) + +static force_inline uint32_t sync_fetch_and_and(volatile uint32_t* dest, uint32_t value) { -#if defined(__GNUG__) - return __sync_fetch_and_and(dest, value); -#else return _InterlockedAnd((volatile long*)dest, value); -#endif } -static __forceinline uint64_t InterlockedAnd(volatile uint64_t* dest, uint64_t value) + +static force_inline uint64_t sync_fetch_and_and(volatile uint64_t* dest, uint64_t value) { -#if defined(__GNUG__) - return __sync_fetch_and_and(dest, value); -#else return _InterlockedAnd64((volatile long long*)dest, value); -#endif } -#endif -#ifndef InterlockedXor -static __forceinline uint8_t InterlockedXor(volatile uint8_t* dest, uint8_t value) +// atomic bitwise xor functions + +static force_inline uint8_t sync_fetch_and_xor(volatile uint8_t* dest, uint8_t value) { -#if defined(__GNUG__) - return __sync_fetch_and_xor(dest, value); -#else return _InterlockedXor8((volatile char*)dest, value); -#endif } -static __forceinline uint16_t InterlockedXor(volatile uint16_t* dest, uint16_t value) -{ -#if defined(__GNUG__) - return __sync_fetch_and_xor(dest, value); -#else - return _InterlockedXor16((volatile short*)dest, value); -#endif -} -static __forceinline uint32_t InterlockedXor(volatile uint32_t* dest, uint32_t value) -{ -#if defined(__GNUG__) - return __sync_fetch_and_xor(dest, value); -#else - return _InterlockedXor((volatile long*)dest, value); -#endif -} -static __forceinline uint64_t InterlockedXor(volatile uint64_t* dest, uint64_t value) -{ -#if defined(__GNUG__) - return __sync_fetch_and_xor(dest, value); -#else - return _InterlockedXor64((volatile long long*)dest, value); -#endif -} -#endif -static __forceinline uint32_t cntlz32(uint32_t arg) +static force_inline uint16_t sync_fetch_and_xor(volatile uint16_t* dest, uint16_t value) +{ + return _InterlockedXor16((volatile short*)dest, value); +} + +static force_inline uint32_t sync_fetch_and_xor(volatile uint32_t* dest, uint32_t value) +{ + return _InterlockedXor((volatile long*)dest, value); +} + +static force_inline uint64_t sync_fetch_and_xor(volatile uint64_t* dest, uint64_t value) +{ + return _InterlockedXor64((volatile long long*)dest, value); +} + +#endif /* _MSC_VER */ + +static force_inline uint32_t cntlz32(uint32_t arg) { #if defined(_MSC_VER) unsigned long res; @@ -317,7 +326,7 @@ static __forceinline uint32_t cntlz32(uint32_t arg) #endif } -static __forceinline uint64_t cntlz64(uint64_t arg) +static force_inline uint64_t cntlz64(uint64_t arg) { #if defined(_MSC_VER) unsigned long res; diff --git a/Utilities/Log.h b/Utilities/Log.h index 12c0c7cb21..c5df9a7217 100644 --- a/Utilities/Log.h +++ b/Utilities/Log.h @@ -129,8 +129,7 @@ static struct { inline operator Log::LogType() { return Log::LogType::TTY; } } T void log_message(Log::LogType type, Log::LogSeverity sev, const char* text); void log_message(Log::LogType type, Log::LogSeverity sev, std::string text); -template -__noinline void log_message(Log::LogType type, Log::LogSeverity sev, const char* fmt, Targs... args) +template never_inline void log_message(Log::LogType type, Log::LogSeverity sev, const char* fmt, Args... args) { log_message(type, sev, fmt::Format(fmt, fmt::do_unveil(args)...)); } diff --git a/Utilities/MTProgressDialog.h b/Utilities/MTProgressDialog.h index 72ef148805..9942ffb7df 100644 --- a/Utilities/MTProgressDialog.h +++ b/Utilities/MTProgressDialog.h @@ -61,7 +61,7 @@ public: Show(); } - __forceinline void Update(const u8 thread_id, const u64 value, const wxString& msg) + force_inline void Update(const u8 thread_id, const u64 value, const wxString& msg) { if(thread_id > m_cores) return; diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 86821274ad..3c4182a854 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -208,49 +208,6 @@ std::vector fmt::split(const std::string& source, std::initializer_ return std::move(result); } -std::string fmt::merge(std::vector source, const std::string& separator) -{ - if (!source.size()) - { - return ""; - } - - std::string result; - - for (int i = 0; i < source.size() - 1; ++i) - { - result += source[i] + separator; - } - - return result + source.back(); -} - -std::string fmt::merge(std::initializer_list> sources, const std::string& separator) -{ - if (!sources.size()) - { - return ""; - } - - std::string result; - bool first = true; - - for (auto &v : sources) - { - if (first) - { - result = fmt::merge(v, separator); - first = false; - } - else - { - result += separator + fmt::merge(v, separator); - } - } - - return result; -} - std::string fmt::tolower(std::string source) { std::transform(source.begin(), source.end(), source.begin(), ::tolower); diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 365b60d005..406446502c 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -95,8 +95,7 @@ namespace fmt T by_value(T x) { return x; } //wrapper to deal with advance sprintf formating options with automatic length finding - template - std::string Format(const char* fmt, Args ... parameters) + template std::string Format(const char* fmt, Args... parameters) { size_t length = 256; std::string str; @@ -139,7 +138,7 @@ namespace fmt if (src.substr(pos, comp_length) == list[i].first) { - src = (pos ? src.substr(0, pos) + list[i].second : list[i].second) + std::string(src.c_str() + pos + comp_length); + src = (pos ? src.substr(0, pos) + list[i].second : list[i].second) + src.substr(pos + comp_length); pos += list[i].second.length() - 1; break; } @@ -163,7 +162,7 @@ namespace fmt if (src.substr(pos, comp_length) == list[i].first) { - src = (pos ? src.substr(0, pos) + list[i].second() : list[i].second()) + std::string(src.c_str() + pos + comp_length); + src = (pos ? src.substr(0, pos) + list[i].second() : list[i].second()) + src.substr(pos + comp_length); pos += list[i].second().length() - 1; break; } @@ -182,7 +181,7 @@ namespace fmt { typedef T result_type; - __forceinline static result_type get_value(const T& arg) + force_inline static result_type get_value(const T& arg) { return arg; } @@ -193,7 +192,7 @@ namespace fmt { typedef const char* result_type; - __forceinline static result_type get_value(const char* arg) + force_inline static result_type get_value(const char* arg) { return arg; } @@ -204,7 +203,7 @@ namespace fmt { typedef const char* result_type; - __forceinline static result_type get_value(const char(&arg)[N]) + force_inline static result_type get_value(const char(&arg)[N]) { return arg; } @@ -215,7 +214,7 @@ namespace fmt { typedef const char* result_type; - __forceinline static result_type get_value(const std::string& arg) + force_inline static result_type get_value(const std::string& arg) { return arg.c_str(); } @@ -226,7 +225,7 @@ namespace fmt { typedef typename std::underlying_type::type result_type; - __forceinline static result_type get_value(const T& arg) + force_inline static result_type get_value(const T& arg) { return static_cast(arg); } @@ -237,14 +236,14 @@ namespace fmt { typedef typename unveil::result_type result_type; - __forceinline static result_type get_value(const be_t& arg) + force_inline static result_type get_value(const be_t& arg) { return unveil::get_value(arg.value()); } }; template - __forceinline typename unveil::result_type do_unveil(const T& arg) + force_inline typename unveil::result_type do_unveil(const T& arg) { return unveil::get_value(arg); } @@ -266,8 +265,7 @@ namespace fmt vm::psv::ref (fmt::unveil) (vm_ref.h) */ - template - __forceinline __safebuffers std::string format(const char* fmt, Args... args) + template force_inline safe_buffers std::string format(const char* fmt, Args... args) { return Format(fmt, do_unveil(args)...); } @@ -291,8 +289,54 @@ namespace fmt std::vector rSplit(const std::string& source, const std::string& delim); std::vector split(const std::string& source, std::initializer_list separators, bool is_skip_empty = true); - std::string merge(std::vector source, const std::string& separator); - std::string merge(std::initializer_list> sources, const std::string& separator); + + template + std::string merge(const T& source, const std::string& separator) + { + if (!source.size()) + { + return{}; + } + + std::string result; + + auto it = source.begin(); + auto end = source.end(); + for (--end; it != end; ++it) + { + result += *it + separator; + } + + return result + source.back(); + } + + template + std::string merge(std::initializer_list sources, const std::string& separator) + { + if (!sources.size()) + { + return{}; + } + + std::string result; + bool first = true; + + for (auto &v : sources) + { + if (first) + { + result = fmt::merge(v, separator); + first = false; + } + else + { + result += separator + fmt::merge(v, separator); + } + } + + return result; + } + std::string tolower(std::string source); std::string toupper(std::string source); std::string escape(std::string source); diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 32a1bd9877..3c04019ddf 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1002,10 +1002,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 = 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; default: return false; } @@ -1025,10 +1025,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 = 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; default: return false; } @@ -1048,10 +1048,10 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) switch (d_size) { - case 1: value = vm::priv_ref>(addr) &= value; break; - case 2: value = vm::priv_ref>(addr) &= value; break; - case 4: value = vm::priv_ref>(addr) &= value; break; - case 8: value = vm::priv_ref>(addr) &= value; break; + case 1: value = vm::priv_ref>(addr) &= value; break; + case 2: value = vm::priv_ref>(addr) &= value; break; + case 4: value = vm::priv_ref>(addr) &= value; break; + case 8: value = vm::priv_ref>(addr) &= value; break; default: return false; } diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 7de4c657cd..783f66176c 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -118,7 +118,7 @@ struct waiter_map_t bool is_stopped(u64 signal_id); // wait until waiter_func() returns true, signal_id is an arbitrary number - template __forceinline __safebuffers void wait_op(const S& signal_id, const WT waiter_func) + template force_inline safe_buffers void wait_op(const S& signal_id, const WT waiter_func) { // generate hash const auto hash = std::hash()(signal_id) % size; @@ -141,7 +141,7 @@ struct waiter_map_t } // signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met) - template __forceinline void notify(const S& signal_id) + template force_inline void notify(const S& signal_id) { // generate hash const auto hash = std::hash()(signal_id) % size; @@ -173,7 +173,7 @@ class squeue_t }; }; - atomic_le_t m_sync; + atomic m_sync; mutable std::mutex m_rcv_mutex; mutable std::mutex m_wcv_mutex; @@ -258,12 +258,12 @@ public: return push(data, [do_exit](){ return do_exit && *do_exit; }); } - __forceinline bool push(const T& data) + force_inline bool push(const T& data) { return push(data, SQUEUE_NEVER_EXIT); } - __forceinline bool try_push(const T& data) + force_inline bool try_push(const T& data) { return push(data, SQUEUE_ALWAYS_EXIT); } @@ -326,12 +326,12 @@ public: return pop(data, [do_exit](){ return do_exit && *do_exit; }); } - __forceinline bool pop(T& data) + force_inline bool pop(T& data) { return pop(data, SQUEUE_NEVER_EXIT); } - __forceinline bool try_pop(T& data) + force_inline bool try_pop(T& data) { return pop(data, SQUEUE_ALWAYS_EXIT); } @@ -388,12 +388,12 @@ public: return peek(data, start_pos, [do_exit](){ return do_exit && *do_exit; }); } - __forceinline bool peek(T& data, u32 start_pos = 0) + force_inline bool peek(T& data, u32 start_pos = 0) { return peek(data, start_pos, SQUEUE_NEVER_EXIT); } - __forceinline bool try_peek(T& data, u32 start_pos = 0) + force_inline bool try_peek(T& data, u32 start_pos = 0) { return peek(data, start_pos, SQUEUE_ALWAYS_EXIT); } diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index 1f6645bdd0..495eac45dc 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -13,121 +13,121 @@ #include #pragma warning(pop) -__forceinline u8 Read8(vfsStream& f) +force_inline u8 Read8(vfsStream& f) { u8 ret; f.Read(&ret, sizeof(ret)); return ret; } -__forceinline u16 Read16(vfsStream& f) +force_inline u16 Read16(vfsStream& f) { be_t ret; f.Read(&ret, sizeof(ret)); return ret; } -__forceinline u32 Read32(vfsStream& f) +force_inline u32 Read32(vfsStream& f) { be_t ret; f.Read(&ret, sizeof(ret)); return ret; } -__forceinline u64 Read64(vfsStream& f) +force_inline u64 Read64(vfsStream& f) { be_t ret; f.Read(&ret, sizeof(ret)); return ret; } -__forceinline u16 Read16LE(vfsStream& f) +force_inline u16 Read16LE(vfsStream& f) { u16 ret; f.Read(&ret, sizeof(ret)); return ret; } -__forceinline u32 Read32LE(vfsStream& f) +force_inline u32 Read32LE(vfsStream& f) { u32 ret; f.Read(&ret, sizeof(ret)); return ret; } -__forceinline u64 Read64LE(vfsStream& f) +force_inline u64 Read64LE(vfsStream& f) { u64 ret; f.Read(&ret, sizeof(ret)); return ret; } -__forceinline void Write8(vfsStream& f, const u8 data) +force_inline void Write8(vfsStream& f, const u8 data) { f.Write(&data, sizeof(data)); } -__forceinline void Write8(const fs::file& f, const u8 data) +force_inline void Write8(const fs::file& f, const u8 data) { f.write(&data, sizeof(data)); } -__forceinline void Write16LE(vfsStream& f, const u16 data) +force_inline void Write16LE(vfsStream& f, const u16 data) { f.Write(&data, sizeof(data)); } -__forceinline void Write16LE(const fs::file& f, const u16 data) +force_inline void Write16LE(const fs::file& f, const u16 data) { f.write(&data, sizeof(data)); } -__forceinline void Write32LE(vfsStream& f, const u32 data) +force_inline void Write32LE(vfsStream& f, const u32 data) { f.Write(&data, sizeof(data)); } -__forceinline void Write32LE(const fs::file& f, const u32 data) +force_inline void Write32LE(const fs::file& f, const u32 data) { f.write(&data, sizeof(data)); } -__forceinline void Write64LE(vfsStream& f, const u64 data) +force_inline void Write64LE(vfsStream& f, const u64 data) { f.Write(&data, sizeof(data)); } -__forceinline void Write64LE(const fs::file& f, const u64 data) +force_inline void Write64LE(const fs::file& f, const u64 data) { f.write(&data, sizeof(data)); } -__forceinline void Write16(vfsStream& f, const u16 data) +force_inline void Write16(vfsStream& f, const u16 data) { Write16LE(f, re16(data)); } -__forceinline void Write16(const fs::file& f, const u16 data) +force_inline void Write16(const fs::file& f, const u16 data) { Write16LE(f, re16(data)); } -__forceinline void Write32(vfsStream& f, const u32 data) +force_inline void Write32(vfsStream& f, const u32 data) { Write32LE(f, re32(data)); } -__forceinline void Write32(const fs::file& f, const u32 data) +force_inline void Write32(const fs::file& f, const u32 data) { Write32LE(f, re32(data)); } -__forceinline void Write64(vfsStream& f, const u64 data) +force_inline void Write64(vfsStream& f, const u64 data) { Write64LE(f, re64(data)); } -__forceinline void Write64(const fs::file& f, const u64 data) +force_inline void Write64(const fs::file& f, const u64 data) { Write64LE(f, re64(data)); } diff --git a/rpcs3/Emu/ARMv7/ARMv7Callback.h b/rpcs3/Emu/ARMv7/ARMv7Callback.h index 18c39fe49d..0777ed4f20 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Callback.h +++ b/rpcs3/Emu/ARMv7/ARMv7Callback.h @@ -5,14 +5,14 @@ namespace vm { template - __forceinline RT _ptr_base::operator()(ARMv7Context& context, T... args) const + force_inline RT _ptr_base::operator()(ARMv7Context& context, T... args) const { return psv_func_detail::func_caller::call(context, vm::cast(this->addr()), args...); } } template -__forceinline RT cb_call(ARMv7Context& context, u32 addr, T... args) +force_inline RT cb_call(ARMv7Context& context, u32 addr, T... args) { return psv_func_detail::func_caller::call(context, addr, args...); } diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index ba97ed2375..dc14117845 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -176,7 +176,7 @@ struct ARMv7Context } template - __noinline void fmt_debug_str(const char* fmt, T... args) + never_inline void fmt_debug_str(const char* fmt, T... args) { debug_str = fmt::format(fmt, args...); } @@ -189,12 +189,12 @@ struct cast_armv7_gpr typedef typename std::underlying_type::type underlying_type; - __forceinline static u32 to_gpr(const T& value) + force_inline static u32 to_gpr(const T& value) { return cast_armv7_gpr::to_gpr(static_cast(value)); } - __forceinline static T from_gpr(const u32 reg) + force_inline static T from_gpr(const u32 reg) { return static_cast(cast_armv7_gpr::from_gpr(reg)); } @@ -203,12 +203,12 @@ struct cast_armv7_gpr template<> struct cast_armv7_gpr { - __forceinline static u32 to_gpr(const u8& value) + force_inline static u32 to_gpr(const u8& value) { return value; } - __forceinline static u8 from_gpr(const u32 reg) + force_inline static u8 from_gpr(const u32 reg) { return static_cast(reg); } @@ -217,12 +217,12 @@ struct cast_armv7_gpr template<> struct cast_armv7_gpr { - __forceinline static u32 to_gpr(const u16& value) + force_inline static u32 to_gpr(const u16& value) { return value; } - __forceinline static u16 from_gpr(const u32 reg) + force_inline static u16 from_gpr(const u32 reg) { return static_cast(reg); } @@ -231,12 +231,12 @@ struct cast_armv7_gpr template<> struct cast_armv7_gpr { - __forceinline static u32 to_gpr(const u32& value) + force_inline static u32 to_gpr(const u32& value) { return value; } - __forceinline static u32 from_gpr(const u32 reg) + force_inline static u32 from_gpr(const u32 reg) { return reg; } @@ -245,12 +245,12 @@ struct cast_armv7_gpr template<> struct cast_armv7_gpr { - __forceinline static u32 to_gpr(const s8& value) + force_inline static u32 to_gpr(const s8& value) { return value; } - __forceinline static s8 from_gpr(const u32 reg) + force_inline static s8 from_gpr(const u32 reg) { return static_cast(reg); } @@ -259,12 +259,12 @@ struct cast_armv7_gpr template<> struct cast_armv7_gpr { - __forceinline static u32 to_gpr(const s16& value) + force_inline static u32 to_gpr(const s16& value) { return value; } - __forceinline static s16 from_gpr(const u32 reg) + force_inline static s16 from_gpr(const u32 reg) { return static_cast(reg); } @@ -273,12 +273,12 @@ struct cast_armv7_gpr template<> struct cast_armv7_gpr { - __forceinline static u32 to_gpr(const s32& value) + force_inline static u32 to_gpr(const s32& value) { return value; } - __forceinline static s32 from_gpr(const u32 reg) + force_inline static s32 from_gpr(const u32 reg) { return static_cast(reg); } @@ -287,25 +287,25 @@ struct cast_armv7_gpr template<> struct cast_armv7_gpr { - __forceinline static u32 to_gpr(const bool& value) + force_inline static u32 to_gpr(const bool& value) { return value; } - __forceinline static bool from_gpr(const u32& reg) + force_inline static bool from_gpr(const u32& reg) { return reinterpret_cast(reg); } }; template -__forceinline u32 cast_to_armv7_gpr(const T& value) +force_inline u32 cast_to_armv7_gpr(const T& value) { return cast_armv7_gpr::to_gpr(value); } template -__forceinline T cast_from_armv7_gpr(const u32 reg) +force_inline T cast_from_armv7_gpr(const u32 reg) { return cast_armv7_gpr::from_gpr(reg); } diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index 42bdedb6d2..89a8c073ca 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -397,7 +397,7 @@ s32 sceKernelCreateEventFlag(vm::psv::ptr pName, u32 attr, u32 initP { sceLibKernel.Error("sceKernelCreateEventFlag(pName=*0x%x, attr=0x%x, initPattern=0x%x, pOptParam=*0x%x)", pName, attr, initPattern, pOptParam); - if (s32 id = g_psv_ef_list.add(new psv_event_flag_t(pName.get_ptr(), attr, initPattern), 0)) + if (s32 id = g_psv_ef_list.create(pName.get_ptr(), attr, initPattern)) { return id; } @@ -461,7 +461,7 @@ s32 sceKernelCreateSema(vm::psv::ptr pName, u32 attr, s32 initCount, { sceLibKernel.Error("sceKernelCreateSema(pName=*0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=*0x%x)", pName, attr, initCount, maxCount, pOptParam); - if (s32 id = g_psv_sema_list.add(new psv_sema_t(pName.get_ptr(), attr, initCount, maxCount), 0)) + if (s32 id = g_psv_sema_list.create(pName.get_ptr(), attr, initCount, maxCount)) { return id; } @@ -473,7 +473,7 @@ s32 sceKernelDeleteSema(s32 semaId) { sceLibKernel.Error("sceKernelDeleteSema(semaId=0x%x)", semaId); - ref_t sema = g_psv_sema_list.get(semaId); + const auto sema = g_psv_sema_list.get(semaId); if (!sema) { @@ -502,7 +502,7 @@ s32 sceKernelWaitSema(s32 semaId, s32 needCount, vm::psv::ptr pTimeout) { sceLibKernel.Error("sceKernelWaitSema(semaId=0x%x, needCount=%d, pTimeout=*0x%x)", semaId, needCount, pTimeout); - ref_t sema = g_psv_sema_list.get(semaId); + const auto sema = g_psv_sema_list.get(semaId); if (!sema) { @@ -545,7 +545,7 @@ s32 sceKernelCreateMutex(vm::psv::ptr pName, u32 attr, s32 initCount { sceLibKernel.Error("sceKernelCreateMutex(pName=*0x%x, attr=0x%x, initCount=%d, pOptParam=*0x%x)", pName, attr, initCount, pOptParam); - if (s32 id = g_psv_mutex_list.add(new psv_mutex_t(pName.get_ptr(), attr, initCount), 0)) + if (s32 id = g_psv_mutex_list.create(pName.get_ptr(), attr, initCount)) { return id; } @@ -646,7 +646,7 @@ s32 sceKernelCreateCond(vm::psv::ptr pName, u32 attr, s32 mutexId, v { sceLibKernel.Error("sceKernelCreateCond(pName=*0x%x, attr=0x%x, mutexId=0x%x, pOptParam=*0x%x)", pName, attr, mutexId, pOptParam); - if (s32 id = g_psv_cond_list.add(new psv_cond_t(pName.get_ptr(), attr, mutexId), 0)) + if (s32 id = g_psv_cond_list.create(pName.get_ptr(), attr, mutexId)) { return id; } diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.h b/rpcs3/Emu/ARMv7/PSVFuncList.h index 170b6690e5..fb7215a61a 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.h +++ b/rpcs3/Emu/ARMv7/PSVFuncList.h @@ -56,12 +56,12 @@ namespace psv_func_detail { static_assert(sizeof(T) <= 4, "Invalid function argument type for ARG_GENERAL"); - __forceinline static T get_arg(ARMv7Context& context) + force_inline static T get_arg(ARMv7Context& context) { return cast_from_armv7_gpr(context.GPR[g_count - 1]); } - __forceinline static void put_arg(ARMv7Context& context, const T& arg) + force_inline static void put_arg(ARMv7Context& context, const T& arg) { context.GPR[g_count - 1] = cast_to_armv7_gpr(arg); } @@ -73,12 +73,12 @@ namespace psv_func_detail // first u64 argument is passed in r0-r1, second one is passed in r2-r3 (if g_count = 3) static_assert(g_count == 1 || g_count == 3, "Wrong u64 argument position"); - __forceinline static u64 get_arg(ARMv7Context& context) + force_inline static u64 get_arg(ARMv7Context& context) { return context.GPR_D[g_count >> 1]; } - __forceinline static void put_arg(ARMv7Context& context, u64 arg) + force_inline static void put_arg(ARMv7Context& context, u64 arg) { context.GPR_D[g_count >> 1] = arg; } @@ -89,12 +89,12 @@ namespace psv_func_detail { static_assert(g_count == 1 || g_count == 3, "Wrong s64 argument position"); - __forceinline static s64 get_arg(ARMv7Context& context) + force_inline static s64 get_arg(ARMv7Context& context) { return context.GPR_D[g_count >> 1]; } - __forceinline static void put_arg(ARMv7Context& context, s64 arg) + force_inline static void put_arg(ARMv7Context& context, s64 arg) { context.GPR_D[g_count >> 1] = arg; } @@ -106,11 +106,11 @@ namespace psv_func_detail static_assert(f_count <= 0, "TODO: Unsupported argument type (float)"); static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_FLOAT"); - __forceinline static T get_arg(ARMv7Context& context) + force_inline static T get_arg(ARMv7Context& context) { } - __forceinline static void put_arg(ARMv7Context& context, const T& arg) + force_inline static void put_arg(ARMv7Context& context, const T& arg) { } }; @@ -121,11 +121,11 @@ namespace psv_func_detail static_assert(v_count <= 0, "TODO: Unsupported argument type (vector)"); static_assert(std::is_same::value, "Invalid function argument type for ARG_VECTOR"); - __forceinline static T get_arg(ARMv7Context& context) + force_inline static T get_arg(ARMv7Context& context) { } - __forceinline static void put_arg(ARMv7Context& context, const T& arg) + force_inline static void put_arg(ARMv7Context& context, const T& arg) { } }; @@ -137,13 +137,13 @@ namespace psv_func_detail static_assert(v_count <= 0, "TODO: Unsupported stack argument type (vector)"); static_assert(sizeof(T) <= 4, "Invalid function argument type for ARG_STACK"); - __forceinline static T get_arg(ARMv7Context& context) + force_inline static T get_arg(ARMv7Context& context) { // TODO: check return cast_from_armv7_gpr(vm::psv::read32(context.SP + sizeof(u32) * (g_count - 5))); } - __forceinline static void put_arg(ARMv7Context& context, const T& arg) + force_inline static void put_arg(ARMv7Context& context, const T& arg) { // TODO: check const int stack_pos = (g_count - 5) * 4 - FIXED_STACK_FRAME_SIZE; @@ -156,13 +156,13 @@ namespace psv_func_detail template struct bind_arg { - __forceinline static u64 get_arg(ARMv7Context& context) + force_inline static u64 get_arg(ARMv7Context& context) { // TODO: check return vm::psv::read64(context.SP + sizeof(u32) * (g_count - 5)); } - __forceinline static void put_arg(ARMv7Context& context, u64 arg) + force_inline static void put_arg(ARMv7Context& context, u64 arg) { // TODO: check const int stack_pos = (g_count - 5) * 4 - FIXED_STACK_FRAME_SIZE; @@ -175,13 +175,13 @@ namespace psv_func_detail template struct bind_arg { - __forceinline static s64 get_arg(ARMv7Context& context) + force_inline static s64 get_arg(ARMv7Context& context) { // TODO: check return vm::psv::read64(context.SP + sizeof(u32) * (g_count - 5)); } - __forceinline static void put_arg(ARMv7Context& context, s64 arg) + force_inline static void put_arg(ARMv7Context& context, s64 arg) { // TODO: check const int stack_pos = (g_count - 5) * 4 - FIXED_STACK_FRAME_SIZE; @@ -199,12 +199,12 @@ namespace psv_func_detail static_assert(type == ARG_GENERAL, "Wrong use of bind_result template"); static_assert(sizeof(T) <= 4, "Invalid function result type for ARG_GENERAL"); - __forceinline static T get_result(ARMv7Context& context) + force_inline static T get_result(ARMv7Context& context) { return cast_from_armv7_gpr(context.GPR[0]); } - __forceinline static void put_result(ARMv7Context& context, const T& result) + force_inline static void put_result(ARMv7Context& context, const T& result) { context.GPR[0] = cast_to_armv7_gpr(result); } @@ -213,12 +213,12 @@ namespace psv_func_detail template<> struct bind_result { - __forceinline static u64 get_result(ARMv7Context& context) + force_inline static u64 get_result(ARMv7Context& context) { return context.GPR_D[0]; } - __forceinline static void put_result(ARMv7Context& context, u64 result) + force_inline static void put_result(ARMv7Context& context, u64 result) { context.GPR_D[0] = result; } @@ -227,12 +227,12 @@ namespace psv_func_detail template<> struct bind_result { - __forceinline static s64 get_result(ARMv7Context& context) + force_inline static s64 get_result(ARMv7Context& context) { return context.GPR_D[0]; } - __forceinline static void put_result(ARMv7Context& context, s64 result) + force_inline static void put_result(ARMv7Context& context, s64 result) { context.GPR_D[0] = result; } @@ -243,7 +243,7 @@ namespace psv_func_detail //{ // static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT"); - // static __forceinline void put_result(ARMv7Context& context, const T& result) + // static force_inline void put_result(ARMv7Context& context, const T& result) // { // } //}; @@ -253,7 +253,7 @@ namespace psv_func_detail //{ // static_assert(std::is_same::value, "Invalid function result type for ARG_VECTOR"); - // static __forceinline void put_result(ARMv7Context& context, const T& result) + // static force_inline void put_result(ARMv7Context& context, const T& result) // { // } //}; @@ -289,7 +289,7 @@ namespace psv_func_detail template struct call_impl { - static __forceinline RT call(F f, Tuple && t) + static force_inline RT call(F f, Tuple && t) { return call_impl::call(f, std::forward(t)); } @@ -298,28 +298,28 @@ namespace psv_func_detail template struct call_impl { - static __forceinline RT call(F f, Tuple && t) + static force_inline RT call(F f, Tuple && t) { return f(std::get(std::forward(t))...); } }; template - __forceinline RT call(F f, Tuple && t) + force_inline RT call(F f, Tuple && t) { typedef typename std::decay::type ttype; return psv_func_detail::call_impl::value, std::tuple_size::value>::call(f, std::forward(t)); } template - __forceinline std::tuple<> get_func_args(ARMv7Context& context) + force_inline std::tuple<> get_func_args(ARMv7Context& context) { // terminator return std::tuple<>(); } template - __forceinline std::tuple get_func_args(ARMv7Context& context) + force_inline std::tuple get_func_args(ARMv7Context& context) { typedef arg_type type; const arg_class t = type::value; @@ -332,14 +332,14 @@ namespace psv_func_detail } template - __forceinline static bool put_func_args(ARMv7Context& context) + force_inline static bool put_func_args(ARMv7Context& context) { // terminator return false; } template - __forceinline static bool put_func_args(ARMv7Context& context, T1 arg, T... args) + force_inline static bool put_func_args(ARMv7Context& context, T1 arg, T... args) { typedef arg_type type; const arg_class t = type::value; @@ -404,7 +404,7 @@ namespace psv_func_detail template struct func_caller { - __forceinline static RT call(ARMv7Context& context, u32 addr, T... args) + force_inline static RT call(ARMv7Context& context, u32 addr, T... args) { func_caller::call(context, addr, args...); @@ -415,7 +415,7 @@ namespace psv_func_detail template struct func_caller { - __forceinline static void call(ARMv7Context& context, u32 addr, T... args) + force_inline static void call(ARMv7Context& context, u32 addr, T... args) { if (put_func_args<0, 0, 0, T...>(context, args...)) { @@ -464,7 +464,7 @@ enum psv_special_function_index : u16 // Do not call directly u32 add_psv_func(psv_func data); // Do not call directly -template __forceinline void call_psv_func(ARMv7Context& context, RT(*func)(T...)) +template force_inline void call_psv_func(ARMv7Context& context, RT(*func)(T...)) { psv_func_detail::func_binder::do_call(context, func); } diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h index 431cbbf33f..3cf33b0b30 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.h +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -21,22 +21,16 @@ union psv_uid_t } }; -template +template class psv_object_list_t // Class for managing object data { -public: - typedef refcounter_t rc_type; - typedef ref_t ref_type; - - static const u32 max = 0x8000; - -private: - std::array m_data; + std::array, 0x8000> m_data; std::atomic m_hint; // guessing next free position + std::mutex m_mutex; void error(s32 uid) { - throw fmt::format("Invalid UID requested (type=0x%x, uid=0x%x)", type, uid); + throw fmt::format("Invalid UID requested (type=0x%x, uid=0x%x)", uid_class, uid); } public: @@ -45,17 +39,8 @@ public: { } - psv_object_list_t(const psv_object_list_t&) = delete; - psv_object_list_t(psv_object_list_t&&) = delete; - - psv_object_list_t& operator =(const psv_object_list_t&) = delete; - psv_object_list_t& operator =(psv_object_list_t&&) = delete; - -public: - static const u32 uid_class = type; - // check if UID is potentially valid (will return true even if the object doesn't exist) - bool check(s32 uid) + inline static bool check(s32 uid) { const psv_uid_t id = psv_uid_t::make(uid); @@ -64,29 +49,35 @@ public: } // share object with UID specified - ref_type get(s32 uid) + inline std::shared_ptr get(s32 uid) { if (!check(uid)) { - return ref_type(); + return nullptr; } - return &m_data[psv_uid_t::make(uid).number]; + std::lock_guard lock(m_mutex); + + return m_data[psv_uid_t::make(uid).number]; } - ref_type operator [](s32 uid) + inline std::shared_ptr operator [](s32 uid) { - return get(uid); + return this->get(uid); } - // generate UID for newly created object (will return zero if the limit exceeded) - s32 add(T* data, s32 error_code) + // create new object and generate UID for it, or do nothing and return zero (if limit reached) + template s32 create(Args&&... args) { + std::lock_guard lock(m_mutex); + for (u32 i = 0, j = m_hint; i < m_data.size(); i++, j = (j + 1) % m_data.size()) { // find an empty position and copy the pointer - if (m_data[j].try_set(data)) + if (!m_data[j]) { + m_data[j] = std::make_shared(args...); // construct object with specified arguments + m_hint = (j + 1) % m_data.size(); // guess next position psv_uid_t id = psv_uid_t::make(1); // make UID @@ -97,8 +88,7 @@ public: } } - delete data; - return error_code; + return 0; } // remove object with specified UID @@ -109,19 +99,29 @@ public: return false; } + std::lock_guard lock(m_mutex); + const u32 pos = psv_uid_t::make(uid).number; m_hint = std::min(pos, m_hint); - return m_data[pos].try_remove(); + if (!m_data[pos]) + { + return false; + } + + m_data[pos].reset(); + return true; } // remove all objects void clear() { + std::lock_guard lock(m_mutex); + for (auto& v : m_data) { - v.try_remove(); + v.reset(); } m_hint = 0; diff --git a/rpcs3/Emu/CPU/CPUDecoder.h b/rpcs3/Emu/CPU/CPUDecoder.h index 68f21cf542..5ff68f0e70 100644 --- a/rpcs3/Emu/CPU/CPUDecoder.h +++ b/rpcs3/Emu/CPU/CPUDecoder.h @@ -354,17 +354,17 @@ public: } } - __forceinline const std::string& GetName() const + force_inline const std::string& GetName() const { return m_name; } - __forceinline const uint GetArgCount() const + force_inline const uint GetArgCount() const { return m_args_count; } - __forceinline const CodeFieldBase& GetArg(uint index) const + force_inline const CodeFieldBase& GetArg(uint index) const { assert(index < m_args_count); return *m_args[index]; diff --git a/rpcs3/Emu/CPU/CPUInstrTable.h b/rpcs3/Emu/CPU/CPUInstrTable.h index 1ec101a875..1402a94cf5 100644 --- a/rpcs3/Emu/CPU/CPUInstrTable.h +++ b/rpcs3/Emu/CPU/CPUInstrTable.h @@ -1,6 +1,6 @@ #pragma once -template __forceinline static T sign(const T value) +template force_inline static T sign(const T value) { static_assert(size > 0 && size < sizeof(T) * 8, "Bad sign size"); diff --git a/rpcs3/Emu/CPU/CPUThreadManager.cpp b/rpcs3/Emu/CPU/CPUThreadManager.cpp index 6e6953e9d4..1fee8dd241 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.cpp +++ b/rpcs3/Emu/CPU/CPUThreadManager.cpp @@ -34,12 +34,12 @@ std::shared_ptr CPUThreadManager::AddThread(CPUThreadType type) { case CPU_THREAD_PPU: { - new_thread.reset(new PPUThread()); + new_thread = std::make_shared(); break; } case CPU_THREAD_SPU: { - new_thread.reset(new SPUThread()); + new_thread = std::make_shared(); break; } case CPU_THREAD_RAW_SPU: @@ -48,7 +48,7 @@ std::shared_ptr CPUThreadManager::AddThread(CPUThreadType type) { if (!m_raw_spu[i]) { - new_thread.reset(new RawSPUThread()); + new_thread = std::make_shared(); new_thread->index = i; m_raw_spu[i] = new_thread; @@ -67,7 +67,7 @@ std::shared_ptr CPUThreadManager::AddThread(CPUThreadType type) if (new_thread) { - new_thread->SetId(Emu.GetIdManager().GetNewID(new_thread)); + new_thread->SetId(Emu.GetIdManager().add(new_thread)); m_threads.push_back(new_thread); SendDbgCommand(DID_CREATE_THREAD, new_thread.get()); @@ -106,13 +106,13 @@ void CPUThreadManager::RemoveThread(u32 id) } // Removing the ID should trigger the actual deletion of the thread - Emu.GetIdManager().RemoveID(id); + Emu.GetIdManager().remove(id); Emu.CheckStatus(); } std::shared_ptr CPUThreadManager::GetThread(u32 id) { - return Emu.GetIdManager().GetIDData(id); + return Emu.GetIdManager().get(id); } std::shared_ptr CPUThreadManager::GetThread(u32 id, CPUThreadType type) diff --git a/rpcs3/Emu/Cell/PPCInstrTable.h b/rpcs3/Emu/Cell/PPCInstrTable.h index fead638bdb..2eac8f73a7 100644 --- a/rpcs3/Emu/Cell/PPCInstrTable.h +++ b/rpcs3/Emu/Cell/PPCInstrTable.h @@ -26,13 +26,13 @@ public: static const u32 shift = 31 - to; static const u32 mask = ((1ULL << ((to - from) + 1)) - 1) << shift; - static __forceinline void encode(u32& data, u32 value) + static force_inline void encode(u32& data, u32 value) { data &= ~mask; data |= (value << shift) & mask; } - static __forceinline u32 decode(u32 data) + static force_inline u32 decode(u32 data) { return (data & mask) >> shift; } @@ -64,13 +64,13 @@ public: static const u32 shift2 = 31 - to2; static const u32 mask2 = ((1 << ((to2 - from2) + 1)) - 1) << shift2; - static __forceinline void encode(u32& data, u32 value) + static force_inline void encode(u32& data, u32 value) { data &= ~(CodeField::mask | mask2); data |= ((value << CodeField::shift) & CodeField::mask) | (((value >> offset) << shift2) & mask2); } - static __forceinline u32 decode(u32 data) + static force_inline u32 decode(u32 data) { return ((data & CodeField::mask) >> CodeField::shift) | (((data & mask2) >> shift2) << offset); } @@ -96,7 +96,7 @@ public: static const int size = _size; - static __forceinline u32 decode(u32 data) + static force_inline u32 decode(u32 data) { return sign((data & CodeField::mask) >> CodeField::shift); } @@ -117,12 +117,12 @@ public: { } - static __forceinline u32 decode(u32 data) + static force_inline u32 decode(u32 data) { return ((data & CodeField::mask) >> CodeField::shift) << offset; } - static __forceinline void encode(u32& data, u32 value) + static force_inline void encode(u32& data, u32 value) { data &= ~CodeField::mask; data |= ((value >> offset) << CodeField::shift) & CodeField::mask; @@ -149,12 +149,12 @@ public: { } - static __forceinline u32 decode(u32 data) + static force_inline u32 decode(u32 data) { return sign((data & CodeField::mask) >> CodeField::shift) << offset; } - static __forceinline void encode(u32& data, u32 value) + static force_inline void encode(u32& data, u32 value) { data &= ~CodeField::mask; data |= ((value >> offset) << CodeField::shift) & CodeField::mask; diff --git a/rpcs3/Emu/Cell/PPUInterpreter.cpp b/rpcs3/Emu/Cell/PPUInterpreter.cpp index e012641c37..74152cfe60 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/PPUInterpreter.cpp @@ -24,7 +24,7 @@ public: } } - __forceinline __m128 operator [] (s32 scale) const + force_inline __m128 operator [] (s32 scale) const { return m_data[scale + 31]; } diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 3dfa186687..5ae0548f65 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -2004,19 +2004,10 @@ void Compiler::BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) { } void Compiler::HACK(u32 index) { - if (index & EIF_SAVE_RTOC) { - auto addr_i64 = (Value *)m_ir_builder->getInt64(0x28); - auto ra_i64 = GetGpr(1); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - - WriteMemory(addr_i64, GetGpr(2, 64)); - } - Call("execute_ppu_func_by_index", &execute_ppu_func_by_index, m_state.args[CompileTaskState::Args::State], m_ir_builder->getInt32(index & ~EIF_FLAGS)); - if (index & EIF_PERFORM_BLR) { - auto lr_i64 = GetLr(); - lr_i64 = m_ir_builder->CreateAnd(lr_i64, ~0x3ULL); - auto lr_i32 = m_ir_builder->CreateTrunc(lr_i64, m_ir_builder->getInt32Ty()); - CreateBranch(nullptr, lr_i32, false, true); + Call("execute_ppu_func_by_index", &execute_ppu_func_by_index, m_state.args[CompileTaskState::Args::State], m_ir_builder->getInt32(index & EIF_USE_BRANCH ? index : index & ~EIF_PERFORM_BLR)); + if (index & EIF_PERFORM_BLR || index & EIF_USE_BRANCH) { + auto lr_i32 = index & EIF_USE_BRANCH ? GetPc() : m_ir_builder->CreateTrunc(m_ir_builder->CreateAnd(GetLr(), ~0x3ULL), m_ir_builder->getInt32Ty()); + CreateBranch(nullptr, lr_i32, false, (index & EIF_USE_BRANCH) == 0); } // copied from Compiler::SC() //auto ret_i1 = Call("PollStatus", m_poll_status_function, m_state.args[CompileTaskState::Args::State]); @@ -6089,9 +6080,10 @@ BranchType ppu_recompiler_llvm::GetBranchTypeFromInstruction(u32 instruction) { } else if (field2 == 528) { type = lk ? BranchType::FunctionCall : BranchType::LocalBranch; } - } else if (field1 == 1 && (instruction & EIF_PERFORM_BLR)) { - type = BranchType::Return; + } else if (field1 == 1 && (instruction & EIF_PERFORM_BLR)) { // classify HACK instruction + type = instruction & EIF_USE_BRANCH ? BranchType::FunctionCall : BranchType::Return; + } else if (field1 == 1 && (instruction & EIF_USE_BRANCH)) { + type = BranchType::LocalBranch; } - return type; } diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 53f3a2c412..31d44fad14 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -847,12 +847,12 @@ struct cast_ppu_gpr typedef typename std::underlying_type::type underlying_type; - __forceinline static u64 to_gpr(const T& value) + force_inline static u64 to_gpr(const T& value) { return cast_ppu_gpr::to_gpr(static_cast(value)); } - __forceinline static T from_gpr(const u64 reg) + force_inline static T from_gpr(const u64 reg) { return static_cast(cast_ppu_gpr::from_gpr(reg)); } @@ -861,12 +861,12 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const u8& value) + force_inline static u64 to_gpr(const u8& value) { return value; } - __forceinline static u8 from_gpr(const u64 reg) + force_inline static u8 from_gpr(const u64 reg) { return static_cast(reg); } @@ -875,12 +875,12 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const u16& value) + force_inline static u64 to_gpr(const u16& value) { return value; } - __forceinline static u16 from_gpr(const u64 reg) + force_inline static u16 from_gpr(const u64 reg) { return static_cast(reg); } @@ -889,12 +889,12 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const u32& value) + force_inline static u64 to_gpr(const u32& value) { return value; } - __forceinline static u32 from_gpr(const u64 reg) + force_inline static u32 from_gpr(const u64 reg) { return static_cast(reg); } @@ -904,12 +904,12 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const unsigned long& value) + force_inline static u64 to_gpr(const unsigned long& value) { return value; } - __forceinline static unsigned long from_gpr(const u64 reg) + force_inline static unsigned long from_gpr(const u64 reg) { return static_cast(reg); } @@ -919,12 +919,12 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const u64& value) + force_inline static u64 to_gpr(const u64& value) { return value; } - __forceinline static u64 from_gpr(const u64 reg) + force_inline static u64 from_gpr(const u64 reg) { return reg; } @@ -933,12 +933,12 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const s8& value) + force_inline static u64 to_gpr(const s8& value) { return value; } - __forceinline static s8 from_gpr(const u64 reg) + force_inline static s8 from_gpr(const u64 reg) { return static_cast(reg); } @@ -947,12 +947,12 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const s16& value) + force_inline static u64 to_gpr(const s16& value) { return value; } - __forceinline static s16 from_gpr(const u64 reg) + force_inline static s16 from_gpr(const u64 reg) { return static_cast(reg); } @@ -961,12 +961,12 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const s32& value) + force_inline static u64 to_gpr(const s32& value) { return value; } - __forceinline static s32 from_gpr(const u64 reg) + force_inline static s32 from_gpr(const u64 reg) { return static_cast(reg); } @@ -975,12 +975,12 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const s64& value) + force_inline static u64 to_gpr(const s64& value) { return value; } - __forceinline static s64 from_gpr(const u64 reg) + force_inline static s64 from_gpr(const u64 reg) { return static_cast(reg); } @@ -989,25 +989,25 @@ struct cast_ppu_gpr template<> struct cast_ppu_gpr { - __forceinline static u64 to_gpr(const bool& value) + force_inline static u64 to_gpr(const bool& value) { return value; } - __forceinline static bool from_gpr(const u64& reg) + force_inline static bool from_gpr(const u64& reg) { return reinterpret_cast(reg); } }; template -__forceinline u64 cast_to_ppu_gpr(const T& value) +force_inline u64 cast_to_ppu_gpr(const T& value) { return cast_ppu_gpr::to_gpr(value); } template -__forceinline T cast_from_ppu_gpr(const u64 reg) +force_inline T cast_from_ppu_gpr(const u64 reg) { return cast_ppu_gpr::from_gpr(reg); } diff --git a/rpcs3/Emu/Cell/RawSPUThread.h b/rpcs3/Emu/Cell/RawSPUThread.h index 51811d4f22..f4186ae4ed 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.h +++ b/rpcs3/Emu/Cell/RawSPUThread.h @@ -9,7 +9,7 @@ enum : u32 RAW_SPU_PROB_OFFSET = 0x00040000, }; -__forceinline static u32 GetRawSPURegAddrByNum(int num, int offset) +force_inline static u32 GetRawSPURegAddrByNum(int num, int offset) { return RAW_SPU_OFFSET * num + RAW_SPU_BASE_ADDR + RAW_SPU_PROB_OFFSET + offset; } diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 1287970cff..893e8d8f63 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -1,43 +1,43 @@ #pragma once +#include "Emu/CPU/CPUDecoder.h" +#include "Emu/Cell/SPUOpcodes.h" -#define ASMJIT_STATIC - -#include "asmjit.h" - -using namespace asmjit; -using namespace asmjit::host; - -#define UNIMPLEMENTED() UNK(__FUNCTION__) +namespace asmjit +{ + struct JitRuntime; + struct X86Compiler; + struct X86GpVar; + struct X86XmmVar; + struct X86Mem; +} class SPURecompiler; +class SPUInterpreter; class SPURecompilerCore : public CPUDecoder { - SPURecompiler* m_enc; + std::unique_ptr m_enc; + std::unique_ptr m_int; + std::unique_ptr m_jit; SPUThread& CPU; public: - SPUInterpreter* inter; - JitRuntime runtime; - bool first; - bool need_check; + bool first = true; + bool need_check = false; struct SPURecEntry { - //u16 host; // absolute position of first instruction of current block (not used now) - u16 count; // count of instructions compiled from current point (and to be checked) + u32 count; // count of instructions compiled from current point (and to be checked) u32 valid; // copy of valid opcode for validation void* pointer; // pointer to executable memory object }; - SPURecEntry entry[0x10000]; + std::array entry = {}; std::vector imm_table; SPURecompilerCore(SPUThread& cpu); - ~SPURecompilerCore(); - void Compile(u16 pos); virtual void Decode(const u32 code); @@ -45,47 +45,6 @@ public: virtual u32 DecodeMemory(const u32 address); }; -#define c (*compiler) - -#define cpu_offsetof(x) static_cast(reinterpret_cast(&(((SPUThread*)0)->x))) -#define cpu_xmm(x) oword_ptr(*cpu_var, cpu_offsetof(x)) -#define cpu_qword(x) qword_ptr(*cpu_var, cpu_offsetof(x)) -#define cpu_dword(x) dword_ptr(*cpu_var, cpu_offsetof(x)) -#define cpu_word(x) word_ptr(*cpu_var, cpu_offsetof(x)) -#define cpu_byte(x) byte_ptr(*cpu_var, cpu_offsetof(x)) - -#define g_imm_offsetof(x) static_cast(reinterpret_cast(&(((g_spu_imm_table_t*)0)->x))) -#define g_imm_xmm(x) oword_ptr(*g_imm_var, g_imm_offsetof(x)) -#define g_imm2_xmm(x, y) oword_ptr(*g_imm_var, y, 0, g_imm_offsetof(x)) - - -#define LOG_OPCODE(...) //ConLog.Write("Compiled "__FUNCTION__"(): "__VA_ARGS__) - -#define LOG3_OPCODE(...) //ConLog.Write("Linked "__FUNCTION__"(): "__VA_ARGS__) - -#define LOG4_OPCODE(...) //c.addComment(fmt::Format("SPU info: "__FUNCTION__"(): "__VA_ARGS__).c_str()) - -#define WRAPPER_BEGIN(a0, a1, a2, a3) struct opwr_##a0 \ -{ \ - static void opcode(u32 a0, u32 a1, u32 a2, u32 a3) \ -{ \ - SPUThread& CPU = *(SPUThread*)GetCurrentNamedThread(); - -#define WRAPPER_END(a0, a1, a2, a3) /*LOG2_OPCODE();*/ } \ -}; \ - /*XmmRelease();*/ \ - if (#a0[0] == 'r') XmmInvalidate(a0); \ - if (#a1[0] == 'r') XmmInvalidate(a1); \ - if (#a2[0] == 'r') XmmInvalidate(a2); \ - if (#a3[0] == 'r') XmmInvalidate(a3); \ - X86CallNode* call##a0 = c.call(imm_ptr(reinterpret_cast(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4()); \ - call##a0->setArg(0, imm_u(a0)); \ - call##a0->setArg(1, imm_u(a1)); \ - call##a0->setArg(2, imm_u(a2)); \ - call##a0->setArg(3, imm_u(a3)); \ - LOG3_OPCODE(/*#a0"=%d, "#a1"=%d, "#a2"=%d, "#a3"=%d", a0, a1, a2, a3*/); - - class SPURecompiler : public SPUOpcodes { private: @@ -93,24 +52,24 @@ private: SPURecompilerCore& rec; public: - X86Compiler* compiler; + asmjit::X86Compiler* compiler; bool do_finalize; // input: - X86GpVar* cpu_var; - X86GpVar* ls_var; - X86GpVar* imm_var; - X86GpVar* g_imm_var; + asmjit::X86GpVar* cpu_var; + asmjit::X86GpVar* ls_var; + asmjit::X86GpVar* imm_var; + asmjit::X86GpVar* g_imm_var; // output: - X86GpVar* pos_var; + asmjit::X86GpVar* pos_var; // temporary: - X86GpVar* addr; - X86GpVar* qw0; - X86GpVar* qw1; - X86GpVar* qw2; + asmjit::X86GpVar* addr; + asmjit::X86GpVar* qw0; + asmjit::X86GpVar* qw1; + asmjit::X86GpVar* qw2; struct XmmLink { - X86XmmVar* data; + asmjit::X86XmmVar* data; s8 reg; bool taken; mutable bool got; @@ -125,7 +84,7 @@ public: { } - const XmmVar& get() const + const asmjit::X86XmmVar& get() const { assert(data); assert(taken); @@ -134,12 +93,13 @@ public: return *data; } - const XmmVar& read() const + const asmjit::X86XmmVar& read() const { assert(data); return *data; } - } xmm_var[16]; + } + xmm_var[16]; SPURecompiler(SPUThread& cpu, SPURecompilerCore& rec) : CPU(cpu) @@ -148,2957 +108,228 @@ public: { } - const XmmLink& XmmAlloc(s8 pref = -1) // get empty xmm register - { - if (pref >= 0) for (u32 i = 0; i < 16; i++) - { - if ((xmm_var[i].reg == pref) && !xmm_var[i].taken) - { - xmm_var[i].taken = true; - xmm_var[i].got = false; - xmm_var[i].access = 0; - LOG4_OPCODE("pref(%d) reg taken (i=%d)", pref, i); - return xmm_var[i]; - } - } - for (u32 i = 0; i < 16; i++) - { - if ((xmm_var[i].reg == -1) && !xmm_var[i].taken) - { - xmm_var[i].taken = true; - xmm_var[i].got = false; - xmm_var[i].access = 0; - LOG4_OPCODE("free reg taken (i=%d)", i); - return xmm_var[i]; - } - } - int last = -1, max = -1; - for (u32 i = 0; i < 16; i++) - { - if (!xmm_var[i].taken) - { - if ((int)xmm_var[i].access > max) - { - last = i; - max = xmm_var[i].access; - } - } - } - if (last >= 0) - { - // (saving cached data?) - //c.movdqa(cpu_xmm(GPR[xmm_var[last].reg]), *xmm_var[last].data); - xmm_var[last].taken = true; - xmm_var[last].got = false; - LOG4_OPCODE("cached reg taken (i=%d): GPR[%d] lost", last, xmm_var[last].reg); - xmm_var[last].reg = -1; // ??? - xmm_var[last].access = 0; - return xmm_var[last]; - } - throw "XmmAlloc() failed"; - } - - const XmmLink* XmmRead(const s8 reg) const // get xmm register with specific SPU reg or nullptr - { - assert(reg >= 0); - for (u32 i = 0; i < 16; i++) - { - if (xmm_var[i].reg == reg) - { - //assert(!xmm_var[i].got); - //if (xmm_var[i].got) throw "XmmRead(): wrong reuse"; - LOG4_OPCODE("GPR[%d] has been read (i=%d)", reg, i); - xmm_var[i].access++; - return &xmm_var[i]; - } - } - LOG4_OPCODE("GPR[%d] not found", reg); - return nullptr; - } - - const XmmLink& XmmGet(s8 reg, s8 target = -1) // get xmm register with specific SPU reg - { - assert(reg >= 0); - const XmmLink* res = nullptr; - if (reg == target) - { - for (u32 i = 0; i < 16; i++) - { - if (xmm_var[i].reg == reg) - { - res = &xmm_var[i]; - if (xmm_var[i].taken) throw "XmmGet(): xmm_var is taken"; - xmm_var[i].taken = true; - xmm_var[i].got = false; - //xmm_var[i].reg = -1; - for (u32 j = i + 1; j < 16; j++) - { - if (xmm_var[j].reg == reg) throw "XmmGet(): xmm_var duplicate"; - } - LOG4_OPCODE("cached GPR[%d] used (i=%d)", reg, i); - break; - } - } - } - if (!res) - { - res = &XmmAlloc(target); - /*if (target != res->reg) - { - c.movdqa(*res->data, cpu_xmm(GPR[reg])); - } - else*/ - { - if (const XmmLink* source = XmmRead(reg)) - { - c.movdqa(*res->data, source->read()); - } - else - { - c.movdqa(*res->data, cpu_xmm(GPR[reg])); - } - } - const_cast(res)->reg = -1; // ??? - LOG4_OPCODE("* cached GPR[%d] not found", reg); - } - return *res; - } - - const XmmLink& XmmCopy(const XmmLink& from, s8 pref = -1) // XmmAlloc + mov - { - const XmmLink* res = &XmmAlloc(pref); - c.movdqa(*res->data, *from.data); - const_cast(res)->reg = -1; // ??? - LOG4_OPCODE("*"); - return *res; - } - - void XmmInvalidate(const s8 reg) // invalidate cached register - { - assert(reg >= 0); - for (u32 i = 0; i < 16; i++) - { - if (xmm_var[i].reg == reg) - { - if (xmm_var[i].taken) throw "XmmInvalidate(): xmm_var is taken"; - LOG4_OPCODE("GPR[%d] invalidated (i=%d)", reg, i); - xmm_var[i].reg = -1; - xmm_var[i].access = 0; - } - } - } - - void XmmFinalize(const XmmLink& var, s8 reg = -1) - { - // invalidation - if (reg >= 0) for (u32 i = 0; i < 16; i++) - { - if (xmm_var[i].reg == reg) - { - LOG4_OPCODE("GPR[%d] invalidated (i=%d)", reg, i); - xmm_var[i].reg = -1; - xmm_var[i].access = 0; - } - } - for (u32 i = 0; i < 16; i++) - { - if (xmm_var[i].data == var.data) - { - assert(xmm_var[i].taken); - // save immediately: - if (reg >= 0) - { - c.movdqa(cpu_xmm(GPR[reg]), *xmm_var[i].data); - } - else - { - } - LOG4_OPCODE("GPR[%d] finalized (i=%d), GPR[%d] replaced", reg, i, xmm_var[i].reg); - // (to disable caching:) - //reg = -1; - xmm_var[i].reg = reg; - xmm_var[i].taken = false; - xmm_var[i].got = false; - xmm_var[i].access = 0; - return; - } - } - assert(false); - } - - void XmmRelease() - { - for (u32 i = 0; i < 16; i++) - { - if (xmm_var[i].reg >= 0) - { - //c.movdqa(cpu_xmm(GPR[xmm_var[i].reg]), *xmm_var[i].data); - LOG4_OPCODE("GPR[%d] released (i=%d)", xmm_var[i].reg, i); - xmm_var[i].reg = -1; - xmm_var[i].access = 0; - } - } - } - - Mem XmmConst(u128 data) - { - s32 shift = 0; - - for (; shift < rec.imm_table.size(); shift++) - { - if (rec.imm_table[shift] == data) - { - return oword_ptr(*imm_var, shift * sizeof(u128)); - } - } - - rec.imm_table.push_back(data); - return oword_ptr(*imm_var, shift * sizeof(u128)); - } + const XmmLink& XmmAlloc(s8 pref = -1); + const XmmLink* XmmRead(const s8 reg) const; + const XmmLink& XmmGet(s8 reg, s8 target = -1); + const XmmLink& XmmCopy(const XmmLink& from, s8 pref = -1); + void XmmInvalidate(const s8 reg); + void XmmFinalize(const XmmLink& var, s8 reg = -1); + void XmmRelease(); + asmjit::X86Mem XmmConst(u128 data); private: + //0 - 10 - void STOP(u32 code) - { - struct STOP_wrapper - { - static void STOP(u32 code) - { - SPUThread& CPU = *(SPUThread*)GetCurrentNamedThread(); - CPU.stop_and_signal(code); - LOG2_OPCODE(); - } - }; - c.mov(cpu_dword(PC), CPU.PC); - X86CallNode* call = c.call(imm_ptr(reinterpret_cast(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1()); - call->setArg(0, imm_u(code)); - c.mov(*pos_var, (CPU.PC >> 2) + 1); - do_finalize = true; - LOG_OPCODE(); - } - void LNOP() - { - LOG_OPCODE(); - } - void SYNC(u32 Cbit) - { - c.mov(cpu_dword(PC), CPU.PC); - // This instruction must be used following a store instruction that modifies the instruction stream. - c.mfence(); - c.mov(*pos_var, (CPU.PC >> 2) + 1 + 0x2000000); - do_finalize = true; - LOG_OPCODE(); - } - void DSYNC() - { - // This instruction forces all earlier load, store, and channel instructions to complete before proceeding. - c.mfence(); - LOG_OPCODE(); - } - void MFSPR(u32 rt, u32 sa) - { - UNIMPLEMENTED(); - } - void RDCH(u32 rt, u32 ra) - { - c.mov(cpu_dword(PC), CPU.PC); - WRAPPER_BEGIN(rt, ra, yy, zz); - CPU.GPR[rt] = u128::from32r(CPU.get_ch_value(ra)); - WRAPPER_END(rt, ra, 0, 0); - // TODO - } - void RCHCNT(u32 rt, u32 ra) - { - c.mov(cpu_dword(PC), CPU.PC); - WRAPPER_BEGIN(rt, ra, yy, zz); - CPU.GPR[rt] = u128::from32r(CPU.get_ch_count(ra)); - WRAPPER_END(rt, ra, 0, 0); - // TODO - } - void SF(u32 rt, u32 ra, u32 rb) - { - // sub from - const XmmLink& vb = XmmGet(rb, rt); - if (const XmmLink* va = XmmRead(ra)) - { - c.psubd(vb.get(), va->read()); - } - else - { - c.psubd(vb.get(), cpu_xmm(GPR[ra])); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void OR(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vb = XmmGet(rb, rt); - if (const XmmLink* va = XmmRead(ra)) - { - c.por(vb.get(), va->read()); - } - else - { - c.por(vb.get(), cpu_xmm(GPR[ra])); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void BG(u32 rt, u32 ra, u32 rb) - { - // compare if-greater-than - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vi = XmmAlloc(); - c.movdqa(vi.get(), XmmConst(u128::from32p(0x80000000))); - c.pxor(va.get(), vi.get()); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pxor(vi.get(), vb->read()); - } - else - { - c.pxor(vi.get(), cpu_xmm(GPR[rb])); - } - c.pcmpgtd(va.get(), vi.get()); - c.paddd(va.get(), XmmConst(u128::from32p(1))); - XmmFinalize(va, rt); - XmmFinalize(vi); - LOG_OPCODE(); - } - void SFH(u32 rt, u32 ra, u32 rb) - { - // sub from (halfword) - const XmmLink& vb = XmmGet(rb, rt); - if (const XmmLink* va = XmmRead(ra)) - { - c.psubw(vb.get(), va->read()); - } - else - { - c.psubw(vb.get(), cpu_xmm(GPR[ra])); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void NOR(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (ra != rb) - { - if (const XmmLink* vb = XmmRead(rb)) - { - c.por(va.get(), vb->read()); - } - else - { - c.por(va.get(), cpu_xmm(GPR[rb])); - } - } - c.pxor(va.get(), XmmConst(u128::from32p(0xffffffff))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ABSDB(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = XmmGet(rb); - const XmmLink& vm = XmmCopy(va); - c.pmaxub(va.get(), vb.get()); - c.pminub(vb.get(), vm.get()); - c.psubb(va.get(), vb.get()); - XmmFinalize(va, rt); - XmmFinalize(vb); - XmmFinalize(vm); - LOG_OPCODE(); - } - void ROT(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - for (u32 i = 0; i < 4; i++) - { - c.mov(qw0->r32(), cpu_dword(GPR[ra]._u32[i])); - c.mov(*addr, cpu_dword(GPR[rb]._u32[i])); - c.rol(qw0->r32(), *addr); - c.mov(cpu_dword(GPR[rt]._u32[i]), qw0->r32()); - } - LOG_OPCODE(); - } - void ROTM(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - for (u32 i = 0; i < 4; i++) - { - c.mov(qw0->r32(), cpu_dword(GPR[ra]._u32[i])); - c.mov(*addr, cpu_dword(GPR[rb]._u32[i])); - c.neg(*addr); - c.shr(*qw0, *addr); - c.mov(cpu_dword(GPR[rt]._u32[i]), qw0->r32()); - } - LOG_OPCODE(); - } - void ROTMA(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - for (u32 i = 0; i < 4; i++) - { - c.movsxd(*qw0, cpu_dword(GPR[ra]._u32[i])); - c.mov(*addr, cpu_dword(GPR[rb]._u32[i])); - c.neg(*addr); - c.sar(*qw0, *addr); - c.mov(cpu_dword(GPR[rt]._u32[i]), qw0->r32()); - } - LOG_OPCODE(); - } - void SHL(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - for (u32 i = 0; i < 4; i++) - { - c.mov(qw0->r32(), cpu_dword(GPR[ra]._u32[i])); - c.mov(*addr, cpu_dword(GPR[rb]._u32[i])); - c.shl(*qw0, *addr); - c.mov(cpu_dword(GPR[rt]._u32[i]), qw0->r32()); - } - LOG_OPCODE(); - } - void ROTH(u32 rt, u32 ra, u32 rb) //nf - { - XmmInvalidate(rt); - for (u32 i = 0; i < 8; i++) - { - c.movzx(qw0->r32(), cpu_word(GPR[ra]._u16[i])); - c.movzx(*addr, cpu_word(GPR[rb]._u16[i])); - c.rol(qw0->r16(), *addr); - c.mov(cpu_word(GPR[rt]._u16[i]), qw0->r16()); - } - LOG_OPCODE(); - } - void ROTHM(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - for (u32 i = 0; i < 8; i++) - { - c.movzx(qw0->r32(), cpu_word(GPR[ra]._u16[i])); - c.movzx(*addr, cpu_word(GPR[rb]._u16[i])); - c.neg(*addr); - c.shr(qw0->r32(), *addr); - c.mov(cpu_word(GPR[rt]._u16[i]), qw0->r16()); - } - LOG_OPCODE(); - } - void ROTMAH(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - for (u32 i = 0; i < 8; i++) - { - c.movsx(qw0->r32(), cpu_word(GPR[ra]._u16[i])); - c.movzx(*addr, cpu_word(GPR[rb]._u16[i])); - c.neg(*addr); - c.sar(qw0->r32(), *addr); - c.mov(cpu_word(GPR[rt]._u16[i]), qw0->r16()); - } - LOG_OPCODE(); - } - void SHLH(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - for (u32 i = 0; i < 8; i++) - { - c.movzx(qw0->r32(), cpu_word(GPR[ra]._u16[i])); - c.movzx(*addr, cpu_word(GPR[rb]._u16[i])); - c.shl(qw0->r32(), *addr); - c.mov(cpu_word(GPR[rt]._u16[i]), qw0->r16()); - } - LOG_OPCODE(); - } - void ROTI(u32 rt, u32 ra, s32 i7) - { - // rotate left - const int s = i7 & 0x1f; - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& v1 = XmmCopy(va); - c.pslld(va.get(), s); - c.psrld(v1.get(), 32 - s); - c.por(va.get(), v1.get()); - XmmFinalize(va, rt); - XmmFinalize(v1); - LOG_OPCODE(); - } - void ROTMI(u32 rt, u32 ra, s32 i7) - { - // shift right logical - const int s = (0 - i7) & 0x3f; - const XmmLink& va = XmmGet(ra, rt); - c.psrld(va.get(), s); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ROTMAI(u32 rt, u32 ra, s32 i7) - { - // shift right arithmetical - const int s = (0 - i7) & 0x3f; - const XmmLink& va = XmmGet(ra, rt); - c.psrad(va.get(), s); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void SHLI(u32 rt, u32 ra, s32 i7) - { - // shift left - const int s = i7 & 0x3f; - const XmmLink& va = XmmGet(ra, rt); - c.pslld(va.get(), s); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ROTHI(u32 rt, u32 ra, s32 i7) - { - // rotate left (halfword) - const int s = i7 & 0xf; - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& v1 = XmmCopy(va); - c.psllw(va.get(), s); - c.psrlw(v1.get(), 16 - s); - c.por(va.get(), v1.get()); - XmmFinalize(va, rt); - XmmFinalize(v1); - LOG_OPCODE(); - } - void ROTHMI(u32 rt, u32 ra, s32 i7) - { - // shift right logical - const int s = (0 - i7) & 0x1f; - const XmmLink& va = XmmGet(ra, rt); - c.psrlw(va.get(), s); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ROTMAHI(u32 rt, u32 ra, s32 i7) - { - // shift right arithmetical (halfword) - const int s = (0 - i7) & 0x1f; - const XmmLink& va = XmmGet(ra, rt); - c.psraw(va.get(), s); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void SHLHI(u32 rt, u32 ra, s32 i7) - { - // shift left (halfword) - const int s = i7 & 0x1f; - const XmmLink& va = XmmGet(ra, rt); - c.psllw(va.get(), s); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void A(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vb = XmmGet(rb, rt); - if (const XmmLink* va = XmmRead(ra)) - { - c.paddd(vb.get(), va->read()); - } - else - { - c.paddd(vb.get(), cpu_xmm(GPR[ra])); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void AND(u32 rt, u32 ra, u32 rb) - { - // and - const XmmLink& vb = XmmGet(rb, rt); - if (const XmmLink* va = XmmRead(ra)) - { - c.pand(vb.get(), va->read()); - } - else - { - c.pand(vb.get(), cpu_xmm(GPR[ra])); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void CG(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = XmmGet(rb); - const XmmLink& vi = XmmAlloc(); - c.movdqa(vi.get(), XmmConst(u128::from32p(0x80000000))); - c.paddd(vb.get(), va.get()); - c.pxor(va.get(), vi.get()); - c.pxor(vb.get(), vi.get()); - c.pcmpgtd(va.get(), vb.get()); - c.psrld(va.get(), 31); - XmmFinalize(va, rt); - XmmFinalize(vb); - XmmFinalize(vi); - LOG_OPCODE(); - } - void AH(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.paddw(va.get(), vb->read()); - } - else - { - c.paddw(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void NAND(u32 rt, u32 ra, u32 rb) - { - // nand - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pand(va.get(), vb->read()); - } - else - { - c.pand(va.get(), cpu_xmm(GPR[rb])); - } - c.pxor(va.get(), XmmConst(u128::from32p(0xffffffff))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void AVGB(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vb = XmmGet(rb); - if (const XmmLink* va = XmmRead(ra)) - { - c.pavgb(vb.get(), va->read()); - } - else - { - c.pavgb(vb.get(), cpu_xmm(GPR[ra])); - } - XmmFinalize(vb, rt); - } - void MTSPR(u32 rt, u32 sa) - { - } - void WRCH(u32 ra, u32 rt) - { - c.mov(cpu_dword(PC), CPU.PC); - WRAPPER_BEGIN(ra, rt, yy, zz); - CPU.set_ch_value(ra, CPU.GPR[rt]._u32[3]); - WRAPPER_END(ra, rt, 0, 0); - // TODO - - /*XmmInvalidate(rt); - - X86GpVar v(c, kVarTypeUInt32); - c.mov(v, cpu_dword(GPR[rt]._u32[3])); - switch (ra) - { - case MFC_LSA: - c.mov(cpu_dword(MFC1.LSA.m_value[0]), v); - break; - - case MFC_EAH: - c.mov(cpu_dword(MFC1.EAH.m_value[0]), v); - break; - - case MFC_EAL: - c.mov(cpu_dword(MFC1.EAL.m_value[0]), v); - break; - - case MFC_Size: - c.mov(cpu_word(MFC1.Size_Tag.m_val16[1]), v); - break; - - case MFC_TagID: - c.mov(cpu_word(MFC1.Size_Tag.m_val16[0]), v); - break; - - default: - { - X86X64CallNode* call = c.call(imm_ptr(reinterpret_cast(&WRCH_wrapper::WRCH)), kFuncConvHost, FuncBuilder2()); - call->setArg(0, imm_u(ra)); - call->setArg(1, v); - } - }*/ - } - void BIZ(u32 intr, u32 rt, u32 ra) - { - switch (intr & 0x30) - { - case 0: break; - default: UNIMPLEMENTED(); return; - } - - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*addr, CPU.PC + 4); - c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); - if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) - c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); - c.cmovne(*pos_var, *addr); - c.shr(*pos_var, 2); - LOG_OPCODE(); - } - void BINZ(u32 intr, u32 rt, u32 ra) - { - switch (intr & 0x30) - { - case 0: break; - default: UNIMPLEMENTED(); return; - } - - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*addr, CPU.PC + 4); - c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); - if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) - c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); - c.cmove(*pos_var, *addr); - c.shr(*pos_var, 2); - LOG_OPCODE(); - } - void BIHZ(u32 intr, u32 rt, u32 ra) - { - switch (intr & 0x30) - { - case 0: break; - default: UNIMPLEMENTED(); return; - } - - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*addr, CPU.PC + 4); - c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); - if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) - c.cmp(cpu_word(GPR[rt]._u16[6]), 0); - c.cmovne(*pos_var, *addr); - c.shr(*pos_var, 2); - LOG_OPCODE(); - } - void BIHNZ(u32 intr, u32 rt, u32 ra) - { - switch (intr & 0x30) - { - case 0: break; - default: UNIMPLEMENTED(); return; - } - - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*addr, CPU.PC + 4); - c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); - if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) - c.cmp(cpu_word(GPR[rt]._u16[6]), 0); - c.cmove(*pos_var, *addr); - c.shr(*pos_var, 2); - LOG_OPCODE(); - } - void STOPD(u32 rc, u32 ra, u32 rb) - { - UNIMPLEMENTED(); - } - void STQX(u32 rt, u32 ra, u32 rb) - { - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - if (ra == rb) - { - c.add(*addr, *addr); - } - else - { - c.add(*addr, cpu_dword(GPR[rb]._u32[3])); - } - c.and_(*addr, 0x3fff0); - - /*const XmmLink& vt = XmmGet(rt); - c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - c.movdqa(oword_ptr(*ls_var, *addr), vt.get()); - XmmFinalize(vt);*/ - - c.mov(*qw0, cpu_qword(GPR[rt]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[rt]._u64[1])); - c.bswap(*qw0); - c.bswap(*qw1); - c.mov(qword_ptr(*ls_var, *addr, 0, 0), *qw1); - c.mov(qword_ptr(*ls_var, *addr, 0, 8), *qw0); - - LOG_OPCODE(); - } - void BI(u32 intr, u32 ra) - { - switch (intr & 0x30) - { - case 0: break; - default: UNIMPLEMENTED(); return; - } - - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); - if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) - c.shr(*pos_var, 2); - LOG_OPCODE(); - } - void BISL(u32 intr, u32 rt, u32 ra) - { - switch (intr & 0x30) - { - case 0: break; - default: UNIMPLEMENTED(); return; - } - - XmmInvalidate(rt); - - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.xor_(*pos_var, *pos_var); - c.mov(cpu_dword(GPR[rt]._u32[0]), *pos_var); - c.mov(cpu_dword(GPR[rt]._u32[1]), *pos_var); - c.mov(cpu_dword(GPR[rt]._u32[2]), *pos_var); - c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); - c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4); - c.shr(*pos_var, 2); - c.or_(*pos_var, 0x2000000); - LOG_OPCODE(); - } - void IRET(u32 ra) - { - UNIMPLEMENTED(); - } - void BISLED(u32 intr, u32 rt, u32 ra) - { - UNIMPLEMENTED(); - } - void HBR(u32 p, u32 ro, u32 ra) - { - LOG_OPCODE(); - } - void GB(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - c.pshufb(va.get(), XmmConst(u128::fromV(_mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 8, 4, 0)))); - c.psllq(va.get(), 7); - c.pmovmskb(*addr, va.get()); - c.pxor(va.get(), va.get()); - c.pinsrw(va.get(), *addr, 6); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void GBH(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - c.pshufb(va.get(), XmmConst(u128::fromV(_mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 14, 12, 10, 8, 6, 4, 2, 0)))); - c.psllq(va.get(), 7); - c.pmovmskb(*addr, va.get()); - c.pxor(va.get(), va.get()); - c.pinsrw(va.get(), *addr, 6); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void GBB(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - c.psllq(va.get(), 7); - c.pmovmskb(*addr, va.get()); - c.pxor(va.get(), va.get()); - c.pinsrw(va.get(), *addr, 6); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void FSM(u32 rt, u32 ra) - { - const XmmLink& vr = XmmAlloc(rt); - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.and_(*addr, 0xf); - c.shl(*addr, 4); - c.movdqa(vr.get(), g_imm2_xmm(fsm[0], *addr)); - XmmFinalize(vr, rt); - LOG_OPCODE(); - } - void FSMH(u32 rt, u32 ra) - { - const XmmLink& vr = XmmAlloc(rt); - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.and_(*addr, 0xff); - c.shl(*addr, 4); - c.movdqa(vr.get(), g_imm2_xmm(fsmh[0], *addr)); - XmmFinalize(vr, rt); - LOG_OPCODE(); - } - void FSMB(u32 rt, u32 ra) - { - const XmmLink& vr = XmmAlloc(rt); - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.and_(*addr, 0xffff); - c.shl(*addr, 4); - c.movdqa(vr.get(), g_imm2_xmm(fsmb[0], *addr)); - XmmFinalize(vr, rt); - LOG_OPCODE(); - } - void FREST(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - c.rcpps(va.get(), va.get()); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void FRSQEST(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - c.andps(va.get(), XmmConst(u128::from32p(0x7fffffff))); // abs - c.rsqrtps(va.get(), va.get()); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void LQX(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - if (ra == rb) - { - c.add(*addr, *addr); - } - else - { - c.add(*addr, cpu_dword(GPR[rb]._u32[3])); - } - c.and_(*addr, 0x3fff0); - - /*const XmmLink& vt = XmmAlloc(rt); - c.movdqa(vt.get(), oword_ptr(*ls_var, *addr)); - c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - XmmFinalize(vt, rt);*/ - - c.mov(*qw0, qword_ptr(*ls_var, *addr, 0, 0)); - c.mov(*qw1, qword_ptr(*ls_var, *addr, 0, 8)); - c.bswap(*qw0); - c.bswap(*qw1); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0); - - LOG_OPCODE(); - } - void ROTQBYBI(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - c.and_(*addr, 0xf << 3); - c.shl(*addr, 1); - c.pshufb(va.get(), g_imm2_xmm(rldq_pshufb[0], *addr)); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ROTQMBYBI(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - c.shr(*addr, 3); - c.neg(*addr); - c.and_(*addr, 0x1f); - c.shl(*addr, 4); - c.pshufb(va.get(), g_imm2_xmm(srdq_pshufb[0], *addr)); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void SHLQBYBI(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - c.and_(*addr, 0x1f << 3); - c.shl(*addr, 1); - c.pshufb(va.get(), g_imm2_xmm(sldq_pshufb[0], *addr)); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CBX(u32 rt, u32 ra, u32 rb) - { - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - if (ra == 1) - { - // assuming that SP % 16 is always zero - } - else if (ra == rb) - { - c.add(*addr, *addr); - } - else - { - c.add(*addr, cpu_dword(GPR[ra]._u32[3])); - } - c.not_(*addr); - c.and_(*addr, 0xf); - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); - XmmFinalize(vr, rt); - XmmInvalidate(rt); - c.mov(byte_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u8[0])), 0x03); - LOG_OPCODE(); - } - void CHX(u32 rt, u32 ra, u32 rb) - { - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - if (ra == 1) - { - // assuming that SP % 16 is always zero - } - else if (ra == rb) - { - c.add(*addr, *addr); - } - else - { - c.add(*addr, cpu_dword(GPR[ra]._u32[3])); - } - c.not_(*addr); - c.and_(*addr, 0xe); - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); - XmmFinalize(vr, rt); - XmmInvalidate(rt); - c.mov(word_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203); - LOG_OPCODE(); - } - void CWX(u32 rt, u32 ra, u32 rb) - { - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - if (ra == 1) - { - // assuming that SP % 16 is always zero - } - else if (ra == rb) - { - c.add(*addr, *addr); - } - else - { - c.add(*addr, cpu_dword(GPR[ra]._u32[3])); - } - c.not_(*addr); - c.and_(*addr, 0xc); - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); - XmmFinalize(vr, rt); - XmmInvalidate(rt); - c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203); - LOG_OPCODE(); - } - void CDX(u32 rt, u32 ra, u32 rb) - { - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - if (ra == 1) - { - // assuming that SP % 16 is always zero - } - else if (ra == rb) - { - c.add(*addr, *addr); - } - else - { - c.add(*addr, cpu_dword(GPR[ra]._u32[3])); - } - c.not_(*addr); - c.and_(*addr, 0x8); - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); - XmmFinalize(vr, rt); - XmmInvalidate(rt); - c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x04050607); - c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[1])), 0x00010203); - LOG_OPCODE(); - } - void ROTQBI(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); - c.mov(*qw2, *qw0); - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - c.and_(*addr, 7); - c.shld(*qw0, *qw1, *addr); - c.shld(*qw1, *qw2, *addr); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); - LOG_OPCODE(); - } - void ROTQMBI(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - c.neg(*addr); - c.and_(*addr, 7); - c.shrd(*qw0, *qw1, *addr); - c.shr(*qw1, *addr); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); - LOG_OPCODE(); - } - void SHLQBI(u32 rt, u32 ra, u32 rb) - { - XmmInvalidate(rt); - c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - c.and_(*addr, 7); - c.shld(*qw1, *qw0, *addr); - c.shl(*qw0, *addr); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); - LOG_OPCODE(); - } - void ROTQBY(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - c.and_(*addr, 0xf); - c.shl(*addr, 4); - c.pshufb(va.get(), g_imm2_xmm(rldq_pshufb[0], *addr)); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ROTQMBY(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - c.neg(*addr); - c.and_(*addr, 0x1f); - c.shl(*addr, 4); - c.pshufb(va.get(), g_imm2_xmm(srdq_pshufb[0], *addr)); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void SHLQBY(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); - c.and_(*addr, 0x1f); - c.shl(*addr, 4); - c.pshufb(va.get(), g_imm2_xmm(sldq_pshufb[0], *addr)); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ORX(u32 rt, u32 ra) - { - XmmInvalidate(rt); - c.mov(*addr, cpu_dword(GPR[ra]._u32[0])); - c.or_(*addr, cpu_dword(GPR[ra]._u32[1])); - c.or_(*addr, cpu_dword(GPR[ra]._u32[2])); - c.or_(*addr, cpu_dword(GPR[ra]._u32[3])); - c.mov(cpu_dword(GPR[rt]._u32[3]), *addr); - c.xor_(*addr, *addr); - c.mov(cpu_dword(GPR[rt]._u32[0]), *addr); - c.mov(cpu_dword(GPR[rt]._u32[1]), *addr); - c.mov(cpu_dword(GPR[rt]._u32[2]), *addr); - LOG_OPCODE(); - } - void CBD(u32 rt, u32 ra, s32 i7) - { - if (ra == 1) - { - // assuming that SP % 16 is always zero - const XmmLink& vr = XmmAlloc(rt); - u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); - value.u8r[i7 & 0xf] = 0x03; - c.movdqa(vr.get(), XmmConst(value)); - XmmFinalize(vr, rt); - } - else - { - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.add(*addr, i7); - c.not_(*addr); - c.and_(*addr, 0xf); - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); - XmmFinalize(vr, rt); - XmmInvalidate(rt); - c.mov(byte_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u8[0])), 0x03); - } - LOG_OPCODE(); - } - void CHD(u32 rt, u32 ra, s32 i7) - { - if (ra == 1) - { - // assuming that SP % 16 is always zero - const XmmLink& vr = XmmAlloc(rt); - u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); - value.u16r[(i7 >> 1) & 0x7] = 0x0203; - c.movdqa(vr.get(), XmmConst(value)); - XmmFinalize(vr, rt); - } - else - { - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.add(*addr, i7); - c.not_(*addr); - c.and_(*addr, 0xe); - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); - XmmFinalize(vr, rt); - XmmInvalidate(rt); - c.mov(word_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203); - } - LOG_OPCODE(); - } - void CWD(u32 rt, u32 ra, s32 i7) - { - if (ra == 1) - { - // assuming that SP % 16 is always zero - const XmmLink& vr = XmmAlloc(rt); - u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); - value.u32r[(i7 >> 2) & 0x3] = 0x00010203; - c.movdqa(vr.get(), XmmConst(value)); - XmmFinalize(vr, rt); - } - else - { - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.add(*addr, i7); - c.not_(*addr); - c.and_(*addr, 0xc); - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); - XmmFinalize(vr, rt); - XmmInvalidate(rt); - c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203); - } - LOG_OPCODE(); - } - void CDD(u32 rt, u32 ra, s32 i7) - { - if (ra == 1) - { - // assuming that SP % 16 is always zero - const XmmLink& vr = XmmAlloc(rt); - u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); - value.u64r[(i7 >> 3) & 0x1] = 0x0001020304050607ull; - c.movdqa(vr.get(), XmmConst(value)); - XmmFinalize(vr, rt); - } - else - { - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.add(*addr, i7); - c.not_(*addr); - c.and_(*addr, 0x8); - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); - XmmFinalize(vr, rt); - XmmInvalidate(rt); - c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x04050607); - c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[1])), 0x00010203); - } - LOG_OPCODE(); - } - void ROTQBII(u32 rt, u32 ra, s32 i7) - { - XmmInvalidate(rt); - c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); - c.mov(*qw2, *qw0); - c.shld(*qw0, *qw1, i7 & 0x7); - c.shld(*qw1, *qw2, i7 & 0x7); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); - LOG_OPCODE(); - } - void ROTQMBII(u32 rt, u32 ra, s32 i7) - { - XmmInvalidate(rt); - c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); - c.shrd(*qw0, *qw1, (0 - i7) & 0x7); - c.shr(*qw1, (0 - i7) & 0x7); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); - LOG_OPCODE(); - } - void SHLQBII(u32 rt, u32 ra, s32 i7) - { - XmmInvalidate(rt); - c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); - c.shld(*qw1, *qw0, i7 & 0x7); - c.shl(*qw0, i7 & 0x7); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); - LOG_OPCODE(); - } - void ROTQBYI(u32 rt, u32 ra, s32 i7) - { - const int s = i7 & 0xf; - const XmmLink& va = XmmGet(ra, rt); - c.palignr(va.get(), va.get(), 16 - s); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ROTQMBYI(u32 rt, u32 ra, s32 i7) - { - const int s = (0 - i7) & 0x1f; - const XmmLink& va = XmmGet(ra, rt); - c.psrldq(va.get(), s); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void SHLQBYI(u32 rt, u32 ra, s32 i7) - { - const int s = i7 & 0x1f; - const XmmLink& va = XmmGet(ra, rt); - c.pslldq(va.get(), s); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void NOP(u32 rt) - { - LOG_OPCODE(); - } - void CGT(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pcmpgtd(va.get(), vb->read()); - } - else - { - c.pcmpgtd(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void XOR(u32 rt, u32 ra, u32 rb) - { - // xor - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pxor(va.get(), vb->read()); - } - else - { - c.pxor(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CGTH(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pcmpgtw(va.get(), vb->read()); - } - else - { - c.pcmpgtw(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void EQV(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vb = XmmGet(rb, rt); - c.pxor(vb.get(), XmmConst(u128::from32p(0xffffffff))); - if (const XmmLink* va = XmmRead(ra)) - { - c.pxor(vb.get(), va->read()); - } - else - { - c.pxor(vb.get(), cpu_xmm(GPR[ra])); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void CGTB(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pcmpgtb(va.get(), vb->read()); - } - else - { - c.pcmpgtb(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void SUMB(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); - const XmmLink& vi = XmmAlloc(); - c.movdqa(vi.get(), XmmConst(u128::from8p(1))); - c.pmaddubsw(va.get(), vi.get()); - c.pmaddubsw(vb.get(), vi.get()); - c.phaddw(va.get(), vb.get()); - c.pshufb(va.get(), XmmConst(u128::fromV(_mm_set_epi8(15, 14, 7, 6, 13, 12, 5, 4, 11, 10, 3, 2, 9, 8, 1, 0)))); - XmmFinalize(va, rt); - XmmFinalize(vb); - XmmFinalize(vi); - LOG_OPCODE(); - } - //HGT uses signed values. HLGT uses unsigned values - void HGT(u32 rt, s32 ra, s32 rb) - { - c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); - c.cmp(*addr, cpu_dword(GPR[rb]._s32[3])); - c.setg(addr->r8()); - c.shl(*addr, 24); - c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.or_(*pos_var, *addr); - do_finalize = true; - LOG_OPCODE(); - } - void CLZ(u32 rt, u32 ra) - { - XmmInvalidate(rt); - c.mov(*qw0, 32 + 31); - for (u32 i = 0; i < 4; i++) - { - c.bsr(*addr, cpu_dword(GPR[ra]._u32[i])); - c.cmovz(*addr, qw0->r32()); - c.xor_(*addr, 31); - c.mov(cpu_dword(GPR[rt]._u32[i]), *addr); - } - LOG_OPCODE(); - } - void XSWD(u32 rt, u32 ra) - { - c.movsxd(*qw0, cpu_dword(GPR[ra]._s32[0])); - c.movsxd(*qw1, cpu_dword(GPR[ra]._s32[2])); - c.mov(cpu_qword(GPR[rt]._s64[0]), *qw0); - c.mov(cpu_qword(GPR[rt]._s64[1]), *qw1); - XmmInvalidate(rt); - LOG_OPCODE(); - } - void XSHW(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - c.pslld(va.get(), 16); - c.psrad(va.get(), 16); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CNTB(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& v1 = XmmCopy(va); - const XmmLink& vm = XmmAlloc(); - c.psrlq(v1.get(), 4); - c.movdqa(vm.get(), XmmConst(u128::from8p(0xf))); - c.pand(va.get(), vm.get()); - c.pand(v1.get(), vm.get()); - c.movdqa(vm.get(), XmmConst(u128::fromV(_mm_set_epi8(4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0)))); - c.pshufb(vm.get(), va.get()); - c.movdqa(va.get(), XmmConst(u128::fromV(_mm_set_epi8(4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0)))); - c.pshufb(va.get(), v1.get()); - c.paddb(va.get(), vm.get()); - XmmFinalize(va, rt); - XmmFinalize(v1); - XmmFinalize(vm); - LOG_OPCODE(); - } - void XSBH(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - c.psllw(va.get(), 8); - c.psraw(va.get(), 8); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CLGT(u32 rt, u32 ra, u32 rb) - { - // compare if-greater-than - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vi = XmmAlloc(); - c.movdqa(vi.get(), XmmConst(u128::from32p(0x80000000))); - c.pxor(va.get(), vi.get()); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pxor(vi.get(), vb->read()); - } - else - { - c.pxor(vi.get(), cpu_xmm(GPR[rb])); - } - c.pcmpgtd(va.get(), vi.get()); - XmmFinalize(va, rt); - XmmFinalize(vi); - LOG_OPCODE(); - } - void ANDC(u32 rt, u32 ra, u32 rb) - { - // and not - const XmmLink& vb = XmmGet(rb, rt); - if (const XmmLink* va = XmmRead(ra)) - { - c.pandn(vb.get(), va->read()); - } - else - { - c.pandn(vb.get(), cpu_xmm(GPR[ra])); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void FCGT(u32 rt, u32 ra, u32 rb) - { - // reverted less-than - const XmmLink& vb = XmmGet(rb, rt); - if (const XmmLink* va = XmmRead(ra)) - { - c.cmpps(vb.get(), va->read(), 1); - } - else - { - c.cmpps(vb.get(), cpu_xmm(GPR[ra]), 1); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void DFCGT(u32 rt, u32 ra, u32 rb) - { - UNIMPLEMENTED(); - } - void FA(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.addps(va.get(), vb->read()); - } - else - { - c.addps(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void FS(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.subps(va.get(), vb->read()); - } - else - { - c.subps(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void FM(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.mulps(va.get(), vb->read()); - } - else - { - c.mulps(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CLGTH(u32 rt, u32 ra, u32 rb) - { - // compare if-greater-than - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vi = XmmAlloc(); - c.movdqa(vi.get(), XmmConst(u128::from16p(0x8000))); - c.pxor(va.get(), vi.get()); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pxor(vi.get(), vb->read()); - } - else - { - c.pxor(vi.get(), cpu_xmm(GPR[rb])); - } - c.pcmpgtw(va.get(), vi.get()); - XmmFinalize(va, rt); - XmmFinalize(vi); - LOG_OPCODE(); - } - void ORC(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vb = XmmGet(rb, rt); - c.pxor(vb.get(), XmmConst(u128::from32p(0xffffffff))); - if (const XmmLink* va = XmmRead(ra)) - { - c.por(vb.get(), va->read()); - } - else - { - c.por(vb.get(), cpu_xmm(GPR[ra])); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void FCMGT(u32 rt, u32 ra, u32 rb) - { - // reverted less-than - const XmmLink& vb = XmmGet(rb, rt); - const XmmLink& vi = XmmAlloc(); - c.movaps(vi.get(), XmmConst(u128::from32p(0x7fffffff))); - c.andps(vb.get(), vi.get()); // abs - if (const XmmLink* va = XmmRead(ra)) - { - c.andps(vi.get(), va->read()); - } - else - { - c.andps(vi.get(), cpu_xmm(GPR[ra])); - } - c.cmpps(vb.get(), vi.get(), 1); - XmmFinalize(vb, rt); - XmmFinalize(vi); - LOG_OPCODE(); - } - void DFCMGT(u32 rt, u32 ra, u32 rb) - { - UNIMPLEMENTED(); - } - void DFA(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.addpd(va.get(), vb->read()); - } - else - { - c.addpd(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void DFS(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.subpd(va.get(), vb->read()); - } - else - { - c.subpd(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void DFM(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.mulpd(va.get(), vb->read()); - } - else - { - c.mulpd(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CLGTB(u32 rt, u32 ra, u32 rb) - { - // compare if-greater-than - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vi = XmmAlloc(); - c.movdqa(vi.get(), XmmConst(u128::from8p(0x80))); - c.pxor(va.get(), vi.get()); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pxor(vi.get(), vb->read()); - } - else - { - c.pxor(vi.get(), cpu_xmm(GPR[rb])); - } - c.pcmpgtb(va.get(), vi.get()); - XmmFinalize(va, rt); - XmmFinalize(vi); - LOG_OPCODE(); - } - void HLGT(u32 rt, u32 ra, u32 rb) - { - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.cmp(*addr, cpu_dword(GPR[rb]._u32[3])); - c.seta(addr->r8()); - c.shl(*addr, 24); - c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.or_(*pos_var, *addr); - do_finalize = true; - LOG_OPCODE(); - } - void DFMA(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vr = XmmGet(rt, rt); - const XmmLink& va = XmmGet(ra); - c.mulpd(va.get(), cpu_xmm(GPR[rb])); - c.addpd(vr.get(), va.get()); - XmmFinalize(vr, rt); - XmmFinalize(va); - LOG_OPCODE(); - } - void DFMS(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vt = (ra == rt) ? XmmCopy(va) : XmmGet(rt); - c.mulpd(va.get(), cpu_xmm(GPR[rb])); - c.subpd(va.get(), vt.get()); - XmmFinalize(va, rt); - XmmFinalize(vt); - LOG_OPCODE(); - } - void DFNMS(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vr = XmmGet(rt, rt); - const XmmLink& va = XmmGet(ra); - c.mulpd(va.get(), cpu_xmm(GPR[rb])); - c.subpd(vr.get(), va.get()); - XmmFinalize(vr, rt); - XmmFinalize(va); - LOG_OPCODE(); - } - void DFNMA(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vt = (ra == rt) ? XmmCopy(va) : XmmGet(rt); - c.mulpd(va.get(), cpu_xmm(GPR[rb])); - c.addpd(vt.get(), va.get()); - c.xorpd(va.get(), va.get()); - c.subpd(va.get(), vt.get()); - XmmFinalize(va, rt); - XmmFinalize(vt); - LOG_OPCODE(); - } - void CEQ(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pcmpeqd(va.get(), vb->read()); - } - else - { - c.pcmpeqd(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void MPYHHU(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); - const XmmLink& va2 = XmmCopy(va); - c.pmulhuw(va.get(), vb.get()); - c.pmullw(va2.get(), vb.get()); - c.pand(va.get(), XmmConst(u128::from32p(0xffff0000))); - c.psrld(va2.get(), 16); - c.por(va.get(), va2.get()); - XmmFinalize(va, rt); - XmmFinalize(vb); - XmmFinalize(va2); - LOG_OPCODE(); - } - void ADDX(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vt = XmmGet(rt); - c.pand(vt.get(), XmmConst(u128::from32p(1))); - c.paddd(vt.get(), cpu_xmm(GPR[ra])); - c.paddd(vt.get(), cpu_xmm(GPR[rb])); - XmmFinalize(vt, rt); - LOG_OPCODE(); - } - void SFX(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vt = XmmGet(rt); - const XmmLink& vb = XmmGet(rb, rt); - c.pandn(vt.get(), XmmConst(u128::from32p(1))); - c.psubd(vb.get(), cpu_xmm(GPR[ra])); - c.psubd(vb.get(), vt.get()); - XmmFinalize(vb, rt); - XmmFinalize(vt); - LOG_OPCODE(); - } - void CGX(u32 rt, u32 ra, u32 rb) //nf - { - WRAPPER_BEGIN(rt, ra, rb, zz); - for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = ((u64)CPU.GPR[ra]._u32[w] + (u64)CPU.GPR[rb]._u32[w] + (u64)(CPU.GPR[rt]._u32[w] & 1)) >> 32; - WRAPPER_END(rt, ra, rb, 0); - } - void BGX(u32 rt, u32 ra, u32 rb) //nf - { - WRAPPER_BEGIN(rt, ra, rb, zz); - s64 nResult; - - for (int w = 0; w < 4; w++) - { - nResult = (u64)CPU.GPR[rb]._u32[w] - (u64)CPU.GPR[ra]._u32[w] - (u64)(1 - (CPU.GPR[rt]._u32[w] & 1)); - CPU.GPR[rt]._u32[w] = nResult < 0 ? 0 : 1; - } - WRAPPER_END(rt, ra, rb, 0); - } - void MPYHHA(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vt = XmmGet(rt, rt); - const XmmLink& va = XmmGet(ra); - const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); - c.psrld(va.get(), 16); - c.psrld(vb.get(), 16); - c.pmaddwd(va.get(), vb.get()); - c.paddd(vt.get(), va.get()); - XmmFinalize(vt, rt); - XmmFinalize(va); - XmmFinalize(vb); - LOG_OPCODE(); - } - void MPYHHAU(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vt = XmmGet(rt, rt); - const XmmLink& va = XmmGet(ra); - const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); - const XmmLink& va2 = XmmCopy(va); - c.pmulhuw(va.get(), vb.get()); - c.pmullw(va2.get(), vb.get()); - c.pand(va.get(), XmmConst(u128::from32p(0xffff0000))); - c.psrld(va2.get(), 16); - c.paddd(vt.get(), va.get()); - c.paddd(vt.get(), va2.get()); - XmmFinalize(vt, rt); - XmmFinalize(va); - XmmFinalize(vb); - XmmFinalize(va2); - LOG_OPCODE(); - } - void FSCRRD(u32 rt) - { - // zero (hack) - const XmmLink& v0 = XmmAlloc(rt); - c.pxor(v0.get(), v0.get()); - XmmFinalize(v0, rt); - LOG_OPCODE(); - } - void FESD(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - c.shufps(va.get(), va.get(), 0x8d); // _f[0] = _f[1]; _f[1] = _f[3]; - c.cvtps2pd(va.get(), va.get()); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void FRDS(u32 rt, u32 ra) - { - const XmmLink& va = XmmGet(ra, rt); - c.cvtpd2ps(va.get(), va.get()); - c.shufps(va.get(), va.get(), 0x72); // _f[1] = _f[0]; _f[3] = _f[1]; _f[0] = _f[2] = 0; - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void FSCRWR(u32 rt, u32 ra) - { - // nop (not implemented) - LOG_OPCODE(); - } - void DFTSV(u32 rt, u32 ra, s32 i7) - { - UNIMPLEMENTED(); - } - void FCEQ(u32 rt, u32 ra, u32 rb) - { - // compare equal - const XmmLink& vb = XmmGet(rb, rt); - if (const XmmLink* va = XmmRead(ra)) - { - c.cmpps(vb.get(), va->read(), 0); - } - else - { - c.cmpps(vb.get(), cpu_xmm(GPR[ra]), 0); - } - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void DFCEQ(u32 rt, u32 ra, u32 rb) - { - UNIMPLEMENTED(); - } - void MPY(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); - const XmmLink& vi = XmmAlloc(); - c.movdqa(vi.get(), XmmConst(u128::from32p(0xffff))); - c.pand(va.get(), vi.get()); - c.pand(vb.get(), vi.get()); - c.pmaddwd(va.get(), vb.get()); - XmmFinalize(va, rt); - XmmFinalize(vb); - XmmFinalize(vi); - LOG_OPCODE(); - } - void MPYH(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); - c.psrld(va.get(), 16); - c.pmullw(va.get(), vb.get()); - c.pslld(va.get(), 16); - XmmFinalize(va, rt); - XmmFinalize(vb); - LOG_OPCODE(); - } - void MPYHH(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); - c.psrld(va.get(), 16); - c.psrld(vb.get(), 16); - c.pmaddwd(va.get(), vb.get()); - XmmFinalize(va, rt); - XmmFinalize(vb); - LOG_OPCODE(); - } - void MPYS(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); - c.pmulhw(va.get(), vb.get()); - c.pslld(va.get(), 16); - c.psrad(va.get(), 16); - XmmFinalize(va, rt); - XmmFinalize(vb); - LOG_OPCODE(); - } - void CEQH(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pcmpeqw(va.get(), vb->read()); - } - else - { - c.pcmpeqw(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void FCMEQ(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vb = XmmGet(rb, rt); - const XmmLink& vi = XmmAlloc(); - c.movaps(vi.get(), XmmConst(u128::from32p(0x7fffffff))); - c.andps(vb.get(), vi.get()); // abs - if (const XmmLink* va = XmmRead(ra)) - { - c.andps(vi.get(), va->read()); - } - else - { - c.andps(vi.get(), cpu_xmm(GPR[ra])); - } - c.cmpps(vb.get(), vi.get(), 0); // == - XmmFinalize(vb, rt); - XmmFinalize(vi); - LOG_OPCODE(); - } - void DFCMEQ(u32 rt, u32 ra, u32 rb) - { - UNIMPLEMENTED(); - } - void MPYU(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); - const XmmLink& va2 = XmmCopy(va); - c.pmulhuw(va.get(), vb.get()); - c.pmullw(va2.get(), vb.get()); - c.pslld(va.get(), 16); - c.pand(va2.get(), XmmConst(u128::from32p(0xffff))); - c.por(va.get(), va2.get()); - XmmFinalize(va, rt); - XmmFinalize(vb); - XmmFinalize(va2); - LOG_OPCODE(); - } - void CEQB(u32 rt, u32 ra, u32 rb) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.pcmpeqb(va.get(), vb->read()); - } - else - { - c.pcmpeqb(va.get(), cpu_xmm(GPR[rb])); - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void FI(u32 rt, u32 ra, u32 rb) - { - const XmmLink& vb = XmmGet(rb); - XmmFinalize(vb, rt); - LOG_OPCODE(); - } - void HEQ(u32 rt, u32 ra, u32 rb) - { - c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); - c.cmp(*addr, cpu_dword(GPR[rb]._s32[3])); - c.sete(addr->r8()); - c.shl(*addr, 24); - c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.or_(*pos_var, *addr); - do_finalize = true; - LOG_OPCODE(); - } + virtual void STOP(u32 code) override; + virtual void LNOP() override; + virtual void SYNC(u32 Cbit) override; + virtual void DSYNC() override; + virtual void MFSPR(u32 rt, u32 sa) override; + virtual void RDCH(u32 rt, u32 ra) override; + virtual void RCHCNT(u32 rt, u32 ra) override; + virtual void SF(u32 rt, u32 ra, u32 rb) override; + virtual void OR(u32 rt, u32 ra, u32 rb) override; + virtual void BG(u32 rt, u32 ra, u32 rb) override; + virtual void SFH(u32 rt, u32 ra, u32 rb) override; + virtual void NOR(u32 rt, u32 ra, u32 rb) override; + virtual void ABSDB(u32 rt, u32 ra, u32 rb) override; + virtual void ROT(u32 rt, u32 ra, u32 rb) override; + virtual void ROTM(u32 rt, u32 ra, u32 rb) override; + virtual void ROTMA(u32 rt, u32 ra, u32 rb) override; + virtual void SHL(u32 rt, u32 ra, u32 rb) override; + virtual void ROTH(u32 rt, u32 ra, u32 rb) override; + virtual void ROTHM(u32 rt, u32 ra, u32 rb) override; + virtual void ROTMAH(u32 rt, u32 ra, u32 rb) override; + virtual void SHLH(u32 rt, u32 ra, u32 rb) override; + virtual void ROTI(u32 rt, u32 ra, s32 i7) override; + virtual void ROTMI(u32 rt, u32 ra, s32 i7) override; + virtual void ROTMAI(u32 rt, u32 ra, s32 i7) override; + virtual void SHLI(u32 rt, u32 ra, s32 i7) override; + virtual void ROTHI(u32 rt, u32 ra, s32 i7) override; + virtual void ROTHMI(u32 rt, u32 ra, s32 i7) override; + virtual void ROTMAHI(u32 rt, u32 ra, s32 i7) override; + virtual void SHLHI(u32 rt, u32 ra, s32 i7) override; + virtual void A(u32 rt, u32 ra, u32 rb) override; + virtual void AND(u32 rt, u32 ra, u32 rb) override; + virtual void CG(u32 rt, u32 ra, u32 rb) override; + virtual void AH(u32 rt, u32 ra, u32 rb) override; + virtual void NAND(u32 rt, u32 ra, u32 rb) override; + virtual void AVGB(u32 rt, u32 ra, u32 rb) override; + virtual void MTSPR(u32 rt, u32 sa) override; + virtual void WRCH(u32 ra, u32 rt) override; + virtual void BIZ(u32 intr, u32 rt, u32 ra) override; + virtual void BINZ(u32 intr, u32 rt, u32 ra) override; + virtual void BIHZ(u32 intr, u32 rt, u32 ra) override; + virtual void BIHNZ(u32 intr, u32 rt, u32 ra) override; + virtual void STOPD(u32 rc, u32 ra, u32 rb) override; + virtual void STQX(u32 rt, u32 ra, u32 rb) override; + virtual void BI(u32 intr, u32 ra) override; + virtual void BISL(u32 intr, u32 rt, u32 ra) override; + virtual void IRET(u32 ra) override; + virtual void BISLED(u32 intr, u32 rt, u32 ra) override; + virtual void HBR(u32 p, u32 ro, u32 ra) override; + virtual void GB(u32 rt, u32 ra) override; + virtual void GBH(u32 rt, u32 ra) override; + virtual void GBB(u32 rt, u32 ra) override; + virtual void FSM(u32 rt, u32 ra) override; + virtual void FSMH(u32 rt, u32 ra) override; + virtual void FSMB(u32 rt, u32 ra) override; + virtual void FREST(u32 rt, u32 ra) override; + virtual void FRSQEST(u32 rt, u32 ra) override; + virtual void LQX(u32 rt, u32 ra, u32 rb) override; + virtual void ROTQBYBI(u32 rt, u32 ra, u32 rb) override; + virtual void ROTQMBYBI(u32 rt, u32 ra, u32 rb) override; + virtual void SHLQBYBI(u32 rt, u32 ra, u32 rb) override; + virtual void CBX(u32 rt, u32 ra, u32 rb) override; + virtual void CHX(u32 rt, u32 ra, u32 rb) override; + virtual void CWX(u32 rt, u32 ra, u32 rb) override; + virtual void CDX(u32 rt, u32 ra, u32 rb) override; + virtual void ROTQBI(u32 rt, u32 ra, u32 rb) override; + virtual void ROTQMBI(u32 rt, u32 ra, u32 rb) override; + virtual void SHLQBI(u32 rt, u32 ra, u32 rb) override; + virtual void ROTQBY(u32 rt, u32 ra, u32 rb) override; + virtual void ROTQMBY(u32 rt, u32 ra, u32 rb) override; + virtual void SHLQBY(u32 rt, u32 ra, u32 rb) override; + virtual void ORX(u32 rt, u32 ra) override; + virtual void CBD(u32 rt, u32 ra, s32 i7) override; + virtual void CHD(u32 rt, u32 ra, s32 i7) override; + virtual void CWD(u32 rt, u32 ra, s32 i7) override; + virtual void CDD(u32 rt, u32 ra, s32 i7) override; + virtual void ROTQBII(u32 rt, u32 ra, s32 i7) override; + virtual void ROTQMBII(u32 rt, u32 ra, s32 i7) override; + virtual void SHLQBII(u32 rt, u32 ra, s32 i7) override; + virtual void ROTQBYI(u32 rt, u32 ra, s32 i7) override; + virtual void ROTQMBYI(u32 rt, u32 ra, s32 i7) override; + virtual void SHLQBYI(u32 rt, u32 ra, s32 i7) override; + virtual void NOP(u32 rt) override; + virtual void CGT(u32 rt, u32 ra, u32 rb) override; + virtual void XOR(u32 rt, u32 ra, u32 rb) override; + virtual void CGTH(u32 rt, u32 ra, u32 rb) override; + virtual void EQV(u32 rt, u32 ra, u32 rb) override; + virtual void CGTB(u32 rt, u32 ra, u32 rb) override; + virtual void SUMB(u32 rt, u32 ra, u32 rb) override; + virtual void HGT(u32 rt, s32 ra, s32 rb) override; + virtual void CLZ(u32 rt, u32 ra) override; + virtual void XSWD(u32 rt, u32 ra) override; + virtual void XSHW(u32 rt, u32 ra) override; + virtual void CNTB(u32 rt, u32 ra) override; + virtual void XSBH(u32 rt, u32 ra) override; + virtual void CLGT(u32 rt, u32 ra, u32 rb) override; + virtual void ANDC(u32 rt, u32 ra, u32 rb) override; + virtual void FCGT(u32 rt, u32 ra, u32 rb) override; + virtual void DFCGT(u32 rt, u32 ra, u32 rb) override; + virtual void FA(u32 rt, u32 ra, u32 rb) override; + virtual void FS(u32 rt, u32 ra, u32 rb) override; + virtual void FM(u32 rt, u32 ra, u32 rb) override; + virtual void CLGTH(u32 rt, u32 ra, u32 rb) override; + virtual void ORC(u32 rt, u32 ra, u32 rb) override; + virtual void FCMGT(u32 rt, u32 ra, u32 rb) override; + virtual void DFCMGT(u32 rt, u32 ra, u32 rb) override; + virtual void DFA(u32 rt, u32 ra, u32 rb) override; + virtual void DFS(u32 rt, u32 ra, u32 rb) override; + virtual void DFM(u32 rt, u32 ra, u32 rb) override; + virtual void CLGTB(u32 rt, u32 ra, u32 rb) override; + virtual void HLGT(u32 rt, u32 ra, u32 rb) override; + virtual void DFMA(u32 rt, u32 ra, u32 rb) override; + virtual void DFMS(u32 rt, u32 ra, u32 rb) override; + virtual void DFNMS(u32 rt, u32 ra, u32 rb) override; + virtual void DFNMA(u32 rt, u32 ra, u32 rb) override; + virtual void CEQ(u32 rt, u32 ra, u32 rb) override; + virtual void MPYHHU(u32 rt, u32 ra, u32 rb) override; + virtual void ADDX(u32 rt, u32 ra, u32 rb) override; + virtual void SFX(u32 rt, u32 ra, u32 rb) override; + virtual void CGX(u32 rt, u32 ra, u32 rb) override; + virtual void BGX(u32 rt, u32 ra, u32 rb) override; + virtual void MPYHHA(u32 rt, u32 ra, u32 rb) override; + virtual void MPYHHAU(u32 rt, u32 ra, u32 rb) override; + virtual void FSCRRD(u32 rt) override; + virtual void FESD(u32 rt, u32 ra) override; + virtual void FRDS(u32 rt, u32 ra) override; + virtual void FSCRWR(u32 rt, u32 ra) override; + virtual void DFTSV(u32 rt, u32 ra, s32 i7) override; + virtual void FCEQ(u32 rt, u32 ra, u32 rb) override; + virtual void DFCEQ(u32 rt, u32 ra, u32 rb) override; + virtual void MPY(u32 rt, u32 ra, u32 rb) override; + virtual void MPYH(u32 rt, u32 ra, u32 rb) override; + virtual void MPYHH(u32 rt, u32 ra, u32 rb) override; + virtual void MPYS(u32 rt, u32 ra, u32 rb) override; + virtual void CEQH(u32 rt, u32 ra, u32 rb) override; + virtual void FCMEQ(u32 rt, u32 ra, u32 rb) override; + virtual void DFCMEQ(u32 rt, u32 ra, u32 rb) override; + virtual void MPYU(u32 rt, u32 ra, u32 rb) override; + virtual void CEQB(u32 rt, u32 ra, u32 rb) override; + virtual void FI(u32 rt, u32 ra, u32 rb) override; + virtual void HEQ(u32 rt, u32 ra, u32 rb) override; //0 - 9 - void CFLTS(u32 rt, u32 ra, s32 i8) - { - const XmmLink& va = XmmGet(ra, rt); - if (i8 != 173) - { - c.mulps(va.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(static_cast(173 - (i8 & 0xff))))))); // scale - } - const XmmLink& vi = XmmAlloc(); - c.movaps(vi.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(31))))); - c.cmpps(vi.get(), va.get(), 2); - c.cvttps2dq(va.get(), va.get()); // convert to ints with truncation - c.pxor(va.get(), vi.get()); // fix result saturation (0x80000000 -> 0x7fffffff) - XmmFinalize(va, rt); - XmmFinalize(vi); - LOG_OPCODE(); - } - void CFLTU(u32 rt, u32 ra, s32 i8) - { - const XmmLink& va = XmmGet(ra, rt); - if (i8 != 173) - { - c.mulps(va.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(static_cast(173 - (i8 & 0xff))))))); // scale - } - c.maxps(va.get(), XmmConst({})); // saturate - const XmmLink& vs = XmmCopy(va); // copy scaled value - const XmmLink& vs2 = XmmCopy(va); - const XmmLink& vs3 = XmmAlloc(); - c.movaps(vs3.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(31))))); - c.subps(vs2.get(), vs3.get()); - c.cmpps(vs3.get(), vs.get(), 2); - c.andps(vs2.get(), vs3.get()); - c.cvttps2dq(va.get(), va.get()); - c.cmpps(vs.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(32)))), 5); - c.cvttps2dq(vs2.get(), vs2.get()); - c.por(va.get(), vs.get()); - c.por(va.get(), vs2.get()); - XmmFinalize(va, rt); - XmmFinalize(vs); - XmmFinalize(vs2); - XmmFinalize(vs3); - LOG_OPCODE(); - } - void CSFLT(u32 rt, u32 ra, s32 i8) - { - const XmmLink& va = XmmGet(ra, rt); - c.cvtdq2ps(va.get(), va.get()); // convert to floats - if (i8 != 155) - { - c.mulps(va.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(static_cast((i8 & 0xff) - 155)))))); // scale - } - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CUFLT(u32 rt, u32 ra, s32 i8) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& v1 = XmmCopy(va); - c.pand(va.get(), XmmConst(u128::from32p(0x7fffffff))); - c.cvtdq2ps(va.get(), va.get()); // convert to floats - c.psrad(v1.get(), 31); // generate mask from sign bit - c.andps(v1.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(31))))); // generate correction component - c.addps(va.get(), v1.get()); // add correction component - if (i8 != 155) - { - c.mulps(va.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(static_cast((i8 & 0xff) - 155)))))); // scale - } - XmmFinalize(va, rt); - XmmFinalize(v1); - LOG_OPCODE(); - } + virtual void CFLTS(u32 rt, u32 ra, s32 i8) override; + virtual void CFLTU(u32 rt, u32 ra, s32 i8) override; + virtual void CSFLT(u32 rt, u32 ra, s32 i8) override; + virtual void CUFLT(u32 rt, u32 ra, s32 i8) override; //0 - 8 - void BRZ(u32 rt, s32 i16) - { - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*addr, (CPU.PC >> 2) + 1); - c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); - c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); - c.cmovne(*pos_var, *addr); - LOG_OPCODE(); - } - void STQA(u32 rt, s32 i16) - { - const u32 lsa = (i16 << 2) & 0x3fff0; - - /*const XmmLink& vt = XmmGet(rt); - c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - c.movdqa(oword_ptr(*ls_var, lsa), vt.get()); - XmmFinalize(vt);*/ - - c.mov(*qw0, cpu_qword(GPR[rt]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[rt]._u64[1])); - c.bswap(*qw0); - c.bswap(*qw1); - c.mov(qword_ptr(*ls_var, lsa), *qw1); - c.mov(qword_ptr(*ls_var, lsa + 8), *qw0); - - LOG_OPCODE(); - } - void BRNZ(u32 rt, s32 i16) - { - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*addr, (CPU.PC >> 2) + 1); - c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); - c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); - c.cmove(*pos_var, *addr); - LOG_OPCODE(); - } - void BRHZ(u32 rt, s32 i16) - { - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*addr, (CPU.PC >> 2) + 1); - c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); - c.cmp(cpu_word(GPR[rt]._u16[6]), 0); - c.cmovnz(*pos_var, *addr); - LOG_OPCODE(); - } - void BRHNZ(u32 rt, s32 i16) - { - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*addr, (CPU.PC >> 2) + 1); - c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); - c.cmp(cpu_word(GPR[rt]._u16[6]), 0); - c.cmovz(*pos_var, *addr); - LOG_OPCODE(); - } - void STQR(u32 rt, s32 i16) - { - const u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0; - - /*const XmmLink& vt = XmmGet(rt); - c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - c.movdqa(oword_ptr(*ls_var, lsa), vt.get()); - XmmFinalize(vt);*/ - - c.mov(*qw0, cpu_qword(GPR[rt]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[rt]._u64[1])); - c.bswap(*qw0); - c.bswap(*qw1); - c.mov(qword_ptr(*ls_var, lsa), *qw1); - c.mov(qword_ptr(*ls_var, lsa + 8), *qw0); - - LOG_OPCODE(); - } - void BRA(s32 i16) - { - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*pos_var, branchTarget(0, i16) >> 2); - LOG_OPCODE(); - } - void LQA(u32 rt, s32 i16) - { - XmmInvalidate(rt); - - const u32 lsa = (i16 << 2) & 0x3fff0; - - /*const XmmLink& vt = XmmAlloc(rt); - c.movdqa(vt.get(), oword_ptr(*ls_var, lsa)); - c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - XmmFinalize(vt, rt);*/ - - c.mov(*qw0, qword_ptr(*ls_var, lsa)); - c.mov(*qw1, qword_ptr(*ls_var, lsa + 8)); - c.bswap(*qw0); - c.bswap(*qw1); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0); - - LOG_OPCODE(); - } - void BRASL(u32 rt, s32 i16) - { - XmmInvalidate(rt); - - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.xor_(*addr, *addr); // zero - c.mov(cpu_dword(GPR[rt]._u32[0]), *addr); - c.mov(cpu_dword(GPR[rt]._u32[1]), *addr); - c.mov(cpu_dword(GPR[rt]._u32[2]), *addr); - c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4); - c.mov(*pos_var, branchTarget(0, i16) >> 2); - LOG_OPCODE(); - } - void BR(s32 i16) - { - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); - LOG_OPCODE(); - } - void FSMBI(u32 rt, s32 i16) - { - if (i16 == 0) - { - // zero - const XmmLink& v0 = XmmAlloc(rt); - c.pxor(v0.get(), v0.get()); - XmmFinalize(v0, rt); - } - else - { - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), g_imm_xmm(fsmb[i16 & 0xffff])); - XmmFinalize(vr, rt); - } - LOG_OPCODE(); - } - void BRSL(u32 rt, s32 i16) - { - XmmInvalidate(rt); - - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - - c.xor_(*addr, *addr); // zero - c.mov(cpu_dword(GPR[rt]._u32[0]), *addr); - c.mov(cpu_dword(GPR[rt]._u32[1]), *addr); - c.mov(cpu_dword(GPR[rt]._u32[2]), *addr); - c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4); - c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); - LOG_OPCODE(); - } - void LQR(u32 rt, s32 i16) - { - XmmInvalidate(rt); - - const u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0; - - /*const XmmLink& vt = XmmAlloc(rt); - c.movdqa(vt.get(), oword_ptr(*ls_var, lsa)); - c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - XmmFinalize(vt, rt);*/ - - c.mov(*qw0, qword_ptr(*ls_var, lsa)); - c.mov(*qw1, qword_ptr(*ls_var, lsa + 8)); - c.bswap(*qw0); - c.bswap(*qw1); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0); - - LOG_OPCODE(); - } - void IL(u32 rt, s32 i16) - { - const XmmLink& vr = XmmAlloc(rt); - if (i16 == 0) - { - c.pxor(vr.get(), vr.get()); - } - else if (i16 == -1) - { - c.pcmpeqd(vr.get(), vr.get()); - } - else - { - c.movdqa(vr.get(), XmmConst(u128::from32p(i16))); - } - XmmFinalize(vr, rt); - LOG_OPCODE(); - } - void ILHU(u32 rt, s32 i16) - { - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::from32p(i16 << 16))); - XmmFinalize(vr, rt); - LOG_OPCODE(); - } - void ILH(u32 rt, s32 i16) - { - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::from32p(i16))); - XmmFinalize(vr, rt); - LOG_OPCODE(); - } - void IOHL(u32 rt, s32 i16) - { - const XmmLink& vt = XmmGet(rt, rt); - c.por(vt.get(), XmmConst(u128::from32p(i16 & 0xffff))); - XmmFinalize(vt, rt); - LOG_OPCODE(); - } - + virtual void BRZ(u32 rt, s32 i16) override; + virtual void STQA(u32 rt, s32 i16) override; + virtual void BRNZ(u32 rt, s32 i16) override; + virtual void BRHZ(u32 rt, s32 i16) override; + virtual void BRHNZ(u32 rt, s32 i16) override; + virtual void STQR(u32 rt, s32 i16) override; + virtual void BRA(s32 i16) override; + virtual void LQA(u32 rt, s32 i16) override; + virtual void BRASL(u32 rt, s32 i16) override; + virtual void BR(s32 i16) override; + virtual void FSMBI(u32 rt, s32 i16) override; + virtual void BRSL(u32 rt, s32 i16) override; + virtual void LQR(u32 rt, s32 i16) override; + virtual void IL(u32 rt, s32 i16) override; + virtual void ILHU(u32 rt, s32 i16) override; + virtual void ILH(u32 rt, s32 i16) override; + virtual void IOHL(u32 rt, s32 i16) override; //0 - 7 - void ORI(u32 rt, u32 ra, s32 i10) - { - if (i10 == -1) - { - // fill with 1 - const XmmLink& v1 = XmmAlloc(rt); - c.pcmpeqd(v1.get(), v1.get()); - XmmFinalize(v1, rt); - } - else if (i10 == 0) - { - if (rt != ra) - { - // mov - const XmmLink& va = XmmGet(ra, rt); - XmmFinalize(va, rt); - } - // else nop - } - else - { - const XmmLink& va = XmmGet(ra, rt); - c.por(va.get(), XmmConst(u128::from32p(i10))); - XmmFinalize(va, rt); - } - LOG_OPCODE(); - } - void ORHI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra, rt); - c.por(va.get(), XmmConst(u128::from16p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ORBI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra, rt); - c.por(va.get(), XmmConst(u128::from8p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void SFI(u32 rt, u32 ra, s32 i10) - { - if (i10 == 0) - { - // zero - const XmmLink& v0 = XmmAlloc(rt); - c.pxor(v0.get(), v0.get()); - c.psubd(v0.get(), cpu_xmm(GPR[ra])); - XmmFinalize(v0, rt); - } - else if (i10 == -1) - { - // fill with 1 - const XmmLink& v1 = XmmAlloc(rt); - c.pcmpeqd(v1.get(), v1.get()); - c.psubd(v1.get(), cpu_xmm(GPR[ra])); - XmmFinalize(v1, rt); - } - else - { - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::from32p(i10))); - c.psubd(vr.get(), cpu_xmm(GPR[ra])); - XmmFinalize(vr, rt); - } - LOG_OPCODE(); - } - void SFHI(u32 rt, u32 ra, s32 i10) - { - if (i10 == 0) - { - // zero - const XmmLink& v0 = XmmAlloc(rt); - c.pxor(v0.get(), v0.get()); - c.psubw(v0.get(), cpu_xmm(GPR[ra])); - XmmFinalize(v0, rt); - } - else if (i10 == -1) - { - // fill with 1 - const XmmLink& v1 = XmmAlloc(rt); - c.pcmpeqw(v1.get(), v1.get()); - c.psubw(v1.get(), cpu_xmm(GPR[ra])); - XmmFinalize(v1, rt); - } - else - { - const XmmLink& vr = XmmAlloc(rt); - c.movdqa(vr.get(), XmmConst(u128::from16p(i10))); - c.psubw(vr.get(), cpu_xmm(GPR[ra])); - XmmFinalize(vr, rt); - } - LOG_OPCODE(); - } - void ANDI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra, rt); - c.pand(va.get(), XmmConst(u128::from32p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ANDHI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra, rt); - c.pand(va.get(), XmmConst(u128::from16p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void ANDBI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra, rt); - c.pand(va.get(), XmmConst(u128::from8p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void AI(u32 rt, u32 ra, s32 i10) - { - // add - const XmmLink& va = XmmGet(ra, rt); - c.paddd(va.get(), XmmConst(u128::from32p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void AHI(u32 rt, u32 ra, s32 i10) - { - // add - const XmmLink& va = XmmGet(ra, rt); - c.paddw(va.get(), XmmConst(u128::from16p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void STQD(u32 rt, s32 i10, u32 ra) // i10 is shifted left by 4 while decoding - { - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - if (i10) c.add(*addr, i10); - c.and_(*addr, 0x3fff0); - - /*const XmmLink& vt = XmmGet(rt); - c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - c.movdqa(oword_ptr(*ls_var, *addr), vt.get()); - XmmFinalize(vt);*/ - - c.mov(*qw0, cpu_qword(GPR[rt]._u64[0])); - c.mov(*qw1, cpu_qword(GPR[rt]._u64[1])); - c.bswap(*qw0); - c.bswap(*qw1); - c.mov(qword_ptr(*ls_var, *addr, 0, 0), *qw1); - c.mov(qword_ptr(*ls_var, *addr, 0, 8), *qw0); - - LOG_OPCODE(); - } - void LQD(u32 rt, s32 i10, u32 ra) // i10 is shifted left by 4 while decoding - { - XmmInvalidate(rt); - - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - if (i10) c.add(*addr, i10); - c.and_(*addr, 0x3fff0); - - /*const XmmLink& vt = XmmAlloc(rt); - c.movdqa(vt.get(), oword_ptr(*ls_var, *addr)); - c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); - XmmFinalize(vt, rt);*/ - - c.mov(*qw0, qword_ptr(*ls_var, *addr, 0, 0)); - c.mov(*qw1, qword_ptr(*ls_var, *addr, 0, 8)); - c.bswap(*qw0); - c.bswap(*qw1); - c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1); - c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0); - - LOG_OPCODE(); - } - void XORI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pxor(va.get(), XmmConst(u128::from32p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void XORHI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pxor(va.get(), XmmConst(u128::from16p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void XORBI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pxor(va.get(), XmmConst(u128::from8p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CGTI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pcmpgtd(va.get(), XmmConst(u128::from32p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CGTHI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pcmpgtw(va.get(), XmmConst(u128::from16p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CGTBI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pcmpgtb(va.get(), XmmConst(u128::from8p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void HGTI(u32 rt, u32 ra, s32 i10) - { - c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); - c.cmp(*addr, i10); - c.setg(addr->r8()); - c.shl(*addr, 24); - c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.or_(*pos_var, *addr); - do_finalize = true; - LOG_OPCODE(); - } - void CLGTI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pxor(va.get(), XmmConst(u128::from32p(0x80000000))); - c.pcmpgtd(va.get(), XmmConst(u128::from32p((u32)i10 - 0x80000000))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CLGTHI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pxor(va.get(), XmmConst(u128::from16p(0x8000))); - c.pcmpgtw(va.get(), XmmConst(u128::from16p((u16)i10 - 0x8000))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CLGTBI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.psubb(va.get(), XmmConst(u128::from8p(0x80))); - c.pcmpgtb(va.get(), XmmConst(u128::from8p((s8)i10 - 0x80))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void HLGTI(u32 rt, u32 ra, s32 i10) - { - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.cmp(*addr, i10); - c.seta(addr->r8()); - c.shl(*addr, 24); - c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.or_(*pos_var, *addr); - do_finalize = true; - LOG_OPCODE(); - } - void MPYI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra, rt); - c.pmaddwd(va.get(), XmmConst(u128::from32p(i10 & 0xffff))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void MPYUI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vi = XmmAlloc(); - const XmmLink& va2 = XmmCopy(va); - c.movdqa(vi.get(), XmmConst(u128::from32p(i10 & 0xffff))); - c.pmulhuw(va.get(), vi.get()); - c.pmullw(va2.get(), vi.get()); - c.pslld(va.get(), 16); - c.por(va.get(), va2.get()); - XmmFinalize(va, rt); - XmmFinalize(vi); - XmmFinalize(va2); - LOG_OPCODE(); - } - void CEQI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pcmpeqd(va.get(), XmmConst(u128::from32p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CEQHI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pcmpeqw(va.get(), XmmConst(u128::from16p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void CEQBI(u32 rt, u32 ra, s32 i10) - { - const XmmLink& va = XmmGet(ra); - c.pcmpeqb(va.get(), XmmConst(u128::from8p(i10))); - XmmFinalize(va, rt); - LOG_OPCODE(); - } - void HEQI(u32 rt, u32 ra, s32 i10) - { - c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); - c.cmp(*addr, i10); - c.sete(addr->r8()); - c.shl(*addr, 24); - c.mov(*pos_var, (CPU.PC >> 2) + 1); - c.or_(*pos_var, *addr); - do_finalize = true; - LOG_OPCODE(); - } - + virtual void ORI(u32 rt, u32 ra, s32 i10) override; + virtual void ORHI(u32 rt, u32 ra, s32 i10) override; + virtual void ORBI(u32 rt, u32 ra, s32 i10) override; + virtual void SFI(u32 rt, u32 ra, s32 i10) override; + virtual void SFHI(u32 rt, u32 ra, s32 i10) override; + virtual void ANDI(u32 rt, u32 ra, s32 i10) override; + virtual void ANDHI(u32 rt, u32 ra, s32 i10) override; + virtual void ANDBI(u32 rt, u32 ra, s32 i10) override; + virtual void AI(u32 rt, u32 ra, s32 i10) override; + virtual void AHI(u32 rt, u32 ra, s32 i10) override; + virtual void STQD(u32 rt, s32 i10, u32 ra) override; + virtual void LQD(u32 rt, s32 i10, u32 ra) override; + virtual void XORI(u32 rt, u32 ra, s32 i10) override; + virtual void XORHI(u32 rt, u32 ra, s32 i10) override; + virtual void XORBI(u32 rt, u32 ra, s32 i10) override; + virtual void CGTI(u32 rt, u32 ra, s32 i10) override; + virtual void CGTHI(u32 rt, u32 ra, s32 i10) override; + virtual void CGTBI(u32 rt, u32 ra, s32 i10) override; + virtual void HGTI(u32 rt, u32 ra, s32 i10) override; + virtual void CLGTI(u32 rt, u32 ra, s32 i10) override; + virtual void CLGTHI(u32 rt, u32 ra, s32 i10) override; + virtual void CLGTBI(u32 rt, u32 ra, s32 i10) override; + virtual void HLGTI(u32 rt, u32 ra, s32 i10) override; + virtual void MPYI(u32 rt, u32 ra, s32 i10) override; + virtual void MPYUI(u32 rt, u32 ra, s32 i10) override; + virtual void CEQI(u32 rt, u32 ra, s32 i10) override; + virtual void CEQHI(u32 rt, u32 ra, s32 i10) override; + virtual void CEQBI(u32 rt, u32 ra, s32 i10) override; + virtual void HEQI(u32 rt, u32 ra, s32 i10) override; //0 - 6 - void HBRA(s32 ro, s32 i16) - { //i16 is shifted left by 2 while decoding - LOG_OPCODE(); - } - void HBRR(s32 ro, s32 i16) - { - LOG_OPCODE(); - } - void ILA(u32 rt, u32 i18) - { - const XmmLink& vr = XmmAlloc(rt); - if (i18 == 0) - { - c.pxor(vr.get(), vr.get()); - } - else - { - c.movdqa(vr.get(), XmmConst(u128::from32p(i18 & 0x3ffff))); - } - XmmFinalize(vr, rt); - LOG_OPCODE(); - } + virtual void HBRA(s32 ro, s32 i16) override; + virtual void HBRR(s32 ro, s32 i16) override; + virtual void ILA(u32 rt, u32 i18) override; //0 - 3 - void SELB(u32 rt, u32 ra, u32 rb, u32 rc) - { - const XmmLink& vb = XmmGet(rb); - const XmmLink& vc = XmmGet(rc); - c.pand(vb.get(), vc.get()); - c.pandn(vc.get(), cpu_xmm(GPR[ra])); - c.por(vb.get(), vc.get()); - XmmFinalize(vb, rt); - XmmFinalize(vc); - LOG_OPCODE(); - } - void SHUFB(u32 rt, u32 ra, u32 rb, u32 rc) - { - const XmmLink& v0 = XmmGet(rc); // v0 = mask - const XmmLink& v1 = XmmAlloc(); - const XmmLink& v2 = XmmCopy(v0); // v2 = mask - const XmmLink& v3 = XmmAlloc(); - const XmmLink& v4 = XmmAlloc(); - const XmmLink& vFF = XmmAlloc(rt); - // generate specific values: - c.movdqa(v1.get(), XmmConst(u128::from8p(0xe0))); // v1 = 11100000 - c.movdqa(v3.get(), XmmConst(u128::from8p(0x80))); // v3 = 10000000 - c.pand(v2.get(), v1.get()); // filter mask v2 = mask & 11100000 - c.movdqa(vFF.get(), v2.get()); // and copy vFF = mask & 11100000 - c.movdqa(v4.get(), XmmConst(u128::from8p(0xc0))); // v4 = 11000000 - c.pcmpeqb(vFF.get(), v4.get()); // gen 0xff vFF = (mask & 11100000 == 11000000) ? 0xff : 0 - c.movdqa(v4.get(), v2.get()); // copy again v4 = mask & 11100000 - c.pand(v4.get(), v3.get()); // filter mask v4 = mask & 10000000 - c.pcmpeqb(v2.get(), v1.get()); // v2 = (mask & 11100000 == 11100000) ? 0xff : 0 - c.pcmpeqb(v4.get(), v3.get()); // v4 = (mask & 10000000 == 10000000) ? 0xff : 0 - c.pand(v2.get(), v3.get()); // generate 0x80 v2 = (mask & 11100000 == 11100000) ? 0x80 : 0 - c.por(vFF.get(), v2.get()); // merge 0xff, 0x80 vFF = (mask & 11100000 == 11000000) ? 0xff : (mask & 11100000 == 11100000) ? 0x80 : 0 - c.pandn(v1.get(), v0.get()); // filter mask v1 = mask & 00011111 - // select bytes from [rb]: - c.movdqa(v2.get(), XmmConst(u128::from8p(0x0f))); // v2 = 00001111 - c.pxor(v1.get(), XmmConst(u128::from8p(0x10))); // v1 = (mask & 00011111) ^ 00010000 - c.psubb(v2.get(), v1.get()); // v2 = 00001111 - ((mask & 00011111) ^ 00010000) - c.movdqa(v1.get(), cpu_xmm(GPR[rb])); // v1 = rb - c.pshufb(v1.get(), v2.get()); // v1 = select(rb, 00001111 - ((mask & 00011111) ^ 00010000)) - // select bytes from [ra]: - c.pxor(v2.get(), XmmConst(u128::from8p(0xf0))); // v2 = (00001111 - ((mask & 00011111) ^ 00010000)) ^ 11110000 - c.movdqa(v3.get(), cpu_xmm(GPR[ra])); // v3 = ra - c.pshufb(v3.get(), v2.get()); // v3 = select(ra, (00001111 - ((mask & 00011111) ^ 00010000)) ^ 11110000) - c.por(v1.get(), v3.get()); // v1 = select(rb, 00001111 - ((mask & 00011111) ^ 00010000)) | (v3) - c.pandn(v4.get(), v1.get()); // filter result v4 = v1 & ((mask & 10000000 == 10000000) ? 0 : 0xff) - c.por(vFF.get(), v4.get()); // final merge vFF = (mask & 10000000 == 10000000) ? ((mask & 11100000 == 11000000) ? 0xff : (mask & 11100000 == 11100000) ? 0x80 : 0) : (v1) - XmmFinalize(vFF, rt); - XmmFinalize(v4); - XmmFinalize(v3); - XmmFinalize(v2); - XmmFinalize(v1); - XmmFinalize(v0); - LOG_OPCODE(); - } - void MPYA(u32 rt, u32 ra, u32 rb, u32 rc) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vb = XmmGet(rb); - const XmmLink& vi = XmmAlloc(); - c.movdqa(vi.get(), XmmConst(u128::from32p(0xffff))); - c.pand(va.get(), vi.get()); - c.pand(vb.get(), vi.get()); - c.pmaddwd(va.get(), vb.get()); - c.paddd(va.get(), cpu_xmm(GPR[rc])); - XmmFinalize(va, rt); - XmmFinalize(vb); - XmmFinalize(vi); - LOG_OPCODE(); - } - void FNMS(u32 rt, u32 ra, u32 rb, u32 rc) - { - const XmmLink& va = XmmGet(ra); - const XmmLink& vc = (ra == rc) ? XmmCopy(va, rt) : XmmGet(rc, rt); + virtual void SELB(u32 rc, u32 ra, u32 rb, u32 rt) override; + virtual void SHUFB(u32 rc, u32 ra, u32 rb, u32 rt) override; + virtual void MPYA(u32 rc, u32 ra, u32 rb, u32 rt) override; + virtual void FNMS(u32 rc, u32 ra, u32 rb, u32 rt) override; + virtual void FMA(u32 rc, u32 ra, u32 rb, u32 rt) override; + virtual void FMS(u32 rc, u32 ra, u32 rb, u32 rt) override; - if (ra == rb) - { - c.mulps(va.get(), va.get()); - } - else if (rb == rc) - { - c.mulps(va.get(), vc.get()); - } - else - { - if (const XmmLink* vb = XmmRead(rb)) - { - c.mulps(va.get(), vb->read()); - } - else - { - c.mulps(va.get(), cpu_xmm(GPR[rb])); - } - } - c.subps(vc.get(), va.get()); - XmmFinalize(vc, rt); - XmmFinalize(va); - LOG_OPCODE(); - } - void FMA(u32 rt, u32 ra, u32 rb, u32 rc) - { - if (ra != rb && rb != rc && rc != ra) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.mulps(va.get(), vb->read()); - } - else - { - c.mulps(va.get(), cpu_xmm(GPR[rb])); - } - if (const XmmLink* vc = XmmRead(rc)) - { - c.addps(va.get(), vc->read()); - } - else - { - c.addps(va.get(), cpu_xmm(GPR[rc])); - } - XmmFinalize(va, rt); - } - else if (ra == rb && rb == rc) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vc = XmmCopy(va); - c.mulps(va.get(), va.get()); - c.addps(va.get(), vc.get()); - XmmFinalize(va, rt); - XmmFinalize(vc); - } - else if (ra == rb) - { - const XmmLink& va = XmmGet(ra, rt); - c.mulps(va.get(), va.get()); - if (const XmmLink* vc = XmmRead(rc)) - { - c.addps(va.get(), vc->read()); - } - else - { - c.addps(va.get(), cpu_xmm(GPR[rc])); - } - XmmFinalize(va, rt); - } - else if (rb == rc) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vc = XmmRead(rc)) - { - c.mulps(va.get(), vc->read()); - c.addps(va.get(), vc->read()); - } - else - { - const XmmLink& vb = XmmGet(rb, rb); - c.mulps(va.get(), vb.get()); - c.addps(va.get(), vb.get()); - XmmFinalize(vb, rb); - } - XmmFinalize(va, rt); - } - else if (ra == rc) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vc = XmmCopy(va); - if (const XmmLink* vb = XmmRead(rb)) - { - c.mulps(va.get(), vb->read()); - } - else - { - c.mulps(va.get(), cpu_xmm(GPR[rb])); - } - c.addps(va.get(), vc.get()); - XmmFinalize(va, rt); - XmmFinalize(vc); - } - else - { - throw "FMA: invalid case"; // should never happen - } - LOG_OPCODE(); - } - void FMS(u32 rt, u32 ra, u32 rb, u32 rc) - { - if (ra != rb && rb != rc && rc != ra) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vb = XmmRead(rb)) - { - c.mulps(va.get(), vb->read()); - } - else - { - c.mulps(va.get(), cpu_xmm(GPR[rb])); - } - if (const XmmLink* vc = XmmRead(rc)) - { - c.subps(va.get(), vc->read()); - } - else - { - c.subps(va.get(), cpu_xmm(GPR[rc])); - } - XmmFinalize(va, rt); - } - else if (ra == rb && rb == rc) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vc = XmmCopy(va); - c.mulps(va.get(), va.get()); - c.subps(va.get(), vc.get()); - XmmFinalize(va, rt); - XmmFinalize(vc); - } - else if (ra == rb) - { - const XmmLink& va = XmmGet(ra, rt); - c.mulps(va.get(), va.get()); - if (const XmmLink* vc = XmmRead(rc)) - { - c.subps(va.get(), vc->read()); - } - else - { - c.subps(va.get(), cpu_xmm(GPR[rc])); - } - XmmFinalize(va, rt); - } - else if (rb == rc) - { - const XmmLink& va = XmmGet(ra, rt); - if (const XmmLink* vc = XmmRead(rc)) - { - c.mulps(va.get(), vc->read()); - c.subps(va.get(), vc->read()); - } - else - { - const XmmLink& vb = XmmGet(rb, rb); - c.mulps(va.get(), vb.get()); - c.subps(va.get(), vb.get()); - XmmFinalize(vb, rb); - } - XmmFinalize(va, rt); - } - else if (ra == rc) - { - const XmmLink& va = XmmGet(ra, rt); - const XmmLink& vc = XmmCopy(va); - if (const XmmLink* vb = XmmRead(rb)) - { - c.mulps(va.get(), vb->read()); - } - else - { - c.mulps(va.get(), cpu_xmm(GPR[rb])); - } - c.subps(va.get(), vc.get()); - XmmFinalize(va, rt); - XmmFinalize(vc); - } - else - { - throw "FMS: invalid case"; // should never happen - } - LOG_OPCODE(); - } - - void UNK(u32 code, u32 opcode, u32 gcode) - { - UNK(fmt::Format("Unimplemented opcode! (0x%08x, 0x%x, 0x%x)", code, opcode, gcode)); - } - - void UNK(const std::string& err) - { - LOG_ERROR(Log::SPU, "%s #pc: 0x%x", err.c_str(), CPU.PC); - c.mov(cpu_dword(PC), CPU.PC); - do_finalize = true; - Emu.Pause(); - } - - + virtual void UNK(u32 code, u32 opcode, u32 gcode) override; + virtual void UNK(const std::string& error); }; - -#undef c diff --git a/rpcs3/Emu/Cell/SPURecompilerCore.cpp b/rpcs3/Emu/Cell/SPURecompilerCore.cpp index 10329f727f..6257baaf7e 100644 --- a/rpcs3/Emu/Cell/SPURecompilerCore.cpp +++ b/rpcs3/Emu/Cell/SPURecompilerCore.cpp @@ -13,27 +13,26 @@ #include "SPUInterpreter.h" #include "SPURecompiler.h" +#define ASMJIT_STATIC + +#include "asmjit.h" + +using namespace asmjit; +using namespace asmjit::host; + SPURecompilerCore::SPURecompilerCore(SPUThread& cpu) : m_enc(new SPURecompiler(cpu, *this)) - , inter(new SPUInterpreter(cpu)) + , m_int(new SPUInterpreter(cpu)) + , m_jit(new JitRuntime) , CPU(cpu) - , first(true) - , need_check(false) { - memset(entry, 0, sizeof(entry)); X86CpuInfo inf; X86CpuUtil::detect(&inf); } -SPURecompilerCore::~SPURecompilerCore() -{ - delete m_enc; - delete inter; -} - void SPURecompilerCore::Decode(const u32 code) // decode instruction and run with interpreter { - (*SPU_instr::rrr_list)(inter, code); + (*SPU_instr::rrr_list)(m_int.get(), code); } void SPURecompilerCore::Compile(u16 pos) @@ -47,7 +46,7 @@ void SPURecompilerCore::Compile(u16 pos) //StringLogger stringLogger; //stringLogger.setOption(kLoggerOptionBinaryForm, true); - X86Compiler compiler(&runtime); + X86Compiler compiler(m_jit.get()); m_enc->compiler = &compiler; //compiler.setLogger(&stringLogger); @@ -106,7 +105,7 @@ void SPURecompilerCore::Compile(u16 pos) //(*SPU_instr::rrr_list)(&dis_asm, opcode); //compiler.addComment(fmt::Format("SPU data: PC=0x%05x %s", pos * 4, dis_asm.last_opcode.c_str()).c_str()); // compile single opcode: - (*SPU_instr::rrr_list)(m_enc, opcode); + (*SPU_instr::rrr_list)(m_enc.get(), opcode); // force finalization between every slice using absolute alignment /*if ((pos % 128 == 127) && !m_enc->do_finalize) { @@ -169,17 +168,16 @@ void SPURecompilerCore::Compile(u16 pos) u32 SPURecompilerCore::DecodeMemory(const u32 address) { - assert(CPU.offset == address - CPU.PC); - const u32 m_offset = CPU.offset; - const u16 pos = (u16)(CPU.PC >> 2); + const u32 pos = CPU.PC >> 2; // 0x0..0xffff + const auto ls = vm::get_ptr(CPU.offset); - //ConLog.Write("DecodeMemory: pos=%d", pos); - u32* ls = vm::get_ptr(m_offset); + assert(CPU.offset == address - CPU.PC && pos < 0x10000); if (entry[pos].pointer) { - // check data (hard way) bool is_valid = true; + + // check data if necessary (hard way) if (need_check) { for (u32 i = 0; i < 0x10000; i++) @@ -190,8 +188,10 @@ u32 SPURecompilerCore::DecodeMemory(const u32 address) break; } } + need_check = false; } + // invalidate if necessary if (!is_valid) { @@ -199,56 +199,35 @@ u32 SPURecompilerCore::DecodeMemory(const u32 address) { if (!entry[i].pointer) continue; - if (!entry[i].valid || entry[i].valid != ls[i] || - i + (u32)entry[i].count > (u32)pos && - i < (u32)pos + (u32)entry[pos].count) + if (!entry[i].valid || entry[i].valid != ls[i] || (i + entry[i].count > pos && i < pos + entry[pos].count)) { - runtime.release(entry[i].pointer); + m_jit->release(entry[i].pointer); entry[i].pointer = nullptr; - for (u32 j = i; j < i + (u32)entry[i].count; j++) + + for (u32 j = i; j < i + entry[i].count; j++) { entry[j].valid = 0; } + //need_check = true; } } - //LOG_ERROR(Log::SPU, "SPURecompilerCore::DecodeMemory(ls=0x%x): code has changed", pos * sizeof(u32)); } } - bool did_compile = false; if (!entry[pos].pointer) { Compile(pos); - did_compile = true; - if (entry[pos].valid == 0) - { - LOG_ERROR(Log::SPU, "SPURecompilerCore::Compile(ls=0x%x): branch to 0x0 opcode", pos * sizeof(u32)); - Emu.Pause(); - return 0; - } } - if (!entry[pos].pointer) return 0; - - typedef u32(*Func)(const void* _cpu, const void* _ls, const void* _imm, const void* _g_imm); - - Func func = asmjit_cast(entry[pos].pointer); - - void* cpu = (u8*)&CPU.GPR[0] - offsetof(SPUThread, GPR[0]); // ugly cpu base offset detection - - //if (did_compile) + if (!entry[pos].pointer) { - //LOG2_OPCODE("SPURecompilerCore::DecodeMemory(ls=0x%x): NewPC = 0x%llx", address, (u64)res << 2); - //if (pos == 0x19c >> 2) - { - //Emu.Pause(); - //for (uint i = 0; i < 128; ++i) LOG_NOTICE(Log::SPU, "r%d = 0x%s", i, CPU.GPR[i].ToString().c_str()); - } + return 0; } - u32 res = pos; - res = func(cpu, vm::get_ptr(m_offset), imm_table.data(), &g_spu_imm); + const auto func = asmjit_cast(entry[pos].pointer); + + u32 res = func(CPU, ls, imm_table.data(), &g_spu_imm); if (res & 0x1000000) { @@ -262,16 +241,6 @@ u32 SPURecompilerCore::DecodeMemory(const u32 address) res &= ~0x2000000; } - if (did_compile) - { - //LOG2_OPCODE("SPURecompilerCore::DecodeMemory(ls=0x%x): NewPC = 0x%llx", address, (u64)res << 2); - //if (pos == 0x340 >> 2) - { - //Emu.Pause(); - //for (uint i = 0; i < 128; ++i) LOG_NOTICE(Log::SPU, "r%d = 0x%s", i, CPU.GPR[i].ToString().c_str()); - } - } - if ((res - 1) == (CPU.PC >> 2)) { return 4; @@ -282,3 +251,3183 @@ u32 SPURecompilerCore::DecodeMemory(const u32 address) return 0; } } + +#define c (*compiler) + +#define cpu_offset(x) static_cast(reinterpret_cast(&(((SPUThread*)0)->x))) +#define cpu_xmm(x) oword_ptr(*cpu_var, cpu_offset(x)) +#define cpu_qword(x) qword_ptr(*cpu_var, cpu_offset(x)) +#define cpu_dword(x) dword_ptr(*cpu_var, cpu_offset(x)) +#define cpu_word(x) word_ptr(*cpu_var, cpu_offset(x)) +#define cpu_byte(x) byte_ptr(*cpu_var, cpu_offset(x)) + +#define g_imm_offset(x) static_cast(reinterpret_cast(&(((g_spu_imm_table_t*)0)->x))) +#define g_imm_xmm(x) oword_ptr(*g_imm_var, g_imm_offset(x)) +#define g_imm2_xmm(x, y) oword_ptr(*g_imm_var, y, 0, g_imm_offset(x)) + + +#define LOG_OPCODE(...) //ConLog.Write("Compiled "__FUNCTION__"(): "__VA_ARGS__) + +#define LOG3_OPCODE(...) //ConLog.Write("Linked "__FUNCTION__"(): "__VA_ARGS__) + +#define LOG4_OPCODE(...) //c.addComment(fmt::Format("SPU info: "__FUNCTION__"(): "__VA_ARGS__).c_str()) + +#define WRAPPER_BEGIN(a0, a1, a2, a3) struct opwr_##a0 \ +{ \ + static void opcode(u32 a0, u32 a1, u32 a2, u32 a3) \ +{ \ + SPUThread& CPU = *(SPUThread*)GetCurrentNamedThread(); + +#define WRAPPER_END(a0, a1, a2, a3) /*LOG2_OPCODE();*/ } \ +}; \ + /*XmmRelease();*/ \ + if (#a0[0] == 'r') XmmInvalidate(a0); \ + if (#a1[0] == 'r') XmmInvalidate(a1); \ + if (#a2[0] == 'r') XmmInvalidate(a2); \ + if (#a3[0] == 'r') XmmInvalidate(a3); \ + X86CallNode* call##a0 = c.call(imm_ptr(reinterpret_cast(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4()); \ + call##a0->setArg(0, imm_u(a0)); \ + call##a0->setArg(1, imm_u(a1)); \ + call##a0->setArg(2, imm_u(a2)); \ + call##a0->setArg(3, imm_u(a3)); \ + LOG3_OPCODE(/*#a0"=%d, "#a1"=%d, "#a2"=%d, "#a3"=%d", a0, a1, a2, a3*/); + +const SPURecompiler::XmmLink& SPURecompiler::XmmAlloc(s8 pref) // get empty xmm register +{ + if (pref >= 0) for (u32 i = 0; i < 16; i++) + { + if ((xmm_var[i].reg == pref) && !xmm_var[i].taken) + { + xmm_var[i].taken = true; + xmm_var[i].got = false; + xmm_var[i].access = 0; + LOG4_OPCODE("pref(%d) reg taken (i=%d)", pref, i); + return xmm_var[i]; + } + } + for (u32 i = 0; i < 16; i++) + { + if ((xmm_var[i].reg == -1) && !xmm_var[i].taken) + { + xmm_var[i].taken = true; + xmm_var[i].got = false; + xmm_var[i].access = 0; + LOG4_OPCODE("free reg taken (i=%d)", i); + return xmm_var[i]; + } + } + int last = -1, max = -1; + for (u32 i = 0; i < 16; i++) + { + if (!xmm_var[i].taken) + { + if ((int)xmm_var[i].access > max) + { + last = i; + max = xmm_var[i].access; + } + } + } + if (last >= 0) + { + // (saving cached data?) + //c.movdqa(cpu_xmm(GPR[xmm_var[last].reg]), *xmm_var[last].data); + xmm_var[last].taken = true; + xmm_var[last].got = false; + LOG4_OPCODE("cached reg taken (i=%d): GPR[%d] lost", last, xmm_var[last].reg); + xmm_var[last].reg = -1; // ??? + xmm_var[last].access = 0; + return xmm_var[last]; + } + throw "XmmAlloc() failed"; +} + +const SPURecompiler::XmmLink* SPURecompiler::XmmRead(const s8 reg) const // get xmm register with specific SPU reg or nullptr +{ + assert(reg >= 0); + for (u32 i = 0; i < 16; i++) + { + if (xmm_var[i].reg == reg) + { + //assert(!xmm_var[i].got); + //if (xmm_var[i].got) throw "XmmRead(): wrong reuse"; + LOG4_OPCODE("GPR[%d] has been read (i=%d)", reg, i); + xmm_var[i].access++; + return &xmm_var[i]; + } + } + LOG4_OPCODE("GPR[%d] not found", reg); + return nullptr; +} + +const SPURecompiler::XmmLink& SPURecompiler::XmmGet(s8 reg, s8 target) // get xmm register with specific SPU reg +{ + assert(reg >= 0); + const XmmLink* res = nullptr; + if (reg == target) + { + for (u32 i = 0; i < 16; i++) + { + if (xmm_var[i].reg == reg) + { + res = &xmm_var[i]; + if (xmm_var[i].taken) throw "XmmGet(): xmm_var is taken"; + xmm_var[i].taken = true; + xmm_var[i].got = false; + //xmm_var[i].reg = -1; + for (u32 j = i + 1; j < 16; j++) + { + if (xmm_var[j].reg == reg) throw "XmmGet(): xmm_var duplicate"; + } + LOG4_OPCODE("cached GPR[%d] used (i=%d)", reg, i); + break; + } + } + } + if (!res) + { + res = &XmmAlloc(target); + /*if (target != res->reg) + { + c.movdqa(*res->data, cpu_xmm(GPR[reg])); + } + else*/ + { + if (const XmmLink* source = XmmRead(reg)) + { + c.movdqa(*res->data, source->read()); + } + else + { + c.movdqa(*res->data, cpu_xmm(GPR[reg])); + } + } + const_cast(res)->reg = -1; // ??? + LOG4_OPCODE("* cached GPR[%d] not found", reg); + } + return *res; +} + +const SPURecompiler::XmmLink& SPURecompiler::XmmCopy(const XmmLink& from, s8 pref) // XmmAlloc + mov +{ + const XmmLink* res = &XmmAlloc(pref); + c.movdqa(*res->data, *from.data); + const_cast(res)->reg = -1; // ??? + LOG4_OPCODE("*"); + return *res; +} + +void SPURecompiler::XmmInvalidate(const s8 reg) // invalidate cached register +{ + assert(reg >= 0); + for (u32 i = 0; i < 16; i++) + { + if (xmm_var[i].reg == reg) + { + if (xmm_var[i].taken) throw "XmmInvalidate(): xmm_var is taken"; + LOG4_OPCODE("GPR[%d] invalidated (i=%d)", reg, i); + xmm_var[i].reg = -1; + xmm_var[i].access = 0; + } + } +} + +void SPURecompiler::XmmFinalize(const XmmLink& var, s8 reg) +{ + // invalidation + if (reg >= 0) for (u32 i = 0; i < 16; i++) + { + if (xmm_var[i].reg == reg) + { + LOG4_OPCODE("GPR[%d] invalidated (i=%d)", reg, i); + xmm_var[i].reg = -1; + xmm_var[i].access = 0; + } + } + for (u32 i = 0; i < 16; i++) + { + if (xmm_var[i].data == var.data) + { + assert(xmm_var[i].taken); + // save immediately: + if (reg >= 0) + { + c.movdqa(cpu_xmm(GPR[reg]), *xmm_var[i].data); + } + else + { + } + LOG4_OPCODE("GPR[%d] finalized (i=%d), GPR[%d] replaced", reg, i, xmm_var[i].reg); + // (to disable caching:) + //reg = -1; + xmm_var[i].reg = reg; + xmm_var[i].taken = false; + xmm_var[i].got = false; + xmm_var[i].access = 0; + return; + } + } + assert(false); +} + +void SPURecompiler::XmmRelease() +{ + for (u32 i = 0; i < 16; i++) + { + if (xmm_var[i].reg >= 0) + { + //c.movdqa(cpu_xmm(GPR[xmm_var[i].reg]), *xmm_var[i].data); + LOG4_OPCODE("GPR[%d] released (i=%d)", xmm_var[i].reg, i); + xmm_var[i].reg = -1; + xmm_var[i].access = 0; + } + } +} + +X86Mem SPURecompiler::XmmConst(u128 data) +{ + s32 shift = 0; + + for (; shift < rec.imm_table.size(); shift++) + { + if (rec.imm_table[shift] == data) + { + return oword_ptr(*imm_var, shift * sizeof(u128)); + } + } + + rec.imm_table.push_back(data); + return oword_ptr(*imm_var, shift * sizeof(u128)); +} + + +void SPURecompiler::STOP(u32 code) +{ + struct STOP_wrapper + { + static void STOP(u32 code) + { + SPUThread& CPU = *(SPUThread*)GetCurrentNamedThread(); + CPU.stop_and_signal(code); + LOG2_OPCODE(); + } + }; + c.mov(cpu_dword(PC), CPU.PC); + X86CallNode* call = c.call(imm_ptr(reinterpret_cast(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1()); + call->setArg(0, imm_u(code)); + c.mov(*pos_var, (CPU.PC >> 2) + 1); + do_finalize = true; + LOG_OPCODE(); +} + +void SPURecompiler::LNOP() +{ + LOG_OPCODE(); +} + +void SPURecompiler::SYNC(u32 Cbit) +{ + c.mov(cpu_dword(PC), CPU.PC); + // This instruction must be used following a store instruction that modifies the instruction stream. + c.mfence(); + c.mov(*pos_var, (CPU.PC >> 2) + 1 + 0x2000000); + do_finalize = true; + LOG_OPCODE(); +} + +void SPURecompiler::DSYNC() +{ + // This instruction forces all earlier load, store, and channel instructions to complete before proceeding. + c.mfence(); + LOG_OPCODE(); +} + +void SPURecompiler::MFSPR(u32 rt, u32 sa) +{ + return UNK("MFSPR"); +} + +void SPURecompiler::RDCH(u32 rt, u32 ra) +{ + c.mov(cpu_dword(PC), CPU.PC); + WRAPPER_BEGIN(rt, ra, yy, zz); + CPU.GPR[rt] = u128::from32r(CPU.get_ch_value(ra)); + WRAPPER_END(rt, ra, 0, 0); + // TODO +} + +void SPURecompiler::RCHCNT(u32 rt, u32 ra) +{ + c.mov(cpu_dword(PC), CPU.PC); + WRAPPER_BEGIN(rt, ra, yy, zz); + CPU.GPR[rt] = u128::from32r(CPU.get_ch_count(ra)); + WRAPPER_END(rt, ra, 0, 0); + // TODO +} + +void SPURecompiler::SF(u32 rt, u32 ra, u32 rb) +{ + // sub from + const XmmLink& vb = XmmGet(rb, rt); + if (const XmmLink* va = XmmRead(ra)) + { + c.psubd(vb.get(), va->read()); + } + else + { + c.psubd(vb.get(), cpu_xmm(GPR[ra])); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::OR(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vb = XmmGet(rb, rt); + if (const XmmLink* va = XmmRead(ra)) + { + c.por(vb.get(), va->read()); + } + else + { + c.por(vb.get(), cpu_xmm(GPR[ra])); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::BG(u32 rt, u32 ra, u32 rb) +{ + // compare if-greater-than + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vi = XmmAlloc(); + c.movdqa(vi.get(), XmmConst(u128::from32p(0x80000000))); + c.pxor(va.get(), vi.get()); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pxor(vi.get(), vb->read()); + } + else + { + c.pxor(vi.get(), cpu_xmm(GPR[rb])); + } + c.pcmpgtd(va.get(), vi.get()); + c.paddd(va.get(), XmmConst(u128::from32p(1))); + XmmFinalize(va, rt); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::SFH(u32 rt, u32 ra, u32 rb) +{ + // sub from (halfword) + const XmmLink& vb = XmmGet(rb, rt); + if (const XmmLink* va = XmmRead(ra)) + { + c.psubw(vb.get(), va->read()); + } + else + { + c.psubw(vb.get(), cpu_xmm(GPR[ra])); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::NOR(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (ra != rb) + { + if (const XmmLink* vb = XmmRead(rb)) + { + c.por(va.get(), vb->read()); + } + else + { + c.por(va.get(), cpu_xmm(GPR[rb])); + } + } + c.pxor(va.get(), XmmConst(u128::from32p(0xffffffff))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ABSDB(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = XmmGet(rb); + const XmmLink& vm = XmmCopy(va); + c.pmaxub(va.get(), vb.get()); + c.pminub(vb.get(), vm.get()); + c.psubb(va.get(), vb.get()); + XmmFinalize(va, rt); + XmmFinalize(vb); + XmmFinalize(vm); + LOG_OPCODE(); +} + +void SPURecompiler::ROT(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + for (u32 i = 0; i < 4; i++) + { + c.mov(qw0->r32(), cpu_dword(GPR[ra]._u32[i])); + c.mov(*addr, cpu_dword(GPR[rb]._u32[i])); + c.rol(qw0->r32(), *addr); + c.mov(cpu_dword(GPR[rt]._u32[i]), qw0->r32()); + } + LOG_OPCODE(); +} + +void SPURecompiler::ROTM(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + for (u32 i = 0; i < 4; i++) + { + c.mov(qw0->r32(), cpu_dword(GPR[ra]._u32[i])); + c.mov(*addr, cpu_dword(GPR[rb]._u32[i])); + c.neg(*addr); + c.shr(*qw0, *addr); + c.mov(cpu_dword(GPR[rt]._u32[i]), qw0->r32()); + } + LOG_OPCODE(); +} + +void SPURecompiler::ROTMA(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + for (u32 i = 0; i < 4; i++) + { + c.movsxd(*qw0, cpu_dword(GPR[ra]._u32[i])); + c.mov(*addr, cpu_dword(GPR[rb]._u32[i])); + c.neg(*addr); + c.sar(*qw0, *addr); + c.mov(cpu_dword(GPR[rt]._u32[i]), qw0->r32()); + } + LOG_OPCODE(); +} + +void SPURecompiler::SHL(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + for (u32 i = 0; i < 4; i++) + { + c.mov(qw0->r32(), cpu_dword(GPR[ra]._u32[i])); + c.mov(*addr, cpu_dword(GPR[rb]._u32[i])); + c.shl(*qw0, *addr); + c.mov(cpu_dword(GPR[rt]._u32[i]), qw0->r32()); + } + LOG_OPCODE(); +} + +void SPURecompiler::ROTH(u32 rt, u32 ra, u32 rb) //nf +{ + XmmInvalidate(rt); + for (u32 i = 0; i < 8; i++) + { + c.movzx(qw0->r32(), cpu_word(GPR[ra]._u16[i])); + c.movzx(*addr, cpu_word(GPR[rb]._u16[i])); + c.rol(qw0->r16(), *addr); + c.mov(cpu_word(GPR[rt]._u16[i]), qw0->r16()); + } + LOG_OPCODE(); +} + +void SPURecompiler::ROTHM(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + for (u32 i = 0; i < 8; i++) + { + c.movzx(qw0->r32(), cpu_word(GPR[ra]._u16[i])); + c.movzx(*addr, cpu_word(GPR[rb]._u16[i])); + c.neg(*addr); + c.shr(qw0->r32(), *addr); + c.mov(cpu_word(GPR[rt]._u16[i]), qw0->r16()); + } + LOG_OPCODE(); +} + +void SPURecompiler::ROTMAH(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + for (u32 i = 0; i < 8; i++) + { + c.movsx(qw0->r32(), cpu_word(GPR[ra]._u16[i])); + c.movzx(*addr, cpu_word(GPR[rb]._u16[i])); + c.neg(*addr); + c.sar(qw0->r32(), *addr); + c.mov(cpu_word(GPR[rt]._u16[i]), qw0->r16()); + } + LOG_OPCODE(); +} + +void SPURecompiler::SHLH(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + for (u32 i = 0; i < 8; i++) + { + c.movzx(qw0->r32(), cpu_word(GPR[ra]._u16[i])); + c.movzx(*addr, cpu_word(GPR[rb]._u16[i])); + c.shl(qw0->r32(), *addr); + c.mov(cpu_word(GPR[rt]._u16[i]), qw0->r16()); + } + LOG_OPCODE(); +} + +void SPURecompiler::ROTI(u32 rt, u32 ra, s32 i7) +{ + // rotate left + const int s = i7 & 0x1f; + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& v1 = XmmCopy(va); + c.pslld(va.get(), s); + c.psrld(v1.get(), 32 - s); + c.por(va.get(), v1.get()); + XmmFinalize(va, rt); + XmmFinalize(v1); + LOG_OPCODE(); +} + +void SPURecompiler::ROTMI(u32 rt, u32 ra, s32 i7) +{ + // shift right logical + const int s = (0 - i7) & 0x3f; + const XmmLink& va = XmmGet(ra, rt); + c.psrld(va.get(), s); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ROTMAI(u32 rt, u32 ra, s32 i7) +{ + // shift right arithmetical + const int s = (0 - i7) & 0x3f; + const XmmLink& va = XmmGet(ra, rt); + c.psrad(va.get(), s); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::SHLI(u32 rt, u32 ra, s32 i7) +{ + // shift left + const int s = i7 & 0x3f; + const XmmLink& va = XmmGet(ra, rt); + c.pslld(va.get(), s); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ROTHI(u32 rt, u32 ra, s32 i7) +{ + // rotate left (halfword) + const int s = i7 & 0xf; + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& v1 = XmmCopy(va); + c.psllw(va.get(), s); + c.psrlw(v1.get(), 16 - s); + c.por(va.get(), v1.get()); + XmmFinalize(va, rt); + XmmFinalize(v1); + LOG_OPCODE(); +} + +void SPURecompiler::ROTHMI(u32 rt, u32 ra, s32 i7) +{ + // shift right logical + const int s = (0 - i7) & 0x1f; + const XmmLink& va = XmmGet(ra, rt); + c.psrlw(va.get(), s); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ROTMAHI(u32 rt, u32 ra, s32 i7) +{ + // shift right arithmetical (halfword) + const int s = (0 - i7) & 0x1f; + const XmmLink& va = XmmGet(ra, rt); + c.psraw(va.get(), s); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::SHLHI(u32 rt, u32 ra, s32 i7) +{ + // shift left (halfword) + const int s = i7 & 0x1f; + const XmmLink& va = XmmGet(ra, rt); + c.psllw(va.get(), s); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::A(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vb = XmmGet(rb, rt); + if (const XmmLink* va = XmmRead(ra)) + { + c.paddd(vb.get(), va->read()); + } + else + { + c.paddd(vb.get(), cpu_xmm(GPR[ra])); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::AND(u32 rt, u32 ra, u32 rb) +{ + // and + const XmmLink& vb = XmmGet(rb, rt); + if (const XmmLink* va = XmmRead(ra)) + { + c.pand(vb.get(), va->read()); + } + else + { + c.pand(vb.get(), cpu_xmm(GPR[ra])); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CG(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = XmmGet(rb); + const XmmLink& vi = XmmAlloc(); + c.movdqa(vi.get(), XmmConst(u128::from32p(0x80000000))); + c.paddd(vb.get(), va.get()); + c.pxor(va.get(), vi.get()); + c.pxor(vb.get(), vi.get()); + c.pcmpgtd(va.get(), vb.get()); + c.psrld(va.get(), 31); + XmmFinalize(va, rt); + XmmFinalize(vb); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::AH(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.paddw(va.get(), vb->read()); + } + else + { + c.paddw(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::NAND(u32 rt, u32 ra, u32 rb) +{ + // nand + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pand(va.get(), vb->read()); + } + else + { + c.pand(va.get(), cpu_xmm(GPR[rb])); + } + c.pxor(va.get(), XmmConst(u128::from32p(0xffffffff))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::AVGB(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vb = XmmGet(rb); + if (const XmmLink* va = XmmRead(ra)) + { + c.pavgb(vb.get(), va->read()); + } + else + { + c.pavgb(vb.get(), cpu_xmm(GPR[ra])); + } + XmmFinalize(vb, rt); +} + +void SPURecompiler::MTSPR(u32 rt, u32 sa) +{ +} + +void SPURecompiler::WRCH(u32 ra, u32 rt) +{ + c.mov(cpu_dword(PC), CPU.PC); + WRAPPER_BEGIN(ra, rt, yy, zz); + CPU.set_ch_value(ra, CPU.GPR[rt]._u32[3]); + WRAPPER_END(ra, rt, 0, 0); + // TODO + + /*XmmInvalidate(rt); + + X86GpVar v(c, kVarTypeUInt32); + c.mov(v, cpu_dword(GPR[rt]._u32[3])); + switch (ra) + { + case MFC_LSA: + c.mov(cpu_dword(MFC1.LSA.m_value[0]), v); + break; + + case MFC_EAH: + c.mov(cpu_dword(MFC1.EAH.m_value[0]), v); + break; + + case MFC_EAL: + c.mov(cpu_dword(MFC1.EAL.m_value[0]), v); + break; + + case MFC_Size: + c.mov(cpu_word(MFC1.Size_Tag.m_val16[1]), v); + break; + + case MFC_TagID: + c.mov(cpu_word(MFC1.Size_Tag.m_val16[0]), v); + break; + + default: + { + X86X64CallNode* call = c.call(imm_ptr(reinterpret_cast(&WRCH_wrapper::WRCH)), kFuncConvHost, FuncBuilder2()); + call->setArg(0, imm_u(ra)); + call->setArg(1, v); + } + }*/ +} + +void SPURecompiler::BIZ(u32 intr, u32 rt, u32 ra) +{ + switch (intr & 0x30) + { + case 0: break; + default: return UNK("BIZ"); + } + + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*addr, CPU.PC + 4); + c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) + c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); + c.cmovne(*pos_var, *addr); + c.shr(*pos_var, 2); + LOG_OPCODE(); +} + +void SPURecompiler::BINZ(u32 intr, u32 rt, u32 ra) +{ + switch (intr & 0x30) + { + case 0: break; + default: return UNK("BINZ"); + } + + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*addr, CPU.PC + 4); + c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) + c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); + c.cmove(*pos_var, *addr); + c.shr(*pos_var, 2); + LOG_OPCODE(); +} + +void SPURecompiler::BIHZ(u32 intr, u32 rt, u32 ra) +{ + switch (intr & 0x30) + { + case 0: break; + default: return UNK("BIHZ"); + } + + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*addr, CPU.PC + 4); + c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) + c.cmp(cpu_word(GPR[rt]._u16[6]), 0); + c.cmovne(*pos_var, *addr); + c.shr(*pos_var, 2); + LOG_OPCODE(); +} + +void SPURecompiler::BIHNZ(u32 intr, u32 rt, u32 ra) +{ + switch (intr & 0x30) + { + case 0: break; + default: return UNK("BIHNZ"); + } + + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*addr, CPU.PC + 4); + c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) + c.cmp(cpu_word(GPR[rt]._u16[6]), 0); + c.cmove(*pos_var, *addr); + c.shr(*pos_var, 2); + LOG_OPCODE(); +} + +void SPURecompiler::STOPD(u32 rc, u32 ra, u32 rb) +{ + return UNK("STOPD"); +} + +void SPURecompiler::STQX(u32 rt, u32 ra, u32 rb) +{ + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + if (ra == rb) + { + c.add(*addr, *addr); + } + else + { + c.add(*addr, cpu_dword(GPR[rb]._u32[3])); + } + c.and_(*addr, 0x3fff0); + + /*const XmmLink& vt = XmmGet(rt); + c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); + c.movdqa(oword_ptr(*ls_var, *addr), vt.get()); + XmmFinalize(vt);*/ + + c.mov(*qw0, cpu_qword(GPR[rt]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[rt]._u64[1])); + c.bswap(*qw0); + c.bswap(*qw1); + c.mov(qword_ptr(*ls_var, *addr, 0, 0), *qw1); + c.mov(qword_ptr(*ls_var, *addr, 0, 8), *qw0); + + LOG_OPCODE(); +} + +void SPURecompiler::BI(u32 intr, u32 ra) +{ + switch (intr & 0x30) + { + case 0: break; + default: return UNK("BI"); + } + + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR) + c.shr(*pos_var, 2); + LOG_OPCODE(); +} + +void SPURecompiler::BISL(u32 intr, u32 rt, u32 ra) +{ + switch (intr & 0x30) + { + case 0: break; + default: return UNK("BISL"); + } + + XmmInvalidate(rt); + + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.xor_(*pos_var, *pos_var); + c.mov(cpu_dword(GPR[rt]._u32[0]), *pos_var); + c.mov(cpu_dword(GPR[rt]._u32[1]), *pos_var); + c.mov(cpu_dword(GPR[rt]._u32[2]), *pos_var); + c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); + c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4); + c.shr(*pos_var, 2); + c.or_(*pos_var, 0x2000000); + LOG_OPCODE(); +} + +void SPURecompiler::IRET(u32 ra) +{ + return UNK("IRET"); +} + +void SPURecompiler::BISLED(u32 intr, u32 rt, u32 ra) +{ + return UNK("BISLED"); +} + +void SPURecompiler::HBR(u32 p, u32 ro, u32 ra) +{ + LOG_OPCODE(); +} + +void SPURecompiler::GB(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + c.pshufb(va.get(), XmmConst(u128::fromV(_mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 8, 4, 0)))); + c.psllq(va.get(), 7); + c.pmovmskb(*addr, va.get()); + c.pxor(va.get(), va.get()); + c.pinsrw(va.get(), *addr, 6); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::GBH(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + c.pshufb(va.get(), XmmConst(u128::fromV(_mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 14, 12, 10, 8, 6, 4, 2, 0)))); + c.psllq(va.get(), 7); + c.pmovmskb(*addr, va.get()); + c.pxor(va.get(), va.get()); + c.pinsrw(va.get(), *addr, 6); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::GBB(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + c.psllq(va.get(), 7); + c.pmovmskb(*addr, va.get()); + c.pxor(va.get(), va.get()); + c.pinsrw(va.get(), *addr, 6); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FSM(u32 rt, u32 ra) +{ + const XmmLink& vr = XmmAlloc(rt); + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.and_(*addr, 0xf); + c.shl(*addr, 4); + c.movdqa(vr.get(), g_imm2_xmm(fsm[0], *addr)); + XmmFinalize(vr, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FSMH(u32 rt, u32 ra) +{ + const XmmLink& vr = XmmAlloc(rt); + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.and_(*addr, 0xff); + c.shl(*addr, 4); + c.movdqa(vr.get(), g_imm2_xmm(fsmh[0], *addr)); + XmmFinalize(vr, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FSMB(u32 rt, u32 ra) +{ + const XmmLink& vr = XmmAlloc(rt); + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.and_(*addr, 0xffff); + c.shl(*addr, 4); + c.movdqa(vr.get(), g_imm2_xmm(fsmb[0], *addr)); + XmmFinalize(vr, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FREST(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + c.rcpps(va.get(), va.get()); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FRSQEST(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + c.andps(va.get(), XmmConst(u128::from32p(0x7fffffff))); // abs + c.rsqrtps(va.get(), va.get()); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::LQX(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + if (ra == rb) + { + c.add(*addr, *addr); + } + else + { + c.add(*addr, cpu_dword(GPR[rb]._u32[3])); + } + c.and_(*addr, 0x3fff0); + + /*const XmmLink& vt = XmmAlloc(rt); + c.movdqa(vt.get(), oword_ptr(*ls_var, *addr)); + c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); + XmmFinalize(vt, rt);*/ + + c.mov(*qw0, qword_ptr(*ls_var, *addr, 0, 0)); + c.mov(*qw1, qword_ptr(*ls_var, *addr, 0, 8)); + c.bswap(*qw0); + c.bswap(*qw1); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0); + + LOG_OPCODE(); +} + +void SPURecompiler::ROTQBYBI(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + c.and_(*addr, 0xf << 3); + c.shl(*addr, 1); + c.pshufb(va.get(), g_imm2_xmm(rldq_pshufb[0], *addr)); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ROTQMBYBI(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + c.shr(*addr, 3); + c.neg(*addr); + c.and_(*addr, 0x1f); + c.shl(*addr, 4); + c.pshufb(va.get(), g_imm2_xmm(srdq_pshufb[0], *addr)); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::SHLQBYBI(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + c.and_(*addr, 0x1f << 3); + c.shl(*addr, 1); + c.pshufb(va.get(), g_imm2_xmm(sldq_pshufb[0], *addr)); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CBX(u32 rt, u32 ra, u32 rb) +{ + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + if (ra == 1) + { + // assuming that SP % 16 is always zero + } + else if (ra == rb) + { + c.add(*addr, *addr); + } + else + { + c.add(*addr, cpu_dword(GPR[ra]._u32[3])); + } + c.not_(*addr); + c.and_(*addr, 0xf); + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); + XmmFinalize(vr, rt); + XmmInvalidate(rt); + c.mov(byte_ptr(*cpu_var, *addr, 0, cpu_offset(GPR[rt])), 0x03); + LOG_OPCODE(); +} + +void SPURecompiler::CHX(u32 rt, u32 ra, u32 rb) +{ + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + if (ra == 1) + { + // assuming that SP % 16 is always zero + } + else if (ra == rb) + { + c.add(*addr, *addr); + } + else + { + c.add(*addr, cpu_dword(GPR[ra]._u32[3])); + } + c.not_(*addr); + c.and_(*addr, 0xe); + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); + XmmFinalize(vr, rt); + XmmInvalidate(rt); + c.mov(word_ptr(*cpu_var, *addr, 0, cpu_offset(GPR[rt])), 0x0203); + LOG_OPCODE(); +} + +void SPURecompiler::CWX(u32 rt, u32 ra, u32 rb) +{ + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + if (ra == 1) + { + // assuming that SP % 16 is always zero + } + else if (ra == rb) + { + c.add(*addr, *addr); + } + else + { + c.add(*addr, cpu_dword(GPR[ra]._u32[3])); + } + c.not_(*addr); + c.and_(*addr, 0xc); + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); + XmmFinalize(vr, rt); + XmmInvalidate(rt); + c.mov(dword_ptr(*cpu_var, *addr, 0, cpu_offset(GPR[rt])), 0x00010203); + LOG_OPCODE(); +} + +void SPURecompiler::CDX(u32 rt, u32 ra, u32 rb) +{ + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + if (ra == 1) + { + // assuming that SP % 16 is always zero + } + else if (ra == rb) + { + c.add(*addr, *addr); + } + else + { + c.add(*addr, cpu_dword(GPR[ra]._u32[3])); + } + c.test(*addr, 0x8); + const XmmLink& vr = XmmAlloc(rt); + Label p1(c), p2(c); + c.jnz(p1); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x00010203, 0x04050607, 0x18191a1b, 0x1c1d1e1f)))); + c.jmp(p2); + c.bind(p1); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x00010203, 0x04050607)))); + c.bind(p2); + XmmFinalize(vr, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ROTQBI(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); + c.mov(*qw2, *qw0); + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + c.and_(*addr, 7); + c.shld(*qw0, *qw1, *addr); + c.shld(*qw1, *qw2, *addr); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); + LOG_OPCODE(); +} + +void SPURecompiler::ROTQMBI(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + c.neg(*addr); + c.and_(*addr, 7); + c.shrd(*qw0, *qw1, *addr); + c.shr(*qw1, *addr); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); + LOG_OPCODE(); +} + +void SPURecompiler::SHLQBI(u32 rt, u32 ra, u32 rb) +{ + XmmInvalidate(rt); + c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + c.and_(*addr, 7); + c.shld(*qw1, *qw0, *addr); + c.shl(*qw0, *addr); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); + LOG_OPCODE(); +} + +void SPURecompiler::ROTQBY(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + c.and_(*addr, 0xf); + c.shl(*addr, 4); + c.pshufb(va.get(), g_imm2_xmm(rldq_pshufb[0], *addr)); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ROTQMBY(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + c.neg(*addr); + c.and_(*addr, 0x1f); + c.shl(*addr, 4); + c.pshufb(va.get(), g_imm2_xmm(srdq_pshufb[0], *addr)); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::SHLQBY(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + c.mov(*addr, cpu_dword(GPR[rb]._u32[3])); + c.and_(*addr, 0x1f); + c.shl(*addr, 4); + c.pshufb(va.get(), g_imm2_xmm(sldq_pshufb[0], *addr)); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ORX(u32 rt, u32 ra) +{ + XmmInvalidate(rt); + c.mov(*addr, cpu_dword(GPR[ra]._u32[0])); + c.or_(*addr, cpu_dword(GPR[ra]._u32[1])); + c.or_(*addr, cpu_dword(GPR[ra]._u32[2])); + c.or_(*addr, cpu_dword(GPR[ra]._u32[3])); + c.mov(cpu_dword(GPR[rt]._u32[3]), *addr); + c.xor_(*addr, *addr); + c.mov(cpu_dword(GPR[rt]._u32[0]), *addr); + c.mov(cpu_dword(GPR[rt]._u32[1]), *addr); + c.mov(cpu_dword(GPR[rt]._u32[2]), *addr); + LOG_OPCODE(); +} + +void SPURecompiler::CBD(u32 rt, u32 ra, s32 i7) +{ + if (ra == 1) + { + // assuming that SP % 16 is always zero + const XmmLink& vr = XmmAlloc(rt); + u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); + value.u8r[i7 & 0xf] = 0x03; + c.movdqa(vr.get(), XmmConst(value)); + XmmFinalize(vr, rt); + } + else + { + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.add(*addr, i7); + c.not_(*addr); + c.and_(*addr, 0xf); + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); + XmmFinalize(vr, rt); + XmmInvalidate(rt); + c.mov(byte_ptr(*cpu_var, *addr, 0, cpu_offset(GPR[rt])), 0x03); + } + LOG_OPCODE(); +} + +void SPURecompiler::CHD(u32 rt, u32 ra, s32 i7) +{ + if (ra == 1) + { + // assuming that SP % 16 is always zero + const XmmLink& vr = XmmAlloc(rt); + u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); + value.u16r[(i7 >> 1) & 0x7] = 0x0203; + c.movdqa(vr.get(), XmmConst(value)); + XmmFinalize(vr, rt); + } + else + { + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.add(*addr, i7); + c.not_(*addr); + c.and_(*addr, 0xe); + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); + XmmFinalize(vr, rt); + XmmInvalidate(rt); + c.mov(word_ptr(*cpu_var, *addr, 0, cpu_offset(GPR[rt])), 0x0203); + } + LOG_OPCODE(); +} + +void SPURecompiler::CWD(u32 rt, u32 ra, s32 i7) +{ + if (ra == 1) + { + // assuming that SP % 16 is always zero + const XmmLink& vr = XmmAlloc(rt); + u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); + value.u32r[(i7 >> 2) & 0x3] = 0x00010203; + c.movdqa(vr.get(), XmmConst(value)); + XmmFinalize(vr, rt); + } + else + { + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.add(*addr, i7); + c.not_(*addr); + c.and_(*addr, 0xc); + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)))); + XmmFinalize(vr, rt); + XmmInvalidate(rt); + c.mov(dword_ptr(*cpu_var, *addr, 0, cpu_offset(GPR[rt])), 0x00010203); + } + LOG_OPCODE(); +} + +void SPURecompiler::CDD(u32 rt, u32 ra, s32 i7) +{ + if (ra == 1) + { + // assuming that SP % 16 is always zero + const XmmLink& vr = XmmAlloc(rt); + u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)); + value.u64r[(i7 >> 3) & 0x1] = 0x0001020304050607ull; + c.movdqa(vr.get(), XmmConst(value)); + XmmFinalize(vr, rt); + } + else + { + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.add(*addr, i7); + c.test(*addr, 0x8); + const XmmLink& vr = XmmAlloc(rt); + Label p1(c), p2(c); + c.jnz(p1); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x00010203, 0x04050607, 0x18191a1b, 0x1c1d1e1f)))); + c.jmp(p2); + c.bind(p1); + c.movdqa(vr.get(), XmmConst(u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x00010203, 0x04050607)))); + c.bind(p2); + XmmFinalize(vr, rt); + } + LOG_OPCODE(); +} + +void SPURecompiler::ROTQBII(u32 rt, u32 ra, s32 i7) +{ + XmmInvalidate(rt); + c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); + c.mov(*qw2, *qw0); + c.shld(*qw0, *qw1, i7 & 0x7); + c.shld(*qw1, *qw2, i7 & 0x7); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); + LOG_OPCODE(); +} + +void SPURecompiler::ROTQMBII(u32 rt, u32 ra, s32 i7) +{ + XmmInvalidate(rt); + c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); + c.shrd(*qw0, *qw1, (0 - i7) & 0x7); + c.shr(*qw1, (0 - i7) & 0x7); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); + LOG_OPCODE(); +} + +void SPURecompiler::SHLQBII(u32 rt, u32 ra, s32 i7) +{ + XmmInvalidate(rt); + c.mov(*qw0, cpu_qword(GPR[ra]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[ra]._u64[1])); + c.shld(*qw1, *qw0, i7 & 0x7); + c.shl(*qw0, i7 & 0x7); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw0); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw1); + LOG_OPCODE(); +} + +void SPURecompiler::ROTQBYI(u32 rt, u32 ra, s32 i7) +{ + const int s = i7 & 0xf; + const XmmLink& va = XmmGet(ra, rt); + c.palignr(va.get(), va.get(), 16 - s); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ROTQMBYI(u32 rt, u32 ra, s32 i7) +{ + const int s = (0 - i7) & 0x1f; + const XmmLink& va = XmmGet(ra, rt); + c.psrldq(va.get(), s); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::SHLQBYI(u32 rt, u32 ra, s32 i7) +{ + const int s = i7 & 0x1f; + const XmmLink& va = XmmGet(ra, rt); + c.pslldq(va.get(), s); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::NOP(u32 rt) +{ + LOG_OPCODE(); +} + +void SPURecompiler::CGT(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pcmpgtd(va.get(), vb->read()); + } + else + { + c.pcmpgtd(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::XOR(u32 rt, u32 ra, u32 rb) +{ + // xor + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pxor(va.get(), vb->read()); + } + else + { + c.pxor(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CGTH(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pcmpgtw(va.get(), vb->read()); + } + else + { + c.pcmpgtw(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::EQV(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vb = XmmGet(rb, rt); + c.pxor(vb.get(), XmmConst(u128::from32p(0xffffffff))); + if (const XmmLink* va = XmmRead(ra)) + { + c.pxor(vb.get(), va->read()); + } + else + { + c.pxor(vb.get(), cpu_xmm(GPR[ra])); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CGTB(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pcmpgtb(va.get(), vb->read()); + } + else + { + c.pcmpgtb(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::SUMB(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); + const XmmLink& vi = XmmAlloc(); + c.movdqa(vi.get(), XmmConst(u128::from8p(1))); + c.pmaddubsw(va.get(), vi.get()); + c.pmaddubsw(vb.get(), vi.get()); + c.phaddw(va.get(), vb.get()); + c.pshufb(va.get(), XmmConst(u128::fromV(_mm_set_epi8(15, 14, 7, 6, 13, 12, 5, 4, 11, 10, 3, 2, 9, 8, 1, 0)))); + XmmFinalize(va, rt); + XmmFinalize(vb); + XmmFinalize(vi); + LOG_OPCODE(); +} + +//HGT uses signed values. HLGT uses unsigned values +void SPURecompiler::HGT(u32 rt, s32 ra, s32 rb) +{ + c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); + c.cmp(*addr, cpu_dword(GPR[rb]._s32[3])); + c.setg(addr->r8()); + c.shl(*addr, 24); + c.mov(*pos_var, (CPU.PC >> 2) + 1); + c.or_(*pos_var, *addr); + do_finalize = true; + LOG_OPCODE(); +} + +void SPURecompiler::CLZ(u32 rt, u32 ra) +{ + XmmInvalidate(rt); + c.mov(*qw0, 32 + 31); + for (u32 i = 0; i < 4; i++) + { + c.bsr(*addr, cpu_dword(GPR[ra]._u32[i])); + c.cmovz(*addr, qw0->r32()); + c.xor_(*addr, 31); + c.mov(cpu_dword(GPR[rt]._u32[i]), *addr); + } + LOG_OPCODE(); +} + +void SPURecompiler::XSWD(u32 rt, u32 ra) +{ + c.movsxd(*qw0, cpu_dword(GPR[ra]._s32[0])); + c.movsxd(*qw1, cpu_dword(GPR[ra]._s32[2])); + c.mov(cpu_qword(GPR[rt]._s64[0]), *qw0); + c.mov(cpu_qword(GPR[rt]._s64[1]), *qw1); + XmmInvalidate(rt); + LOG_OPCODE(); +} + +void SPURecompiler::XSHW(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + c.pslld(va.get(), 16); + c.psrad(va.get(), 16); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CNTB(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& v1 = XmmCopy(va); + const XmmLink& vm = XmmAlloc(); + c.psrlq(v1.get(), 4); + c.movdqa(vm.get(), XmmConst(u128::from8p(0xf))); + c.pand(va.get(), vm.get()); + c.pand(v1.get(), vm.get()); + c.movdqa(vm.get(), XmmConst(u128::fromV(_mm_set_epi8(4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0)))); + c.pshufb(vm.get(), va.get()); + c.movdqa(va.get(), XmmConst(u128::fromV(_mm_set_epi8(4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0)))); + c.pshufb(va.get(), v1.get()); + c.paddb(va.get(), vm.get()); + XmmFinalize(va, rt); + XmmFinalize(v1); + XmmFinalize(vm); + LOG_OPCODE(); +} + +void SPURecompiler::XSBH(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + c.psllw(va.get(), 8); + c.psraw(va.get(), 8); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CLGT(u32 rt, u32 ra, u32 rb) +{ + // compare if-greater-than + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vi = XmmAlloc(); + c.movdqa(vi.get(), XmmConst(u128::from32p(0x80000000))); + c.pxor(va.get(), vi.get()); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pxor(vi.get(), vb->read()); + } + else + { + c.pxor(vi.get(), cpu_xmm(GPR[rb])); + } + c.pcmpgtd(va.get(), vi.get()); + XmmFinalize(va, rt); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::ANDC(u32 rt, u32 ra, u32 rb) +{ + // and not + const XmmLink& vb = XmmGet(rb, rt); + if (const XmmLink* va = XmmRead(ra)) + { + c.pandn(vb.get(), va->read()); + } + else + { + c.pandn(vb.get(), cpu_xmm(GPR[ra])); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FCGT(u32 rt, u32 ra, u32 rb) +{ + // reverted less-than + const XmmLink& vb = XmmGet(rb, rt); + if (const XmmLink* va = XmmRead(ra)) + { + c.cmpps(vb.get(), va->read(), 1); + } + else + { + c.cmpps(vb.get(), cpu_xmm(GPR[ra]), 1); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::DFCGT(u32 rt, u32 ra, u32 rb) +{ + return UNK("DFCGT"); +} + +void SPURecompiler::FA(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.addps(va.get(), vb->read()); + } + else + { + c.addps(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FS(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.subps(va.get(), vb->read()); + } + else + { + c.subps(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FM(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.mulps(va.get(), vb->read()); + } + else + { + c.mulps(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CLGTH(u32 rt, u32 ra, u32 rb) +{ + // compare if-greater-than + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vi = XmmAlloc(); + c.movdqa(vi.get(), XmmConst(u128::from16p(0x8000))); + c.pxor(va.get(), vi.get()); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pxor(vi.get(), vb->read()); + } + else + { + c.pxor(vi.get(), cpu_xmm(GPR[rb])); + } + c.pcmpgtw(va.get(), vi.get()); + XmmFinalize(va, rt); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::ORC(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vb = XmmGet(rb, rt); + c.pxor(vb.get(), XmmConst(u128::from32p(0xffffffff))); + if (const XmmLink* va = XmmRead(ra)) + { + c.por(vb.get(), va->read()); + } + else + { + c.por(vb.get(), cpu_xmm(GPR[ra])); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FCMGT(u32 rt, u32 ra, u32 rb) +{ + // reverted less-than + const XmmLink& vb = XmmGet(rb, rt); + const XmmLink& vi = XmmAlloc(); + c.movaps(vi.get(), XmmConst(u128::from32p(0x7fffffff))); + c.andps(vb.get(), vi.get()); // abs + if (const XmmLink* va = XmmRead(ra)) + { + c.andps(vi.get(), va->read()); + } + else + { + c.andps(vi.get(), cpu_xmm(GPR[ra])); + } + c.cmpps(vb.get(), vi.get(), 1); + XmmFinalize(vb, rt); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::DFCMGT(u32 rt, u32 ra, u32 rb) +{ + return UNK("DFCMGT"); +} + +void SPURecompiler::DFA(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.addpd(va.get(), vb->read()); + } + else + { + c.addpd(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::DFS(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.subpd(va.get(), vb->read()); + } + else + { + c.subpd(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::DFM(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.mulpd(va.get(), vb->read()); + } + else + { + c.mulpd(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CLGTB(u32 rt, u32 ra, u32 rb) +{ + // compare if-greater-than + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vi = XmmAlloc(); + c.movdqa(vi.get(), XmmConst(u128::from8p(0x80))); + c.pxor(va.get(), vi.get()); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pxor(vi.get(), vb->read()); + } + else + { + c.pxor(vi.get(), cpu_xmm(GPR[rb])); + } + c.pcmpgtb(va.get(), vi.get()); + XmmFinalize(va, rt); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::HLGT(u32 rt, u32 ra, u32 rb) +{ + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.cmp(*addr, cpu_dword(GPR[rb]._u32[3])); + c.seta(addr->r8()); + c.shl(*addr, 24); + c.mov(*pos_var, (CPU.PC >> 2) + 1); + c.or_(*pos_var, *addr); + do_finalize = true; + LOG_OPCODE(); +} + +void SPURecompiler::DFMA(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vr = XmmGet(rt, rt); + const XmmLink& va = XmmGet(ra); + c.mulpd(va.get(), cpu_xmm(GPR[rb])); + c.addpd(vr.get(), va.get()); + XmmFinalize(vr, rt); + XmmFinalize(va); + LOG_OPCODE(); +} + +void SPURecompiler::DFMS(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vt = (ra == rt) ? XmmCopy(va) : XmmGet(rt); + c.mulpd(va.get(), cpu_xmm(GPR[rb])); + c.subpd(va.get(), vt.get()); + XmmFinalize(va, rt); + XmmFinalize(vt); + LOG_OPCODE(); +} + +void SPURecompiler::DFNMS(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vr = XmmGet(rt, rt); + const XmmLink& va = XmmGet(ra); + c.mulpd(va.get(), cpu_xmm(GPR[rb])); + c.subpd(vr.get(), va.get()); + XmmFinalize(vr, rt); + XmmFinalize(va); + LOG_OPCODE(); +} + +void SPURecompiler::DFNMA(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vt = (ra == rt) ? XmmCopy(va) : XmmGet(rt); + c.mulpd(va.get(), cpu_xmm(GPR[rb])); + c.addpd(vt.get(), va.get()); + c.xorpd(va.get(), va.get()); + c.subpd(va.get(), vt.get()); + XmmFinalize(va, rt); + XmmFinalize(vt); + LOG_OPCODE(); +} + +void SPURecompiler::CEQ(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pcmpeqd(va.get(), vb->read()); + } + else + { + c.pcmpeqd(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::MPYHHU(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); + const XmmLink& va2 = XmmCopy(va); + c.pmulhuw(va.get(), vb.get()); + c.pmullw(va2.get(), vb.get()); + c.pand(va.get(), XmmConst(u128::from32p(0xffff0000))); + c.psrld(va2.get(), 16); + c.por(va.get(), va2.get()); + XmmFinalize(va, rt); + XmmFinalize(vb); + XmmFinalize(va2); + LOG_OPCODE(); +} + +void SPURecompiler::ADDX(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vt = XmmGet(rt); + c.pand(vt.get(), XmmConst(u128::from32p(1))); + c.paddd(vt.get(), cpu_xmm(GPR[ra])); + c.paddd(vt.get(), cpu_xmm(GPR[rb])); + XmmFinalize(vt, rt); + LOG_OPCODE(); +} + +void SPURecompiler::SFX(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vt = XmmGet(rt); + const XmmLink& vb = XmmGet(rb, rt); + c.pandn(vt.get(), XmmConst(u128::from32p(1))); + c.psubd(vb.get(), cpu_xmm(GPR[ra])); + c.psubd(vb.get(), vt.get()); + XmmFinalize(vb, rt); + XmmFinalize(vt); + LOG_OPCODE(); +} + +void SPURecompiler::CGX(u32 rt, u32 ra, u32 rb) //nf +{ + WRAPPER_BEGIN(rt, ra, rb, zz); + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = ((u64)CPU.GPR[ra]._u32[w] + (u64)CPU.GPR[rb]._u32[w] + (u64)(CPU.GPR[rt]._u32[w] & 1)) >> 32; + WRAPPER_END(rt, ra, rb, 0); +} + +void SPURecompiler::BGX(u32 rt, u32 ra, u32 rb) //nf +{ + WRAPPER_BEGIN(rt, ra, rb, zz); + s64 nResult; + + for (int w = 0; w < 4; w++) + { + nResult = (u64)CPU.GPR[rb]._u32[w] - (u64)CPU.GPR[ra]._u32[w] - (u64)(1 - (CPU.GPR[rt]._u32[w] & 1)); + CPU.GPR[rt]._u32[w] = nResult < 0 ? 0 : 1; + } + WRAPPER_END(rt, ra, rb, 0); +} + +void SPURecompiler::MPYHHA(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vt = XmmGet(rt, rt); + const XmmLink& va = XmmGet(ra); + const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); + c.psrld(va.get(), 16); + c.psrld(vb.get(), 16); + c.pmaddwd(va.get(), vb.get()); + c.paddd(vt.get(), va.get()); + XmmFinalize(vt, rt); + XmmFinalize(va); + XmmFinalize(vb); + LOG_OPCODE(); +} + +void SPURecompiler::MPYHHAU(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vt = XmmGet(rt, rt); + const XmmLink& va = XmmGet(ra); + const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); + const XmmLink& va2 = XmmCopy(va); + c.pmulhuw(va.get(), vb.get()); + c.pmullw(va2.get(), vb.get()); + c.pand(va.get(), XmmConst(u128::from32p(0xffff0000))); + c.psrld(va2.get(), 16); + c.paddd(vt.get(), va.get()); + c.paddd(vt.get(), va2.get()); + XmmFinalize(vt, rt); + XmmFinalize(va); + XmmFinalize(vb); + XmmFinalize(va2); + LOG_OPCODE(); +} + +void SPURecompiler::FSCRRD(u32 rt) +{ + // zero (hack) + const XmmLink& v0 = XmmAlloc(rt); + c.pxor(v0.get(), v0.get()); + XmmFinalize(v0, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FESD(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + c.shufps(va.get(), va.get(), 0x8d); // _f[0] = _f[1]; _f[1] = _f[3]; + c.cvtps2pd(va.get(), va.get()); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FRDS(u32 rt, u32 ra) +{ + const XmmLink& va = XmmGet(ra, rt); + c.cvtpd2ps(va.get(), va.get()); + c.shufps(va.get(), va.get(), 0x72); // _f[1] = _f[0]; _f[3] = _f[1]; _f[0] = _f[2] = 0; + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FSCRWR(u32 rt, u32 ra) +{ + // nop (not implemented) + LOG_OPCODE(); +} + +void SPURecompiler::DFTSV(u32 rt, u32 ra, s32 i7) +{ + return UNK("DFTSV"); +} + +void SPURecompiler::FCEQ(u32 rt, u32 ra, u32 rb) +{ + // compare equal + const XmmLink& vb = XmmGet(rb, rt); + if (const XmmLink* va = XmmRead(ra)) + { + c.cmpps(vb.get(), va->read(), 0); + } + else + { + c.cmpps(vb.get(), cpu_xmm(GPR[ra]), 0); + } + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::DFCEQ(u32 rt, u32 ra, u32 rb) +{ + return UNK("DFCEQ"); +} + +void SPURecompiler::MPY(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); + const XmmLink& vi = XmmAlloc(); + c.movdqa(vi.get(), XmmConst(u128::from32p(0xffff))); + c.pand(va.get(), vi.get()); + c.pand(vb.get(), vi.get()); + c.pmaddwd(va.get(), vb.get()); + XmmFinalize(va, rt); + XmmFinalize(vb); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::MPYH(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); + c.psrld(va.get(), 16); + c.pmullw(va.get(), vb.get()); + c.pslld(va.get(), 16); + XmmFinalize(va, rt); + XmmFinalize(vb); + LOG_OPCODE(); +} + +void SPURecompiler::MPYHH(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); + c.psrld(va.get(), 16); + c.psrld(vb.get(), 16); + c.pmaddwd(va.get(), vb.get()); + XmmFinalize(va, rt); + XmmFinalize(vb); + LOG_OPCODE(); +} + +void SPURecompiler::MPYS(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); + c.pmulhw(va.get(), vb.get()); + c.pslld(va.get(), 16); + c.psrad(va.get(), 16); + XmmFinalize(va, rt); + XmmFinalize(vb); + LOG_OPCODE(); +} + +void SPURecompiler::CEQH(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pcmpeqw(va.get(), vb->read()); + } + else + { + c.pcmpeqw(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FCMEQ(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vb = XmmGet(rb, rt); + const XmmLink& vi = XmmAlloc(); + c.movaps(vi.get(), XmmConst(u128::from32p(0x7fffffff))); + c.andps(vb.get(), vi.get()); // abs + if (const XmmLink* va = XmmRead(ra)) + { + c.andps(vi.get(), va->read()); + } + else + { + c.andps(vi.get(), cpu_xmm(GPR[ra])); + } + c.cmpps(vb.get(), vi.get(), 0); // == + XmmFinalize(vb, rt); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::DFCMEQ(u32 rt, u32 ra, u32 rb) +{ + return UNK("DFCMEQ"); +} + +void SPURecompiler::MPYU(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = (ra == rb) ? XmmCopy(va) : XmmGet(rb); + const XmmLink& va2 = XmmCopy(va); + c.pmulhuw(va.get(), vb.get()); + c.pmullw(va2.get(), vb.get()); + c.pslld(va.get(), 16); + c.pand(va2.get(), XmmConst(u128::from32p(0xffff))); + c.por(va.get(), va2.get()); + XmmFinalize(va, rt); + XmmFinalize(vb); + XmmFinalize(va2); + LOG_OPCODE(); +} + +void SPURecompiler::CEQB(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.pcmpeqb(va.get(), vb->read()); + } + else + { + c.pcmpeqb(va.get(), cpu_xmm(GPR[rb])); + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::FI(u32 rt, u32 ra, u32 rb) +{ + const XmmLink& vb = XmmGet(rb); + XmmFinalize(vb, rt); + LOG_OPCODE(); +} + +void SPURecompiler::HEQ(u32 rt, u32 ra, u32 rb) +{ + c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); + c.cmp(*addr, cpu_dword(GPR[rb]._s32[3])); + c.sete(addr->r8()); + c.shl(*addr, 24); + c.mov(*pos_var, (CPU.PC >> 2) + 1); + c.or_(*pos_var, *addr); + do_finalize = true; + LOG_OPCODE(); +} + +void SPURecompiler::CFLTS(u32 rt, u32 ra, s32 i8) +{ + const XmmLink& va = XmmGet(ra, rt); + if (i8 != 173) + { + c.mulps(va.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(static_cast(173 - (i8 & 0xff))))))); // scale + } + const XmmLink& vi = XmmAlloc(); + c.movaps(vi.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(31))))); + c.cmpps(vi.get(), va.get(), 2); + c.cvttps2dq(va.get(), va.get()); // convert to ints with truncation + c.pxor(va.get(), vi.get()); // fix result saturation (0x80000000 -> 0x7fffffff) + XmmFinalize(va, rt); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::CFLTU(u32 rt, u32 ra, s32 i8) +{ + const XmmLink& va = XmmGet(ra, rt); + if (i8 != 173) + { + c.mulps(va.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(static_cast(173 - (i8 & 0xff))))))); // scale + } + c.maxps(va.get(), XmmConst({})); // saturate + const XmmLink& vs = XmmCopy(va); // copy scaled value + const XmmLink& vs2 = XmmCopy(va); + const XmmLink& vs3 = XmmAlloc(); + c.movaps(vs3.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(31))))); + c.subps(vs2.get(), vs3.get()); + c.cmpps(vs3.get(), vs.get(), 2); + c.andps(vs2.get(), vs3.get()); + c.cvttps2dq(va.get(), va.get()); + c.cmpps(vs.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(32)))), 5); + c.cvttps2dq(vs2.get(), vs2.get()); + c.por(va.get(), vs.get()); + c.por(va.get(), vs2.get()); + XmmFinalize(va, rt); + XmmFinalize(vs); + XmmFinalize(vs2); + XmmFinalize(vs3); + LOG_OPCODE(); +} + +void SPURecompiler::CSFLT(u32 rt, u32 ra, s32 i8) +{ + const XmmLink& va = XmmGet(ra, rt); + c.cvtdq2ps(va.get(), va.get()); // convert to floats + if (i8 != 155) + { + c.mulps(va.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(static_cast((i8 & 0xff) - 155)))))); // scale + } + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CUFLT(u32 rt, u32 ra, s32 i8) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& v1 = XmmCopy(va); + c.pand(va.get(), XmmConst(u128::from32p(0x7fffffff))); + c.cvtdq2ps(va.get(), va.get()); // convert to floats + c.psrad(v1.get(), 31); // generate mask from sign bit + c.andps(v1.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(31))))); // generate correction component + c.addps(va.get(), v1.get()); // add correction component + if (i8 != 155) + { + c.mulps(va.get(), XmmConst(u128::fromF(_mm_set1_ps(exp2f(static_cast((i8 & 0xff) - 155)))))); // scale + } + XmmFinalize(va, rt); + XmmFinalize(v1); + LOG_OPCODE(); +} + +void SPURecompiler::BRZ(u32 rt, s32 i16) +{ + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*addr, (CPU.PC >> 2) + 1); + c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); + c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); + c.cmovne(*pos_var, *addr); + LOG_OPCODE(); +} + +void SPURecompiler::STQA(u32 rt, s32 i16) +{ + const u32 lsa = (i16 << 2) & 0x3fff0; + + /*const XmmLink& vt = XmmGet(rt); + c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); + c.movdqa(oword_ptr(*ls_var, lsa), vt.get()); + XmmFinalize(vt);*/ + + c.mov(*qw0, cpu_qword(GPR[rt]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[rt]._u64[1])); + c.bswap(*qw0); + c.bswap(*qw1); + c.mov(qword_ptr(*ls_var, lsa), *qw1); + c.mov(qword_ptr(*ls_var, lsa + 8), *qw0); + + LOG_OPCODE(); +} + +void SPURecompiler::BRNZ(u32 rt, s32 i16) +{ + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*addr, (CPU.PC >> 2) + 1); + c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); + c.cmp(cpu_dword(GPR[rt]._u32[3]), 0); + c.cmove(*pos_var, *addr); + LOG_OPCODE(); +} + +void SPURecompiler::BRHZ(u32 rt, s32 i16) +{ + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*addr, (CPU.PC >> 2) + 1); + c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); + c.cmp(cpu_word(GPR[rt]._u16[6]), 0); + c.cmovnz(*pos_var, *addr); + LOG_OPCODE(); +} + +void SPURecompiler::BRHNZ(u32 rt, s32 i16) +{ + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*addr, (CPU.PC >> 2) + 1); + c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); + c.cmp(cpu_word(GPR[rt]._u16[6]), 0); + c.cmovz(*pos_var, *addr); + LOG_OPCODE(); +} + +void SPURecompiler::STQR(u32 rt, s32 i16) +{ + const u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0; + + /*const XmmLink& vt = XmmGet(rt); + c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); + c.movdqa(oword_ptr(*ls_var, lsa), vt.get()); + XmmFinalize(vt);*/ + + c.mov(*qw0, cpu_qword(GPR[rt]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[rt]._u64[1])); + c.bswap(*qw0); + c.bswap(*qw1); + c.mov(qword_ptr(*ls_var, lsa), *qw1); + c.mov(qword_ptr(*ls_var, lsa + 8), *qw0); + + LOG_OPCODE(); +} + +void SPURecompiler::BRA(s32 i16) +{ + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*pos_var, branchTarget(0, i16) >> 2); + LOG_OPCODE(); +} + +void SPURecompiler::LQA(u32 rt, s32 i16) +{ + XmmInvalidate(rt); + + const u32 lsa = (i16 << 2) & 0x3fff0; + + /*const XmmLink& vt = XmmAlloc(rt); + c.movdqa(vt.get(), oword_ptr(*ls_var, lsa)); + c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); + XmmFinalize(vt, rt);*/ + + c.mov(*qw0, qword_ptr(*ls_var, lsa)); + c.mov(*qw1, qword_ptr(*ls_var, lsa + 8)); + c.bswap(*qw0); + c.bswap(*qw1); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0); + + LOG_OPCODE(); +} + +void SPURecompiler::BRASL(u32 rt, s32 i16) +{ + XmmInvalidate(rt); + + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.xor_(*addr, *addr); // zero + c.mov(cpu_dword(GPR[rt]._u32[0]), *addr); + c.mov(cpu_dword(GPR[rt]._u32[1]), *addr); + c.mov(cpu_dword(GPR[rt]._u32[2]), *addr); + c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4); + c.mov(*pos_var, branchTarget(0, i16) >> 2); + LOG_OPCODE(); +} + +void SPURecompiler::BR(s32 i16) +{ + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); + LOG_OPCODE(); +} + +void SPURecompiler::FSMBI(u32 rt, s32 i16) +{ + if (i16 == 0) + { + // zero + const XmmLink& v0 = XmmAlloc(rt); + c.pxor(v0.get(), v0.get()); + XmmFinalize(v0, rt); + } + else + { + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), g_imm_xmm(fsmb[i16 & 0xffff])); + XmmFinalize(vr, rt); + } + LOG_OPCODE(); +} + +void SPURecompiler::BRSL(u32 rt, s32 i16) +{ + XmmInvalidate(rt); + + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + + c.xor_(*addr, *addr); // zero + c.mov(cpu_dword(GPR[rt]._u32[0]), *addr); + c.mov(cpu_dword(GPR[rt]._u32[1]), *addr); + c.mov(cpu_dword(GPR[rt]._u32[2]), *addr); + c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4); + c.mov(*pos_var, branchTarget(CPU.PC, i16) >> 2); + LOG_OPCODE(); +} + +void SPURecompiler::LQR(u32 rt, s32 i16) +{ + XmmInvalidate(rt); + + const u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0; + + /*const XmmLink& vt = XmmAlloc(rt); + c.movdqa(vt.get(), oword_ptr(*ls_var, lsa)); + c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); + XmmFinalize(vt, rt);*/ + + c.mov(*qw0, qword_ptr(*ls_var, lsa)); + c.mov(*qw1, qword_ptr(*ls_var, lsa + 8)); + c.bswap(*qw0); + c.bswap(*qw1); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0); + + LOG_OPCODE(); +} + +void SPURecompiler::IL(u32 rt, s32 i16) +{ + const XmmLink& vr = XmmAlloc(rt); + if (i16 == 0) + { + c.pxor(vr.get(), vr.get()); + } + else if (i16 == -1) + { + c.pcmpeqd(vr.get(), vr.get()); + } + else + { + c.movdqa(vr.get(), XmmConst(u128::from32p(i16))); + } + XmmFinalize(vr, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ILHU(u32 rt, s32 i16) +{ + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::from32p(i16 << 16))); + XmmFinalize(vr, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ILH(u32 rt, s32 i16) +{ + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::from32p(i16))); + XmmFinalize(vr, rt); + LOG_OPCODE(); +} + +void SPURecompiler::IOHL(u32 rt, s32 i16) +{ + const XmmLink& vt = XmmGet(rt, rt); + c.por(vt.get(), XmmConst(u128::from32p(i16 & 0xffff))); + XmmFinalize(vt, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ORI(u32 rt, u32 ra, s32 i10) +{ + if (i10 == -1) + { + // fill with 1 + const XmmLink& v1 = XmmAlloc(rt); + c.pcmpeqd(v1.get(), v1.get()); + XmmFinalize(v1, rt); + } + else if (i10 == 0) + { + if (rt != ra) + { + // mov + const XmmLink& va = XmmGet(ra, rt); + XmmFinalize(va, rt); + } + // else nop + } + else + { + const XmmLink& va = XmmGet(ra, rt); + c.por(va.get(), XmmConst(u128::from32p(i10))); + XmmFinalize(va, rt); + } + LOG_OPCODE(); +} + +void SPURecompiler::ORHI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra, rt); + c.por(va.get(), XmmConst(u128::from16p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ORBI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra, rt); + c.por(va.get(), XmmConst(u128::from8p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::SFI(u32 rt, u32 ra, s32 i10) +{ + if (i10 == 0) + { + // zero + const XmmLink& v0 = XmmAlloc(rt); + c.pxor(v0.get(), v0.get()); + c.psubd(v0.get(), cpu_xmm(GPR[ra])); + XmmFinalize(v0, rt); + } + else if (i10 == -1) + { + // fill with 1 + const XmmLink& v1 = XmmAlloc(rt); + c.pcmpeqd(v1.get(), v1.get()); + c.psubd(v1.get(), cpu_xmm(GPR[ra])); + XmmFinalize(v1, rt); + } + else + { + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::from32p(i10))); + c.psubd(vr.get(), cpu_xmm(GPR[ra])); + XmmFinalize(vr, rt); + } + LOG_OPCODE(); +} + +void SPURecompiler::SFHI(u32 rt, u32 ra, s32 i10) +{ + if (i10 == 0) + { + // zero + const XmmLink& v0 = XmmAlloc(rt); + c.pxor(v0.get(), v0.get()); + c.psubw(v0.get(), cpu_xmm(GPR[ra])); + XmmFinalize(v0, rt); + } + else if (i10 == -1) + { + // fill with 1 + const XmmLink& v1 = XmmAlloc(rt); + c.pcmpeqw(v1.get(), v1.get()); + c.psubw(v1.get(), cpu_xmm(GPR[ra])); + XmmFinalize(v1, rt); + } + else + { + const XmmLink& vr = XmmAlloc(rt); + c.movdqa(vr.get(), XmmConst(u128::from16p(i10))); + c.psubw(vr.get(), cpu_xmm(GPR[ra])); + XmmFinalize(vr, rt); + } + LOG_OPCODE(); +} + +void SPURecompiler::ANDI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra, rt); + c.pand(va.get(), XmmConst(u128::from32p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ANDHI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra, rt); + c.pand(va.get(), XmmConst(u128::from16p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::ANDBI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra, rt); + c.pand(va.get(), XmmConst(u128::from8p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::AI(u32 rt, u32 ra, s32 i10) +{ + // add + const XmmLink& va = XmmGet(ra, rt); + c.paddd(va.get(), XmmConst(u128::from32p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::AHI(u32 rt, u32 ra, s32 i10) +{ + // add + const XmmLink& va = XmmGet(ra, rt); + c.paddw(va.get(), XmmConst(u128::from16p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::STQD(u32 rt, s32 i10, u32 ra) // i10 is shifted left by 4 while decoding +{ + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + if (i10) c.add(*addr, i10); + c.and_(*addr, 0x3fff0); + + /*const XmmLink& vt = XmmGet(rt); + c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); + c.movdqa(oword_ptr(*ls_var, *addr), vt.get()); + XmmFinalize(vt);*/ + + c.mov(*qw0, cpu_qword(GPR[rt]._u64[0])); + c.mov(*qw1, cpu_qword(GPR[rt]._u64[1])); + c.bswap(*qw0); + c.bswap(*qw1); + c.mov(qword_ptr(*ls_var, *addr, 0, 0), *qw1); + c.mov(qword_ptr(*ls_var, *addr, 0, 8), *qw0); + + LOG_OPCODE(); +} + +void SPURecompiler::LQD(u32 rt, s32 i10, u32 ra) // i10 is shifted left by 4 while decoding +{ + XmmInvalidate(rt); + + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + if (i10) c.add(*addr, i10); + c.and_(*addr, 0x3fff0); + + /*const XmmLink& vt = XmmAlloc(rt); + c.movdqa(vt.get(), oword_ptr(*ls_var, *addr)); + c.pshufb(vt.get(), XmmConst(_mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f))); + XmmFinalize(vt, rt);*/ + + c.mov(*qw0, qword_ptr(*ls_var, *addr, 0, 0)); + c.mov(*qw1, qword_ptr(*ls_var, *addr, 0, 8)); + c.bswap(*qw0); + c.bswap(*qw1); + c.mov(cpu_qword(GPR[rt]._u64[0]), *qw1); + c.mov(cpu_qword(GPR[rt]._u64[1]), *qw0); + + LOG_OPCODE(); +} + +void SPURecompiler::XORI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pxor(va.get(), XmmConst(u128::from32p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::XORHI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pxor(va.get(), XmmConst(u128::from16p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::XORBI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pxor(va.get(), XmmConst(u128::from8p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CGTI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pcmpgtd(va.get(), XmmConst(u128::from32p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CGTHI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pcmpgtw(va.get(), XmmConst(u128::from16p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CGTBI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pcmpgtb(va.get(), XmmConst(u128::from8p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::HGTI(u32 rt, u32 ra, s32 i10) +{ + c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); + c.cmp(*addr, i10); + c.setg(addr->r8()); + c.shl(*addr, 24); + c.mov(*pos_var, (CPU.PC >> 2) + 1); + c.or_(*pos_var, *addr); + do_finalize = true; + LOG_OPCODE(); +} + +void SPURecompiler::CLGTI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pxor(va.get(), XmmConst(u128::from32p(0x80000000))); + c.pcmpgtd(va.get(), XmmConst(u128::from32p((u32)i10 - 0x80000000))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CLGTHI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pxor(va.get(), XmmConst(u128::from16p(0x8000))); + c.pcmpgtw(va.get(), XmmConst(u128::from16p((u16)i10 - 0x8000))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CLGTBI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.psubb(va.get(), XmmConst(u128::from8p(0x80))); + c.pcmpgtb(va.get(), XmmConst(u128::from8p((s8)i10 - 0x80))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::HLGTI(u32 rt, u32 ra, s32 i10) +{ + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.cmp(*addr, i10); + c.seta(addr->r8()); + c.shl(*addr, 24); + c.mov(*pos_var, (CPU.PC >> 2) + 1); + c.or_(*pos_var, *addr); + do_finalize = true; + LOG_OPCODE(); +} + +void SPURecompiler::MPYI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra, rt); + c.pmaddwd(va.get(), XmmConst(u128::from32p(i10 & 0xffff))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::MPYUI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vi = XmmAlloc(); + const XmmLink& va2 = XmmCopy(va); + c.movdqa(vi.get(), XmmConst(u128::from32p(i10 & 0xffff))); + c.pmulhuw(va.get(), vi.get()); + c.pmullw(va2.get(), vi.get()); + c.pslld(va.get(), 16); + c.por(va.get(), va2.get()); + XmmFinalize(va, rt); + XmmFinalize(vi); + XmmFinalize(va2); + LOG_OPCODE(); +} + +void SPURecompiler::CEQI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pcmpeqd(va.get(), XmmConst(u128::from32p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CEQHI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pcmpeqw(va.get(), XmmConst(u128::from16p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::CEQBI(u32 rt, u32 ra, s32 i10) +{ + const XmmLink& va = XmmGet(ra); + c.pcmpeqb(va.get(), XmmConst(u128::from8p(i10))); + XmmFinalize(va, rt); + LOG_OPCODE(); +} + +void SPURecompiler::HEQI(u32 rt, u32 ra, s32 i10) +{ + c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); + c.cmp(*addr, i10); + c.sete(addr->r8()); + c.shl(*addr, 24); + c.mov(*pos_var, (CPU.PC >> 2) + 1); + c.or_(*pos_var, *addr); + do_finalize = true; + LOG_OPCODE(); +} + +void SPURecompiler::HBRA(s32 ro, s32 i16) +{ + //i16 is shifted left by 2 while decoding + LOG_OPCODE(); +} + +void SPURecompiler::HBRR(s32 ro, s32 i16) +{ + LOG_OPCODE(); +} + +void SPURecompiler::ILA(u32 rt, u32 i18) +{ + const XmmLink& vr = XmmAlloc(rt); + if (i18 == 0) + { + c.pxor(vr.get(), vr.get()); + } + else + { + c.movdqa(vr.get(), XmmConst(u128::from32p(i18 & 0x3ffff))); + } + XmmFinalize(vr, rt); + LOG_OPCODE(); +} + +void SPURecompiler::SELB(u32 rt, u32 ra, u32 rb, u32 rc) +{ + const XmmLink& vb = XmmGet(rb); + const XmmLink& vc = XmmGet(rc); + c.pand(vb.get(), vc.get()); + c.pandn(vc.get(), cpu_xmm(GPR[ra])); + c.por(vb.get(), vc.get()); + XmmFinalize(vb, rt); + XmmFinalize(vc); + LOG_OPCODE(); +} + +void SPURecompiler::SHUFB(u32 rt, u32 ra, u32 rb, u32 rc) +{ + const XmmLink& v0 = XmmGet(rc); // v0 = mask + const XmmLink& v1 = XmmAlloc(); + const XmmLink& v2 = XmmCopy(v0); // v2 = mask + const XmmLink& v3 = XmmAlloc(); + const XmmLink& v4 = XmmAlloc(); + const XmmLink& vFF = XmmAlloc(rt); + // generate specific values: + c.movdqa(v1.get(), XmmConst(u128::from8p(0xe0))); // v1 = 11100000 + c.movdqa(v3.get(), XmmConst(u128::from8p(0x80))); // v3 = 10000000 + c.pand(v2.get(), v1.get()); // filter mask v2 = mask & 11100000 + c.movdqa(vFF.get(), v2.get()); // and copy vFF = mask & 11100000 + c.movdqa(v4.get(), XmmConst(u128::from8p(0xc0))); // v4 = 11000000 + c.pcmpeqb(vFF.get(), v4.get()); // gen 0xff vFF = (mask & 11100000 == 11000000) ? 0xff : 0 + c.movdqa(v4.get(), v2.get()); // copy again v4 = mask & 11100000 + c.pand(v4.get(), v3.get()); // filter mask v4 = mask & 10000000 + c.pcmpeqb(v2.get(), v1.get()); // v2 = (mask & 11100000 == 11100000) ? 0xff : 0 + c.pcmpeqb(v4.get(), v3.get()); // v4 = (mask & 10000000 == 10000000) ? 0xff : 0 + c.pand(v2.get(), v3.get()); // generate 0x80 v2 = (mask & 11100000 == 11100000) ? 0x80 : 0 + c.por(vFF.get(), v2.get()); // merge 0xff, 0x80 vFF = (mask & 11100000 == 11000000) ? 0xff : (mask & 11100000 == 11100000) ? 0x80 : 0 + c.pandn(v1.get(), v0.get()); // filter mask v1 = mask & 00011111 + // select bytes from [rb]: + c.movdqa(v2.get(), XmmConst(u128::from8p(0x0f))); // v2 = 00001111 + c.pxor(v1.get(), XmmConst(u128::from8p(0x10))); // v1 = (mask & 00011111) ^ 00010000 + c.psubb(v2.get(), v1.get()); // v2 = 00001111 - ((mask & 00011111) ^ 00010000) + c.movdqa(v1.get(), cpu_xmm(GPR[rb])); // v1 = rb + c.pshufb(v1.get(), v2.get()); // v1 = select(rb, 00001111 - ((mask & 00011111) ^ 00010000)) + // select bytes from [ra]: + c.pxor(v2.get(), XmmConst(u128::from8p(0xf0))); // v2 = (00001111 - ((mask & 00011111) ^ 00010000)) ^ 11110000 + c.movdqa(v3.get(), cpu_xmm(GPR[ra])); // v3 = ra + c.pshufb(v3.get(), v2.get()); // v3 = select(ra, (00001111 - ((mask & 00011111) ^ 00010000)) ^ 11110000) + c.por(v1.get(), v3.get()); // v1 = select(rb, 00001111 - ((mask & 00011111) ^ 00010000)) | (v3) + c.pandn(v4.get(), v1.get()); // filter result v4 = v1 & ((mask & 10000000 == 10000000) ? 0 : 0xff) + c.por(vFF.get(), v4.get()); // final merge vFF = (mask & 10000000 == 10000000) ? ((mask & 11100000 == 11000000) ? 0xff : (mask & 11100000 == 11100000) ? 0x80 : 0) : (v1) + XmmFinalize(vFF, rt); + XmmFinalize(v4); + XmmFinalize(v3); + XmmFinalize(v2); + XmmFinalize(v1); + XmmFinalize(v0); + LOG_OPCODE(); +} + +void SPURecompiler::MPYA(u32 rt, u32 ra, u32 rb, u32 rc) +{ + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vb = XmmGet(rb); + const XmmLink& vi = XmmAlloc(); + c.movdqa(vi.get(), XmmConst(u128::from32p(0xffff))); + c.pand(va.get(), vi.get()); + c.pand(vb.get(), vi.get()); + c.pmaddwd(va.get(), vb.get()); + c.paddd(va.get(), cpu_xmm(GPR[rc])); + XmmFinalize(va, rt); + XmmFinalize(vb); + XmmFinalize(vi); + LOG_OPCODE(); +} + +void SPURecompiler::FNMS(u32 rt, u32 ra, u32 rb, u32 rc) +{ + const XmmLink& va = XmmGet(ra); + const XmmLink& vc = (ra == rc) ? XmmCopy(va, rt) : XmmGet(rc, rt); + + if (ra == rb) + { + c.mulps(va.get(), va.get()); + } + else if (rb == rc) + { + c.mulps(va.get(), vc.get()); + } + else + { + if (const XmmLink* vb = XmmRead(rb)) + { + c.mulps(va.get(), vb->read()); + } + else + { + c.mulps(va.get(), cpu_xmm(GPR[rb])); + } + } + c.subps(vc.get(), va.get()); + XmmFinalize(vc, rt); + XmmFinalize(va); + LOG_OPCODE(); +} + +void SPURecompiler::FMA(u32 rt, u32 ra, u32 rb, u32 rc) +{ + if (ra != rb && rb != rc && rc != ra) + { + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.mulps(va.get(), vb->read()); + } + else + { + c.mulps(va.get(), cpu_xmm(GPR[rb])); + } + if (const XmmLink* vc = XmmRead(rc)) + { + c.addps(va.get(), vc->read()); + } + else + { + c.addps(va.get(), cpu_xmm(GPR[rc])); + } + XmmFinalize(va, rt); + } + else if (ra == rb && rb == rc) + { + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vc = XmmCopy(va); + c.mulps(va.get(), va.get()); + c.addps(va.get(), vc.get()); + XmmFinalize(va, rt); + XmmFinalize(vc); + } + else if (ra == rb) + { + const XmmLink& va = XmmGet(ra, rt); + c.mulps(va.get(), va.get()); + if (const XmmLink* vc = XmmRead(rc)) + { + c.addps(va.get(), vc->read()); + } + else + { + c.addps(va.get(), cpu_xmm(GPR[rc])); + } + XmmFinalize(va, rt); + } + else if (rb == rc) + { + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vc = XmmRead(rc)) + { + c.mulps(va.get(), vc->read()); + c.addps(va.get(), vc->read()); + } + else + { + const XmmLink& vb = XmmGet(rb, rb); + c.mulps(va.get(), vb.get()); + c.addps(va.get(), vb.get()); + XmmFinalize(vb, rb); + } + XmmFinalize(va, rt); + } + else if (ra == rc) + { + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vc = XmmCopy(va); + if (const XmmLink* vb = XmmRead(rb)) + { + c.mulps(va.get(), vb->read()); + } + else + { + c.mulps(va.get(), cpu_xmm(GPR[rb])); + } + c.addps(va.get(), vc.get()); + XmmFinalize(va, rt); + XmmFinalize(vc); + } + else + { + throw "FMA: invalid case"; // should never happen + } + LOG_OPCODE(); +} + +void SPURecompiler::FMS(u32 rt, u32 ra, u32 rb, u32 rc) +{ + if (ra != rb && rb != rc && rc != ra) + { + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vb = XmmRead(rb)) + { + c.mulps(va.get(), vb->read()); + } + else + { + c.mulps(va.get(), cpu_xmm(GPR[rb])); + } + if (const XmmLink* vc = XmmRead(rc)) + { + c.subps(va.get(), vc->read()); + } + else + { + c.subps(va.get(), cpu_xmm(GPR[rc])); + } + XmmFinalize(va, rt); + } + else if (ra == rb && rb == rc) + { + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vc = XmmCopy(va); + c.mulps(va.get(), va.get()); + c.subps(va.get(), vc.get()); + XmmFinalize(va, rt); + XmmFinalize(vc); + } + else if (ra == rb) + { + const XmmLink& va = XmmGet(ra, rt); + c.mulps(va.get(), va.get()); + if (const XmmLink* vc = XmmRead(rc)) + { + c.subps(va.get(), vc->read()); + } + else + { + c.subps(va.get(), cpu_xmm(GPR[rc])); + } + XmmFinalize(va, rt); + } + else if (rb == rc) + { + const XmmLink& va = XmmGet(ra, rt); + if (const XmmLink* vc = XmmRead(rc)) + { + c.mulps(va.get(), vc->read()); + c.subps(va.get(), vc->read()); + } + else + { + const XmmLink& vb = XmmGet(rb, rb); + c.mulps(va.get(), vb.get()); + c.subps(va.get(), vb.get()); + XmmFinalize(vb, rb); + } + XmmFinalize(va, rt); + } + else if (ra == rc) + { + const XmmLink& va = XmmGet(ra, rt); + const XmmLink& vc = XmmCopy(va); + if (const XmmLink* vb = XmmRead(rb)) + { + c.mulps(va.get(), vb->read()); + } + else + { + c.mulps(va.get(), cpu_xmm(GPR[rb])); + } + c.subps(va.get(), vc.get()); + XmmFinalize(va, rt); + XmmFinalize(vc); + } + else + { + throw "FMS: invalid case"; // should never happen + } + LOG_OPCODE(); +} + +void SPURecompiler::UNK(u32 code, u32 opcode, u32 gcode) +{ + UNK(fmt::Format("Unimplemented opcode! (0x%08x, 0x%x, 0x%x)", code, opcode, gcode)); +} + +void SPURecompiler::UNK(const std::string& err) +{ + LOG_ERROR(Log::SPU, "%s #pc: 0x%x", err.c_str(), CPU.PC); + c.mov(cpu_dword(PC), CPU.PC); + do_finalize = true; + Emu.Pause(); +} diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 6176add701..29f209c3f4 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -50,7 +50,7 @@ public: } } - __forceinline spu_inter_func_t operator [] (u32 opcode) const + force_inline spu_inter_func_t operator [] (u32 opcode) const { return funcs[opcode >> 21]; } @@ -760,7 +760,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value) LV2_LOCK; - const auto ef = Emu.GetIdManager().GetIDData(data); + const auto ef = Emu.GetIdManager().get(data); if (!ef) { @@ -806,7 +806,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value) LV2_LOCK; - const auto ef = Emu.GetIdManager().GetIDData(data); + const auto ef = Emu.GetIdManager().get(data); if (!ef) { @@ -1054,7 +1054,7 @@ void SPUThread::stop_and_signal(u32 code) LV2_LOCK; - std::shared_ptr queue; + std::shared_ptr queue; for (auto& v : this->spuq) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 15045ebb6c..b76fda8e1c 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -4,7 +4,7 @@ #include "Emu/Cell/SPUContext.h" #include "MFC.h" -struct event_queue_t; +struct lv2_event_queue_t; struct spu_group_t; // SPU Channels @@ -137,7 +137,7 @@ union spu_channel_t u32 value; }; - atomic_t sync_var; // atomic variable + atomic sync_var; // atomic variable public: bool push(u32 value) @@ -223,8 +223,8 @@ struct spu_channel_4_t u32 value2; }; - atomic_le_t sync_var; - atomic_le_t value3; + atomic sync_var; + atomic value3; public: void clear() @@ -280,10 +280,10 @@ public: struct spu_interrupt_tag_t { - atomic_le_t mask; - atomic_le_t stat; + atomic mask; + atomic stat; - atomic_le_t assigned; + atomic assigned; std::mutex handler_mutex; std::condition_variable cond; @@ -338,7 +338,7 @@ struct g_spu_imm_table_t } } - __forceinline __m128 operator [] (s32 scale) const + force_inline __m128 operator [] (s32 scale) const { return m_data[scale + 155]; } @@ -527,22 +527,22 @@ public: spu_channel_t ch_snr2; // SPU Signal Notification Register 2 u32 ch_event_mask; - atomic_le_t ch_event_stat; + atomic ch_event_stat; u64 ch_dec_start_timestamp; // timestamp of writing decrementer value u32 ch_dec_value; // written decrementer value - atomic_le_t run_ctrl; // SPU Run Control register (only provided to get latest data written) - atomic_le_t status; // SPU Status register - atomic_le_t npc; // SPU Next Program Counter register + atomic run_ctrl; // SPU Run Control register (only provided to get latest data written) + atomic status; // SPU Status register + atomic npc; // SPU Next Program Counter register spu_interrupt_tag_t int0; // SPU Class 0 Interrupt Management spu_interrupt_tag_t int2; // SPU Class 2 Interrupt Management std::weak_ptr tg; // SPU Thread Group - std::array>, 32> spuq; // Event Queue Keys for SPU Thread - std::weak_ptr spup[64]; // SPU Ports + std::array>, 32> spuq; // Event Queue Keys for SPU Thread + std::weak_ptr spup[64]; // SPU Ports void write_snr(bool number, u32 value) { diff --git a/rpcs3/Emu/Event.cpp b/rpcs3/Emu/Event.cpp index 29df4196fa..531d974fe7 100644 --- a/rpcs3/Emu/Event.cpp +++ b/rpcs3/Emu/Event.cpp @@ -28,9 +28,9 @@ bool EventManager::CheckKey(u64 key) return eq_map.find(key) != eq_map.end(); } -bool EventManager::RegisterKey(std::shared_ptr& data, u64 key) +bool EventManager::RegisterKey(const std::shared_ptr& data) { - if (!key) + if (!data->key) { // always ok return true; @@ -38,12 +38,12 @@ bool EventManager::RegisterKey(std::shared_ptr& data, u64 key) std::lock_guard lock(m_lock); - if (eq_map.find(key) != eq_map.end()) + if (eq_map.find(data->key) != eq_map.end()) { return false; } - eq_map[key] = data; + eq_map[data->key] = data; return true; } @@ -68,7 +68,7 @@ bool EventManager::UnregisterKey(u64 key) return false; } -std::shared_ptr EventManager::GetEventQueue(u64 key) +std::shared_ptr EventManager::GetEventQueue(u64 key) { if (!key) { diff --git a/rpcs3/Emu/Event.h b/rpcs3/Emu/Event.h index bd12001ae3..6569f54a55 100644 --- a/rpcs3/Emu/Event.h +++ b/rpcs3/Emu/Event.h @@ -1,18 +1,25 @@ #pragma once -struct event_queue_t; +struct lv2_event_queue_t; class EventManager { std::mutex m_lock; - std::unordered_map> eq_map; + std::unordered_map> eq_map; public: void Init(); void Clear(); bool CheckKey(u64 key); - bool RegisterKey(std::shared_ptr& data, u64 key); + bool RegisterKey(const std::shared_ptr& data); bool UnregisterKey(u64 key); - std::shared_ptr GetEventQueue(u64 key); + template std::shared_ptr MakeEventQueue(Args&&... args) + { + const auto queue = std::make_shared(args...); + + return RegisterKey(queue) ? queue : nullptr; + } + + std::shared_ptr GetEventQueue(u64 key); }; diff --git a/rpcs3/Emu/FS/vfsStream.h b/rpcs3/Emu/FS/vfsStream.h index 28e775c2cd..8fa63d0967 100644 --- a/rpcs3/Emu/FS/vfsStream.h +++ b/rpcs3/Emu/FS/vfsStream.h @@ -19,14 +19,14 @@ struct vfsStream virtual u64 Write(const void* src, u64 count) = 0; - template __forceinline bool SWrite(const T& data, u64 count = sizeof(T)) + template force_inline bool SWrite(const T& data, u64 count = sizeof(T)) { return Write(&data, count) == count; } virtual u64 Read(void* dst, u64 count) = 0; - template __forceinline bool SRead(T& data, u64 count = sizeof(T)) + template force_inline bool SRead(T& data, u64 count = sizeof(T)) { return Read(&data, count) == count; } diff --git a/rpcs3/Emu/HDD/HDD.h b/rpcs3/Emu/HDD/HDD.h index 22668d9474..4274bd66d4 100644 --- a/rpcs3/Emu/HDD/HDD.h +++ b/rpcs3/Emu/HDD/HDD.h @@ -82,7 +82,7 @@ class vfsHDDFile void WriteEntry(u64 block, const vfsHDD_Entry& data, const std::string& name); - __forceinline u32 GetMaxNameLen() const + force_inline u32 GetMaxNameLen() const { return m_hdd_info.block_size - sizeof(vfsHDD_Entry); } @@ -149,7 +149,7 @@ class vfsHDD : public vfsFileBase public: vfsHDD(vfsDevice* device, const std::string& hdd_path); - __forceinline u32 GetMaxNameLen() const + force_inline u32 GetMaxNameLen() const { return m_hdd_info.block_size - sizeof(vfsHDD_Entry); } diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index 3921327ca6..6cee9d4bfc 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -2,210 +2,174 @@ #define ID_MANAGER_INCLUDED -enum IDType +// ID type +enum : u32 { - // Special objects - TYPE_MEM, - TYPE_MUTEX, - TYPE_COND, - TYPE_RWLOCK, - TYPE_INTR_TAG, - TYPE_INTR_SERVICE_HANDLE, - TYPE_EVENT_QUEUE, - TYPE_EVENT_PORT, - TYPE_TRACE, - TYPE_SPUIMAGE, - TYPE_PRX, - TYPE_SPUPORT, - TYPE_LWMUTEX, - TYPE_TIMER, - TYPE_SEMAPHORE, - TYPE_FS_FILE, - TYPE_FS_DIR, - TYPE_LWCOND, - TYPE_EVENT_FLAG, - - // Any other objects - TYPE_OTHER, + ID_TYPE_NONE = 0, }; -class ID final +// Helper template to detect type +template struct ID_type { - const std::type_info& m_info; - std::shared_ptr m_data; - IDType m_type; + //static_assert(sizeof(T) == 0, "ID type not registered (use REG_ID_TYPE)"); + static const u32 type = ID_TYPE_NONE; // default type +}; + +class ID_data_t final +{ public: - template ID(std::shared_ptr& data, const IDType type) - : m_info(typeid(T)) - , m_data(data) - , m_type(type) + const std::shared_ptr data; + const std::type_info& info; + const u32 type; + + template force_inline ID_data_t(std::shared_ptr data, u32 type) + : data(std::move(data)) + , info(typeid(T)) + , type(type) { } - ID() - : m_info(typeid(void)) - , m_data(nullptr) - , m_type(TYPE_OTHER) + ID_data_t(const ID_data_t& right) = delete; + + ID_data_t& operator =(const ID_data_t& right) = delete; + + ID_data_t(ID_data_t&& right) + : data(std::move(const_cast&>(right.data))) + , info(right.info) + , type(right.type) { } - ID(const ID& right) = delete; - - ID(ID&& right) - : m_info(right.m_info) - , m_data(right.m_data) - , m_type(right.m_type) - { - right.m_data = nullptr; - right.m_type = TYPE_OTHER; - } - - ID& operator=(ID&& other) = delete; - - const std::type_info& GetInfo() const - { - return m_info; - } - - template std::shared_ptr GetData() const - { - return std::static_pointer_cast(m_data); - } - - IDType GetType() const - { - return m_type; - } + ID_data_t& operator =(ID_data_t&& other) = delete; }; -class IdManager +class ID_manager { - static const u32 s_first_id = 1; - static const u32 s_max_id = -1; - - std::unordered_map m_id_map; - std::set m_types[TYPE_OTHER]; std::mutex m_mutex; - u32 m_cur_id = s_first_id; + std::unordered_map m_id_map; + u32 m_cur_id = 1; // first ID public: - template bool CheckID(const u32 id) + // check if ID exists and has specified type + template bool check_id(const u32 id) { std::lock_guard lock(m_mutex); auto f = m_id_map.find(id); - return f != m_id_map.end() && f->second.GetInfo() == typeid(T); + return f != m_id_map.end() && f->second.info == typeid(T); } - void Clear() + // must be called from the constructor called through make() to get further ID of current object + u32 get_cur_id() + { + // if called correctly from make(), the mutex is locked + // if called illegally, the mutex is unlocked with high probability (wrong ID is returned otherwise) + + if (m_mutex.try_lock()) + { + // schedule unlocking + std::lock_guard lock(m_mutex, std::adopt_lock); + + throw "Invalid get_cur_id() usage"; + } + + return m_cur_id; + } + + void clear() { std::lock_guard lock(m_mutex); m_id_map.clear(); - m_cur_id = s_first_id; + m_cur_id = 1; // first ID } - template u32 GetNewID(std::shared_ptr& data, const IDType type = TYPE_OTHER) + // add new ID using existing std::shared_ptr (not recommended, use make() instead) + template u32 add(std::shared_ptr data, u32 type = ID_type::type) { std::lock_guard lock(m_mutex); - m_id_map.emplace(m_cur_id, ID(data, type)); - - if (type < TYPE_OTHER) - { - m_types[type].insert(m_cur_id); - } + m_id_map.emplace(m_cur_id, ID_data_t(std::move(data), type)); return m_cur_id++; } - template std::shared_ptr GetIDData(const u32 id) + // add new ID of specified type with specified constructor arguments (passed to std::make_shared<>) + template u32 make(Args&&... args) + { + std::lock_guard lock(m_mutex); + + const u32 type = ID_type::type; + + m_id_map.emplace(m_cur_id, ID_data_t(std::make_shared(args...), type)); + + return m_cur_id++; + } + + template std::shared_ptr get(u32 id) { std::lock_guard lock(m_mutex); auto f = m_id_map.find(id); - if (f == m_id_map.end() || f->second.GetInfo() != typeid(T)) + if (f == m_id_map.end() || f->second.info != typeid(T)) { return nullptr; } - return f->second.GetData(); + return std::static_pointer_cast(f->second.data); } - bool HasID(const u32 id) - { - std::lock_guard lock(m_mutex); - - return m_id_map.find(id) != m_id_map.end(); - } - - IDType GetIDType(const u32 id) + template bool remove(u32 id) { std::lock_guard lock(m_mutex); auto item = m_id_map.find(id); - if (item == m_id_map.end()) - { - return TYPE_OTHER; - } - - return item->second.GetType(); - } - - template bool RemoveID(const u32 id) - { - std::lock_guard lock(m_mutex); - - auto item = m_id_map.find(id); - - if (item == m_id_map.end() || item->second.GetInfo() != typeid(T)) + if (item == m_id_map.end() || item->second.info != typeid(T)) { return false; } - if (item->second.GetType() < TYPE_OTHER) - { - m_types[item->second.GetType()].erase(id); - } - m_id_map.erase(item); return true; } - u32 GetTypeCount(IDType type) + u32 get_count_by_type(u32 type) { std::lock_guard lock(m_mutex); - if (type < TYPE_OTHER) + u32 result = 0; + + for (auto& v : m_id_map) { - return (u32)m_types[type].size(); - } - else - { - assert(!"Invalid ID type"); - return 0; + if (v.second.type == type) + { + result++; + } } + + return result; } - std::set GetTypeIDs(IDType type) + std::set get_IDs_by_type(u32 type) { - // you cannot simply return reference to existing set std::lock_guard lock(m_mutex); - if (type < TYPE_OTHER) + std::set result; + + for (auto& v : m_id_map) { - return m_types[type]; - } - else - { - assert(!"Invalid ID type"); - return std::set{}; + if (v.second.type == type) + { + result.insert(v.first); + } } + + return result; } }; diff --git a/rpcs3/Emu/Memory/atomic.h b/rpcs3/Emu/Memory/atomic.h index f53214792e..b09cf04359 100644 --- a/rpcs3/Emu/Memory/atomic.h +++ b/rpcs3/Emu/Memory/atomic.h @@ -1,11 +1,5 @@ #pragma once -#undef InterlockedExchange -#undef InterlockedCompareExchange -#undef InterlockedOr -#undef InterlockedAnd -#undef InterlockedXor - template struct _to_atomic_subtype { @@ -51,73 +45,74 @@ union _atomic_base type data; // unsafe direct access subtype sub_data; // unsafe direct access to substitute type - __forceinline static const subtype to_subtype(const type& value) + force_inline static const subtype to_subtype(const type& value) { return reinterpret_cast(value); } - __forceinline static const type from_subtype(const subtype value) + force_inline static const type from_subtype(const subtype value) { return reinterpret_cast(value); } - __forceinline static type& to_type(subtype& value) + force_inline static type& to_type(subtype& value) { return reinterpret_cast(value); } public: // atomically compare data with cmp, replace with exch if equal, return previous data value anyway - __forceinline const type compare_and_swap(const type& cmp, const type& exch) volatile + force_inline const type compare_and_swap(const type& cmp, const type& exch) volatile { - return from_subtype(InterlockedCompareExchange(&sub_data, to_subtype(exch), to_subtype(cmp))); + return from_subtype(sync_val_compare_and_swap(&sub_data, to_subtype(cmp), to_subtype(exch))); } // atomically compare data with cmp, replace with exch if equal, return true if data was replaced - __forceinline bool compare_and_swap_test(const type& cmp, const type& exch) volatile + force_inline bool compare_and_swap_test(const type& cmp, const type& exch) volatile { - return InterlockedCompareExchangeTest(&sub_data, to_subtype(exch), to_subtype(cmp)); + return sync_bool_compare_and_swap(&sub_data, to_subtype(cmp), to_subtype(exch)); } // read data with memory barrier - __forceinline const type read_sync() const volatile + force_inline const type read_sync() const volatile { - return from_subtype(InterlockedCompareExchange(const_cast(&sub_data), 0, 0)); + const subtype zero = {}; + return from_subtype(sync_val_compare_and_swap(const_cast(&sub_data), zero, zero)); } // atomically replace data with exch, return previous data value - __forceinline const type exchange(const type& exch) volatile + force_inline const type exchange(const type& exch) volatile { - return from_subtype(InterlockedExchange(&sub_data, to_subtype(exch))); + return from_subtype(sync_lock_test_and_set(&sub_data, to_subtype(exch))); } // read data without memory barrier - __forceinline const type read_relaxed() const volatile + force_inline const type read_relaxed() const volatile { const subtype value = const_cast(sub_data); return from_subtype(value); } // write data without memory barrier - __forceinline void write_relaxed(const type& value) volatile + force_inline void write_relaxed(const type& value) volatile { const_cast(sub_data) = to_subtype(value); } // perform atomic operation on data - template __forceinline void atomic_op(const FT atomic_proc) volatile + template force_inline void atomic_op(const FT atomic_proc) volatile { while (true) { const subtype old = const_cast(sub_data); subtype _new = old; atomic_proc(to_type(_new)); // function should accept reference to T type - if (InterlockedCompareExchangeTest(&sub_data, _new, old)) return; + if (sync_bool_compare_and_swap(&sub_data, old, _new)) return; } } // perform atomic operation on data with special exit condition (if intermediate result != proceed_value) - template __forceinline RT atomic_op(const RT proceed_value, const FT atomic_proc) volatile + template force_inline RT atomic_op(const RT proceed_value, const FT atomic_proc) volatile { while (true) { @@ -125,155 +120,114 @@ public: subtype _new = old; auto res = static_cast(atomic_proc(to_type(_new))); // function should accept reference to T type and return some value if (res != proceed_value) return res; - if (InterlockedCompareExchangeTest(&sub_data, _new, old)) return proceed_value; + if (sync_bool_compare_and_swap(&sub_data, old, _new)) return proceed_value; } } // perform atomic operation on data with additional memory barrier - template __forceinline void atomic_op_sync(const FT atomic_proc) volatile + template force_inline void atomic_op_sync(const FT atomic_proc) volatile { - subtype old = InterlockedCompareExchange(&sub_data, 0, 0); + const subtype zero = {}; + subtype old = sync_val_compare_and_swap(&sub_data, zero, zero); while (true) { subtype _new = old; atomic_proc(to_type(_new)); // function should accept reference to T type - const subtype val = InterlockedCompareExchange(&sub_data, _new, old); + const subtype val = sync_val_compare_and_swap(&sub_data, old, _new); if (val == old) return; old = val; } } // perform atomic operation on data with additional memory barrier and special exit condition (if intermediate result != proceed_value) - template __forceinline RT atomic_op_sync(const RT proceed_value, const FT atomic_proc) volatile + template force_inline RT atomic_op_sync(const RT proceed_value, const FT atomic_proc) volatile { - subtype old = InterlockedCompareExchange(&sub_data, 0, 0); + const subtype zero = {}; + subtype old = sync_val_compare_and_swap(&sub_data, zero, zero); while (true) { subtype _new = old; auto res = static_cast(atomic_proc(to_type(_new))); // function should accept reference to T type and return some value if (res != proceed_value) return res; - const subtype val = InterlockedCompareExchange(&sub_data, _new, old); + const subtype val = sync_val_compare_and_swap(&sub_data, old, _new); if (val == old) return proceed_value; old = val; } } // atomic bitwise OR, returns previous data - __forceinline const type _or(const type& right) volatile + force_inline const type _or(const type& right) volatile { - return from_subtype(InterlockedOr(&sub_data, to_subtype(right))); + return from_subtype(sync_fetch_and_or(&sub_data, to_subtype(right))); } // atomic bitwise AND, returns previous data - __forceinline const type _and(const type& right) volatile + force_inline const type _and(const type& right) volatile { - return from_subtype(InterlockedAnd(&sub_data, to_subtype(right))); + return from_subtype(sync_fetch_and_and(&sub_data, to_subtype(right))); } // atomic bitwise AND NOT (inverts right argument), returns previous data - __forceinline const type _and_not(const type& right) volatile + force_inline const type _and_not(const type& right) volatile { - return from_subtype(InterlockedAnd(&sub_data, ~to_subtype(right))); + return from_subtype(sync_fetch_and_and(&sub_data, ~to_subtype(right))); } // atomic bitwise XOR, returns previous data - __forceinline const type _xor(const type& right) volatile + force_inline const type _xor(const type& right) volatile { - return from_subtype(InterlockedXor(&sub_data, to_subtype(right))); + return from_subtype(sync_fetch_and_xor(&sub_data, to_subtype(right))); } - __forceinline const type operator |= (const type& right) volatile + force_inline const type operator |= (const type& right) volatile { - return from_subtype(InterlockedOr(&sub_data, to_subtype(right)) | to_subtype(right)); + return from_subtype(sync_fetch_and_or(&sub_data, to_subtype(right)) | to_subtype(right)); } - __forceinline const type operator &= (const type& right) volatile + force_inline const type operator &= (const type& right) volatile { - return from_subtype(InterlockedAnd(&sub_data, to_subtype(right)) & to_subtype(right)); + return from_subtype(sync_fetch_and_and(&sub_data, to_subtype(right)) & to_subtype(right)); } - __forceinline const type operator ^= (const type& right) volatile + force_inline const type operator ^= (const type& right) volatile { - return from_subtype(InterlockedXor(&sub_data, to_subtype(right)) ^ to_subtype(right)); + return from_subtype(sync_fetch_and_xor(&sub_data, to_subtype(right)) ^ to_subtype(right)); } }; // Helper definitions -template using if_arithmetic_t = const typename std::enable_if::value && std::is_arithmetic::value, T>::type; + +template using if_arithmetic_le_t = const typename std::enable_if::value && std::is_arithmetic::value, le_t>::type; template using if_arithmetic_be_t = const typename std::enable_if::value && std::is_arithmetic::value, be_t>::type; -template using if_arithmetic_atomic_t = typename std::enable_if::value && std::is_arithmetic::value, _atomic_base&>::type; -template using if_arithmetic_atomic_be_t = typename std::enable_if::value && std::is_arithmetic::value, _atomic_base>&>::type; -template inline static if_arithmetic_t operator ++(_atomic_base& left) +template inline static if_arithmetic_le_t operator ++(_atomic_base>& left) { - T result; - - left.atomic_op([&result](T& value) - { - result = ++value; - }); - - return result; + return left.from_subtype(sync_fetch_and_add(&left.sub_data, 1) + 1); } -template inline static if_arithmetic_t operator --(_atomic_base& left) +template inline static if_arithmetic_le_t operator --(_atomic_base>& left) { - T result; - - left.atomic_op([&result](T& value) - { - result = --value; - }); - - return result; + return left.from_subtype(sync_fetch_and_sub(&left.sub_data, 1) - 1); } -template inline static if_arithmetic_t operator ++(_atomic_base& left, int) +template inline static if_arithmetic_le_t operator ++(_atomic_base>& left, int) { - T result; - - left.atomic_op([&result](T& value) - { - result = value++; - }); - - return result; + return left.from_subtype(sync_fetch_and_add(&left.sub_data, 1)); } -template inline static if_arithmetic_t operator --(_atomic_base& left, int) +template inline static if_arithmetic_le_t operator --(_atomic_base>& left, int) { - T result; - - left.atomic_op([&result](T& value) - { - result = value--; - }); - - return result; + return left.from_subtype(sync_fetch_and_sub(&left.sub_data, 1)); } -template inline static if_arithmetic_t operator +=(_atomic_base& left, T2 right) +template inline static if_arithmetic_le_t operator +=(_atomic_base>& left, T2 right) { - T result; - - left.atomic_op([&result, right](T& value) - { - result = (value += right); - }); - - return result; + return left.from_subtype(sync_fetch_and_add(&left.sub_data, right) + right); } -template inline static if_arithmetic_t operator -=(_atomic_base& left, T2 right) +template inline static if_arithmetic_le_t operator -=(_atomic_base>& left, T2 right) { - T result; - - left.atomic_op([&result, right](T& value) - { - result = (value -= right); - }); - - return result; + return left.from_subtype(sync_fetch_and_sub(&left.sub_data, right) - right); } template inline static if_arithmetic_be_t operator ++(_atomic_base>& left) @@ -348,18 +302,8 @@ template inline static if_arithmetic_be_t operat return result; } -template using atomic_le_t = _atomic_base; +template using atomic = _atomic_base; // Atomic Type with native endianness (for emulator memory) -template using atomic_be_t = _atomic_base::type>; +template using atomic_be_t = _atomic_base::type>; // Atomic BE Type (for PS3 virtual memory) -namespace ps3 -{ - template using atomic_t = atomic_be_t; -} - -namespace psv -{ - template using atomic_t = atomic_le_t; -} - -using namespace ps3; +template using atomic_le_t = _atomic_base::type>; // Atomic LE Type (for PSV virtual memory) diff --git a/rpcs3/Emu/Memory/refcnt.h b/rpcs3/Emu/Memory/refcnt.h deleted file mode 100644 index c756d93722..0000000000 --- a/rpcs3/Emu/Memory/refcnt.h +++ /dev/null @@ -1,196 +0,0 @@ -#pragma once -#include "atomic.h" - -// run endless loop for debugging -__forceinline static void deadlock() -{ - while (true) - { - std::this_thread::yield(); - } -} - -template -class ref_t; - -template -class refcounter_t // non-relocateable "smart" pointer with ref counter -{ -public: - typedef T type, * p_type; - typedef refcounter_t rc_type; - - // counter > 0, ptr != nullptr : object exists and shared - // counter > 0, ptr == nullptr : object exists and shared, but not owned by refcounter_t - // counter == 0, ptr != nullptr : object exists and not shared - // counter == 0, ptr == nullptr : object doesn't exist - // counter < 0 : bad state, used to provoke error for debugging - - struct sync_var_t - { - s64 counter; - p_type ptr; - }; - -private: - atomic_le_t m_var; - - friend class ref_t; - - // try to share object (increment counter), returns nullptr if doesn't exist or cannot be shared - __forceinline p_type ref_inc() - { - p_type out_ptr; - - m_var.atomic_op([&out_ptr](sync_var_t& v) - { - assert(v.counter >= 0); - - if ((out_ptr = v.ptr)) - { - v.counter++; - } - }); - - return out_ptr; - } - - // try to release previously shared object (decrement counter), returns true if should be deleted - __forceinline bool ref_dec() - { - bool do_delete; - - m_var.atomic_op([&do_delete](sync_var_t& v) - { - assert(v.counter > 0); - - do_delete = !--v.counter && !v.ptr; - }); - - return do_delete; - } - -public: - refcounter_t() - { - // initialize ref counter - m_var.write_relaxed({ 0, nullptr }); - } - - ~refcounter_t() - { - // set bad state - auto ref = m_var.exchange({ -1, nullptr }); - - // finalize - if (ref.counter) - { - deadlock(); - } - else if (ref.ptr) - { - delete ref.ptr; - } - } - - refcounter_t(const rc_type& right) = delete; - refcounter_t(rc_type&& right_rv) = delete; - - rc_type& operator =(const rc_type& right) = delete; - rc_type& operator =(rc_type&& right_rv) = delete; - -public: - // try to set new object (if it doesn't exist) - bool try_set(p_type ptr) - { - return m_var.compare_and_swap_test({ 0, nullptr }, { 0, ptr }); - } - - // try to remove object (if exists) - bool try_remove() - { - bool out_res; - p_type out_ptr; - - m_var.atomic_op([&out_res, &out_ptr](sync_var_t& v) - { - out_res = (out_ptr = v.ptr); - - if (v.counter) - { - out_ptr = nullptr; - } - - v.ptr = nullptr; - }); - - if (out_ptr) - { - delete out_ptr; - } - - return out_res; - } -}; - -template -class ref_t -{ -public: - typedef T type, * p_type; - typedef refcounter_t * rc_type; - -private: - rc_type m_rc; - p_type m_ptr; - -public: - ref_t() - : m_rc(nullptr) - , m_ptr(nullptr) - { - } - - ref_t(rc_type rc) - : m_rc(rc) - , m_ptr(rc->ref_inc()) - { - } - - ~ref_t() - { - if (m_ptr && m_rc->ref_dec()) - { - delete m_ptr; - } - } - - ref_t(const ref_t& right) = delete; - - ref_t(ref_t&& right_rv) - : m_rc(right_rv.m_rc) - , m_ptr(right_rv.m_ptr) - { - right_rv.m_rc = nullptr; - right_rv.m_ptr = nullptr; - } - - ref_t& operator =(const ref_t& right) = delete; - ref_t& operator =(ref_t&& right_rv) = delete; - -public: - T& operator *() const - { - return *m_ptr; - } - - T* operator ->() const - { - return m_ptr; - } - - explicit operator bool() const - { - return m_ptr; - } -}; diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index ff2da7e06b..623f1489fb 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -75,7 +75,7 @@ namespace vm void* g_base_addr = (atexit(finalize), initialize()); void* g_priv_addr; - std::array, 0x100000000ull / 4096> g_page_info = {}; // information about every page + std::array, 0x100000000ull / 4096> g_page_info = {}; // information about every page class reservation_mutex_t { @@ -91,7 +91,7 @@ namespace vm bool do_notify; - __noinline void lock() + never_inline void lock() { NamedThreadBase* owner = GetCurrentNamedThread(); NamedThreadBase* old = nullptr; @@ -113,7 +113,7 @@ namespace vm do_notify = true; } - __noinline void unlock() + never_inline void unlock() { NamedThreadBase* owner = GetCurrentNamedThread(); diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 3447db2b48..5413ca90b3 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -90,14 +90,14 @@ namespace vm u32 get_addr(const void* real_pointer); - __noinline void error(const u64 addr, const char* func); + never_inline void error(const u64 addr, const char* func); template struct cast_ptr { static_assert(std::is_same::value, "Unsupported vm::cast() type"); - __forceinline static u32 cast(const T& addr, const char* func) + force_inline static u32 cast(const T& addr, const char* func) { return 0; } @@ -106,7 +106,7 @@ namespace vm template<> struct cast_ptr { - __forceinline static u32 cast(const u32 addr, const char* func) + force_inline static u32 cast(const u32 addr, const char* func) { return addr; } @@ -115,7 +115,7 @@ namespace vm template<> struct cast_ptr { - __forceinline static u32 cast(const u64 addr, const char* func) + force_inline static u32 cast(const u64 addr, const char* func) { const u32 res = static_cast(addr); if (res != addr) @@ -130,14 +130,14 @@ namespace vm template struct cast_ptr> { - __forceinline static u32 cast(const be_t& addr, const char* func) + force_inline static u32 cast(const be_t& addr, const char* func) { return cast_ptr::cast(addr.value(), func); } }; template - __forceinline static u32 cast(const T& addr, const char* func = "vm::cast") + force_inline static u32 cast(const T& addr, const char* func = "vm::cast") { return cast_ptr::cast(addr, func); } @@ -298,10 +298,16 @@ namespace vm u32 alloc_offset; template - ptr alloc(u32 count) const + ptr alloc(u32 count = 1) const { return ptr::make(allocator(count * sizeof(T))); } + + template + ptr fixed_alloc(u32 addr, u32 count = 1) const + { + return ptr::make(fixed_allocator(addr, count * sizeof(T))); + } }; extern location_info g_locations[memory_location_count]; diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index d1eef9fe21..973aa55719 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -6,11 +6,10 @@ struct ARMv7Context; namespace vm { template - class _ptr_base + struct _ptr_base { AT m_addr; - public: typedef typename std::remove_cv::type type; static const u32 address_size = sizeof(AT); @@ -57,24 +56,26 @@ namespace vm _ptr_base operator - (typename remove_be_t::type count) const { return make(m_addr - count * address_size); } _ptr_base operator - (typename to_be_t::type count) const { return make(m_addr - count * address_size); } - __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } - __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } - __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } - __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } - __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } - __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } - __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } - __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + force_inline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + force_inline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + force_inline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + force_inline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + force_inline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + force_inline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + force_inline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + force_inline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } explicit operator bool() const { return m_addr != 0; } - __forceinline _ptr_base::value, typename to_be_t::type, AT>>& operator *() const + force_inline _ptr_base::value, typename to_be_t::type, AT>::type> operator *() const { - return vm::get_ref<_ptr_base::value, typename to_be_t::type, AT>>>(vm::cast(m_addr)); + AT addr = convert_le_be(read64(convert_le_be(m_addr))); + return (_ptr_base::value, typename to_be_t::type, AT>::type>&)addr; } - __forceinline _ptr_base::value, typename to_be_t::type, AT>>& operator [](AT index) const + force_inline _ptr_base::value, typename to_be_t::type, AT>::type> operator [](AT index) const { - return vm::get_ref<_ptr_base::value, typename to_be_t::type, AT>>>(vm::cast(m_addr + sizeof(AT)* index)); + AT addr = convert_le_be(read64(convert_le_be(m_addr + 8 * index))); + return (_ptr_base::value, typename to_be_t::type, AT>::type>&)addr; } template @@ -89,35 +90,35 @@ namespace vm return m_addr; } - void set(const AT value) + template + void set(U&& value) { - m_addr = value; + m_addr = convert_le_be(value); } static _ptr_base make(const AT& addr) { - return reinterpret_cast<_ptr_base&>(addr); + return reinterpret_cast(addr); } _ptr_base& operator = (const _ptr_base& right) = default; }; template - class _ptr_base + struct _ptr_base { AT m_addr; - public: static_assert(!std::is_pointer::value, "vm::_ptr_base<> error: invalid type (pointer)"); static_assert(!std::is_reference::value, "vm::_ptr_base<> error: invalid type (reference)"); typedef typename std::remove_cv::type type; - __forceinline static const u32 data_size() + force_inline static const u32 data_size() { - return sizeof(T); + return convert_le_be(sizeof(T)); } - __forceinline T* const operator -> () const + force_inline T* const operator -> () const { return vm::get_ptr(vm::cast(m_addr)); } @@ -160,34 +161,34 @@ namespace vm return *this; } - _ptr_base operator + (typename remove_be_t::type count) const { return make(m_addr + count * data_size()); } - _ptr_base operator + (typename to_be_t::type count) const { return make(m_addr + count * data_size()); } - _ptr_base operator - (typename remove_be_t::type count) const { return make(m_addr - count * data_size()); } - _ptr_base operator - (typename to_be_t::type count) const { return make(m_addr - count * data_size()); } + _ptr_base operator + (typename remove_be_t::type count) const { return make(convert_le_be(convert_le_be(m_addr) + count * convert_le_be(data_size()))); } + _ptr_base operator + (typename to_be_t::type count) const { return make(convert_le_be(convert_le_be(m_addr) + count * convert_le_be(data_size()))); } + _ptr_base operator - (typename remove_be_t::type count) const { return make(convert_le_be(convert_le_be(m_addr) - count * convert_le_be(data_size()))); } + _ptr_base operator - (typename to_be_t::type count) const { return make(convert_le_be(convert_le_be(m_addr) - count * convert_le_be(data_size()))); } - __forceinline T& operator *() const + force_inline T& operator *() const { return vm::get_ref(vm::cast(m_addr)); } - __forceinline T& operator [](typename remove_be_t::type index) const + force_inline T& operator [](typename remove_be_t::type index) const { return vm::get_ref(vm::cast(m_addr + data_size() * index)); } - __forceinline T& operator [](typename to_be_t::forced_type index) const + force_inline T& operator [](typename to_be_t::forced_type index) const { return vm::get_ref(vm::cast(m_addr + data_size() * index)); } - __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } - __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } - __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } - __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } - __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } - __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } - __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } - __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + force_inline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + force_inline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + force_inline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + force_inline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + force_inline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + force_inline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + force_inline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + force_inline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } explicit operator bool() const { return m_addr != 0; } explicit operator T*() const { return get_ptr(); } @@ -228,19 +229,19 @@ namespace vm }; template - class _ptr_base + struct _ptr_base { AT m_addr; - public: AT addr() const { return m_addr; } - void set(const AT value) + template + void set(U&& value) { - m_addr = value; + m_addr = convert_le_be(value); } void* get_ptr() const @@ -258,14 +259,14 @@ namespace vm return get_ptr(); } - __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } - __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } - __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } - __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } - __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } - __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } - __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } - __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + force_inline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + force_inline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + force_inline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + force_inline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + force_inline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + force_inline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + force_inline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + force_inline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } explicit operator bool() const { return m_addr != 0; } template @@ -291,19 +292,19 @@ namespace vm }; template - class _ptr_base + struct _ptr_base { AT m_addr; - public: AT addr() const { return m_addr; } - void set(const AT value) + template + void set(U&& value) { - m_addr = value; + m_addr = convert_le_be(value); } const void* get_ptr() const @@ -321,14 +322,14 @@ namespace vm return get_ptr(); } - __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } - __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } - __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } - __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } - __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } - __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } - __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } - __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + force_inline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + force_inline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + force_inline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + force_inline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + force_inline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + force_inline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + force_inline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + force_inline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } explicit operator bool() const { return m_addr != 0; } template @@ -347,37 +348,40 @@ namespace vm }; template - class _ptr_base + struct _ptr_base { AT m_addr; - public: typedef RT(type)(T...); - RT operator()(PPUThread& CPU, T... args) const; // defined in CB_FUNC.h, call using specified PPU thread context + // defined in CB_FUNC.h, call using specified PPU thread context + RT operator()(PPUThread& CPU, T... args) const; - RT operator()(ARMv7Context& context, T... args) const; // defined in ARMv7Callback.h, passing context is mandatory + // defined in ARMv7Callback.h, passing context is mandatory + RT operator()(ARMv7Context& context, T... args) const; - RT operator()(T... args) const; // defined in CB_FUNC.h, call using current PPU thread context + // defined in CB_FUNC.h, call using current PPU thread context + RT operator()(T... args) const; AT addr() const { return m_addr; } - void set(const AT value) + template + void set(U&& value) { - m_addr = value; + m_addr = convert_le_be(value); } - __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } - __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } - __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } - __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } - __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } - __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } - __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } - __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + force_inline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + force_inline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + force_inline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + force_inline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + force_inline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + force_inline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + force_inline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + force_inline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } explicit operator bool() const { return m_addr != 0; } template @@ -402,39 +406,47 @@ namespace vm }; template - class _ptr_base + struct _ptr_base { AT m_addr; - public: static_assert(!sizeof(AT), "vm::_ptr_base<> error: use RT(T...) format for functions instead of RT(*)(T...)"); }; + // Native endianness pointer to LE data + template using ptrl = _ptr_base::type, lvl, AT>; + + // Native endianness pointer to BE data + template using ptrb = _ptr_base::type, lvl, AT>; + // BE pointer to LE data - template using bptrl = _ptr_base::type>; + template using bptrl = _ptr_base::type, lvl, typename to_be_t::type>; // BE pointer to BE data template using bptrb = _ptr_base::type, lvl, typename to_be_t::type>; - // LE pointer to BE data - template using lptrb = _ptr_base::type, lvl, AT>; - // LE pointer to LE data - template using lptrl = _ptr_base; + template using lptrl = _ptr_base::type, lvl, typename to_le_t::type>; + + // LE pointer to BE data + template using lptrb = _ptr_base::type, lvl, typename to_le_t::type>; namespace ps3 { - // default pointer for HLE functions (LE pointer to BE data) - template using ptr = lptrb; + // default pointer for PS3 HLE functions (Native endianness pointer to BE data) + template using ptr = ptrb; - // default pointer for HLE structures (BE pointer to BE data) + // default pointer for PS3 HLE structures (BE pointer to BE data) template using bptr = bptrb; } namespace psv { - // default pointer for HLE functions & structures (LE pointer to LE data) - template using ptr = lptrl; + // default pointer for PSV HLE functions (Native endianness pointer to LE data) + template using ptr = ptrl; + + // default pointer for PSV HLE structures (LE pointer to LE data) + template using lptr = lptrl; } // PS3 emulation is main now, so lets it be as default @@ -462,7 +474,7 @@ namespace fmt { typedef typename unveil::result_type result_type; - __forceinline static result_type get_value(const vm::_ptr_base& arg) + force_inline static result_type get_value(const vm::_ptr_base& arg) { return unveil::get_value(arg.addr()); } @@ -477,12 +489,12 @@ struct cast_ppu_gpr; template struct cast_ppu_gpr, false> { - __forceinline static u64 to_gpr(const vm::_ptr_base& value) + force_inline static u64 to_gpr(const vm::_ptr_base& value) { return cast_ppu_gpr::value>::to_gpr(value.addr()); } - __forceinline static vm::_ptr_base from_gpr(const u64 reg) + force_inline static vm::_ptr_base from_gpr(const u64 reg) { return vm::_ptr_base::make(cast_ppu_gpr::value>::from_gpr(reg)); } @@ -496,12 +508,12 @@ struct cast_armv7_gpr; template struct cast_armv7_gpr, false> { - __forceinline static u32 to_gpr(const vm::_ptr_base& value) + force_inline static u32 to_gpr(const vm::_ptr_base& value) { return cast_armv7_gpr::value>::to_gpr(value.addr()); } - __forceinline static vm::_ptr_base from_gpr(const u32 reg) + force_inline static vm::_ptr_base from_gpr(const u32 reg) { return vm::_ptr_base::make(cast_armv7_gpr::value>::from_gpr(reg)); } diff --git a/rpcs3/Emu/Memory/vm_ref.h b/rpcs3/Emu/Memory/vm_ref.h index c43474bea5..a2e7903d16 100644 --- a/rpcs3/Emu/Memory/vm_ref.h +++ b/rpcs3/Emu/Memory/vm_ref.h @@ -60,31 +60,40 @@ namespace vm } }; - //BE reference to LE data - template using brefl = _ref_base::type>; + // Native endianness reference to LE data + template using refl = _ref_base::type, AT>; - //BE reference to BE data + // Native endianness reference to BE data + template using refb = _ref_base::type, AT>; + + // BE reference to LE data + template using brefl = _ref_base::type, typename to_be_t::type>; + + // BE reference to BE data template using brefb = _ref_base::type, typename to_be_t::type>; - //LE reference to BE data - template using lrefb = _ref_base::type, AT>; + // LE reference to LE data + template using lrefl = _ref_base::type, typename to_le_t::type>; - //LE reference to LE data - template using lrefl = _ref_base; + // LE reference to BE data + template using lrefb = _ref_base::type, typename to_le_t::type>; namespace ps3 { - //default reference for HLE functions (LE reference to BE data) - template using ref = lrefb; + // default reference for PS3 HLE functions (Native endianness reference to BE data) + template using ref = refb; - //default reference for HLE structures (BE reference to BE data) + // default reference for PS3 HLE structures (BE reference to BE data) template using bref = brefb; } namespace psv { - //default reference for HLE functions & structures (LE reference to LE data) - template using ref = lrefl; + // default reference for PSV HLE functions (Native endianness reference to LE data) + template using ref = refl; + + // default reference for PSV HLE structures (LE reference to LE data) + template using lref = lrefl; } //PS3 emulation is main now, so lets it be as default @@ -100,7 +109,7 @@ namespace fmt { typedef typename unveil::result_type result_type; - __forceinline static result_type get_value(const vm::_ref_base& arg) + force_inline static result_type get_value(const vm::_ref_base& arg) { return unveil::get_value(arg.addr()); } @@ -115,12 +124,12 @@ struct cast_ppu_gpr; template struct cast_ppu_gpr, false> { - __forceinline static u64 to_gpr(const vm::_ref_base& value) + force_inline static u64 to_gpr(const vm::_ref_base& value) { return cast_ppu_gpr::value>::to_gpr(value.addr()); } - __forceinline static vm::_ref_base from_gpr(const u64 reg) + force_inline static vm::_ref_base from_gpr(const u64 reg) { return vm::_ref_base::make(cast_ppu_gpr::value>::from_gpr(reg)); } @@ -134,12 +143,12 @@ struct cast_armv7_gpr; template struct cast_armv7_gpr, false> { - __forceinline static u32 to_gpr(const vm::_ref_base& value) + force_inline static u32 to_gpr(const vm::_ref_base& value) { return cast_armv7_gpr::value>::to_gpr(value.addr()); } - __forceinline static vm::_ref_base from_gpr(const u32 reg) + force_inline static vm::_ref_base from_gpr(const u32 reg) { return vm::_ref_base::make(cast_armv7_gpr::value>::from_gpr(reg)); } diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index b33eaf69cb..dfef1b4a9b 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -425,7 +425,7 @@ namespace vm return m_addr; } - __forceinline uint count() const + force_inline uint count() const { return _count; } diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index 40fa67c2b5..39c15ab2ca 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -201,9 +201,9 @@ enum struct CellGcmControl { - atomic_t put; - atomic_t get; - atomic_t ref; + atomic_be_t put; + atomic_be_t get; + atomic_be_t ref; }; struct CellGcmConfig diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index 92b8c13847..545f2b0d1f 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -24,7 +24,7 @@ namespace cb_detail { static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_GENERAL"); - __forceinline static void set_value(PPUThread& CPU, const T& arg) + force_inline static void set_value(PPUThread& CPU, const T& arg) { CPU.GPR[g_count + 2] = cast_to_ppu_gpr(arg); } @@ -35,7 +35,7 @@ namespace cb_detail { static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_FLOAT"); - __forceinline static void set_value(PPUThread& CPU, const T& arg) + force_inline static void set_value(PPUThread& CPU, const T& arg) { CPU.FPR[f_count] = static_cast(arg); } @@ -46,7 +46,7 @@ namespace cb_detail { static_assert(std::is_same::value, "Invalid callback argument type for ARG_VECTOR"); - __forceinline static void set_value(PPUThread& CPU, const T& arg) + force_inline static void set_value(PPUThread& CPU, const T& arg) { CPU.VPR[v_count + 1] = arg; } @@ -59,7 +59,7 @@ namespace cb_detail static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)"); static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_STACK"); - __forceinline static void set_value(PPUThread& CPU, const T& arg) + force_inline static void set_value(PPUThread& CPU, const T& arg) { const int stack_pos = (g_count - 9) * 8 - FIXED_STACK_FRAME_SIZE; static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)"); @@ -68,14 +68,14 @@ namespace cb_detail }; template - __forceinline static bool _bind_func_args(PPUThread& CPU) + force_inline static bool _bind_func_args(PPUThread& CPU) { // terminator return false; } template - __forceinline static bool _bind_func_args(PPUThread& CPU, T1 arg1, T... args) + force_inline static bool _bind_func_args(PPUThread& CPU, T1 arg1, T... args) { static_assert(!std::is_pointer::value, "Invalid callback argument type (pointer)"); static_assert(!std::is_reference::value, "Invalid callback argument type (reference)"); @@ -99,7 +99,7 @@ namespace cb_detail static_assert(type == ARG_GENERAL, "Wrong use of _func_res template"); static_assert(sizeof(T) <= 8, "Invalid callback result type for ARG_GENERAL"); - __forceinline static T get_value(const PPUThread& CPU) + force_inline static T get_value(const PPUThread& CPU) { return cast_from_ppu_gpr(CPU.GPR[3]); } @@ -110,7 +110,7 @@ namespace cb_detail { static_assert(sizeof(T) <= 8, "Invalid callback result type for ARG_FLOAT"); - __forceinline static T get_value(const PPUThread& CPU) + force_inline static T get_value(const PPUThread& CPU) { return static_cast(CPU.FPR[1]); } @@ -121,7 +121,7 @@ namespace cb_detail { static_assert(std::is_same::value, "Invalid callback result type for ARG_VECTOR"); - __forceinline static T get_value(const PPUThread& CPU) + force_inline static T get_value(const PPUThread& CPU) { return CPU.VPR[2]; } @@ -130,7 +130,7 @@ namespace cb_detail template struct _func_caller { - __forceinline static RT call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) + force_inline static RT call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) { _func_caller::call(CPU, pc, rtoc, args...); @@ -147,7 +147,7 @@ namespace cb_detail template struct _func_caller { - __forceinline static void call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) + force_inline static void call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) { const bool stack = _bind_func_args<0, 0, 0, T...>(CPU, args...); if (stack) CPU.GPR[1] -= FIXED_STACK_FRAME_SIZE; @@ -162,7 +162,7 @@ namespace cb_detail namespace vm { template - __forceinline RT _ptr_base::operator()(PPUThread& CPU, T... args) const + force_inline RT _ptr_base::operator()(PPUThread& CPU, T... args) const { const auto data = vm::get_ptr>(vm::cast(m_addr)); const u32 pc = data[0]; @@ -172,14 +172,14 @@ namespace vm } template - __forceinline RT _ptr_base::operator()(T... args) const + force_inline RT _ptr_base::operator()(T... args) const { return operator()(GetCurrentPPUThread(), args...); } } template -__forceinline RT cb_call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) +force_inline RT cb_call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) { return cb_detail::_func_caller::call(CPU, pc, rtoc, args...); } diff --git a/rpcs3/Emu/SysCalls/LogBase.h b/rpcs3/Emu/SysCalls/LogBase.h index 767594d8ec..4acdc0d11b 100644 --- a/rpcs3/Emu/SysCalls/LogBase.h +++ b/rpcs3/Emu/SysCalls/LogBase.h @@ -17,8 +17,7 @@ class LogBase void LogOutput(LogType type, const std::string& text) const; - template - __noinline void LogPrepare(LogType type, const char* fmt, Targs... args) const + template never_inline void LogPrepare(LogType type, const char* fmt, Args... args) const { LogOutput(type, fmt::Format(fmt, args...)); } @@ -36,14 +35,12 @@ public: virtual const std::string& GetName() const = 0; - template - __forceinline void Notice(const char* fmt, Targs... args) const + template force_inline void Notice(const char* fmt, Args... args) const { LogPrepare(LogNotice, fmt, fmt::do_unveil(args)...); } - template - __forceinline void Log(const char* fmt, Targs... args) const + template force_inline void Log(const char* fmt, Args... args) const { if (CheckLogging()) { @@ -51,32 +48,27 @@ public: } } - template - __forceinline void Success(const char* fmt, Targs... args) const + template force_inline void Success(const char* fmt, Args... args) const { LogPrepare(LogSuccess, fmt, fmt::do_unveil(args)...); } - template - __forceinline void Warning(const char* fmt, Targs... args) const + template force_inline void Warning(const char* fmt, Args... args) const { LogPrepare(LogWarning, fmt, fmt::do_unveil(args)...); } - template - __forceinline void Error(const char* fmt, Targs... args) const + template force_inline void Error(const char* fmt, Args... args) const { LogPrepare(LogError, fmt, fmt::do_unveil(args)...); } - template - __forceinline void Fatal(const char* fmt, Targs... args) const + template force_inline void Fatal(const char* fmt, Args... args) const { LogPrepare(LogFatal, fmt, fmt::do_unveil(args)...); } - template - __forceinline void Todo(const char* fmt, Targs... args) const + template force_inline void Todo(const char* fmt, Args... args) const { LogPrepare(LogTodo, fmt, fmt::do_unveil(args)...); } diff --git a/rpcs3/Emu/SysCalls/Modules.cpp b/rpcs3/Emu/SysCalls/Modules.cpp index 0e9f3561f9..b1eeb20cfd 100644 --- a/rpcs3/Emu/SysCalls/Modules.cpp +++ b/rpcs3/Emu/SysCalls/Modules.cpp @@ -15,9 +15,19 @@ std::vector g_ppu_func_subs; u32 add_ppu_func(ModuleFunc func) { + if (g_ppu_func_list.empty()) + { + // prevent relocations if the array growths, must be sizeof(ModuleFunc) * 0x8000 ~~ about 1 MB of memory + g_ppu_func_list.reserve(0x8000); + } + for (auto& f : g_ppu_func_list) { - assert(f.id != func.id); + if (f.id == func.id) + { + // TODO: if NIDs overlap or if the same function is added twice + assert(!"add_ppu_func(): NID already exists"); + } } g_ppu_func_list.push_back(func); @@ -93,15 +103,56 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index) { if (auto func = get_ppu_func_by_index(index)) { - auto old_last_syscall = CPU.m_last_syscall; - CPU.m_last_syscall = func->id; - + // save RTOC if necessary if (index & EIF_SAVE_RTOC) { - // save RTOC if necessary vm::write64(vm::cast(CPU.GPR[1] + 0x28), CPU.GPR[2]); } + // save old syscall/NID value + auto old_last_syscall = CPU.m_last_syscall; + + // branch directly to the LLE function + if (index & EIF_USE_BRANCH) + { + // for example, FastCall2 can't work with functions which do user level context switch + + if (old_last_syscall) + { + throw "Unfortunately, this function cannot be called from the callback."; + } + + if (!func->lle_func) + { + throw "Wrong usage: LLE function not set."; + } + + if (func->flags & MFF_FORCED_HLE) + { + throw "Wrong usage: Forced HLE enabled."; + } + + if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(HLE, "Branch to LLE function: %s", SysCalls::GetFuncName(func->id)); + } + + if (index & EIF_PERFORM_BLR) + { + throw "TODO: Branch with link"; + // CPU.LR = CPU.PC + 4; + } + + const auto data = vm::get_ptr>(func->lle_func.addr()); + CPU.SetBranch(data[0]); + CPU.GPR[2] = data[1]; // set rtoc + + return; + } + + // change current syscall/NID value + CPU.m_last_syscall = func->id; + if (func->lle_func && !(func->flags & MFF_FORCED_HLE)) { // call LLE function if available @@ -427,6 +478,15 @@ bool patch_ppu_import(u32 addr, u32 index) using namespace PPU_instr; + if (index >= g_ppu_func_list.size()) + { + return false; + } + + const u32 imm = (g_ppu_func_list[index].flags & MFF_NO_RETURN) && !(g_ppu_func_list[index].flags & MFF_FORCED_HLE) + ? index | EIF_USE_BRANCH + : index | EIF_PERFORM_BLR; + // check different patterns: if (vm::check_addr(addr, 32) && @@ -439,7 +499,7 @@ bool patch_ppu_import(u32 addr, u32 index) data[6] == MTCTR(r0) && data[7] == BCTR()) { - vm::write32(addr, HACK(index | EIF_SAVE_RTOC | EIF_PERFORM_BLR)); + vm::write32(addr, HACK(imm | EIF_SAVE_RTOC)); return true; } @@ -467,7 +527,7 @@ bool patch_ppu_import(u32 addr, u32 index) sub[0xd] == MTLR(r0) && sub[0xe] == BLR()) { - vm::write32(addr, HACK(index | EIF_PERFORM_BLR)); + vm::write32(addr, HACK(imm)); return true; } } @@ -490,7 +550,7 @@ bool patch_ppu_import(u32 addr, u32 index) data[0xe] == MTLR(r0) && data[0xf] == BLR()) { - vm::write32(addr, HACK(index | EIF_PERFORM_BLR)); + vm::write32(addr, HACK(imm)); return true; } @@ -511,7 +571,7 @@ bool patch_ppu_import(u32 addr, u32 index) data[0xd] == MTLR(r0) && data[0xe] == BLR()) { - vm::write32(addr, HACK(index | EIF_PERFORM_BLR)); + vm::write32(addr, HACK(imm)); return true; } @@ -531,10 +591,11 @@ bool patch_ppu_import(u32 addr, u32 index) data[0xc] == LD(r2, r1, 0x28) && data[0xd] == BLR()) { - vm::write32(addr, HACK(index | EIF_PERFORM_BLR)); + vm::write32(addr, HACK(imm)); return true; } + //vm::write32(addr, HACK(imm)); return false; } diff --git a/rpcs3/Emu/SysCalls/Modules.h b/rpcs3/Emu/SysCalls/Modules.h index bc1ffe66d4..67f68567b8 100644 --- a/rpcs3/Emu/SysCalls/Modules.h +++ b/rpcs3/Emu/SysCalls/Modules.h @@ -9,6 +9,7 @@ class Module; enum : u32 { MFF_FORCED_HLE = (1 << 0), // always call HLE function + MFF_NO_RETURN = (1 << 1), // uses EIF_USE_BRANCH flag with LLE, ignored with MFF_FORCED_HLE }; // flags passed with index @@ -16,8 +17,9 @@ enum : u32 { EIF_SAVE_RTOC = (1 << 25), // save RTOC in [SP+0x28] before calling HLE/LLE function EIF_PERFORM_BLR = (1 << 24), // do BLR after calling HLE/LLE function + EIF_USE_BRANCH = (1 << 23), // do only branch, LLE must be set, last_syscall must be zero - EIF_FLAGS = 0x3000000, // all flags + EIF_FLAGS = 0x3800000, // all flags }; struct ModuleFunc @@ -121,6 +123,7 @@ bool patch_ppu_import(u32 addr, u32 index); #define REG_FUNC(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &module, #name, bind_func(name))) #define REG_FUNC_FH(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_FORCED_HLE, &module, #name, bind_func(name))) +#define REG_FUNC_NR(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_NO_RETURN, &module, #name, bind_func(name))) #define REG_UNNAMED(module, nid) add_ppu_func(ModuleFunc(0x##nid, 0, &module, "_nid_"#nid, bind_func(_nid_##nid))) diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index bca545f960..528cc2b3cf 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -216,12 +216,10 @@ next: } } -u32 adecOpen(AudioDecoder* adec_ptr) +void adecOpen(u32 adec_id) // TODO: call from the constructor { - std::shared_ptr sptr(adec_ptr); - AudioDecoder& adec = *adec_ptr; - - u32 adec_id = Emu.GetIdManager().GetNewID(sptr); + const auto sptr = Emu.GetIdManager().get(adec_id); + AudioDecoder& adec = *sptr; adec.id = adec_id; @@ -234,9 +232,9 @@ u32 adecOpen(AudioDecoder* adec_ptr) adec.adecCb->InitRegs(); adec.adecCb->DoRun(); - thread_t t(fmt::format("AudioDecoder[0x%x] Thread", adec_id), [adec_ptr, sptr]() + thread_t t(fmt::format("AudioDecoder[0x%x] Thread", adec_id), [sptr]() { - AudioDecoder& adec = *adec_ptr; + AudioDecoder& adec = *sptr; AdecTask& task = adec.task; while (true) @@ -478,8 +476,6 @@ u32 adecOpen(AudioDecoder* adec_ptr) adec.is_finished = true; }); - - return adec_id; } bool adecCheckType(AudioCodecType type) @@ -536,7 +532,7 @@ s32 cellAdecOpen(vm::ptr type, vm::ptr res, vm:: return CELL_ADEC_ERROR_ARG; } - *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); + adecOpen(*handle = Emu.GetIdManager().make(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); return CELL_OK; } @@ -550,7 +546,7 @@ s32 cellAdecOpenEx(vm::ptr type, vm::ptr res, return CELL_ADEC_ERROR_ARG; } - *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); + adecOpen(*handle = Emu.GetIdManager().make(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); return CELL_OK; } @@ -564,7 +560,7 @@ s32 cellAdecClose(u32 handle) { cellAdec.Warning("cellAdecClose(handle=0x%x)", handle); - const auto adec = Emu.GetIdManager().GetIDData(handle); + const auto adec = Emu.GetIdManager().get(handle); if (!adec) { @@ -585,7 +581,7 @@ s32 cellAdecClose(u32 handle) } if (adec->adecCb) Emu.GetCPU().RemoveThread(adec->adecCb->GetId()); - Emu.GetIdManager().RemoveID(handle); + Emu.GetIdManager().remove(handle); return CELL_OK; } @@ -593,7 +589,7 @@ s32 cellAdecStartSeq(u32 handle, u32 param) { cellAdec.Warning("cellAdecStartSeq(handle=0x%x, param=*0x%x)", handle, param); - const auto adec = Emu.GetIdManager().GetIDData(handle); + const auto adec = Emu.GetIdManager().get(handle); if (!adec) { @@ -646,7 +642,7 @@ s32 cellAdecEndSeq(u32 handle) { cellAdec.Warning("cellAdecEndSeq(handle=0x%x)", handle); - const auto adec = Emu.GetIdManager().GetIDData(handle); + const auto adec = Emu.GetIdManager().get(handle); if (!adec) { @@ -661,7 +657,7 @@ s32 cellAdecDecodeAu(u32 handle, vm::ptr auInfo) { cellAdec.Log("cellAdecDecodeAu(handle=0x%x, auInfo=*0x%x)", handle, auInfo); - const auto adec = Emu.GetIdManager().GetIDData(handle); + const auto adec = Emu.GetIdManager().get(handle); if (!adec) { @@ -684,7 +680,7 @@ s32 cellAdecGetPcm(u32 handle, vm::ptr outBuffer) { cellAdec.Log("cellAdecGetPcm(handle=0x%x, outBuffer=*0x%x)", handle, outBuffer); - const auto adec = Emu.GetIdManager().GetIDData(handle); + const auto adec = Emu.GetIdManager().get(handle); if (!adec) { @@ -800,7 +796,7 @@ s32 cellAdecGetPcmItem(u32 handle, vm::ptr> pcmItem) { cellAdec.Log("cellAdecGetPcmItem(handle=0x%x, pcmItem=**0x%x)", handle, pcmItem); - const auto adec = Emu.GetIdManager().GetIDData(handle); + const auto adec = Emu.GetIdManager().get(handle); if (!adec) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 39cf506454..e857e9acf8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -763,12 +763,12 @@ s32 cellAudioCreateNotifyEventQueue(vm::ptr id, vm::ptr key) { const u64 key_value = 0x80004d494f323221ull + k; - std::shared_ptr queue(new event_queue_t(SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0, key_value, 32)); + auto queue = std::make_shared(SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0, key_value, 32); // register key if not used yet - if (Emu.GetEventManager().RegisterKey(queue, key_value)) + if (Emu.GetEventManager().RegisterKey(queue)) { - *id = Emu.GetIdManager().GetNewID(queue, TYPE_EVENT_QUEUE); + *id = Emu.GetIdManager().add(std::move(queue)); *key = key_value; return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.h b/rpcs3/Emu/SysCalls/Modules/cellAudio.h index 84b6bd65b4..08356a506a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.h @@ -98,7 +98,7 @@ enum AudioPortState : u32 struct AudioPortConfig { std::mutex mutex; - atomic_le_t state; + atomic state; u32 channel; u32 block; @@ -116,13 +116,13 @@ struct AudioPortConfig }; float level; - atomic_le_t level_set; + atomic level_set; }; struct AudioConfig //custom structure { std::mutex mutex; - atomic_le_t state; + atomic state; thread_t audio_thread; AudioPortConfig ports[AUDIO_PORT_COUNT]; diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 0e9866667e..7bb177751f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -298,12 +298,10 @@ void dmuxQueryEsAttr(u32 info /* may be 0 */, vm::ptr cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2); } -u32 dmuxOpen(Demuxer* dmux_ptr) +void dmuxOpen(u32 dmux_id) // TODO: call from the constructor { - std::shared_ptr sptr(dmux_ptr); - Demuxer& dmux = *dmux_ptr; - - u32 dmux_id = Emu.GetIdManager().GetNewID(sptr); + const auto sptr = Emu.GetIdManager().get(dmux_id); + Demuxer& dmux = *sptr; dmux.id = dmux_id; @@ -316,9 +314,9 @@ u32 dmuxOpen(Demuxer* dmux_ptr) dmux.dmuxCb->InitRegs(); dmux.dmuxCb->DoRun(); - thread_t t(fmt::format("Demuxer[0x%x] Thread", dmux_id), [dmux_ptr, sptr]() + thread_t t(fmt::format("Demuxer[0x%x] Thread", dmux_id), [sptr]() { - Demuxer& dmux = *dmux_ptr; + Demuxer& dmux = *sptr; DemuxerTask task; DemuxerStream stream = {}; @@ -711,7 +709,7 @@ u32 dmuxOpen(Demuxer* dmux_ptr) } } es.dmux = nullptr; - Emu.GetIdManager().RemoveID(task.es.es); + Emu.GetIdManager().remove(task.es.es); break; } @@ -772,8 +770,6 @@ u32 dmuxOpen(Demuxer* dmux_ptr) dmux.is_finished = true; }); - - return dmux_id; } s32 cellDmuxQueryAttr(vm::ptr type, vm::ptr attr) @@ -813,7 +809,7 @@ s32 cellDmuxOpen(vm::ptr type, vm::ptrmemAddr, res->memSize, cb->cbMsgFunc, cb->cbArg)); + dmuxOpen(*handle = Emu.GetIdManager().make(res->memAddr, res->memSize, cb->cbMsgFunc, cb->cbArg)); return CELL_OK; } @@ -829,7 +825,7 @@ s32 cellDmuxOpenEx(vm::ptr type, vm::ptrmemAddr, resEx->memSize, cb->cbMsgFunc, cb->cbArg)); + dmuxOpen(*handle = Emu.GetIdManager().make(resEx->memAddr, resEx->memSize, cb->cbMsgFunc, cb->cbArg)); return CELL_OK; } @@ -850,7 +846,7 @@ s32 cellDmuxOpen2(vm::ptr type2, vm::ptrmemAddr, res2->memSize, cb->cbMsgFunc, cb->cbArg)); + dmuxOpen(*handle = Emu.GetIdManager().make(res2->memAddr, res2->memSize, cb->cbMsgFunc, cb->cbArg)); return CELL_OK; } @@ -859,7 +855,7 @@ s32 cellDmuxClose(u32 handle) { cellDmux.Warning("cellDmuxClose(handle=0x%x)", handle); - const auto dmux = Emu.GetIdManager().GetIDData(handle); + const auto dmux = Emu.GetIdManager().get(handle); if (!dmux) { @@ -881,7 +877,7 @@ s32 cellDmuxClose(u32 handle) } if (dmux->dmuxCb) Emu.GetCPU().RemoveThread(dmux->dmuxCb->GetId()); - Emu.GetIdManager().RemoveID(handle); + Emu.GetIdManager().remove(handle); return CELL_OK; } @@ -889,7 +885,7 @@ s32 cellDmuxSetStream(u32 handle, u32 streamAddress, u32 streamSize, bool discon { cellDmux.Log("cellDmuxSetStream(handle=0x%x, streamAddress=0x%x, streamSize=%d, discontinuity=%d, userData=0x%llx)", handle, streamAddress, streamSize, discontinuity, userData); - const auto dmux = Emu.GetIdManager().GetIDData(handle); + const auto dmux = Emu.GetIdManager().get(handle); if (!dmux) { @@ -917,7 +913,7 @@ s32 cellDmuxResetStream(u32 handle) { cellDmux.Warning("cellDmuxResetStream(handle=0x%x)", handle); - const auto dmux = Emu.GetIdManager().GetIDData(handle); + const auto dmux = Emu.GetIdManager().get(handle); if (!dmux) { @@ -932,7 +928,7 @@ s32 cellDmuxResetStreamAndWaitDone(u32 handle) { cellDmux.Warning("cellDmuxResetStreamAndWaitDone(handle=0x%x)", handle); - const auto dmux = Emu.GetIdManager().GetIDData(handle); + const auto dmux = Emu.GetIdManager().get(handle); if (!dmux) { @@ -993,7 +989,7 @@ s32 cellDmuxEnableEs(u32 handle, vm::ptr esFilterId, { cellDmux.Warning("cellDmuxEnableEs(handle=0x%x, esFilterId=*0x%x, esResourceInfo=*0x%x, esCb=*0x%x, esSpecificInfo=*0x%x, esHandle=*0x%x)", handle, esFilterId, esResourceInfo, esCb, esSpecificInfo, esHandle); - const auto dmux = Emu.GetIdManager().GetIDData(handle); + const auto dmux = Emu.GetIdManager().get(handle); if (!dmux) { @@ -1002,11 +998,11 @@ s32 cellDmuxEnableEs(u32 handle, vm::ptr esFilterId, // TODO: check esFilterId, esResourceInfo, esCb and esSpecificInfo correctly - std::shared_ptr es(new ElementaryStream(dmux.get(), esResourceInfo->memAddr, esResourceInfo->memSize, + auto es = std::make_shared(dmux.get(), esResourceInfo->memAddr, esResourceInfo->memSize, esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2, - esCb->cbEsMsgFunc, esCb->cbArg, esSpecificInfo)); + esCb->cbEsMsgFunc, esCb->cbArg, esSpecificInfo); - u32 id = Emu.GetIdManager().GetNewID(es); + u32 id = Emu.GetIdManager().add(es); es->id = id; *esHandle = id; @@ -1025,7 +1021,7 @@ s32 cellDmuxDisableEs(u32 esHandle) { cellDmux.Warning("cellDmuxDisableEs(esHandle=0x%x)", esHandle); - const auto es = Emu.GetIdManager().GetIDData(esHandle); + const auto es = Emu.GetIdManager().get(esHandle); if (!es) { @@ -1044,7 +1040,7 @@ s32 cellDmuxResetEs(u32 esHandle) { cellDmux.Log("cellDmuxResetEs(esHandle=0x%x)", esHandle); - const auto es = Emu.GetIdManager().GetIDData(esHandle); + const auto es = Emu.GetIdManager().get(esHandle); if (!es) { @@ -1063,7 +1059,7 @@ s32 cellDmuxGetAu(u32 esHandle, vm::ptr auInfo, vm::ptr auSpecificInfo { cellDmux.Log("cellDmuxGetAu(esHandle=0x%x, auInfo=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfo, auSpecificInfo); - const auto es = Emu.GetIdManager().GetIDData(esHandle); + const auto es = Emu.GetIdManager().get(esHandle); if (!es) { @@ -1086,7 +1082,7 @@ s32 cellDmuxPeekAu(u32 esHandle, vm::ptr auInfo, vm::ptr auSpecificInf { cellDmux.Log("cellDmuxPeekAu(esHandle=0x%x, auInfo=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfo, auSpecificInfo); - const auto es = Emu.GetIdManager().GetIDData(esHandle); + const auto es = Emu.GetIdManager().get(esHandle); if (!es) { @@ -1109,7 +1105,7 @@ s32 cellDmuxGetAuEx(u32 esHandle, vm::ptr auInfoEx, vm::ptr auSpecific { cellDmux.Log("cellDmuxGetAuEx(esHandle=0x%x, auInfoEx=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfoEx, auSpecificInfo); - const auto es = Emu.GetIdManager().GetIDData(esHandle); + const auto es = Emu.GetIdManager().get(esHandle); if (!es) { @@ -1132,7 +1128,7 @@ s32 cellDmuxPeekAuEx(u32 esHandle, vm::ptr auInfoEx, vm::ptr auSpecifi { cellDmux.Log("cellDmuxPeekAuEx(esHandle=0x%x, auInfoEx=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfoEx, auSpecificInfo); - const auto es = Emu.GetIdManager().GetIDData(esHandle); + const auto es = Emu.GetIdManager().get(esHandle); if (!es) { @@ -1155,7 +1151,7 @@ s32 cellDmuxReleaseAu(u32 esHandle) { cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle); - const auto es = Emu.GetIdManager().GetIDData(esHandle); + const auto es = Emu.GetIdManager().get(esHandle); if (!es) { @@ -1173,7 +1169,7 @@ s32 cellDmuxFlushEs(u32 esHandle) { cellDmux.Warning("cellDmuxFlushEs(esHandle=0x%x)", esHandle); - const auto es = Emu.GetIdManager().GetIDData(esHandle); + const auto es = Emu.GetIdManager().get(esHandle); if (!es) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellFiber.cpp b/rpcs3/Emu/SysCalls/Modules/cellFiber.cpp index 5b51c39312..77d1c9aa7b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFiber.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellFiber.cpp @@ -293,57 +293,57 @@ int cellFiberPpuUtilWorkerControlInitializeWithAttribute() Module cellFiber("cellFiber", []() { - REG_FUNC(cellFiber, _cellFiberPpuInitialize); + REG_FUNC_NR(cellFiber, _cellFiberPpuInitialize); - REG_FUNC(cellFiber, _cellFiberPpuSchedulerAttributeInitialize); - REG_FUNC(cellFiber, cellFiberPpuInitializeScheduler); - REG_FUNC(cellFiber, cellFiberPpuFinalizeScheduler); - REG_FUNC(cellFiber, cellFiberPpuRunFibers); - REG_FUNC(cellFiber, cellFiberPpuCheckFlags); - REG_FUNC(cellFiber, cellFiberPpuHasRunnableFiber); + REG_FUNC_NR(cellFiber, _cellFiberPpuSchedulerAttributeInitialize); + REG_FUNC_NR(cellFiber, cellFiberPpuInitializeScheduler); + REG_FUNC_NR(cellFiber, cellFiberPpuFinalizeScheduler); + REG_FUNC_NR(cellFiber, cellFiberPpuRunFibers); + REG_FUNC_NR(cellFiber, cellFiberPpuCheckFlags); + REG_FUNC_NR(cellFiber, cellFiberPpuHasRunnableFiber); - REG_FUNC(cellFiber, _cellFiberPpuAttributeInitialize); - REG_FUNC(cellFiber, cellFiberPpuCreateFiber); - REG_FUNC(cellFiber, cellFiberPpuExit); - REG_FUNC(cellFiber, cellFiberPpuYield); - REG_FUNC(cellFiber, cellFiberPpuJoinFiber); - REG_FUNC(cellFiber, cellFiberPpuSelf); - REG_FUNC(cellFiber, cellFiberPpuSendSignal); - REG_FUNC(cellFiber, cellFiberPpuWaitSignal); - REG_FUNC(cellFiber, cellFiberPpuWaitFlag); - REG_FUNC(cellFiber, cellFiberPpuGetScheduler); - REG_FUNC(cellFiber, cellFiberPpuSetPriority); - REG_FUNC(cellFiber, cellFiberPpuCheckStackLimit); + REG_FUNC_NR(cellFiber, _cellFiberPpuAttributeInitialize); + REG_FUNC_NR(cellFiber, cellFiberPpuCreateFiber); + REG_FUNC_NR(cellFiber, cellFiberPpuExit); + REG_FUNC_NR(cellFiber, cellFiberPpuYield); + REG_FUNC_NR(cellFiber, cellFiberPpuJoinFiber); + REG_FUNC_NR(cellFiber, cellFiberPpuSelf); + REG_FUNC_NR(cellFiber, cellFiberPpuSendSignal); + REG_FUNC_NR(cellFiber, cellFiberPpuWaitSignal); + REG_FUNC_NR(cellFiber, cellFiberPpuWaitFlag); + REG_FUNC_NR(cellFiber, cellFiberPpuGetScheduler); + REG_FUNC_NR(cellFiber, cellFiberPpuSetPriority); + REG_FUNC_NR(cellFiber, cellFiberPpuCheckStackLimit); - REG_FUNC(cellFiber, _cellFiberPpuContextAttributeInitialize); - REG_FUNC(cellFiber, cellFiberPpuContextInitialize); - REG_FUNC(cellFiber, cellFiberPpuContextFinalize); - REG_FUNC(cellFiber, cellFiberPpuContextRun); - REG_FUNC(cellFiber, cellFiberPpuContextSwitch); - REG_FUNC(cellFiber, cellFiberPpuContextSelf); - REG_FUNC(cellFiber, cellFiberPpuContextReturnToThread); - REG_FUNC(cellFiber, cellFiberPpuContextCheckStackLimit); + REG_FUNC_NR(cellFiber, _cellFiberPpuContextAttributeInitialize); + REG_FUNC_NR(cellFiber, cellFiberPpuContextInitialize); + REG_FUNC_NR(cellFiber, cellFiberPpuContextFinalize); + REG_FUNC_NR(cellFiber, cellFiberPpuContextRun); + REG_FUNC_NR(cellFiber, cellFiberPpuContextSwitch); + REG_FUNC_NR(cellFiber, cellFiberPpuContextSelf); + REG_FUNC_NR(cellFiber, cellFiberPpuContextReturnToThread); + REG_FUNC_NR(cellFiber, cellFiberPpuContextCheckStackLimit); - REG_FUNC(cellFiber, cellFiberPpuContextRunScheduler); - REG_FUNC(cellFiber, cellFiberPpuContextEnterScheduler); + REG_FUNC_NR(cellFiber, cellFiberPpuContextRunScheduler); + REG_FUNC_NR(cellFiber, cellFiberPpuContextEnterScheduler); - REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceInitialize); - REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceFinalize); - REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStart); - REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStop); + REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceInitialize); + REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceFinalize); + REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStart); + REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStop); - REG_FUNC(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlRunFibers); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitialize); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSendSignal); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlFinalize); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlWakeup); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlShutdown); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags); - REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute); + REG_FUNC_NR(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlRunFibers); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitialize); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSendSignal); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlFinalize); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlWakeup); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlShutdown); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags); + REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute); }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp b/rpcs3/Emu/SysCalls/Modules/cellFs.cpp index daadb68b59..c0aa4254d2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellFs.cpp @@ -210,7 +210,7 @@ s32 cellFsGetDirectoryEntries(u32 fd, vm::ptr entries, u32 { cellFs.Warning("cellFsGetDirectoryEntries(fd=0x%x, entries=*0x%x, entries_size=0x%x, data_count=*0x%x)", fd, entries, entries_size, data_count); - const auto directory = Emu.GetIdManager().GetIDData(fd); + const auto directory = Emu.GetIdManager().get(fd); if (!directory) { @@ -255,7 +255,7 @@ s32 cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr buf, u64 buffer_size, // TODO: use single sys_fs_fcntl syscall - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file || file->flags & CELL_FS_O_WRONLY) { @@ -286,7 +286,7 @@ s32 cellFsWriteWithOffset(u32 fd, u64 offset, vm::ptr buf, u64 data_ // TODO: use single sys_fs_fcntl syscall - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file || !(file->flags & CELL_FS_O_ACCMODE)) { @@ -330,7 +330,7 @@ s32 cellFsStReadInit(u32 fd, vm::ptr ringbuf) return CELL_FS_EINVAL; } - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -368,7 +368,7 @@ s32 cellFsStReadFinish(u32 fd) { cellFs.Warning("cellFsStReadFinish(fd=0x%x)", fd); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -391,7 +391,7 @@ s32 cellFsStReadGetRingBuf(u32 fd, vm::ptr ringbuf) { cellFs.Warning("cellFsStReadGetRingBuf(fd=0x%x, ringbuf=*0x%x)", fd, ringbuf); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -415,7 +415,7 @@ s32 cellFsStReadGetStatus(u32 fd, vm::ptr status) { cellFs.Warning("cellFsStReadGetRingBuf(fd=0x%x, status=*0x%x)", fd, status); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -449,7 +449,7 @@ s32 cellFsStReadGetRegid(u32 fd, vm::ptr regid) { cellFs.Warning("cellFsStReadGetRingBuf(fd=0x%x, regid=*0x%x)", fd, regid); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -470,7 +470,7 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size) { cellFs.Warning("cellFsStReadStart(fd=0x%x, offset=0x%llx, size=0x%llx)", fd, offset, size); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -552,7 +552,7 @@ s32 cellFsStReadStop(u32 fd) { cellFs.Warning("cellFsStReadStop(fd=0x%x)", fd); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -583,7 +583,7 @@ s32 cellFsStRead(u32 fd, vm::ptr buf, u64 size, vm::ptr rsize) { cellFs.Warning("cellFsStRead(fd=0x%x, buf=*0x%x, size=0x%llx, rsize=*0x%x)", fd, buf, size, rsize); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -617,7 +617,7 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr addr, vm::ptr size) { cellFs.Warning("cellFsStReadGetCurrentAddr(fd=0x%x, addr=*0x%x, size=*0x%x)", fd, addr, size); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -650,7 +650,7 @@ s32 cellFsStReadPutCurrentAddr(u32 fd, vm::ptr addr, u64 size) { cellFs.Warning("cellFsStReadPutCurrentAddr(fd=0x%x, addr=*0x%x, size=0x%llx)", fd, addr, size); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -677,7 +677,7 @@ s32 cellFsStReadWait(u32 fd, u64 size) { cellFs.Warning("cellFsStReadWait(fd=0x%x, size=0x%llx)", fd, size); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -711,7 +711,7 @@ s32 cellFsStReadWaitCallback(u32 fd, u64 size, fs_st_cb_t func) { cellFs.Warning("cellFsStReadWaitCallback(fd=0x%x, size=0x%llx, func=*0x%x)", fd, size, func); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -879,7 +879,7 @@ void fsAio(vm::ptr aio, bool write, s32 xid, fs_aio_cb_t func) s32 error = CELL_OK; u64 result = 0; - const auto file = Emu.GetIdManager().GetIDData(aio->fd); + const auto file = Emu.GetIdManager().get(aio->fd); if (!file || (!write && file->flags & CELL_FS_O_WRONLY) || (write && !(file->flags & CELL_FS_O_ACCMODE))) { @@ -931,11 +931,6 @@ s32 cellFsAioRead(vm::ptr aio, vm::ptr id, fs_aio_cb_t func) { cellFs.Warning("cellFsAioRead(aio=*0x%x, id=*0x%x, func=*0x%x)", aio, id, func); - if (!Emu.GetIdManager().CheckID(aio->fd)) - { - return CELL_FS_EBADF; - } - // TODO: detect mount point and send AIO request to the AIO thread of this mount point const s32 xid = (*id = ++g_fs_aio_id); @@ -949,11 +944,6 @@ s32 cellFsAioWrite(vm::ptr aio, vm::ptr id, fs_aio_cb_t func) { cellFs.Warning("cellFsAioWrite(aio=*0x%x, id=*0x%x, func=*0x%x)", aio, id, func); - if (!Emu.GetIdManager().CheckID(aio->fd)) - { - return CELL_FS_EBADF; - } - // TODO: detect mount point and send AIO request to the AIO thread of this mount point const s32 xid = (*id = ++g_fs_aio_id); @@ -983,7 +973,7 @@ s32 cellFsSetIoBufferFromDefaultContainer(u32 fd, u32 buffer_size, u32 page_type { cellFs.Todo("cellFsSetIoBufferFromDefaultContainer(fd=0x%x, buffer_size=%d, page_type=%d)", fd, buffer_size, page_type); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp index e6c3da6484..352cedc091 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp @@ -34,7 +34,7 @@ s32 cellGifDecOpen(u32 mainHandle, vm::ptr subHandle, vm::ptr current_subHandle(new CellGifDecSubHandle); + auto current_subHandle = std::make_shared(); current_subHandle->fd = 0; current_subHandle->src = *src; @@ -48,16 +48,16 @@ s32 cellGifDecOpen(u32 mainHandle, vm::ptr subHandle, vm::ptr file_s(Emu.GetVFS().OpenFile(src->fileName.get_ptr(), vfsRead)); - std::shared_ptr file(new fs_file_t(file_s, 0, 0)); - if (!file) return CELL_GIFDEC_ERROR_OPEN_FILE; - current_subHandle->fd = Emu.GetIdManager().GetNewID(file, TYPE_FS_FILE); - current_subHandle->fileSize = file->file->GetSize(); + if (!file_s) return CELL_GIFDEC_ERROR_OPEN_FILE; + + current_subHandle->fd = Emu.GetIdManager().make(file_s, 0, 0); + current_subHandle->fileSize = file_s->GetSize(); break; } } // From now, every u32 subHandle argument is a pointer to a CellGifDecSubHandle struct. - *subHandle = Emu.GetIdManager().GetNewID(current_subHandle); + *subHandle = Emu.GetIdManager().add(std::move(current_subHandle)); return CELL_OK; } @@ -66,7 +66,7 @@ s32 cellGifDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr { cellGifDec.Warning("cellGifDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info=*0x%x)", mainHandle, subHandle, info); - const auto subHandle_data = Emu.GetIdManager().GetIDData(subHandle); + const auto subHandle_data = Emu.GetIdManager().get(subHandle); if (!subHandle_data) { @@ -88,7 +88,7 @@ s32 cellGifDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr case se32(CELL_GIFDEC_FILE): { - auto file = Emu.GetIdManager().GetIDData(fd); + auto file = Emu.GetIdManager().get(fd); file->file->Seek(0); file->file->Read(buffer.begin(), buffer.size()); break; @@ -120,7 +120,7 @@ s32 cellGifDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr(subHandle); + const auto subHandle_data = Emu.GetIdManager().get(subHandle); if (!subHandle_data) { @@ -154,7 +154,7 @@ s32 cellGifDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_STOP; - const auto subHandle_data = Emu.GetIdManager().GetIDData(subHandle); + const auto subHandle_data = Emu.GetIdManager().get(subHandle); if (!subHandle_data) { @@ -176,7 +176,7 @@ s32 cellGifDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt case se32(CELL_GIFDEC_FILE): { - auto file = Emu.GetIdManager().GetIDData(fd); + auto file = Emu.GetIdManager().get(fd); file->file->Seek(0); file->file->Read(gif.ptr(), gif.size()); break; @@ -273,15 +273,15 @@ s32 cellGifDecClose(u32 mainHandle, u32 subHandle) { cellGifDec.Warning("cellGifDecClose(mainHandle=0x%x, subHandle=0x%x)", mainHandle, subHandle); - const auto subHandle_data = Emu.GetIdManager().GetIDData(subHandle); + const auto subHandle_data = Emu.GetIdManager().get(subHandle); if (!subHandle_data) { return CELL_GIFDEC_ERROR_FATAL; } - Emu.GetIdManager().RemoveID(subHandle_data->fd); - Emu.GetIdManager().RemoveID(subHandle); + Emu.GetIdManager().remove(subHandle_data->fd); + Emu.GetIdManager().remove(subHandle); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp index eb9463603c..4f04d0ab20 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp @@ -39,7 +39,7 @@ s32 cellJpgDecOpen(u32 mainHandle, vm::ptr subHandle, vm::ptr current_subHandle(new CellJpgDecSubHandle); + auto current_subHandle = std::make_shared(); current_subHandle->fd = 0; current_subHandle->src = *src; @@ -54,16 +54,16 @@ s32 cellJpgDecOpen(u32 mainHandle, vm::ptr subHandle, vm::ptr file_s(Emu.GetVFS().OpenFile(src->fileName.get_ptr(), vfsRead)); - std::shared_ptr file(new fs_file_t(file_s, 0, 0)); - if (!file) return CELL_JPGDEC_ERROR_OPEN_FILE; - current_subHandle->fd = Emu.GetIdManager().GetNewID(file, TYPE_FS_FILE); - current_subHandle->fileSize = file->file->GetSize(); + if (!file_s) return CELL_JPGDEC_ERROR_OPEN_FILE; + + current_subHandle->fd = Emu.GetIdManager().make(file_s, 0, 0); + current_subHandle->fileSize = file_s->GetSize(); break; } } // From now, every u32 subHandle argument is a pointer to a CellJpgDecSubHandle struct. - *subHandle = Emu.GetIdManager().GetNewID(current_subHandle); + *subHandle = Emu.GetIdManager().add(std::move(current_subHandle)); return CELL_OK; } @@ -72,15 +72,15 @@ s32 cellJpgDecClose(u32 mainHandle, u32 subHandle) { cellJpgDec.Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle=0x%x)", mainHandle, subHandle); - const auto subHandle_data = Emu.GetIdManager().GetIDData(subHandle); + const auto subHandle_data = Emu.GetIdManager().get(subHandle); if (!subHandle_data) { return CELL_JPGDEC_ERROR_FATAL; } - Emu.GetIdManager().RemoveID(subHandle_data->fd); - Emu.GetIdManager().RemoveID(subHandle); + Emu.GetIdManager().remove(subHandle_data->fd); + Emu.GetIdManager().remove(subHandle); return CELL_OK; } @@ -89,7 +89,7 @@ s32 cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr { cellJpgDec.Log("cellJpgDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info=*0x%x)", mainHandle, subHandle, info); - const auto subHandle_data = Emu.GetIdManager().GetIDData(subHandle); + const auto subHandle_data = Emu.GetIdManager().get(subHandle); if (!subHandle_data) { @@ -111,7 +111,7 @@ s32 cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr case se32(CELL_JPGDEC_FILE): { - auto file = Emu.GetIdManager().GetIDData(fd); + auto file = Emu.GetIdManager().get(fd); file->file->Seek(0); file->file->Read(buffer.ptr(), buffer.size()); break; @@ -163,7 +163,7 @@ s32 cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_STOP; - const auto subHandle_data = Emu.GetIdManager().GetIDData(subHandle); + const auto subHandle_data = Emu.GetIdManager().get(subHandle); if (!subHandle_data) { @@ -185,7 +185,7 @@ s32 cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt case se32(CELL_JPGDEC_FILE): { - auto file = Emu.GetIdManager().GetIDData(fd); + auto file = Emu.GetIdManager().get(fd); file->file->Seek(0); file->file->Read(jpg.ptr(), jpg.size()); break; @@ -297,7 +297,7 @@ s32 cellJpgDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr(subHandle); + const auto subHandle_data = Emu.GetIdManager().get(subHandle); if (!subHandle_data) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index 4f5ece6bfb..58eab5a692 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -86,10 +86,10 @@ s32 pngDecOpen( { // Get file descriptor and size std::shared_ptr file_s(Emu.GetVFS().OpenFile(src->fileName.get_ptr(), vfsRead)); - std::shared_ptr file(new fs_file_t(file_s, 0, 0)); - if (!file) return CELL_PNGDEC_ERROR_OPEN_FILE; - stream->fd = Emu.GetIdManager().GetNewID(file, TYPE_FS_FILE); - stream->fileSize = file->file->GetSize(); + if (!file_s) return CELL_PNGDEC_ERROR_OPEN_FILE; + + stream->fd = Emu.GetIdManager().make(file_s, 0, 0); + stream->fileSize = file_s->GetSize(); break; } } @@ -115,7 +115,7 @@ s32 pngDecOpen( s32 pngDecClose(CellPngDecSubHandle stream) { - Emu.GetIdManager().RemoveID(stream->fd); + Emu.GetIdManager().remove(stream->fd); if (!Memory.Free(stream.addr())) { @@ -148,7 +148,7 @@ s32 pngReadHeader( break; case se32(CELL_PNGDEC_FILE): { - auto file = Emu.GetIdManager().GetIDData(stream->fd); + auto file = Emu.GetIdManager().get(stream->fd); file->file->Seek(0); file->file->Read(buffer.begin(), buffer.size()); break; @@ -260,7 +260,7 @@ s32 pngDecodeData( case se32(CELL_PNGDEC_FILE): { - auto file = Emu.GetIdManager().GetIDData(stream->fd); + auto file = Emu.GetIdManager().get(stream->fd); file->file->Seek(0); file->file->Read(png.ptr(), png.size()); break; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index a2f2cd8860..a585717aff 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -33,7 +33,7 @@ enum : u32 SAVEDATA_OP_FIXED_DELETE = 14, }; -__noinline s32 savedata_op( +never_inline s32 savedata_op( PPUThread& CPU, u32 operation, u32 version, @@ -61,7 +61,8 @@ __noinline s32 savedata_op( return CELL_SAVEDATA_ERROR_BUSY; } - std::string base_dir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current or specified user + // path of the specified user (00000001 by default) + const std::string base_dir = fmt::format("/dev_hdd0/home/%08d/savedata/", userId ? userId : 1u); vm::stackvar result(CPU); @@ -498,7 +499,7 @@ __noinline s32 savedata_op( fileGet->excSize = 0; memset(fileGet->reserved, 0, sizeof(fileGet->reserved)); - while (true) + while (funcFile) { funcFile(CPU, result, fileGet, fileSet); @@ -785,10 +786,10 @@ s32 cellSaveDataUserListSave( u32 container, vm::ptr userdata) { - cellSysutil.Todo("cellSaveDataUserListSave(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSysutil.Error("cellSaveDataUserListSave(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, setList, setBuf, funcList, funcStat, funcFile, container, userdata); - return CELL_OK; + return savedata_op(CPU, SAVEDATA_OP_LIST_SAVE, version, vm::null, 0, setList, setBuf, funcList, vm::null, funcStat, funcFile, container, 6, userdata, userId, vm::null); } s32 cellSaveDataUserListLoad( @@ -803,10 +804,10 @@ s32 cellSaveDataUserListLoad( u32 container, vm::ptr userdata) { - cellSysutil.Todo("cellSaveDataUserListLoad(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSysutil.Error("cellSaveDataUserListLoad(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, setList, setBuf, funcList, funcStat, funcFile, container, userdata); - return CELL_OK; + return savedata_op(CPU, SAVEDATA_OP_LIST_LOAD, version, vm::null, 0, setList, setBuf, funcList, vm::null, funcStat, funcFile, container, 6, userdata, userId, vm::null); } s32 cellSaveDataUserFixedSave( @@ -821,10 +822,10 @@ s32 cellSaveDataUserFixedSave( u32 container, vm::ptr userdata) { - cellSysutil.Todo("cellSaveDataUserFixedSave(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSysutil.Error("cellSaveDataUserFixedSave(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); - return CELL_OK; + return savedata_op(CPU, SAVEDATA_OP_FIXED_SAVE, version, vm::null, 0, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); } s32 cellSaveDataUserFixedLoad( @@ -839,10 +840,10 @@ s32 cellSaveDataUserFixedLoad( u32 container, vm::ptr userdata) { - cellSysutil.Todo("cellSaveDataUserFixedLoad(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSysutil.Error("cellSaveDataUserFixedLoad(version=%d, userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); - return CELL_OK; + return savedata_op(CPU, SAVEDATA_OP_FIXED_LOAD, version, vm::null, 0, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); } s32 cellSaveDataUserAutoSave( @@ -857,10 +858,10 @@ s32 cellSaveDataUserAutoSave( u32 container, vm::ptr userdata) { - cellSysutil.Todo("cellSaveDataUserAutoSave(version=%d, userId=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSysutil.Error("cellSaveDataUserAutoSave(version=%d, userId=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, dirName, errDialog, setBuf, funcStat, funcFile, container, userdata); - return CELL_OK; + return savedata_op(CPU, SAVEDATA_OP_AUTO_SAVE, version, dirName, errDialog, vm::null, setBuf, vm::null, vm::null, funcStat, funcFile, container, 6, userdata, userId, vm::null); } s32 cellSaveDataUserAutoLoad( @@ -875,10 +876,10 @@ s32 cellSaveDataUserAutoLoad( u32 container, vm::ptr userdata) { - cellSysutil.Todo("cellSaveDataUserAutoLoad(version=%d, userId=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSysutil.Error("cellSaveDataUserAutoLoad(version=%d, userId=%d, dirName=*0x%x, errDialog=%d, setBuf=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, dirName, errDialog, setBuf, funcStat, funcFile, container, userdata); - return CELL_OK; + return savedata_op(CPU, SAVEDATA_OP_AUTO_LOAD, version, dirName, errDialog, vm::null, setBuf, vm::null, vm::null, funcStat, funcFile, container, 6, userdata, userId, vm::null); } s32 cellSaveDataUserListAutoSave( @@ -894,10 +895,10 @@ s32 cellSaveDataUserListAutoSave( u32 container, vm::ptr userdata) { - cellSysutil.Todo("cellSaveDataUserListAutoSave(version=%d, userId=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSysutil.Error("cellSaveDataUserListAutoSave(version=%d, userId=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, errDialog, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); - return CELL_OK; + return savedata_op(CPU, SAVEDATA_OP_LIST_AUTO_SAVE, version, vm::null, errDialog, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); } s32 cellSaveDataUserListAutoLoad( @@ -913,10 +914,10 @@ s32 cellSaveDataUserListAutoLoad( u32 container, vm::ptr userdata) { - cellSysutil.Todo("cellSaveDataUserListAutoLoad(version=%d, userId=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", + cellSysutil.Error("cellSaveDataUserListAutoLoad(version=%d, userId=%d, errDialog=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x, userdata=*0x%x)", version, userId, errDialog, setList, setBuf, funcFixed, funcStat, funcFile, container, userdata); - return CELL_OK; + return savedata_op(CPU, SAVEDATA_OP_LIST_AUTO_LOAD, version, vm::null, errDialog, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 6, userdata, userId, vm::null); } s32 cellSaveDataUserFixedDelete( @@ -937,7 +938,7 @@ s32 cellSaveDataUserFixedDelete( void cellSaveDataEnableOverlay(s32 enable) { - cellSysutil.Todo("cellSaveDataEnableOverlay(enable=%d)", enable); + cellSysutil.Error("cellSaveDataEnableOverlay(enable=%d)", enable); return; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 9f49bea788..4f95d79c20 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -3,6 +3,8 @@ #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/CB_FUNC.h" +#include "Emu/IdManager.h" +#include "Emu/Event.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/SPUThread.h" @@ -27,16 +29,20 @@ s32 _cellSpursSendSignal(vm::ptr taskset, u32 taskID); s32 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptr port, s32 size, u64 name_u64) { - queue_id = event_queue_create(SYS_SYNC_FIFO, SYS_PPU_QUEUE, name_u64, 0, size); - if (!queue_id) + auto queue = Emu.GetEventManager().MakeEventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, name_u64, 0, size); + + if (!queue) // rough { - return CELL_EAGAIN; // rough + return CELL_EAGAIN; } + queue_id = Emu.GetIdManager().add(std::move(queue)); + if (s32 res = spursAttachLv2EventQueue(spurs, queue_id, port, 1, true)) { assert(!"spursAttachLv2EventQueue() failed"); } + return CELL_OK; } @@ -105,7 +111,7 @@ s32 spursInit( u32 sem; for (u32 i = 0; i < 0x10; i++) { - sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl"); + sem = Emu.GetIdManager().make(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl"); assert(sem && ~sem); // should rollback if semaphore creation failed and return the error spurs->m.wklF1[i].sem = sem; } @@ -113,12 +119,12 @@ s32 spursInit( { for (u32 i = 0; i < 0x10; i++) { - sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl"); + sem = Emu.GetIdManager().make(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuWkl"); assert(sem && ~sem); spurs->m.wklF2[i].sem = sem; } } - sem = semaphore_create(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuPrv"); + sem = Emu.GetIdManager().make(0, 1, SYS_SYNC_PRIORITY, *(u64*)"_spuPrv"); assert(sem && ~sem); spurs->m.semPrv = sem; spurs->m.unk11 = -1; @@ -186,7 +192,7 @@ s32 spursInit( } spurs->m.queue = queue; - u32 port = event_port_create(0); + u32 port = Emu.GetIdManager().make(SYS_EVENT_PORT_LOCAL, 0); assert(port && ~port); spurs->m.port = port; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index b45ac75b60..fb84c1f541 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -304,7 +304,7 @@ struct CellSpursWorkloadFlag { be_t unused0; be_t unused1; - atomic_t flag; + atomic_be_t flag; }; typedef void(CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); @@ -412,7 +412,7 @@ struct CellSpurs vm::bptr addr; // Address of the executable be_t arg; // spu argument be_t size; - atomic_t uniqueId; // The unique id is the same for all workloads with the same addr + atomic_be_t uniqueId; // The unique id is the same for all workloads with the same addr u8 pad[3]; u8 priority[8]; }; @@ -436,30 +436,30 @@ struct CellSpurs // real data struct { - atomic_t wklReadyCount1[0x10]; // 0x00 Number of SPUs requested by each workload (0..15 wids). - atomic_t wklIdleSpuCountOrReadyCount2[0x10]; // 0x10 SPURS1: Number of idle SPUs requested by each workload (0..15 wids). SPURS2: Number of SPUs requested by each workload (16..31 wids). + atomic_be_t wklReadyCount1[0x10]; // 0x00 Number of SPUs requested by each workload (0..15 wids). + atomic_be_t wklIdleSpuCountOrReadyCount2[0x10]; // 0x10 SPURS1: Number of idle SPUs requested by each workload (0..15 wids). SPURS2: Number of SPUs requested by each workload (16..31 wids). u8 wklCurrentContention[0x10]; // 0x20 Number of SPUs used by each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. u8 wklPendingContention[0x10]; // 0x30 Number of SPUs that are pending to context switch to the workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. u8 wklMinContention[0x10]; // 0x40 Min SPUs required for each workload. SPURS1: index = wid. SPURS2: Unused. - atomic_t wklMaxContention[0x10]; // 0x50 Max SPUs that may be allocated to each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. + atomic_be_t wklMaxContention[0x10]; // 0x50 Max SPUs that may be allocated to each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. CellSpursWorkloadFlag wklFlag; // 0x60 - atomic_t wklSignal1; // 0x70 (bitset for 0..15 wids) - atomic_t sysSrvMessage; // 0x72 + atomic_be_t wklSignal1; // 0x70 (bitset for 0..15 wids) + atomic_be_t sysSrvMessage; // 0x72 u8 spuIdling; // 0x73 u8 flags1; // 0x74 Type is SpursFlags1 u8 sysSrvTraceControl; // 0x75 u8 nSpus; // 0x76 - atomic_t wklFlagReceiver; // 0x77 - atomic_t wklSignal2; // 0x78 (bitset for 16..32 wids) + atomic_be_t wklFlagReceiver; // 0x77 + atomic_be_t wklSignal2; // 0x78 (bitset for 16..32 wids) u8 x7A[6]; // 0x7A - atomic_t wklState1[0x10]; // 0x80 SPURS_WKL_STATE_* + atomic_be_t wklState1[0x10]; // 0x80 SPURS_WKL_STATE_* u8 wklStatus1[0x10]; // 0x90 u8 wklEvent1[0x10]; // 0xA0 - atomic_t wklMskA; // 0xB0 - System service - Available workloads (32*u1) - atomic_t wklMskB; // 0xB4 - System service - Available module id + atomic_be_t wklMskA; // 0xB0 - System service - Available workloads (32*u1) + atomic_be_t wklMskB; // 0xB4 - System service - Available module id u32 xB8; // 0xB8 u8 sysSrvExitBarrier; // 0xBC - atomic_t sysSrvMsgUpdateWorkload; // 0xBD + atomic_be_t sysSrvMsgUpdateWorkload; // 0xBD u8 xBE; // 0xBE u8 sysSrvMsgTerminate; // 0xBF u8 sysSrvWorkload[8]; // 0xC0 @@ -471,7 +471,7 @@ struct CellSpurs u8 xCD; // 0xCD u8 sysSrvMsgUpdateTrace; // 0xCE u8 xCF; // 0xCF - atomic_t wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_* + atomic_be_t wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_* u8 wklStatus2[0x10]; // 0xE0 u8 wklEvent2[0x10]; // 0xF0 _sub_str1 wklF1[0x10]; // 0x100 @@ -495,10 +495,10 @@ struct CellSpurs u8 unknown3[0xD5C - 0xD54]; be_t queue; // 0xD5C - Event queue be_t port; // 0xD60 - Event port - atomic_t xD64; // 0xD64 - SPURS handler dirty - atomic_t xD65; // 0xD65 - SPURS handler waiting - atomic_t xD66; // 0xD66 - SPURS handler exiting - atomic_t enableEH; // 0xD68 + atomic_be_t xD64; // 0xD64 - SPURS handler dirty + atomic_be_t xD65; // 0xD65 - SPURS handler waiting + atomic_be_t xD66; // 0xD66 - SPURS handler exiting + atomic_be_t enableEH; // 0xD68 be_t exception; // 0xD6C sys_spu_image spuImg; // 0xD70 be_t flags; // 0xD80 @@ -509,7 +509,7 @@ struct CellSpurs be_t unk5; // 0xD9C be_t revision; // 0xDA0 be_t sdkVersion; // 0xDA4 - atomic_t spups; // 0xDA8 - SPU port bits + atomic_be_t spups; // 0xDA8 - SPU port bits sys_lwmutex_t mutex; // 0xDB0 sys_lwcond_t cond; // 0xDC8 u8 unknown9[0xE00 - 0xDD0]; @@ -528,7 +528,7 @@ struct CellSpurs } c; }; - __forceinline atomic_t& wklState(const u32 wid) + force_inline atomic_be_t& wklState(const u32 wid) { if (wid & 0x10) { @@ -540,12 +540,12 @@ struct CellSpurs } } - __forceinline vm::ptr get_lwmutex() + force_inline vm::ptr get_lwmutex() { return vm::ptr::make(vm::get_addr(&m.mutex)); } - __forceinline vm::ptr get_lwcond() + force_inline vm::ptr get_lwcond() { return vm::ptr::make(vm::get_addr(&m.cond)); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index 0fb5912579..c291d608c1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -39,11 +39,11 @@ union CellSyncMutex struct { - atomic_t release_count; - atomic_t acquire_count; + atomic_be_t release_count; + atomic_be_t acquire_count; }; - atomic_t sync_var; + atomic_be_t sync_var; }; static_assert(sizeof(CellSyncMutex) == 4, "CellSyncMutex: wrong size"); @@ -56,7 +56,7 @@ struct CellSyncBarrier be_t m_count; }; - atomic_t data; + atomic_be_t data; }; static_assert(sizeof(CellSyncBarrier) == 4, "CellSyncBarrier: wrong size"); @@ -69,7 +69,7 @@ struct CellSyncRwm be_t m_writers; }; - atomic_t data; + atomic_be_t data; be_t m_size; vm::bptr m_buffer; }; @@ -84,7 +84,7 @@ struct CellSyncQueue be_t m_v2; }; - atomic_t data; + atomic_be_t data; be_t m_size; be_t m_depth; vm::bptr m_buffer; @@ -143,14 +143,14 @@ struct CellSyncLFQueue union // 0x0 { - atomic_t pop1; - atomic_t pop3; + atomic_be_t pop1; + atomic_be_t pop3; }; union // 0x8 { - atomic_t push1; - atomic_t push3; + atomic_be_t push1; + atomic_be_t push3; }; be_t m_size; // 0x10 @@ -159,10 +159,10 @@ struct CellSyncLFQueue u8 m_bs[4]; // 0x20 be_t m_direction; // 0x24 be_t m_v1; // 0x28 - atomic_t init; // 0x2C - atomic_t push2; // 0x30 + atomic_be_t init; // 0x2C + atomic_be_t push2; // 0x30 be_t m_hs1[15]; // 0x32 - atomic_t pop2; // 0x50 + atomic_be_t pop2; // 0x50 be_t m_hs2[15]; // 0x52 vm::bptr m_eaSignal; // 0x70 be_t m_v2; // 0x78 diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 35d9c100b2..665f8da71b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -207,12 +207,11 @@ u32 vdecQueryAttr(CellVdecCodecType type, u32 profile, u32 spec_addr /* may be 0 return CELL_OK; } -u32 vdecOpen(VideoDecoder* vdec_ptr) +void vdecOpen(u32 vdec_id) // TODO: call from the constructor { - std::shared_ptr sptr(vdec_ptr); - VideoDecoder& vdec = *vdec_ptr; + const auto sptr = Emu.GetIdManager().get(vdec_id); - u32 vdec_id = Emu.GetIdManager().GetNewID(sptr); + VideoDecoder& vdec = *sptr; vdec.id = vdec_id; @@ -225,9 +224,9 @@ u32 vdecOpen(VideoDecoder* vdec_ptr) vdec.vdecCb->InitRegs(); vdec.vdecCb->DoRun(); - thread_t t(fmt::format("VideoDecoder[0x%x] Thread", vdec_id), [vdec_ptr, sptr]() + thread_t t(fmt::format("VideoDecoder[0x%x] Thread", vdec_id), [sptr]() { - VideoDecoder& vdec = *vdec_ptr; + VideoDecoder& vdec = *sptr; VdecTask& task = vdec.task; while (true) @@ -549,8 +548,6 @@ u32 vdecOpen(VideoDecoder* vdec_ptr) vdec.is_finished = true; }); - - return vdec_id; } s32 cellVdecQueryAttr(vm::ptr type, vm::ptr attr) @@ -571,7 +568,7 @@ s32 cellVdecOpen(vm::ptr type, vm::ptrcodecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); + vdecOpen(*handle = Emu.GetIdManager().make(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); return CELL_OK; } @@ -580,7 +577,7 @@ s32 cellVdecOpenEx(vm::ptr type, vm::ptrcodecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); + vdecOpen(*handle = Emu.GetIdManager().make(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); return CELL_OK; } @@ -589,7 +586,7 @@ s32 cellVdecClose(u32 handle) { cellVdec.Warning("cellVdecClose(handle=0x%x)", handle); - const auto vdec = Emu.GetIdManager().GetIDData(handle); + const auto vdec = Emu.GetIdManager().get(handle); if (!vdec) { @@ -610,7 +607,7 @@ s32 cellVdecClose(u32 handle) } if (vdec->vdecCb) Emu.GetCPU().RemoveThread(vdec->vdecCb->GetId()); - Emu.GetIdManager().RemoveID(handle); + Emu.GetIdManager().remove(handle); return CELL_OK; } @@ -618,7 +615,7 @@ s32 cellVdecStartSeq(u32 handle) { cellVdec.Log("cellVdecStartSeq(handle=0x%x)", handle); - const auto vdec = Emu.GetIdManager().GetIDData(handle); + const auto vdec = Emu.GetIdManager().get(handle); if (!vdec) { @@ -633,7 +630,7 @@ s32 cellVdecEndSeq(u32 handle) { cellVdec.Warning("cellVdecEndSeq(handle=0x%x)", handle); - const auto vdec = Emu.GetIdManager().GetIDData(handle); + const auto vdec = Emu.GetIdManager().get(handle); if (!vdec) { @@ -648,7 +645,7 @@ s32 cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::ptr(handle); + const auto vdec = Emu.GetIdManager().get(handle); if (!vdec || mode > CELL_VDEC_DEC_MODE_PB_SKIP) { @@ -678,7 +675,7 @@ s32 cellVdecGetPicture(u32 handle, vm::ptr format, vm:: { cellVdec.Log("cellVdecGetPicture(handle=0x%x, format=*0x%x, outBuff=*0x%x)", handle, format, outBuff); - const auto vdec = Emu.GetIdManager().GetIDData(handle); + const auto vdec = Emu.GetIdManager().get(handle); if (!vdec || !format) { @@ -802,7 +799,7 @@ s32 cellVdecGetPicItem(u32 handle, vm::ptr> picItem) { cellVdec.Log("cellVdecGetPicItem(handle=0x%x, picItem=**0x%x)", handle, picItem); - const auto vdec = Emu.GetIdManager().GetIDData(handle); + const auto vdec = Emu.GetIdManager().get(handle); if (!vdec) { @@ -947,7 +944,7 @@ s32 cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc) { cellVdec.Log("cellVdecSetFrameRate(handle=0x%x, frc=0x%x)", handle, frc); - const auto vdec = Emu.GetIdManager().GetIDData(handle); + const auto vdec = Emu.GetIdManager().get(handle); if (!vdec) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index 9691ff1d93..dab1201638 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -27,22 +27,12 @@ s32 cellVpostQueryAttr(vm::ptr cfgParam, vm::ptr data_ptr(data); - u32 id = Emu.GetIdManager().GetNewID(data_ptr); - - cellVpost.Notice("*** Vpost instance created (to_rgba=%d): id = %d", data->to_rgba, id); - - return id; -} - s32 cellVpostOpen(vm::ptr cfgParam, vm::ptr resource, vm::ptr handle) { cellVpost.Warning("cellVpostOpen(cfgParam=*0x%x, resource=*0x%x, handle=*0x%x)", cfgParam, resource, handle); // TODO: check values - *handle = vpostOpen(new VpostInstance(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV)); + *handle = Emu.GetIdManager().make(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV); return CELL_OK; } @@ -51,7 +41,7 @@ s32 cellVpostOpenEx(vm::ptr cfgParam, vm::ptroutPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV)); + *handle = Emu.GetIdManager().make(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV); return CELL_OK; } @@ -59,14 +49,14 @@ s32 cellVpostClose(u32 handle) { cellVpost.Warning("cellVpostClose(handle=0x%x)", handle); - const auto vpost = Emu.GetIdManager().GetIDData(handle); + const auto vpost = Emu.GetIdManager().get(handle); if (!vpost) { return CELL_VPOST_ERROR_C_ARG_HDL_INVALID; } - Emu.GetIdManager().RemoveID(handle); + Emu.GetIdManager().remove(handle); return CELL_OK; } @@ -74,7 +64,7 @@ s32 cellVpostExec(u32 handle, vm::ptr inPicBuff, vm::ptr(handle); + const auto vpost = Emu.GetIdManager().get(handle); if (!vpost) { diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index b0d5761d15..b356d14ada 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -112,12 +112,10 @@ s32 sys_lwmutex_create(vm::ptr lwmutex, vm::ptr lw(new lwmutex_t(protocol, attr->name_u64)); - lwmutex->lock_var = { { lwmutex::free, lwmutex::zero } }; lwmutex->attribute = attr->recursive | attr->protocol; lwmutex->recursive_count = 0; - lwmutex->sleep_queue = Emu.GetIdManager().GetNewID(lw, TYPE_LWMUTEX); + lwmutex->sleep_queue = Emu.GetIdManager().make(protocol, attr->name_u64); return CELL_OK; } @@ -362,9 +360,7 @@ s32 sys_lwcond_create(vm::ptr lwcond, vm::ptr lwmut { sysPrxForUser.Warning("sys_lwcond_create(lwcond=*0x%x, lwmutex=*0x%x, attr=*0x%x)", lwcond, lwmutex, attr); - std::shared_ptr cond(new lwcond_t(attr->name_u64)); - - lwcond->lwcond_queue = Emu.GetIdManager().GetNewID(cond, TYPE_LWCOND); + lwcond->lwcond_queue = Emu.GetIdManager().make(attr->name_u64); lwcond->lwmutex = lwmutex; return CELL_OK; @@ -770,16 +766,14 @@ u32 _sys_heap_create_heap(vm::ptr name, u32 arg2, u32 arg3, u32 arg4 { sysPrxForUser.Warning("_sys_heap_create_heap(name=*0x%x, arg2=0x%x, arg3=0x%x, arg4=0x%x)", name, arg2, arg3, arg4); - std::shared_ptr heap(new HeapInfo(name.get_ptr())); - - return Emu.GetIdManager().GetNewID(heap); + return Emu.GetIdManager().make(name.get_ptr()); } s32 _sys_heap_delete_heap(u32 heap) { sysPrxForUser.Warning("_sys_heap_delete_heap(heap=0x%x)", heap); - Emu.GetIdManager().RemoveID(heap); + Emu.GetIdManager().remove(heap); return CELL_OK; } @@ -1169,7 +1163,7 @@ s32 sys_process_get_paramsfo(vm::ptr buffer) return _sys_process_get_paramsfo(buffer); } -void sys_spinlock_initialize(vm::ptr> lock) +void sys_spinlock_initialize(vm::ptr> lock) { sysPrxForUser.Log("sys_spinlock_initialize(lock=*0x%x)", lock); @@ -1177,7 +1171,7 @@ void sys_spinlock_initialize(vm::ptr> lock) lock->exchange(be_t::make(0)); } -void sys_spinlock_lock(vm::ptr> lock) +void sys_spinlock_lock(vm::ptr> lock) { sysPrxForUser.Log("sys_spinlock_lock(lock=*0x%x)", lock); @@ -1194,7 +1188,7 @@ void sys_spinlock_lock(vm::ptr> lock) } } -s32 sys_spinlock_trylock(vm::ptr> lock) +s32 sys_spinlock_trylock(vm::ptr> lock) { sysPrxForUser.Log("sys_spinlock_trylock(lock=*0x%x)", lock); @@ -1207,7 +1201,7 @@ s32 sys_spinlock_trylock(vm::ptr> lock) return CELL_OK; } -void sys_spinlock_unlock(vm::ptr> lock) +void sys_spinlock_unlock(vm::ptr> lock) { sysPrxForUser.Log("sys_spinlock_unlock(lock=*0x%x)", lock); @@ -1263,7 +1257,7 @@ void sys_ppu_thread_exit(PPUThread& CPU, u64 val) std::mutex g_once_mutex; -void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init) +void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init) { sysPrxForUser.Warning("sys_ppu_thread_once(once_ctrl=*0x%x, init=*0x%x)", once_ctrl, init); diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index a0bf5e87be..898d1f2220 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -21,7 +21,7 @@ namespace ppu_func_detail { static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_GENERAL"); - static __forceinline T get_arg(PPUThread& CPU) + static force_inline T get_arg(PPUThread& CPU) { return cast_from_ppu_gpr(CPU.GPR[g_count + 2]); } @@ -32,7 +32,7 @@ namespace ppu_func_detail { static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_FLOAT"); - static __forceinline T get_arg(PPUThread& CPU) + static force_inline T get_arg(PPUThread& CPU) { return static_cast(CPU.FPR[f_count]); } @@ -43,7 +43,7 @@ namespace ppu_func_detail { static_assert(std::is_same::value, "Invalid function argument type for ARG_VECTOR"); - static __forceinline T get_arg(PPUThread& CPU) + static force_inline T get_arg(PPUThread& CPU) { return CPU.VPR[v_count + 1]; } @@ -56,7 +56,7 @@ namespace ppu_func_detail static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)"); static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_STACK"); - static __forceinline T get_arg(PPUThread& CPU) + static force_inline T get_arg(PPUThread& CPU) { // TODO: check stack argument displacement const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 13, 0) + std::max(v_count - 12, 0)); @@ -70,7 +70,7 @@ namespace ppu_func_detail static_assert(type == ARG_GENERAL, "Wrong use of bind_result template"); static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_GENERAL"); - static __forceinline void put_result(PPUThread& CPU, const T& result) + static force_inline void put_result(PPUThread& CPU, const T& result) { CPU.GPR[3] = cast_to_ppu_gpr(result); } @@ -81,7 +81,7 @@ namespace ppu_func_detail { static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT"); - static __forceinline void put_result(PPUThread& CPU, const T& result) + static force_inline void put_result(PPUThread& CPU, const T& result) { CPU.FPR[1] = static_cast(result); } @@ -92,7 +92,7 @@ namespace ppu_func_detail { static_assert(std::is_same::value, "Invalid function result type for ARG_VECTOR"); - static __forceinline void put_result(PPUThread& CPU, const T& result) + static force_inline void put_result(PPUThread& CPU, const T& result) { CPU.VPR[2] = result; } @@ -109,7 +109,7 @@ namespace ppu_func_detail template struct bind_arg_packed { - static __forceinline T get_arg(PPUThread& CPU) + static force_inline T get_arg(PPUThread& CPU) { return bind_arg> 8), (type_pack >> 16), (type_pack >> 24)>::get_arg(CPU); } @@ -118,7 +118,7 @@ namespace ppu_func_detail template struct call_impl { - static __forceinline RT call(F f, Tuple && t) + static force_inline RT call(F f, Tuple && t) { return call_impl::call(f, std::forward(t)); } @@ -127,28 +127,28 @@ namespace ppu_func_detail template struct call_impl { - static __forceinline RT call(F f, Tuple && t) + static force_inline RT call(F f, Tuple && t) { return f(std::get(std::forward(t))...); } }; template - __forceinline RT call(F f, Tuple && t) + force_inline RT call(F f, Tuple && t) { typedef typename std::decay::type ttype; return ppu_func_detail::call_impl::value, std::tuple_size::value>::call(f, std::forward(t)); } template - __forceinline std::tuple<> iterate(PPUThread& CPU) + force_inline std::tuple<> iterate(PPUThread& CPU) { // terminator return std::tuple<>(); } template - __forceinline std::tuple iterate(PPUThread& CPU) + force_inline std::tuple iterate(PPUThread& CPU) { static_assert(!std::is_pointer::value, "Invalid function argument type (pointer)"); static_assert(!std::is_reference::value, "Invalid function argument type (reference)"); @@ -223,7 +223,7 @@ namespace ppu_func_detail }; } -template __forceinline void call_ppu_func(PPUThread& CPU, RT(*func)(T...)) +template force_inline void call_ppu_func(PPUThread& CPU, RT(*func)(T...)) { ppu_func_detail::func_binder::do_call(CPU, func); } diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index 7f3608fbfb..fc3652a1f8 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -422,7 +422,7 @@ const ppu_func_caller sc_table[1024] = null_func, //462 (0x1CE) UNS null_func,//bind_func(sys_prx_load_module_by_fd) //463 (0x1CF) null_func,//bind_func(sys_prx_load_module_on_memcontainer_by_fd) //464 (0x1D0) - null_func,//bind_func(sys_prx_load_module_list) //465 (0x1D1) + bind_func(sys_prx_load_module_list), //465 (0x1D1) null_func,//bind_func(sys_prx_load_module_list_on_memcontainer) //466 (0x1D2) null_func,//bind_func(sys_prx_get_ppu_guid) //467 (0x1D3) null_func,//bind_func(sys_...) //468 (0x1D4) ROOT @@ -437,14 +437,14 @@ const ppu_func_caller sc_table[1024] = null_func, null_func, null_func, //477-479 UNS - null_func,//bind_func(sys_prx_load_module), //480 (0x1E0) - null_func,//bind_func(sys_prx_start_module), //481 (0x1E1) - null_func,//bind_func(sys_prx_stop_module), //482 (0x1E2) - null_func,//bind_func(sys_prx_unload_module), //483 (0x1E3) - null_func,//bind_func(sys_prx_register_module), //484 (0x1E4) + bind_func(sys_prx_load_module), //480 (0x1E0) + bind_func(sys_prx_start_module), //481 (0x1E1) + bind_func(sys_prx_stop_module), //482 (0x1E2) + bind_func(sys_prx_unload_module), //483 (0x1E3) + bind_func(sys_prx_register_module), //484 (0x1E4) bind_func(sys_prx_query_module), //485 (0x1E5) bind_func(sys_prx_register_library), //486 (0x1E6) - null_func,//bind_func(sys_prx_unregister_library), //487 (0x1E7) + bind_func(sys_prx_unregister_library), //487 (0x1E7) bind_func(sys_prx_link_library), //488 (0x1E8) bind_func(sys_prx_unlink_library), //489 (0x1E9) bind_func(sys_prx_query_library), //490 (0x1EA) diff --git a/rpcs3/Emu/SysCalls/lv2/sleep_queue.cpp b/rpcs3/Emu/SysCalls/lv2/sleep_queue.cpp index 0cf0fa52f7..ba938fe3b2 100644 --- a/rpcs3/Emu/SysCalls/lv2/sleep_queue.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sleep_queue.cpp @@ -125,7 +125,7 @@ u32 sleep_queue_t::signal(u32 protocol) if (m_waiting.size()) { res = m_waiting[0]; - if (!Emu.GetIdManager().CheckID(res)) + if (!Emu.GetIdManager().check_id(res)) { LOG_ERROR(HLE, "sleep_queue_t['%s']::signal(SYS_SYNC_FIFO) failed: invalid thread (%d)", m_name.c_str(), res); Emu.Pause(); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp index ca179cf27e..2d22b1cb6e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp @@ -19,7 +19,7 @@ s32 sys_cond_create(vm::ptr cond_id, u32 mutex_id, vm::ptr(mutex_id); + const auto mutex = std::move(Emu.GetIdManager().get(mutex_id)); if (!mutex) { @@ -37,9 +37,7 @@ s32 sys_cond_create(vm::ptr cond_id, u32 mutex_id, vm::ptr cond(new cond_t(mutex, attr->name_u64)); - - *cond_id = Emu.GetIdManager().GetNewID(cond, TYPE_COND); + *cond_id = Emu.GetIdManager().make(mutex, attr->name_u64); return CELL_OK; } @@ -50,7 +48,7 @@ s32 sys_cond_destroy(u32 cond_id) LV2_LOCK; - const auto cond = Emu.GetIdManager().GetIDData(cond_id); + const auto cond = Emu.GetIdManager().get(cond_id); if (!cond) { @@ -67,7 +65,7 @@ s32 sys_cond_destroy(u32 cond_id) throw __FUNCTION__; } - Emu.GetIdManager().RemoveID(cond_id); + Emu.GetIdManager().remove(cond_id); return CELL_OK; } @@ -78,7 +76,7 @@ s32 sys_cond_signal(u32 cond_id) LV2_LOCK; - const auto cond = Emu.GetIdManager().GetIDData(cond_id); + const auto cond = Emu.GetIdManager().get(cond_id); if (!cond) { @@ -101,7 +99,7 @@ s32 sys_cond_signal_all(u32 cond_id) LV2_LOCK; - const auto cond = Emu.GetIdManager().GetIDData(cond_id); + const auto cond = Emu.GetIdManager().get(cond_id); if (!cond) { @@ -124,14 +122,14 @@ s32 sys_cond_signal_to(u32 cond_id, u32 thread_id) LV2_LOCK; - const auto cond = Emu.GetIdManager().GetIDData(cond_id); + const auto cond = Emu.GetIdManager().get(cond_id); if (!cond) { return CELL_ESRCH; } - if (!Emu.GetIdManager().CheckID(thread_id)) + if (!Emu.GetIdManager().check_id(thread_id)) { return CELL_ESRCH; } @@ -158,7 +156,7 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout) LV2_LOCK; - const auto cond = Emu.GetIdManager().GetIDData(cond_id); + const auto cond = Emu.GetIdManager().get(cond_id); if (!cond) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.h b/rpcs3/Emu/SysCalls/lv2/sys_cond.h index 43164e58c7..ee61ee9912 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.h @@ -1,6 +1,6 @@ #pragma once -struct mutex_t; +struct lv2_mutex_t; struct sys_cond_attribute_t { @@ -15,10 +15,10 @@ struct sys_cond_attribute_t }; }; -struct cond_t +struct lv2_cond_t { const u64 name; - const std::shared_ptr mutex; // associated mutex + const std::shared_ptr mutex; // associated mutex std::atomic signaled; @@ -26,15 +26,17 @@ struct cond_t std::condition_variable cv; std::unordered_set waiters; - cond_t(const std::shared_ptr& mutex, u64 name) + lv2_cond_t(const std::shared_ptr& mutex, u64 name) : mutex(mutex) , name(name) , signaled(0) - , waiters(0) + //, waiters(0) { } }; +REG_ID_TYPE(lv2_cond_t, 0x86); // SYS_COND_OBJECT + class PPUThread; // SysCalls diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp index 21f77b3b88..ab64c03805 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp @@ -13,15 +13,6 @@ SysCallBase sys_event("sys_event"); -u32 event_queue_create(u32 protocol, s32 type, u64 name_u64, u64 event_queue_key, s32 size) -{ - std::shared_ptr queue(new event_queue_t(protocol, type, name_u64, event_queue_key, size)); - - Emu.GetEventManager().RegisterKey(queue, event_queue_key); - - return Emu.GetIdManager().GetNewID(queue, TYPE_EVENT_QUEUE); -} - s32 sys_event_queue_create(vm::ptr equeue_id, vm::ptr attr, u64 event_queue_key, s32 size) { sys_event.Warning("sys_event_queue_create(equeue_id=*0x%x, attr=*0x%x, event_queue_key=0x%llx, size=%d)", equeue_id, attr, event_queue_key, size); @@ -49,14 +40,14 @@ s32 sys_event_queue_create(vm::ptr equeue_id, vm::ptr default: sys_event.Error("sys_event_queue_create(): unknown type (0x%x)", type); return CELL_EINVAL; } - std::shared_ptr queue(new event_queue_t(protocol, type, attr->name_u64, event_queue_key, size)); + auto queue = Emu.GetEventManager().MakeEventQueue(protocol, type, attr->name_u64, event_queue_key, size); - if (!Emu.GetEventManager().RegisterKey(queue, event_queue_key)) + if (!queue) { return CELL_EEXIST; } - *equeue_id = Emu.GetIdManager().GetNewID(queue, TYPE_EVENT_QUEUE); + *equeue_id = Emu.GetIdManager().add(std::move(queue)); return CELL_OK; } @@ -67,7 +58,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode) LV2_LOCK; - const auto queue = Emu.GetIdManager().GetIDData(equeue_id); + const auto queue = Emu.GetIdManager().get(equeue_id); if (!queue) { @@ -95,7 +86,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode) } Emu.GetEventManager().UnregisterKey(queue->key); - Emu.GetIdManager().RemoveID(equeue_id); + Emu.GetIdManager().remove(equeue_id); return CELL_OK; } @@ -106,7 +97,7 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr event_array, LV2_LOCK; - const auto queue = Emu.GetIdManager().GetIDData(equeue_id); + const auto queue = Emu.GetIdManager().get(equeue_id); if (!queue) { @@ -146,7 +137,7 @@ s32 sys_event_queue_receive(PPUThread& CPU, u32 equeue_id, vm::ptr LV2_LOCK; - const auto queue = Emu.GetIdManager().GetIDData(equeue_id); + const auto queue = Emu.GetIdManager().get(equeue_id); if (!queue) { @@ -203,7 +194,7 @@ s32 sys_event_queue_drain(u32 equeue_id) LV2_LOCK; - const auto queue = Emu.GetIdManager().GetIDData(equeue_id); + const auto queue = Emu.GetIdManager().get(equeue_id); if (!queue) { @@ -215,13 +206,6 @@ s32 sys_event_queue_drain(u32 equeue_id) return CELL_OK; } -u32 event_port_create(u64 name) -{ - std::shared_ptr eport(new event_port_t(SYS_EVENT_PORT_LOCAL, name)); - - return Emu.GetIdManager().GetNewID(eport, TYPE_EVENT_PORT); -} - s32 sys_event_port_create(vm::ptr eport_id, s32 port_type, u64 name) { sys_event.Warning("sys_event_port_create(eport_id=*0x%x, port_type=%d, name=0x%llx)", eport_id, port_type, name); @@ -232,9 +216,7 @@ s32 sys_event_port_create(vm::ptr eport_id, s32 port_type, u64 name) return CELL_EINVAL; } - std::shared_ptr eport(new event_port_t(port_type, name)); - - *eport_id = Emu.GetIdManager().GetNewID(eport, TYPE_EVENT_PORT); + *eport_id = Emu.GetIdManager().make(port_type, name); return CELL_OK; } @@ -245,7 +227,7 @@ s32 sys_event_port_destroy(u32 eport_id) LV2_LOCK; - const auto port = Emu.GetIdManager().GetIDData(eport_id); + const auto port = Emu.GetIdManager().get(eport_id); if (!port) { @@ -257,7 +239,7 @@ s32 sys_event_port_destroy(u32 eport_id) return CELL_EISCONN; } - Emu.GetIdManager().RemoveID(eport_id); + Emu.GetIdManager().remove(eport_id); return CELL_OK; } @@ -268,8 +250,8 @@ s32 sys_event_port_connect_local(u32 eport_id, u32 equeue_id) LV2_LOCK; - const auto port = Emu.GetIdManager().GetIDData(eport_id); - const auto queue = Emu.GetIdManager().GetIDData(equeue_id); + const auto port = Emu.GetIdManager().get(eport_id); + const auto queue = Emu.GetIdManager().get(equeue_id); if (!port || !queue) { @@ -297,7 +279,7 @@ s32 sys_event_port_disconnect(u32 eport_id) LV2_LOCK; - const auto port = Emu.GetIdManager().GetIDData(eport_id); + const auto port = Emu.GetIdManager().get(eport_id); if (!port) { @@ -324,7 +306,7 @@ s32 sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3) LV2_LOCK; - const auto port = Emu.GetIdManager().GetIDData(eport_id); + const auto port = Emu.GetIdManager().get(eport_id); if (!port) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.h b/rpcs3/Emu/SysCalls/lv2/sys_event.h index d5e2045bda..8d10f379b3 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.h @@ -69,7 +69,7 @@ struct event_t } }; -struct event_queue_t +struct lv2_event_queue_t { const u32 protocol; const s32 type; @@ -84,7 +84,7 @@ struct event_queue_t std::condition_variable cv; std::atomic waiters; - event_queue_t(u32 protocol, s32 type, u64 name, u64 key, s32 size) + lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 key, s32 size) : protocol(protocol) , type(type) , name(name) @@ -108,24 +108,24 @@ struct event_queue_t } }; -struct event_port_t +REG_ID_TYPE(lv2_event_queue_t, 0x8D); // SYS_EVENT_QUEUE_OBJECT + +struct lv2_event_port_t { const s32 type; // port type, must be SYS_EVENT_PORT_LOCAL const u64 name; // passed as event source (generated from id and process id if not set) - std::weak_ptr queue; // event queue this port is connected to + std::weak_ptr queue; // event queue this port is connected to - event_port_t(s32 type, u64 name) + lv2_event_port_t(s32 type, u64 name) : type(type) , name(name) { } }; -class PPUThread; +REG_ID_TYPE(lv2_event_port_t, 0x0E); // SYS_EVENT_PORT_OBJECT -// Aux -u32 event_port_create(u64 name); -u32 event_queue_create(u32 protocol, s32 type, u64 name_u64, u64 event_queue_key, s32 size); +class PPUThread; // SysCalls s32 sys_event_queue_create(vm::ptr equeue_id, vm::ptr attr, u64 event_queue_key, s32 size); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp index b645ff86c6..14e512ca94 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp @@ -47,9 +47,7 @@ s32 sys_event_flag_create(vm::ptr id, vm::ptr attr, u6 default: sys_event_flag.Error("sys_event_flag_create(): unknown type (0x%x)", attr->type); return CELL_EINVAL; } - std::shared_ptr ef(new event_flag_t(init, protocol, type, attr->name_u64)); - - *id = Emu.GetIdManager().GetNewID(ef, TYPE_EVENT_FLAG); + *id = Emu.GetIdManager().make(init, protocol, type, attr->name_u64); return CELL_OK; } @@ -60,7 +58,7 @@ s32 sys_event_flag_destroy(u32 id) LV2_LOCK; - const auto ef = Emu.GetIdManager().GetIDData(id); + const auto ef = Emu.GetIdManager().get(id); if (!ef) { @@ -72,7 +70,7 @@ s32 sys_event_flag_destroy(u32 id) return CELL_EBUSY; } - Emu.GetIdManager().RemoveID(id); + Emu.GetIdManager().remove(id); return CELL_OK; } @@ -105,7 +103,7 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr result, u64 t default: return CELL_EINVAL; } - const auto ef = Emu.GetIdManager().GetIDData(id); + const auto ef = Emu.GetIdManager().get(id); if (!ef) { @@ -212,7 +210,7 @@ s32 sys_event_flag_trywait(u32 id, u64 bitptn, u32 mode, vm::ptr result) default: return CELL_EINVAL; } - const auto ef = Emu.GetIdManager().GetIDData(id); + const auto ef = Emu.GetIdManager().get(id); if (!ef) { @@ -252,7 +250,7 @@ s32 sys_event_flag_set(u32 id, u64 bitptn) LV2_LOCK; - const auto ef = Emu.GetIdManager().GetIDData(id); + const auto ef = Emu.GetIdManager().get(id); if (!ef) { @@ -280,7 +278,7 @@ s32 sys_event_flag_clear(u32 id, u64 bitptn) LV2_LOCK; - const auto ef = Emu.GetIdManager().GetIDData(id); + const auto ef = Emu.GetIdManager().get(id); if (!ef) { @@ -308,7 +306,7 @@ s32 sys_event_flag_cancel(u32 id, vm::ptr num) *num = 0; } - const auto ef = Emu.GetIdManager().GetIDData(id); + const auto ef = Emu.GetIdManager().get(id); if (!ef) { @@ -344,7 +342,7 @@ s32 sys_event_flag_get(u32 id, vm::ptr flags) return CELL_EFAULT; } - const auto ef = Emu.GetIdManager().GetIDData(id); + const auto ef = Emu.GetIdManager().get(id); if (!ef) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h index c76effbea4..348d5c736c 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h @@ -27,7 +27,7 @@ struct sys_event_flag_attr }; }; -struct event_flag_t +struct lv2_event_flag_t { const u32 protocol; const s32 type; @@ -40,7 +40,7 @@ struct event_flag_t std::condition_variable cv; std::atomic waiters; - event_flag_t(u64 pattern, u32 protocol, s32 type, u64 name) + lv2_event_flag_t(u64 pattern, u32 protocol, s32 type, u64 name) : flags(pattern) , protocol(protocol) , type(type) @@ -51,6 +51,8 @@ struct event_flag_t } }; +REG_ID_TYPE(lv2_event_flag_t, 0x98); // SYS_EVENT_FLAG_OBJECT + s32 sys_event_flag_create(vm::ptr id, vm::ptr attr, u64 init); s32 sys_event_flag_destroy(u32 id); s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr result, u64 timeout); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp b/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp index 9dd921d6cb..fad6fe9c17 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp @@ -109,9 +109,7 @@ s32 sys_fs_open(vm::ptr path, s32 flags, vm::ptr fd, s32 mode, return CELL_FS_ENOENT; } - std::shared_ptr file_handler(new fs_file_t(file, mode, flags)); - - *fd = Emu.GetIdManager().GetNewID(file_handler, TYPE_FS_FILE); + *fd = Emu.GetIdManager().make(file, mode, flags); return CELL_OK; } @@ -120,7 +118,7 @@ s32 sys_fs_read(u32 fd, vm::ptr buf, u64 nbytes, vm::ptr nread) { sys_fs.Log("sys_fs_read(fd=0x%x, buf=0x%x, nbytes=0x%llx, nread=0x%x)", fd, buf, nbytes, nread); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file || file->flags & CELL_FS_O_WRONLY) { @@ -138,7 +136,7 @@ s32 sys_fs_write(u32 fd, vm::ptr buf, u64 nbytes, vm::ptr nwrit { sys_fs.Log("sys_fs_write(fd=0x%x, buf=*0x%x, nbytes=0x%llx, nwrite=*0x%x)", fd, buf, nbytes, nwrite); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file || !(file->flags & CELL_FS_O_ACCMODE)) { @@ -158,7 +156,7 @@ s32 sys_fs_close(u32 fd) { sys_fs.Log("sys_fs_close(fd=0x%x)", fd); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -167,7 +165,7 @@ s32 sys_fs_close(u32 fd) // TODO: return CELL_FS_EBUSY if locked - Emu.GetIdManager().RemoveID(fd); + Emu.GetIdManager().remove(fd); return CELL_OK; } @@ -177,7 +175,7 @@ s32 sys_fs_opendir(vm::ptr path, vm::ptr fd) sys_fs.Warning("sys_fs_opendir(path=*0x%x, fd=*0x%x)", path, fd); sys_fs.Warning("*** path = '%s'", path.get_ptr()); - std::shared_ptr directory(Emu.GetVFS().OpenDir(path.get_ptr())); + std::shared_ptr directory(Emu.GetVFS().OpenDir(path.get_ptr())); if (!directory || !directory->IsOpened()) { @@ -185,7 +183,7 @@ s32 sys_fs_opendir(vm::ptr path, vm::ptr fd) return CELL_FS_ENOENT; } - *fd = Emu.GetIdManager().GetNewID(directory, TYPE_FS_DIR); + *fd = Emu.GetIdManager().add(std::move(directory)); return CELL_OK; } @@ -194,7 +192,7 @@ s32 sys_fs_readdir(u32 fd, vm::ptr dir, vm::ptr nread) { sys_fs.Warning("sys_fs_readdir(fd=0x%x, dir=*0x%x, nread=*0x%x)", fd, dir, nread); - const auto directory = Emu.GetIdManager().GetIDData(fd); + const auto directory = Emu.GetIdManager().get(fd); if (!directory) { @@ -222,14 +220,14 @@ s32 sys_fs_closedir(u32 fd) { sys_fs.Log("sys_fs_closedir(fd=0x%x)", fd); - const auto directory = Emu.GetIdManager().GetIDData(fd); + const auto directory = Emu.GetIdManager().get(fd); if (!directory) { return CELL_FS_EBADF; } - Emu.GetIdManager().RemoveID(fd); + Emu.GetIdManager().remove(fd); return CELL_OK; } @@ -271,7 +269,7 @@ s32 sys_fs_fstat(u32 fd, vm::ptr sb) { sys_fs.Warning("sys_fs_fstat(fd=0x%x, sb=*0x%x)", fd, sb); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -420,7 +418,7 @@ s32 sys_fs_lseek(u32 fd, s64 offset, s32 whence, vm::ptr pos) return CELL_FS_EINVAL; } - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -438,7 +436,7 @@ s32 sys_fs_fget_block_size(u32 fd, vm::ptr sector_size, vm::ptr block_ { sys_fs.Todo("sys_fs_fget_block_size(fd=0x%x, sector_size=*0x%x, block_size=*0x%x, arg4=*0x%x, arg5=*0x%x)", fd, sector_size, block_size, arg4, arg5); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file) { @@ -486,7 +484,7 @@ s32 sys_fs_ftruncate(u32 fd, u64 size) { sys_fs.Warning("sys_fs_ftruncate(fd=0x%x, size=0x%llx)", fd, size); - const auto file = Emu.GetIdManager().GetIDData(fd); + const auto file = Emu.GetIdManager().get(fd); if (!file || !(file->flags & CELL_FS_O_ACCMODE)) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_fs.h b/rpcs3/Emu/SysCalls/lv2/sys_fs.h index bd4945cd3c..bc53cbd904 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_fs.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_fs.h @@ -145,6 +145,8 @@ struct CellFsUtimbuf #pragma pack(pop) +struct vfsStream; + // Stream Support Status (st_status) enum : u32 { @@ -163,7 +165,7 @@ struct fs_st_cb_rec_t u32 pad; }; -struct fs_file_t +struct lv2_file_t { const std::shared_ptr file; const s32 mode; @@ -172,7 +174,7 @@ struct fs_file_t std::mutex mutex; std::condition_variable cv; - atomic_le_t st_status; + atomic st_status; u64 st_ringbuf_size; u64 st_block_size; @@ -186,9 +188,9 @@ struct fs_file_t std::atomic st_total_read; std::atomic st_copied; - atomic_le_t st_callback; + atomic st_callback; - fs_file_t(std::shared_ptr& file, s32 mode, s32 flags) + lv2_file_t(const std::shared_ptr& file, s32 mode, s32 flags) : file(file) , mode(mode) , flags(flags) @@ -198,6 +200,14 @@ struct fs_file_t } }; +REG_ID_TYPE(lv2_file_t, 0x73); // SYS_FS_FD_OBJECT + +class vfsDirBase; + +using lv2_dir_t = vfsDirBase; + +REG_ID_TYPE(lv2_dir_t, 0x73); // SYS_FS_FD_OBJECT + // SysCalls s32 sys_fs_test(u32 arg1, u32 arg2, vm::ptr arg3, u32 arg4, vm::ptr arg5, u32 arg6); s32 sys_fs_open(vm::ptr path, s32 flags, vm::ptr fd, s32 mode, vm::ptr arg, u64 size); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp index 89a6146f34..7ce6a93aef 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp @@ -78,8 +78,6 @@ s32 sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u64 intrthread, return CELL_ESRCH; } - std::shared_ptr handler(new interrupt_handler_t{ it }); - PPUThread& ppu = static_cast(*it); { @@ -127,7 +125,7 @@ s32 sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u64 intrthread, }; } - *ih = Emu.GetIdManager().GetNewID(handler, TYPE_INTR_SERVICE_HANDLE); + *ih = Emu.GetIdManager().make(it); ppu.Exec(); return CELL_OK; @@ -137,7 +135,7 @@ s32 _sys_interrupt_thread_disestablish(u32 ih, vm::ptr r13) { sys_interrupt.Todo("_sys_interrupt_thread_disestablish(ih=0x%x, r13=*0x%x)", ih, r13); - const auto handler = Emu.GetIdManager().GetIDData(ih); + const auto handler = Emu.GetIdManager().get(ih); if (!handler) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.h b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.h index 7167f6b546..4420ee78f5 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.h @@ -2,11 +2,18 @@ class PPUThread; -struct interrupt_handler_t +struct lv2_int_handler_t { std::shared_ptr handler; + + lv2_int_handler_t(const std::shared_ptr& handler) + : handler(handler) + { + } }; +REG_ID_TYPE(lv2_int_handler_t, 0x0B); // SYS_INTR_SERVICE_HANDLE_OBJECT + // SysCalls s32 sys_interrupt_tag_destroy(u32 intrtag); s32 sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u64 intrthread, u64 arg); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp index 91889c9965..d86f786cda 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp @@ -15,19 +15,15 @@ SysCallBase sys_lwcond("sys_lwcond"); void lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name) { - std::shared_ptr cond(new lwcond_t(name)); - lwcond.lwmutex.set(vm::get_addr(&lwmutex)); - lwcond.lwcond_queue = Emu.GetIdManager().GetNewID(cond, TYPE_LWCOND); + lwcond.lwcond_queue = Emu.GetIdManager().make(name); } s32 _sys_lwcond_create(vm::ptr lwcond_id, u32 lwmutex_id, vm::ptr control, u64 name, u32 arg5) { sys_lwcond.Warning("_sys_lwcond_create(lwcond_id=*0x%x, lwmutex_id=0x%x, control=*0x%x, name=0x%llx, arg5=0x%x)", lwcond_id, lwmutex_id, control, name, arg5); - std::shared_ptr cond(new lwcond_t(name)); - - *lwcond_id = Emu.GetIdManager().GetNewID(cond, TYPE_LWCOND); + *lwcond_id = Emu.GetIdManager().make(name); return CELL_OK; } @@ -38,7 +34,7 @@ s32 _sys_lwcond_destroy(u32 lwcond_id) LV2_LOCK; - const auto cond = Emu.GetIdManager().GetIDData(lwcond_id); + const auto cond = Emu.GetIdManager().get(lwcond_id); if (!cond) { @@ -50,7 +46,7 @@ s32 _sys_lwcond_destroy(u32 lwcond_id) return CELL_EBUSY; } - Emu.GetIdManager().RemoveID(lwcond_id); + Emu.GetIdManager().remove(lwcond_id); return CELL_OK; } @@ -61,8 +57,8 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod LV2_LOCK; - const auto cond = Emu.GetIdManager().GetIDData(lwcond_id); - const auto mutex = Emu.GetIdManager().GetIDData(lwmutex_id); + const auto cond = Emu.GetIdManager().get(lwcond_id); + const auto mutex = Emu.GetIdManager().get(lwmutex_id); if (!cond || (lwmutex_id && !mutex)) { @@ -122,8 +118,8 @@ s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode) LV2_LOCK; - const auto cond = Emu.GetIdManager().GetIDData(lwcond_id); - const auto mutex = Emu.GetIdManager().GetIDData(lwmutex_id); + const auto cond = Emu.GetIdManager().get(lwcond_id); + const auto mutex = Emu.GetIdManager().get(lwmutex_id); if (!cond || (lwmutex_id && !mutex)) { @@ -169,8 +165,8 @@ s32 _sys_lwcond_queue_wait(PPUThread& CPU, u32 lwcond_id, u32 lwmutex_id, u64 ti LV2_LOCK; - const auto cond = Emu.GetIdManager().GetIDData(lwcond_id); - const auto mutex = Emu.GetIdManager().GetIDData(lwmutex_id); + const auto cond = Emu.GetIdManager().get(lwcond_id); + const auto mutex = Emu.GetIdManager().get(lwmutex_id); if (!cond || !mutex) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h index 7e94ccbdc2..52a822adc7 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h @@ -17,7 +17,7 @@ struct sys_lwcond_t be_t lwcond_queue; // lwcond pseudo-id }; -struct lwcond_t +struct lv2_lwcond_t { const u64 name; @@ -28,15 +28,17 @@ struct lwcond_t std::condition_variable cv; std::unordered_set waiters; - lwcond_t(u64 name) + lv2_lwcond_t(u64 name) : name(name) , signaled1(0) , signaled2(0) - , waiters(0) + //, waiters(0) { } }; +REG_ID_TYPE(lv2_lwcond_t, 0x97); // SYS_LWCOND_OBJECT + // Aux void lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp index cf9b796dd1..2dd2fe39f2 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp @@ -14,12 +14,10 @@ SysCallBase sys_lwmutex("sys_lwmutex"); void lwmutex_create(sys_lwmutex_t& lwmutex, bool recursive, u32 protocol, u64 name) { - std::shared_ptr mutex(new lwmutex_t(protocol, name)); - lwmutex.lock_var = { { lwmutex::free, lwmutex::zero } }; lwmutex.attribute = protocol | (recursive ? SYS_SYNC_RECURSIVE : SYS_SYNC_NOT_RECURSIVE); lwmutex.recursive_count = 0; - lwmutex.sleep_queue = Emu.GetIdManager().GetNewID(mutex, TYPE_LWMUTEX); + lwmutex.sleep_queue = Emu.GetIdManager().make(protocol, name); } s32 _sys_lwmutex_create(vm::ptr lwmutex_id, u32 protocol, vm::ptr control, u32 arg4, u64 name, u32 arg6) @@ -39,9 +37,7 @@ s32 _sys_lwmutex_create(vm::ptr lwmutex_id, u32 protocol, vm::ptr mutex(new lwmutex_t(protocol, name)); - - *lwmutex_id = Emu.GetIdManager().GetNewID(mutex, TYPE_LWMUTEX); + *lwmutex_id = Emu.GetIdManager().make(protocol, name); return CELL_OK; } @@ -52,7 +48,7 @@ s32 _sys_lwmutex_destroy(u32 lwmutex_id) LV2_LOCK; - const auto mutex = Emu.GetIdManager().GetIDData(lwmutex_id); + const auto mutex = Emu.GetIdManager().get(lwmutex_id); if (!mutex) { @@ -64,7 +60,7 @@ s32 _sys_lwmutex_destroy(u32 lwmutex_id) return CELL_EBUSY; } - Emu.GetIdManager().RemoveID(lwmutex_id); + Emu.GetIdManager().remove(lwmutex_id); return CELL_OK; } @@ -77,7 +73,7 @@ s32 _sys_lwmutex_lock(u32 lwmutex_id, u64 timeout) LV2_LOCK; - const auto mutex = Emu.GetIdManager().GetIDData(lwmutex_id); + const auto mutex = Emu.GetIdManager().get(lwmutex_id); if (!mutex) { @@ -117,7 +113,7 @@ s32 _sys_lwmutex_trylock(u32 lwmutex_id) LV2_LOCK; - const auto mutex = Emu.GetIdManager().GetIDData(lwmutex_id); + const auto mutex = Emu.GetIdManager().get(lwmutex_id); if (!mutex) { @@ -140,7 +136,7 @@ s32 _sys_lwmutex_unlock(u32 lwmutex_id) LV2_LOCK; - const auto mutex = Emu.GetIdManager().GetIDData(lwmutex_id); + const auto mutex = Emu.GetIdManager().get(lwmutex_id); if (!mutex) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h index e39802b8fd..0543b24cb6 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h @@ -47,15 +47,15 @@ struct sys_lwmutex_t union { - atomic_t lock_var; + atomic_be_t lock_var; struct { - atomic_t owner; - atomic_t waiter; + atomic_be_t owner; + atomic_be_t waiter; }; - atomic_t all_info; + atomic_be_t all_info; }; be_t attribute; @@ -64,7 +64,7 @@ struct sys_lwmutex_t be_t pad; }; -struct lwmutex_t +struct lv2_lwmutex_t { const u32 protocol; const u64 name; @@ -76,7 +76,7 @@ struct lwmutex_t std::condition_variable cv; std::atomic waiters; - lwmutex_t(u32 protocol, u64 name) + lv2_lwmutex_t(u32 protocol, u64 name) : protocol(protocol) , name(name) , signaled(0) @@ -85,6 +85,8 @@ struct lwmutex_t } }; +REG_ID_TYPE(lv2_lwmutex_t, 0x95); // SYS_LWMUTEX_OBJECT + // Aux void lwmutex_create(sys_lwmutex_t& lwmutex, bool recursive, u32 protocol, u64 name); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp b/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp index 335873dc23..bfdcd3a4a4 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp @@ -45,7 +45,7 @@ s32 sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_a sys_memory.Log("sys_memory_allocate_from_container(size=0x%x, cid=0x%x, flags=0x%x)", size, cid, flags); // Check if this container ID is valid. - const auto ct = Emu.GetIdManager().GetIDData(cid); + const auto ct = Emu.GetIdManager().get(cid); if (!ct) { @@ -124,11 +124,7 @@ s32 sys_memory_container_create(vm::ptr cid, u32 yield_size) return CELL_ENOMEM; // Wrap the allocated memory in a memory container. - std::shared_ptr ct(new MemoryContainerInfo(addr, yield_size)); - u32 id = Emu.GetIdManager().GetNewID(ct, TYPE_MEM); - *cid = id; - - sys_memory.Warning("*** memory_container created(addr=0x%llx): id = %d", addr, id); + *cid = Emu.GetIdManager().make(addr, yield_size); return CELL_OK; } @@ -138,7 +134,7 @@ s32 sys_memory_container_destroy(u32 cid) sys_memory.Warning("sys_memory_container_destroy(cid=0x%x)", cid); // Check if this container ID is valid. - const auto ct = Emu.GetIdManager().GetIDData(cid); + const auto ct = Emu.GetIdManager().get(cid); if (!ct) { @@ -147,7 +143,7 @@ s32 sys_memory_container_destroy(u32 cid) // Release the allocated memory and remove the ID. Memory.Free(ct->addr); - Emu.GetIdManager().RemoveID(cid); + Emu.GetIdManager().remove(cid); return CELL_OK; } @@ -157,7 +153,7 @@ s32 sys_memory_container_get_size(vm::ptr mem_info, u32 cid) sys_memory.Warning("sys_memory_container_get_size(mem_info_addr=0x%x, cid=0x%x)", mem_info.addr(), cid); // Check if this container ID is valid. - const auto ct = Emu.GetIdManager().GetIDData(cid); + const auto ct = Emu.GetIdManager().get(cid); if (!ct) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp index ddbee52e5b..cbb6f03e1c 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp @@ -77,8 +77,7 @@ s32 sys_mmapper_allocate_memory(u32 size, u64 flags, vm::ptr mem_id) } // Generate a new mem ID. - std::shared_ptr info(new mmapper_info(size, flags)); - *mem_id = Emu.GetIdManager().GetNewID(info, TYPE_MEM); + *mem_id = Emu.GetIdManager().make(size, flags); return CELL_OK; } @@ -89,7 +88,7 @@ s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm: size, cid, flags, mem_id.addr()); // Check if this container ID is valid. - const auto ct = Emu.GetIdManager().GetIDData(cid); + const auto ct = Emu.GetIdManager().get(cid); if (!ct) { @@ -116,8 +115,7 @@ s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm: ct->size = size; // Generate a new mem ID. - std::shared_ptr info(new mmapper_info(ct->size, flags)); - *mem_id = Emu.GetIdManager().GetNewID(info, TYPE_MEM); + *mem_id = Emu.GetIdManager().make(ct->size, flags); return CELL_OK; } @@ -145,7 +143,7 @@ s32 sys_mmapper_free_memory(u32 mem_id) sys_mmapper.Warning("sys_mmapper_free_memory(mem_id=0x%x)", mem_id); // Check if this mem ID is valid. - const auto info = Emu.GetIdManager().GetIDData(mem_id); + const auto info = Emu.GetIdManager().get(mem_id); if (!info) { @@ -153,7 +151,7 @@ s32 sys_mmapper_free_memory(u32 mem_id) } // Release the allocated memory and remove the ID. - Emu.GetIdManager().RemoveID(mem_id); + Emu.GetIdManager().remove(mem_id); return CELL_OK; } @@ -163,7 +161,7 @@ s32 sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags) sys_mmapper.Warning("sys_mmapper_map_memory(start_addr=0x%x, mem_id=0x%x, flags=0x%llx)", start_addr, mem_id, flags); // Check if this mem ID is valid. - const auto info = Emu.GetIdManager().GetIDData(mem_id); + const auto info = Emu.GetIdManager().get(mem_id); if (!info) { @@ -186,7 +184,7 @@ s32 sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_ start_addr, mem_id, flags, alloc_addr); // Check if this mem ID is valid. - const auto info = Emu.GetIdManager().GetIDData(mem_id); + const auto info = Emu.GetIdManager().get(mem_id); if (!info) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.h b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.h index 608f6b8dac..a32000d347 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.h @@ -19,6 +19,8 @@ struct mmapper_info } }; +REG_ID_TYPE(mmapper_info, 0x08); // SYS_MEM_OBJECT + // SysCalls s32 sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr); s32 sys_mmapper_allocate_fixed_address(); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp index a2241c62aa..96333a6920 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp @@ -41,9 +41,7 @@ s32 sys_mutex_create(vm::ptr mutex_id, vm::ptr attr) return CELL_EINVAL; } - std::shared_ptr mutex(new mutex_t(recursive, protocol, attr->name_u64)); - - *mutex_id = Emu.GetIdManager().GetNewID(mutex, TYPE_MUTEX); + *mutex_id = Emu.GetIdManager().make(recursive, protocol, attr->name_u64); return CELL_OK; } @@ -54,7 +52,7 @@ s32 sys_mutex_destroy(u32 mutex_id) LV2_LOCK; - const auto mutex = Emu.GetIdManager().GetIDData(mutex_id); + const auto mutex = Emu.GetIdManager().get(mutex_id); if (!mutex) { @@ -77,7 +75,7 @@ s32 sys_mutex_destroy(u32 mutex_id) return CELL_EPERM; } - Emu.GetIdManager().RemoveID(mutex_id); + Emu.GetIdManager().remove(mutex_id); return CELL_OK; } @@ -90,7 +88,7 @@ s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout) LV2_LOCK; - const auto mutex = Emu.GetIdManager().GetIDData(mutex_id); + const auto mutex = Emu.GetIdManager().get(mutex_id); if (!mutex) { @@ -148,7 +146,7 @@ s32 sys_mutex_trylock(PPUThread& CPU, u32 mutex_id) LV2_LOCK; - const auto mutex = Emu.GetIdManager().GetIDData(mutex_id); + const auto mutex = Emu.GetIdManager().get(mutex_id); if (!mutex) { @@ -190,7 +188,7 @@ s32 sys_mutex_unlock(PPUThread& CPU, u32 mutex_id) LV2_LOCK; - const auto mutex = Emu.GetIdManager().GetIDData(mutex_id); + const auto mutex = Emu.GetIdManager().get(mutex_id); if (!mutex) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h index 31f155b574..b111aa4f31 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h @@ -17,7 +17,7 @@ struct sys_mutex_attribute_t }; }; -struct mutex_t +struct lv2_mutex_t { const bool recursive; const u32 protocol; @@ -31,7 +31,7 @@ struct mutex_t std::condition_variable cv; std::atomic waiters; - mutex_t(bool recursive, u32 protocol, u64 name) + lv2_mutex_t(bool recursive, u32 protocol, u64 name) : recursive(recursive) , protocol(protocol) , name(name) @@ -42,6 +42,8 @@ struct mutex_t } }; +REG_ID_TYPE(lv2_mutex_t, 0x85); // SYS_MUTEX_OBJECT + class PPUThread; // SysCalls diff --git a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp index 1d850ec15f..c552e3aa45 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp @@ -206,81 +206,78 @@ void sys_game_process_exitspawn2(vm::ptr path, u32 argv_addr, u32 en s32 sys_process_get_number_of_object(u32 object, vm::ptr nump) { - sys_process.Todo("sys_process_get_number_of_object(object=%d, nump_addr=0x%x)", - object, nump.addr()); + sys_process.Error("sys_process_get_number_of_object(object=0x%x, nump=*0x%x)", object, nump); switch(object) { - case SYS_MEM_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_MEM); break; - case SYS_MUTEX_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_MUTEX); break; - case SYS_COND_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_COND); break; - case SYS_RWLOCK_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_RWLOCK); break; - case SYS_INTR_TAG_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_INTR_TAG); break; - case SYS_INTR_SERVICE_HANDLE_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_INTR_SERVICE_HANDLE); break; - case SYS_EVENT_QUEUE_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_EVENT_QUEUE); break; - case SYS_EVENT_PORT_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_EVENT_PORT); break; - case SYS_TRACE_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_TRACE); break; - case SYS_SPUIMAGE_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_SPUIMAGE); break; - case SYS_PRX_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_PRX); break; - case SYS_SPUPORT_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_SPUPORT); break; - case SYS_LWMUTEX_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_LWMUTEX); break; - case SYS_TIMER_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_TIMER); break; - case SYS_SEMAPHORE_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_SEMAPHORE); break; - case SYS_LWCOND_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_LWCOND); break; - case SYS_EVENT_FLAG_OBJECT: *nump = Emu.GetIdManager().GetTypeCount(TYPE_EVENT_FLAG); break; + case SYS_MEM_OBJECT: + case SYS_MUTEX_OBJECT: + case SYS_COND_OBJECT: + case SYS_RWLOCK_OBJECT: + case SYS_INTR_TAG_OBJECT: + case SYS_INTR_SERVICE_HANDLE_OBJECT: + case SYS_EVENT_QUEUE_OBJECT: + case SYS_EVENT_PORT_OBJECT: + case SYS_TRACE_OBJECT: + case SYS_SPUIMAGE_OBJECT: + case SYS_PRX_OBJECT: + case SYS_SPUPORT_OBJECT: + case SYS_LWMUTEX_OBJECT: + case SYS_TIMER_OBJECT: + case SYS_SEMAPHORE_OBJECT: case SYS_FS_FD_OBJECT: - *nump = Emu.GetIdManager().GetTypeCount(TYPE_FS_FILE) + Emu.GetIdManager().GetTypeCount(TYPE_FS_DIR); - break; - - default: - return CELL_EINVAL; + case SYS_LWCOND_OBJECT: + case SYS_EVENT_FLAG_OBJECT: + { + *nump = Emu.GetIdManager().get_count_by_type(object); + return CELL_OK; + } } - return CELL_OK; + return CELL_EINVAL; } s32 sys_process_get_id(u32 object, vm::ptr buffer, u32 size, vm::ptr set_size) { - sys_process.Todo("sys_process_get_id(object=%d, buffer_addr=0x%x, size=%d, set_size_addr=0x%x)", - object, buffer.addr(), size, set_size.addr()); + sys_process.Error("sys_process_get_id(object=0x%x, buffer=*0x%x, size=%d, set_size=*0x%x)", object, buffer, size, set_size); - switch(object) + switch (object) { + case SYS_MEM_OBJECT: + case SYS_MUTEX_OBJECT: + case SYS_COND_OBJECT: + case SYS_RWLOCK_OBJECT: + case SYS_INTR_TAG_OBJECT: + case SYS_INTR_SERVICE_HANDLE_OBJECT: + case SYS_EVENT_QUEUE_OBJECT: + case SYS_EVENT_PORT_OBJECT: + case SYS_TRACE_OBJECT: + case SYS_SPUIMAGE_OBJECT: + case SYS_PRX_OBJECT: + case SYS_SPUPORT_OBJECT: + case SYS_LWMUTEX_OBJECT: + case SYS_TIMER_OBJECT: + case SYS_SEMAPHORE_OBJECT: + case SYS_FS_FD_OBJECT: + case SYS_LWCOND_OBJECT: + case SYS_EVENT_FLAG_OBJECT: + { + const auto objects = Emu.GetIdManager().get_IDs_by_type(object); -#define ADD_OBJECTS(type) { \ - u32 i=0; \ - const auto objects = Emu.GetIdManager().GetTypeIDs(type); \ - for(auto id=objects.begin(); i pOpt) +{ + sys_prx.Warning("prx_load_module(path='%s', flags=0x%llx, pOpt=*0x%x)", path.c_str(), flags, pOpt); + + loader::handlers::elf64 loader; + + vfsFile f(path); + if (!f.IsOpened()) + return CELL_PRX_ERROR_UNKNOWN_MODULE; + + if (loader.init(f) != loader::handler::error_code::ok || !loader.is_sprx()) + return CELL_PRX_ERROR_ILLEGAL_LIBRARY; + + loader::handlers::elf64::sprx_info info; + loader.load_sprx(info); + + auto prx = std::make_shared(); + + auto meta = info.modules[""]; + prx->start.set(meta.exports[0xBC9A0086]); + prx->stop.set(meta.exports[0xAB779874]); + prx->exit.set(meta.exports[0x3AB9A95E]); + + for (auto &module_ : info.modules) + { + if (module_.first == "") + continue; + + Module* module = Emu.GetModuleManager().GetModuleByName(module_.first.c_str()); + + if (!module) + { + sys_prx.Error("Unknown module '%s'", module_.first.c_str()); + } + + for (auto& f : module_.second.exports) + { + const u32 nid = f.first; + const u32 addr = f.second; + + u32 index; + + auto func = get_ppu_func_by_nid(nid, &index); + + if (!func) + { + index = add_ppu_func(ModuleFunc(nid, 0, module, nullptr, nullptr, vm::ptr::make(addr))); + } + else + { + func->lle_func.set(addr); + + if (func->flags & MFF_FORCED_HLE) + { + u32 i_addr = 0; + + if (!vm::check_addr(addr, 8) || !vm::check_addr(i_addr = vm::read32(addr), 4)) + { + sys_prx.Error("Failed to inject code for exported function '%s' (opd=0x%x, 0x%x)", SysCalls::GetFuncName(nid), addr, i_addr); + } + else + { + vm::write32(i_addr, PPU_instr::HACK(index | EIF_PERFORM_BLR)); + } + } + } + } + + for (auto &import : module_.second.imports) + { + u32 nid = import.first; + u32 addr = import.second; + + u32 index; + + auto func = get_ppu_func_by_nid(nid, &index); + + if (!func) + { + sys_prx.Error("Unimplemented function '%s' in '%s' module (0x%x)", SysCalls::GetFuncName(nid), module_.first); + + index = add_ppu_func(ModuleFunc(nid, 0, module, nullptr, nullptr)); + } + else + { + const bool is_lle = func->lle_func && !(func->flags & MFF_FORCED_HLE); + + sys_prx.Error("Imported %sfunction '%s' in '%s' module (0x%x)", (is_lle ? "LLE " : ""), SysCalls::GetFuncName(nid), module_.first, addr); + } + + if (!patch_ppu_import(addr, index)) + { + sys_prx.Error("Failed to inject code at address 0x%x", addr); + } + } + } + + for (auto& seg : info.segments) + { + const u32 addr = seg.begin.addr(); + const u32 size = align(seg.size, 4096); + + if (vm::check_addr(addr, size)) + { + fill_ppu_exec_map(addr, size); + } + else + { + sys_prx.Error("Failed to process executable area (addr=0x%x, size=0x%x)", addr, size); + } + } + + return Emu.GetIdManager().add(std::move(prx)); +} + s32 sys_prx_load_module(vm::ptr path, u64 flags, vm::ptr pOpt) { - sys_prx.Todo("sys_prx_load_module(path=\"%s\", flags=0x%llx, pOpt=0x%x)", path.get_ptr(), flags, pOpt.addr()); + sys_prx.Warning("sys_prx_load_module(path=*0x%x, flags=0x%llx, pOpt=*0x%x)", path, flags, pOpt); - std::string _path = path.get_ptr(); - // Check if the file is SPRX - std::string local_path; - Emu.GetVFS().GetDevice(_path, local_path); - if (IsSelf(local_path)) { - if (!DecryptSelf(local_path+".prx", local_path)) { - return CELL_PRX_ERROR_ILLEGAL_LIBRARY; - } - _path += ".prx"; + return prx_load_module(path.get_ptr(), flags, pOpt); +} + +s32 sys_prx_load_module_list(s32 count, vm::ptr path_list, u64 flags, vm::ptr pOpt, vm::ptr id_list) +{ + sys_prx.Warning("sys_prx_load_module_list(count=%d, path_list=*0x%x, flags=0x%llx, pOpt=*0x%x, id_list=*0x%x)", count, path_list, flags, pOpt, id_list); + + for (s32 i = 0; i < count; ++i) + { + auto path = path_list[i]; + std::string name = path.get_ptr(); + s32 result = prx_load_module(name, flags, pOpt); + + if (result < 0) + return result; + + id_list[i] = result; } - vfsFile f(_path); - if (!f.IsOpened()) { - return CELL_PRX_ERROR_UNKNOWN_MODULE; - } - - // Create the PRX object and return its id - std::shared_ptr prx(new sys_prx_t()); - prx->size = (u32)f.GetSize(); - prx->address = (u32)Memory.Alloc(prx->size, 4); - prx->path = (const char*)path; - - // Load the PRX into memory - f.Read(vm::get_ptr(prx->address), prx->size); - - u32 id = Emu.GetIdManager().GetNewID(prx, TYPE_PRX); - return id; + return CELL_OK; } s32 sys_prx_load_module_on_memcontainer() @@ -62,56 +177,62 @@ s32 sys_prx_load_module_on_memcontainer_by_fd() return CELL_OK; } -s32 sys_prx_start_module(s32 id, u32 args, u32 argp_addr, vm::ptr modres, u64 flags, vm::ptr pOpt) +s32 sys_prx_start_module(s32 id, u64 flags, vm::ptr pOpt) { - sys_prx.Todo("sys_prx_start_module(id=0x%x, args=%d, argp_addr=0x%x, modres_addr=0x%x, flags=0x%llx, pOpt=0x%x)", - id, args, argp_addr, modres.addr(), flags, pOpt.addr()); + sys_prx.Warning("sys_prx_start_module(id=0x%x, flags=0x%llx, pOpt=*0x%x)", id, flags, pOpt); - const auto prx = Emu.GetIdManager().GetIDData(id); + const auto prx = Emu.GetIdManager().get(id); if (!prx) { return CELL_ESRCH; } - if (prx->isStarted) - return CELL_PRX_ERROR_ALREADY_STARTED; + //if (prx->is_started) + // return CELL_PRX_ERROR_ALREADY_STARTED; + + //prx->is_started = true; + pOpt->entry_point.set(be_t::make(prx->start ? prx->start.addr() : ~0ull)); return CELL_OK; } -s32 sys_prx_stop_module(s32 id, u32 args, u32 argp_addr, vm::ptr modres, u64 flags, vm::ptr pOpt) +s32 sys_prx_stop_module(s32 id, u64 flags, vm::ptr pOpt) { - sys_prx.Todo("sys_prx_stop_module(id=0x%x, args=%d, argp_addr=0x%x, modres_addr=0x%x, flags=0x%llx, pOpt=0x%x)", - id, args, argp_addr, modres.addr(), flags, pOpt.addr()); + sys_prx.Warning("sys_prx_stop_module(id=0x%x, flags=0x%llx, pOpt=*0x%x)", id, flags, pOpt); - const auto prx = Emu.GetIdManager().GetIDData(id); + const auto prx = Emu.GetIdManager().get(id); if (!prx) { return CELL_ESRCH; } - if (!prx->isStarted) - return CELL_PRX_ERROR_ALREADY_STOPPED; + //if (!prx->is_started) + // return CELL_PRX_ERROR_ALREADY_STOPPED; + + //prx->is_started = false; + pOpt->entry_point.set(be_t::make(prx->stop ? prx->stop.addr() : -1)); return CELL_OK; } s32 sys_prx_unload_module(s32 id, u64 flags, vm::ptr pOpt) { - sys_prx.Todo("sys_prx_unload_module(id=0x%x, flags=0x%llx, pOpt=0x%x)", id, flags, pOpt.addr()); + sys_prx.Warning("sys_prx_unload_module(id=0x%x, flags=0x%llx, pOpt=*0x%x)", id, flags, pOpt); // Get the PRX, free the used memory and delete the object and its ID - const auto prx = Emu.GetIdManager().GetIDData(id); + const auto prx = Emu.GetIdManager().get(id); if (!prx) { return CELL_ESRCH; } - Memory.Free(prx->address); - Emu.GetIdManager().RemoveID(id); + //Memory.Free(prx->address); + + //s32 result = prx->exit ? prx->exit() : CELL_OK; + Emu.GetIdManager().remove(id); return CELL_OK; } @@ -146,15 +267,15 @@ s32 sys_prx_get_module_info() return CELL_OK; } -s32 sys_prx_register_library(u32 lib_addr) +s32 sys_prx_register_library(vm::ptr library) { - sys_prx.Todo("sys_prx_register_library(lib_addr=0x%x)", lib_addr); + sys_prx.Todo("sys_prx_register_library(library=*0x%x)", library); return CELL_OK; } -s32 sys_prx_unregister_library() +s32 sys_prx_unregister_library(vm::ptr library) { - sys_prx.Todo("sys_prx_unregister_library()"); + sys_prx.Todo("sys_prx_unregister_library(library=*0x%x)", library); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_prx.h b/rpcs3/Emu/SysCalls/lv2/sys_prx.h index f0c550ecff..215aa3a4a6 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_prx.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_prx.h @@ -101,11 +101,15 @@ struct sys_prx_load_module_option_t struct sys_prx_start_module_option_t { be_t size; + be_t put; + vm::bptr argv), 1, u64> entry_point; }; struct sys_prx_stop_module_option_t { be_t size; + be_t put; + vm::bptr argv), 1, u64> entry_point; }; struct sys_prx_unload_module_option_t @@ -114,34 +118,37 @@ struct sys_prx_unload_module_option_t }; // Auxiliary data types -struct sys_prx_t +struct lv2_prx_t { - u32 size; - u32 address; - std::string path; - bool isStarted; + bool is_started = false; - sys_prx_t() - : isStarted(false) + vm::ptr argv)> start = vm::null; + vm::ptr argv)> stop = vm::null; + vm::ptr exit = vm::null; + + lv2_prx_t() { } }; +REG_ID_TYPE(lv2_prx_t, 0x23); // SYS_PRX_OBJECT + // SysCalls s32 sys_prx_load_module(vm::ptr path, u64 flags, vm::ptr pOpt); +s32 sys_prx_load_module_list(s32 count, vm::ptr path_list, u64 flags, vm::ptr pOpt, vm::ptr id_list); s32 sys_prx_load_module_on_memcontainer(); s32 sys_prx_load_module_by_fd(); s32 sys_prx_load_module_on_memcontainer_by_fd(); -s32 sys_prx_start_module(s32 id, u32 args, u32 argp_addr, vm::ptr modres, u64 flags, vm::ptr pOpt); -s32 sys_prx_stop_module(s32 id, u32 args, u32 argp_addr, vm::ptr modres, u64 flags, vm::ptr pOpt); +s32 sys_prx_start_module(s32 id, u64 flags, vm::ptr pOpt); +s32 sys_prx_stop_module(s32 id, u64 flags, vm::ptr pOpt); s32 sys_prx_unload_module(s32 id, u64 flags, vm::ptr pOpt); s32 sys_prx_get_module_list(); s32 sys_prx_get_my_module_id(); s32 sys_prx_get_module_id_by_address(); s32 sys_prx_get_module_id_by_name(); s32 sys_prx_get_module_info(); -s32 sys_prx_register_library(u32 lib_addr); -s32 sys_prx_unregister_library(); +s32 sys_prx_register_library(vm::ptr library); +s32 sys_prx_unregister_library(vm::ptr library); s32 sys_prx_get_ppu_guid(); s32 sys_prx_register_module(); s32 sys_prx_query_module(); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp index 9757486276..d23d5270dc 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp @@ -36,9 +36,7 @@ s32 sys_rwlock_create(vm::ptr rw_lock_id, vm::ptr a return CELL_EINVAL; } - std::shared_ptr rwlock(new rwlock_t(attr->protocol, attr->name_u64)); - - *rw_lock_id = Emu.GetIdManager().GetNewID(rwlock, TYPE_RWLOCK); + *rw_lock_id = Emu.GetIdManager().make(attr->protocol, attr->name_u64); return CELL_OK; } @@ -49,7 +47,7 @@ s32 sys_rwlock_destroy(u32 rw_lock_id) LV2_LOCK; - const auto rwlock = Emu.GetIdManager().GetIDData(rw_lock_id); + const auto rwlock = Emu.GetIdManager().get(rw_lock_id); if (!rwlock) { @@ -61,7 +59,7 @@ s32 sys_rwlock_destroy(u32 rw_lock_id) return CELL_EBUSY; } - Emu.GetIdManager().RemoveID(rw_lock_id); + Emu.GetIdManager().remove(rw_lock_id); return CELL_OK; } @@ -74,7 +72,7 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) LV2_LOCK; - const auto rwlock = Emu.GetIdManager().GetIDData(rw_lock_id); + const auto rwlock = Emu.GetIdManager().get(rw_lock_id); if (!rwlock) { @@ -113,7 +111,7 @@ s32 sys_rwlock_tryrlock(u32 rw_lock_id) LV2_LOCK; - const auto rwlock = Emu.GetIdManager().GetIDData(rw_lock_id); + const auto rwlock = Emu.GetIdManager().get(rw_lock_id); if (!rwlock) { @@ -136,7 +134,7 @@ s32 sys_rwlock_runlock(u32 rw_lock_id) LV2_LOCK; - const auto rwlock = Emu.GetIdManager().GetIDData(rw_lock_id); + const auto rwlock = Emu.GetIdManager().get(rw_lock_id); if (!rwlock) { @@ -164,7 +162,7 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout) LV2_LOCK; - const auto rwlock = Emu.GetIdManager().GetIDData(rw_lock_id); + const auto rwlock = Emu.GetIdManager().get(rw_lock_id); if (!rwlock) { @@ -208,7 +206,7 @@ s32 sys_rwlock_trywlock(PPUThread& CPU, u32 rw_lock_id) LV2_LOCK; - const auto rwlock = Emu.GetIdManager().GetIDData(rw_lock_id); + const auto rwlock = Emu.GetIdManager().get(rw_lock_id); if (!rwlock) { @@ -236,7 +234,7 @@ s32 sys_rwlock_wunlock(PPUThread& CPU, u32 rw_lock_id) LV2_LOCK; - const auto rwlock = Emu.GetIdManager().GetIDData(rw_lock_id); + const auto rwlock = Emu.GetIdManager().get(rw_lock_id); if (!rwlock) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.h b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.h index 5fdfa81e94..cb3d73a575 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.h @@ -15,7 +15,7 @@ struct sys_rwlock_attribute_t }; }; -struct rwlock_t +struct lv2_rwlock_t { const u32 protocol; const u64 name; @@ -29,7 +29,7 @@ struct rwlock_t std::atomic rwaiters; std::atomic wwaiters; - rwlock_t(u32 protocol, u64 name) + lv2_rwlock_t(u32 protocol, u64 name) : protocol(protocol) , name(name) , readers(0) @@ -40,6 +40,8 @@ struct rwlock_t } }; +REG_ID_TYPE(lv2_rwlock_t, 0x88); // SYS_RWLOCK_OBJECT + // SysCalls s32 sys_rwlock_create(vm::ptr rw_lock_id, vm::ptr attr); s32 sys_rwlock_destroy(u32 rw_lock_id); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp index 56db6b34aa..a693d7239a 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp @@ -12,13 +12,6 @@ SysCallBase sys_semaphore("sys_semaphore"); -u32 semaphore_create(s32 initial_val, s32 max_val, u32 protocol, u64 name_u64) -{ - std::shared_ptr sem(new semaphore_t(protocol, max_val, name_u64, initial_val)); - - return Emu.GetIdManager().GetNewID(sem, TYPE_SEMAPHORE); -} - s32 sys_semaphore_create(vm::ptr sem, vm::ptr attr, s32 initial_val, s32 max_val) { sys_semaphore.Warning("sys_semaphore_create(sem=*0x%x, attr=*0x%x, initial_val=%d, max_val=%d)", sem, attr, initial_val, max_val); @@ -50,7 +43,7 @@ s32 sys_semaphore_create(vm::ptr sem, vm::ptr at return CELL_EINVAL; } - *sem = semaphore_create(initial_val, max_val, protocol, attr->name_u64); + *sem = Emu.GetIdManager().make(initial_val, max_val, protocol, attr->name_u64); return CELL_OK; } @@ -61,7 +54,7 @@ s32 sys_semaphore_destroy(u32 sem) LV2_LOCK; - const auto semaphore = Emu.GetIdManager().GetIDData(sem); + const auto semaphore = Emu.GetIdManager().get(sem); if (!semaphore) { @@ -73,7 +66,7 @@ s32 sys_semaphore_destroy(u32 sem) return CELL_EBUSY; } - Emu.GetIdManager().RemoveID(sem); + Emu.GetIdManager().remove(sem); return CELL_OK; } @@ -86,7 +79,7 @@ s32 sys_semaphore_wait(u32 sem, u64 timeout) LV2_LOCK; - const auto semaphore = Emu.GetIdManager().GetIDData(sem); + const auto semaphore = Emu.GetIdManager().get(sem); if (!semaphore) { @@ -125,7 +118,7 @@ s32 sys_semaphore_trywait(u32 sem) LV2_LOCK; - const auto semaphore = Emu.GetIdManager().GetIDData(sem); + const auto semaphore = Emu.GetIdManager().get(sem); if (!semaphore) { @@ -148,7 +141,7 @@ s32 sys_semaphore_post(u32 sem, s32 count) LV2_LOCK; - const auto semaphore = Emu.GetIdManager().GetIDData(sem); + const auto semaphore = Emu.GetIdManager().get(sem); if (!semaphore) { @@ -189,7 +182,7 @@ s32 sys_semaphore_get_value(u32 sem, vm::ptr count) LV2_LOCK; - const auto semaphore = Emu.GetIdManager().GetIDData(sem); + const auto semaphore = Emu.GetIdManager().get(sem); if (!semaphore) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h index 102545bc2c..a0e98a97ba 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h @@ -15,7 +15,7 @@ struct sys_semaphore_attribute_t }; }; -struct semaphore_t +struct lv2_sema_t { const u32 protocol; const s32 max; @@ -27,7 +27,7 @@ struct semaphore_t std::condition_variable cv; std::atomic waiters; - semaphore_t(u32 protocol, s32 max, u64 name, s32 value) + lv2_sema_t(u32 protocol, s32 max, u64 name, s32 value) : protocol(protocol) , max(max) , name(name) @@ -37,8 +37,7 @@ struct semaphore_t } }; -// Aux -u32 semaphore_create(s32 initial_val, s32 max_val, u32 protocol, u64 name_u64); +REG_ID_TYPE(lv2_sema_t, 0x96); // SYS_SEMAPHORE_OBJECT // SysCalls s32 sys_semaphore_create(vm::ptr sem, vm::ptr attr, s32 initial_val, s32 max_val); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 7790bb0f4b..dd39861734 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -108,7 +108,7 @@ u32 spu_thread_initialize(u32 group_id, u32 spu_num, vm::ptr img, spu.SetName(name); spu.m_custom_task = task; - const auto group = Emu.GetIdManager().GetIDData(group_id); + const auto group = Emu.GetIdManager().get(group_id); spu.tg = group; group->threads[spu_num] = t; @@ -140,7 +140,7 @@ s32 sys_spu_thread_initialize(vm::ptr thread, u32 group_id, u32 spu_num, vm LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(group_id); + const auto group = Emu.GetIdManager().get(group_id); if (!group) { @@ -221,9 +221,7 @@ u32 spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type sys_spu.Todo("Unsupported SPU Thread Group type (0x%x)", type); } - std::shared_ptr group(new spu_group_t(name, num, prio, type, container)); - - return Emu.GetIdManager().GetNewID(group); + return Emu.GetIdManager().make(name, num, prio, type, container); } s32 sys_spu_thread_group_create(vm::ptr id, u32 num, s32 prio, vm::ptr attr) @@ -247,7 +245,7 @@ s32 sys_spu_thread_group_destroy(u32 id) LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); + const auto group = Emu.GetIdManager().get(id); if (!group) { @@ -274,7 +272,7 @@ s32 sys_spu_thread_group_destroy(u32 id) } group->state = SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED; // hack - Emu.GetIdManager().RemoveID(id); + Emu.GetIdManager().remove(id); return CELL_OK; } @@ -285,7 +283,7 @@ s32 sys_spu_thread_group_start(u32 id) LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); + const auto group = Emu.GetIdManager().get(id); if (!group) { @@ -348,7 +346,7 @@ s32 sys_spu_thread_group_suspend(u32 id) LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); + const auto group = Emu.GetIdManager().get(id); if (!group) { @@ -403,7 +401,7 @@ s32 sys_spu_thread_group_resume(u32 id) LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); + const auto group = Emu.GetIdManager().get(id); if (!group) { @@ -450,7 +448,7 @@ s32 sys_spu_thread_group_yield(u32 id) LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); + const auto group = Emu.GetIdManager().get(id); if (!group) { @@ -475,7 +473,7 @@ s32 sys_spu_thread_group_terminate(u32 id, s32 value) // seems the id can be either SPU Thread Group or SPU Thread auto thread = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); - auto group = Emu.GetIdManager().GetIDData(id); + auto group = Emu.GetIdManager().get(id); if (!group && !thread) { @@ -540,7 +538,7 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr cause, vm::ptr status) LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); + const auto group = Emu.GetIdManager().get(id); if (!group) { @@ -778,8 +776,8 @@ s32 sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et) LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); - const auto queue = Emu.GetIdManager().GetIDData(eq); + const auto group = Emu.GetIdManager().get(id); + const auto queue = Emu.GetIdManager().get(eq); if (!group || !queue) { @@ -834,7 +832,7 @@ s32 sys_spu_thread_group_disconnect_event(u32 id, u32 et) LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); + const auto group = Emu.GetIdManager().get(id); if (!group) { @@ -898,7 +896,7 @@ s32 sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup) LV2_LOCK; const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); - const auto queue = Emu.GetIdManager().GetIDData(eq); + const auto queue = Emu.GetIdManager().get(eq); if (!t || !queue) { @@ -965,7 +963,7 @@ s32 sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num) LV2_LOCK; const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); - const auto queue = Emu.GetIdManager().GetIDData(spuq); + const auto queue = Emu.GetIdManager().get(spuq); if (!t || !queue) { @@ -1038,8 +1036,8 @@ s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, vm:: LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); - const auto queue = Emu.GetIdManager().GetIDData(eq); + const auto group = Emu.GetIdManager().get(id); + const auto queue = Emu.GetIdManager().get(eq); if (!group || !queue) { @@ -1113,7 +1111,7 @@ s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup) LV2_LOCK; - const auto group = Emu.GetIdManager().GetIDData(id); + const auto group = Emu.GetIdManager().get(id); if (!group) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.h b/rpcs3/Emu/SysCalls/lv2/sys_spu.h index 45884f9744..590d93dead 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.h @@ -157,9 +157,9 @@ struct spu_group_t std::atomic join_state; // flags used to detect exit cause std::condition_variable join_cv; // used to signal waiting PPU thread - std::weak_ptr ep_run; // port for SYS_SPU_THREAD_GROUP_EVENT_RUN events - std::weak_ptr ep_exception; // TODO: SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION - std::weak_ptr ep_sysmodule; // TODO: SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE + std::weak_ptr ep_run; // port for SYS_SPU_THREAD_GROUP_EVENT_RUN events + std::weak_ptr ep_exception; // TODO: SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION + std::weak_ptr ep_sysmodule; // TODO: SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE spu_group_t(std::string name, u32 num, s32 prio, s32 type, u32 ct) : name(name) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp index c1fb0ffa59..3bc6592e11 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp @@ -18,7 +18,7 @@ s32 sys_timer_create(vm::ptr timer_id) std::shared_ptr timer(new lv2_timer_t); - thread_t(fmt::format("Timer[0x%x] Thread", (*timer_id = Emu.GetIdManager().GetNewID(timer, TYPE_TIMER))), [timer]() + thread_t(fmt::format("Timer[0x%x] Thread", (*timer_id = Emu.GetIdManager().add(timer))), [timer]() // TODO: call from the constructor { LV2_LOCK; @@ -62,7 +62,7 @@ s32 sys_timer_destroy(u32 timer_id) LV2_LOCK; - const auto timer = Emu.GetIdManager().GetIDData(timer_id); + const auto timer = Emu.GetIdManager().get(timer_id); if (!timer) { @@ -74,7 +74,7 @@ s32 sys_timer_destroy(u32 timer_id) return CELL_EISCONN; } - Emu.GetIdManager().RemoveID(timer_id); + Emu.GetIdManager().remove(timer_id); return CELL_OK; } @@ -85,7 +85,7 @@ s32 sys_timer_get_information(u32 timer_id, vm::ptr inf LV2_LOCK; - const auto timer = Emu.GetIdManager().GetIDData(timer_id); + const auto timer = Emu.GetIdManager().get(timer_id); if (!timer) { @@ -108,7 +108,7 @@ s32 _sys_timer_start(u32 timer_id, u64 base_time, u64 period) LV2_LOCK; - const auto timer = Emu.GetIdManager().GetIDData(timer_id); + const auto timer = Emu.GetIdManager().get(timer_id); if (!timer) { @@ -160,7 +160,7 @@ s32 sys_timer_stop(u32 timer_id) LV2_LOCK; - const auto timer = Emu.GetIdManager().GetIDData(timer_id); + const auto timer = Emu.GetIdManager().get(timer_id); if (!timer) { @@ -178,8 +178,8 @@ s32 sys_timer_connect_event_queue(u32 timer_id, u32 queue_id, u64 name, u64 data LV2_LOCK; - const auto timer = Emu.GetIdManager().GetIDData(timer_id); - const auto queue = Emu.GetIdManager().GetIDData(queue_id); + const auto timer = Emu.GetIdManager().get(timer_id); + const auto queue = Emu.GetIdManager().get(queue_id); if (!timer || !queue) { @@ -205,7 +205,7 @@ s32 sys_timer_disconnect_event_queue(u32 timer_id) LV2_LOCK; - const auto timer = Emu.GetIdManager().GetIDData(timer_id); + const auto timer = Emu.GetIdManager().get(timer_id); if (!timer) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_timer.h b/rpcs3/Emu/SysCalls/lv2/sys_timer.h index 95b0c94793..257d779b3d 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_timer.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_timer.h @@ -18,7 +18,7 @@ struct sys_timer_information_t // "timer_t" conflicts with some definition struct lv2_timer_t { - std::weak_ptr port; // event queue + std::weak_ptr port; // event queue u64 source; // event source u64 data1; // event arg 1 u64 data2; // event arg 2 @@ -37,6 +37,8 @@ struct lv2_timer_t } }; +REG_ID_TYPE(lv2_timer_t, 0x11); // SYS_TIMER_OBJECT + s32 sys_timer_create(vm::ptr timer_id); s32 sys_timer_destroy(u32 timer_id); s32 sys_timer_get_information(u32 timer_id, vm::ptr info); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp index da5144cd04..cb9f9b65ff 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp @@ -39,7 +39,7 @@ s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 a else { // Check memory container. - const auto ct = Emu.GetIdManager().GetIDData(cid); + const auto ct = Emu.GetIdManager().get(cid); if (!ct) { diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 84cace9b3e..29e50d58c2 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -49,7 +49,7 @@ Emulator::Emulator() , m_pad_manager(new PadManager()) , m_keyboard_manager(new KeyboardManager()) , m_mouse_manager(new MouseManager()) - , m_id_manager(new IdManager()) + , m_id_manager(new ID_manager()) , m_gs_manager(new GSManager()) , m_audio_manager(new AudioManager()) , m_callback_manager(new CallbackManager()) @@ -326,7 +326,7 @@ void Emulator::Pause() if (!IsRunning()) return; SendDbgCommand(DID_PAUSE_EMU); - if (InterlockedCompareExchange((volatile u32*)&m_status, Paused, Running) == Running) + if (sync_bool_compare_and_swap((volatile u32*)&m_status, Running, Paused)) { SendDbgCommand(DID_PAUSED_EMU); @@ -396,7 +396,7 @@ void Emulator::Stop() GetAudioManager().Close(); GetEventManager().Clear(); GetCPU().Close(); - GetIdManager().Clear(); + GetIdManager().clear(); GetPadManager().Close(); GetKeyboardManager().Close(); GetMouseManager().Close(); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 5f8c114132..280907b66f 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -14,7 +14,7 @@ class CPUThreadManager; class PadManager; class KeyboardManager; class MouseManager; -class IdManager; +class ID_manager; class GSManager; class AudioManager; class CallbackManager; @@ -84,7 +84,7 @@ class Emulator PadManager* m_pad_manager; KeyboardManager* m_keyboard_manager; MouseManager* m_mouse_manager; - IdManager* m_id_manager; + ID_manager* m_id_manager; GSManager* m_gs_manager; AudioManager* m_audio_manager; CallbackManager* m_callback_manager; @@ -141,7 +141,7 @@ public: PadManager& GetPadManager() { return *m_pad_manager; } KeyboardManager& GetKeyboardManager() { return *m_keyboard_manager; } MouseManager& GetMouseManager() { return *m_mouse_manager; } - IdManager& GetIdManager() { return *m_id_manager; } + ID_manager& GetIdManager() { return *m_id_manager; } GSManager& GetGSManager() { return *m_gs_manager; } AudioManager& GetAudioManager() { return *m_audio_manager; } CallbackManager& GetCallbackManager() { return *m_callback_manager; } @@ -190,10 +190,10 @@ public: void SavePoints(const std::string& path); void LoadPoints(const std::string& path); - __forceinline bool IsRunning() const { return m_status == Running; } - __forceinline bool IsPaused() const { return m_status == Paused; } - __forceinline bool IsStopped() const { return m_status == Stopped; } - __forceinline bool IsReady() const { return m_status == Ready; } + force_inline bool IsRunning() const { return m_status == Running; } + force_inline bool IsPaused() const { return m_status == Paused; } + force_inline bool IsStopped() const { return m_status == Stopped; } + force_inline bool IsReady() const { return m_status == Ready; } }; using lv2_lock_type = std::unique_lock; diff --git a/rpcs3/Gui/KernelExplorer.cpp b/rpcs3/Gui/KernelExplorer.cpp index bf451f35bf..c7bee4f0f7 100644 --- a/rpcs3/Gui/KernelExplorer.cpp +++ b/rpcs3/Gui/KernelExplorer.cpp @@ -13,6 +13,7 @@ #include "Emu/SysCalls/lv2/sys_cond.h" #include "Emu/SysCalls/lv2/sys_semaphore.h" #include "Emu/SysCalls/lv2/sys_event.h" +#include "Emu/SysCalls/lv2/sys_process.h" #include "KernelExplorer.h" @@ -50,7 +51,6 @@ KernelExplorer::KernelExplorer(wxWindow* parent) void KernelExplorer::Update() { - int count; char name[4096]; m_tree->DeleteAllItems(); @@ -77,112 +77,104 @@ void KernelExplorer::Update() // TODO: FileSystem // Semaphores - count = Emu.GetIdManager().GetTypeCount(TYPE_SEMAPHORE); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_SEMAPHORE_OBJECT)) { sprintf(name, "Semaphores (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().GetTypeIDs(TYPE_SEMAPHORE)) + for (const auto id : Emu.GetIdManager().get_IDs_by_type(SYS_SEMAPHORE_OBJECT)) { - const auto sem = Emu.GetIdManager().GetIDData(id); + const auto sem = Emu.GetIdManager().get(id); sprintf(name, "Semaphore: ID = 0x%x '%s', Count = %d, Max Count = %d, Waiters = %d", id, &name64(sem->name), sem->value.load(), sem->max, sem->waiters.load()); m_tree->AppendItem(node, name); } } // Mutexes - count = Emu.GetIdManager().GetTypeCount(TYPE_MUTEX); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_MUTEX_OBJECT)) { sprintf(name, "Mutexes (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().GetTypeIDs(TYPE_MUTEX)) + for (const auto id : Emu.GetIdManager().get_IDs_by_type(SYS_MUTEX_OBJECT)) { - const auto mutex = Emu.GetIdManager().GetIDData(id); + const auto mutex = Emu.GetIdManager().get(id); sprintf(name, "Mutex: ID = 0x%x '%s'", id, &name64(mutex->name)); m_tree->AppendItem(node, name); } } // Light Weight Mutexes - count = Emu.GetIdManager().GetTypeCount(TYPE_LWMUTEX); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_LWMUTEX_OBJECT)) { sprintf(name, "Lightweight Mutexes (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().GetTypeIDs(TYPE_LWMUTEX)) + for (const auto id : Emu.GetIdManager().get_IDs_by_type(SYS_LWMUTEX_OBJECT)) { - const auto lwm = Emu.GetIdManager().GetIDData(id); + const auto lwm = Emu.GetIdManager().get(id); sprintf(name, "Lightweight Mutex: ID = 0x%x '%s'", id, &name64(lwm->name)); m_tree->AppendItem(node, name); } } // Condition Variables - count = Emu.GetIdManager().GetTypeCount(TYPE_COND); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_COND_OBJECT)) { sprintf(name, "Condition Variables (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().GetTypeIDs(TYPE_COND)) + for (const auto id : Emu.GetIdManager().get_IDs_by_type(SYS_COND_OBJECT)) { - const auto cond = Emu.GetIdManager().GetIDData(id); + const auto cond = Emu.GetIdManager().get(id); sprintf(name, "Condition Variable: ID = 0x%x '%s'", id, &name64(cond->name)); m_tree->AppendItem(node, name); } } // Light Weight Condition Variables - count = Emu.GetIdManager().GetTypeCount(TYPE_LWCOND); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_LWCOND_OBJECT)) { sprintf(name, "Lightweight Condition Variables (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().GetTypeIDs(TYPE_LWCOND)) + for (const auto id : Emu.GetIdManager().get_IDs_by_type(SYS_LWCOND_OBJECT)) { - const auto lwc = Emu.GetIdManager().GetIDData(id); + const auto lwc = Emu.GetIdManager().get(id); sprintf(name, "Lightweight Condition Variable: ID = 0x%x '%s'", id, &name64(lwc->name)); m_tree->AppendItem(node, name); } } // Event Queues - count = Emu.GetIdManager().GetTypeCount(TYPE_EVENT_QUEUE); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_EVENT_QUEUE_OBJECT)) { sprintf(name, "Event Queues (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().GetTypeIDs(TYPE_EVENT_QUEUE)) + for (const auto id : Emu.GetIdManager().get_IDs_by_type(SYS_EVENT_QUEUE_OBJECT)) { - const auto queue = Emu.GetIdManager().GetIDData(id); + const auto queue = Emu.GetIdManager().get(id); sprintf(name, "Event Queue: ID = 0x%x '%s', Key = %#llx", id, &name64(queue->name), queue->key); m_tree->AppendItem(node, name); } } // Event Ports - count = Emu.GetIdManager().GetTypeCount(TYPE_EVENT_PORT); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_EVENT_PORT_OBJECT)) { sprintf(name, "Event Ports (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().GetTypeIDs(TYPE_EVENT_PORT)) + for (const auto id : Emu.GetIdManager().get_IDs_by_type(SYS_EVENT_PORT_OBJECT)) { - const auto port = Emu.GetIdManager().GetIDData(id); + const auto port = Emu.GetIdManager().get(id); sprintf(name, "Event Port: ID = 0x%x, Name = %#llx", id, port->name); m_tree->AppendItem(node, name); } } // Modules - count = Emu.GetIdManager().GetTypeCount(TYPE_PRX); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_PRX_OBJECT)) { sprintf(name, "Modules (%d)", count); const auto& node = m_tree->AppendItem(root, name); //sprintf(name, "Segment List (%l)", 2 * objects.size()); // TODO: Assuming 2 segments per PRX file is not good //m_tree->AppendItem(node, name); - for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_PRX)) + for (const auto& id : Emu.GetIdManager().get_IDs_by_type(SYS_PRX_OBJECT)) { sprintf(name, "PRX: ID = 0x%x", id); m_tree->AppendItem(node, name); @@ -190,12 +182,11 @@ void KernelExplorer::Update() } // Memory Containers - count = Emu.GetIdManager().GetTypeCount(TYPE_MEM); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_MEM_OBJECT)) { sprintf(name, "Memory Containers (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_MEM)) + for (const auto& id : Emu.GetIdManager().get_IDs_by_type(SYS_MEM_OBJECT)) { sprintf(name, "Memory Container: ID = 0x%x", id); m_tree->AppendItem(node, name); @@ -203,12 +194,11 @@ void KernelExplorer::Update() } // Event Flags - count = Emu.GetIdManager().GetTypeCount(TYPE_EVENT_FLAG); - if (count) + if (u32 count = Emu.GetIdManager().get_count_by_type(SYS_EVENT_FLAG_OBJECT)) { sprintf(name, "Event Flags (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto& id : Emu.GetIdManager().GetTypeIDs(TYPE_EVENT_FLAG)) + for (const auto& id : Emu.GetIdManager().get_IDs_by_type(SYS_EVENT_FLAG_OBJECT)) { sprintf(name, "Event Flag: ID = 0x%x", id); m_tree->AppendItem(node, name); diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index 32fd0706fa..0a25330f96 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -673,26 +673,6 @@ namespace loader LOG_WARNING(LOADER, "Unknown module '%s'", module_name.c_str()); } - //struct tbl_item - //{ - // be_t stub; - // be_t rtoc; - //}; - - //struct stub_data_t - //{ - // be_t data[3]; - //} - //static const stub_data = - //{ - // be_t::make(MR(11, 2)), - // be_t::make(SC(0)), - // be_t::make(BLR()) - //}; - - //const auto& tbl = vm::get().alloc(stub->s_imports); - //const auto& dst = vm::get().alloc(stub->s_imports); - for (u32 i = 0; i < stub->s_imports; ++i) { const u32 nid = stub->s_nid[i]; @@ -719,31 +699,6 @@ namespace loader { LOG_ERROR(LOADER, "Failed to inject code at address 0x%x", addr); } - - //if (!func || !func->lle_func) - //{ - // dst[i] = stub_data; - - // tbl[i].stub = (dst + i).addr(); - // tbl[i].rtoc = stub->s_nid[i]; - - // stub->s_text[i] = (tbl + i).addr(); - - // if (!func) - // { - // - // } - // else //if (Ini.HLELogging.GetValue()) - // { - // LOG_NOTICE(LOADER, "Imported function '%s' in '%s' module (HLE)", SysCalls::GetHLEFuncName(nid).c_str(), module_name.c_str()); - // } - //} - //else - //{ - // stub->s_text[i] = func->lle_func.addr(); - // //Is function auto exported, than we can use it - // LOG_NOTICE(LOADER, "Imported function '%s' in '%s' module (LLE: 0x%x)", SysCalls::GetHLEFuncName(nid).c_str(), module_name.c_str(), (u32)stub->s_text[i]); - //} } } } diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 70f6cb37cc..80ef571ee6 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -418,7 +418,6 @@ - diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 9adbdd03c6..aa8ddbdc0e 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1543,9 +1543,6 @@ Emu\Memory - - Emu\Memory - Emu\SysCalls\lv2 diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index b6a071cf0e..0b3601d755 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -52,7 +52,7 @@ typedef int16_t s16; typedef int32_t s32; typedef int64_t s64; -template __forceinline T align(const T addr, int align) +template force_inline T align(const T addr, int align) { return (addr + (align - 1)) & ~(align - 1); } @@ -61,7 +61,10 @@ template __forceinline T align(const T addr, int align) #include "Utilities/StrFmt.h" #include "Emu/Memory/atomic.h" -#include "Emu/Memory/refcnt.h" + +template struct ID_type; + +#define REG_ID_TYPE(t, id) template<> struct ID_type { static const u32 type = id; } #define _PRGNAME_ "RPCS3" #define _PRGVER_ "0.0.0.5"