From bac960a725fa7e411cde4e140a372d6e82e232c3 Mon Sep 17 00:00:00 2001 From: yz70s Date: Sun, 9 Dec 2018 12:41:24 +0100 Subject: i386.cpp: move cpuid and msr routines to new file cpuidmsrs.hxx ... (nw) ... and add placeholders for athlonxp msrs. --- scripts/src/cpu.lua | 1 + src/devices/cpu/i386/cpuidmsrs.hxx | 395 +++++++++++++++++++++++++++++++++++++ src/devices/cpu/i386/i386.cpp | 182 +---------------- src/devices/cpu/i386/i386.h | 5 + 4 files changed, 405 insertions(+), 178 deletions(-) create mode 100644 src/devices/cpu/i386/cpuidmsrs.hxx diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index f8503ac9056..afb42dd1dd7 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1073,6 +1073,7 @@ if (CPUS["I386"]~=null) then MAME_DIR .. "src/devices/cpu/i386/pentops.hxx", MAME_DIR .. "src/devices/cpu/i386/x87ops.hxx", MAME_DIR .. "src/devices/cpu/i386/x87priv.h", + MAME_DIR .. "src/devices/cpu/i386/cpuidmsrs.hxx", } end diff --git a/src/devices/cpu/i386/cpuidmsrs.hxx b/src/devices/cpu/i386/cpuidmsrs.hxx new file mode 100644 index 00000000000..e7abcf27154 --- /dev/null +++ b/src/devices/cpu/i386/cpuidmsrs.hxx @@ -0,0 +1,395 @@ + +uint64_t pentium_device::opcode_rdmsr(bool &valid_msr) +{ + uint32_t offset = REG32(ECX); + + switch (offset) + { + // Machine Check Exception (TODO) + case 0x00: + valid_msr = true; + popmessage("RDMSR: Reading P5_MC_ADDR"); + return 0; + case 0x01: + valid_msr = true; + popmessage("RDMSR: Reading P5_MC_TYPE"); + return 0; + // Time Stamp Counter + case 0x10: + valid_msr = true; + popmessage("RDMSR: Reading TSC"); + return m_tsc; + // Event Counters (TODO) + case 0x11: // CESR + valid_msr = true; + popmessage("RDMSR: Reading CESR"); + return 0; + case 0x12: // CTR0 + valid_msr = true; + return m_perfctr[0]; + case 0x13: // CTR1 + valid_msr = true; + return m_perfctr[1]; + default: + if (!(offset & ~0xf)) // 2-f are test registers + { + valid_msr = true; + logerror("RDMSR: Reading test MSR %x", offset); + return 0; + } + logerror("RDMSR: invalid P5 MSR read %08x at %08x\n", offset, m_pc - 2); + valid_msr = false; + return 0; + } + return -1; +} + +void pentium_device::opcode_wrmsr(uint64_t data, bool &valid_msr) +{ + uint32_t offset = REG32(ECX); + + switch (offset) + { + // Machine Check Exception (TODO) + case 0x00: + popmessage("WRMSR: Writing P5_MC_ADDR"); + valid_msr = true; + break; + case 0x01: + popmessage("WRMSR: Writing P5_MC_TYPE"); + valid_msr = true; + break; + // Time Stamp Counter + case 0x10: + m_tsc = data; + popmessage("WRMSR: Writing to TSC"); + valid_msr = true; + break; + // Event Counters (TODO) + case 0x11: // CESR + popmessage("WRMSR: Writing to CESR"); + valid_msr = true; + break; + case 0x12: // CTR0 + m_perfctr[0] = data; + valid_msr = true; + break; + case 0x13: // CTR1 + m_perfctr[1] = data; + valid_msr = true; + break; + default: + if (!(offset & ~0xf)) // 2-f are test registers + { + valid_msr = true; + logerror("WRMSR: Writing test MSR %x", offset); + break; + } + logerror("WRMSR: invalid MSR write %08x (%08x%08x) at %08x\n", offset, (uint32_t)(data >> 32), (uint32_t)data, m_pc - 2); + valid_msr = false; + break; + } +} + +uint64_t pentium_pro_device::opcode_rdmsr(bool &valid_msr) +{ + uint32_t offset = REG32(ECX); + + switch (offset) + { + // Machine Check Exception (TODO) + case 0x00: + valid_msr = true; + popmessage("RDMSR: Reading P5_MC_ADDR"); + return 0; + case 0x01: + valid_msr = true; + popmessage("RDMSR: Reading P5_MC_TYPE"); + return 0; + // Time Stamp Counter + case 0x10: + valid_msr = true; + popmessage("RDMSR: Reading TSC"); + return m_tsc; + // Performance Counters (TODO) + case 0xc1: // PerfCtr0 + valid_msr = true; + return m_perfctr[0]; + case 0xc2: // PerfCtr1 + valid_msr = true; + return m_perfctr[1]; + default: + logerror("RDMSR: unimplemented register called %08x at %08x\n", offset, m_pc - 2); + valid_msr = true; + return 0; + } + return -1; +} + +void pentium_pro_device::opcode_wrmsr(uint64_t data, bool &valid_msr) +{ + uint32_t offset = REG32(ECX); + + switch (offset) + { + // Time Stamp Counter + case 0x10: + m_tsc = data; + popmessage("WRMSR: Writing to TSC"); + valid_msr = true; + break; + // Performance Counters (TODO) + case 0xc1: // PerfCtr0 + m_perfctr[0] = data; + valid_msr = true; + break; + case 0xc2: // PerfCtr1 + m_perfctr[1] = data; + valid_msr = true; + break; + default: + logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n", offset, (uint32_t)(data >> 32), (uint32_t)data, m_pc - 2); + valid_msr = true; + break; + } +} + +uint64_t pentium4_device::opcode_rdmsr(bool &valid_msr) +{ + switch (REG32(ECX)) + { + default: + logerror("RDMSR: unimplemented register called %08x at %08x\n", REG32(ECX), m_pc - 2); + valid_msr = true; + return 0; + } + return -1; +} + +void pentium4_device::opcode_wrmsr(uint64_t data, bool &valid_msr) +{ + switch (REG32(ECX)) + { + default: + logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n", REG32(ECX), (uint32_t)(data >> 32), (uint32_t)data, m_pc - 2); + valid_msr = true; + break; + } +} + +void athlonxp_device::opcode_cpuid() +{ + switch (REG32(EAX)) + { + case 0x80000000: + { + REG32(EAX) = 0x80000008; + REG32(EBX) = m_cpuid_id0; + REG32(ECX) = m_cpuid_id2; + REG32(EDX) = m_cpuid_id1; + CYCLES(CYCLES_CPUID); + break; + } + + case 0x80000001: + { + REG32(EAX) = m_cpu_version + 0x100; // family+1 as specified in AMD documentation + REG32(EDX) = m_feature_flags; + CYCLES(CYCLES_CPUID); + break; + } + + case 0x80000002: + case 0x80000003: + case 0x80000004: + { + int offset = (REG32(EAX) - 0x80000002) << 4; + uint8_t *b = m_processor_name_string + offset; + REG32(EAX) = b[ 0] + (b[ 1] << 8) + (b[ 2] << 16) + (b[ 3] << 24); + REG32(EBX) = b[ 4] + (b[ 5] << 8) + (b[ 6] << 16) + (b[ 7] << 24); + REG32(ECX) = b[ 8] + (b[ 9] << 8) + (b[10] << 16) + (b[11] << 24); + REG32(EDX) = b[12] + (b[13] << 8) + (b[14] << 16) + (b[15] << 24); + CYCLES(CYCLES_CPUID); + break; + } + + case 0x80000005: + { + REG32(EAX) = 0x0408FF08; // 2M/4M data tlb associativity 04 data tlb number of entries 08 instruction tlb associativity FF instruction tlb number of entries 08 + REG32(EBX) = 0xFF20FF10; // 4K data tlb associativity FF data tlb number of entries 20 instruction tlb associativity FF instruction tlb number of entries 10 + REG32(ECX) = 0x40020140; // L1 data cache size in K 40 associativity 02 lines per tag 01 line size in bytes 40 + REG32(EDX) = 0x40020140; // L1 instruction cache size in K 40 associativity 02 lines per tag 01 line size in bytes 40 + CYCLES(CYCLES_CPUID); + break; + } + + case 0x80000006: + { + REG32(EAX) = 0; + REG32(EBX) = 0x41004100; // 4 100 4 100 + REG32(ECX) = 0x01008140; // L2 cache size in K 0100 associativity 8=16-way lines per tag 1 line size in bytes 40 + CYCLES(CYCLES_CPUID); + break; + } + + case 0x80000007: + { + REG32(EDX) = 1; + CYCLES(CYCLES_CPUID); + break; + } + + case 0x80000008: + { + REG32(EAX) = 0x00002022; + CYCLES(CYCLES_CPUID); + break; + } + + default: + i386_device::opcode_cpuid(); + } +} + +uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr) +{ + uint32_t offset = REG32(ECX); + + switch (offset) + { + case 0x10: // TSC + break; + case 0x1b: // APIC_BASE + break; + case 0x17b: // MCG_CTL + break; + case 0x200: // MTRRphysBase0-7 + case 0x201: // MTRRphysMask0-7 + case 0x202: + case 0x203: + case 0x204: + case 0x205: + case 0x206: + case 0x207: + case 0x208: + case 0x209: + case 0x20a: + case 0x20b: + case 0x20c: + case 0x20d: + case 0x20e: + case 0x20f: + break; + case 0x2ff: // MTRRdefType + break; + case 0x250: // MTRRfix64K_00000 + break; + case 0x258: // MTRRfix16K_80000 + break; + case 0x259: // MTRRfix16K_A0000 + break; + case 0x268: // MTRRfix4K_C0000-F8000 + case 0x269: + case 0x26a: + case 0x26b: + case 0x26c: + case 0x26d: + case 0x26e: + case 0x26f: + break; + case 0x400: // MC0_CTL + break; + case 0x404: // MC1_CTL + break; + case 0x408: // MC2_CTL + break; + case 0x40c: // MC3_CTL + break; + case 0xC0010010: // SYS_CFG + break; + case 0xC0010015: // HWCR + break; + case 0xC0010016: // IORRBase + case 0xC0010017: // IORRMask + case 0xC0010018: + case 0xC0010019: + break; + case 0xC001001A: // TOP_MEM + break; + case 0xC001001D: // TOP_MEM2 + break; + case 0xC0010113: // SMM_MASK + break; + } + valid_msr = true; + return 0; +} + +void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr) +{ + uint32_t offset = REG32(ECX); + + switch (offset) + { + case 0x1b: // APIC_BASE + break; + case 0x17b: // MCG_CTL + break; + case 0x200: // MTRRphysBase0-7 + case 0x201: // MTRRphysMask0-7 + case 0x202: + case 0x203: + case 0x204: + case 0x205: + case 0x206: + case 0x207: + case 0x208: + case 0x209: + case 0x20a: + case 0x20b: + case 0x20c: + case 0x20d: + case 0x20e: + case 0x20f: + break; + case 0x2ff: // MTRRdefType + break; + case 0x250: // MTRRfix64K_00000 + break; + case 0x258: // MTRRfix16K_80000 + break; + case 0x259: // MTRRfix16K_A0000 + break; + case 0x268: // MTRRfix4K_C0000-F8000 + case 0x269: + case 0x26a: + case 0x26b: + case 0x26c: + case 0x26d: + case 0x26e: + case 0x26f: + break; + case 0x400: // MC0_CTL + break; + case 0x404: // MC1_CTL + break; + case 0x408: // MC2_CTL + break; + case 0x40c: // MC3_CTL + break; + case 0xC0010010: // SYS_CFG + break; + case 0xC0010015: // HWCR + break; + case 0xC0010016: // IORRBase + case 0xC0010017: // IORRMask + case 0xC0010018: + case 0xC0010019: + break; + case 0xC001001A: // TOP_MEM + break; + case 0xC0010113: // SMM_MASK + break; + } + valid_msr = true; +} diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp index 68781154970..a4408c69175 100644 --- a/src/devices/cpu/i386/i386.cpp +++ b/src/devices/cpu/i386/i386.cpp @@ -3037,6 +3037,8 @@ void i386_device::report_invalid_modrm(const char* opcode, uint8_t modrm) #include "i486ops.hxx" #include "pentops.hxx" #include "x87ops.hxx" +#include "cpuidmsrs.hxx" + void i386_device::i386_decode_opcode() { @@ -4321,98 +4323,6 @@ void pentium_device::device_reset() CHANGE_PC(m_eip); } -uint64_t pentium_device::opcode_rdmsr(bool &valid_msr) -{ - uint32_t offset = REG32(ECX); - - switch (offset) - { - // Machine Check Exception (TODO) - case 0x00: - valid_msr = true; - popmessage("RDMSR: Reading P5_MC_ADDR"); - return 0; - case 0x01: - valid_msr = true; - popmessage("RDMSR: Reading P5_MC_TYPE"); - return 0; - // Time Stamp Counter - case 0x10: - valid_msr = true; - popmessage("RDMSR: Reading TSC"); - return m_tsc; - // Event Counters (TODO) - case 0x11: // CESR - valid_msr = true; - popmessage("RDMSR: Reading CESR"); - return 0; - case 0x12: // CTR0 - valid_msr = true; - return m_perfctr[0]; - case 0x13: // CTR1 - valid_msr = true; - return m_perfctr[1]; - default: - if (!(offset & ~0xf)) // 2-f are test registers - { - valid_msr = true; - logerror("RDMSR: Reading test MSR %x", offset); - return 0; - } - logerror("RDMSR: invalid P5 MSR read %08x at %08x\n", offset, m_pc - 2); - valid_msr = false; - return 0; - } - return -1; -} - -void pentium_device::opcode_wrmsr(uint64_t data, bool &valid_msr) -{ - uint32_t offset = REG32(ECX); - - switch (offset) - { - // Machine Check Exception (TODO) - case 0x00: - popmessage("WRMSR: Writing P5_MC_ADDR"); - valid_msr = true; - break; - case 0x01: - popmessage("WRMSR: Writing P5_MC_TYPE"); - valid_msr = true; - break; - // Time Stamp Counter - case 0x10: - m_tsc = data; - popmessage("WRMSR: Writing to TSC"); - valid_msr = true; - break; - // Event Counters (TODO) - case 0x11: // CESR - popmessage("WRMSR: Writing to CESR"); - valid_msr = true; - break; - case 0x12: // CTR0 - m_perfctr[0] = data; - valid_msr = true; - break; - case 0x13: // CTR1 - m_perfctr[1] = data; - valid_msr = true; - break; - default: - if (!(offset & ~0xf)) // 2-f are test registers - { - valid_msr = true; - logerror("WRMSR: Writing test MSR %x", offset); - break; - } - logerror("WRMSR: invalid MSR write %08x (%08x%08x) at %08x\n", offset, (uint32_t)(data >> 32), (uint32_t)data, m_pc - 2); - valid_msr = false; - break; - } -} - /*****************************************************************************/ /* Cyrix MediaGX */ @@ -4550,69 +4460,6 @@ void pentium_pro_device::device_reset() CHANGE_PC(m_eip); } -uint64_t pentium_pro_device::opcode_rdmsr(bool &valid_msr) -{ - uint32_t offset = REG32(ECX); - - switch (offset) - { - // Machine Check Exception (TODO) - case 0x00: - valid_msr = true; - popmessage("RDMSR: Reading P5_MC_ADDR"); - return 0; - case 0x01: - valid_msr = true; - popmessage("RDMSR: Reading P5_MC_TYPE"); - return 0; - // Time Stamp Counter - case 0x10: - valid_msr = true; - popmessage("RDMSR: Reading TSC"); - return m_tsc; - // Performance Counters (TODO) - case 0xc1: // PerfCtr0 - valid_msr = true; - return m_perfctr[0]; - case 0xc2: // PerfCtr1 - valid_msr = true; - return m_perfctr[1]; - default: - logerror("RDMSR: unimplemented register called %08x at %08x\n", offset, m_pc - 2); - valid_msr = true; - return 0; - } - return -1; -} - -void pentium_pro_device::opcode_wrmsr(uint64_t data, bool &valid_msr) -{ - uint32_t offset = REG32(ECX); - - switch (offset) - { - // Time Stamp Counter - case 0x10: - m_tsc = data; - popmessage("WRMSR: Writing to TSC"); - valid_msr = true; - break; - // Performance Counters (TODO) - case 0xc1: // PerfCtr0 - m_perfctr[0] = data; - valid_msr = true; - break; - case 0xc2: // PerfCtr1 - m_perfctr[1] = data; - valid_msr = true; - break; - default: - logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n", offset, (uint32_t)(data >> 32), (uint32_t)data, m_pc - 2); - valid_msr = true; - break; - } -} - /*****************************************************************************/ /* Intel Pentium MMX */ @@ -4877,6 +4724,8 @@ void athlonxp_device::device_reset() m_cpuid_id0 = ('h' << 24) | ('t' << 16) | ('u' << 8) | 'A'; // Auth m_cpuid_id1 = ('i' << 24) | ('t' << 16) | ('n' << 8) | 'e'; // enti m_cpuid_id2 = ('D' << 24) | ('M' << 16) | ('A' << 8) | 'c'; // cAMD + memset(m_processor_name_string, 0, 48); + strcpy((char *)m_processor_name_string, "AMD Athlon(tm) Processor"); m_cpuid_max_input_value_eax = 0x01; m_cpu_version = REG32(EDX); @@ -4954,26 +4803,3 @@ void pentium4_device::device_reset() CHANGE_PC(m_eip); } - -uint64_t pentium4_device::opcode_rdmsr(bool &valid_msr) -{ - switch (REG32(ECX)) - { - default: - logerror("RDMSR: unimplemented register called %08x at %08x\n", REG32(ECX), m_pc - 2); - valid_msr = true; - return 0; - } - return -1; -} - -void pentium4_device::opcode_wrmsr(uint64_t data, bool &valid_msr) -{ - switch (REG32(ECX)) - { - default: - logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n", REG32(ECX), (uint32_t)(data >> 32), (uint32_t)data, m_pc - 2); - valid_msr = true; - break; - } -} diff --git a/src/devices/cpu/i386/i386.h b/src/devices/cpu/i386/i386.h index fe9236167ee..ed65129571b 100644 --- a/src/devices/cpu/i386/i386.h +++ b/src/devices/cpu/i386/i386.h @@ -1618,8 +1618,13 @@ public: athlonxp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: + virtual void opcode_cpuid() override; + virtual uint64_t opcode_rdmsr(bool &valid_msr) override; + virtual void opcode_wrmsr(uint64_t data, bool &valid_msr) override; virtual void device_start() override; virtual void device_reset() override; + + uint8_t m_processor_name_string[48]; }; -- cgit v1.2.3