kdefx Library API Documentation

kcpuinfo.cpp

00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (C) 2003 Fredrik Höglund <fredrik@kde.org> 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00017 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00018 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00019 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00020 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00021 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00022 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00023 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00024 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00025 */ 00026 00027 #include <csignal> 00028 #include <csetjmp> 00029 00030 #include <config.h> 00031 #include "kcpuinfo.h" 00032 00033 00034 #if defined(__GNUC__) || defined(__INTEL_COMPILER) 00035 # define HAVE_GNU_INLINE_ASM 00036 #endif 00037 00038 00039 // Copied from kdecore/kglobal.h 00040 #if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 > 2) 00041 # define KDE_NO_EXPORT __attribute__ ((visibility("hidden"))) 00042 #else 00043 # define KDE_NO_EXPORT 00044 #endif 00045 00046 typedef void (*kde_sighandler_t) (int); 00047 00048 #ifdef __i386__ 00049 static jmp_buf KDE_NO_EXPORT env; 00050 00051 // Sighandler for the SSE OS support check 00052 static void KDE_NO_EXPORT sighandler( int ) 00053 { 00054 std::longjmp( env, 1 ); 00055 } 00056 #endif 00057 00058 #ifdef __PPC__ 00059 static sigjmp_buf KDE_NO_EXPORT jmpbuf; 00060 static sig_atomic_t KDE_NO_EXPORT canjump = 0; 00061 00062 static void KDE_NO_EXPORT sigill_handler( int sig ) 00063 { 00064 if ( !canjump ) { 00065 signal( sig, SIG_DFL ); 00066 raise( sig ); 00067 } 00068 canjump = 0; 00069 siglongjmp( jmpbuf, 1 ); 00070 } 00071 #endif 00072 00073 static int KDE_NO_EXPORT getCpuFeatures() 00074 { 00075 int features = 0; 00076 00077 #if defined( HAVE_GNU_INLINE_ASM ) 00078 #if defined( __i386__ ) 00079 bool haveCPUID = false; 00080 bool have3DNOW = false; 00081 int result = 0; 00082 00083 // First check if the CPU supports the CPUID instruction 00084 __asm__ __volatile__( 00085 // Try to toggle the CPUID bit in the EFLAGS register 00086 "pushf \n\t" // Push the EFLAGS register onto the stack 00087 "popl %%ecx \n\t" // Pop the value into ECX 00088 "movl %%ecx, %%edx \n\t" // Copy ECX to EDX 00089 "xorl $0x00200000, %%ecx \n\t" // Toggle bit 21 (CPUID) in ECX 00090 "pushl %%ecx \n\t" // Push the modified value onto the stack 00091 "popf \n\t" // Pop it back into EFLAGS 00092 00093 // Check if the CPUID bit was successfully toggled 00094 "pushf \n\t" // Push EFLAGS back onto the stack 00095 "popl %%ecx \n\t" // Pop the value into ECX 00096 "xorl %%eax, %%eax \n\t" // Zero out the EAX register 00097 "cmpl %%ecx, %%edx \n\t" // Compare ECX with EDX 00098 "je .Lno_cpuid_support%= \n\t" // Jump if they're identical 00099 "movl $1, %%eax \n\t" // Set EAX to true 00100 ".Lno_cpuid_support%=: \n\t" 00101 : "=a"(haveCPUID) : : "%ecx", "%edx" ); 00102 00103 // If we don't have CPUID we won't have the other extensions either 00104 if ( ! haveCPUID ) 00105 return 0L; 00106 00107 // Execute CPUID with the feature request bit set 00108 __asm__ __volatile__( 00109 "pushl %%ebx \n\t" // Save EBX 00110 "movl $1, %%eax \n\t" // Set EAX to 1 (features request) 00111 "cpuid \n\t" // Call CPUID 00112 "popl %%ebx \n\t" // Restore EBX 00113 : "=d"(result) : : "%eax", "%ecx" ); 00114 00115 // Test bit 23 (MMX support) 00116 if ( result & 0x00800000 ) 00117 features |= KCPUInfo::IntelMMX; 00118 00119 __asm__ __volatile__( 00120 "pushl %%ebx \n\t" 00121 "movl $0x80000000, %%eax \n\t" 00122 "cpuid \n\t" 00123 "cmpl $0x80000000, %%eax \n\t" 00124 "jbe .Lno_extended%= \n\t" 00125 "movl $0x80000001, %%eax \n\t" 00126 "cpuid \n\t" 00127 "test $0x80000000, %%edx \n\t" 00128 "jz .Lno_extended%= \n\t" 00129 "movl $1, %%eax \n\t" // // Set EAX to true 00130 ".Lno_extended%=: \n\t" 00131 "popl %%ebx \n\t" // Restore EBX 00132 : "=a"(have3DNOW) : ); 00133 00134 if ( have3DNOW ) 00135 features |= KCPUInfo::AMD3DNOW; 00136 00137 #ifdef HAVE_X86_SSE 00138 // Test bit 25 (SSE support) 00139 if ( result & 0x00200000 ) { 00140 features |= KCPUInfo::IntelSSE; 00141 00142 // OS support test for SSE. 00143 // Install our own sighandler for SIGILL. 00144 kde_sighandler_t oldhandler = std::signal( SIGILL, sighandler ); 00145 00146 // Try executing an SSE insn to see if we get a SIGILL 00147 if ( setjmp( env ) ) 00148 features ^= KCPUInfo::IntelSSE; // The OS support test failed 00149 else 00150 __asm__ __volatile__("xorps %xmm0, %xmm0"); 00151 00152 // Restore the default sighandler 00153 std::signal( SIGILL, oldhandler ); 00154 00155 // Test bit 26 (SSE2 support) 00156 if ( (result & 0x00400000) && (features & KCPUInfo::IntelSSE) ) 00157 features |= KCPUInfo::IntelSSE2; 00158 00159 // Note: The OS requirements for SSE2 are the same as for SSE 00160 // so we don't have to do any additional tests for that. 00161 } 00162 #endif // HAVE_X86_SSE 00163 #elif defined __PPC__ && defined HAVE_PPC_ALTIVEC 00164 signal( SIGILL, sigill_handler ); 00165 if ( sigsetjmp( jmpbuf, 1 ) ) { 00166 signal( SIGILL, SIG_DFL ); 00167 } else { 00168 canjump = 1; 00169 __asm__ __volatile__( "mtspr 256, %0\n\t" 00170 "vand %%v0, %%v0, %%v0" 00171 : /* none */ 00172 : "r" (-1) ); 00173 signal( SIGILL, SIG_DFL ); 00174 features |= KCPUInfo::AltiVec; 00175 } 00176 #endif // __i386__ 00177 #endif //HAVE_GNU_INLINE_ASM 00178 00179 return features; 00180 } 00181 00182 unsigned int KCPUInfo::s_features = getCpuFeatures(); 00183 00184
KDE Logo
This file is part of the documentation for kdefx Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:39:51 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003