From: <man...@us...> - 2013-06-07 00:18:26
|
Revision: 2311 http://sourceforge.net/p/modplug/code/2311 Author: manxorist Date: 2013-06-07 00:18:17 +0000 (Fri, 07 Jun 2013) Log Message: ----------- [Ref] Rewrite cpuid feature detection in more readable C with intrinsics and move it from soundlib/Mmx_mix.cpp into common/misc_util.cpp. [Fix] Fix the semantics and naming of the feature flags and feature flag macros to more closely match commonly used feature names. Modified Paths: -------------- trunk/OpenMPT/common/BuildSettings.h trunk/OpenMPT/common/misc_util.cpp trunk/OpenMPT/common/misc_util.h trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/sounddsp/EQ.cpp trunk/OpenMPT/soundlib/Mmx_mix.cpp trunk/OpenMPT/soundlib/Snd_defs.h trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/common/BuildSettings.h =================================================================== --- trunk/OpenMPT/common/BuildSettings.h 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/common/BuildSettings.h 2013-06-07 00:18:17 UTC (rev 2311) @@ -44,12 +44,12 @@ // Generate inline assembly using MMX instructions (only used when the CPU supports it). #define ENABLE_MMX -// Generate inline assembly using 3DNOW instructions (only used when the CPU supports it). -#define ENABLE_3DNOW - // Generate inline assembly using SSE instructions (only used when the CPU supports it). #define ENABLE_SSE +// Generate inline assembly using AMD specific instruction set extensions (only used when the CPU supports it). +#define ENABLE_X86_AMD + #endif // ENABLE_ASM Modified: trunk/OpenMPT/common/misc_util.cpp =================================================================== --- trunk/OpenMPT/common/misc_util.cpp 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/common/misc_util.cpp 2013-06-07 00:18:17 UTC (rev 2311) @@ -10,3 +10,124 @@ #include "stdafx.h" #include "misc_util.h" + + +#if defined(ENABLE_ASM) + + +uint32 ProcSupport = 0; + + +#if MPT_COMPILER_MSVC && defined(ENABLE_X86) + + +#include <intrin.h> + + +typedef char cpuid_result_string[12]; + + +struct cpuid_result { + uint32 a; + uint32 b; + uint32 c; + uint32 d; + std::string as_string() const + { + cpuid_result_string result; + result[0+0] = (b >> 0) & 0xff; + result[0+1] = (b >> 8) & 0xff; + result[0+2] = (b >>16) & 0xff; + result[0+3] = (b >>24) & 0xff; + result[4+0] = (d >> 0) & 0xff; + result[4+1] = (d >> 8) & 0xff; + result[4+2] = (d >>16) & 0xff; + result[4+3] = (d >>24) & 0xff; + result[8+0] = (c >> 0) & 0xff; + result[8+1] = (c >> 8) & 0xff; + result[8+2] = (c >>16) & 0xff; + result[8+3] = (c >>24) & 0xff; + return std::string(result, result + 12); + } +}; + + +static cpuid_result cpuid(uint32 function) +//---------------------------------------- +{ + cpuid_result result; + int CPUInfo[4]; + __cpuid(CPUInfo, function); + result.a = CPUInfo[0]; + result.b = CPUInfo[1]; + result.c = CPUInfo[2]; + result.d = CPUInfo[3]; + return result; +} + + +static bool has_cpuid() +//--------------------- +{ + const uint32 eflags_cpuid = 1<<21; + uint32 old_eflags = __readeflags(); + __writeeflags(old_eflags ^ eflags_cpuid); + bool result = ((__readeflags() ^ old_eflags) & eflags_cpuid) ? true : false; + __writeeflags(old_eflags); + return result; +} + + +void InitProcSupport() +//-------------------- +{ + + ProcSupport = 0; + + if(has_cpuid()) + { + + cpuid_result VendorString = cpuid(0x00000000u); + + cpuid_result StandardFeatureFlags = cpuid(0x00000001u); + if(StandardFeatureFlags.d & (1<<23)) ProcSupport |= PROCSUPPORT_MMX; + if(StandardFeatureFlags.d & (1<<25)) ProcSupport |= PROCSUPPORT_SSE; + if(StandardFeatureFlags.d & (1<<26)) ProcSupport |= PROCSUPPORT_SSE2; + if(StandardFeatureFlags.c & (1<< 0)) ProcSupport |= PROCSUPPORT_SSE3; + + if(VendorString.as_string() == "AuthenticAMD") + { + + cpuid_result ExtendedVendorString = cpuid(0x80000000u); + if(ExtendedVendorString.a >= 0x80000001u) + { + + cpuid_result ExtendedFeatureFlags = cpuid(0x80000001u); + if(ExtendedFeatureFlags.d & (1<<22)) ProcSupport |= PROCSUPPORT_AMD_MMXEXT; + if(ExtendedFeatureFlags.d & (1<<31)) ProcSupport |= PROCSUPPORT_AMD_3DNOW; + if(ExtendedFeatureFlags.d & (1<<30)) ProcSupport |= PROCSUPPORT_AMD_3DNOW2; + + } + + } + + } + +} + + +#else // !( MPT_COMPILER_MSVC && ENABLE_X86 ) + + +void InitProcSupport() +//-------------------- +{ + ProcSupport = 0; +} + + +#endif // MPT_COMPILER_MSVC && ENABLE_X86 + + +#endif // ENABLE_ASM + Modified: trunk/OpenMPT/common/misc_util.h =================================================================== --- trunk/OpenMPT/common/misc_util.h 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/common/misc_util.h 2013-06-07 00:18:17 UTC (rev 2311) @@ -441,3 +441,21 @@ }; } // namespace Util + + +#ifdef ENABLE_ASM +#define PROCSUPPORT_MMX 0x00001 // Processor supports MMX instructions +#define PROCSUPPORT_SSE 0x00010 // Processor supports SSE instructions +#define PROCSUPPORT_SSE2 0x00020 // Processor supports SSE2 instructions +#define PROCSUPPORT_SSE3 0x00040 // Processor supports SSE3 instructions +#define PROCSUPPORT_AMD_MMXEXT 0x10000 // Processor supports AMD MMX extensions +#define PROCSUPPORT_AMD_3DNOW 0x20000 // Processor supports AMD 3DNow! instructions +#define PROCSUPPORT_AMD_3DNOW2 0x40000 // Processor supports AMD 3DNow!2 instructions +extern uint32 ProcSupport; +void InitProcSupport(); +static inline uint32 GetProcSupport() +{ + return ProcSupport; +} +#endif // ENABLE_ASM + Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2013-06-07 00:18:17 UTC (rev 2311) @@ -874,7 +874,7 @@ { TrackerSettings::Instance().m_ResamplerSettings.SrcMode = SRCMODE_SPLINE; } - if(GetProcSupport() & PROCSUPPORT_MMXEX) + if(GetProcSupport() & PROCSUPPORT_SSE) { TrackerSettings::Instance().m_ResamplerSettings.SrcMode = SRCMODE_POLYPHASE; } Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2013-06-07 00:18:17 UTC (rev 2311) @@ -521,10 +521,10 @@ } -#ifdef ENABLE_MMX +#if defined(ENABLE_X86_AMD) || defined(ENABLE_SSE) -static void mmxex_findminmax16(void *p, int scanlen, int smplsize, int *smin, int *smax) -//-------------------------------------------------------------------------------------- +static void amdmmxext_or_sse_findminmax16(void *p, int scanlen, int smplsize, int *smin, int *smax) +//------------------------------------------------------------------------------------------------- { _asm { mov ebx, p @@ -585,8 +585,8 @@ } -static void mmxex_findminmax8(void *p, int scanlen, int smplsize, int *smin, int *smax) -//------------------------------------------------------------------------------------- +static void amdmmxext_or_sse_findminmax8(void *p, int scanlen, int smplsize, int *smin, int *smax) +//------------------------------------------------------------------------------------------------ { _asm { mov ebx, p @@ -715,10 +715,10 @@ signed short *p = (signed short *)(psample + poshi*smplsize); smin = 32767; smax = -32768; -#ifdef ENABLE_MMX - if(GetProcSupport() & PROCSUPPORT_MMXEX) +#if defined(ENABLE_X86_AMD) || defined(ENABLE_SSE) + if(GetProcSupport() & (PROCSUPPORT_AMD_MMXEXT|PROCSUPPORT_SSE)) { - mmxex_findminmax16(p, scanlen, smplsize, &smin, &smax); + amdmmxext_or_sse_findminmax16(p, scanlen, smplsize, &smin, &smax); } else #endif { @@ -738,10 +738,10 @@ signed char *p = psample + poshi * smplsize; smin = 127; smax = -128; -#ifdef ENABLE_MMX - if(GetProcSupport() & PROCSUPPORT_MMXEX) +#if defined(ENABLE_X86_AMD) || defined(ENABLE_SSE) + if(GetProcSupport() & (PROCSUPPORT_AMD_MMXEXT|PROCSUPPORT_SSE)) { - mmxex_findminmax8(p, scanlen, smplsize, &smin, &smax); + amdmmxext_or_sse_findminmax8(p, scanlen, smplsize, &smin, &smax); } else #endif { Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2013-06-07 00:18:17 UTC (rev 2311) @@ -3413,7 +3413,6 @@ return; } -#ifdef ENABLE_MMX #ifdef ENABLE_SSE if(GetProcSupport() & PROCSUPPORT_SSE) { @@ -3422,7 +3421,6 @@ SSEDeinterleaveInt16ToFloat(outputs[0], outputs[1], samples); } else #endif // ENABLE_SSE -#endif // ENABLE_MMX { InterleaveFloatToInt16(inputs[0], inputs[1], samples); m_pMediaProcess->Process(samples * 2 * sizeof(int16), reinterpret_cast<BYTE *>(m_pMixBuffer), m_DataTime, DMO_INPLACE_NORMAL); Modified: trunk/OpenMPT/sounddsp/EQ.cpp =================================================================== --- trunk/OpenMPT/sounddsp/EQ.cpp 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/sounddsp/EQ.cpp 2013-06-07 00:18:17 UTC (rev 2311) @@ -109,10 +109,11 @@ } +#ifdef ENABLE_X86_AMD + static void AMD_StereoEQ(EQBANDSTRUCT *pbl, EQBANDSTRUCT *pbr, float32 *pbuffer, UINT nCount) //------------------------------------------------------------------------------------------- { -#ifdef ENABLE_3DNOW float tmp[16]; _asm { @@ -189,14 +190,16 @@ movd [edx+EQBANDSTRUCT.y2], mm7 emms } -#endif } +#endif // ENABLE_X86_AMD + +#ifdef ENABLE_SSE + static void SSE_StereoEQ(EQBANDSTRUCT *pbl, EQBANDSTRUCT *pbr, float32 *pbuffer, UINT nCount) //------------------------------------------------------------------------------------------- { -#ifdef ENABLE_SSE static const float gk1 = 1.0f; _asm { mov eax, pbl @@ -284,9 +287,10 @@ movss [edx+EQBANDSTRUCT.y2], xmm1 done:; } -#endif // ENABLE_SSE } +#endif // ENABLE_SSE + #pragma warning(default:4100) #else @@ -326,7 +330,6 @@ { #ifdef ENABLE_SSE -#ifdef ENABLE_MMX if(GetProcSupport() & PROCSUPPORT_SSE) { @@ -347,12 +350,11 @@ } else -#endif // ENABLE_MMX #endif // ENABLE_SSE -#ifdef ENABLE_3DNOW +#ifdef ENABLE_X86_AMD - if(GetProcSupport() & PROCSUPPORT_3DNOW) + if(GetProcSupport() & PROCSUPPORT_AMD_3DNOW) { MonoMixToFloat(pbuffer, MixFloatBuffer, nCount*2, 1.0f/static_cast<float>(MIXING_CLIPMAX)); @@ -366,7 +368,7 @@ FloatToMonoMix(MixFloatBuffer, pbuffer, nCount*2, static_cast<float>(MIXING_CLIPMAX)); } else -#endif // ENABLE_3DNOW +#endif // ENABLE_X86_AMD { @@ -390,10 +392,10 @@ CEQ::CEQ() //-------- { - #if defined(ENABLE_MMX) || defined(ENABLE_SSE) + #if defined(ENABLE_SSE) || defined(ENABLE_X86_AMD) ALWAYS_ASSERT(((uintptr_t)&(gEQ[0])) % 4 == 0); ALWAYS_ASSERT(((uintptr_t)&(gEQ[1])) % 4 == 0); - #endif + #endif // ENABLE_SSE || ENABLE_X86_AMD memcpy(gEQ, gEQDefaults, sizeof(gEQ)); } Modified: trunk/OpenMPT/soundlib/Mmx_mix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Mmx_mix.cpp 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/soundlib/Mmx_mix.cpp 2013-06-07 00:18:17 UTC (rev 2311) @@ -24,75 +24,10 @@ #include "Sndfile.h" -#ifdef ENABLE_ASM - -static uint32 gdwSysInfo = 0; - -void InitProcSupport() -//-------------------- -{ -#ifdef ENABLE_X86 - static unsigned int fProcessorExtensions = 0; - _asm - { - pushfd // Store original EFLAGS on stack - pop eax // Get original EFLAGS in EAX - mov ecx, eax // Duplicate original EFLAGS in ECX for toggle check - xor eax, 0x00200000L // Flip ID bit in EFLAGS - push eax // Save new EFLAGS value on stack - popfd // Replace current EFLAGS value - pushfd // Store new EFLAGS on stack - pop eax // Get new EFLAGS in EAX - xor eax, ecx // Can we toggle ID bit? - jz Done // Jump if no, Processor is older than a Pentium so CPU_ID is not supported - mov fProcessorExtensions, PROCSUPPORT_CPUID - mov eax, 1 // Set EAX to tell the CPUID instruction what to return - push ebx - cpuid // Get family/model/stepping/features - pop ebx - test edx, 0x00800000L // Check if mmx technology available - jz Done // Jump if no - // Tests have passed, this machine supports the Intel MultiMedia Instruction Set! - or fProcessorExtensions, PROCSUPPORT_MMX - // Check for SSE: PROCSUPPORT_SSE - test edx, 0x02000000L // check if SSE is present (bit 25) - jz nosse // done if no - // else set the correct bit in fProcessorExtensions - or fProcessorExtensions, (PROCSUPPORT_MMXEX|PROCSUPPORT_SSE) - jmp Done - nosse: - // Check for AMD 3DNow! - mov eax, 0x80000000 - cpuid - cmp eax, 0x80000000 - jbe Done - mov eax, 0x80000001 - cpuid // CPU_ID - test edx, 0x80000000 - jz Done - or fProcessorExtensions, PROCSUPPORT_3DNOW // 3DNow! supported - test edx, (1<<22) // Bit 22: AMD MMX extensions - jz Done - or fProcessorExtensions, PROCSUPPORT_MMXEX // MMX extensions supported - Done: - } - gdwSysInfo = fProcessorExtensions; -#endif -} - -uint32 GetProcSupport() -//--------------------- -{ - return gdwSysInfo; -} - -#endif - - //////////////////////////////////////////////////////////////////////////////////// // 3DNow! optimizations -#ifdef ENABLE_3DNOW +#ifdef ENABLE_X86_AMD // Convert integer mix to floating-point static void AMD_StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount, const float _i2fc) @@ -222,7 +157,7 @@ } } -#endif +#endif // ENABLE_X86_AMD /////////////////////////////////////////////////////////////////////////////////////// // SSE Optimizations @@ -442,19 +377,19 @@ { #ifdef ENABLE_SSE - if(gdwSysInfo & PROCSUPPORT_SSE) + if(GetProcSupport() & PROCSUPPORT_SSE) { SSE_StereoMixToFloat(pSrc, pOut1, pOut2, nCount, _i2fc); return; } #endif // ENABLE_SSE - #ifdef ENABLE_3DNOW - if(gdwSysInfo & PROCSUPPORT_3DNOW) + #ifdef ENABLE_X86_AMD + if(GetProcSupport() & PROCSUPPORT_AMD_3DNOW) { AMD_StereoMixToFloat(pSrc, pOut1, pOut2, nCount, _i2fc); return; } - #endif // ENABLE_3DNOW + #endif // ENABLE_X86_AMD #ifdef ENABLE_X86 X86_StereoMixToFloat(pSrc, pOut1, pOut2, nCount, _i2fc); @@ -468,13 +403,13 @@ void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount, const float _f2ic) { - #ifdef ENABLE_3DNOW - if(gdwSysInfo & PROCSUPPORT_3DNOW) + #ifdef ENABLE_X86_AMD + if(GetProcSupport() & PROCSUPPORT_AMD_3DNOW) { AMD_FloatToStereoMix(pIn1, pIn2, pOut, nCount, _f2ic); return; } - #endif // ENABLE_3DNOW + #endif // ENABLE_X86_AMD #ifdef ENABLE_X86 X86_FloatToStereoMix(pIn1, pIn2, pOut, nCount, _f2ic); @@ -489,19 +424,19 @@ { #ifdef ENABLE_SSE - if(gdwSysInfo & PROCSUPPORT_SSE) + if(GetProcSupport() & PROCSUPPORT_SSE) { SSE_MonoMixToFloat(pSrc, pOut, nCount, _i2fc); return; } #endif // ENABLE_SSE - #ifdef ENABLE_3DNOW - if(gdwSysInfo & PROCSUPPORT_3DNOW) + #ifdef ENABLE_X86_AMD + if(GetProcSupport() & PROCSUPPORT_AMD_3DNOW) { AMD_MonoMixToFloat(pSrc, pOut, nCount, _i2fc); return; } - #endif // ENABLE_3DNOW + #endif // ENABLE_X86_AMD #ifdef ENABLE_X86 X86_MonoMixToFloat(pSrc, pOut, nCount, _i2fc); @@ -515,13 +450,13 @@ void FloatToMonoMix(const float *pIn, int *pOut, UINT nCount, const float _f2ic) { - #ifdef ENABLE_3DNOW - if(gdwSysInfo & PROCSUPPORT_3DNOW) + #ifdef ENABLE_X86_AMD + if(GetProcSupport() & PROCSUPPORT_AMD_3DNOW) { AMD_FloatToMonoMix(pIn, pOut, nCount, _f2ic); return; } - #endif // ENABLE_3DNOW + #endif // ENABLE_X86_AMD #ifdef ENABLE_X86 X86_FloatToMonoMix(pIn, pOut, nCount, _f2ic); Modified: trunk/OpenMPT/soundlib/Snd_defs.h =================================================================== --- trunk/OpenMPT/soundlib/Snd_defs.h 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/soundlib/Snd_defs.h 2013-06-07 00:18:17 UTC (rev 2311) @@ -242,15 +242,6 @@ #define DNA_NOTEFADE 2 -#ifdef ENABLE_ASM -#define PROCSUPPORT_CPUID 0x01 -#define PROCSUPPORT_MMX 0x02 // Processor supports MMX instructions -#define PROCSUPPORT_MMXEX 0x04 // Processor supports AMD MMX extensions -#define PROCSUPPORT_3DNOW 0x08 // Processor supports AMD 3DNow! instructions -#define PROCSUPPORT_SSE 0x10 // Processor supports SSE instructions -#endif - - // Module flags enum SongFlags { Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2013-06-06 23:16:28 UTC (rev 2310) +++ trunk/OpenMPT/soundlib/Sndfile.h 2013-06-07 00:18:17 UTC (rev 2311) @@ -186,12 +186,6 @@ #endif // MODPLUG_TRACKER -#ifdef ENABLE_ASM -void InitProcSupport(); -uint32 GetProcSupport(); -#endif - - void StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount, const float _i2fc); void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount, const float _f2ic); void MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount, const float _i2fc); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |