From 5feba3a7167b54bbebb1bba7159dcbda91b41663 Mon Sep 17 00:00:00 2001 From: Waldemar Pawlaszek Date: Sun, 31 Jul 2022 22:26:59 +0200 Subject: [PATCH] More robust popcnt --- src/engine/platform/sound/lynx/Mikey.cpp | 105 +++++++++++------------ 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/src/engine/platform/sound/lynx/Mikey.cpp b/src/engine/platform/sound/lynx/Mikey.cpp index 718180033..791336c1b 100644 --- a/src/engine/platform/sound/lynx/Mikey.cpp +++ b/src/engine/platform/sound/lynx/Mikey.cpp @@ -26,39 +26,11 @@ #include #include -#if defined(i386) || defined(__i386__) || defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) -#define IS_INTEL -#endif +#if defined( _MSC_VER ) -#ifdef IS_INTEL -#if defined ( _MSC_VER ) #include -static void cpuid( int info[4], int infoType ) -{ - __cpuidex( info, infoType, 0 ); -} - -#else -#include - -static void cpuid( int info[4], int infoType ) -{ - __cpuid_count( infoType, 0, info[0], info[1], info[2], info[3] ); -} - -#endif -#endif - -namespace Lynx -{ - -namespace -{ - -static constexpr int64_t CNT_MAX = std::numeric_limits::max() & ~15; - -uint32_t popcnt_generic( uint32_t x ) +static uint32_t popcnt_generic( uint32_t x ) { int v = 0; while ( x != 0 ) @@ -69,18 +41,60 @@ uint32_t popcnt_generic( uint32_t x ) return v; } -#ifdef IS_INTEL -uint32_t popcnt_intrinsic( uint32_t x ) +#if defined( _M_IX86 ) || defined( _M_X64 ) + +static uint32_t popcnt_intrinsic( uint32_t x ) { -#if defined ( _MSC_VER ) return __popcnt( x ); -#else - return __builtin_popcount( x ); -#endif } + +static uint32_t( *popcnt )( uint32_t ); + +//detecting popcnt availability on msvc intel +static void selectPOPCNT() +{ + int info[4]; + __cpuid( info, 1 ); + if ( ( info[2] & ( (int)1 << 23 ) ) != 0 ) + { + popcnt = &popcnt_intrinsic; + } + else + { + popcnt = &popcnt_generic; + } +} + +#else //defined( _M_IX86 ) || defined( _M_X64 ) + +//MSVC non INTEL should use generic implementation +inline void selectPOPCNT() +{ +} + +#define popcnt popcnt_generic + #endif -static uint32_t( *popcnt )( uint32_t x ); +#else //defined( _MSC_VER ) + +//non MVSC should use builtin implementation + +inline void selectPOPCNT() +{ +} + +#define popcnt __builtin_popcount + +#endif + +namespace Lynx +{ + +namespace +{ + +static constexpr int64_t CNT_MAX = std::numeric_limits::max() & ~15; int32_t clamp( int32_t v, int32_t lo, int32_t hi ) { @@ -526,23 +540,8 @@ private: Mikey::Mikey( uint32_t sampleRate ) : mMikey{ std::make_unique() }, mQueue{ std::make_unique() }, mTick{}, mNextTick{}, mSampleRate{ sampleRate }, mSamplesRemainder{}, mTicksPerSample{ 16000000 / mSampleRate, 16000000 % mSampleRate } { + selectPOPCNT(); enqueueSampling(); - - //detecting popcnt availability -#ifdef IS_INTEL - int info[4]; - cpuid( info, 1 ); - if ( ( info[2] & ( (int)1 << 23 ) ) != 0 ) - { - popcnt = &popcnt_intrinsic; - } - else - { - popcnt = &popcnt_generic; - } -#else - popcnt = &popcnt_generic; -#endif } Mikey::~Mikey()