www.pudn.com > zfxcengine-0.1.0.zip > ceMathInit.cpp
/* $Id: ceMathInit.cpp,v 1.4 2005/03/24 21:22:13 andreaskohn Exp $ */ #include#include "Math/ceMath.h" #include "SDL.h" #include "SDL_cpuinfo.h" namespace ZFXCE { static CPUInfo_t CPUInfo; BOOL bUseInlineAsm=TRUE; // Enrico: // Copyright von diesem Assembler Code liegt bei Humus, emiper-8@student.luth.se // Leider fehlen mir die Kenntnisse, um das Plattformunabhängig selber zu schreiben. #if defined(WIN32) #define WIN32_LEAN_AND_MEAN #include "Windows.h" #define CPUID __asm _emit 0x0F __asm _emit 0xA2 #define RDTSC __asm _emit 0x0F __asm _emit 0x31 #define cpuid(func, a, b, c, d) cpuidAsm(func, &a, &b, &c, &d) #pragma warning(disable: 4035) typedef signed __int64 int64; typedef unsigned __int64 uint64; void cpuidAsm(UINT func, UINT *a, UINT *b, UINT *c, UINT *d) { __asm { PUSH EAX PUSH EBX PUSH ECX PUSH EDX MOV EAX, func CPUID MOV EDI, a MOV [EDI], EAX MOV EDI, b MOV [EDI], EBX MOV EDI, c MOV [EDI], ECX MOV EDI, d MOV [EDI], EDX POP EDX POP ECX POP EBX POP EAX } } inline uint64 getCycleNumber() { __asm { RDTSC } } uint64 getHz() { LARGE_INTEGER t1,t2,tf; uint64 c1,c2; QueryPerformanceFrequency(&tf); QueryPerformanceCounter(&t1); c1 = getCycleNumber(); // Some spin-wait for (volatile int i = 0; i < 1000000; i++); QueryPerformanceCounter(&t2); c2 = getCycleNumber(); return ((c2 - c1) * tf.QuadPart / (t2.QuadPart - t1.QuadPart)); } #else /* Linux, *BSD, and all the others. */ #include #if 0 // XXX: we need an asm guru for that. This code is basically i386, and it creates errors with recent gnu c++ compilers. #define cpuid(in,a,b,c,d)\ asm volatile ("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in)); #define rdtsc(a,d)\ asm volatile ("rdtsc" : "=a" (a), "=d" (d)); #else #define cpuid(in,a,b,c,d) \ (a)=0,(b)=0,(c)=0,(d)=0 #define rdtsc(a,d) \ (a)=0,(d)=0 #endif typedef unsigned int uint; typedef signed long long int64; typedef unsigned long long uint64; inline uint64 getCycleNumber() { union { struct { unsigned int a,d; } parts; long long ad; } ads; rdtsc(ads.parts.a,ads.parts.d); return ads.ad; } uint64 getHz(){ static struct timeval t1, t2; static struct timezone tz; unsigned long long c1,c2; gettimeofday(&t1, &tz); c1 = getCycleNumber(); // Some spin-wait for (volatile int i = 0; i < 1000000; i++); gettimeofday(&t2, &tz); c2 = getCycleNumber(); return (1000000 * (c2 - c1)) / ((t2.tv_usec - t1.tv_usec) + 1000000 * (t2.tv_sec - t1.tv_sec)); } #endif BOOL ceMathLibInit(BOOL bUseAsm, CPUInfo_t* pCPUInfo) { // Sobald wir irgendwann mal die Funktionen mit 3Dnow oder SSE implementiert haben, // kann man mittels diesem Parameter den Assembler abschalten. Z.B. um // Geschwindigkeitsvergleiche durchzuführen... bUseInlineAsm = bUseAsm; // Namen resetten memset(&CPUInfo.strCPUName[0], 0, sizeof(char) * 49); memset(&CPUInfo.strCPUVendor[0], 0, sizeof(char) * 13); // Features rausfinden - neu seit SDL 1.2.7 CPUInfo.bHasMMX = SDL_HasMMX(); CPUInfo.bHasMMXEx = SDL_HasMMXExt(); CPUInfo.bHas3DNow = SDL_Has3DNow(); CPUInfo.bHas3DNowExt = SDL_Has3DNowExt(); CPUInfo.bHasSSE = SDL_HasSSE(); CPUInfo.bHasSSE2 = SDL_HasSSE2(); // Den Rest machen wir so UINT maxi=0; cpuid(0, maxi, ((UINT *) CPUInfo.strCPUVendor)[0], ((UINT *) CPUInfo.strCPUVendor)[2], ((UINT *) CPUInfo.strCPUVendor)[1]); if (maxi >= 1) { UINT a,b,c,d; a = b = c = d = 0; cpuid(1, a, b, c, d); CPUInfo.iCPUFamily = (a >> 8) & 0x0F; UINT maxei=0; cpuid(0x80000000, maxei, b, c, d); if (maxei >= 0x80000001) { cpuid(0x80000001, a, b, c, d); if (maxei >= 0x80000002) { cpuid(0x80000002, ((UINT *) CPUInfo.strCPUName)[0], ((UINT *) CPUInfo.strCPUName)[1], ((UINT *) CPUInfo.strCPUName)[2], ((UINT *) CPUInfo.strCPUName)[3]); CPUInfo.strCPUName[16] = '\0'; if (maxei >= 0x80000003){ cpuid(0x80000003, ((UINT *) CPUInfo.strCPUName)[4], ((UINT *) CPUInfo.strCPUName)[5], ((UINT *) CPUInfo.strCPUName)[6], ((UINT *) CPUInfo.strCPUName)[7]); CPUInfo.strCPUName[32] = '\0'; if (maxei >= 0x80000004){ cpuid(0x80000004, ((UINT *) CPUInfo.strCPUName)[8], ((UINT *) CPUInfo.strCPUName)[9], ((UINT *) CPUInfo.strCPUName)[10], ((UINT *) CPUInfo.strCPUName)[11]); CPUInfo.strCPUName[48] = '\0'; } } } } } // Sicher gehen, dass wir einen highperformance counter haben, ohne den können wir nicht die Mhz zählen if( SDL_HasRDTSC() ) CPUInfo.uiMhZ = (UINT) getHz() / 1000000; // Wenn gewünscht, kopieren wir hier die Infos über die CPU if(pCPUInfo) { memcpy(pCPUInfo, &CPUInfo, sizeof(CPUInfo_t) ); } return TRUE; } } // Namespace ZFXCE