home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / system / source / cpuaccel.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  6.0 KB  |  251 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #include "stdafx.h"
  27. #include <wtypes.h>
  28. #include <winnt.h>
  29. #include <intrin.h>
  30. #include <vd2/system/cpuaccel.h>
  31.  
  32. static long g_lCPUExtensionsEnabled;
  33. static long g_lCPUExtensionsAvailable;
  34.  
  35. extern "C" {
  36.     bool FPU_enabled, MMX_enabled, SSE_enabled, ISSE_enabled, SSE2_enabled;
  37. };
  38.  
  39.  
  40. #ifdef _M_AMD64
  41.  
  42.     long CPUCheckForExtensions() {
  43.         long flags = CPUF_SUPPORTS_FPU;
  44.  
  45.         // This code used to use IsProcessorFeaturePresent(), but this function is somewhat
  46.         // suboptimal in Win64 -- for one thing, it doesn't return true for MMX, at least
  47.         // on Vista 64.
  48.  
  49.         // check for SSE3, SSSE3, SSE4.1
  50.         int cpuInfo[4];
  51.         __cpuid(cpuInfo, 1);
  52.  
  53.         if (cpuInfo[3] & (1 << 23))
  54.             flags |= CPUF_SUPPORTS_MMX;
  55.  
  56.         if (cpuInfo[3] & (1 << 25))
  57.             flags |= CPUF_SUPPORTS_SSE | CPUF_SUPPORTS_INTEGER_SSE;
  58.  
  59.         if (cpuInfo[3] & (1 << 26))
  60.             flags |= CPUF_SUPPORTS_SSE2;
  61.  
  62.         if (cpuInfo[2] & 0x00000001)
  63.             flags |= CPUF_SUPPORTS_SSE3;
  64.  
  65.         if (cpuInfo[2] & 0x00000200)
  66.             flags |= CPUF_SUPPORTS_SSSE3;
  67.  
  68.         if (cpuInfo[2] & 0x00080000)
  69.             flags |= CPUF_SUPPORTS_SSE41;
  70.  
  71.         // check for 3DNow!, 3DNow! extensions
  72.         __cpuid(cpuInfo, 0x80000000);
  73.         if (cpuInfo[0] >= 0x80000001) {
  74.             __cpuid(cpuInfo, 0x80000001);
  75.  
  76.             if (cpuInfo[3] & (1 << 31))
  77.                 flags |= CPUF_SUPPORTS_3DNOW;
  78.  
  79.             if (cpuInfo[3] & (1 << 30))
  80.                 flags |= CPUF_SUPPORTS_3DNOW_EXT;
  81.  
  82.             if (cpuInfo[3] & (1 << 22))
  83.                 flags |= CPUF_SUPPORTS_INTEGER_SSE;
  84.         }
  85.  
  86.         return flags;
  87.     }
  88.  
  89. #else
  90.  
  91.     // This is ridiculous.
  92.  
  93.     static long CPUCheckForSSESupport() {
  94.         __try {
  95.     //        __asm andps xmm0,xmm0
  96.  
  97.             __asm _emit 0x0f
  98.             __asm _emit 0x54
  99.             __asm _emit 0xc0
  100.  
  101.         } __except(EXCEPTION_EXECUTE_HANDLER) {
  102.             if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
  103.                 g_lCPUExtensionsAvailable &= ~(CPUF_SUPPORTS_SSE|CPUF_SUPPORTS_SSE2|CPUF_SUPPORTS_SSE3|CPUF_SUPPORTS_SSSE3);
  104.         }
  105.  
  106.         return g_lCPUExtensionsAvailable;
  107.     }
  108.  
  109.     long __declspec(naked) CPUCheckForExtensions() {
  110.         __asm {
  111.             push    ebp
  112.             push    edi
  113.             push    esi
  114.             push    ebx
  115.  
  116.             xor        ebp,ebp            ;cpu flags - if we don't have CPUID, we probably
  117.                                     ;won't want to try FPU optimizations.
  118.  
  119.             ;check for CPUID.
  120.  
  121.             pushfd                    ;flags -> EAX
  122.             pop        eax
  123.             or        eax,00200000h    ;set the ID bit
  124.             push    eax                ;EAX -> flags
  125.             popfd
  126.             pushfd                    ;flags -> EAX
  127.             pop        eax
  128.             and        eax,00200000h    ;ID bit set?
  129.             jz        done            ;nope...
  130.  
  131.             ;CPUID exists, check for features register.
  132.  
  133.             mov        ebp,00000003h
  134.             xor        eax,eax
  135.             cpuid
  136.             or        eax,eax
  137.             jz        done            ;no features register?!?
  138.  
  139.             ;features register exists, look for MMX, SSE, SSE2.
  140.  
  141.             mov        eax,1
  142.             cpuid
  143.             mov        ebx,edx
  144.             and        ebx,00800000h    ;MMX is bit 23 of EDX
  145.             shr        ebx,21
  146.             or        ebp,ebx            ;set bit 2 if MMX exists
  147.  
  148.             mov        ebx,edx
  149.             and        edx,02000000h    ;SSE is bit 25 of EDX
  150.             shr        edx,25
  151.             neg        edx
  152.             and        edx,00000018h    ;set bits 3 and 4 if SSE exists
  153.             or        ebp,edx
  154.  
  155.             and        ebx,04000000h    ;SSE2 is bit 26 of EDX
  156.             shr        ebx,21
  157.             and        ebx,00000020h    ;set bit 5
  158.             or        ebp,ebx
  159.  
  160.             test    ecx, 1            ;SSE3 is bit 0 of ECX
  161.             jz        no_sse3
  162.             or        ebp, 100h
  163. no_sse3:
  164.  
  165.             test    ecx, 200h        ;SSSE3 is bit 9 of ECX
  166.             jz        no_ssse3
  167.             or        ebp, 200h
  168. no_ssse3:
  169.  
  170.             test    ecx, 80000h        ;SSE4_1 is bit 19 of ECX
  171.             jz        no_sse4_1
  172.             or        ebp, 400h
  173. no_sse4_1:
  174.  
  175.             ;check for vendor feature register (K6/Athlon).
  176.  
  177.             mov        eax,80000000h
  178.             cpuid
  179.             mov        ecx,80000001h
  180.             cmp        eax,ecx
  181.             jb        done
  182.  
  183.             ;vendor feature register exists, look for 3DNow! and Athlon extensions
  184.  
  185.             mov        eax,ecx
  186.             cpuid
  187.  
  188.             mov        eax,edx
  189.             and        edx,80000000h    ;3DNow! is bit 31
  190.             shr        edx,25
  191.             or        ebp,edx            ;set bit 6
  192.  
  193.             mov        edx,eax
  194.             and        eax,40000000h    ;3DNow!2 is bit 30
  195.             shr        eax,23
  196.             or        ebp,eax            ;set bit 7
  197.  
  198.             and        edx,00400000h    ;AMD MMX extensions (integer SSE) is bit 22
  199.             shr        edx,19
  200.             or        ebp,edx
  201.  
  202.     done:
  203.             mov        eax,ebp
  204.             mov        g_lCPUExtensionsAvailable, ebp
  205.  
  206.             ;Full SSE and SSE-2 require OS support for the xmm* registers.
  207.  
  208.             test    eax,00000030h
  209.             jz        nocheck
  210.             call    CPUCheckForSSESupport
  211.     nocheck:
  212.             pop        ebx
  213.             pop        esi
  214.             pop        edi
  215.             pop        ebp
  216.             ret
  217.         }
  218.     }
  219.  
  220. #endif
  221.  
  222. long CPUEnableExtensions(long lEnableFlags) {
  223.     g_lCPUExtensionsEnabled = lEnableFlags;
  224.  
  225.     MMX_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_MMX);
  226.     FPU_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_FPU);
  227.     SSE_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_SSE);
  228.     ISSE_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_INTEGER_SSE);
  229.     SSE2_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_SSE2);
  230.  
  231.     return g_lCPUExtensionsEnabled;
  232. }
  233.  
  234. long CPUGetAvailableExtensions() {
  235.     return g_lCPUExtensionsAvailable;
  236. }
  237.  
  238. long CPUGetEnabledExtensions() {
  239.     return g_lCPUExtensionsEnabled;
  240. }
  241.  
  242. void VDCPUCleanupExtensions() {
  243. #ifndef _M_AMD64
  244.     if (ISSE_enabled)
  245.         __asm sfence
  246.     if (MMX_enabled)
  247.         __asm emms
  248. #else
  249.     _mm_sfence();
  250. #endif
  251. }