|
|
@@ -194,123 +194,8 @@ check_os_altivec_support(void) |
|
|
|
} |
|
|
|
#endif /* PIPE_ARCH_PPC */ |
|
|
|
|
|
|
|
/* 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. |
|
|
|
*/ |
|
|
|
#if defined(PIPE_ARCH_X86) || defined (PIPE_ARCH_X86_64) |
|
|
|
static void |
|
|
|
check_os_katmai_support(void) |
|
|
|
{ |
|
|
|
#if defined(PIPE_ARCH_X86) |
|
|
|
#if defined(PIPE_OS_FREEBSD) |
|
|
|
int has_sse=0, ret; |
|
|
|
int len = sizeof (has_sse); |
|
|
|
|
|
|
|
ret = sysctlbyname("hw.instruction_sse", &has_sse, &len, NULL, 0); |
|
|
|
if (ret || !has_sse) |
|
|
|
util_cpu_caps.has_sse=0; |
|
|
|
|
|
|
|
#elif defined(PIPE_OS_NETBSD) || defined(PIPE_OS_OPENBSD) |
|
|
|
int has_sse, has_sse2, ret, mib[2]; |
|
|
|
int varlen; |
|
|
|
|
|
|
|
mib[0] = CTL_MACHDEP; |
|
|
|
mib[1] = CPU_SSE; |
|
|
|
varlen = sizeof (has_sse); |
|
|
|
|
|
|
|
ret = sysctl(mib, 2, &has_sse, &varlen, NULL, 0); |
|
|
|
if (ret < 0 || !has_sse) { |
|
|
|
util_cpu_caps.has_sse = 0; |
|
|
|
} else { |
|
|
|
util_cpu_caps.has_sse = 1; |
|
|
|
} |
|
|
|
|
|
|
|
mib[1] = CPU_SSE2; |
|
|
|
varlen = sizeof (has_sse2); |
|
|
|
ret = sysctl(mib, 2, &has_sse2, &varlen, NULL, 0); |
|
|
|
if (ret < 0 || !has_sse2) { |
|
|
|
util_cpu_caps.has_sse2 = 0; |
|
|
|
} else { |
|
|
|
util_cpu_caps.has_sse2 = 1; |
|
|
|
} |
|
|
|
util_cpu_caps.has_sse = 0; /* FIXME ?!?!? */ |
|
|
|
|
|
|
|
#elif defined(PIPE_OS_WINDOWS) |
|
|
|
LPTOP_LEVEL_EXCEPTION_FILTER exc_fil; |
|
|
|
if (util_cpu_caps.has_sse) { |
|
|
|
exc_fil = SetUnhandledExceptionFilter(win32_sig_handler_sse); |
|
|
|
#if defined(PIPE_CC_GCC) |
|
|
|
__asm __volatile ("xorps %xmm0, %xmm0"); |
|
|
|
#elif defined(PIPE_CC_MSVC) |
|
|
|
__asm { |
|
|
|
xorps xmm0, xmm0 /* executing SSE instruction */ |
|
|
|
} |
|
|
|
#else |
|
|
|
#error Unsupported compiler |
|
|
|
#endif |
|
|
|
SetUnhandledExceptionFilter(exc_fil); |
|
|
|
} |
|
|
|
#elif defined(PIPE_OS_LINUX) |
|
|
|
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 (util_cpu_caps.has_sse) { |
|
|
|
__asm __volatile ("xorps %xmm1, %xmm0"); |
|
|
|
} |
|
|
|
|
|
|
|
/* 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 (util_cpu_caps.has_sse) { |
|
|
|
/* test_os_katmai_exception_support(); */ |
|
|
|
} |
|
|
|
|
|
|
|
/* Restore the original signal handlers. |
|
|
|
*/ |
|
|
|
sigaction(SIGILL, &saved_sigill, NULL); |
|
|
|
sigaction(SIGFPE, &saved_sigfpe, NULL); |
|
|
|
|
|
|
|
#else |
|
|
|
/* We can't use POSIX signal handling to test the availability of |
|
|
|
* SSE, so we disable it by default. |
|
|
|
*/ |
|
|
|
util_cpu_caps.has_sse = 0; |
|
|
|
#endif /* __linux__ */ |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined(PIPE_ARCH_X86_64) |
|
|
|
util_cpu_caps.has_sse = 1; |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if defined(PIPE_ARCH_X86) || defined (PIPE_ARCH_X86_64) |
|
|
|
static int has_cpuid(void) |
|
|
|
{ |
|
|
|
#if defined(PIPE_ARCH_X86) |
|
|
@@ -469,9 +354,6 @@ util_cpu_detect(void) |
|
|
|
util_cpu_caps.cacheline = regs2[2] & 0xFF; |
|
|
|
} |
|
|
|
|
|
|
|
if (util_cpu_caps.has_sse) |
|
|
|
check_os_katmai_support(); |
|
|
|
|
|
|
|
if (!util_cpu_caps.has_sse) { |
|
|
|
util_cpu_caps.has_sse2 = 0; |
|
|
|
util_cpu_caps.has_sse3 = 0; |