275 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			275 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //========= Copyright Valve Corporation, All rights reserved. ============//
 | |
| //
 | |
| // Purpose: win32 dependant ASM code for CPU capability detection
 | |
| //
 | |
| // $Workfile:     $
 | |
| // $NoKeywords: $
 | |
| //=============================================================================//
 | |
| 
 | |
| #if defined( _X360 ) || defined( WIN64 )
 | |
| 
 | |
| bool CheckMMXTechnology(void) { return false; }
 | |
| bool CheckSSETechnology(void) { return false; }
 | |
| bool CheckSSE2Technology(void) { return false; }
 | |
| bool Check3DNowTechnology(void) { return false; }
 | |
| 
 | |
| #elif defined( _WIN32 ) && !defined( _X360 )
 | |
| 
 | |
| #pragma optimize( "", off )
 | |
| #pragma warning( disable: 4800 ) //'int' : forcing value to bool 'true' or 'false' (performance warning)
 | |
| 
 | |
| // stuff from windows.h
 | |
| #ifndef EXCEPTION_EXECUTE_HANDLER
 | |
| #define EXCEPTION_EXECUTE_HANDLER       1
 | |
| #endif
 | |
| 
 | |
| bool CheckMMXTechnology(void)
 | |
| {
 | |
|     int retval = true;
 | |
|     unsigned int RegEDX = 0;
 | |
| 
 | |
| #ifdef CPUID
 | |
| 	_asm pushad;
 | |
| #endif
 | |
| 
 | |
|     __try
 | |
| 	{
 | |
|         _asm
 | |
| 		{
 | |
| #ifdef CPUID
 | |
| 			xor edx, edx	// Clue the compiler that EDX is about to be used.
 | |
| #endif
 | |
|             mov eax, 1      // set up CPUID to return processor version and features
 | |
|                             //      0 = vendor string, 1 = version info, 2 = cache info
 | |
|             CPUID           // code bytes = 0fh,  0a2h
 | |
|             mov RegEDX, edx // features returned in edx
 | |
| 		}
 | |
|     } 
 | |
| 	__except(EXCEPTION_EXECUTE_HANDLER) 
 | |
| 	{ 
 | |
| 		retval = false; 
 | |
| 	}
 | |
| 
 | |
| 	// If CPUID not supported, then certainly no MMX extensions.
 | |
|     if (retval)
 | |
| 	{
 | |
| 		if (RegEDX & 0x800000)          // bit 23 is set for MMX technology
 | |
| 		{
 | |
| 		   __try 
 | |
| 		   { 
 | |
| 				// try executing the MMX instruction "emms"
 | |
| 			   _asm EMMS
 | |
| 		   } 
 | |
| 		   __except(EXCEPTION_EXECUTE_HANDLER) 
 | |
| 		   { 
 | |
| 			   retval = false; 
 | |
| 		   }
 | |
| 		}
 | |
| 
 | |
| 		else
 | |
| 			retval = false;           // processor supports CPUID but does not support MMX technology
 | |
| 
 | |
| 		// if retval == 0 here, it means the processor has MMX technology but
 | |
| 		// floating-point emulation is on; so MMX technology is unavailable
 | |
| 	}
 | |
| 
 | |
| #ifdef CPUID
 | |
| 	_asm popad;
 | |
| #endif
 | |
| 
 | |
|     return retval;
 | |
| }
 | |
| 
 | |
| bool CheckSSETechnology(void)
 | |
