X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fx86%2Fcommon_x86.c;h=eece7c1c84deac32c1fb3e23643a5cabb29d878b;hb=30655c211c97a69f0eeb9ad6176ca1db67d15bf9;hp=aaef4f8349e8ee949d9e7b5872a9f5bc0d31058b;hpb=902d2faadf37a5627ab2cbcd8993825c8749ec82;p=mesa.git diff --git a/src/mesa/x86/common_x86.c b/src/mesa/x86/common_x86.c index aaef4f8349e..eece7c1c84d 100644 --- a/src/mesa/x86/common_x86.c +++ b/src/mesa/x86/common_x86.c @@ -1,10 +1,8 @@ -/* $Id: common_x86.c,v 1.19 2002/07/11 15:33:02 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 6.0.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,17 +22,19 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* +/** + * \file common_x86.c + * * Check CPU capabilities & initialize optimized funtions for this particular * processor. * - * Written by Holger Waechtler - * Changed by Andre Werthmann for using the - * new Katmai functions. + * Changed by Andre Werthmann for using the new SSE functions. + * + * \author Holger Waechtler + * \author Andre Werthmann */ -#include -#include +/* XXX these includes should probably go into imports.h or glheader.h */ #if defined(USE_SSE_ASM) && defined(__linux__) #include #endif @@ -43,16 +43,20 @@ #include #endif -#include "context.h" #include "common_x86_asm.h" +#include "imports.h" int _mesa_x86_cpu_features = 0; /* No reason for this to be public. */ -extern int _mesa_identify_x86_cpu_features( void ); - +extern GLuint _ASMAPI _mesa_x86_has_cpuid(void); +extern void _ASMAPI _mesa_x86_cpuid(GLuint op, GLuint *reg_eax, GLuint *reg_ebx, GLuint *reg_ecx, GLuint *reg_edx); +extern GLuint _ASMAPI _mesa_x86_cpuid_eax(GLuint op); +extern GLuint _ASMAPI _mesa_x86_cpuid_ebx(GLuint op); +extern GLuint _ASMAPI _mesa_x86_cpuid_ecx(GLuint op); +extern GLuint _ASMAPI _mesa_x86_cpuid_edx(GLuint op); static void message( const char *msg ) { @@ -60,14 +64,14 @@ static void message( const char *msg ) #ifdef DEBUG debug = GL_TRUE; #else - if ( getenv( "MESA_DEBUG" ) ) { + if ( _mesa_getenv( "MESA_DEBUG" ) ) { debug = GL_TRUE; } else { debug = GL_FALSE; } #endif if ( debug ) { - fprintf( stderr, "%s", msg ); + _mesa_debug( NULL, "%s", msg ); } } @@ -86,12 +90,19 @@ static void message( const char *msg ) * loop in the signal delivery from the kernel as we can't interact with * the SIMD FPU state to clear the exception bits. Either way, this is * not good. + * + * However, I have been told by Alan Cox that all 2.4 (and later) Linux + * kernels provide full SSE support on all processors that expose SSE via + * the CPUID mechanism. It just so happens that this is the exact set of + * kernels supported DRI. Therefore, when building for DRI the funky SSE + * exception test is omitted. */ extern void _mesa_test_os_sse_support( void ); extern void _mesa_test_os_sse_exception_support( void ); -#if defined(__linux__) && defined(_POSIX_SOURCE) && defined(X86_FXSR_MAGIC) +#if defined(__linux__) && defined(_POSIX_SOURCE) && defined(X86_FXSR_MAGIC) \ + && !defined(IN_DRI_DRIVER) static void sigill_handler( int signal, struct sigcontext sc ) { message( "SIGILL, " ); @@ -131,6 +142,37 @@ static void sigfpe_handler( int signal, struct sigcontext sc ) } #endif /* __linux__ && _POSIX_SOURCE && X86_FXSR_MAGIC */ +#if defined(WIN32) +#ifndef STATUS_FLOAT_MULTIPLE_TRAPS +# define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L) +#endif +static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS exp) +{ + PEXCEPTION_RECORD rec = exp->ExceptionRecord; + PCONTEXT ctx = exp->ContextRecord; + + if ( rec->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION ) { + message( "EXCEPTION_ILLEGAL_INSTRUCTION, " ); + _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM); + } else if ( rec->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS ) { + message( "STATUS_FLOAT_MULTIPLE_TRAPS, " ); + /* Windows seems to clear the exception flag itself, we just have to increment Eip */ + } else { + message( "UNEXPECTED EXCEPTION (0x%08x), terminating!" ); + return EXCEPTION_EXECUTE_HANDLER; + } + + if ( (ctx->ContextFlags & CONTEXT_CONTROL) != CONTEXT_CONTROL ) { + message( "Context does not contain control registers, terminating!" ); + return EXCEPTION_EXECUTE_HANDLER; + } + ctx->Eip += 3; + + return EXCEPTION_CONTINUE_EXECUTION; +} +#endif /* WIN32 */ + + /* If we're running on a processor that can do SSE, let's see if we * are allowed to or not. This will catch 2.4.0 or later kernels that * haven't been configured for a Pentium III but are running on one, @@ -141,7 +183,7 @@ static void sigfpe_handler( int signal, struct sigcontext sc ) */ static void check_os_sse_support( void ) { -#if defined(__linux__) +#if defined(__linux__) && !defined(IN_DRI_DRIVER) #if defined(_POSIX_SOURCE) && defined(X86_FXSR_MAGIC) struct sigaction saved_sigill; struct sigaction saved_sigfpe; @@ -219,12 +261,51 @@ static void check_os_sse_support( void ) #endif /* _POSIX_SOURCE && X86_FXSR_MAGIC */ #elif defined(__FreeBSD__) { - int ret, len, enabled; + int ret, enabled; + unsigned int len; len = sizeof(enabled); ret = sysctlbyname("hw.instruction_sse", &enabled, &len, NULL, 0); if (ret || !enabled) _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM); } +#elif defined(WIN32) + LPTOP_LEVEL_EXCEPTION_FILTER oldFilter; + + /* Install our ExceptionFilter */ + oldFilter = SetUnhandledExceptionFilter( ExceptionFilter ); + + if ( cpu_has_xmm ) { + message( "Testing OS support for SSE... " ); + + _mesa_test_os_sse_support(); + + if ( cpu_has_xmm ) { + message( "yes.\n" ); + } else { + message( "no!\n" ); + } + } + + if ( cpu_has_xmm ) { + message( "Testing OS support for SSE unmasked exceptions... " ); + + _mesa_test_os_sse_exception_support(); + + if ( cpu_has_xmm ) { + message( "yes.\n" ); + } else { + message( "no!\n" ); + } + } + + /* Restore previous exception filter */ + SetUnhandledExceptionFilter( oldFilter ); + + if ( cpu_has_xmm ) { + message( "Tests of OS support for SSE passed.\n" ); + } else { + message( "Tests of OS support for SSE failed!\n" ); + } #else /* Do nothing on other platforms for now. */ @@ -239,9 +320,85 @@ 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; - if ( getenv( "MESA_NO_ASM" ) ) { +#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 ( _mesa_getenv( "MESA_NO_ASM" ) ) { _mesa_x86_cpu_features = 0; } @@ -251,7 +408,7 @@ void _mesa_init_all_x86_transform_asm( void ) #ifdef USE_MMX_ASM if ( cpu_has_mmx ) { - if ( getenv( "MESA_NO_MMX" ) == 0 ) { + if ( _mesa_getenv( "MESA_NO_MMX" ) == 0 ) { message( "MMX cpu detected.\n" ); } else { _mesa_x86_cpu_features &= ~(X86_FEATURE_MMX); @@ -261,7 +418,7 @@ void _mesa_init_all_x86_transform_asm( void ) #ifdef USE_3DNOW_ASM if ( cpu_has_3dnow ) { - if ( getenv( "MESA_NO_3DNOW" ) == 0 ) { + if ( _mesa_getenv( "MESA_NO_3DNOW" ) == 0 ) { message( "3DNow! cpu detected.\n" ); _mesa_init_3dnow_transform_asm(); } else { @@ -271,14 +428,17 @@ void _mesa_init_all_x86_transform_asm( void ) #endif #ifdef USE_SSE_ASM - if ( cpu_has_xmm && getenv( "MESA_FORCE_SSE" ) == 0 ) { - check_os_sse_support(); - } if ( cpu_has_xmm ) { - if ( getenv( "MESA_NO_SSE" ) == 0 ) { + if ( _mesa_getenv( "MESA_NO_SSE" ) == 0 ) { message( "SSE cpu detected.\n" ); - _mesa_init_sse_transform_asm(); + if ( _mesa_getenv( "MESA_FORCE_SSE" ) == 0 ) { + check_os_sse_support(); + } + if ( cpu_has_xmm ) { + _mesa_init_sse_transform_asm(); + } } else { + message( "SSE cpu detected, but switched off by user.\n" ); _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM); } }