about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/emu/x64run0f.c8
-rwxr-xr-xsrc/include/cpu_info.h94
-rw-r--r--src/include/my_cpuid.h8
-rw-r--r--src/tools/my_cpuid.c188
4 files changed, 297 insertions, 1 deletions
diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c
index 51496f55..2544580f 100644
--- a/src/emu/x64run0f.c
+++ b/src/emu/x64run0f.c
@@ -18,7 +18,7 @@
 #include "x64trace.h"

 #include "x87emu_private.h"

 #include "box64context.h"

-//#include "my_cpuid.h"

+#include "my_cpuid.h"

 #include "bridge.h"

 //#include "signals.h"

 #ifdef DYNAREC

@@ -32,6 +32,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
     uint8_t opcode;

     uint8_t nextop;

     int32_t tmp32s;

+    uint32_t tmp32u;

     reg64_t *oped, *opgd;

 

     opcode = F8;

@@ -61,6 +62,11 @@ int Run0F(x64emu_t *emu, rex_t rex)
             , R_RIP += tmp32s;

         )                               /* 0x80 -> 0x8F Jxx */

 

+        case 0xA2:                      /* CPUID */

+            tmp32u = R_EAX;

+            my_cpuid(emu, tmp32u);

+            break;

+

         case 0xAF:                      /* IMUL Gd,Ed */

             nextop = F8;

             GETED;

