new X86 CPU detection code (Petr Sebor)
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 21 Jan 2003 16:13:55 +0000 (16:13 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Tue, 21 Jan 2003 16:13:55 +0000 (16:13 +0000)
src/mesa/x86/common_x86.c
src/mesa/x86/common_x86_asm.S
src/mesa/x86/common_x86_features.h

index b680cb701a05ce64257db17dfa63f196370dab5b..f22cd18b341882e72715a9dd45e61683f505d2c7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: common_x86.c,v 1.20 2002/11/13 15:03:31 brianp Exp $ */
+/* $Id: common_x86.c,v 1.21 2003/01/21 16:13:55 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -52,8 +52,14 @@ int _mesa_x86_cpu_features = 0;
 
 /* 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 _mesa_init_all_x86_transform_asm( void )
 {
    (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 0bd55e799ceadf54572ce4cae097df9381a11e9e..9deceeaa32731114cdd904ce601f24be4ec83e47 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: common_x86_asm.S,v 1.16 2003/01/09 23:43:02 brianp Exp $ */
+/* $Id: common_x86_asm.S,v 1.17 2003/01/21 16:13:58 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -32,6 +32,7 @@
  * Written by Holger Waechtler <holger@akaflieg.extern.tu-berlin.de>
  *
  * Cleaned up and simplified by Gareth Hughes <gareth@valinux.com>
+ *
  */
 
 /*
 #include "matypes.h"
 #include "common_x86_features.h"
 
+       SEG_TEXT
 
-/* Intel vendor string
- */
-#define GENU   0x756e6547      /* "Genu" */
-#define INEI   0x49656e69      /* "ineI" */
-#define NTEL   0x6c65746e      /* "ntel" */
+ALIGNTEXT4
+GLOBL GLNAME(_mesa_x86_has_cpuid)
+GLNAME(_mesa_x86_has_cpuid):
 
-/* AMD vendor string
- */
-#define AUTH   0x68747541      /* "Auth" */
-#define ENTI   0x69746e65      /* "enti" */
-#define CAMD   0x444d4163      /* "cAMD" */
+       /* Test for the CPUID command.  If the ID Flag bit in EFLAGS
+        * (bit 21) is writable, the CPUID command is present */
+       PUSHF_L
+       POP_L   (EAX)
+       MOV_L   (EAX, ECX)
+       XOR_L   (CONST(0x00200000), EAX)
+       PUSH_L  (EAX)
+       POPF_L
+       PUSHF_L
+       POP_L   (EAX)
 
+       /* Verify the ID Flag bit has been written. */
+       CMP_L   (ECX, EAX)
+       SETNE   (AL)
+       XOR_L   (CONST(0xff), EAX)
 
-       SEG_DATA
+       RET
 
-/* 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" )
 
+ALIGNTEXT4
+GLOBL GLNAME(_mesa_x86_cpuid)
+GLNAME(_mesa_x86_cpuid):
 
-       SEG_TEXT
+       MOV_L   (REGOFF(4, ESP), EAX)           /* cpuid op */
+       PUSH_L  (EDI)
+       PUSH_L  (EBX)
 
-ALIGNTEXT4
-GLOBL GLNAME( _mesa_identify_x86_cpu_features )
-GLNAME( _mesa_identify_x86_cpu_features ):
+       CPUID
 
-       PUSH_L  ( EBX )
-       PUSH_L  ( ESI )
+       MOV_L   (REGOFF(16, ESP), EDI)  /* *eax */
+       MOV_L   (EAX, REGIND(EDI))
+       MOV_L   (REGOFF(20, ESP), EDI)  /* *ebx */
+       MOV_L   (EBX, REGIND(EDI))
+       MOV_L   (REGOFF(24, ESP), EDI)  /* *ecx */
+       MOV_L   (ECX, REGIND(EDI))
+       MOV_L   (REGOFF(28, ESP), EDI)  /* *edx */
+       MOV_L   (EDX, REGIND(EDI))
+
+       POP_L   (EBX)
+       POP_L   (EDI)
+       RET
 
-       /* Test for the CPUID command.  If the ID Flag bit in EFLAGS
-        * (bit 21) is writable, the CPUID command is present.
-        */
-       PUSHF_L
-       POP_L   ( EAX )
-       MOV_L   ( EAX, ECX )
-       XOR_L   ( CONST(0x00200000), EAX )
-       PUSH_L  ( EAX )
-       POPF_L
-       PUSHF_L
-       POP_L   ( EAX )
+ALIGNTEXT4
+GLOBL GLNAME(_mesa_x86_cpuid_eax)
+GLNAME(_mesa_x86_cpuid_eax):
 
-       /* Verify the ID Flag bit has been written.
-        */
-       CMP_L   ( ECX, EAX )
-       JZ      ( LLBL (cpuid_done) )
+       MOV_L   (REGOFF(4, ESP), EAX)           /* cpuid op */
+       PUSH_L  (EBX)
 
-       /* Get the CPU vendor info.
-        */
-       XOR_L   ( EAX, EAX )
        CPUID
 
-       /* 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 )
+       POP_L   (EBX)
+       RET
 
-       /* 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) )
+ALIGNTEXT4
+GLOBL GLNAME(_mesa_x86_cpuid_ebx)
+GLNAME(_mesa_x86_cpuid_ebx):
 
-LLBL(cpuid_amd):
+       MOV_L   (REGOFF(4, ESP), EAX)           /* cpuid op */
+       PUSH_L  (EBX)
 
-       /* 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   (EBX, EAX)                      /* return EBX */
 
-       MOV_L   ( CONST(0x80000000), EAX )
-       CPUID
-       TEST_L  ( EAX, EAX )
-       JZ      ( LLBL (cpuid_failed) )
+       POP_L   (EBX)
+       RET
 
-       MOV_L   ( CONST(0x80000001), EAX )
-       CPUID
-       MOV_L   ( EDX, EAX )
-       
-       AND_L   ( CONST(0x02000000), ESI )      /* OR in the SSE bit */
-       OR_L    ( ESI, EAX )
-       
-       JMP     ( LLBL (cpuid_done) )
+ALIGNTEXT4
+GLOBL GLNAME(_mesa_x86_cpuid_ecx)
+GLNAME(_mesa_x86_cpuid_ecx):
 
-LLBL(cpuid_other):
+       MOV_L   (REGOFF(4, ESP), EAX)           /* cpuid op */
+       PUSH_L  (EBX)
 
-       /* Test for other processors here when required.
-        */
+       CPUID
+       MOV_L   (ECX, EAX)                      /* return ECX */
 
-LLBL(cpuid_failed):
+       POP_L   (EBX)
+       RET
 
-       /* 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 )
+ALIGNTEXT4
+GLOBL GLNAME(_mesa_x86_cpuid_edx)
+GLNAME(_mesa_x86_cpuid_edx):
 
-LLBL (cpuid_done):
+       MOV_L   (REGOFF(4, ESP), EAX)           /* cpuid op */
+       PUSH_L  (EBX)
 
-       POP_L   ( ESI )
-       POP_L   ( EBX )
-       RET
+       CPUID
+       MOV_L   (EDX, EAX)                      /* return EDX */
 
+       POP_L   (EBX)
+       RET
 
 #ifdef USE_SSE_ASM
 /* Execute an SSE instruction to see if the operating system correctly
@@ -235,3 +200,4 @@ GLNAME( _mesa_test_os_sse_exception_support ):
        RET
 
 #endif
+
index 258f38937b6f003e22f193ec8d07d850896d1d90..90509775cfcd89f0c058ed8d33271e676e34e814 100644 (file)
@@ -1,8 +1,8 @@
-/* $Id: common_x86_features.h,v 1.5 2002/10/29 20:28:57 brianp Exp $ */
+/* $Id: common_x86_features.h,v 1.6 2003/01/21 16:14:00 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  5.1
  *
  * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
  *
 #ifndef __COMMON_X86_FEATURES_H__
 #define __COMMON_X86_FEATURES_H__
 
-/* 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)
+
+/* standard X86 CPU features */
+#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)
+
+/* extended X86 CPU features */
+#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)
@@ -78,3 +65,4 @@
 #define cpu_has_3dnowext       (_mesa_x86_cpu_features & X86_FEATURE_3DNOWEXT)
 
 #endif
+