diff --git a/DevTools/UserspaceEmulator/SimpleRegion.cpp b/DevTools/UserspaceEmulator/SimpleRegion.cpp index 324e651798..c77ad7eefa 100644 --- a/DevTools/UserspaceEmulator/SimpleRegion.cpp +++ b/DevTools/UserspaceEmulator/SimpleRegion.cpp @@ -75,4 +75,9 @@ void SimpleRegion::write32(u32 offset, u32 value) *reinterpret_cast(m_data + offset) = value; } +u8* SimpleRegion::cacheable_ptr(u32 offset) +{ + return m_data + offset; +} + } diff --git a/DevTools/UserspaceEmulator/SimpleRegion.h b/DevTools/UserspaceEmulator/SimpleRegion.h index c4df498882..6cbe707c04 100644 --- a/DevTools/UserspaceEmulator/SimpleRegion.h +++ b/DevTools/UserspaceEmulator/SimpleRegion.h @@ -45,6 +45,8 @@ public: u8* data() { return m_data; } + virtual u8* cacheable_ptr(u32 offset) override; + private: u8* m_data { nullptr }; }; diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index bd6f06d20e..980ce3bb83 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -61,23 +61,44 @@ void SoftCPU::dump() const printf("o=%u s=%u z=%u a=%u p=%u c=%u\n", of(), sf(), zf(), af(), pf(), cf()); } +void SoftCPU::update_code_cache() +{ + auto* region = m_emulator.mmu().find_region({ cs(), eip() }); + ASSERT(region); + + m_cached_code_ptr = region->cacheable_ptr(eip() - region->base()); + m_cached_code_end = region->cacheable_ptr(region->size()); +} + u8 SoftCPU::read8() { - auto value = read_memory8({ cs(), eip() }); + if (!m_cached_code_ptr || m_cached_code_ptr >= m_cached_code_end) + update_code_cache(); + + u8 value = *m_cached_code_ptr; + m_cached_code_ptr += 1; m_eip += 1; return value; } u16 SoftCPU::read16() { - auto value = read_memory16({ cs(), eip() }); + if (!m_cached_code_ptr || (m_cached_code_ptr + 2) >= m_cached_code_end) + update_code_cache(); + + u16 value = *reinterpret_cast(m_cached_code_ptr); + m_cached_code_ptr += 2; m_eip += 2; return value; } u32 SoftCPU::read32() { - auto value = read_memory32({ cs(), eip() }); + if (!m_cached_code_ptr || (m_cached_code_ptr + 4) >= m_cached_code_end) + update_code_cache(); + + u32 value = *reinterpret_cast(m_cached_code_ptr); + m_cached_code_ptr += 4; m_eip += 4; return value; } diff --git a/DevTools/UserspaceEmulator/SoftCPU.h b/DevTools/UserspaceEmulator/SoftCPU.h index 6d8670e74f..137506daab 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.h +++ b/DevTools/UserspaceEmulator/SoftCPU.h @@ -56,7 +56,12 @@ public: void dump() const; u32 eip() const { return m_eip; } - void set_eip(u32 eip) { m_eip = eip; } + void set_eip(u32 eip) + { + m_eip = eip; + m_cached_code_ptr = nullptr; + m_cached_code_end = nullptr; + } struct Flags { enum Flag { @@ -792,6 +797,8 @@ private: template void do_once_or_repeat(const X86::Instruction& insn, Callback); + void update_code_cache(); + private: Emulator& m_emulator; @@ -800,6 +807,9 @@ private: u32 m_eflags { 0 }; u32 m_eip { 0 }; + + const u8* m_cached_code_ptr { nullptr }; + const u8* m_cached_code_end { nullptr }; }; } diff --git a/DevTools/UserspaceEmulator/SoftMMU.h b/DevTools/UserspaceEmulator/SoftMMU.h index 53c75598d6..9d34cf2883 100644 --- a/DevTools/UserspaceEmulator/SoftMMU.h +++ b/DevTools/UserspaceEmulator/SoftMMU.h @@ -53,6 +53,8 @@ public: virtual u16 read16(u32 offset) = 0; virtual u32 read32(u32 offset) = 0; + virtual u8* cacheable_ptr([[maybe_unused]] u32 offset) { return nullptr; } + protected: Region(u32 base, u32 size) : m_base(base)