|
@@ -78,6 +78,7 @@ static int
|
|
|
CPU_haveCPUID(void)
|
|
|
{
|
|
|
int has_CPUID = 0;
|
|
|
+
|
|
|
/* *INDENT-OFF* */
|
|
|
#ifndef SDL_CPUINFO_DISABLED
|
|
|
#if defined(__GNUC__) && defined(i386)
|
|
@@ -215,59 +216,47 @@ done:
|
|
|
a = b = c = d = 0
|
|
|
#endif
|
|
|
|
|
|
-static int
|
|
|
-CPU_getCPUIDFeatures(void)
|
|
|
-{
|
|
|
- int features = 0;
|
|
|
- int a, b, c, d;
|
|
|
-
|
|
|
- cpuid(0, a, b, c, d);
|
|
|
- if (a >= 1) {
|
|
|
- cpuid(1, a, b, c, d);
|
|
|
- features = d;
|
|
|
- }
|
|
|
- return features;
|
|
|
-}
|
|
|
+static int CPU_CPUIDFeatures[4];
|
|
|
+static int CPU_CPUIDMaxFunction = 0;
|
|
|
+static SDL_bool CPU_OSSavesYMM = SDL_FALSE;
|
|
|
|
|
|
-static SDL_bool
|
|
|
-CPU_OSSavesYMM(void)
|
|
|
+static void
|
|
|
+CPU_calcCPUIDFeatures(void)
|
|
|
{
|
|
|
- int a, b, c, d;
|
|
|
-
|
|
|
- /* Check to make sure we can call xgetbv */
|
|
|
- cpuid(0, a, b, c, d);
|
|
|
- if (a < 1) {
|
|
|
- return SDL_FALSE;
|
|
|
- }
|
|
|
- cpuid(1, a, b, c, d);
|
|
|
- if (!(c & 0x08000000)) {
|
|
|
- return SDL_FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- /* Call xgetbv to see if YMM register state is saved */
|
|
|
- a = 0;
|
|
|
+ static SDL_bool checked = SDL_FALSE;
|
|
|
+ if (!checked) {
|
|
|
+ checked = SDL_TRUE;
|
|
|
+ if (CPU_haveCPUID()) {
|
|
|
+ int a, b, c, d;
|
|
|
+ cpuid(0, a, b, c, d);
|
|
|
+ CPU_CPUIDMaxFunction = a;
|
|
|
+ if (CPU_CPUIDMaxFunction >= 1) {
|
|
|
+ cpuid(1, a, b, c, d);
|
|
|
+ CPU_CPUIDFeatures[0] = a;
|
|
|
+ CPU_CPUIDFeatures[1] = b;
|
|
|
+ CPU_CPUIDFeatures[2] = c;
|
|
|
+ CPU_CPUIDFeatures[3] = d;
|
|
|
+
|
|
|
+ /* Check to make sure we can call xgetbv */
|
|
|
+ if (c & 0x08000000) {
|
|
|
+ /* Call xgetbv to see if YMM register state is saved */
|
|
|
#if defined(__GNUC__) && (defined(i386) || defined(__x86_64__))
|
|
|
- asm(".byte 0x0f, 0x01, 0xd0" : "=a" (a) : "c" (0) : "%edx");
|
|
|
+ asm(".byte 0x0f, 0x01, 0xd0" : "=a" (a) : "c" (0) : "%edx");
|
|
|
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */
|
|
|
- a = (int)_xgetbv(0);
|
|
|
+ a = (int)_xgetbv(0);
|
|
|
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
|
|
|
- __asm
|
|
|
- {
|
|
|
- xor ecx, ecx
|
|
|
- _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
|
|
|
- mov a, eax
|
|
|
- }
|
|
|
+ __asm
|
|
|
+ {
|
|
|
+ xor ecx, ecx
|
|
|
+ _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
|
|
|
+ mov a, eax
|
|
|
+ }
|
|
|
#endif
|
|
|
- return ((a & 6) == 6) ? SDL_TRUE : SDL_FALSE;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-CPU_haveRDTSC(void)
|
|
|
-{
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
- return (CPU_getCPUIDFeatures() & 0x00000010);
|
|
|
+ CPU_OSSavesYMM = ((a & 6) == 6) ? SDL_TRUE : SDL_FALSE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -299,21 +288,11 @@ CPU_haveAltiVec(void)
|
|
|
return altivec;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-CPU_haveMMX(void)
|
|
|
-{
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
- return (CPU_getCPUIDFeatures() & 0x00800000);
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int
|
|
|
CPU_have3DNow(void)
|
|
|
{
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
+ if (CPU_CPUIDMaxFunction > 0) { /* that is, do we have CPUID at all? */
|
|
|
int a, b, c, d;
|
|
|
-
|
|
|
cpuid(0x80000000, a, b, c, d);
|
|
|
if (a >= 0x80000001) {
|
|
|
cpuid(0x80000001, a, b, c, d);
|
|
@@ -323,95 +302,22 @@ CPU_have3DNow(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-CPU_haveSSE(void)
|
|
|
-{
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
- return (CPU_getCPUIDFeatures() & 0x02000000);
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-CPU_haveSSE2(void)
|
|
|
-{
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
- return (CPU_getCPUIDFeatures() & 0x04000000);
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-CPU_haveSSE3(void)
|
|
|
-{
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
- int a, b, c, d;
|
|
|
-
|
|
|
- cpuid(0, a, b, c, d);
|
|
|
- if (a >= 1) {
|
|
|
- cpuid(1, a, b, c, d);
|
|
|
- return (c & 0x00000001);
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-CPU_haveSSE41(void)
|
|
|
-{
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
- int a, b, c, d;
|
|
|
-
|
|
|
- cpuid(0, a, b, c, d);
|
|
|
- if (a >= 1) {
|
|
|
- cpuid(1, a, b, c, d);
|
|
|
- return (c & 0x00080000);
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-CPU_haveSSE42(void)
|
|
|
-{
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
- int a, b, c, d;
|
|
|
-
|
|
|
- cpuid(0, a, b, c, d);
|
|
|
- if (a >= 1) {
|
|
|
- cpuid(1, a, b, c, d);
|
|
|
- return (c & 0x00100000);
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-CPU_haveAVX(void)
|
|
|
-{
|
|
|
- if (CPU_haveCPUID() && CPU_OSSavesYMM()) {
|
|
|
- int a, b, c, d;
|
|
|
-
|
|
|
- cpuid(0, a, b, c, d);
|
|
|
- if (a >= 1) {
|
|
|
- cpuid(1, a, b, c, d);
|
|
|
- return (c & 0x10000000);
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
+#define CPU_haveRDTSC() (CPU_CPUIDFeatures[3] & 0x00000010)
|
|
|
+#define CPU_haveMMX() (CPU_CPUIDFeatures[3] & 0x00800000)
|
|
|
+#define CPU_haveSSE() (CPU_CPUIDFeatures[3] & 0x02000000)
|
|
|
+#define CPU_haveSSE2() (CPU_CPUIDFeatures[3] & 0x04000000)
|
|
|
+#define CPU_haveSSE3() (CPU_CPUIDFeatures[2] & 0x00000001)
|
|
|
+#define CPU_haveSSE41() (CPU_CPUIDFeatures[2] & 0x00080000)
|
|
|
+#define CPU_haveSSE42() (CPU_CPUIDFeatures[2] & 0x00100000)
|
|
|
+#define CPU_haveAVX() (CPU_OSSavesYMM && (CPU_CPUIDFeatures[2] & 0x10000000))
|
|
|
|
|
|
static int
|
|
|
CPU_haveAVX2(void)
|
|
|
{
|
|
|
- if (CPU_haveCPUID() && CPU_OSSavesYMM()) {
|
|
|
+ if (CPU_OSSavesYMM && (CPU_CPUIDMaxFunction >= 7)) {
|
|
|
int a, b, c, d;
|
|
|
-
|
|
|
- cpuid(0, a, b, c, d);
|
|
|
- if (a >= 7) {
|
|
|
- cpuid(7, a, b, c, d);
|
|
|
- return (b & 0x00000020);
|
|
|
- }
|
|
|
+ cpuid(7, a, b, c, d);
|
|
|
+ return (b & 0x00000020);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
@@ -459,7 +365,8 @@ SDL_GetCPUType(void)
|
|
|
if (!SDL_CPUType[0]) {
|
|
|
int i = 0;
|
|
|
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
+ CPU_calcCPUIDFeatures();
|
|
|
+ if (CPU_CPUIDMaxFunction > 0) { /* do we have CPUID at all? */
|
|
|
int a, b, c, d;
|
|
|
cpuid(0x00000000, a, b, c, d);
|
|
|
(void) a;
|
|
@@ -496,7 +403,8 @@ SDL_GetCPUName(void)
|
|
|
int i = 0;
|
|
|
int a, b, c, d;
|
|
|
|
|
|
- if (CPU_haveCPUID()) {
|
|
|
+ CPU_calcCPUIDFeatures();
|
|
|
+ if (CPU_CPUIDMaxFunction > 0) { /* do we have CPUID at all? */
|
|
|
cpuid(0x80000000, a, b, c, d);
|
|
|
if (a >= 0x80000004) {
|
|
|
cpuid(0x80000002, a, b, c, d);
|
|
@@ -584,6 +492,7 @@ static Uint32
|
|
|
SDL_GetCPUFeatures(void)
|
|
|
{
|
|
|
if (SDL_CPUFeatures == 0xFFFFFFFF) {
|
|
|
+ CPU_calcCPUIDFeatures();
|
|
|
SDL_CPUFeatures = 0;
|
|
|
if (CPU_haveRDTSC()) {
|
|
|
SDL_CPUFeatures |= CPU_HAS_RDTSC;
|
|
@@ -622,103 +531,71 @@ SDL_GetCPUFeatures(void)
|
|
|
return SDL_CPUFeatures;
|
|
|
}
|
|
|
|
|
|
-SDL_bool
|
|
|
-SDL_HasRDTSC(void)
|
|
|
+#define CPU_FEATURE_AVAILABLE(f) ((SDL_GetCPUFeatures() & f) ? SDL_TRUE : SDL_FALSE)
|
|
|
+
|
|
|
+SDL_bool SDL_HasRDTSC(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_RDTSC);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_HasAltiVec(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_ALTIVEC);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_HasMMX(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_MMX);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_Has3DNow(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_3DNOW);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_HasSSE(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_HasSSE2(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE2);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_HasSSE3(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE3);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_HasSSE41(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE41);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_HasSSE42(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE42);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_HasAVX(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_AVX) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX);
|
|
|
}
|
|
|
|
|
|
SDL_bool
|
|
|
SDL_HasAVX2(void)
|
|
|
{
|
|
|
- if (SDL_GetCPUFeatures() & CPU_HAS_AVX2) {
|
|
|
- return SDL_TRUE;
|
|
|
- }
|
|
|
- return SDL_FALSE;
|
|
|
+ return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX2);
|
|
|
}
|
|
|
|
|
|
static int SDL_SystemRAM = 0;
|