kdefx Library: kcpuinfo.cpp Source File (kdefx Library)

| # kdefx Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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/kdemacros.h
    00040 #if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 > 4)
    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 env;
    00050
    00051 // Sighandler for the SSE OS support check
    00052 static void 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 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

This file is part of the documentation for kdefx Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:17:09 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003