Go to the source code of this file.
Functions | |
static int | has_cpuid (void) |
static int | cpuid (unsigned int ax, unsigned int *p) |
static void | check_os_katmai_support (void) |
void | cpu_detect_initialize () |
struct cpu_detect_caps * | cpu_detect_get_caps () |
int | cpu_detect_get_tsc () |
int | cpu_detect_get_mmx () |
int | cpu_detect_get_mmx2 () |
int | cpu_detect_get_sse () |
int | cpu_detect_get_sse2 () |
int | cpu_detect_get_sse3 () |
int | cpu_detect_get_ssse3 () |
int | cpu_detect_get_3dnow () |
int | cpu_detect_get_3dnow2 () |
int | cpu_detect_get_altivec () |
Variables | |
static struct cpu_detect_caps | __cpu_detect_caps |
static int | __cpu_detect_initialized = 0 |
static void check_os_katmai_support | ( | void | ) | [static] |
Definition at line 192 of file u_cpu_detect.c.
References __cpu_detect_caps, cpu_detect_caps::hasSSE, and cpu_detect_caps::hasSSE2.
00193 { 00194 #if defined(ARCH_X86) 00195 #if defined(OS_FREEBSD) 00196 int has_sse=0, ret; 00197 int len = sizeof (has_sse); 00198 00199 ret = sysctlbyname("hw.instruction_sse", &has_sse, &len, NULL, 0); 00200 if (ret || !has_sse) 00201 __cpu_detect_caps.hasSSE=0; 00202 00203 #elif defined(OS_NETBSD) || defined(OS_OPENBSD) 00204 int has_sse, has_sse2, ret, mib[2]; 00205 int varlen; 00206 00207 mib[0] = CTL_MACHDEP; 00208 mib[1] = CPU_SSE; 00209 varlen = sizeof (has_sse); 00210 00211 ret = sysctl(mib, 2, &has_sse, &varlen, NULL, 0); 00212 if (ret < 0 || !has_sse) { 00213 __cpu_detect_caps.hasSSE = 0; 00214 } else { 00215 __cpu_detect_caps.hasSSE = 1; 00216 } 00217 00218 mib[1] = CPU_SSE2; 00219 varlen = sizeof (has_sse2); 00220 ret = sysctl(mib, 2, &has_sse2, &varlen, NULL, 0); 00221 if (ret < 0 || !has_sse2) { 00222 __cpu_detect_caps.hasSSE2 = 0; 00223 } else { 00224 __cpu_detect_caps.hasSSE2 = 1; 00225 } 00226 __cpu_detect_caps.hasSSE = 0; /* FIXME ?!?!? */ 00227 00228 #elif defined(OS_WIN32) 00229 LPTOP_LEVEL_EXCEPTION_FILTER exc_fil; 00230 if (__cpu_detect_caps.hasSSE) { 00231 exc_fil = SetUnhandledExceptionFilter(win32_sig_handler_sse); 00232 __asm __volatile ("xorps %xmm0, %xmm0"); 00233 SetUnhandledExceptionFilter(exc_fil); 00234 } 00235 #elif defined(OS_LINUX) 00236 struct sigaction saved_sigill; 00237 struct sigaction saved_sigfpe; 00238 00239 /* Save the original signal handlers. 00240 */ 00241 sigaction(SIGILL, NULL, &saved_sigill); 00242 sigaction(SIGFPE, NULL, &saved_sigfpe); 00243 00244 signal(SIGILL, (void (*)(int))sigill_handler_sse); 00245 signal(SIGFPE, (void (*)(int))sigfpe_handler_sse); 00246 00247 /* Emulate test for OSFXSR in CR4. The OS will set this bit if it 00248 * supports the extended FPU save and restore required for SSE. If 00249 * we execute an SSE instruction on a PIII and get a SIGILL, the OS 00250 * doesn't support Streaming SIMD Exceptions, even if the processor 00251 * does. 00252 */ 00253 if (__cpu_detect_caps.hasSSE) { 00254 __asm __volatile ("xorps %xmm1, %xmm0"); 00255 } 00256 00257 /* Emulate test for OSXMMEXCPT in CR4. The OS will set this bit if 00258 * it supports unmasked SIMD FPU exceptions. If we unmask the 00259 * exceptions, do a SIMD divide-by-zero and get a SIGILL, the OS 00260 * doesn't support unmasked SIMD FPU exceptions. If we get a SIGFPE 00261 * as expected, we're okay but we need to clean up after it. 00262 * 00263 * Are we being too stringent in our requirement that the OS support 00264 * unmasked exceptions? Certain RedHat 2.2 kernels enable SSE by 00265 * setting CR4.OSFXSR but don't support unmasked exceptions. Win98 00266 * doesn't even support them. We at least know the user-space SSE 00267 * support is good in kernels that do support unmasked exceptions, 00268 * and therefore to be safe I'm going to leave this test in here. 00269 */ 00270 if (__cpu_detect_caps.hasSSE) { 00271 // test_os_katmai_exception_support(); 00272 } 00273 00274 /* Restore the original signal handlers. 00275 */ 00276 sigaction(SIGILL, &saved_sigill, NULL); 00277 sigaction(SIGFPE, &saved_sigfpe, NULL); 00278 00279 #else 00280 /* We can't use POSIX signal handling to test the availability of 00281 * SSE, so we disable it by default. 00282 */ 00283 __cpu_detect_caps.hasSSE = 0; 00284 #endif /* __linux__ */ 00285 #endif 00286 }
int cpu_detect_get_3dnow | ( | void | ) |
Definition at line 492 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::has3DNow.
00493 { 00494 return __cpu_detect_caps.has3DNow; 00495 }
int cpu_detect_get_3dnow2 | ( | void | ) |
Definition at line 497 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::has3DNowExt.
00498 { 00499 return __cpu_detect_caps.has3DNowExt; 00500 }
int cpu_detect_get_altivec | ( | void | ) |
Definition at line 502 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::hasAltiVec.
00503 { 00504 return __cpu_detect_caps.hasAltiVec; 00505 }
struct cpu_detect_caps* cpu_detect_get_caps | ( | void | ) | [read] |
Definition at line 451 of file u_cpu_detect.c.
References __cpu_detect_caps.
00452 { 00453 return &__cpu_detect_caps; 00454 }
int cpu_detect_get_mmx | ( | void | ) |
Definition at line 462 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::hasMMX.
00463 { 00464 return __cpu_detect_caps.hasMMX; 00465 }
int cpu_detect_get_mmx2 | ( | void | ) |
Definition at line 467 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::hasMMX2.
00468 { 00469 return __cpu_detect_caps.hasMMX2; 00470 }
int cpu_detect_get_sse | ( | void | ) |
Definition at line 472 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::hasSSE.
00473 { 00474 return __cpu_detect_caps.hasSSE; 00475 }
int cpu_detect_get_sse2 | ( | void | ) |
Definition at line 477 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::hasSSE2.
00478 { 00479 return __cpu_detect_caps.hasSSE2; 00480 }
int cpu_detect_get_sse3 | ( | void | ) |
Definition at line 482 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::hasSSE3.
00483 { 00484 return __cpu_detect_caps.hasSSE3; 00485 }
int cpu_detect_get_ssse3 | ( | void | ) |
Definition at line 487 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::hasSSSE3.
00488 { 00489 return __cpu_detect_caps.hasSSSE3; 00490 }
int cpu_detect_get_tsc | ( | void | ) |
Definition at line 457 of file u_cpu_detect.c.
References __cpu_detect_caps, and cpu_detect_caps::hasTSC.
00458 { 00459 return __cpu_detect_caps.hasTSC; 00460 }
void cpu_detect_initialize | ( | void | ) |
Definition at line 332 of file u_cpu_detect.c.
References __cpu_detect_caps, __cpu_detect_initialized, cpu_detect_caps::cacheline, check_os_katmai_support(), CPU_DETECT_TYPE_ALPHA, CPU_DETECT_TYPE_MIPS, CPU_DETECT_TYPE_OTHER, CPU_DETECT_TYPE_POWERPC, CPU_DETECT_TYPE_SPARC, CPU_DETECT_TYPE_X86, cpuid(), cpu_detect_caps::has3DNow, cpu_detect_caps::has3DNowExt, has_cpuid(), cpu_detect_caps::hasMMX, cpu_detect_caps::hasMMX2, cpu_detect_caps::hasSSE, cpu_detect_caps::hasSSE2, cpu_detect_caps::hasSSE3, cpu_detect_caps::hasSSSE3, cpu_detect_caps::hasTSC, cpu_detect_caps::nrcpu, cpu_detect_caps::type, and cpu_detect_caps::x86cpuType.
00333 { 00334 unsigned int regs[4]; 00335 unsigned int regs2[4]; 00336 00337 int mib[2], ncpu; 00338 int len; 00339 00340 memset(&__cpu_detect_caps, 0, sizeof (struct cpu_detect_caps)); 00341 00342 /* Check for arch type */ 00343 #if defined(ARCH_MIPS) 00344 __cpu_detect_caps.type = CPU_DETECT_TYPE_MIPS; 00345 #elif defined(ARCH_ALPHA) 00346 __cpu_detect_caps.type = CPU_DETECT_TYPE_ALPHA; 00347 #elif defined(ARCH_SPARC) 00348 __cpu_detect_caps.type = CPU_DETECT_TYPE_SPARC; 00349 #elif defined(ARCH_X86) 00350 __cpu_detect_caps.type = CPU_DETECT_TYPE_X86; 00351 #elif defined(ARCH_POWERPC) 00352 __cpu_detect_caps.type = CPU_DETECT_TYPE_POWERPC; 00353 #else 00354 __cpu_detect_caps.type = CPU_DETECT_TYPE_OTHER; 00355 #endif 00356 00357 /* Count the number of CPUs in system */ 00358 #if !defined(OS_WIN32) && !defined(OS_UNKNOWN) && defined(_SC_NPROCESSORS_ONLN) 00359 __cpu_detect_caps.nrcpu = sysconf(_SC_NPROCESSORS_ONLN); 00360 if (__cpu_detect_caps.nrcpu == -1) 00361 __cpu_detect_caps.nrcpu = 1; 00362 00363 #elif defined(OS_NETBSD) || defined(OS_FREEBSD) || defined(OS_OPENBSD) 00364 00365 mib[0] = CTL_HW; 00366 mib[1] = HW_NCPU; 00367 00368 len = sizeof (ncpu); 00369 sysctl(mib, 2, &ncpu, &len, NULL, 0); 00370 __cpu_detect_caps.nrcpu = ncpu; 00371 00372 #else 00373 __cpu_detect_caps.nrcpu = 1; 00374 #endif 00375 00376 #if defined(ARCH_X86) 00377 /* No cpuid, old 486 or lower */ 00378 if (has_cpuid() == 0) 00379 return; 00380 00381 __cpu_detect_caps.cacheline = 32; 00382 00383 /* Get max cpuid level */ 00384 cpuid(0x00000000, regs); 00385 00386 if (regs[0] >= 0x00000001) { 00387 unsigned int cacheline; 00388 00389 cpuid (0x00000001, regs2); 00390 00391 __cpu_detect_caps.x86cpuType = (regs2[0] >> 8) & 0xf; 00392 if (__cpu_detect_caps.x86cpuType == 0xf) 00393 __cpu_detect_caps.x86cpuType = 8 + ((regs2[0] >> 20) & 255); /* use extended family (P4, IA64) */ 00394 00395 /* general feature flags */ 00396 __cpu_detect_caps.hasTSC = (regs2[3] & (1 << 8 )) >> 8; /* 0x0000010 */ 00397 __cpu_detect_caps.hasMMX = (regs2[3] & (1 << 23 )) >> 23; /* 0x0800000 */ 00398 __cpu_detect_caps.hasSSE = (regs2[3] & (1 << 25 )) >> 25; /* 0x2000000 */ 00399 __cpu_detect_caps.hasSSE2 = (regs2[3] & (1 << 26 )) >> 26; /* 0x4000000 */ 00400 __cpu_detect_caps.hasSSE3 = (regs2[2] & (1)); /* 0x0000001 */ 00401 __cpu_detect_caps.hasSSSE3 = (regs2[2] & (1 << 9 )) >> 9; /* 0x0000020 */ 00402 __cpu_detect_caps.hasMMX2 = __cpu_detect_caps.hasSSE; /* SSE cpus supports mmxext too */ 00403 00404 cacheline = ((regs2[1] >> 8) & 0xFF) * 8; 00405 if (cacheline > 0) 00406 __cpu_detect_caps.cacheline = cacheline; 00407 } 00408 00409 cpuid(0x80000000, regs); 00410 00411 if (regs[0] >= 0x80000001) { 00412 00413 cpuid(0x80000001, regs2); 00414 00415 __cpu_detect_caps.hasMMX |= (regs2[3] & (1 << 23 )) >> 23; /* 0x0800000 */ 00416 __cpu_detect_caps.hasMMX2 |= (regs2[3] & (1 << 22 )) >> 22; /* 0x400000 */ 00417 __cpu_detect_caps.has3DNow = (regs2[3] & (1 << 31 )) >> 31; /* 0x80000000 */ 00418 __cpu_detect_caps.has3DNowExt = (regs2[3] & (1 << 30 )) >> 30; 00419 } 00420 00421 if (regs[0] >= 0x80000006) { 00422 cpuid(0x80000006, regs2); 00423 __cpu_detect_caps.cacheline = regs2[2] & 0xFF; 00424 } 00425 00426 00427 #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_CYGWIN) || defined(OS_OPENBSD) 00428 if (__cpu_detect_caps.hasSSE) 00429 check_os_katmai_support(); 00430 00431 if (!__cpu_detect_caps.hasSSE) { 00432 __cpu_detect_caps.hasSSE2 = 0; 00433 __cpu_detect_caps.hasSSE3 = 0; 00434 __cpu_detect_caps.hasSSSE3 = 0; 00435 } 00436 #else 00437 __cpu_detect_caps.hasSSE = 0; 00438 __cpu_detect_caps.hasSSE2 = 0; 00439 __cpu_detect_caps.hasSSE3 = 0; 00440 __cpu_detect_caps.hasSSSE3 = 0; 00441 #endif 00442 #endif /* ARCH_X86 */ 00443 00444 #if defined(ARCH_POWERPC) 00445 check_os_altivec_support(); 00446 #endif /* ARCH_POWERPC */ 00447 00448 __cpu_detect_initialized = 1; 00449 }
static int cpuid | ( | unsigned int | ax, | |
unsigned int * | p | |||
) | [static] |
Definition at line 313 of file u_cpu_detect.c.
00314 { 00315 #if defined(ARCH_X86) 00316 unsigned int flags; 00317 00318 __asm __volatile 00319 ("movl %%ebx, %%esi\n\t" 00320 "cpuid\n\t" 00321 "xchgl %%ebx, %%esi" 00322 : "=a" (p[0]), "=S" (p[1]), 00323 "=c" (p[2]), "=d" (p[3]) 00324 : "0" (ax)); 00325 00326 return 0; 00327 #else 00328 return -1; 00329 #endif 00330 }
static int has_cpuid | ( | void | ) | [static] |
Definition at line 289 of file u_cpu_detect.c.
00290 { 00291 #if defined(ARCH_X86) 00292 int a, c; 00293 00294 __asm __volatile 00295 ("pushf\n" 00296 "popl %0\n" 00297 "movl %0, %1\n" 00298 "xorl $0x200000, %0\n" 00299 "push %0\n" 00300 "popf\n" 00301 "pushf\n" 00302 "popl %0\n" 00303 : "=a" (a), "=c" (c) 00304 : 00305 : "cc"); 00306 00307 return a != c; 00308 #else 00309 return 0; 00310 #endif 00311 }
struct cpu_detect_caps __cpu_detect_caps [static] |
Definition at line 76 of file u_cpu_detect.c.
int __cpu_detect_initialized = 0 [static] |
Definition at line 77 of file u_cpu_detect.c.