shithub: openh264

ref: 99faf1ec4a47c5362a6bde552d6097166e2fda16
dir: /processing/src/common/cpu.cpp/

View raw version
/*!
 * \copy
 *     Copyright (c)  2009-2013, Cisco Systems
 *     All rights reserved.
 *
 *     Redistribution and use in source and binary forms, with or without
 *     modification, are permitted provided that the following conditions
 *     are met:
 *
 *        * Redistributions of source code must retain the above copyright
 *          notice, this list of conditions and the following disclaimer.
 *
 *        * Redistributions in binary form must reproduce the above copyright
 *          notice, this list of conditions and the following disclaimer in
 *          the documentation and/or other materials provided with the
 *          distribution.
 *
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *     POSSIBILITY OF SUCH DAMAGE.
 *
 * \file	cpu.c
 *
 * \brief	CPU compatibility detection
 *
 * \date	04/29/2009 Created
 *
 *************************************************************************************
 */

#include "util.h"
#include "cpu.h"

WELSVP_NAMESPACE_BEGIN

#define    CPU_Vender_AMD    "AuthenticAMD"
#define    CPU_Vender_INTEL  "GenuineIntel"
#define    CPU_Vender_CYRIX  "CyrixInstead"


#if defined(X86_ASM)

uint32_t WelsCPUFeatureDetect( int32_t *pNumberOfLogicProcessors )
{
    uint32_t uiCPU = 0;	
    uint32_t uiFeatureA = 0, uiFeatureB = 0, uiFeatureC = 0, uiFeatureD = 0;
	int32_t  CacheLineSize = 0;
	int8_t   chVenderName[16] = { 0 };	
	
    if( !WelsCPUIdVerify() )
    {
        /* cpuid is not supported in cpu */
        return 0;
    }
	
	WelsCPUId( 0, &uiFeatureA, (uint32_t*)&chVenderName[0],(uint32_t*)&chVenderName[8],(uint32_t*)&chVenderName[4] );
    if( uiFeatureA == 0 )
    {
		/* maximum input value for basic cpuid information */
        return 0;
    }
	
	WelsCPUId( 1, &uiFeatureA, &uiFeatureB, &uiFeatureC, &uiFeatureD );
    if( (uiFeatureD & 0x00800000) == 0 )
    {
        /* Basic MMX technology is not support in cpu, mean nothing for us so return here */
        return 0;
    }
	
    uiCPU = WELS_CPU_MMX;
    if( uiFeatureD & 0x02000000 )
    {
        /* SSE technology is identical to AMD MMX extensions */
        uiCPU |= WELS_CPU_MMXEXT|WELS_CPU_SSE;
    }
    if( uiFeatureD & 0x04000000 )
    {
        /* SSE2 support here */
        uiCPU |= WELS_CPU_SSE2;
    }
	if ( uiFeatureD & 0x00000001 )
	{
		/* x87 FPU on-chip checking */
		uiCPU |= WELS_CPU_FPU;
	}
	if ( uiFeatureD & 0x00008000 )
	{
		/* CMOV instruction checking */
		uiCPU |= WELS_CPU_CMOV;
	}
	if ( !strcmp((const str_t*)chVenderName,CPU_Vender_INTEL) )	// confirmed_safe_unsafe_usage
	{
		if ( uiFeatureD & 0x10000000 )
		{
			/* Multi-Threading checking: contains of multiple logic processors */
			uiCPU |= WELS_CPU_HTT;
		}
	}	

	if( uiFeatureC & 0x00000001 ){
		/* SSE3 support here */
		uiCPU |= WELS_CPU_SSE3;
	}
	if( uiFeatureC & 0x00000200 ){
		/* SSSE3 support here */
		uiCPU |= WELS_CPU_SSSE3;
	}
	if( uiFeatureC & 0x00080000 ){
		/* SSE4.1 support here, 45nm Penryn processor */
		uiCPU |= WELS_CPU_SSE41; 
	}
	if( uiFeatureC & 0x00100000 ){
		/* SSE4.2 support here, next generation Nehalem processor */
		uiCPU |= WELS_CPU_SSE42;
	}
	if ( WelsCPUSupportAVX( uiFeatureA, uiFeatureC ) )	// 
	{
		/* AVX supported */
		uiCPU |= WELS_CPU_AVX;
	}
	if ( WelsCPUSupportFMA( uiFeatureA, uiFeatureC ) )	// 
	{
		/* AVX FMA supported */
		uiCPU |= WELS_CPU_FMA;
	}
	if ( uiFeatureC & 0x02000000 )
	{
		/* AES checking */
		uiCPU |= WELS_CPU_AES;
	}
	if ( uiFeatureC & 0x00400000 )
	{
		/* MOVBE checking */
		uiCPU |= WELS_CPU_MOVBE;
	}

	if ( pNumberOfLogicProcessors != NULL )
	{
		// HTT enabled on chip
		*pNumberOfLogicProcessors = (uiFeatureB & 0x00ff0000) >> 16; // feature bits: 23-16 on returned EBX		
	}	
	
    WelsCPUId( 0x80000000, &uiFeatureA, &uiFeatureB, &uiFeatureC, &uiFeatureD );

	if( (!strcmp((const str_t*)chVenderName,CPU_Vender_AMD)) && (uiFeatureA>=0x80000001) ){	// confirmed_safe_unsafe_usage
		WelsCPUId(0x80000001, &uiFeatureA, &uiFeatureB, &uiFeatureC, &uiFeatureD );
		if( uiFeatureD&0x00400000 ){
			uiCPU |= WELS_CPU_MMXEXT;
		}
		if( uiFeatureD&0x80000000 ){
			uiCPU |= WELS_CPU_3DNOW;
		}
	}

	if( !strcmp((const str_t*)chVenderName,CPU_Vender_INTEL) ){	// confirmed_safe_unsafe_usage
		int32_t  family, model;

		WelsCPUId(1, &uiFeatureA, &uiFeatureB, &uiFeatureC, &uiFeatureD);
		family = ((uiFeatureA>>8)&0xf) + ((uiFeatureA>>20)&0xff);
        model  = ((uiFeatureA>>4)&0xf) + ((uiFeatureA>>12)&0xf0);

		if( (family==6) && (model==9 || model==13 || model==14) ){
			uiCPU &= ~(WELS_CPU_SSE2|WELS_CPU_SSE3);
		}
	}

	// get cache line size
	if( (!strcmp((const str_t*)chVenderName,CPU_Vender_INTEL)) || !(strcmp((const str_t*)chVenderName,CPU_Vender_CYRIX)) ){	// confirmed_safe_unsafe_usage
		WelsCPUId(1, &uiFeatureA, &uiFeatureB, &uiFeatureC, &uiFeatureD);

		CacheLineSize = (uiFeatureB&0xff00)>>5;	// ((clflush_line_size >> 8) << 3), CLFLUSH_line_size * 8 = CacheLineSize_in_byte

		if( CacheLineSize == 128 ){
			uiCPU |= WELS_CPU_CACHELINE_128;
		}
		else if( CacheLineSize == 64 ){
			uiCPU |= WELS_CPU_CACHELINE_64;
		}
		else if( CacheLineSize == 32 ){
			uiCPU |= WELS_CPU_CACHELINE_32;
		}
		else if( CacheLineSize == 16 ){
			uiCPU |= WELS_CPU_CACHELINE_16;
		}
	}
	
    return uiCPU;
}


void WelsCPURestore( const uint32_t kuiCPU )
{
    if( kuiCPU & (WELS_CPU_MMX|WELS_CPU_MMXEXT|WELS_CPU_3DNOW|WELS_CPU_3DNOWEXT) )
    {
        WelsEmms();
    }
}

#endif


WELSVP_NAMESPACE_END