[PATCH 8/8] ntdll: Split up feature detection by architecture

James Eder jimportal at gmail.com
Sat Oct 20 19:40:50 CDT 2012


For x86/x86_64 feature detection becomes unified under the CPUID code. The
old code, which relied on OS specific sysctl and file parsing, goes away.
This results in more complete and consistent feature detection for all x86
based machines.

ARM and PowerPC get their own functions based on the code removed from
fill_cpu_info().  PowerPC support should be unchanged while ARM support is
nicer due to it not trying to detect x86 features.
---
 dlls/ntdll/nt.c | 333 +-------------------------------------------------------
 1 file changed, 1 insertion(+), 332 deletions(-)

diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 31bae2f..fa2a67b 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -1131,339 +1131,8 @@ void fill_cpu_info(void)
     NtCurrentTeb()->Peb->NumberOfProcessors = num;
 
     memset(&cached_sci, 0, sizeof(cached_sci));
-    /* choose sensible defaults ...
-     * FIXME: perhaps overridable with precompiler flags?
-     */
-#ifdef __i386__
-    cached_sci.Architecture     = PROCESSOR_ARCHITECTURE_INTEL;
-    cached_sci.Level		= 5; /* 586 */
-#elif defined(__x86_64__)
-    cached_sci.Architecture     = PROCESSOR_ARCHITECTURE_AMD64;
-#elif defined(__powerpc__)
-    cached_sci.Architecture     = PROCESSOR_ARCHITECTURE_PPC;
-#elif defined(__arm__)
-    cached_sci.Architecture     = PROCESSOR_ARCHITECTURE_ARM;
-#elif defined(__sparc__)
-    cached_sci.Architecture     = PROCESSOR_ARCHITECTURE_SPARC;
-#else
-#error Unknown CPU
-#endif
-    cached_sci.Revision   = 0;
-    cached_sci.Reserved   = 0;
-    cached_sci.FeatureSet = 0x1fff;
-
-    /* Hmm, reasonable processor feature defaults? */
-
-#ifdef linux
-    {
-	char line[200];
-	FILE *f = fopen ("/proc/cpuinfo", "r");
-
-	if (!f)
-		return;
-	while (fgets(line,200,f) != NULL)
-        {
-            char	*s,*value;
-
-            /* NOTE: the ':' is the only character we can rely on */
-            if (!(value = strchr(line,':')))
-                continue;
-
-            /* terminate the valuename */
-            s = value - 1;
-            while ((s >= line) && ((*s == ' ') || (*s == '\t'))) s--;
-            *(s + 1) = '\0';
-
-            /* and strip leading spaces from value */
-            value += 1;
-            while (*value==' ') value++;
-            if ((s = strchr(value,'\n')))
-                *s='\0';
-
-            if (!strcasecmp(line, "model"))
-            {
-                /* First part of Revision */
-                int	x;
-
-                if (sscanf(value, "%d",&x))
-                    cached_sci.Revision = cached_sci.Revision | (x << 8);
-
-                continue;
-            }
+    get_cpuinfo(&cached_sci);
 
-            /* 2.1 and ARM method */
-            if (!strcasecmp(line, "cpu family") || !strcasecmp(line, "CPU architecture"))
-            {
-                if (isdigit(value[0]))
-                {
-                    cached_sci.Level = atoi(value);
-                }
-                continue;
-            }
-            /* old 2.0 method */
-            if (!strcasecmp(line, "cpu"))
-            {
-                if (isdigit(value[0]) && value[1] == '8' && value[2] == '6' && value[3] == 0)
-                {
-                    switch (cached_sci.Level = value[0] - '0')
-                    {
-                    case 3:
-                    case 4:
-                    case 5:
-                    case 6:
-                        break;
-                    default:
-                        FIXME("unknown Linux 2.0 cpu family '%s', please report ! (-> setting to 386)\n", value);
-                        cached_sci.Level = 3;
-                        break;
-                    }
-                }
-                continue;
-            }
-            if (!strcasecmp(line, "stepping"))
-            {
-                /* Second part of Revision */
-                int	x;
-
-                if (sscanf(value, "%d",&x))
-                    cached_sci.Revision = cached_sci.Revision | x;
-                continue;
-            }
-            if (!strcasecmp(line, "fdiv_bug"))
-            {
-                if (!strncasecmp(value, "yes",3))
-                    user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
-                continue;
-            }
-            if (!strcasecmp(line, "fpu"))
-            {
-                if (!strncasecmp(value, "no",2))
-                    user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = TRUE;
-                continue;
-            }
-            if (!strcasecmp(line, "flags") || !strcasecmp(line, "features"))
-            {
-                if (strstr(value, "cx8"))
-                    user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
-                if (strstr(value, "cx16"))
-                    user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE128] = TRUE;
-                if (strstr(value, "mmx"))
-                    user_shared_data->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
-                if (strstr(value, "nx"))
-                    user_shared_data->ProcessorFeatures[PF_NX_ENABLED] = TRUE;
-                if (strstr(value, "tsc"))
-                    user_shared_data->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
-                if (strstr(value, "3dnow"))
-                {
-                    user_shared_data->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = TRUE;
-                    cached_sci.FeatureSet |= CPU_FEATURE_3DNOW;
-                }
-                /* This will also catch sse2, but we have sse itself
-                 * if we have sse2, so no problem */
-                if (strstr(value, "sse"))
-                {
-                    user_shared_data->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
-                    cached_sci.FeatureSet |= CPU_FEATURE_SSE;
-                }
-                if (strstr(value, "sse2"))
-                {
-                    user_shared_data->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
-                    cached_sci.FeatureSet |= CPU_FEATURE_SSE2;
-                }
-                if (strstr(value, "pni"))
-                    user_shared_data->ProcessorFeatures[PF_SSE3_INSTRUCTIONS_AVAILABLE] = TRUE;
-                if (strstr(value, "pae"))
-                    user_shared_data->ProcessorFeatures[PF_PAE_ENABLED] = TRUE;
-                if (strstr(value, "ht"))
-                    cached_sci.FeatureSet |= CPU_FEATURE_HTT;
-                continue;
-            }
-	}
-	fclose(f);
-    }
-#elif defined (__NetBSD__)
-    {
-        int mib[2];
-        int value;
-        size_t val_len;
-        char model[256];
-        char *cpuclass;
-        FILE *f = fopen("/var/run/dmesg.boot", "r");
-
-        /* first deduce as much as possible from the sysctls */
-        mib[0] = CTL_MACHDEP;
-#ifdef CPU_FPU_PRESENT
-        mib[1] = CPU_FPU_PRESENT;
-        val_len = sizeof(value);
-        if (sysctl(mib, 2, &value, &val_len, NULL, 0) >= 0)
-            user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = !value;
-#endif
-#ifdef CPU_SSE
-        mib[1] = CPU_SSE;   /* this should imply MMX */
-        val_len = sizeof(value);
-        if (sysctl(mib, 2, &value, &val_len, NULL, 0) >= 0)
-            if (value) user_shared_data->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
-#endif
-#ifdef CPU_SSE2
-        mib[1] = CPU_SSE2;  /* this should imply MMX */
-        val_len = sizeof(value);
-        if (sysctl(mib, 2, &value, &val_len, NULL, 0) >= 0)
-            if (value) user_shared_data->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
-#endif
-        mib[0] = CTL_HW;
-        mib[1] = HW_MODEL;
-        val_len = sizeof(model)-1;
-        if (sysctl(mib, 2, model, &val_len, NULL, 0) >= 0)
-        {
-            model[val_len] = '\0'; /* just in case */
-            cpuclass = strstr(model, "-class");
-            if (cpuclass != NULL) {
-                while(cpuclass > model && cpuclass[0] != '(') cpuclass--;
-                if (!strncmp(cpuclass+1, "386", 3))
-                {
-                    cached_sci.Level= 3;
-                }
-                if (!strncmp(cpuclass+1, "486", 3))
-                {
-                    cached_sci.Level= 4;
-                }
-                if (!strncmp(cpuclass+1, "586", 3))
-                {
-                    cached_sci.Level= 5;
-                }
-                if (!strncmp(cpuclass+1, "686", 3))
-                {
-                    cached_sci.Level= 6;
-                    /* this should imply MMX */
-                    user_shared_data->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
-                }
-            }
-        }
-
-        /* it may be worth reading from /var/run/dmesg.boot for
-           additional information such as CX8, MMX and TSC
-           (however this information should be considered less
-           reliable than that from the sysctl calls) */
-        if (f != NULL)
-        {
-            while (fgets(model, 255, f) != NULL)
-            {
-                int cpu, features;
-                if (sscanf(model, "cpu%d: features %x<", &cpu, &features) == 2)
-                {
-                    /* we could scan the string but it is easier
-                       to test the bits directly */
-                    if (features & 0x1)
-                        user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = TRUE;
-                    if (features & 0x10)
-                        user_shared_data->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
-                    if (features & 0x100)
-                        user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
-                    if (features & 0x800000)
-                        user_shared_data->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
-
-                    break;
-                }
-            }
-            fclose(f);
-        }
-    }
-#elif defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__DragonFly__)
-    {
-        get_cpuinfo( &cached_sci );
-
-        /* Check for OS support of SSE -- Is this used, and should it be sse1 or sse2? */
-        /*len = sizeof(num);
-          ret = sysctlbyname("hw.instruction_sse", &num, &len, NULL, 0);
-          if (!ret)
-          user_shared_data->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = num;*/
-    }
-#elif defined(__sun)
-    {
-        get_cpuinfo( &cached_sci );
-    }
-#elif defined (__APPLE__)
-    {
-        size_t valSize;
-        int value;
-        int cputype;
-        char buffer[1024];
-
-        valSize = sizeof(int);
-        if (sysctlbyname ("hw.optional.floatingpoint", &value, &valSize, NULL, 0) == 0)
-        {
-            if (value)
-                user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE;
-            else
-                user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = TRUE;
-        }
-
-        valSize = sizeof(int);
-        if (sysctlbyname ("hw.cputype", &cputype, &valSize, NULL, 0) == 0)
-        {
-            switch (cputype)
-            {
-            case CPU_TYPE_POWERPC:
-                cached_sci.Architecture = PROCESSOR_ARCHITECTURE_PPC;
-                valSize = sizeof(int);
-                if (sysctlbyname ("hw.cpusubtype", &value, &valSize, NULL, 0) == 0)
-                {
-                    switch (value)
-                    {
-                    case CPU_SUBTYPE_POWERPC_601:
-                    case CPU_SUBTYPE_POWERPC_602:       cached_sci.Level = 1;   break;
-                    case CPU_SUBTYPE_POWERPC_603:       cached_sci.Level = 3;   break;
-                    case CPU_SUBTYPE_POWERPC_603e:
-                    case CPU_SUBTYPE_POWERPC_603ev:     cached_sci.Level = 6;   break;
-                    case CPU_SUBTYPE_POWERPC_604:       cached_sci.Level = 4;   break;
-                    case CPU_SUBTYPE_POWERPC_604e:      cached_sci.Level = 9;   break;
-                    case CPU_SUBTYPE_POWERPC_620:       cached_sci.Level = 20;  break;
-                    case CPU_SUBTYPE_POWERPC_750:       /* G3/G4 derive from 603 so ... */
-                    case CPU_SUBTYPE_POWERPC_7400:
-                    case CPU_SUBTYPE_POWERPC_7450:      cached_sci.Level = 6;   break;
-                    case CPU_SUBTYPE_POWERPC_970:       cached_sci.Level = 9;
-                        /* :o) user_shared_data->ProcessorFeatures[PF_ALTIVEC_INSTRUCTIONS_AVAILABLE] ;-) */
-                        break;
-                    default: break;
-                    }
-                }
-                break; /* CPU_TYPE_POWERPC */
-            case CPU_TYPE_I386:
-                cached_sci.Architecture = PROCESSOR_ARCHITECTURE_INTEL;
-                valSize = sizeof(int);
-                if (sysctlbyname ("machdep.cpu.family", &value, &valSize, NULL, 0) == 0)
-                {
-                    cached_sci.Level = value;
-                }
-                valSize = sizeof(int);
-                if (sysctlbyname ("machdep.cpu.model", &value, &valSize, NULL, 0) == 0)
-                    cached_sci.Revision = (value << 8);
-                valSize = sizeof(int);
-                if (sysctlbyname ("machdep.cpu.stepping", &value, &valSize, NULL, 0) == 0)
-                    cached_sci.Revision |= value;
-                valSize = sizeof(buffer);
-                if (sysctlbyname ("machdep.cpu.features", buffer, &valSize, NULL, 0) == 0)
-                {
-                    if (!valSize) FIXME("Buffer not large enough, please increase\n");
-                    if (strstr(buffer, "CX8"))   user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
-                    if (strstr(buffer, "CX16"))  user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE128] = TRUE;
-                    if (strstr(buffer, "MMX"))   user_shared_data->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
-                    if (strstr(buffer, "TSC"))   user_shared_data->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
-                    if (strstr(buffer, "3DNOW")) user_shared_data->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = TRUE;
-                    if (strstr(buffer, "SSE"))   user_shared_data->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
-                    if (strstr(buffer, "SSE2"))  user_shared_data->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
-                    if (strstr(buffer, "SSE3"))  user_shared_data->ProcessorFeatures[PF_SSE3_INSTRUCTIONS_AVAILABLE] = TRUE;
-                    if (strstr(buffer, "PAE"))   user_shared_data->ProcessorFeatures[PF_PAE_ENABLED] = TRUE;
-                    if (strstr(buffer, "HTT"))   cached_sci.FeatureSet |= CPU_FEATURE_HTT;
-                }
-                break; /* CPU_TYPE_I386 */
-            default: break;
-            } /* switch (cputype) */
-        }
-    }
-#else
-    FIXME("not yet supported on this system\n");
-#endif
     TRACE("<- CPU arch %d, level %d, rev %d, features 0x%x\n",
           cached_sci.Architecture, cached_sci.Level, cached_sci.Revision, cached_sci.FeatureSet);
 }
-- 
1.7.12.4




More information about the wine-patches mailing list