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.
char ** ppsz_argv; /* command line arguments */
char ** ppsz_env; /* environment variables */
char * psz_arg0; /* program name (whithout path) */
char ** ppsz_argv; /* command line arguments */
char ** ppsz_env; /* environment variables */
char * psz_arg0; /* program name (whithout path) */
+ int i_cpu_capabilities; /* CPU extensions */
/* Generic settings */
boolean_t b_audio; /* is audio output allowed ? */
/* Generic settings */
boolean_t b_audio; /* is audio output allowed ? */
*****************************************************************************/
#define CPU_CAPABILITY_NONE 0
*****************************************************************************/
#define CPU_CAPABILITY_NONE 0
-#define CPU_CAPABILITY_MMX 1<<0
-#define CPU_CAPABILITY_3DNOW 1<<1
-#define CPU_CAPABILITY_MMXEXT 1<<2
-
-#define cpuid( a, eax, ebx, ecx, edx ) \
- asm volatile ( "pushl %%ebx \n\
- cpuid \n\
- popl %%ebx" \
- : "=a" ( eax ), \
- "=c" ( ecx ), \
- "=d" ( edx ) \
- : "a" ( a ) \
- : "cc" );
+#define CPU_CAPABILITY_486 1<<0
+#define CPU_CAPABILITY_586 1<<1
+#define CPU_CAPABILITY_PPRO 1<<2
+#define CPU_CAPABILITY_MMX 1<<3
+#define CPU_CAPABILITY_3DNOW 1<<4
+#define CPU_CAPABILITY_MMXEXT 1<<5
/*****************************************************************************
* TestVersion: tests if the given string equals the current version
/*****************************************************************************
* TestVersion: tests if the given string equals the current version
int TestVersion( char * psz_version );
int TestProgram( char * psz_program );
int TestMethod( char * psz_var, char * psz_method );
int TestVersion( char * psz_version );
int TestProgram( char * psz_program );
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__
- return( CPU_CAPABILITY_NONE );
-#else
- int i_reg, i_dummy = 0;
+ int i_capabilities = CPU_CAPABILITY_NONE;
+#ifdef __i386__
+ int i_eax, i_ebx, i_ecx, i_edx;
+ 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
popl %%eax
asm volatile ( "pushfl
popl %%eax
- movl %%eax, %%ecx
- xorl $0x40000, %%eax
+ movl %%eax, %%ebx
+ xorl $0x200000, %%eax
- popl %%eax
- xorl %%ecx, %%eax
- andl $0x40000, %%eax"
- : "=a" ( i_reg ) );
+ popl %%eax"
+ : "=a" ( i_eax ),
+ "=b" ( i_ebx )
+ :
+ : "cc" );
- return( CPU_CAPABILITY_NONE );
+ return( i_capabilities );
- /* test for a 486 CPU */
- asm volatile ( "movl %%ecx, %%eax
- xorl $0x200000, %%eax
- pushl %%eax
- popfl
- pushfl
- popl %%eax
- xorl %%ecx, %%eax
- pushl %%ecx
- popfl
- andl $0x200000, %%eax"
- : "=a" ( i_reg ) );
+ i_capabilities |= CPU_CAPABILITY_486;
+
+ /* the CPU supports the CPUID instruction - get its level */
+ cpuid( 0x00000000 );
- return( CPU_CAPABILITY_NONE );
+ return( i_capabilities );
- /* the CPU supports the CPUID instruction - get its level */
- cpuid( 0, i_reg, i_dummy, i_dummy, i_dummy );
+ /* FIXME: this isn't correct, since some 486s have cpuid */
+ 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_edx & 0x00800000) )
- return( CPU_CAPABILITY_NONE );
+ return( i_capabilities );
- /* test for the MMX flag */
- cpuid( 1, i_dummy, i_dummy, i_dummy, i_reg );
+ i_capabilities |= CPU_CAPABILITY_MMX;
+
+ 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;
- return( CPU_CAPABILITY_MMX );
-#endif
+ return( i_capabilities );
* idctmmx.c : MMX IDCT module
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* idctmmx.c : MMX IDCT module
*****************************************************************************
* 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>
*
*****************************************************************************/
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" ) )
{
* idctmmxext.c : MMX EXT IDCT module
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* idctmmxext.c : MMX EXT IDCT module
*****************************************************************************
* 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 $
*****************************************************************************/
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" ) )
{
static int yuv_Probe( probedata_t *p_data )
{
/* Test for MMX support in the CPU */
static int yuv_Probe( probedata_t *p_data )
{
/* 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" ) )
{
+ 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
+
- if( !( TestCPU() & CPU_CAPABILITY_MMX ) )
+ if( ! TestCPU( CPU_CAPABILITY_MMX ) )
- fprintf( stderr, "Sorry, this program needs an MMX processor. "
- "Please run the non-MMX version.\n" );
+ fprintf( stderr, "Sorry, this program needs MMX extensions.\n"
+ "Please try a version without MMX support.\n" );
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 );
+}
+