1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:17:45 +00:00

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.
This commit is contained in:
Andreas Kling 2020-11-16 13:54:00 +01:00
parent b4ff85f138
commit d14695f823
2 changed files with 15 additions and 18 deletions

View file

@ -140,8 +140,9 @@ void SoftCPU::update_code_cache()
TODO(); TODO();
} }
m_cached_code_ptr = region->cacheable_ptr(eip() - region->base()); // FIXME: This cache needs to be invalidated if the code region is ever unmapped.
m_cached_code_end = region->cacheable_ptr(region->size()); m_cached_code_region = region;
m_cached_code_base_ptr = region->data();
} }
ValueWithShadow<u8> SoftCPU::read_memory8(X86::LogicalAddress address) ValueWithShadow<u8> SoftCPU::read_memory8(X86::LogicalAddress address)

View file

@ -26,6 +26,7 @@
#pragma once #pragma once
#include "Region.h"
#include "ValueWithShadow.h" #include "ValueWithShadow.h"
#include <LibX86/Instruction.h> #include <LibX86/Instruction.h>
#include <LibX86/Interpreter.h> #include <LibX86/Interpreter.h>
@ -33,6 +34,7 @@
namespace UserspaceEmulator { namespace UserspaceEmulator {
class Emulator; class Emulator;
class Region;
union PartAddressableRegister { union PartAddressableRegister {
struct { struct {
@ -68,8 +70,6 @@ public:
void set_eip(u32 eip) void set_eip(u32 eip)
{ {
m_eip = eip; m_eip = eip;
m_cached_code_ptr = nullptr;
m_cached_code_end = nullptr;
} }
struct Flags { struct Flags {
@ -1151,8 +1151,8 @@ private:
// FIXME: Or just something like m_flags_tainted? // FIXME: Or just something like m_flags_tainted?
ValueWithShadow<u16> m_fpu_cw { 0, 0 }; ValueWithShadow<u16> m_fpu_cw { 0, 0 };
const u8* m_cached_code_ptr { nullptr }; Region* m_cached_code_region { nullptr };
const u8* m_cached_code_end { nullptr }; u8* m_cached_code_base_ptr { nullptr };
u32 m_secret_handshake_state { 0 }; u32 m_secret_handshake_state { 0 };
u32 m_secret_data[3]; u32 m_secret_data[3];
@ -1160,44 +1160,40 @@ private:
ALWAYS_INLINE u8 SoftCPU::read8() 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(); update_code_cache();
u8 value = *m_cached_code_ptr; u8 value = m_cached_code_base_ptr[m_eip - m_cached_code_region->base()];
m_cached_code_ptr += 1;
m_eip += 1; m_eip += 1;
return value; return value;
} }
ALWAYS_INLINE u16 SoftCPU::read16() 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(); update_code_cache();
u16 value = *reinterpret_cast<const u16*>(m_cached_code_ptr); u16 value = *reinterpret_cast<const u16*>(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]);
m_cached_code_ptr += 2;
m_eip += 2; m_eip += 2;
return value; return value;
} }
ALWAYS_INLINE u32 SoftCPU::read32() 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(); update_code_cache();
u32 value = *reinterpret_cast<const u32*>(m_cached_code_ptr); u32 value = *reinterpret_cast<const u32*>(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]);
m_cached_code_ptr += 4;
m_eip += 4; m_eip += 4;
return value; return value;
} }
ALWAYS_INLINE u64 SoftCPU::read64() 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(); update_code_cache();
u64 value = *reinterpret_cast<const u64*>(m_cached_code_ptr); auto value = *reinterpret_cast<const u64*>(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]);
m_cached_code_ptr += 8;
m_eip += 8; m_eip += 8;
return value; return value;
} }