| {
 | |
|     int retval = true;
 | |
|     unsigned int RegEDX = 0;
 | |
| 
 | |
| #ifdef CPUID
 | |
| 	_asm pushad;
 | |
| #endif
 | |
| 
 | |
| 	// Do we have support for the CPUID function?
 | |
|     __try
 | |
| 	{
 | |
|         _asm
 | |
| 		{
 | |
| #ifdef CPUID
 | |
| 			xor edx, edx			// Clue the compiler that EDX is about to be used.
 | |
| #endif
 | |
|             mov eax, 1				// set up CPUID to return processor version and features
 | |
| 									//      0 = vendor string, 1 = version info, 2 = cache info
 | |
|             CPUID					// code bytes = 0fh,  0a2h
 | |
|             mov RegEDX, edx			// features returned in edx
 | |
| 		}
 | |
|     } 
 | |
| 	__except(EXCEPTION_EXECUTE_HANDLER) 
 | |
| 	{ 
 | |
| 		retval = false; 
 | |
| 	}
 | |
| 
 | |
| 	// If CPUID not supported, then certainly no SSE extensions.
 | |
|     if (retval)
 | |
| 	{
 | |
| 		// Do we have support for SSE in this processor?
 | |
| 		if ( RegEDX & 0x2000000L )		// bit 25 is set for SSE technology
 | |
| 		{
 | |
| 			// Make sure that SSE is supported by executing an inline SSE instruction
 | |
| 
 | |
| // BUGBUG, FIXME - Visual C Version 6.0 does not support SSE inline code YET (No macros from Intel either)
 | |
| // Fix this if VC7 supports inline SSE instructinons like "xorps" as shown below.
 | |
| #if 1
 | |
| 			__try
 | |
| 			{
 | |
| 				_asm
 | |
| 				{
 | |
| 					// Attempt execution of a SSE instruction to make sure OS supports SSE FPU context switches
 | |
| 					xorps xmm0, xmm0
 | |
| 					// This will work on Win2k+ (Including masking SSE FPU exception to "normalized" values)
 | |
| 					// This will work on Win98+ (But no "masking" of FPU exceptions provided)
 | |
| 				}
 | |
| 			} 
 | |
| 			__except(EXCEPTION_EXECUTE_HANDLER) 
 | |
| #endif
 | |
| 
 | |
| 			{ 
 | |
| 				retval = false; 
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 			retval = false;
 | |
| 	}
 | |
| #ifdef CPUID
 | |
| 	_asm popad;
 | |
| #endif
 | |
| 
 | |
|     return retval;
 | |
| }
 | |
| 
 | |
| bool CheckSSE2Technology(void)
 | |
| {
 | |
|     int retval = true;
 | |
|     unsigned int RegEDX = 0;
 | |
| 
 | |
| #ifdef CPUID
 | |
| 	_asm pushad;
 | |
| #endif
 | |
| 
 | |
| 	// Do we have support for the CPUID function?
 | |
|     __try
 | |
| 	{
 | |
|         _asm
 | |
| 		{
 | |
| #ifdef CPUID
 | |
| 			xor edx, edx			// Clue the compiler that EDX is about to be used.
 | |
| #endif
 | |
|             mov eax, 1				// set up CPUID to return processor version and features
 | |
| 									//      0 = vendor string, 1 = version info, 2 = cache info
 | |
|             CPUID					// code bytes = 0fh,  0a2h
 | |
|             mov RegEDX, edx			// features returned in edx
 | |
| 		}
 | |
|     } 
 | |
| 	__except(EXCEPTION_EXECUTE_HANDLER) 
 | |
| 	{ 
 | |
| 		retval = false; 
 | |
| 	}
 | |
| 
 | |
| 	// If CPUID not supported, then certainly no SSE extensions.
 | |
|     if (retval)
 | |
| 	{
 | |
| 		// Do we have support for SSE in this processor?
 | |
| 		if ( RegEDX & 0x04000000 )		// bit 26 is set for SSE2 technology
 | |
| 		{
 | |
| 			// Make sure that SSE is supported by executing an inline SSE instruction
 | |
| 
 | |
| 			__try
 | |
| 			{
 | |
| 				_asm
 | |
| 				{
 | |
| 					// Attempt execution of a SSE2 instruction to make sure OS supports SSE FPU context switches
 | |
| 					xorpd xmm0, xmm0
 | |
| 				}
 | |
| 			} 
 | |
| 			__except(EXCEPTION_EXECUTE_HANDLER) 
 | |
| 
 | |
| 			{ 
 | |
| 				retval = false; 
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 			retval = false;
 | |
| 	}
 | |
| #ifdef CPUID
 | |
| 	_asm popad;
 | |
| #endif
 | |
| 
 | |
|     return retval;
 | |
| }
 | |
| 
 | |
| bool Check3DNowTechnology(void)
 | |
| {
 | |
|     int retval = true;
 | |
|     unsigned int RegEAX = 0;
 | |
| 
 | |
| #ifdef CPUID
 | |
| 	_asm pushad;
 | |
| #endif
 | |
| 
 | |
|     // First see if we can execute CPUID at all
 | |
| 	__try
 | |
| 	{
 | |
|         _asm
 | |
| 		{
 | |
| #ifdef CPUID
 | |
| //			xor edx, edx			// Clue the compiler that EDX is about to be used.
 | |
| #endif
 | |
|             mov eax, 0x80000000     // setup CPUID to return whether AMD >0x80000000 function are supported.
 | |
| 									// 0x80000000 = Highest 0x80000000+ function, 0x80000001 = 3DNow support
 | |
|             CPUID					// code bytes = 0fh,  0a2h
 | |
|             mov RegEAX, eax			// result returned in eax
 | |
| 		}
 | |
|     } 
 | |
| 	__except(EXCEPTION_EXECUTE_HANDLER) 
 | |
| 	{ 
 | |
| 		retval = false; 
 | |
| 	}
 | |
| 
 | |
| 	// If CPUID not supported, then there is definitely no 3DNow support
 | |
|     if (retval)
 | |
| 	{
 | |
| 		// Are there any "higher" AMD CPUID functions?
 | |
| 		if (RegEAX > 0x80000000L )				
 | |
| 		{
 | |
| 		   __try 
 | |
| 			{
 | |
| 			_asm
 | |
| 				{
 | |
| 					mov			eax, 0x80000001		// setup to test for CPU features
 | |
| 					CPUID							// code bytes = 0fh,  0a2h
 | |
| 					shr			edx, 31				// If bit 31 is set, we have 3DNow support!
 | |
| 					mov			retval, edx			// Save the return value for end of function
 | |
| 				}
 | |
| 			}
 | |
| 			__except(EXCEPTION_EXECUTE_HANDLER) 
 | |
| 			{ 
 | |
| 				retval = false; 
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			// processor supports CPUID but does not support AMD CPUID functions
 | |
| 			retval = false;					
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| #ifdef CPUID
 | |
| 	_asm popad;
 | |
| #endif
 | |
| 
 | |
|     return retval;
 | |
| }
 | |
| 
 | |
| #pragma optimize( "", on )
 | |
| 
 | |
| #endif // _WIN32
 |