Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#ifdef WIN32
Toshihiro Shimizu 890ddd
#include <wtypes.h></wtypes.h>
Toshihiro Shimizu 890ddd
#include <winnt.h></winnt.h>
Toshihiro Shimizu 890ddd
#include <emmintrin.h></emmintrin.h>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace TSystem;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef x64
Toshihiro Shimizu 890ddd
long TSystem::getCPUExtensions()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return TSystem::CpuSupportsSse | TSystem::CpuSupportsSse2; //TSystem::CPUExtensionsNone
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#ifndef WIN32
Toshihiro Shimizu 890ddd
long TSystem::getCPUExtensions()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return TSystem::CPUExtensionsNone;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
long CPUExtensionsAvailable = TSystem::CPUExtensionsNone;
Toshihiro Shimizu 890ddd
bool CPUExtensionsEnabled = true;
Toshihiro Shimizu 890ddd
bool FistTime = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#ifdef WIN32
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
long CPUCheckForSSESupport()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	__try {
Toshihiro Shimizu 890ddd
		//		__asm andps xmm0,xmm0
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		__asm _emit 0x0f __asm _emit 0x54 __asm _emit 0xc0
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} __except (EXCEPTION_EXECUTE_HANDLER) {
Toshihiro Shimizu 890ddd
		if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
Toshihiro Shimizu 890ddd
			CPUExtensionsAvailable &= ~(CpuSupportsSse | CpuSupportsSse2);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return CPUExtensionsAvailable;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
long __declspec(naked) CPUCheckForExtensions()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	__asm {
Toshihiro Shimizu 890ddd
		push	ebp
Toshihiro Shimizu 890ddd
		push	edi
Toshihiro Shimizu 890ddd
		push	esi
Toshihiro Shimizu 890ddd
		push	ebx
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		xor		ebp,ebp			;cpu flags - if we don't have CPUID, we probably
Toshihiro Shimizu 890ddd
								;won't want to try FPU optimizations.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		;check for CPUID.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		pushfd					;flags -> EAX
Toshihiro Shimizu 890ddd
		pop		eax
Toshihiro Shimizu 890ddd
		or		eax,00200000h	;set the ID bit
Toshihiro Shimizu 890ddd
		push	eax				;EAX -> flags
Toshihiro Shimizu 890ddd
		popfd
Toshihiro Shimizu 890ddd
		pushfd					;flags -> EAX
Toshihiro Shimizu 890ddd
		pop		eax
Toshihiro Shimizu 890ddd
		and		eax,00200000h	;ID bit set?
Toshihiro Shimizu 890ddd
		jz		done			;nope...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		;CPUID exists, check for features register.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		mov		ebp,00000003h
Toshihiro Shimizu 890ddd
		xor		eax,eax
Toshihiro Shimizu 890ddd
		cpuid
Toshihiro Shimizu 890ddd
		or		eax,eax
Toshihiro Shimizu 890ddd
		jz		done			;no features register?!?
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		;features register exists, look for MMX, SSE, SSE2.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		mov		eax,1
Toshihiro Shimizu 890ddd
		cpuid
Toshihiro Shimizu 890ddd
		mov		ebx,edx
Toshihiro Shimizu 890ddd
		and		ebx,00800000h	;MMX is bit 23
Toshihiro Shimizu 890ddd
		shr		ebx,21
Toshihiro Shimizu 890ddd
		or		ebp,ebx			;set bit 2 if MMX exists
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		mov		ebx,edx
Toshihiro Shimizu 890ddd
		and		edx,02000000h	;SSE is bit 25
Toshihiro Shimizu 890ddd
		shr		edx,25
Toshihiro Shimizu 890ddd
		neg		edx
Toshihiro Shimizu 890ddd
		and		edx,00000018h	;set bits 3 and 4 if SSE exists
Toshihiro Shimizu 890ddd
		or		ebp,edx
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		and		ebx,04000000h	;SSE2 is bit 26
Toshihiro Shimizu 890ddd
		shr		ebx,21
Toshihiro Shimizu 890ddd
		and		ebx,00000020h	;set bit 5
Toshihiro Shimizu 890ddd
		or		ebp,ebx
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		;check for vendor feature register (K6/Athlon).
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		mov		eax,80000000h
Toshihiro Shimizu 890ddd
		cpuid
Toshihiro Shimizu 890ddd
		mov		ecx,80000001h
Toshihiro Shimizu 890ddd
		cmp		eax,ecx
Toshihiro Shimizu 890ddd
		jb		done
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		;vendor feature register exists, look for 3DNow! and Athlon extensions
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		mov		eax,ecx
Toshihiro Shimizu 890ddd
		cpuid
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		mov		eax,edx
Toshihiro Shimizu 890ddd
		and		edx,80000000h	;3DNow! is bit 31
Toshihiro Shimizu 890ddd
		shr		edx,25
Toshihiro Shimizu 890ddd
		or		ebp,edx			;set bit 6
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		mov		edx,eax
Toshihiro Shimizu 890ddd
		and		eax,40000000h	;3DNow!2 is bit 30
Toshihiro Shimizu 890ddd
		shr		eax,23
Toshihiro Shimizu 890ddd
		or		ebp,eax			;set bit 7
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		and		edx,00400000h	;AMD MMX extensions (integer SSE) is bit 22
Toshihiro Shimizu 890ddd
		shr		edx,19
Toshihiro Shimizu 890ddd
		or		ebp,edx
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
done:
Toshihiro Shimizu 890ddd
		mov		eax,ebp
Toshihiro Shimizu 890ddd
		mov		CPUExtensionsAvailable, ebp
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		;Full SSE and SSE-2 require OS support for the xmm* registers.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		test	eax,00000030h
Toshihiro Shimizu 890ddd
		jz		nocheck
Toshihiro Shimizu 890ddd
		call	CPUCheckForSSESupport
Toshihiro Shimizu 890ddd
nocheck:
Toshihiro Shimizu 890ddd
		pop		ebx
Toshihiro Shimizu 890ddd
		pop		esi
Toshihiro Shimizu 890ddd
		pop		edi
Toshihiro Shimizu 890ddd
		pop		ebp
Toshihiro Shimizu 890ddd
		ret
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#endif
Toshihiro Shimizu 890ddd
//#endif
Toshihiro Shimizu 890ddd
} // anonymous namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
long TSystem::getCPUExtensions()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (FistTime) {
Toshihiro Shimizu 890ddd
		CPUCheckForExtensions();
Toshihiro Shimizu 890ddd
		FistTime = false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (CPUExtensionsEnabled)
Toshihiro Shimizu 890ddd
		return CPUExtensionsAvailable;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return TSystem::CPUExtensionsNone;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
void TSystem::enableCPUExtensions(bool on)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  CPUExtensionsEnabled = on;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/