From 068a4812fc1d9e321aa65a91ceb8bc824bedc69a Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 21 Jan 2003 16:13:55 +0000 Subject: [PATCH] new X86 CPU detection code (Petr Sebor) --- src/mesa/x86/common_x86.c | 88 +++++++++++++++++- src/mesa/x86/common_x86_asm.S | 182 +++++++++++++++---------------------- src/mesa/x86/common_x86_features.h | 60 +++++------- 3 files changed, 183 insertions(+), 147 deletions(-) diff --git a/src/mesa/x86/common_x86.c b/src/mesa/x86/common_x86.c index b680cb701a0..f22cd18b341 100644 --- a/src/mesa/x86/common_x86.c +++ b/src/mesa/x86/common_x86.c @@ -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; } diff --git a/src/mesa/x86/common_x86_asm.S b/src/mesa/x86/common_x86_asm.S index 0bd55e799ce..9deceeaa327 100644 --- a/src/mesa/x86/common_x86_asm.S +++ b/src/mesa/x86/common_x86_asm.S @@ -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 * * Cleaned up and simplified by Gareth Hughes + * */ /* @@ -43,140 +44,104 @@ #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 + diff --git a/src/mesa/x86/common_x86_features.h b/src/mesa/x86/common_x86_features.h index 258f38937b6..90509775cfc 100644 --- a/src/mesa/x86/common_x86_features.h +++ b/src/mesa/x86/common_x86_features.h @@ -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. * @@ -35,40 +35,27 @@ #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 + -- 2.11.0