Hi,

I have recently rewritten the Mesa CPU detection code and
would like someone else to give it a try.

Basically, the highlights are:

- added _mesa_x86_has_cpuid
- added _mesa_x86_cpuid
- added _mesa_x86_cpuid_eax
- added _mesa_x86_cpuid_ebx
- added _mesa_x86_cpuid_ecx
- added _mesa_x86_cpuid_edx
- removed _mesa_identify_x86_cpu_features
- differentiated extended cpu features (in ..x86_features.h)
  from the std ones
- changed the X86_FEATURE semantics a little bit

with these tools, I am trying to parse the cpu feature while
making distinction between the normal and extended cpu
feature sets - no need to query the cpu vendor string, while
making the code highly readable for people not familiar with
the assembly langugage.

Please consider applying...

-petrs


Bernhard Kaindl wrote:
Hi,
   I'd like to report a finding on my Satellite 1110-z16 with
Mobile Celeron 1500 and Radeon LY under SuSE 8.1 and Mandrake 9
using the installed XFree86-4.2 based X11/Mesa.
 
Both show a problem with many 3D Linux apps arborting with SIGILL,
MESA_DEBUG showed that the apps were thinking that the Celeron
supported 3DNow(message 3dnow supported was printed) which it at
least does not when checking /proc/cpuinfo.
 
After I disabled the use of 3dnow by exporting MESA_NO_3DNOW,
everything works but it's a not good needing to export it and it's
only a workaround.
 