diff --git a/src/include/cpu_info.h b/src/include/cpu_info.h
new file mode 100755
index 00000000..18c4a1b9
--- /dev/null
+++ b/src/include/cpu_info.h
@@ -0,0 +1,94 @@
+#ifndef __CPU_INFO__H_
+#define __CPU_INFO__H_
+enum ProcessorVendors {
+  VENDOR_INTEL = 1,
+  VENDOR_AMD,
+  VENDOR_OTHER,
+  VENDOR_MAX
+};
+
+enum ProcessorTypes {
+  INTEL_ATOM = 1,
+  INTEL_CORE2,
+  INTEL_COREI7,
+  AMDFAM10H,
+  AMDFAM15H,
+  INTEL_i386,
+  INTEL_i486,
+  INTEL_PENTIUM,
+  INTEL_PENTIUM_PRO,
+  INTEL_PENTIUM_II,
+  INTEL_PENTIUM_III,
+  INTEL_PENTIUM_IV,
+  INTEL_PENTIUM_M,
+  INTEL_CORE_DUO,
+  INTEL_XEONPHI,
+  INTEL_X86_64,
+  INTEL_NOCONA,
+  INTEL_PRESCOTT,
+  AMD_i486,
+  AMDPENTIUM,
+  AMDATHLON,
+  AMDFAM14H,
+  AMDFAM16H,
+  CPU_TYPE_MAX
+};
+
+enum ProcessorSubtypes {
+  INTEL_COREI7_NEHALEM = 1,
+  INTEL_COREI7_WESTMERE,
+  INTEL_COREI7_SANDYBRIDGE,
+  AMDFAM10H_BARCELONA,
+  AMDFAM10H_SHANGHAI,
+  AMDFAM10H_ISTANBUL,
+  AMDFAM15H_BDVER1,
+  AMDFAM15H_BDVER2,
+  INTEL_PENTIUM_MMX,
+  INTEL_CORE2_65,
+  INTEL_CORE2_45,
+  INTEL_COREI7_IVYBRIDGE,
+  INTEL_COREI7_HASWELL,
+  INTEL_COREI7_BROADWELL,
+  INTEL_COREI7_SKYLAKE,
+  INTEL_COREI7_SKYLAKE_AVX512,
+  INTEL_ATOM_BONNELL,
+  INTEL_ATOM_SILVERMONT,
+  INTEL_KNIGHTS_LANDING,
+  AMDPENTIUM_K6,
+  AMDPENTIUM_K62,
+  AMDPENTIUM_K63,
+  AMDPENTIUM_GEODE,
+  AMDATHLON_TBIRD,
+  AMDATHLON_MP,
+  AMDATHLON_XP,
+  AMDATHLON_K8SSE3,
+  AMDATHLON_OPTERON,
+  AMDATHLON_FX,
+  AMDATHLON_64,
+  AMD_BTVER1,
+  AMD_BTVER2,
+  AMDFAM15H_BDVER3,
+  AMDFAM15H_BDVER4,
+  CPU_SUBTYPE_MAX
+};
+
+enum ProcessorFeatures {
+  FEATURE_CMOV = 0,
+  FEATURE_MMX,
+  FEATURE_POPCNT,
+  FEATURE_SSE,
+  FEATURE_SSE2,
+  FEATURE_SSE3,
+  FEATURE_SSSE3,
+  FEATURE_SSE4_1,
+  FEATURE_SSE4_2,
+  FEATURE_AVX,
+  FEATURE_AVX2,
+  FEATURE_AVX512,
+  FEATURE_AVX512SAVE,
+  FEATURE_MOVBE,
+  FEATURE_ADX,
+  FEATURE_EM64T
+};
+
+#endif
\ No newline at end of file
diff --git a/src/include/my_cpuid.h b/src/include/my_cpuid.h
new file mode 100644
index 00000000..53792ea0
--- /dev/null
+++ b/src/include/my_cpuid.h
@@ -0,0 +1,8 @@
+#ifndef __MY_CPUID_H__
+#define __MY_CPUID_H__
+#include <stdint.h>
+typedef struct x64emu_s x64emu_t;
+
+void my_cpuid(x64emu_t* emu, uint32_t tmp32u);
+
+#endif //__MY_CPUID_H__
\ No newline at end of file
diff --git a/src/tools/my_cpuid.c b/src/tools/my_cpuid.c
new file mode 100644
index 00000000..3aaf9d51
--- /dev/null
+++ b/src/tools/my_cpuid.c
@@ -0,0 +1,188 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "my_cpuid.h"
+#include "../emu/x64emu_private.h"
+#include "debug.h"
+
+int get_cpuMhz()
+{
+	int MHz = 0;
+#ifdef __arm__
+	FILE *f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
+	if(f) {
+		int r;
+		if(1==fscanf(f, "%d", &r))
+			MHz = r/1000;
+		fclose(f);
+	}
+#endif
+	if(!MHz)
+		MHz = 1000; // default to 1Ghz...
+	return MHz;
+}
+
+void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
+{
+    emu->regs[_AX].dword[1] = emu->regs[_DX].dword[1] = emu->regs[_CX].dword[1] = emu->regs[_BX].dword[1] = 0;
+    switch(tmp32u) {
+        case 0x0:
+            // emulate a P4. TODO: Emulate a Core2?
+            R_EAX = 0x0000000D;//0x80000004;
+            // return GenuineIntel
+            R_EBX = 0x756E6547;
+            R_EDX = 0x49656E69;
+            R_ECX = 0x6C65746E;
+            break;
+        case 0x1:
+            R_EAX = 0x00000601; // familly and all
+            R_EBX = 0;          // Brand indexe, CLFlush, Max APIC ID, Local APIC ID
+            R_EDX =   1         // fpu 
+                    | 1<<4      // rdtsc
+                    | 1<<8      // cmpxchg8
+                    | 1<<11     // sep (sysenter & sysexit)
+                    | 1<<15     // cmov
+                    | 1<<19     // clflush (seems to be with SSE2)
+                    | 1<<23     // mmx
+                    | 1<<24     // fxsr (fxsave, fxrestore)
+                    | 1<<25     // SSE
+                    | 1<<26     // SSE2
+                    ;
+            R_ECX =   1<<0      // SSE3
+                    | 1<<9      // SSSE3
+                    | 1<<12     // fma
+                    | 1<<13     // cx16 (cmpxchg16)
+                    ; 
+            break;
+        case 0x2:   // TLB and Cache info. Sending 1st gen P4 info...
+            R_EAX = 0x665B5001;
+            R_EBX = 0x00000000;
+            R_ECX = 0x00000000;
+            R_EDX = 0x007A7000;
+            break;
+        
+        case 0x4:   // Cache info
+            switch (R_ECX) {
+                case 0: // L1 data cache
+                    R_EAX = (1 | (1<<5) | (1<<8));   //type
+                    R_EBX = (63 | (7<<22)); // size
+                    R_ECX = 63;
+                    R_EDX = 1;
+                    break;
+                case 1: // L1 inst cache
+                    R_EAX = (2 | (1<<5) | (1<<8)); //type
+                    R_EBX = (63 | (7<<22)); // size
+                    R_ECX = 63;
+                    R_EDX = 1;
+                    break;
+                case 2: // L2 cache
+                    R_EAX = (3 | (2<<5) | (1<<8)); //type
+                    R_EBX = (63 | (15<<22));    // size
+                    R_ECX = 4095;
+                    R_EDX = 1;
+                    break;
+
+                default:
+                    R_EAX = 0x00000000;
+                    R_EBX = 0x00000000;
+                    R_ECX = 0x00000000;
+                    R_EDX = 0x00000000;
+                    break;
+            }
+            break;
+        case 0x5:   //mwait info
+            R_EAX = 0;
+            R_EBX = 0;
+            R_ECX = 1 | 2;
+            R_EDX = 0;
+            break;
+        case 0x3:   // PSN
+        case 0x6:   // thermal
+        case 0x8:   // more extended capabilities
+        case 0x9:   // direct cache access
+        case 0xA:   // Architecture performance monitor
+            R_EAX = 0;
+            R_EBX = 0;
+            R_ECX = 0;
+            R_EDX = 0;
+            break;
+        case 0x7:   // extended bits...
+            /*if(R_ECX==0)    R_EAX = 0;
+            else*/ R_EAX = R_ECX = R_EBX = R_EDX = 0;
+            break;
+        case 0xB:   // Extended Topology Enumaretion Leaf
+            //TODO!
+            R_EAX = 0;
+            break;
+        case 0xC:   //?
+            R_EAX = 0;
+            break;
+        case 0xD:   // Processor Extended State Enumeration Main Leaf / Sub Leaf
+            if(R_CX==0) {
+                R_EAX = 1 | 2;  // x87 SSE saved
+                R_EBX = 512;    // size of xsave/xrstor
+                R_ECX = 512;    // same
+                R_EDX = 0;      // more bits
+            } else if(R_CX==1){
+                R_EAX = R_ECX = R_EBX = R_EDX = 0;  // XSAVEOPT and co are not available
+            } else {
+                R_EAX = R_ECX = R_EBX = R_EDX = 0;
+            }
+            break;
+            
+        case 0x80000000:        // max extended
+            R_EAX = 0x80000005;
+            break;
+        case 0x80000001:        //Extended Processor Signature and Feature Bits
+            R_EAX = 0;  // reserved
+            R_EBX = 0;  // reserved
+            R_ECX = (1<<5) | (1<<8); // LZCNT | PREFETCHW
+            R_EDX = 0;
+            break;
+        case 0x80000002:    // Brand part 1 (P4 signature)
+            R_EAX = 0x20202020;
+            R_EBX = 0x20202020;
+            R_ECX = 0x20202020;
+            R_EDX = 0x6E492020;
+            break;
+        case 0x80000003:    // Brand part 2
+            R_EAX = 0x286C6574;
+            R_EBX = 0x50202952;
+            R_ECX = 0x69746E65;
+            R_EDX = 0x52286D75;
+            break;
+        case 0x80000004:    // Brand part 3, with frequency
+            R_EAX = 0x20342029;
+            R_EBX = 0x20555043;
+            {
+                static int MHz = 0;
+                if(!MHz)
+					MHz = get_cpuMhz();
+                if(MHz>15000) { // swiches to GHz display...
+                    char tmp[11];
+                    sprintf(tmp, "%1.2f", MHz/1000.);
+                    R_ECX = *(uint32_t*)tmp;
+                    R_EDX = 0x007A4847; // GHz
+                } else {
+                    char tmp[11];
+                    sprintf(tmp, "%04d", MHz);
+                    R_ECX = *(uint32_t*)tmp;
+                    R_EDX = 0x007A484D; // MHz
+                }
+            }
+            break;  
+        case 0x80000005:
+            R_EAX = 0;
+            R_EBX = 0;
+            R_ECX = 0;
+            R_EDX = 0;
+            break;
+        default:
+            printf_log(LOG_INFO, "Warning, CPUID command %X unsupported (ECX=%08x)\n", tmp32u, R_ECX);
+            R_EAX = 0;
+            R_EBX = 0;
+            R_ECX = 0;
+            R_EDX = 0;
+    }   
+}