ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

common_x86.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  6.5.1
00004  *
00005  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00037 /* XXX these includes should probably go into imports.h or glheader.h */
00038 #if defined(USE_SSE_ASM) && defined(__linux__)
00039 #include <linux/version.h>
00040 #endif
00041 #if defined(USE_SSE_ASM) && defined(__FreeBSD__)
00042 #include <sys/types.h>
00043 #include <sys/sysctl.h>
00044 #endif
00045 #if defined(USE_SSE_ASM) && defined(__OpenBSD__)
00046 #include <sys/param.h>
00047 #include <sys/sysctl.h>
00048 #include <machine/cpu.h>
00049 #endif
00050 
00051 #include "main/imports.h"
00052 #include "common_x86_asm.h"
00053 
00054 
00055 int _mesa_x86_cpu_features = 0;
00056 
00057 /* No reason for this to be public.
00058  */
00059 extern GLuint   _ASMAPI _mesa_x86_has_cpuid(void);
00060 extern void _ASMAPI _mesa_x86_cpuid(GLuint op, GLuint *reg_eax, GLuint *reg_ebx, GLuint *reg_ecx, GLuint *reg_edx);
00061 extern GLuint   _ASMAPI _mesa_x86_cpuid_eax(GLuint op);
00062 extern GLuint   _ASMAPI _mesa_x86_cpuid_ebx(GLuint op);
00063 extern GLuint   _ASMAPI _mesa_x86_cpuid_ecx(GLuint op);
00064 extern GLuint   _ASMAPI _mesa_x86_cpuid_edx(GLuint op);
00065 
00066 
00067 #if defined(USE_SSE_ASM)
00068 /*
00069  * We must verify that the Streaming SIMD Extensions are truly supported
00070  * on this processor before we go ahead and hook out the optimized code.
00071  *
00072  * However, I have been told by Alan Cox that all 2.4 (and later) Linux
00073  * kernels provide full SSE support on all processors that expose SSE via
00074  * the CPUID mechanism.
00075  */
00076 extern void _mesa_test_os_sse_support( void );
00077 extern void _mesa_test_os_sse_exception_support( void );
00078 
00079 #if defined(WIN32)
00080 #ifndef STATUS_FLOAT_MULTIPLE_TRAPS
00081 # define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L)
00082 #endif
00083 static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS exp)
00084 {
00085    PEXCEPTION_RECORD rec = exp->ExceptionRecord;
00086    PCONTEXT ctx = exp->ContextRecord;
00087 
00088    if ( rec->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION ) {
00089       _mesa_debug(NULL, "EXCEPTION_ILLEGAL_INSTRUCTION\n" );
00090       _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
00091    } else if ( rec->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS ) {
00092       _mesa_debug(NULL, "STATUS_FLOAT_MULTIPLE_TRAPS\n");
00093       /* Windows seems to clear the exception flag itself, we just have to increment Eip */
00094    } else {
00095       _mesa_debug(NULL, "UNEXPECTED EXCEPTION (0x%08x), terminating!\n" );
00096       return EXCEPTION_EXECUTE_HANDLER;
00097    }
00098 
00099    if ( (ctx->ContextFlags & CONTEXT_CONTROL) != CONTEXT_CONTROL ) {
00100       _mesa_debug(NULL, "Context does not contain control registers, terminating!\n");
00101       return EXCEPTION_EXECUTE_HANDLER;
00102    }
00103    ctx->Eip += 3;
00104 
00105    return EXCEPTION_CONTINUE_EXECUTION;
00106 }
00107 #endif /* WIN32 */
00108 
00109 
00110 static void check_os_sse_support( void )
00111 {
00112 #if defined(__FreeBSD__)
00113    {
00114       int ret, enabled;
00115       unsigned int len;
00116       len = sizeof(enabled);
00117       ret = sysctlbyname("hw.instruction_sse", &enabled, &len, NULL, 0);
00118       if (ret || !enabled)
00119          _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
00120    }
00121 #elif defined (__NetBSD__)
00122    {
00123       int ret, enabled;
00124       size_t len = sizeof(enabled);
00125       ret = sysctlbyname("machdep.sse", &enabled, &len, (void *)NULL, 0);
00126       if (ret || !enabled)
00127          _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
00128    }
00129 #elif defined(__OpenBSD__)
00130    {
00131       int mib[2];
00132       int ret, enabled;
00133       size_t len = sizeof(enabled);
00134 
00135       mib[0] = CTL_MACHDEP;
00136       mib[1] = CPU_SSE;
00137 
00138       ret = sysctl(mib, 2, &enabled, &len, NULL, 0);
00139       if (ret || !enabled)
00140          _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
00141    }
00142 #elif defined(WIN32)
00143    LPTOP_LEVEL_EXCEPTION_FILTER oldFilter;
00144    
00145    /* Install our ExceptionFilter */
00146    oldFilter = SetUnhandledExceptionFilter( ExceptionFilter );
00147    
00148    if ( cpu_has_xmm ) {
00149       _mesa_debug(NULL, "Testing OS support for SSE...\n");
00150 
00151       _mesa_test_os_sse_support();
00152 
00153       if ( cpu_has_xmm ) {
00154      _mesa_debug(NULL, "Yes.\n");
00155       } else {
00156      _mesa_debug(NULL, "No!\n");
00157       }
00158    }
00159 
00160    if ( cpu_has_xmm ) {
00161       _mesa_debug(NULL, "Testing OS support for SSE unmasked exceptions...\n");
00162 
00163       //_mesa_test_os_sse_exception_support();
00164 
00165       if ( cpu_has_xmm ) {
00166      _mesa_debug(NULL, "Yes.\n");
00167       } else {
00168      _mesa_debug(NULL, "No!\n");
00169       }
00170    }
00171 
00172    /* Restore previous exception filter */
00173    SetUnhandledExceptionFilter( oldFilter );
00174 
00175    if ( cpu_has_xmm ) {
00176       _mesa_debug(NULL, "Tests of OS support for SSE passed.\n");
00177    } else {
00178       _mesa_debug(NULL, "Tests of OS support for SSE failed!\n");
00179    }
00180 #else
00181    /* Do nothing on other platforms for now.
00182     */
00183    _mesa_debug(NULL, "Not testing OS support for SSE, leaving enabled.\n");
00184 #endif /* __FreeBSD__ */
00185 }
00186 
00187 #endif /* USE_SSE_ASM */
00188 
00189 
00190 void _mesa_init_all_x86_transform_asm( void )
00191 {
00192 #ifdef USE_X86_ASM
00193    _mesa_x86_cpu_features = 0;
00194 
00195    if (!_mesa_x86_has_cpuid()) {
00196        _mesa_debug(NULL, "CPUID not detected\n");
00197    }
00198    else {
00199        GLuint cpu_features;
00200        GLuint cpu_ext_features;
00201        GLuint cpu_ext_info;
00202        char cpu_vendor[13];
00203        GLuint result;
00204 
00205        /* get vendor name */
00206        _mesa_x86_cpuid(0, &result, (GLuint *)(cpu_vendor + 0), (GLuint *)(cpu_vendor + 8), (GLuint *)(cpu_vendor + 4));
00207        cpu_vendor[12] = '\0';
00208 
00209        _mesa_debug(NULL, "CPU vendor: %s\n", cpu_vendor);
00210 
00211        /* get cpu features */
00212        cpu_features = _mesa_x86_cpuid_edx(1);
00213 
00214        if (cpu_features & X86_CPU_FPU)
00215        _mesa_x86_cpu_features |= X86_FEATURE_FPU;
00216        if (cpu_features & X86_CPU_CMOV)
00217        _mesa_x86_cpu_features |= X86_FEATURE_CMOV;
00218 
00219 #ifdef USE_MMX_ASM
00220        if (cpu_features & X86_CPU_MMX)
00221        _mesa_x86_cpu_features |= X86_FEATURE_MMX;
00222 #endif
00223 
00224 #ifdef USE_SSE_ASM
00225        if (cpu_features & X86_CPU_XMM)
00226        _mesa_x86_cpu_features |= X86_FEATURE_XMM;
00227        if (cpu_features & X86_CPU_XMM2)
00228        _mesa_x86_cpu_features |= X86_FEATURE_XMM2;
00229 #endif
00230 
00231        /* query extended cpu features */
00232        if ((cpu_ext_info = _mesa_x86_cpuid_eax(0x80000000)) > 0x80000000) {
00233        if (cpu_ext_info >= 0x80000001) {
00234 
00235            cpu_ext_features = _mesa_x86_cpuid_edx(0x80000001);
00236 
00237            if (cpu_features & X86_CPU_MMX) {
00238 
00239 #ifdef USE_3DNOW_ASM
00240            if (cpu_ext_features & X86_CPUEXT_3DNOW)
00241                _mesa_x86_cpu_features |= X86_FEATURE_3DNOW;
00242            if (cpu_ext_features & X86_CPUEXT_3DNOW_EXT)
00243                _mesa_x86_cpu_features |= X86_FEATURE_3DNOWEXT;
00244 #endif
00245 
00246 #ifdef USE_MMX_ASM
00247            if (cpu_ext_features & X86_CPUEXT_MMX_EXT)
00248                _mesa_x86_cpu_features |= X86_FEATURE_MMXEXT;
00249 #endif
00250            }
00251        }
00252 
00253        /* query cpu name */
00254        if (cpu_ext_info >= 0x80000002) {
00255            GLuint ofs;
00256            char cpu_name[49];
00257            for (ofs = 0; ofs < 3; ofs++)
00258            _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));
00259            cpu_name[48] = '\0'; /* the name should be NULL terminated, but just to be sure */
00260 
00261            _mesa_debug(NULL, "CPU name: %s\n", cpu_name);
00262        }
00263        }
00264 
00265    }
00266    
00267    if ( _mesa_getenv( "MESA_NO_ASM" ) ) {
00268       _mesa_x86_cpu_features = 0;
00269    }
00270 
00271    if ( _mesa_x86_cpu_features ) {
00272       _mesa_init_x86_transform_asm();
00273    }
00274 
00275 #ifdef USE_MMX_ASM
00276    if ( cpu_has_mmx ) {
00277       if ( _mesa_getenv( "MESA_NO_MMX" ) == 0 ) {
00278          _mesa_debug(NULL, "MMX cpu detected.\n");
00279       } else {
00280          _mesa_x86_cpu_features &= ~(X86_FEATURE_MMX);
00281       }
00282    }
00283 #endif
00284 
00285 #ifdef USE_3DNOW_ASM
00286    if ( cpu_has_3dnow ) {
00287       if ( _mesa_getenv( "MESA_NO_3DNOW" ) == 0 ) {
00288          _mesa_debug(NULL, "3DNow! cpu detected.\n");
00289          _mesa_init_3dnow_transform_asm();
00290       } else {
00291          _mesa_x86_cpu_features &= ~(X86_FEATURE_3DNOW);
00292       }
00293    }
00294 #endif
00295 
00296 #ifdef USE_SSE_ASM
00297    if ( cpu_has_xmm ) {
00298       if ( _mesa_getenv( "MESA_NO_SSE" ) == 0 ) {
00299          _mesa_debug(NULL, "SSE cpu detected.\n");
00300          if ( _mesa_getenv( "MESA_FORCE_SSE" ) == 0 ) {
00301             check_os_sse_support();
00302          }
00303          if ( cpu_has_xmm ) {
00304             _mesa_init_sse_transform_asm();
00305          }
00306       } else {
00307          _mesa_debug(NULL, "SSE cpu detected, but switched off by user.\n");
00308          _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
00309       }
00310    }
00311 #endif
00312 #endif
00313 }
00314 

Generated on Sat May 26 2012 04:19:39 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.