X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fcpu.c;h=2e0b218a0d1a119a4fabb4ba3aea399541f842db;hb=15e4046f07eb5eb9daf1907c2b1c3f2ce5aae791;hp=4df79dc17189c223fba0162e1e214c7fccdff520;hpb=b9e9cb420db33d098d3d9edea1f3e9d84d5fb18f;p=vlc diff --git a/src/misc/cpu.c b/src/misc/cpu.c index 4df79dc171..2e0b218a0d 100644 --- a/src/misc/cpu.c +++ b/src/misc/cpu.c @@ -1,8 +1,8 @@ /***************************************************************************** * cpu.c: CPU detection code ***************************************************************************** - * Copyright (C) 1998-2002 VideoLAN - * $Id: cpu.c,v 1.4 2002/06/07 14:30:41 sam Exp $ + * Copyright (C) 1998-2004 the VideoLAN team + * $Id$ * * Authors: Samuel Hocevar * Christophe Massiot @@ -20,116 +20,118 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* SIGHUP, SIGINT, SIGKILL */ -#include /* longjmp, setjmp */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include -#ifdef SYS_DARWIN -# include /* AltiVec detection */ -# include /* some day the header files||compiler * - will define it for us */ -# include +#ifdef HAVE_SIGNAL_H +# include /* SIGHUP, SIGINT, SIGKILL */ +# include /* longjmp, setjmp */ #endif -#include "vlc_cpu.h" +#include "libvlc.h" + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__)) +#include +#endif /***************************************************************************** * Local prototypes *****************************************************************************/ -static void IllegalSignalHandler( int i_signal ); +#ifdef HAVE_SIGNAL_H +static void SigHandler ( int ); +#endif /***************************************************************************** * Global variables - they're needed for signal handling *****************************************************************************/ +#ifdef HAVE_SIGNAL_H static jmp_buf env; static int i_illegal; -#if defined( __i386__ ) -static char *psz_capability; +#if defined( __i386__ ) || defined( __x86_64__ ) +static const char *psz_capability; +#endif #endif /***************************************************************************** - * CPUCapabilities: list the processors MMX support and other capabilities + * CPUCapabilities: get the CPU capabilities ***************************************************************************** * This function is called to list extensions the CPU may have. *****************************************************************************/ -u32 __CPUCapabilities( vlc_object_t *p_this ) +uint32_t CPUCapabilities( void ) { - volatile u32 i_capabilities = CPU_CAPABILITY_NONE; - -#if defined( SYS_DARWIN ) - struct host_basic_info hi; - kern_return_t ret; - host_name_port_t host; + volatile uint32_t i_capabilities = CPU_CAPABILITY_NONE; - int i_size; - char *psz_name, *psz_subname; +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__)) + int selectors[2] = { CTL_HW, HW_VECTORUNIT }; + int i_has_altivec = 0; + size_t i_length = sizeof( i_has_altivec ); + int i_error = sysctl( selectors, 2, &i_has_altivec, &i_length, NULL, 0); i_capabilities |= CPU_CAPABILITY_FPU; - /* Should 'never' fail? */ - host = mach_host_self(); - - i_size = sizeof( hi ) / sizeof( int ); - ret = host_info( host, HOST_BASIC_INFO, ( host_info_t )&hi, &i_size ); - - if( ret != KERN_SUCCESS ) - { - fprintf( stderr, "error: couldn't get CPU information\n" ); - return i_capabilities; - } - - slot_name( hi.cpu_type, hi.cpu_subtype, &psz_name, &psz_subname ); - /* FIXME: need better way to detect newer proccessors. - * could do strncmp(a,b,5), but that's real ugly */ - if( !strcmp(psz_name, "ppc7400") || !strcmp(psz_name, "ppc7450") ) - { + if( i_error == 0 && i_has_altivec != 0 ) i_capabilities |= CPU_CAPABILITY_ALTIVEC; - } return i_capabilities; -#elif defined( __i386__ ) +#elif defined( __i386__ ) || defined( __x86_64__ ) volatile unsigned int i_eax, i_ebx, i_ecx, i_edx; volatile vlc_bool_t b_amd; /* Needed for x86 CPU capabilities detection */ -# define cpuid( a ) \ - asm volatile ( "pushl %%ebx\n\t" \ - "cpuid\n\t" \ - "movl %%ebx,%1\n\t" \ - "popl %%ebx\n\t" \ - : "=a" ( i_eax ), \ - "=r" ( i_ebx ), \ - "=c" ( i_ecx ), \ - "=d" ( i_edx ) \ - : "a" ( a ) \ - : "cc" ); - - i_capabilities |= CPU_CAPABILITY_FPU; +# if defined( __x86_64__ ) +# define cpuid( reg ) \ + asm volatile ( "cpuid\n\t" \ + "movl %%ebx,%1\n\t" \ + : "=a" ( i_eax ), \ + "=b" ( i_ebx ), \ + "=c" ( i_ecx ), \ + "=d" ( i_edx ) \ + : "a" ( reg ) \ + : "cc" ); +# else +# define cpuid( reg ) \ + asm volatile ( "push %%ebx\n\t" \ + "cpuid\n\t" \ + "movl %%ebx,%1\n\t" \ + "pop %%ebx\n\t" \ + : "=a" ( i_eax ), \ + "=r" ( i_ebx ), \ + "=c" ( i_ecx ), \ + "=d" ( i_edx ) \ + : "a" ( reg ) \ + : "cc" ); +# endif -# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) - signal( SIGILL, IllegalSignalHandler ); +# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) \ + && defined( HAVE_SIGNAL_H ) + void (*pf_sigill) (int) = signal( SIGILL, SigHandler ); # endif - /* test for a 486 CPU */ - asm volatile ( "pushl %%ebx\n\t" - "pushfl\n\t" - "popl %%eax\n\t" + i_capabilities |= CPU_CAPABILITY_FPU; + +# if defined( __i386__ ) + /* check if cpuid instruction is supported */ + asm volatile ( "push %%ebx\n\t" + "pushf\n\t" + "pop %%eax\n\t" "movl %%eax, %%ebx\n\t" "xorl $0x200000, %%eax\n\t" - "pushl %%eax\n\t" - "popfl\n\t" - "pushfl\n\t" - "popl %%eax\n\t" + "push %%eax\n\t" + "popf\n\t" + "pushf\n\t" + "pop %%eax\n\t" "movl %%ebx,%1\n\t" - "popl %%ebx\n\t" + "pop %%ebx\n\t" : "=a" ( i_eax ), "=r" ( i_ebx ) : @@ -137,11 +139,15 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) if( i_eax == i_ebx ) { -# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) - signal( SIGILL, NULL ); -# endif +# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) \ + && defined( HAVE_SIGNAL_H ) + signal( SIGILL, pf_sigill ); +# endif return i_capabilities; } +# else + /* x86_64 supports cpuid instruction, so we dont need to check it */ +# endif i_capabilities |= CPU_CAPABILITY_486; @@ -150,8 +156,9 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) if( !i_eax ) { -# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) - signal( SIGILL, NULL ); +# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) \ + && defined( HAVE_SIGNAL_H ) + signal( SIGILL, pf_sigill ); # endif return i_capabilities; } @@ -168,8 +175,9 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) if( ! (i_edx & 0x00800000) ) { -# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) - signal( SIGILL, NULL ); +# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) \ + && defined( HAVE_SIGNAL_H ) + signal( SIGILL, pf_sigill ); # endif return i_capabilities; } @@ -185,13 +193,11 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) psz_capability = "SSE"; i_illegal = 0; - vlc_mutex_lock( p_this->p_vlc->p_global_lock ); if( setjmp( env ) == 0 ) { /* Test a SSE instruction */ __asm__ __volatile__ ( "xorps %%xmm0,%%xmm0\n" : : ); } - vlc_mutex_unlock( p_this->p_vlc->p_global_lock ); if( i_illegal == 0 ) { @@ -200,13 +206,34 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) # endif } + if( i_edx & 0x04000000 ) + { +# if defined(CAN_COMPILE_SSE) + /* We test if OS supports the SSE instructions */ + psz_capability = "SSE2"; + i_illegal = 0; + + if( setjmp( env ) == 0 ) + { + /* Test a SSE2 instruction */ + __asm__ __volatile__ ( "movupd %%xmm0, %%xmm0\n" : : ); + } + + if( i_illegal == 0 ) + { + i_capabilities |= CPU_CAPABILITY_SSE2; + } +# endif + } + /* test for additional capabilities */ cpuid( 0x80000000 ); if( i_eax < 0x80000001 ) { -# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) - signal( SIGILL, NULL ); +# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) \ + && defined( HAVE_SIGNAL_H ) + signal( SIGILL, pf_sigill ); # endif return i_capabilities; } @@ -220,13 +247,11 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) psz_capability = "3D Now!"; i_illegal = 0; - vlc_mutex_lock( p_this->p_vlc->p_global_lock ); if( setjmp( env ) == 0 ) { /* Test a 3D Now! instruction */ __asm__ __volatile__ ( "pfadd %%mm0,%%mm0\n" "femms\n" : : ); } - vlc_mutex_unlock( p_this->p_vlc->p_global_lock ); if( i_illegal == 0 ) { @@ -240,21 +265,21 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) i_capabilities |= CPU_CAPABILITY_MMXEXT; } -# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) - signal( SIGILL, NULL ); +# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW ) \ + && defined( HAVE_SIGNAL_H ) + signal( SIGILL, pf_sigill ); # endif return i_capabilities; -#elif defined( __powerpc__ ) +#elif defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ ) - i_capabilities |= CPU_CAPABILITY_FPU; +# ifdef CAN_COMPILE_ALTIVEC && defined( HAVE_SIGNAL_H ) + void (*pf_sigill) (int) = signal( SIGILL, SigHandler ); -# ifdef CAN_COMPILE_ALTIVEC - signal( SIGILL, IllegalSignalHandler ); + i_capabilities |= CPU_CAPABILITY_FPU; i_illegal = 0; - vlc_mutex_lock( p_this->p_vlc->p_global_lock ); if( setjmp( env ) == 0 ) { asm volatile ("mtspr 256, %0\n\t" @@ -262,14 +287,13 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) : : "r" (-1)); } - vlc_mutex_unlock( p_this->p_vlc->p_global_lock ); if( i_illegal == 0 ) { i_capabilities |= CPU_CAPABILITY_ALTIVEC; } - signal( SIGILL, NULL ); + signal( SIGILL, pf_sigill ); # endif return i_capabilities; @@ -279,6 +303,10 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) i_capabilities |= CPU_CAPABILITY_FPU; return i_capabilities; +#elif defined( _MSC_VER ) && !defined( UNDER_CE ) + i_capabilities |= CPU_CAPABILITY_FPU; + return i_capabilities; + #else /* default behaviour */ return i_capabilities; @@ -287,12 +315,13 @@ u32 __CPUCapabilities( vlc_object_t *p_this ) } /***************************************************************************** - * IllegalSignalHandler: system signal handler + * SigHandler: system signal handler ***************************************************************************** * This function is called when an illegal instruction signal is received by * the program. We use this function to test OS and CPU capabilities *****************************************************************************/ -static void IllegalSignalHandler( int i_signal ) +#if defined( HAVE_SIGNAL_H ) +static void SigHandler( int i_signal ) { /* Acknowledge the signal received */ i_illegal = 1; @@ -313,4 +342,17 @@ static void IllegalSignalHandler( int i_signal ) longjmp( env, 1 ); } +#endif + + +uint32_t cpu_flags = 0; + + +/***************************************************************************** + * vlc_CPU: get pre-computed CPU capability flags + ****************************************************************************/ +unsigned vlc_CPU (void) +{ + return cpu_flags; +}