sdl2-compat: cpu: SDL_Has3DNow removed from SDL3, implement here.

From caafce97b8789ebcbb6c9190ec9951213382cabe Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Sat, 24 Dec 2022 02:05:28 -0500
Subject: [PATCH] cpu: SDL_Has3DNow removed from SDL3, implement here.

The cpuid code is copied from sdl12-compat.
---
 src/sdl2_compat.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++
 src/sdl3_syms.h   |  1 -
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index 5478a15..c71ac1d 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -2648,6 +2648,69 @@ SDL_CreateRenderer(SDL_Window *window, int index, Uint32 flags)
     return SDL3_CreateRenderer(window, name, flags);
 }
 
+
+/* SDL3 doesn't have 3dNow. */
+#if defined(__GNUC__) && defined(__i386__)
+#define cpuid(func, a, b, c, d) \
+    __asm__ __volatile__ ( \
+"        pushl %%ebx        \n" \
+"        xorl %%ecx,%%ecx   \n" \
+"        cpuid              \n" \
+"        movl %%ebx, %%esi  \n" \
+"        popl %%ebx         \n" : \
+            "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
+#elif defined(__GNUC__) && defined(__x86_64__)
+#define cpuid(func, a, b, c, d) \
+    __asm__ __volatile__ ( \
+"        pushq %%rbx        \n" \
+"        xorq %%rcx,%%rcx   \n" \
+"        cpuid              \n" \
+"        movq %%rbx, %%rsi  \n" \
+"        popq %%rbx         \n" : \
+            "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
+#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+#define cpuid(func, a, b, c, d) \
+    __asm { \
+        __asm mov eax, func \
+        __asm xor ecx, ecx \
+        __asm cpuid \
+        __asm mov a, eax \
+        __asm mov b, ebx \
+        __asm mov c, ecx \
+        __asm mov d, edx \
+}
+#elif defined(_MSC_VER) && defined(_M_X64)
+#include <intrin.h>
+#define cpuid(func, a, b, c, d) \
+{ \
+    int CPUInfo[4]; \
+    __cpuid(CPUInfo, func); \
+    a = CPUInfo[0]; \
+    b = CPUInfo[1]; \
+    c = CPUInfo[2]; \
+    d = CPUInfo[3]; \
+}
+#else
+#define cpuid(func, a, b, c, d) \
+    do { a = b = c = d = 0; (void) a; (void) b; (void) c; (void) d; } while (0)
+#endif
+
+DECLSPEC SDL_bool SDLCALL
+SDL_Has3DNow(void)
+{
+    /* if there's no MMX, presumably there's no 3DNow. */
+    /* This lets SDL3 deal with the check for CPUID support _at all_ and eliminates non-AMD CPUs. */
+    if (SDL3_HasMMX()) {
+        int a, b, c, d;
+        cpuid(0x80000000, a, b, c, d);
+        if (a >= 0x80000001) {
+            cpuid(0x80000001, a, b, c, d);
+            return d & 0x80000000;
+        }
+    }
+    return 0;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/sdl3_syms.h b/src/sdl3_syms.h
index d070e37..a304b3c 100644
--- a/src/sdl3_syms.h
+++ b/src/sdl3_syms.h
@@ -126,7 +126,6 @@ SDL3_SYM_PASSTHROUGH(int,GetCPUCacheLineSize,(void),(),return)
 SDL3_SYM_PASSTHROUGH(SDL_bool,HasRDTSC,(void),(),return)
 SDL3_SYM_PASSTHROUGH(SDL_bool,HasAltiVec,(void),(),return)
 SDL3_SYM_PASSTHROUGH(SDL_bool,HasMMX,(void),(),return)
-SDL3_SYM_PASSTHROUGH(SDL_bool,Has3DNow,(void),(),return)
 SDL3_SYM_PASSTHROUGH(SDL_bool,HasSSE,(void),(),return)
 SDL3_SYM_PASSTHROUGH(SDL_bool,HasSSE2,(void),(),return)
 SDL3_SYM_PASSTHROUGH(SDL_bool,HasSSE3,(void),(),return)