u_cpu_detect.c File Reference

Include dependency graph for u_cpu_detect.c:

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_capscpu_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


Function Documentation

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 }


Variable Documentation

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.


Generated on Tue Sep 29 06:25:28 2009 for Gallium3D by  doxygen 1.5.4