diff --git a/src/devices/cpu/i386/cpuidmsrs.hxx b/src/devices/cpu/i386/cpuidmsrs.hxx index 842ff85b4b2..8b02d7828cd 100644 --- a/src/devices/cpu/i386/cpuidmsrs.hxx +++ b/src/devices/cpu/i386/cpuidmsrs.hxx @@ -347,6 +347,7 @@ uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr) // 20 MtrrVarDramEn - Enable top of memory address and I/O range registers // 19 MtrrFixDramModEn - Enable modification of RdDram and WrDram bits in fixed MTRRs // 18 MtrrFixDramEn - Enable RdDram and WrDram attributes in fixed MTRRs + ret = m_msr_sys_cfg; break; case 0xC0010015: // HWCR break; @@ -363,6 +364,7 @@ uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr) break; case 0xC001001A: // TOP_MEM // 39-23 TOM16-0 - Top of Memory, accesses from this address onward are directed to mmio + ret = (uint64_t)m_msr_top_mem; break; case 0xC001001D: // TOP_MEM2 break; @@ -434,6 +436,7 @@ void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr) case 0x40c: // MC3_CTL break; case 0xC0010010: // SYS_CFG + m_msr_sys_cfg = data; break; case 0xC0010015: // HWCR break; @@ -443,6 +446,7 @@ void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr) case 0xC0010019: break; case 0xC001001A: // TOP_MEM + m_msr_top_mem = (offs_t)data; break; case 0xC0010113: // SMM_MASK break; diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp index 22123c46387..97dd5e5a8b6 100644 --- a/src/devices/cpu/i386/i386.cpp +++ b/src/devices/cpu/i386/i386.cpp @@ -133,6 +133,8 @@ pentium3_device::pentium3_device(const machine_config &mconfig, const char *tag, athlonxp_device::athlonxp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : pentium_device(mconfig, ATHLONXP, tag, owner, clock) + , m_data_config("mmio", ENDIANNESS_LITTLE, 32, 32, 0, 32, 12) + , m_opcodes_config("debugger", ENDIANNESS_LITTLE, 32, 32, 0, 32, 12) { // TODO: put correct value set_vtlb_dynamic_entries(256); @@ -4692,11 +4694,22 @@ void athlonxp_device::device_start() { i386_common_init(); register_state_i386_x87_xmm(); + m_data = &space(AS_DATA); + m_opcodes = &space(AS_OPCODES); + mmacache32 = m_data->cache<2, 0, ENDIANNESS_LITTLE>(); + m_opcodes->install_read_handler(0, 0xffffffff, read32_delegate(FUNC(athlonxp_device::debug_read_memory), this)); build_x87_opcode_table(); build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO | OP_MMX | OP_SSE); m_cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM].get(); // TODO: generate own cycle tables m_cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM].get(); // TODO: generate own cycle tables + + // put savestate calls here + save_item(NAME(m_processor_name_string)); + save_item(NAME(m_msr_top_mem)); + save_item(NAME(m_msr_sys_cfg)); + save_item(NAME(m_msr_mtrrfix)); + save_item(NAME(m_memory_ranges_1m)); } void athlonxp_device::device_reset() @@ -4745,7 +4758,9 @@ void athlonxp_device::device_reset() for (int n = 0; n < 11; n++) m_msr_mtrrfix[n] = 0; for (int n = 0; n < (1024 / 4); n++) - m_memory_ranges_1m[n] = 0; // change the 0 to 6 to test the cache just after reset + m_memory_ranges_1m[n] = 0; + m_msr_top_mem = 1024 * 1024; + m_msr_sys_cfg = 0; m_cpuid_max_input_value_eax = 0x01; m_cpu_version = REG32(EDX); @@ -4756,6 +4771,16 @@ void athlonxp_device::device_reset() CHANGE_PC(m_eip); } +device_memory_interface::space_config_vector athlonxp_device::memory_space_config() const +{ + return space_config_vector{ + std::make_pair(AS_PROGRAM, &m_program_config), + std::make_pair(AS_IO, &m_io_config), + std::make_pair(AS_DATA, &m_data_config), + std::make_pair(AS_OPCODES, &m_opcodes_config) + }; +} + void athlonxp_device::parse_mtrrfix(u64 mtrr, offs_t base, int kblock) { int nb = kblock / 4; @@ -4788,11 +4813,48 @@ int athlonxp_device::check_cacheable(offs_t address) return m_memory_ranges_1m[block] | disabled; } +template +int athlonxp_device::address_mode(offs_t address) +{ + if (address >= m_msr_top_mem) + return 1; + if (address >= 1 * 1024 * 1024) + return 0; + if ((m_memory_ranges_1m[address >> 12] & (1 << (3 + wr))) != 0) + return 0; + return 1; +} + +READ32_MEMBER(athlonxp_device::debug_read_memory) +{ + offs_t address = offset << 2; + int mode = check_cacheable(address); + bool nocache = false; + address_space *m = m_program; + u8 *data; + + if ((mode & 7) == 0) + nocache = true; + if (mode & 1) + nocache = true; + if (nocache == false) + { + int offset = (address & 63); + data = cache.search(address); + if (data) + return *(u32 *)(data + offset); + } + if (address_mode<1>(address)) + m = m_data; + return m->read_dword(address); +} + template dt athlonxp_device::opcode_read_cache(offs_t address) { int mode = check_cacheable(address); bool nocache = false; + memory_access_cache<2, 0, ENDIANNESS_LITTLE> *m = macache32; u8 *data; if ((mode & 7) == 0) @@ -4814,31 +4876,21 @@ dt athlonxp_device::opcode_read_cache(offs_t address) offs_t old_address = cache.old(); for (int w = 0; w < 64; w += 4) - macache32->write_dword(old_address + w, *(u32 *)(data + w)); + m->write_dword(old_address + w, *(u32 *)(data + w)); } for (int r = 0; r < 64; r += 4) - *(u32 *)(data + r) = macache32->read_dword(address + r); + *(u32 *)(data + r) = m->read_dword(address + r); return *(dt *)(data + offset); } - else - { - if (sizeof(dt) == 1) - return macache32->read_byte(address); - else if (sizeof(dt) == 2) - return macache32->read_word(address); - else - return macache32->read_dword(address); - } } + if (address_mode<1>(address)) + m = mmacache32; + if (sizeof(dt) == 1) + return m->read_byte(address); + else if (sizeof(dt) == 2) + return m->read_word(address); else - { - if (sizeof(dt) == 1) - return macache32->read_byte(address); - else if (sizeof(dt) == 2) - return macache32->read_word(address); - else - return macache32->read_dword(address); - } + return m->read_dword(address); } template @@ -4846,6 +4898,7 @@ dt athlonxp_device::program_read_cache(offs_t address) { int mode = check_cacheable(address); bool nocache = false; + address_space *m = m_program; u8 *data; if ((mode & 7) == 0) @@ -4867,31 +4920,21 @@ dt athlonxp_device::program_read_cache(offs_t address) offs_t old_address = cache.old(); for (int w = 0; w < 64; w += 4) - m_program->write_dword(old_address + w, *(u32 *)(data + w)); + m->write_dword(old_address + w, *(u32 *)(data + w)); } for (int r = 0; r < 64; r += 4) - *(u32 *)(data + r) = m_program->read_dword(address + r); + *(u32 *)(data + r) = m->read_dword(address + r); return *(dt *)(data + offset); } - else - { - if (sizeof(dt) == 1) - return m_program->read_byte(address); - else if (sizeof(dt) == 2) - return m_program->read_word(address); - else - return m_program->read_dword(address); - } } + if (address_mode<1>(address)) + m = m_data; + if (sizeof(dt) == 1) + return m->read_byte(address); + else if (sizeof(dt) == 2) + return m->read_word(address); else - { - if (sizeof(dt) == 1) - return m_program->read_byte(address); - else if (sizeof(dt) == 2) - return m_program->read_word(address); - else - return m_program->read_dword(address); - } + return m->read_dword(address); } template @@ -4899,6 +4942,7 @@ void athlonxp_device::program_write_cache(offs_t address, dt data) { int mode = check_cacheable(address); bool nocache = false; + address_space *m = m_program; u8 *dataw; if ((mode & 7) == 0) @@ -4923,36 +4967,28 @@ void athlonxp_device::program_write_cache(offs_t address, dt data) offs_t old_address = cache.old(); for (int w = 0; w < 64; w += 4) - m_program->write_dword(old_address + w, *(u32 *)(dataw + w)); + m->write_dword(old_address + w, *(u32 *)(dataw + w)); } for (int r = 0; r < 64; r += 4) - *(u32 *)(dataw + r) = m_program->read_dword(address + r); + *(u32 *)(dataw + r) = m->read_dword(address + r); *(dt *)(dataw + offset) = data; - } - else - { - if (sizeof(dt) == 1) - m_program->write_byte(address, data); - else if (sizeof(dt) == 2) - m_program->write_word(address, data); - else - m_program->write_dword(address, data); + return; } } + if (address_mode<0>(address)) + m = m_data; + if (sizeof(dt) == 1) + m->write_byte(address, data); + else if (sizeof(dt) == 2) + m->write_word(address, data); else - { - if (sizeof(dt) == 1) - m_program->write_byte(address, data); - else if (sizeof(dt) == 2) - m_program->write_word(address, data); - else - m_program->write_dword(address, data); - } + m->write_dword(address, data); } void athlonxp_device::cache_writeback() { // dirty cachelines are written back to memory + address_space *m = m_program; u32 base; u8 *data; @@ -4960,7 +4996,7 @@ void athlonxp_device::cache_writeback() while (data != nullptr) { for (int w = 0; w < 64; w += 4) - m_program->write_dword(base + w, *(u32 *)(data + w)); + m->write_dword(base + w, *(u32 *)(data + w)); data = cache.next_dirty(base, false); } } diff --git a/src/devices/cpu/i386/i386.h b/src/devices/cpu/i386/i386.h index 6fd0dc04266..e3182fcfb81 100644 --- a/src/devices/cpu/i386/i386.h +++ b/src/devices/cpu/i386/i386.h @@ -1655,15 +1655,28 @@ protected: virtual void mem_pwd16(offs_t address, u16 data) override { program_write_cache(address, data); } virtual void mem_pwd32(offs_t address, u32 data) override { program_write_cache(address, data); } + // device_memory_interface override + virtual space_config_vector memory_space_config() const override; + private: void parse_mtrrfix(u64 mtrr, offs_t base, int kblock); - int check_cacheable(offs_t address); + inline int check_cacheable(offs_t address); + template int address_mode(offs_t address); template dt opcode_read_cache(offs_t address); template dt program_read_cache(offs_t address); template void program_write_cache(offs_t address, dt data); + DECLARE_READ32_MEMBER(debug_read_memory); + + address_space_config m_data_config; + address_space *m_data; + address_space_config m_opcodes_config; + address_space *m_opcodes; + memory_access_cache<2, 0, ENDIANNESS_LITTLE> *mmacache32; uint8_t m_processor_name_string[48]; + offs_t m_msr_top_mem; + uint64_t m_msr_sys_cfg; uint64_t m_msr_mtrrfix[11]; uint8_t m_memory_ranges_1m[1024 / 4]; cpucache<17, 9, Cache2Way, CacheLineBytes64> cache; // 512 sets, 2 ways (cachelines per set), 64 bytes per cacheline