Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Shinya Kitaoka 9f5a1b
#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
Shinya Kitaoka 120a6e
long TSystem::getCPUExtensions() {
Shinya Kitaoka 120a6e
  return TSystem::CpuSupportsSse |
Shinya Kitaoka 120a6e
         TSystem::CpuSupportsSse2;  // TSystem::CPUExtensionsNone
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 9f5a1b
#ifndef _WIN32
Shinya Kitaoka 120a6e
long TSystem::getCPUExtensions() { return TSystem::CPUExtensionsNone; }
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
long CPUExtensionsAvailable = TSystem::CPUExtensionsNone;
Shinya Kitaoka 120a6e
bool CPUExtensionsEnabled   = true;
Shinya Kitaoka 120a6e
bool FistTime               = true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
//#ifdef _WIN32
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
long CPUCheckForSSESupport() {
Shinya Kitaoka 120a6e
  __try {
Shinya Kitaoka 120a6e
    //		__asm andps xmm0,xmm0
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    __asm _emit 0x0f __asm _emit 0x54 __asm _emit 0xc0
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  } __except (EXCEPTION_EXECUTE_HANDLER) {
Shinya Kitaoka 120a6e
    if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
Shinya Kitaoka 120a6e
      CPUExtensionsAvailable &= ~(CpuSupportsSse | CpuSupportsSse2);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return CPUExtensionsAvailable;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
long __declspec(naked) CPUCheckForExtensions() {
Shinya Kitaoka 120a6e
        __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
Shinya Kitaoka 120a6e
}  // anonymous namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
long TSystem::getCPUExtensions() {
Shinya Kitaoka 120a6e
  if (FistTime) {
Shinya Kitaoka 120a6e
    CPUCheckForExtensions();
Shinya Kitaoka 120a6e
    FistTime = false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (CPUExtensionsEnabled)
Shinya Kitaoka 120a6e
    return CPUExtensionsAvailable;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    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
*/