From 551eb4328c5969733997eb7aa597a501e9561d15 Mon Sep 17 00:00:00 2001 From: yz70s Date: Fri, 5 Apr 2019 10:40:21 +0200 Subject: i386.cpp: add new mame debugger function cacheflush(x) to writeback cache (nw) cacheflush() or cacheflush(0) writes back dirty cachelines to ram cacheflush(1) also marks dirty cachelines as clean cacheflush(2) or cacheflush(3) also invalidates the whole cache --- src/devices/cpu/i386/i386.cpp | 49 +++++++++++++++++++++++++++++++++---------- src/devices/cpu/i386/i386.h | 17 ++++++++++----- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp index f372dba1239..22123c46387 100644 --- a/src/devices/cpu/i386/i386.cpp +++ b/src/devices/cpu/i386/i386.cpp @@ -3316,6 +3316,26 @@ uint64_t i386_device::debug_virttophys(symbol_table &table, int params, const ui return result; } +uint64_t i386_device::debug_cacheflush(symbol_table &table, int params, const uint64_t *param) +{ + uint32_t option; + bool invalidate; + bool clean; + + if (params > 0) + option = param[0]; + else + option = 0; + invalidate = (option & 1) != 0; + clean = (option & 2) != 0; + cache_writeback(); + if (invalidate) + cache_invalidate(); + if (clean) + cache_clean(); + return 0; +} + void i386_device::device_debug_setup() { using namespace std::placeholders; @@ -3323,6 +3343,7 @@ void i386_device::device_debug_setup() debug()->symtable().add("seglimit", 1, 1, std::bind(&i386_device::debug_seglimit, this, _1, _2, _3)); debug()->symtable().add("segofftovirt", 2, 2, std::bind(&i386_device::debug_segofftovirt, this, _1, _2, _3)); debug()->symtable().add("virttophys", 1, 1, std::bind(&i386_device::debug_virttophys, this, _1, _2, _3)); + debug()->symtable().add("cacheflush", 0, 1, std::bind(&i386_device::debug_cacheflush, this, _1, _2, _3)); } /*************************************************************************/ @@ -4929,30 +4950,36 @@ void athlonxp_device::program_write_cache(offs_t address, dt data) } } -void athlonxp_device::invalidate_cache(bool writeback) +void athlonxp_device::cache_writeback() { + // dirty cachelines are written back to memory u32 base; u8 *data; - data = cache.first_dirty(base, true); + data = cache.first_dirty(base, false); while (data != nullptr) { - if (writeback) - for (int w = 0; w < 64; w += 4) - m_program->write_dword(base + w, *(u32 *)(data + w)); - data = cache.next_dirty(base, true); + for (int w = 0; w < 64; w += 4) + m_program->write_dword(base + w, *(u32 *)(data + w)); + data = cache.next_dirty(base, false); } - cache.reset(); } -void athlonxp_device::opcode_invd() +void athlonxp_device::cache_invalidate() { - invalidate_cache(false); + // dirty cachelines are not written back to memory + cache.reset(); } -void athlonxp_device::opcode_wbinvd() +void athlonxp_device::cache_clean() { - invalidate_cache(true); + // dirty cachelines are marked as clean but not written back to memory + u32 base; + u8 *data; + + data = cache.first_dirty(base, true); + while (data != nullptr) + data = cache.next_dirty(base, true); } diff --git a/src/devices/cpu/i386/i386.h b/src/devices/cpu/i386/i386.h index 90aab9f0667..6fd0dc04266 100644 --- a/src/devices/cpu/i386/i386.h +++ b/src/devices/cpu/i386/i386.h @@ -41,6 +41,7 @@ public: uint64_t debug_seglimit(symbol_table &table, int params, const uint64_t *param); uint64_t debug_segofftovirt(symbol_table &table, int params, const uint64_t *param); uint64_t debug_virttophys(symbol_table &table, int params, const uint64_t *param); + uint64_t debug_cacheflush(symbol_table &table, int params, const uint64_t *param); protected: i386_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int program_data_width, int program_addr_width, int io_data_width); @@ -76,8 +77,14 @@ protected: virtual void opcode_cpuid(); virtual uint64_t opcode_rdmsr(bool &valid_msr); virtual void opcode_wrmsr(uint64_t data, bool &valid_msr); - virtual void opcode_invd() {} - virtual void opcode_wbinvd() {} + virtual void opcode_invd() { cache_invalidate(); } + virtual void opcode_wbinvd() { cache_writeback(); cache_invalidate(); } + + // routines for the cache + // default implementation assumes there is no cache + virtual void cache_writeback() {} + virtual void cache_invalidate() {} + virtual void cache_clean() {} // routine to access memory virtual u8 mem_pr8(offs_t address) { return macache32->read_byte(address); } @@ -1632,8 +1639,9 @@ 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 opcode_invd() override; - virtual void opcode_wbinvd() override; + virtual void cache_writeback() override; + virtual void cache_invalidate() override; + virtual void cache_clean() override; virtual void device_start() override; virtual void device_reset() override; @@ -1650,7 +1658,6 @@ protected: private: void parse_mtrrfix(u64 mtrr, offs_t base, int kblock); int check_cacheable(offs_t address); - void invalidate_cache(bool writeback); template dt opcode_read_cache(offs_t address); template dt program_read_cache(offs_t address); -- cgit v1.2.3