mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 20:22:30 +01:00
bts/btr/btc support improved
This commit is contained in:
parent
130f7905ba
commit
8c8242345e
@ -174,7 +174,7 @@ struct atomic_storage
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The rest: ugly MSVC intrinsics + possibly __asm__ implementations (TODO) */
|
/* The rest: ugly MSVC intrinsics + inline asm implementations */
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct atomic_storage<T, 1> : atomic_storage<T, 0>
|
struct atomic_storage<T, 1> : atomic_storage<T, 0>
|
||||||
@ -297,6 +297,27 @@ struct atomic_storage<T, 2> : atomic_storage<T, 0>
|
|||||||
short r = _InterlockedDecrement16((volatile short*)&dest);
|
short r = _InterlockedDecrement16((volatile short*)&dest);
|
||||||
return (T&)r;
|
return (T&)r;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline bool bts(T& dest, uint bit)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
__asm__("lock btsw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool btr(T& dest, uint bit)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
__asm__("lock btrw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool btc(T& dest, uint bit)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
__asm__("lock btcw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -375,6 +396,27 @@ struct atomic_storage<T, 4> : atomic_storage<T, 0>
|
|||||||
{
|
{
|
||||||
return _interlockedbittestandreset((volatile long*)&dest, bit) != 0;
|
return _interlockedbittestandreset((volatile long*)&dest, bit) != 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline bool bts(T& dest, uint bit)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
__asm__("lock btsl %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool btr(T& dest, uint bit)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
__asm__("lock btrl %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool btc(T& dest, uint bit)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
__asm__("lock btcl %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -453,6 +495,27 @@ struct atomic_storage<T, 8> : atomic_storage<T, 0>
|
|||||||
{
|
{
|
||||||
return _interlockedbittestandreset64((volatile llong*)&dest, bit) != 0;
|
return _interlockedbittestandreset64((volatile llong*)&dest, bit) != 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline bool bts(T& dest, uint bit)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
__asm__("lock btsq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool btr(T& dest, uint bit)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
__asm__("lock btrq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool btc(T& dest, uint bit)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
__asm__("lock btcq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -490,6 +553,8 @@ struct atomic_storage<T, 16> : atomic_storage<T, 0>
|
|||||||
return *(T*)+cmp;
|
return *(T*)+cmp;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T1, typename T2, typename>
|
template<typename T1, typename T2, typename>
|
||||||
@ -642,7 +707,7 @@ struct atomic_test_and_set
|
|||||||
{
|
{
|
||||||
bool operator()(T1& lhs, const T2& rhs) const
|
bool operator()(T1& lhs, const T2& rhs) const
|
||||||
{
|
{
|
||||||
return lhs.test_and_set(rhs);
|
return test_and_set(lhs, rhs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -659,7 +724,7 @@ struct atomic_test_and_reset
|
|||||||
{
|
{
|
||||||
bool operator()(T1& lhs, const T2& rhs) const
|
bool operator()(T1& lhs, const T2& rhs) const
|
||||||
{
|
{
|
||||||
return lhs.test_and_reset(rhs);
|
return test_and_reset(lhs, rhs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -676,7 +741,7 @@ struct atomic_test_and_complement
|
|||||||
{
|
{
|
||||||
bool operator()(T1& lhs, const T2& rhs) const
|
bool operator()(T1& lhs, const T2& rhs) const
|
||||||
{
|
{
|
||||||
return lhs.test_and_complement(rhs);
|
return test_and_complement(lhs, rhs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,32 +199,32 @@ struct bs_base
|
|||||||
return (shift(lhs) & static_cast<under>(rhs)) != 0;
|
return (shift(lhs) & static_cast<under>(rhs)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool test_and_set(type& lhs, type rhs)
|
friend bool test_and_set(type& lhs, type rhs)
|
||||||
{
|
{
|
||||||
return test_and_set(reinterpret_cast<under&>(lhs), static_cast<under>(rhs));
|
return test_and_set(reinterpret_cast<under&>(lhs), static_cast<under>(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool test_and_set(type& lhs, T rhs)
|
friend bool test_and_set(type& lhs, T rhs)
|
||||||
{
|
{
|
||||||
return test_and_set(reinterpret_cast<under&>(lhs), shift(rhs));
|
return test_and_set(reinterpret_cast<under&>(lhs), shift(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool test_and_reset(type& lhs, type rhs)
|
friend bool test_and_reset(type& lhs, type rhs)
|
||||||
{
|
{
|
||||||
return test_and_reset(reinterpret_cast<under&>(lhs), static_cast<under>(rhs));
|
return test_and_reset(reinterpret_cast<under&>(lhs), static_cast<under>(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool test_and_reset(type& lhs, T rhs)
|
friend bool test_and_reset(type& lhs, T rhs)
|
||||||
{
|
{
|
||||||
return test_and_reset(reinterpret_cast<under&>(lhs), shift(rhs));
|
return test_and_reset(reinterpret_cast<under&>(lhs), shift(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool test_and_complement(type& lhs, type rhs)
|
friend bool test_and_complement(type& lhs, type rhs)
|
||||||
{
|
{
|
||||||
return test_and_complement(reinterpret_cast<under&>(lhs), static_cast<under>(rhs));
|
return test_and_complement(reinterpret_cast<under&>(lhs), static_cast<under>(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool test_and_complement(type& lhs, T rhs)
|
friend bool test_and_complement(type& lhs, T rhs)
|
||||||
{
|
{
|
||||||
return test_and_complement(reinterpret_cast<under&>(lhs), shift(rhs));
|
return test_and_complement(reinterpret_cast<under&>(lhs), shift(rhs));
|
||||||
}
|
}
|
||||||
@ -461,6 +461,8 @@ struct atomic_test_and_set<BS, T, void_t<decltype(T::__bitset_enum_max), std::en
|
|||||||
return atomic_storage<under>::bts(reinterpret_cast<under&>(left), static_cast<uint>(static_cast<under>(value)));
|
return atomic_storage<under>::bts(reinterpret_cast<under&>(left), static_cast<uint>(static_cast<under>(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr auto fetch_op = &_op;
|
||||||
|
static constexpr auto op_fetch = &_op;
|
||||||
static constexpr auto atomic_op = &_op;
|
static constexpr auto atomic_op = &_op;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -474,6 +476,8 @@ struct atomic_test_and_reset<BS, T, void_t<decltype(T::__bitset_enum_max), std::
|
|||||||
return atomic_storage<under>::btr(reinterpret_cast<under&>(left), static_cast<uint>(static_cast<under>(value)));
|
return atomic_storage<under>::btr(reinterpret_cast<under&>(left), static_cast<uint>(static_cast<under>(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr auto fetch_op = &_op;
|
||||||
|
static constexpr auto op_fetch = &_op;
|
||||||
static constexpr auto atomic_op = &_op;
|
static constexpr auto atomic_op = &_op;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -487,6 +491,53 @@ struct atomic_test_and_complement<BS, T, void_t<decltype(T::__bitset_enum_max),
|
|||||||
return atomic_storage<under>::btc(reinterpret_cast<under&>(left), static_cast<uint>(static_cast<under>(value)));
|
return atomic_storage<under>::btc(reinterpret_cast<under&>(left), static_cast<uint>(static_cast<under>(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr auto fetch_op = &_op;
|
||||||
|
static constexpr auto op_fetch = &_op;
|
||||||
|
static constexpr auto atomic_op = &_op;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct atomic_test_and_set<T, T, void_t<decltype(T::__bitset_set_type)>>
|
||||||
|
{
|
||||||
|
using under = std::underlying_type_t<T>;
|
||||||
|
|
||||||
|
static inline bool _op(T& left, T value)
|
||||||
|
{
|
||||||
|
return atomic_storage<under>::test_and_set(reinterpret_cast<under&>(left), static_cast<under>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto fetch_op = &_op;
|
||||||
|
static constexpr auto op_fetch = &_op;
|
||||||
|
static constexpr auto atomic_op = &_op;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct atomic_test_and_reset<T, T, void_t<decltype(T::__bitset_set_type)>>
|
||||||
|
{
|
||||||
|
using under = std::underlying_type_t<T>;
|
||||||
|
|
||||||
|
static inline bool _op(T& left, T value)
|
||||||
|
{
|
||||||
|
return atomic_storage<under>::test_and_reset(reinterpret_cast<under&>(left), static_cast<under>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto fetch_op = &_op;
|
||||||
|
static constexpr auto op_fetch = &_op;
|
||||||
|
static constexpr auto atomic_op = &_op;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct atomic_test_and_complement<T, T, void_t<decltype(T::__bitset_set_type)>>
|
||||||
|
{
|
||||||
|
using under = std::underlying_type_t<T>;
|
||||||
|
|
||||||
|
static inline bool _op(T& left, T value)
|
||||||
|
{
|
||||||
|
return atomic_storage<under>::test_and_complement(reinterpret_cast<under&>(left), static_cast<under>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto fetch_op = &_op;
|
||||||
|
static constexpr auto op_fetch = &_op;
|
||||||
static constexpr auto atomic_op = &_op;
|
static constexpr auto atomic_op = &_op;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -634,3 +685,48 @@ struct atomic_xor<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std:
|
|||||||
static constexpr auto op_fetch = &op2;
|
static constexpr auto op_fetch = &op2;
|
||||||
static constexpr auto atomic_op = &op2;
|
static constexpr auto atomic_op = &op2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct atomic_test_and_set<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std::is_enum<T>::value>>>
|
||||||
|
{
|
||||||
|
using under = std::underlying_type_t<T>;
|
||||||
|
|
||||||
|
static inline bool _op(T& left, T value)
|
||||||
|
{
|
||||||
|
return atomic_storage<under>::test_and_set(reinterpret_cast<under&>(left), static_cast<under>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto fetch_op = &_op;
|
||||||
|
static constexpr auto op_fetch = &_op;
|
||||||
|
static constexpr auto atomic_op = &_op;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct atomic_test_and_reset<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std::is_enum<T>::value>>>
|
||||||
|
{
|
||||||
|
using under = std::underlying_type_t<T>;
|
||||||
|
|
||||||
|
static inline bool _op(T& left, T value)
|
||||||
|
{
|
||||||
|
return atomic_storage<under>::test_and_reset(reinterpret_cast<under&>(left), static_cast<under>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto fetch_op = &_op;
|
||||||
|
static constexpr auto op_fetch = &_op;
|
||||||
|
static constexpr auto atomic_op = &_op;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct atomic_test_and_complement<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std::is_enum<T>::value>>>
|
||||||
|
{
|
||||||
|
using under = std::underlying_type_t<T>;
|
||||||
|
|
||||||
|
static inline bool _op(T& left, T value)
|
||||||
|
{
|
||||||
|
return atomic_storage<under>::test_and_complement(reinterpret_cast<under&>(left), static_cast<under>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto fetch_op = &_op;
|
||||||
|
static constexpr auto op_fetch = &_op;
|
||||||
|
static constexpr auto atomic_op = &_op;
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user