Commit ba59eb04 authored by Sam Hocevar's avatar Sam Hocevar

. a few changes in the CPU extensions detection code, borrowed from the

   kernel and from mpeg2dec. I still don't know how to detect if code
   compiled with -mcpu=pentiumpro will run, since the cpuid arcanes are
   quite obtuse to me. Perhaps we should also have a way not to load modules
   if they have been compiled with a different CPU to avoid segfaults.
parent 5464102f
...@@ -39,6 +39,7 @@ typedef struct ...@@ -39,6 +39,7 @@ typedef struct
char ** ppsz_argv; /* command line arguments */ char ** ppsz_argv; /* command line arguments */
char ** ppsz_env; /* environment variables */ char ** ppsz_env; /* environment variables */
char * psz_arg0; /* program name (whithout path) */ char * psz_arg0; /* program name (whithout path) */
int i_cpu_capabilities; /* CPU extensions */
/* Generic settings */ /* Generic settings */
boolean_t b_audio; /* is audio output allowed ? */ boolean_t b_audio; /* is audio output allowed ? */
......
...@@ -21,19 +21,12 @@ ...@@ -21,19 +21,12 @@
*****************************************************************************/ *****************************************************************************/
#define CPU_CAPABILITY_NONE 0 #define CPU_CAPABILITY_NONE 0
#define CPU_CAPABILITY_MMX 1<<0 #define CPU_CAPABILITY_486 1<<0
#define CPU_CAPABILITY_3DNOW 1<<1 #define CPU_CAPABILITY_586 1<<1
#define CPU_CAPABILITY_MMXEXT 1<<2 #define CPU_CAPABILITY_PPRO 1<<2
#define CPU_CAPABILITY_MMX 1<<3
#define cpuid( a, eax, ebx, ecx, edx ) \ #define CPU_CAPABILITY_3DNOW 1<<4
asm volatile ( "pushl %%ebx \n\ #define CPU_CAPABILITY_MMXEXT 1<<5
cpuid \n\
popl %%ebx" \
: "=a" ( eax ), \
"=c" ( ecx ), \
"=d" ( edx ) \
: "a" ( a ) \
: "cc" );
/***************************************************************************** /*****************************************************************************
* TestVersion: tests if the given string equals the current version * TestVersion: tests if the given string equals the current version
...@@ -41,72 +34,102 @@ ...@@ -41,72 +34,102 @@
int TestVersion( char * psz_version ); int TestVersion( char * psz_version );
int TestProgram( char * psz_program ); int TestProgram( char * psz_program );
int TestMethod( char * psz_var, char * psz_method ); int TestMethod( char * psz_var, char * psz_method );
int TestCPU( int i_capabilities );
/***************************************************************************** /*****************************************************************************
* TestCPU: tests if the processor has MMX support and other capabilities * CPUCapabilities: list the processors MMX support and other capabilities
***************************************************************************** *****************************************************************************
* This function is called to check extensions the CPU may have. * This function is called to list extensions the CPU may have.
*****************************************************************************/ *****************************************************************************/
static __inline__ int TestCPU( void ) static __inline__ int CPUCapabilities( void )
{ {
#ifndef __i386__ int i_capabilities = CPU_CAPABILITY_NONE;
return( CPU_CAPABILITY_NONE ); #ifdef __i386__
#else int i_eax, i_ebx, i_ecx, i_edx;
int i_reg, i_dummy = 0; boolean_t b_amd;
#define cpuid( a ) \
asm volatile ( "cpuid" \
: "=a" ( i_eax ), \
"=b" ( i_ebx ), \
"=c" ( i_ecx ), \
"=d" ( i_edx ) \
: "a" ( a ) \
: "cc" ); \
/* test for a 386 CPU */ /* test for a 486 CPU */
asm volatile ( "pushfl asm volatile ( "pushfl
popl %%eax popl %%eax
movl %%eax, %%ecx movl %%eax, %%ebx
xorl $0x40000, %%eax xorl $0x200000, %%eax
pushl %%eax pushl %%eax
popfl popfl
pushfl pushfl
popl %%eax popl %%eax"
xorl %%ecx, %%eax : "=a" ( i_eax ),
andl $0x40000, %%eax" "=b" ( i_ebx )
: "=a" ( i_reg ) ); :
: "cc" );
if( !i_reg ) if( i_eax == i_ebx )
{ {
return( CPU_CAPABILITY_NONE ); return( i_capabilities );
} }
/* test for a 486 CPU */ i_capabilities |= CPU_CAPABILITY_486;
asm volatile ( "movl %%ecx, %%eax
xorl $0x200000, %%eax /* the CPU supports the CPUID instruction - get its level */
pushl %%eax cpuid( 0x00000000 );
popfl
pushfl
popl %%eax
xorl %%ecx, %%eax
pushl %%ecx
popfl
andl $0x200000, %%eax"
: "=a" ( i_reg ) );
if( !i_reg ) if( !i_eax )
{ {
return( CPU_CAPABILITY_NONE ); return( i_capabilities );
} }
/* the CPU supports the CPUID instruction - get its level */ /* FIXME: this isn't correct, since some 486s have cpuid */
cpuid( 0, i_reg, i_dummy, i_dummy, i_dummy ); i_capabilities |= CPU_CAPABILITY_586;
/* borrowed from mpeg2dec */
b_amd = ( i_ebx == 0x68747541 ) && ( i_ecx == 0x444d4163 )
&& ( i_edx == 0x69746e65 );
/* test for the MMX flag */
cpuid( 0x00000001 );
if( !i_reg ) if( ! (i_edx & 0x00800000) )
{ {
return( CPU_CAPABILITY_NONE ); return( i_capabilities );
} }
/* test for the MMX flag */ i_capabilities |= CPU_CAPABILITY_MMX;
cpuid( 1, i_dummy, i_dummy, i_dummy, i_reg );
if( i_edx & 0x02000000 )
{
i_capabilities |= CPU_CAPABILITY_MMXEXT;
}
/* test for additional capabilities */
cpuid( 0x80000000 );
if( i_eax < 0x80000001 )
{
return( i_capabilities );
}
/* list these additional capabilities */
cpuid( 0x80000001 );
if( i_edx & 0x80000000 )
{
i_capabilities |= CPU_CAPABILITY_3DNOW;
}
if( ! (i_reg & 0x00800000) ) if( b_amd && ( i_edx & 0x00400000 ) )
{ {
return( CPU_CAPABILITY_NONE ); i_capabilities |= CPU_CAPABILITY_MMXEXT;
} }
#endif /* __i386__ */
return( CPU_CAPABILITY_MMX ); return( i_capabilities );
#endif
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* idctmmx.c : MMX IDCT module * idctmmx.c : MMX IDCT module
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: idctmmx.c,v 1.4 2001/01/16 05:04:25 sam Exp $ * $Id: idctmmx.c,v 1.5 2001/01/16 16:09:52 sam Exp $
* *
* Authors: Gaël Hendryckx <jimmy@via.ecp.fr> * Authors: Gaël Hendryckx <jimmy@via.ecp.fr>
* *
...@@ -143,7 +143,7 @@ static void idct_getfunctions( function_list_t * p_function_list ) ...@@ -143,7 +143,7 @@ static void idct_getfunctions( function_list_t * p_function_list )
*****************************************************************************/ *****************************************************************************/
static int idct_Probe( probedata_t *p_data ) static int idct_Probe( probedata_t *p_data )
{ {
if( TestCPU() & CPU_CAPABILITY_MMX ) if( TestCPU( CPU_CAPABILITY_MMX ) )
{ {
if( TestMethod( IDCT_METHOD_VAR, "idctmmx" ) ) if( TestMethod( IDCT_METHOD_VAR, "idctmmx" ) )
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* idctmmxext.c : MMX EXT IDCT module * idctmmxext.c : MMX EXT IDCT module
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: idctmmxext.c,v 1.2 2001/01/16 14:05:38 sam Exp $ * $Id: idctmmxext.c,v 1.3 2001/01/16 16:09:52 sam Exp $
* *
* Authors: * Authors:
* *
...@@ -143,7 +143,7 @@ static void idct_getfunctions( function_list_t * p_function_list ) ...@@ -143,7 +143,7 @@ static void idct_getfunctions( function_list_t * p_function_list )
*****************************************************************************/ *****************************************************************************/
static int idct_Probe( probedata_t *p_data ) static int idct_Probe( probedata_t *p_data )
{ {
if( TestCPU() & CPU_CAPABILITY_MMXEXT ) if( 0/*TestCPU( CPU_CAPABILITY_MMXEXT )*/ )
{ {
if( TestMethod( IDCT_METHOD_VAR, "idctmmxext" ) ) if( TestMethod( IDCT_METHOD_VAR, "idctmmxext" ) )
{ {
......
...@@ -75,7 +75,7 @@ void yuv_getfunctions( function_list_t * p_function_list ) ...@@ -75,7 +75,7 @@ void yuv_getfunctions( function_list_t * p_function_list )
static int yuv_Probe( probedata_t *p_data ) static int yuv_Probe( probedata_t *p_data )
{ {
/* Test for MMX support in the CPU */ /* Test for MMX support in the CPU */
if( TestCPU() & CPU_CAPABILITY_MMX ) if( TestCPU( CPU_CAPABILITY_MMX ) )
{ {
if( TestMethod( YUV_METHOD_VAR, "yuvmmx" ) ) if( TestMethod( YUV_METHOD_VAR, "yuvmmx" ) )
{ {
......
...@@ -191,14 +191,25 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) ...@@ -191,14 +191,25 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
beos_Create(); beos_Create();
#endif #endif
p_main->i_cpu_capabilities = CPUCapabilities();
/* /*
* Test if our code is likely to run on this CPU * Test if our code is likely to run on this CPU
*/ */
#if defined( __pentium__ ) || defined( __pentiumpro__ )
if( ! TestCPU( CPU_CAPABILITY_586 ) )
{
fprintf( stderr, "Sorry, this program needs a Pentium CPU.\n"
"Please try a version without Pentium support.\n" );
return( 1 );
}
#endif
#ifdef HAVE_MMX #ifdef HAVE_MMX
if( !( TestCPU() & CPU_CAPABILITY_MMX ) ) if( ! TestCPU( CPU_CAPABILITY_MMX ) )
{ {
fprintf( stderr, "Sorry, this program needs an MMX processor. " fprintf( stderr, "Sorry, this program needs MMX extensions.\n"
"Please run the non-MMX version.\n" ); "Please try a version without MMX support.\n" );
return( 1 ); return( 1 );
} }
#endif #endif
......
...@@ -58,3 +58,11 @@ int TestMethod( char * psz_var, char * psz_method ) ...@@ -58,3 +58,11 @@ int TestMethod( char * psz_var, char * psz_method )
return( !strcmp( psz_method, main_GetPszVariable( psz_var, "" ) ) ); return( !strcmp( psz_method, main_GetPszVariable( psz_var, "" ) ) );
} }
/*****************************************************************************
* TestCPU: tests if the processor has MMX support and other capabilities
*****************************************************************************/
int TestCPU( int i_capabilities )
{
return( (i_capabilities & p_main->i_cpu_capabilities) == i_capabilities );
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment