📄 cpudetect.c
字号:
*/ sc.fpstate->mxcsr |= 0x00000200; sc.fpstate->mxcsr &= 0xfffffffb; } else { /* If we ever get here, we're completely hosed. */ mp_msg(MSGT_CPUDETECT,MSGL_V, "\n\n" ); mp_msg(MSGT_CPUDETECT,MSGL_V, "SSE enabling test failed badly!" ); }}#endif /* __linux__ && _POSIX_SOURCE && X86_FXSR_MAGIC */#ifdef WIN32LONG CALLBACK win32_sig_handler_sse(EXCEPTION_POINTERS* ep){ if(ep->ExceptionRecord->ExceptionCode==EXCEPTION_ILLEGAL_INSTRUCTION){ mp_msg(MSGT_CPUDETECT,MSGL_V, "SIGILL, " ); ep->ContextRecord->Eip +=3; gCpuCaps.hasSSE=0; return EXCEPTION_CONTINUE_EXECUTION; } return EXCEPTION_CONTINUE_SEARCH;}#endif /* WIN32 *//* If we're running on a processor that can do SSE, let's see if we * are allowed to or not. This will catch 2.4.0 or later kernels that * haven't been configured for a Pentium III but are running on one, * and RedHat patched 2.2 kernels that have broken exception handling * support for user space apps that do SSE. */static void check_os_katmai_support( void ){#ifdef ARCH_X86_64 gCpuCaps.hasSSE=1; gCpuCaps.hasSSE2=1;#elif defined(__FreeBSD__) int has_sse=0, ret; size_t len=sizeof(has_sse); ret = sysctlbyname("hw.instruction_sse", &has_sse, &len, NULL, 0); if (ret || !has_sse) gCpuCaps.hasSSE=0;#elif defined(__NetBSD__) || defined (__OpenBSD__)#if __NetBSD_Version__ >= 105250000 || (defined __OpenBSD__) int has_sse, has_sse2, ret, mib[2]; size_t varlen; mib[0] = CTL_MACHDEP; mib[1] = CPU_SSE; varlen = sizeof(has_sse); mp_msg(MSGT_CPUDETECT,MSGL_V, "Testing OS support for SSE... " ); ret = sysctl(mib, 2, &has_sse, &varlen, NULL, 0); if (ret < 0 || !has_sse) { gCpuCaps.hasSSE=0; mp_msg(MSGT_CPUDETECT,MSGL_V, "no!\n" ); } else { gCpuCaps.hasSSE=1; mp_msg(MSGT_CPUDETECT,MSGL_V, "yes!\n" ); } mib[1] = CPU_SSE2; varlen = sizeof(has_sse2); mp_msg(MSGT_CPUDETECT,MSGL_V, "Testing OS support for SSE2... " ); ret = sysctl(mib, 2, &has_sse2, &varlen, NULL, 0); if (ret < 0 || !has_sse2) { gCpuCaps.hasSSE2=0; mp_msg(MSGT_CPUDETECT,MSGL_V, "no!\n" ); } else { gCpuCaps.hasSSE2=1; mp_msg(MSGT_CPUDETECT,MSGL_V, "yes!\n" ); }#else gCpuCaps.hasSSE = 0; mp_msg(MSGT_CPUDETECT,MSGL_WARN, "No OS support for SSE, disabling to be safe.\n" );#endif#elif defined(WIN32) LPTOP_LEVEL_EXCEPTION_FILTER exc_fil; if ( gCpuCaps.hasSSE ) { mp_msg(MSGT_CPUDETECT,MSGL_V, "Testing OS support for SSE... " ); exc_fil = SetUnhandledExceptionFilter(win32_sig_handler_sse); __asm __volatile ("xorps %xmm0, %xmm0"); SetUnhandledExceptionFilter(exc_fil); if ( gCpuCaps.hasSSE ) mp_msg(MSGT_CPUDETECT,MSGL_V, "yes.\n" ); else mp_msg(MSGT_CPUDETECT,MSGL_V, "no!\n" ); }#elif defined(__linux__)#if defined(_POSIX_SOURCE) && defined(X86_FXSR_MAGIC) struct sigaction saved_sigill; struct sigaction saved_sigfpe; /* Save the original signal handlers. */ sigaction( SIGILL, NULL, &saved_sigill ); sigaction( SIGFPE, NULL, &saved_sigfpe ); signal( SIGILL, (void (*)(int))sigill_handler_sse ); signal( SIGFPE, (void (*)(int))sigfpe_handler_sse ); /* Emulate test for OSFXSR in CR4. The OS will set this bit if it * supports the extended FPU save and restore required for SSE. If * we execute an SSE instruction on a PIII and get a SIGILL, the OS * doesn't support Streaming SIMD Exceptions, even if the processor * does. */ if ( gCpuCaps.hasSSE ) { mp_msg(MSGT_CPUDETECT,MSGL_V, "Testing OS support for SSE... " );// __asm __volatile ("xorps %%xmm0, %%xmm0"); __asm __volatile ("xorps %xmm0, %xmm0"); if ( gCpuCaps.hasSSE ) { mp_msg(MSGT_CPUDETECT,MSGL_V, "yes.\n" ); } else { mp_msg(MSGT_CPUDETECT,MSGL_V, "no!\n" ); } } /* Emulate test for OSXMMEXCPT in CR4. The OS will set this bit if * it supports unmasked SIMD FPU exceptions. If we unmask the * exceptions, do a SIMD divide-by-zero and get a SIGILL, the OS * doesn't support unmasked SIMD FPU exceptions. If we get a SIGFPE * as expected, we're okay but we need to clean up after it. * * Are we being too stringent in our requirement that the OS support * unmasked exceptions? Certain RedHat 2.2 kernels enable SSE by * setting CR4.OSFXSR but don't support unmasked exceptions. Win98 * doesn't even support them. We at least know the user-space SSE * support is good in kernels that do support unmasked exceptions, * and therefore to be safe I'm going to leave this test in here. */ if ( gCpuCaps.hasSSE ) { mp_msg(MSGT_CPUDETECT,MSGL_V, "Testing OS support for SSE unmasked exceptions... " );// test_os_katmai_exception_support(); if ( gCpuCaps.hasSSE ) { mp_msg(MSGT_CPUDETECT,MSGL_V, "yes.\n" ); } else { mp_msg(MSGT_CPUDETECT,MSGL_V, "no!\n" ); } } /* Restore the original signal handlers. */ sigaction( SIGILL, &saved_sigill, NULL ); sigaction( SIGFPE, &saved_sigfpe, NULL ); /* If we've gotten to here and the XMM CPUID bit is still set, we're * safe to go ahead and hook out the SSE code throughout Mesa. */ if ( gCpuCaps.hasSSE ) { mp_msg(MSGT_CPUDETECT,MSGL_V, "Tests of OS support for SSE passed.\n" ); } else { mp_msg(MSGT_CPUDETECT,MSGL_V, "Tests of OS support for SSE failed!\n" ); }#else /* We can't use POSIX signal handling to test the availability of * SSE, so we disable it by default. */ mp_msg(MSGT_CPUDETECT,MSGL_WARN, "Cannot test OS support for SSE, disabling to be safe.\n" ); gCpuCaps.hasSSE=0;#endif /* _POSIX_SOURCE && X86_FXSR_MAGIC */#else /* Do nothing on other platforms for now. */ mp_msg(MSGT_CPUDETECT,MSGL_WARN, "Cannot test OS support for SSE, leaving disabled.\n" ); gCpuCaps.hasSSE=0;#endif /* __linux__ */}#else /* ARCH_X86 || ARCH_X86_64 */#ifdef SYS_DARWIN#include <sys/sysctl.h>#else#include <signal.h>#include <setjmp.h>static sigjmp_buf jmpbuf;static volatile sig_atomic_t canjump = 0;static void sigill_handler (int sig){ if (!canjump) { signal (sig, SIG_DFL); raise (sig); } canjump = 0; siglongjmp (jmpbuf, 1);}#endifvoid GetCpuCaps( CpuCaps *caps){ caps->cpuType=0; caps->cpuStepping=0; caps->hasMMX=0; caps->hasMMX2=0; caps->has3DNow=0; caps->has3DNowExt=0; caps->hasSSE=0; caps->hasSSE2=0; caps->isX86=0; caps->hasAltiVec = 0;#ifdef HAVE_ALTIVEC #ifdef SYS_DARWIN /* rip-off from ffmpeg altivec detection code. this code also appears on Apple's AltiVec pages. */ { int sels[2] = {CTL_HW, HW_VECTORUNIT}; int has_vu = 0; size_t len = sizeof(has_vu); int err; err = sysctl(sels, 2, &has_vu, &len, NULL, 0); if (err == 0) if (has_vu != 0) caps->hasAltiVec = 1; }#else /* SYS_DARWIN *//* no Darwin, do it the brute-force way *//* this is borrowed from the libmpeg2 library */ { signal (SIGILL, sigill_handler); if (sigsetjmp (jmpbuf, 1)) { signal (SIGILL, SIG_DFL); } else { canjump = 1; asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0" : : "r" (-1)); signal (SIGILL, SIG_DFL); caps->hasAltiVec = 1; } }#endif /* SYS_DARWIN */ mp_msg(MSGT_CPUDETECT,MSGL_INFO,"AltiVec %sfound\n", (caps->hasAltiVec ? "" : "not "));#endif /* HAVE_ALTIVEC */#ifdef ARCH_IA64 mp_msg(MSGT_CPUDETECT,MSGL_INFO,"CPU: Intel Itanium\n");#endif#ifdef ARCH_SPARC mp_msg(MSGT_CPUDETECT,MSGL_INFO,"CPU: Sun Sparc\n");#endif#ifdef ARCH_ARMV4L mp_msg(MSGT_CPUDETECT,MSGL_INFO,"CPU: ARM\n");#endif#ifdef ARCH_POWERPC mp_msg(MSGT_CPUDETECT,MSGL_INFO,"CPU: PowerPC\n");#endif#ifdef ARCH_ALPHA mp_msg(MSGT_CPUDETECT,MSGL_INFO,"CPU: Digital Alpha\n");#endif#ifdef ARCH_SGI_MIPS mp_msg(MSGT_CPUDETECT,MSGL_INFO,"CPU: SGI MIPS\n");#endif#ifdef ARCH_PA_RISC mp_msg(MSGT_CPUDETECT,MSGL_INFO,"CPU: Hewlett-Packard PA-RISC\n");#endif#ifdef ARCH_S390 mp_msg(MSGT_CPUDETECT,MSGL_INFO,"CPU: IBM S/390\n");#endif#ifdef ARCH_S390X mp_msg(MSGT_CPUDETECT,MSGL_INFO,"CPU: IBM S/390X\n");#endif#ifdef ARCH_VAX mp_msg(MSGT_CPUDETECT,MSGL_INFO, "CPU: Digital VAX\n" );#endif}#endif /* !ARCH_X86 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -