added CPUID code from rbench and get_cpl to be used by the
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 2 May 2022 22:26:18 +0000 (01:26 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 2 May 2022 22:26:18 +0000 (01:26 +0300)
write-combining enable in gfx.c (again backported from rbench)

.gitignore
src/cpuid.c [new file with mode: 0644]
src/cpuid.h [new file with mode: 0644]
src/cpuid_s.asm [new file with mode: 0644]
src/dos/audos.c
src/dos/main.c
src/glut/main.c
src/sdl/main.c
src/util.h

index e86dd42..ac97839 100644 (file)
@@ -21,6 +21,7 @@ Release
 *sdf
 demo
 *.zip
+*.ZIP
 data
 *.a
 *.dll
diff --git a/src/cpuid.c b/src/cpuid.c
new file mode 100644 (file)
index 0000000..b67143a
--- /dev/null
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <string.h>
+#include "cpuid.h"
+
+static const char *cpuname(struct cpuid_info *cpu);
+static const char *cpuvendor(struct cpuid_info *cpu);
+
+struct cpuid_info cpuid;
+
+void print_cpuid(struct cpuid_info *cpu)
+{
+       int i, col, len;
+       char buf[64];
+       static const char *featstr[32] = {
+               "fpu", "vme", "dbgext", "pse", "tsc", "msr", "pae", "mce",
+               "cx8", "apic", "?", "sep", "mtrr", "pge", "mca", "cmov",
+               "pat", "pse36", "psn", "clf", "?", "dtes", "acpi", "mmx",
+               "fxsr", "sse", "sse2", "ss", "htt", "tm1", "ia64", "pbe"};
+       static const char *feat2str[32] = {
+               "sse3", "pclmul", "dtes64", "monitor", "ds-cpl", "vmx", "smx", "est",
+               "tm2", "ssse3", "cid", "sdbg", "fma", "cx16", "etprd", "pdcm",
+               "?", "pcid", "dca", "sse41", "sse42", "x2apic", "movbe", "popcnt",
+               "?", "aes", "xsave", "osxsave", "avx", "f16c", "rdrand", "?"};
+
+       printf("CPU: %s - %s\n", cpuvendor(cpu), cpuname(cpu));
+       printf("features:\n   ");
+       col = 3;
+       for(i=0; i<32; i++) {
+               if(cpu->feat & (1 << i)) {
+                       len = strlen(featstr[i]) + 1;
+                       if(col + len >= 80) {
+                               fputs("\n   ", stdout);
+                               col = 3;
+                       }
+                       col += printf(" %s", featstr[i]);
+               }
+       }
+       for(i=0; i<32; i++) {
+               if(cpu->feat2 & (1 << i)) {
+                       len = strlen(feat2str[i]) + 1;
+                       if(col + len >= 80) {
+                               fputs("\n   ", stdout);
+                               col = 3;
+                       }
+                       col += printf(" %s", feat2str[i]);
+               }
+       }
+       putchar('\n');
+}
+
+static const char *fam4_models[16] = {
+       "486 DX 25/33", "486 DX 50", "486 SX", "486 DX/2", "486 SL", "486 SX/2",
+       0, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB"
+};
+static const char *fam5_models[16] = {
+       "Pentium 60/66", "Pentium 60/66", "Pentium 75-200", "OverDrive", "Pentium MMX",
+       0, 0, "Mobile Pentium 75-200", "Mobile Pentium MMX", "Quark"
+};
+static const char *fam6_models[16] = {
+       "Pentium Pro", "Pentium Pro", 0, "Pentium 2", "Pentium 2", "Pentium 2",
+       "Mobile Pentium 2", "Pentium 3", "Pentium 3", 0, "Pentium 3", "Pentium 3"
+};
+
+
+static const char *cpuname(struct cpuid_info *cpu)
+{
+       int model, family;
+       char *rd, *wr;
+
+       if(cpu->brandstr) {
+               /* unwank the string */
+               rd = wr = cpu->brandstr;
+               while(*rd) {
+                       if(rd[0] == '(' && rd[1] == 'T' && rd[2] == 'M' && rd[3] == ')')
+                               rd += 4;
+                       else if(rd[0] == '(' && rd[1] == 'R' && rd[2] == ')')
+                               rd += 3;
+                       if(rd != wr) *wr = *rd;
+                       wr++;
+                       rd++;
+               }
+               return cpu->brandstr;
+       }
+
+       if(CPUID_EXTMODEL(cpu->id)) {
+               /* processors new enough to have an extended model, should also provide
+                * a brand string. If we end up here, we don't know what it is
+                */
+               return "unknown";
+       }
+
+       model = CPUID_MODEL(cpu->id);
+       family = CPUID_FAMILY(cpu->id) | (CPUID_EXTFAMILY(cpu->id) << 4);
+
+       switch(family) {
+       case 3: return "386";
+       case 4: return fam4_models[model] ? fam4_models[model] : "486";
+       case 5: return fam5_models[model] ? fam5_models[model] : "Pentium";
+       case 6: return fam6_models[model] ? fam6_models[model] : "unknown";
+       case 15: return "Pentium 4";
+       default:
+               break;
+       }
+       return "unknown";
+}
+
+static const char *cpuvendor(struct cpuid_info *cpu)
+{
+       static char other[16];
+       static const struct { const char *wank, *vendor; } unwanktab[] = {
+               {"GenuineIntel", "intel"},
+               {"AuthenticAMD", "AMD"},
+               {"AMDisbetter!", "AMD"},
+               {"CentaurHauls", "IDT"},
+               {"CyrixInstead", "Cyrix"},
+               {"TransmetaCPU", "Transmeta"},
+               {"GenuineTMx86", "Transmeta"},
+               {"Geode by NSC", "NatSemi"},
+               {"NexGenDriven", "NexGen"},
+               {"RiseRiseRise", "Rise"},
+               {"SiS SiS SiS ", "SiS"},
+               {"UMC UMC UMC ", "UMC"},
+               {"VIA VIA VIA ", "VIA"},
+               {"Vortex86 SoC", "DM&P"},
+               {"  Shanghai  ", "Zhaoxin"},
+               {"HygonGenuine", "Hygon"},
+               {"E2K MACHINE", "MCST Elbrus"},
+               {"MiSTer A0486", "ao486"},
+               {"bhyve bhyve ", "bhyve"},
+               {" KVMKVMKVM  ", "KVM"},
+               {"TCGTCGTCGTCG", "qemu"},
+               {"Microsoft Hv", "MS Hyper-V"},
+               {" lrpepyh  vr", "Parallels"},
+               {"VMwareVMware", "VMware"},
+               {"XenVMMXenVMM", "Xen"},
+               {"ACRNACRNACRN", "ACRN"},
+               {" QNXQVMBSQG ", "QNX Hypervisor"},
+               {0, 0}
+       };
+
+       int i;
+       for(i=0; unwanktab[i].wank; i++) {
+               if(memcmp(cpu->vendor, unwanktab[i].wank, 12) == 0) {
+                       return unwanktab[i].vendor;
+               }
+       }
+
+       memcpy(other, cpu->vendor, 12);
+       other[12] = 0;
+       return other;
+}
diff --git a/src/cpuid.h b/src/cpuid.h
new file mode 100644 (file)
index 0000000..5566f69
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef CPUID_H_
+#define CPUID_H_
+
+#include "inttypes.h"
+
+struct cpuid_info {
+       uint32_t maxidx;        /* 0: eax */
+       char vendor[12];        /* 0: ebx, edx, ecx */
+       uint32_t id;            /* 1: eax */
+       uint32_t rsvd0;         /* 1: ebx */
+       uint32_t feat;          /* 1: edx */
+       uint32_t feat2;         /* 1: ecx */
+
+       char brandstr[48];      /* 80000002h-80000004h */
+};
+
+extern struct cpuid_info cpuid;
+
+#define CPU_HAVE_MMX           (cpuid.feat & CPUID_FEAT_MMX)
+#define CPU_HAVE_MTRR          (cpuid.feat & CPUID_FEAT_MTRR)
+
+#define CPUID_STEPPING(id)     ((id) & 0xf)
+#define CPUID_MODEL(id)                (((id) >> 4) & 0xf)
+#define CPUID_FAMILY(id)       (((id) >> 8) & 0xf)
+#define CPUID_EXTMODEL(id)     (((id) >> 16) & 0xf)
+#define CPUID_EXTFAMILY(id)    (((id) >> 20) & 0xff)
+
+#define CPUID_FEAT_FPU                 0x00000001
+#define CPUID_FEAT_VME                 0x00000002
+#define CPUID_FEAT_DBGEXT              0x00000004
+#define CPUID_FEAT_PSE                 0x00000008
+#define CPUID_FEAT_TSC                 0x00000010
+#define CPUID_FEAT_MSR                 0x00000020
+#define CPUID_FEAT_PAE                 0x00000040
+#define CPUID_FEAT_MCE                 0x00000080
+#define CPUID_FEAT_CX8                 0x00000100
+#define CPUID_FEAT_APIC                        0x00000200
+
+#define CPUID_FEAT_SEP                 0x00000800
+#define CPUID_FEAT_MTRR                        0x00001000
+#define CPUID_FEAT_PGE                 0x00002000
+#define CPUID_FEAT_MCA                 0x00004000
+#define CPUID_FEAT_CMOV                        0x00008000
+#define CPUID_FEAT_PAT                 0x00010000
+#define CPUID_FEAT_PSE36               0x00020000
+#define CPUID_FEAT_PSN                 0x00040000
+#define CPUID_FEAT_CLF                 0x00080000
+
+#define CPUID_FEAT_DTES                        0x00200000
+#define CPUID_FEAT_ACPI                        0x00400000
+#define CPUID_FEAT_MMX                 0x00800000
+#define CPUID_FEAT_FXSR                        0x01000000
+#define CPUID_FEAT_SSE                 0x02000000
+#define CPUID_FEAT_SSE2                        0x04000000
+#define CPUID_FEAT_SS                  0x08000000
+#define CPUID_FEAT_HTT                 0x10000000
+#define CPUID_FEAT_TM1                 0x20000000
+#define CPUID_FEAT_IA64                        0x40000000
+#define CPUID_FEAT_PBE                 0x80000000
+
+#define CPUID_FEAT2_SSE3               0x00000001
+#define CPUID_FEAT2_PCLMUL             0x00000002
+#define CPUID_FEAT2_DTES64             0x00000004
+#define CPUID_FEAT2_MONITOR            0x00000008
+#define CPUID_FEAT2_DS_CPL             0x00000010
+#define CPUID_FEAT2_VMX                        0x00000020
+#define CPUID_FEAT2_SMX                        0x00000040
+#define CPUID_FEAT2_EST                        0x00000080
+#define CPUID_FEAT2_TM2                        0x00000100
+#define CPUID_FEAT2_SSSE3              0x00000200
+#define CPUID_FEAT2_CID                        0x00000400
+#define CPUID_FEAT2_SDBG               0x00000800
+#define CPUID_FEAT2_FMA                        0x00001000
+#define CPUID_FEAT2_CX16               0x00002000
+#define CPUID_FEAT2_ETPRD              0x00004000
+#define CPUID_FEAT2_PDCM               0x00008000
+
+#define CPUID_FEAT2_PCID               0x00020000
+#define CPUID_FEAT2_DCA                        0x00040000
+#define CPUID_FEAT2_SSE41              0x00080000
+#define CPUID_FEAT2_SSE42              0x00100000
+#define CPUID_FEAT2_X2APIC             0x00200000
+#define CPUID_FEAT2_MOVBE              0x00400000
+#define CPUID_FEAT2_POPCNT             0x00800000
+
+#define CPUID_FEAT2_AES                        0x02000000
+#define CPUID_FEAT2_XSAVE              0x04000000
+#define CPUID_FEAT2_OSXSAVE            0x08000000
+#define CPUID_FEAT2_AVX                        0x10000000
+#define CPUID_FEAT2_F16C               0x20000000
+#define CPUID_FEAT2_RDRAND             0x40000000
+
+int read_cpuid(struct cpuid_info *info);
+void print_cpuid(struct cpuid_info *info);
+
+#endif /* CPUID_H_ */
diff --git a/src/cpuid_s.asm b/src/cpuid_s.asm
new file mode 100644 (file)
index 0000000..b7b9626
--- /dev/null
@@ -0,0 +1,131 @@
+       section .text
+; foo_ are watcom functions, _foo are djgpp functions
+
+F_ID equ 0x200000
+
+       global read_cpuid
+       global _read_cpuid
+       global read_cpuid_
+read_cpuid_:
+       push eax
+       call check_cpuid
+       pop eax
+       jnc read_cpuid_nocheck
+       mov eax, -1
+       ret
+
+_read_cpuid:
+read_cpuid:
+       call check_cpuid
+       mov eax, [esp + 4]
+       jnc read_cpuid_nocheck
+       mov eax, -1
+       ret
+
+       ; determine if cpuid is available. avail: cf=0, not avail: cf=1
+check_cpuid:
+       pushf
+       pop eax
+       mov edx, eax    ; keep a copy of the original eflags in edx
+       xor eax, F_ID
+       push eax
+       popf
+       pushf
+       pop eax
+       clc
+       cmp eax, edx
+       jnz .noerr
+       stc
+.noerr:        ret
+
+       ; enter with the cpuid_info structure pointer in eax
+read_cpuid_nocheck:
+       push ebp
+       mov ebp, esp
+       push ebx
+       push edi
+       push esi
+       push eax        ; save the original struct pointer
+       sub esp, 8
+       mov edi, eax    ; struct pointer -> edi
+
+       ; clear struct
+       cld
+       push edi
+       mov ecx, (32+48)/4
+       xor eax, eax
+       rep stosd
+       pop edi
+
+       xor eax, eax
+       mov [esp], eax  ; current index
+       cpuid
+
+       mov [edi], eax          ; maxidx
+       ; clamp to the size of our cpuid_info structure
+       cmp eax, 1
+       jbe .skipclamp
+       mov eax, 1
+.skipclamp:
+       mov [esp + 4], eax      ; maximum index
+
+       mov [edi + 4], ebx      ; vendor name
+       mov [edi + 8], edx
+       mov [edi + 12], ecx
+       add edi, 16
+
+.loop: mov eax, [esp]
+       inc eax
+       cmp eax, [esp + 4]
+       ja .loopend
+       mov [esp], eax
+       cpuid
+       mov [edi], eax
+       mov [edi + 4], ebx
+       mov [edi + 8], edx
+       mov [edi + 12], ecx
+       add edi, 16
+       jmp .loop
+.loopend:
+       ; try to retrieve the brand string (avail on P4 or newer)
+       mov eax, 80000000h
+       cpuid
+       test eax, 80000000h
+       jz .done        ; no extended cpuid functions
+       cmp eax, 80000004h
+       jb .done        ; no brand string available
+
+       ; brand string available
+       mov esi, esp            ; save esp to esi
+       mov esp, [esp + 8]      ; esp <- original struct pointer
+       add esp, 32+48          ; offset to end of brandstr
+       mov eax, 80000004h
+       cpuid
+       push edx
+       push ecx
+       push ebx
+       push eax
+       mov eax, 80000003h
+       cpuid
+       push edx
+       push ecx
+       push ebx
+       push eax
+       mov eax, 80000002h
+       cpuid
+       push edx
+       push ecx
+       push ebx
+       push eax
+       mov esp, esi    ; done restore esp
+
+.done: add esp, 8
+       pop eax
+       pop esi
+       pop edi
+       pop ebx
+       pop ebp
+       xor eax, eax
+       ret
+       
+; vi:ft=nasm:
index 74376c6..2e6f376 100644 (file)
@@ -1,5 +1,6 @@
-#ifndef NO_SOUND
 #include <stdio.h>
+
+#ifndef NO_SOUND
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
index 566d47e..d820c7b 100644 (file)
@@ -10,6 +10,7 @@
 #include "audio.h"
 #include "sball.h"
 #include "vmath.h"
+#include "cpuid.h"
 
 static int handle_sball_event(sball_event *ev);
 static void recalc_sball_matrix(float *xform);
@@ -38,6 +39,10 @@ int main(int argc, char **argv)
        __djgpp_nearptr_enable();
 #endif
 
+       if(read_cpuid(&cpuid) == 0) {
+               print_cpuid(&cpuid);
+       }
+
        init_logger("demo.log");
 
        /* au_init needs to be called early, before init_timer, and also before
index 824837e..8d19192 100644 (file)
@@ -11,6 +11,7 @@
 #include "cfgopt.h"
 #include "cgmath/cgmath.h"
 #include "util.h"
+#include "cpuid.h"
 
 static void display(void);
 static void idle(void);
@@ -101,6 +102,9 @@ int main(int argc, char **argv)
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_CULL_FACE);
 
+       if(read_cpuid(&cpuid) == 0) {
+               print_cpuid(&cpuid);
+       }
 
        if(!set_video_mode(match_video_mode(FB_WIDTH, FB_HEIGHT, FB_BPP), 1)) {
                return 1;
index f2487cf..784b208 100644 (file)
@@ -9,6 +9,7 @@
 #include "cfgopt.h"
 #include "sball.h"
 #include "vmath.h"
+#include "cpuid.h"
 
 static void handle_event(SDL_Event *ev);
 static void toggle_fullscreen(void);
@@ -65,6 +66,10 @@ int main(int argc, char **argv)
        SDL_WM_SetCaption("dosdemo/SDL", 0);
        SDL_ShowCursor(0);
 
+       if(read_cpuid(&cpuid) == 0) {
+               print_cpuid(&cpuid);
+       }
+
        time_msec = 0;
        if(demo_init(argc, argv) == -1) {
                /*free(fb_pixels);*/
index 8a46036..5f3489f 100644 (file)
@@ -106,6 +106,12 @@ void debug_break(void);
 
 void halt(void);
 #pragma aux halt = "hlt";
+
+unsigned int get_cs(void);
+#pragma aux get_cs = \
+       "xor eax, eax" \
+       "mov ax, cs" \
+       value[eax];
 #endif
 
 #ifdef __GNUC__
@@ -168,14 +174,25 @@ static void INLINE memset16(void *dest, uint16_t val, int count)
        : "%eax", "%ebx", "%ecx", "%edx")
 
 #define debug_break() \
-       asm volatile ("int $3")
+       asm volatile("int $3")
 
 #define halt() \
        asm volatile("hlt")
+
+static unsigned int INLINE get_cs(void)
+{
+       unsigned int res;
+       asm volatile (
+               "xor %%eax, %%eax\n\t"
+               "mov %%cs, %0\n\t"
+               : "=a"(res)
+       );
+       return res;
+}
 #endif
 
 #ifdef _MSC_VER
-void __inline memset16(void *dest, uint16_t val, int count)
+static void __inline memset16(void *dest, uint16_t val, int count)
 {
        __asm {
                cld
@@ -221,6 +238,19 @@ void __inline memset16(void *dest, uint16_t val, int count)
        do { \
                __asm { int 3 } \
        } while(0)
+
+static unsigned int __inline get_cs(void)
+{
+       unsigned int res;
+       __asm {
+               xor eax, eax
+               mov ax, cs
+               mov [res], ax
+       }
+       return res;
+}
 #endif
 
+#define get_cpl()      ((int)(get_cs() & 7))
+
 #endif /* UTIL_H_ */