diff --git a/src/xenia/base/math.h b/src/xenia/base/math.h index a2f2dc233..4a54647b8 100644 --- a/src/xenia/base/math.h +++ b/src/xenia/base/math.h @@ -17,6 +17,16 @@ #include #include #include + +#if defined __has_include +#if __has_include() +#include +#endif +#endif +#if __cpp_lib_bitops +#include +#endif + #include "xenia/base/platform.h" #if XE_ARCH_AMD64 @@ -101,6 +111,23 @@ constexpr uint32_t select_bits(uint32_t value, uint32_t a, uint32_t b) { return (value & make_bitmask(a, b)) >> a; } +#if __cpp_lib_bitops +template +constexpr inline uint32_t bit_count(T v) { + return static_cast(std::popcount(v)); +} +#else +#if XE_COMPILER_MSVC || XE_COMPILER_INTEL +inline uint32_t bit_count(uint32_t v) { return __popcnt(v); } +inline uint32_t bit_count(uint64_t v) { + return static_cast(__popcnt64(v)); +} +#elif XE_COMPILER_GCC || XE_COMPILER_CLANG +static_assert(sizeof(unsigned int) == sizeof(uint32_t)); +static_assert(sizeof(unsigned long long) == sizeof(uint64_t)); +inline uint32_t bit_count(uint32_t v) { return __builtin_popcount(v); } +inline uint32_t bit_count(uint64_t v) { return __builtin_popcountll(v); } +#else inline uint32_t bit_count(uint32_t v) { v = v - ((v >> 1) & 0x55555555); v = (v & 0x33333333) + ((v >> 2) & 0x33333333); @@ -116,6 +143,8 @@ inline uint32_t bit_count(uint64_t v) { v = v + (v >> 32) & 0x0000007F; return static_cast(v); } +#endif +#endif // lzcnt instruction, typed for integers of all sizes. // The number of leading zero bits in the value parameter. If value is zero, the