From d14695f823c5ee4e3876c8e917408ac78e1db5a0 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 16 Nov 2020 13:54:00 +0100 Subject: [PATCH] UserspaceEmulator: Cache the region we're executing code from Instead of caching a raw pointer to the next instruction, cache the region we're fetching instructions from, and a pointer to its base. This way we don't need to keep invalidating and reloading the cache whenever the CPU jumps. --- DevTools/UserspaceEmulator/SoftCPU.cpp | 5 +++-- DevTools/UserspaceEmulator/SoftCPU.h | 28 +++++++++++--------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index 3b050c212f..cec716739b 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -140,8 +140,9 @@ void SoftCPU::update_code_cache() TODO(); } - m_cached_code_ptr = region->cacheable_ptr(eip() - region->base()); - m_cached_code_end = region->cacheable_ptr(region->size()); + // FIXME: This cache needs to be invalidated if the code region is ever unmapped. + m_cached_code_region = region; + m_cached_code_base_ptr = region->data(); } ValueWithShadow SoftCPU::read_memory8(X86::LogicalAddress address) diff --git a/DevTools/UserspaceEmulator/SoftCPU.h b/DevTools/UserspaceEmulator/SoftCPU.h index 0951cdc9cc..7a29cb30f4 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.h +++ b/DevTools/UserspaceEmulator/SoftCPU.h @@ -26,6 +26,7 @@ #pragma once +#include "Region.h" #include "ValueWithShadow.h" #include #include @@ -33,6 +34,7 @@ namespace UserspaceEmulator { class Emulator; +class Region; union PartAddressableRegister { struct { @@ -68,8 +70,6 @@ public: void set_eip(u32 eip) { m_eip = eip; - m_cached_code_ptr = nullptr; - m_cached_code_end = nullptr; } struct Flags { @@ -1151,8 +1151,8 @@ private: // FIXME: Or just something like m_flags_tainted? ValueWithShadow m_fpu_cw { 0, 0 }; - const u8* m_cached_code_ptr { nullptr }; - const u8* m_cached_code_end { nullptr }; + Region* m_cached_code_region { nullptr }; + u8* m_cached_code_base_ptr { nullptr }; u32 m_secret_handshake_state { 0 }; u32 m_secret_data[3]; @@ -1160,44 +1160,40 @@ private: ALWAYS_INLINE u8 SoftCPU::read8() { - if (!m_cached_code_ptr || m_cached_code_ptr >= m_cached_code_end) + if (!m_cached_code_region || !m_cached_code_region->contains(m_eip)) update_code_cache(); - u8 value = *m_cached_code_ptr; - m_cached_code_ptr += 1; + u8 value = m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]; m_eip += 1; return value; } ALWAYS_INLINE u16 SoftCPU::read16() { - if (!m_cached_code_ptr || (m_cached_code_ptr + 1) >= m_cached_code_end) + if (!m_cached_code_region || !m_cached_code_region->contains(m_eip)) update_code_cache(); - u16 value = *reinterpret_cast(m_cached_code_ptr); - m_cached_code_ptr += 2; + u16 value = *reinterpret_cast(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]); m_eip += 2; return value; } ALWAYS_INLINE u32 SoftCPU::read32() { - if (!m_cached_code_ptr || (m_cached_code_ptr + 3) >= m_cached_code_end) + if (!m_cached_code_region || !m_cached_code_region->contains(m_eip)) update_code_cache(); - u32 value = *reinterpret_cast(m_cached_code_ptr); - m_cached_code_ptr += 4; + u32 value = *reinterpret_cast(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]); m_eip += 4; return value; } ALWAYS_INLINE u64 SoftCPU::read64() { - if (!m_cached_code_ptr || (m_cached_code_ptr + 7) >= m_cached_code_end) + if (!m_cached_code_region || !m_cached_code_region->contains(m_eip)) update_code_cache(); - u64 value = *reinterpret_cast(m_cached_code_ptr); - m_cached_code_ptr += 8; + auto value = *reinterpret_cast(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]); m_eip += 8; return value; }