diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-06 10:24:33 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-06 10:24:33 +0100 |
| commit | aed9ebd7d66fb3c4e9954c5d0759c2446b820ed3 (patch) | |
| tree | 7a89f8fbcb4222bf80d631fe208fe00d1c4ae930 /src/tools | |
| parent | f335df23ec5276ebf67c0a9d59fb504da60839aa (diff) | |
| download | box64-aed9ebd7d66fb3c4e9954c5d0759c2446b820ed3.tar.gz box64-aed9ebd7d66fb3c4e9954c5d0759c2446b820ed3.zip | |
Added 0F A2 cpuid opcode
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/my_cpuid.c | 188 |
1 files changed, 188 insertions, 0 deletions
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; + } +} |