So it looks like as if the Mesa CPUID asm gets the 3dnow feature
bit set, so the feature is enabled and depending what the app does
it gets the sigill or not(glxgears and fgfs do not but show no
rendering in a part of the window if I move another window into the
middle of the 3d window.
 
Both distributions use Free 4.2 code, but I've started
downloading the 4.3.99 rpms do test with it.
 
Just guessing(maybe fixed already, just could not get the newest
XF86 4.3/Mesa Source over the slow modem I'm using atm yet, but
working on it):
 
I've checked the 2.4.19 x86 feature/CPUID code in
arch/i386/kernel/setup.c and found a place where it
does something to the 3dnow flag.
 
Maybe the CPUID regs set on stepping 7 of the Mobile
Celeron 1500 are a bit different and the kernel handles
this by the special 3dnow lines I've seen.
 
Bernd


Index: common_x86.c
===================================================================
RCS file: /cvsroot/mesa3d/Mesa/src/X86/common_x86.c,v
retrieving revision 1.20
diff -u -r1.20 common_x86.c
--- common_x86.c        13 Nov 2002 15:03:31 -0000      1.20
+++ common_x86.c        31 Dec 2002 03:02:45 -0000
@@ -52,8 +52,14 @@
 
 /* No reason for this to be public.
  */
-extern int _mesa_identify_x86_cpu_features( void );
+extern int     _mesa_identify_x86_cpu_features(void);
 
+extern GLuint  _mesa_x86_has_cpuid(void);
+extern void    _mesa_x86_cpuid(GLuint op, GLuint *reg_eax, GLuint *reg_ebx, GLuint 
+*reg_ecx, GLuint *reg_edx);
+extern GLuint  _mesa_x86_cpuid_eax(GLuint op);
+extern GLuint  _mesa_x86_cpuid_ebx(GLuint op);
+extern GLuint  _mesa_x86_cpuid_ecx(GLuint op);
+extern GLuint  _mesa_x86_cpuid_edx(GLuint op);
 
 static void message( const char *msg )
 {
@@ -240,8 +246,84 @@
 {
    (void) message; /* silence warning */
 #ifdef USE_X86_ASM
-   _mesa_x86_cpu_features = _mesa_identify_x86_cpu_features();
+   _mesa_x86_cpu_features = 0;
 
+   if (!_mesa_x86_has_cpuid()) {
+       message("CPUID not detected");
+   }
+   else {
+       GLuint cpu_features;
+       GLuint cpu_ext_features;
+       GLuint cpu_ext_info;
+       char cpu_vendor[13];
+       GLuint result;
+
+       /* get vendor name */
+       _mesa_x86_cpuid(0, &result, (GLuint *)(cpu_vendor + 0), (GLuint *)(cpu_vendor 
++ 8), (GLuint *)(cpu_vendor + 4));
+       cpu_vendor[12] = '\0';
+
+       message("cpu vendor: ");
+       message(cpu_vendor);
+       message("\n");
+
+       /* get cpu features */
+       cpu_features = _mesa_x86_cpuid_edx(1);
+
+       if (cpu_features & X86_CPU_FPU)
+          _mesa_x86_cpu_features |= X86_FEATURE_FPU;
+       if (cpu_features & X86_CPU_CMOV)
+          _mesa_x86_cpu_features |= X86_FEATURE_CMOV;
+
+#ifdef USE_MMX_ASM
+       if (cpu_features & X86_CPU_MMX)
+          _mesa_x86_cpu_features |= X86_FEATURE_MMX;
+#endif
+
+#ifdef USE_SSE_ASM
+       if (cpu_features & X86_CPU_XMM)
+          _mesa_x86_cpu_features |= X86_FEATURE_XMM;
+       if (cpu_features & X86_CPU_XMM2)
+          _mesa_x86_cpu_features |= X86_FEATURE_XMM2;
+#endif
+
+       /* query extended cpu features */
+       if ((cpu_ext_info = _mesa_x86_cpuid_eax(0x80000000)) > 0x80000000) {
+          if (cpu_ext_info >= 0x80000001) {
+
+              cpu_ext_features = _mesa_x86_cpuid_edx(0x80000001);
+
+              if (cpu_features & X86_CPU_MMX) {
+
+#ifdef USE_3DNOW_ASM
+                  if (cpu_ext_features & X86_CPUEXT_3DNOW)
+                      _mesa_x86_cpu_features |= X86_FEATURE_3DNOW;
+                  if (cpu_ext_features & X86_CPUEXT_3DNOW_EXT)
+                      _mesa_x86_cpu_features |= X86_FEATURE_3DNOWEXT;
+#endif
+
+#ifdef USE_MMX_ASM
+                  if (cpu_ext_features & X86_CPUEXT_MMX_EXT)
+                      _mesa_x86_cpu_features |= X86_FEATURE_MMXEXT;
+#endif
+              }
+          }
+
+          /* query cpu name */
+          if (cpu_ext_info >= 0x80000002) {
+              GLuint ofs;
+              char cpu_name[49];
+              for (ofs = 0; ofs < 3; ofs++)
+                  _mesa_x86_cpuid(0x80000002+ofs, (GLuint *)(cpu_name + (16*ofs)+0), 
+(GLuint *)(cpu_name + (16*ofs)+4), (GLuint *)(cpu_name + (16*ofs)+8), (GLuint 
+*)(cpu_name + (16*ofs)+12));
+              cpu_name[48] = '\0'; /* the name should be NULL terminated, but just to 
+be sure */
+
+              message("cpu name: ");
+              message(cpu_name);
+              message("\n");
+          }
+       }
+
+   }
+   
    if ( getenv( "MESA_NO_ASM" ) ) {
       _mesa_x86_cpu_features = 0;
    }
Index: common_x86_asm.S
===================================================================
RCS file: /cvsroot/mesa3d/Mesa/src/X86/common_x86_asm.S,v
retrieving revision 1.13
diff -u -r1.13 common_x86_asm.S
--- common_x86_asm.S    9 Nov 2002 17:43:58 -0000       1.13
+++ common_x86_asm.S    31 Dec 2002 03:02:45 -0000
@@ -43,36 +43,11 @@
 #include "matypes.h"
 #include "common_x86_features.h"
 
-
-/* Intel vendor string
- */
-#define GENU   0x756e6547      /* "Genu" */
-#define INEI   0x49656e69      /* "ineI" */
-#define NTEL   0x6c65746e      /* "ntel" */
-
-/* AMD vendor string
- */
-#define AUTH   0x68747541      /* "Auth" */
-#define ENTI   0x69746e65      /* "enti" */
-#define CAMD   0x444d4163      /* "cAMD" */
-
-
-       SEG_DATA
-
-/* We might want to print out some useful messages.
- */
-GLNAME( found_intel ): STRING( "Genuine Intel processor found\n\0" )
-GLNAME( found_amd ):   STRING( "Authentic AMD processor found\n\0" )
-
-
        SEG_TEXT
 
 ALIGNTEXT4
-GLOBL GLNAME( _mesa_identify_x86_cpu_features )
-GLNAME( _mesa_identify_x86_cpu_features ):
-
-       PUSH_L  ( EBX )
-       PUSH_L  ( ESI )
+GLOBL GLNAME( _mesa_x86_has_cpuid )
+GLNAME( _mesa_x86_has_cpuid ):
 
        /* Test for the CPUID command.  If the ID Flag bit in EFLAGS
         * (bit 21) is writable, the CPUID command is present.
@@ -89,94 +64,113 @@
        /* Verify the ID Flag bit has been written.
         */
        CMP_L   ( ECX, EAX )
-       JZ      ( LLBL (cpuid_done) )
+       SETNE   ( AL )
+       XOR_L   ( CONST(0xff), EAX )
 
-       /* Get the CPU vendor info.
-        */
-       XOR_L   ( EAX, EAX )
-       CPUID
+       RET
 
-       /* Test for Intel processors.  We must look for the
-        * "GenuineIntel" string in EBX, ECX and EDX.
-        */
-       CMP_L   ( CONST(GENU), EBX )
-       JNE     ( LLBL(cpuid_amd) )
-       CMP_L   ( CONST(INEI), EDX )
-       JNE     ( LLBL(cpuid_amd) )
-       CMP_L   ( CONST(NTEL), ECX )
-       JNE     ( LLBL(cpuid_amd) )
 
-       /* We have an Intel processor, so we can get the feature
-        * information with an CPUID input value of 1.
-        */
-       MOV_L   ( CONST(0x1), EAX )
-       CPUID
-       MOV_L   ( EDX, EAX )
+ALIGNTEXT4
+GLOBL GLNAME( _mesa_x86_cpuid )
+GLNAME( _mesa_x86_cpuid ):
 
-       /* Mask out highest bit, which is used by AMD for 3dnow
-         * Newer Intel have this bit set, but do not support 3dnow 
-        */
-        AND_L   ( CONST(0X7FFFFFFF), EAX)
-       JMP     ( LLBL(cpuid_done) )
+       MOV_L   ( REGOFF(4, ESP), EAX )         /* cpuid op */
 
-LLBL(cpuid_amd):
+       PUSH_L  ( EDI )
+       PUSH_L  ( EBX )
+       PUSH_L  ( ECX )
+       PUSH_L  ( EDX )
 
-       /* Test for AMD processors.  We must look for the
-        * "AuthenticAMD" string in EBX, ECX and EDX.
-        */
-       CMP_L   ( CONST(AUTH), EBX )
-       JNE     ( LLBL(cpuid_other) )
-       CMP_L   ( CONST(ENTI), EDX )
-       JNE     ( LLBL(cpuid_other) )
-       CMP_L   ( CONST(CAMD), ECX )
-       JNE     ( LLBL(cpuid_other) )
-
-       /* We have an AMD processor, so we can get the feature
-        * information after we verify that the extended functions are
-        * supported.
-        */
-       /* The features we need are almost all in the extended set.  The
-        * exception is SSE enable, which is in the standard set (0x1).
-        */
-       MOV_L   ( CONST(0x1), EAX )
        CPUID
-       TEST_L  ( EAX, EAX )
-       JZ      ( LLBL (cpuid_failed) )
-       MOV_L   ( EDX, ESI )
 
-       MOV_L   ( CONST(0x80000000), EAX )
+       MOV_L   ( REGOFF(24, ESP), EDI )        /* *eax */
+       MOV_L   ( EAX, REGIND(EDI) )
+       MOV_L   ( REGOFF(28, ESP), EDI )        /* *ebx */
+       MOV_L   ( EBX, REGIND(EDI) )
+       MOV_L   ( REGOFF(32, ESP), EDI )        /* *ecx */
+       MOV_L   ( ECX, REGIND(EDI) )
+       MOV_L   ( REGOFF(36, ESP), EDI )        /* *edx */
+       MOV_L   ( EDX, REGIND(EDI) )
+
+       POP_L   ( EDX )
+       POP_L   ( ECX )
+       POP_L   ( EBX )
+       POP_L   ( EDI )
+       RET
+
+ALIGNTEXT4
+GLOBL GLNAME( _mesa_x86_cpuid_eax )
+GLNAME( _mesa_x86_cpuid_eax ):
+
+       MOV_L   ( REGOFF(4, ESP), EAX )         /* cpuid op */
+
+       PUSH_L  ( EBX )
+       PUSH_L  ( ECX )
+       PUSH_L  ( EDX )
+
        CPUID
-       TEST_L  ( EAX, EAX )
-       JZ      ( LLBL (cpuid_failed) )
 
-       MOV_L   ( CONST(0x80000001), EAX )
+       POP_L   ( EDX )
+       POP_L   ( ECX )
+       POP_L   ( EBX )
+       RET
+
+ALIGNTEXT4
+GLOBL GLNAME( _mesa_x86_cpuid_ebx )
+GLNAME( _mesa_x86_cpuid_ebx ):
+
+       MOV_L   ( REGOFF(4, ESP), EAX )         /* cpuid op */
+
+       PUSH_L  ( EBX )
+       PUSH_L  ( ECX )
+       PUSH_L  ( EDX )
+
        CPUID
-       MOV_L   ( EDX, EAX )
-       
-       AND_L   ( CONST(0x02000000), ESI )      /* OR in the SSE bit */
-       OR_L    ( ESI, EAX )
-       
-       JMP     ( LLBL (cpuid_done) )
+       MOV_L   ( EBX, EAX )                    /* return EBX */
 
-LLBL(cpuid_other):
+       POP_L   ( EDX )
+       POP_L   ( ECX )
+       POP_L   ( EBX )
 
-       /* Test for other processors here when required.
-        */
+       RET
 
-LLBL(cpuid_failed):
+ALIGNTEXT4
+GLOBL GLNAME( _mesa_x86_cpuid_ecx )
+GLNAME( _mesa_x86_cpuid_ecx ):
 
-       /* If we can't determine the feature information, we must
-        * return zero to indicate that no platform-specific
-        * optimizations can be used.
-        */
-       MOV_L   ( CONST(0), EAX )
+       MOV_L   ( REGOFF(4, ESP), EAX )         /* cpuid op */
+
+       PUSH_L  ( EBX )
+       PUSH_L  ( ECX )
+       PUSH_L  ( EDX )
 
-LLBL (cpuid_done):
+       CPUID
+       MOV_L   ( ECX, EAX )                    /* return ECX */
 
-       POP_L   ( ESI )
+       POP_L   ( EDX )
+       POP_L   ( ECX )
        POP_L   ( EBX )
+
        RET
 
+ALIGNTEXT4
+GLOBL GLNAME( _mesa_x86_cpuid_edx )
+GLNAME( _mesa_x86_cpuid_edx ):
+
+       MOV_L   ( REGOFF(4, ESP), EAX )         /* cpuid op */
+
+       PUSH_L  ( EBX )
+       PUSH_L  ( ECX )
+       PUSH_L  ( EDX )
+
+       CPUID
+       MOV_L   ( EDX, EAX )                    /* return EDX */
+
+       POP_L   ( EDX )
+       POP_L   ( ECX )
+       POP_L   ( EBX )
+
+       RET
 
 #ifdef USE_SSE_ASM
 /* Execute an SSE instruction to see if the operating system correctly
Index: common_x86_features.h
===================================================================
RCS file: /cvsroot/mesa3d/Mesa/src/X86/common_x86_features.h,v
retrieving revision 1.5
diff -u -r1.5 common_x86_features.h
--- common_x86_features.h       29 Oct 2002 20:28:57 -0000      1.5
+++ common_x86_features.h       31 Dec 2002 03:02:46 -0000
@@ -37,38 +37,25 @@
 
 /* Capabilities of CPUs
  */
-#define X86_FEATURE_FPU                0x00000001
-#define X86_FEATURE_VME                0x00000002
-#define X86_FEATURE_DE         0x00000004
-#define X86_FEATURE_PSE                0x00000008
-#define X86_FEATURE_TSC                0x00000010
-#define X86_FEATURE_MSR                0x00000020
-#define X86_FEATURE_PAE                0x00000040
-#define X86_FEATURE_MCE                0x00000080
-#define X86_FEATURE_CX8                0x00000100
-#define X86_FEATURE_APIC       0x00000200
-#define X86_FEATURE_10         0x00000400
-#define X86_FEATURE_SEP                0x00000800
-#define X86_FEATURE_MTRR       0x00001000
-#define X86_FEATURE_PGE                0x00002000
-#define X86_FEATURE_MCA                0x00004000
-#define X86_FEATURE_CMOV       0x00008000
-#define X86_FEATURE_PAT                0x00010000
-#define X86_FEATURE_PSE36      0x00020000
-#define X86_FEATURE_18         0x00040000
-#define X86_FEATURE_19         0x00080000
-#define X86_FEATURE_20         0x00100000
-#define X86_FEATURE_21         0x00200000
-#define X86_FEATURE_MMXEXT     0x00400000
-#define X86_FEATURE_MMX                0x00800000
-#define X86_FEATURE_FXSR       0x01000000
-#define X86_FEATURE_XMM                0x02000000
-#define X86_FEATURE_XMM2       0x04000000
-#define X86_FEATURE_27         0x08000000
-#define X86_FEATURE_28         0x10000000
-#define X86_FEATURE_29         0x20000000
-#define X86_FEATURE_3DNOWEXT   0x40000000
-#define X86_FEATURE_3DNOW      0x80000000
+#define X86_FEATURE_FPU                (1<<0)
+#define X86_FEATURE_CMOV       (1<<1)
+#define X86_FEATURE_MMXEXT     (1<<2)
+#define X86_FEATURE_MMX                (1<<3)
+#define X86_FEATURE_FXSR       (1<<4)
+#define X86_FEATURE_XMM                (1<<5)
+#define X86_FEATURE_XMM2       (1<<6)
+#define X86_FEATURE_3DNOWEXT   (1<<7)
+#define X86_FEATURE_3DNOW      (1<<8)
+
+#define X86_CPU_FPU            (1<<0)
+#define X86_CPU_CMOV           (1<<15)
+#define X86_CPU_MMX            (1<<23)
+#define X86_CPU_XMM            (1<<25)
+#define X86_CPU_XMM2           (1<<26)
+
+#define X86_CPUEXT_MMX_EXT     (1<<22)
+#define X86_CPUEXT_3DNOW_EXT   (1<<30)
+#define X86_CPUEXT_3DNOW       (1<<31)
 
 #define cpu_has_mmx            (_mesa_x86_cpu_features & X86_FEATURE_MMX)
 #define cpu_has_mmxext         (_mesa_x86_cpu_features & X86_FEATURE_MMXEXT)


Reply via email to