• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdefx

kcpuinfo.cpp

Go to the documentation of this file.
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 typedef void (*kde_sighandler_t) (int);
00039 
00040 #ifdef __i386__
00041 static jmp_buf env;
00042 
00043 // Sighandler for the SSE OS support check
00044 static void sighandler( int )
00045 {
00046     std::longjmp( env, 1 );
00047 }
00048 #endif
00049 
00050 #ifdef __PPC__
00051 static sigjmp_buf KDE_NO_EXPORT jmpbuf;
00052 static sig_atomic_t KDE_NO_EXPORT canjump = 0;
00053 
00054 static void KDE_NO_EXPORT sigill_handler( int sig )
00055 {
00056     if ( !canjump ) {
00057         signal( sig, SIG_DFL );
00058         raise( sig );
00059     }
00060     canjump = 0;
00061     siglongjmp( jmpbuf, 1 );
00062 }
00063 #endif
00064 
00065 static int getCpuFeatures()
00066 {
00067     volatile int features = 0;
00068 
00069 #if defined( HAVE_GNU_INLINE_ASM )
00070 #if defined( __i386__ )
00071     bool haveCPUID = false;
00072     bool have3DNOW = false;
00073     int result = 0;
00074 
00075     // First check if the CPU supports the CPUID instruction
00076     __asm__ __volatile__(
00077     // Try to toggle the CPUID bit in the EFLAGS register
00078     "pushf                      \n\t"   // Push the EFLAGS register onto the stack
00079     "popl   %%ecx               \n\t"   // Pop the value into ECX
00080     "movl   %%ecx, %%edx        \n\t"   // Copy ECX to EDX
00081     "xorl   $0x00200000, %%ecx  \n\t"   // Toggle bit 21 (CPUID) in ECX
00082     "pushl  %%ecx               \n\t"   // Push the modified value onto the stack
00083     "popf                       \n\t"   // Pop it back into EFLAGS
00084 
00085     // Check if the CPUID bit was successfully toggled
00086     "pushf                      \n\t"   // Push EFLAGS back onto the stack
00087     "popl   %%ecx               \n\t"   // Pop the value into ECX
00088     "xorl   %%eax, %%eax        \n\t"   // Zero out the EAX register
00089     "cmpl   %%ecx, %%edx        \n\t"   // Compare ECX with EDX
00090     "je    .Lno_cpuid_support%= \n\t"   // Jump if they're identical
00091     "movl      $1, %%eax        \n\t"   // Set EAX to true
00092     ".Lno_cpuid_support%=:      \n\t"
00093     : "=a"(haveCPUID) : : "%ecx", "%edx" );
00094 
00095     // If we don't have CPUID we won't have the other extensions either
00096     if ( ! haveCPUID )
00097         return 0L;
00098 
00099     // Execute CPUID with the feature request bit set
00100     __asm__ __volatile__(
00101     "pushl  %%ebx               \n\t"   // Save EBX
00102     "movl      $1, %%eax        \n\t"   // Set EAX to 1 (features request)
00103     "cpuid                      \n\t"   // Call CPUID
00104     "popl   %%ebx               \n\t"   // Restore EBX
00105     : "=d"(result) : : "%eax", "%ecx" );
00106 
00107     // Test bit 23 (MMX support)
00108     if ( result & 0x00800000 )
00109         features |= KCPUInfo::IntelMMX;
00110 
00111     __asm__ __volatile__(
00112       "pushl %%ebx             \n\t"
00113       "movl $0x80000000, %%eax \n\t"
00114       "cpuid                   \n\t"
00115       "cmpl $0x80000000, %%eax \n\t"
00116       "jbe .Lno_extended%=     \n\t"
00117       "movl $0x80000001, %%eax \n\t"
00118       "cpuid                   \n\t"
00119       "test $0x80000000, %%edx \n\t"
00120       "jz .Lno_extended%=      \n\t"
00121       "movl      $1, %%eax     \n\t"   // // Set EAX to true
00122       ".Lno_extended%=:        \n\t"
00123       "popl   %%ebx            \n\t"   // Restore EBX
00124       : "=a"(have3DNOW) : );
00125 
00126     if ( have3DNOW )
00127         features |= KCPUInfo::AMD3DNOW;
00128 
00129 #ifdef HAVE_X86_SSE
00130     // Test bit 25 (SSE support)
00131     if ( result & 0x00200000 ) {
00132         features |= KCPUInfo::IntelSSE;
00133 
00134         // OS support test for SSE.
00135         // Install our own sighandler for SIGILL.
00136         kde_sighandler_t oldhandler = std::signal( SIGILL, sighandler );
00137 
00138         // Try executing an SSE insn to see if we get a SIGILL
00139         if ( setjmp( env ) )
00140             features ^= KCPUInfo::IntelSSE; // The OS support test failed
00141         else
00142             __asm__ __volatile__("xorps %xmm0, %xmm0");
00143 
00144         // Restore the default sighandler
00145         std::signal( SIGILL, oldhandler );
00146 
00147         // Test bit 26 (SSE2 support)
00148         if ( (result & 0x00400000) && (features & KCPUInfo::IntelSSE) )
00149             features |= KCPUInfo::IntelSSE2;
00150 
00151         // Note: The OS requirements for SSE2 are the same as for SSE
00152         //       so we don't have to do any additional tests for that.
00153     }
00154 #endif // HAVE_X86_SSE
00155 #elif defined __PPC__ && defined HAVE_PPC_ALTIVEC
00156     signal( SIGILL, sigill_handler );
00157     if ( sigsetjmp( jmpbuf, 1 ) ) {
00158         signal( SIGILL, SIG_DFL );
00159     } else {
00160         canjump = 1;
00161         __asm__ __volatile__( "mtspr 256, %0\n\t"
00162                               "vand %%v0, %%v0, %%v0"
00163                               : /* none */
00164                               : "r" (-1) );
00165         signal( SIGILL, SIG_DFL );
00166         features |= KCPUInfo::AltiVec;
00167     }
00168 #endif // __i386__
00169 #endif //HAVE_GNU_INLINE_ASM
00170 
00171     return features;
00172 }
00173 
00174 unsigned int KCPUInfo::s_features = getCpuFeatures();
00175 
00176 

kdefx

Skip menu "kdefx"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal