mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
UE+LibX86: Support bigger reads and writes
This commit is contained in:
parent
a99812633b
commit
f1957bb86b
Notes:
sideshowbarker
2024-07-18 19:10:23 +09:00
Author: https://github.com/Hendiadyoin1 Commit: https://github.com/SerenityOS/serenity/commit/f1957bb86bd Pull-request: https://github.com/SerenityOS/serenity/pull/6225 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/bcoles
11 changed files with 316 additions and 4 deletions
|
@ -129,6 +129,40 @@ ValueWithShadow<u64> MmapRegion::read64(u32 offset)
|
||||||
return { *reinterpret_cast<const u64*>(m_data + offset), *reinterpret_cast<const u64*>(m_shadow_data + offset) };
|
return { *reinterpret_cast<const u64*>(m_data + offset), *reinterpret_cast<const u64*>(m_shadow_data + offset) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueWithShadow<u128> MmapRegion::read128(u32 offset)
|
||||||
|
{
|
||||||
|
if (!is_readable()) {
|
||||||
|
reportln("128-bit read from unreadable MmapRegion @ {:p}", base() + offset);
|
||||||
|
emulator().dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_malloc_block()) {
|
||||||
|
if (auto* tracer = emulator().malloc_tracer())
|
||||||
|
tracer->audit_read(*this, base() + offset, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY(offset + 15 < size());
|
||||||
|
return { *reinterpret_cast<const u128*>(m_data + offset), *reinterpret_cast<const u128*>(m_shadow_data + offset) };
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueWithShadow<u256> MmapRegion::read256(u32 offset)
|
||||||
|
{
|
||||||
|
if (!is_readable()) {
|
||||||
|
reportln("256-bit read from unreadable MmapRegion @ {:p}", base() + offset);
|
||||||
|
emulator().dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_malloc_block()) {
|
||||||
|
if (auto* tracer = emulator().malloc_tracer())
|
||||||
|
tracer->audit_read(*this, base() + offset, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY(offset + 31 < size());
|
||||||
|
return { *reinterpret_cast<const u256*>(m_data + offset), *reinterpret_cast<const u256*>(m_shadow_data + offset) };
|
||||||
|
}
|
||||||
|
|
||||||
void MmapRegion::write8(u32 offset, ValueWithShadow<u8> value)
|
void MmapRegion::write8(u32 offset, ValueWithShadow<u8> value)
|
||||||
{
|
{
|
||||||
if (!is_writable()) {
|
if (!is_writable()) {
|
||||||
|
@ -203,6 +237,44 @@ void MmapRegion::write64(u32 offset, ValueWithShadow<u64> value)
|
||||||
*reinterpret_cast<u64*>(m_shadow_data + offset) = value.shadow();
|
*reinterpret_cast<u64*>(m_shadow_data + offset) = value.shadow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MmapRegion::write128(u32 offset, ValueWithShadow<u128> value)
|
||||||
|
{
|
||||||
|
if (!is_writable()) {
|
||||||
|
reportln("128-bit write from unwritable MmapRegion @ {:p}", base() + offset);
|
||||||
|
emulator().dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_malloc_block()) {
|
||||||
|
if (auto* tracer = emulator().malloc_tracer())
|
||||||
|
tracer->audit_write(*this, base() + offset, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY(offset + 15 < size());
|
||||||
|
VERIFY(m_data != m_shadow_data);
|
||||||
|
*reinterpret_cast<u128*>(m_data + offset) = value.value();
|
||||||
|
*reinterpret_cast<u128*>(m_shadow_data + offset) = value.shadow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MmapRegion::write256(u32 offset, ValueWithShadow<u256> value)
|
||||||
|
{
|
||||||
|
if (!is_writable()) {
|
||||||
|
reportln("256-bit write from unwritable MmapRegion @ {:p}", base() + offset);
|
||||||
|
emulator().dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_malloc_block()) {
|
||||||
|
if (auto* tracer = emulator().malloc_tracer())
|
||||||
|
tracer->audit_write(*this, base() + offset, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY(offset + 31 < size());
|
||||||
|
VERIFY(m_data != m_shadow_data);
|
||||||
|
*reinterpret_cast<u256*>(m_data + offset) = value.value();
|
||||||
|
*reinterpret_cast<u256*>(m_shadow_data + offset) = value.shadow();
|
||||||
|
}
|
||||||
|
|
||||||
NonnullOwnPtr<MmapRegion> MmapRegion::split_at(VirtualAddress offset)
|
NonnullOwnPtr<MmapRegion> MmapRegion::split_at(VirtualAddress offset)
|
||||||
{
|
{
|
||||||
VERIFY(!m_malloc);
|
VERIFY(!m_malloc);
|
||||||
|
|
|
@ -24,11 +24,15 @@ public:
|
||||||
virtual ValueWithShadow<u16> read16(u32 offset) override;
|
virtual ValueWithShadow<u16> read16(u32 offset) override;
|
||||||
virtual ValueWithShadow<u32> read32(u32 offset) override;
|
virtual ValueWithShadow<u32> read32(u32 offset) override;
|
||||||
virtual ValueWithShadow<u64> read64(u32 offset) override;
|
virtual ValueWithShadow<u64> read64(u32 offset) override;
|
||||||
|
virtual ValueWithShadow<u128> read128(u32 offset) override;
|
||||||
|
virtual ValueWithShadow<u256> read256(u32 offset) override;
|
||||||
|
|
||||||
virtual void write8(u32 offset, ValueWithShadow<u8>) override;
|
virtual void write8(u32 offset, ValueWithShadow<u8>) override;
|
||||||
virtual void write16(u32 offset, ValueWithShadow<u16>) override;
|
virtual void write16(u32 offset, ValueWithShadow<u16>) override;
|
||||||
virtual void write32(u32 offset, ValueWithShadow<u32>) override;
|
virtual void write32(u32 offset, ValueWithShadow<u32>) override;
|
||||||
virtual void write64(u32 offset, ValueWithShadow<u64>) override;
|
virtual void write64(u32 offset, ValueWithShadow<u64>) override;
|
||||||
|
virtual void write128(u32 offset, ValueWithShadow<u128>) override;
|
||||||
|
virtual void write256(u32 offset, ValueWithShadow<u256>) override;
|
||||||
|
|
||||||
virtual u8* data() override { return m_data; }
|
virtual u8* data() override { return m_data; }
|
||||||
virtual u8* shadow_data() override { return m_shadow_data; }
|
virtual u8* shadow_data() override { return m_shadow_data; }
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "ValueWithShadow.h"
|
#include "ValueWithShadow.h"
|
||||||
#include <AK/TypeCasts.h>
|
#include <AK/TypeCasts.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
#include <LibX86/Types.h>
|
||||||
|
|
||||||
namespace UserspaceEmulator {
|
namespace UserspaceEmulator {
|
||||||
|
|
||||||
|
@ -31,11 +32,15 @@ public:
|
||||||
virtual void write16(u32 offset, ValueWithShadow<u16>) = 0;
|
virtual void write16(u32 offset, ValueWithShadow<u16>) = 0;
|
||||||
virtual void write32(u32 offset, ValueWithShadow<u32>) = 0;
|
virtual void write32(u32 offset, ValueWithShadow<u32>) = 0;
|
||||||
virtual void write64(u32 offset, ValueWithShadow<u64>) = 0;
|
virtual void write64(u32 offset, ValueWithShadow<u64>) = 0;
|
||||||
|
virtual void write128(u32 offset, ValueWithShadow<u128>) = 0;
|
||||||
|
virtual void write256(u32 offset, ValueWithShadow<u256>) = 0;
|
||||||
|
|
||||||
virtual ValueWithShadow<u8> read8(u32 offset) = 0;
|
virtual ValueWithShadow<u8> read8(u32 offset) = 0;
|
||||||
virtual ValueWithShadow<u16> read16(u32 offset) = 0;
|
virtual ValueWithShadow<u16> read16(u32 offset) = 0;
|
||||||
virtual ValueWithShadow<u32> read32(u32 offset) = 0;
|
virtual ValueWithShadow<u32> read32(u32 offset) = 0;
|
||||||
virtual ValueWithShadow<u64> read64(u32 offset) = 0;
|
virtual ValueWithShadow<u64> read64(u32 offset) = 0;
|
||||||
|
virtual ValueWithShadow<u128> read128(u32 offset) = 0;
|
||||||
|
virtual ValueWithShadow<u256> read256(u32 offset) = 0;
|
||||||
|
|
||||||
virtual u8* cacheable_ptr([[maybe_unused]] u32 offset) { return nullptr; }
|
virtual u8* cacheable_ptr([[maybe_unused]] u32 offset) { return nullptr; }
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,18 @@ ValueWithShadow<u64> SimpleRegion::read64(u32 offset)
|
||||||
return { *reinterpret_cast<const u64*>(m_data + offset), *reinterpret_cast<const u64*>(m_shadow_data + offset) };
|
return { *reinterpret_cast<const u64*>(m_data + offset), *reinterpret_cast<const u64*>(m_shadow_data + offset) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueWithShadow<u128> SimpleRegion::read128(u32 offset)
|
||||||
|
{
|
||||||
|
VERIFY(offset + 15 < size());
|
||||||
|
return { *reinterpret_cast<const u128*>(m_data + offset), *reinterpret_cast<const u128*>(m_shadow_data + offset) };
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueWithShadow<u256> SimpleRegion::read256(u32 offset)
|
||||||
|
{
|
||||||
|
VERIFY(offset + 31 < size());
|
||||||
|
return { *reinterpret_cast<const u256*>(m_data + offset), *reinterpret_cast<const u256*>(m_shadow_data + offset) };
|
||||||
|
}
|
||||||
|
|
||||||
void SimpleRegion::write8(u32 offset, ValueWithShadow<u8> value)
|
void SimpleRegion::write8(u32 offset, ValueWithShadow<u8> value)
|
||||||
{
|
{
|
||||||
VERIFY(offset < size());
|
VERIFY(offset < size());
|
||||||
|
@ -74,6 +86,18 @@ void SimpleRegion::write64(u32 offset, ValueWithShadow<u64> value)
|
||||||
*reinterpret_cast<u64*>(m_data + offset) = value.value();
|
*reinterpret_cast<u64*>(m_data + offset) = value.value();
|
||||||
*reinterpret_cast<u64*>(m_shadow_data + offset) = value.shadow();
|
*reinterpret_cast<u64*>(m_shadow_data + offset) = value.shadow();
|
||||||
}
|
}
|
||||||
|
void SimpleRegion::write128(u32 offset, ValueWithShadow<u128> value)
|
||||||
|
{
|
||||||
|
VERIFY(offset + 15 < size());
|
||||||
|
*reinterpret_cast<u128*>(m_data + offset) = value.value();
|
||||||
|
*reinterpret_cast<u128*>(m_shadow_data + offset) = value.shadow();
|
||||||
|
}
|
||||||
|
void SimpleRegion::write256(u32 offset, ValueWithShadow<u256> value)
|
||||||
|
{
|
||||||
|
VERIFY(offset + 31 < size());
|
||||||
|
*reinterpret_cast<u256*>(m_data + offset) = value.value();
|
||||||
|
*reinterpret_cast<u256*>(m_shadow_data + offset) = value.shadow();
|
||||||
|
}
|
||||||
|
|
||||||
u8* SimpleRegion::cacheable_ptr(u32 offset)
|
u8* SimpleRegion::cacheable_ptr(u32 offset)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,11 +19,15 @@ public:
|
||||||
virtual ValueWithShadow<u16> read16(u32 offset) override;
|
virtual ValueWithShadow<u16> read16(u32 offset) override;
|
||||||
virtual ValueWithShadow<u32> read32(u32 offset) override;
|
virtual ValueWithShadow<u32> read32(u32 offset) override;
|
||||||
virtual ValueWithShadow<u64> read64(u32 offset) override;
|
virtual ValueWithShadow<u64> read64(u32 offset) override;
|
||||||
|
virtual ValueWithShadow<u128> read128(u32 offset) override;
|
||||||
|
virtual ValueWithShadow<u256> read256(u32 offset) override;
|
||||||
|
|
||||||
virtual void write8(u32 offset, ValueWithShadow<u8>) override;
|
virtual void write8(u32 offset, ValueWithShadow<u8>) override;
|
||||||
virtual void write16(u32 offset, ValueWithShadow<u16>) override;
|
virtual void write16(u32 offset, ValueWithShadow<u16>) override;
|
||||||
virtual void write32(u32 offset, ValueWithShadow<u32>) override;
|
virtual void write32(u32 offset, ValueWithShadow<u32>) override;
|
||||||
virtual void write64(u32 offset, ValueWithShadow<u64>) override;
|
virtual void write64(u32 offset, ValueWithShadow<u64>) override;
|
||||||
|
virtual void write128(u32 offset, ValueWithShadow<u128>) override;
|
||||||
|
virtual void write256(u32 offset, ValueWithShadow<u256>) override;
|
||||||
|
|
||||||
virtual u8* data() override { return m_data; }
|
virtual u8* data() override { return m_data; }
|
||||||
virtual u8* shadow_data() override { return m_shadow_data; }
|
virtual u8* shadow_data() override { return m_shadow_data; }
|
||||||
|
|
|
@ -133,6 +133,25 @@ ValueWithShadow<u64> SoftCPU::read_memory64(X86::LogicalAddress address)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueWithShadow<u128> SoftCPU::read_memory128(X86::LogicalAddress address)
|
||||||
|
{
|
||||||
|
VERIFY(address.selector() == 0x1b || address.selector() == 0x23 || address.selector() == 0x2b);
|
||||||
|
auto value = m_emulator.mmu().read128(address);
|
||||||
|
#if MEMORY_DEBUG
|
||||||
|
outln("\033[36;1mread_memory128: @{:04x}:{:08x} -> {:032x} ({:032x})\033[0m", address.selector(), address.offset(), value, value.shadow());
|
||||||
|
#endif
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
ValueWithShadow<u256> SoftCPU::read_memory256(X86::LogicalAddress address)
|
||||||
|
{
|
||||||
|
VERIFY(address.selector() == 0x1b || address.selector() == 0x23 || address.selector() == 0x2b);
|
||||||
|
auto value = m_emulator.mmu().read256(address);
|
||||||
|
#if MEMORY_DEBUG
|
||||||
|
outln("\033[36;1mread_memory256: @{:04x}:{:08x} -> {:064x} ({:064x})\033[0m", address.selector(), address.offset(), value, value.shadow());
|
||||||
|
#endif
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
void SoftCPU::write_memory8(X86::LogicalAddress address, ValueWithShadow<u8> value)
|
void SoftCPU::write_memory8(X86::LogicalAddress address, ValueWithShadow<u8> value)
|
||||||
{
|
{
|
||||||
VERIFY(address.selector() == 0x23 || address.selector() == 0x2b);
|
VERIFY(address.selector() == 0x23 || address.selector() == 0x2b);
|
||||||
|
@ -161,6 +180,24 @@ void SoftCPU::write_memory64(X86::LogicalAddress address, ValueWithShadow<u64> v
|
||||||
m_emulator.mmu().write64(address, value);
|
m_emulator.mmu().write64(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoftCPU::write_memory128(X86::LogicalAddress address, ValueWithShadow<u128> value)
|
||||||
|
{
|
||||||
|
VERIFY(address.selector() == 0x23 || address.selector() == 0x2b);
|
||||||
|
#if MEMORY_DEBUG
|
||||||
|
outln("\033[36;1mwrite_memory128: @{:04x}:{:08x} <- {:032x} ({:032x})\033[0m", address.selector(), address.offset(), value, value.shadow());
|
||||||
|
#endif
|
||||||
|
m_emulator.mmu().write128(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftCPU::write_memory256(X86::LogicalAddress address, ValueWithShadow<u256> value)
|
||||||
|
{
|
||||||
|
VERIFY(address.selector() == 0x23 || address.selector() == 0x2b);
|
||||||
|
#if MEMORY_DEBUG
|
||||||
|
outln("\033[36;1mwrite_memory256: @{:04x}:{:08x} <- {:064x} ({:064x})\033[0m", address.selector(), address.offset(), value, value.shadow());
|
||||||
|
#endif
|
||||||
|
m_emulator.mmu().write256(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
void SoftCPU::push_string(const StringView& string)
|
void SoftCPU::push_string(const StringView& string)
|
||||||
{
|
{
|
||||||
size_t space_to_allocate = round_up_to_power_of_two(string.length() + 1, 16);
|
size_t space_to_allocate = round_up_to_power_of_two(string.length() + 1, 16);
|
||||||
|
|
|
@ -39,6 +39,8 @@ public:
|
||||||
using ValueWithShadowType16 = ValueWithShadow<u16>;
|
using ValueWithShadowType16 = ValueWithShadow<u16>;
|
||||||
using ValueWithShadowType32 = ValueWithShadow<u32>;
|
using ValueWithShadowType32 = ValueWithShadow<u32>;
|
||||||
using ValueWithShadowType64 = ValueWithShadow<u64>;
|
using ValueWithShadowType64 = ValueWithShadow<u64>;
|
||||||
|
using ValueWithShadowType128 = ValueWithShadow<u128>;
|
||||||
|
using ValueWithShadowType256 = ValueWithShadow<u256>;
|
||||||
|
|
||||||
explicit SoftCPU(Emulator&);
|
explicit SoftCPU(Emulator&);
|
||||||
void dump() const;
|
void dump() const;
|
||||||
|
@ -347,6 +349,8 @@ public:
|
||||||
ValueWithShadow<u16> read_memory16(X86::LogicalAddress);
|
ValueWithShadow<u16> read_memory16(X86::LogicalAddress);
|
||||||
ValueWithShadow<u32> read_memory32(X86::LogicalAddress);
|
ValueWithShadow<u32> read_memory32(X86::LogicalAddress);
|
||||||
ValueWithShadow<u64> read_memory64(X86::LogicalAddress);
|
ValueWithShadow<u64> read_memory64(X86::LogicalAddress);
|
||||||
|
ValueWithShadow<u128> read_memory128(X86::LogicalAddress);
|
||||||
|
ValueWithShadow<u256> read_memory256(X86::LogicalAddress);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ValueWithShadow<T> read_memory(X86::LogicalAddress address)
|
ValueWithShadow<T> read_memory(X86::LogicalAddress address)
|
||||||
|
@ -357,12 +361,20 @@ public:
|
||||||
return read_memory16(address);
|
return read_memory16(address);
|
||||||
if constexpr (sizeof(T) == 4)
|
if constexpr (sizeof(T) == 4)
|
||||||
return read_memory32(address);
|
return read_memory32(address);
|
||||||
|
if constexpr (sizeof(T) == 8)
|
||||||
|
return read_memory64(address);
|
||||||
|
if constexpr (sizeof(T) == 16)
|
||||||
|
return read_memory128(address);
|
||||||
|
if constexpr (sizeof(T) == 32)
|
||||||
|
return read_memory256(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_memory8(X86::LogicalAddress, ValueWithShadow<u8>);
|
void write_memory8(X86::LogicalAddress, ValueWithShadow<u8>);
|
||||||
void write_memory16(X86::LogicalAddress, ValueWithShadow<u16>);
|
void write_memory16(X86::LogicalAddress, ValueWithShadow<u16>);
|
||||||
void write_memory32(X86::LogicalAddress, ValueWithShadow<u32>);
|
void write_memory32(X86::LogicalAddress, ValueWithShadow<u32>);
|
||||||
void write_memory64(X86::LogicalAddress, ValueWithShadow<u64>);
|
void write_memory64(X86::LogicalAddress, ValueWithShadow<u64>);
|
||||||
|
void write_memory128(X86::LogicalAddress, ValueWithShadow<u128>);
|
||||||
|
void write_memory256(X86::LogicalAddress, ValueWithShadow<u256>);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void write_memory(X86::LogicalAddress address, ValueWithShadow<T> data)
|
void write_memory(X86::LogicalAddress address, ValueWithShadow<T> data)
|
||||||
|
@ -373,6 +385,12 @@ public:
|
||||||
return write_memory16(address, data);
|
return write_memory16(address, data);
|
||||||
if constexpr (sizeof(T) == 4)
|
if constexpr (sizeof(T) == 4)
|
||||||
return write_memory32(address, data);
|
return write_memory32(address, data);
|
||||||
|
if constexpr (sizeof(T) == 8)
|
||||||
|
return write_memory64(address, data);
|
||||||
|
if constexpr (sizeof(T) == 16)
|
||||||
|
return write_memory128(address, data);
|
||||||
|
if constexpr (sizeof(T) == 32)
|
||||||
|
return write_memory256(address, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool evaluate_condition(u8 condition) const
|
bool evaluate_condition(u8 condition) const
|
||||||
|
|
|
@ -163,6 +163,42 @@ ValueWithShadow<u64> SoftMMU::read64(X86::LogicalAddress address)
|
||||||
return region->read64(address.offset() - region->base());
|
return region->read64(address.offset() - region->base());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueWithShadow<u128> SoftMMU::read128(X86::LogicalAddress address)
|
||||||
|
{
|
||||||
|
auto* region = find_region(address);
|
||||||
|
if (!region) {
|
||||||
|
reportln("SoftMMU::read128: No region for @ {:p}", address.offset());
|
||||||
|
m_emulator.dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!region->is_readable()) {
|
||||||
|
reportln("SoftMMU::read128: Non-readable region @ {:p}", address.offset());
|
||||||
|
m_emulator.dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
return region->read128(address.offset() - region->base());
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueWithShadow<u256> SoftMMU::read256(X86::LogicalAddress address)
|
||||||
|
{
|
||||||
|
auto* region = find_region(address);
|
||||||
|
if (!region) {
|
||||||
|
reportln("SoftMMU::read256: No region for @ {:p}", address.offset());
|
||||||
|
m_emulator.dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!region->is_readable()) {
|
||||||
|
reportln("SoftMMU::read256: Non-readable region @ {:p}", address.offset());
|
||||||
|
m_emulator.dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
return region->read256(address.offset() - region->base());
|
||||||
|
}
|
||||||
|
|
||||||
void SoftMMU::write8(X86::LogicalAddress address, ValueWithShadow<u8> value)
|
void SoftMMU::write8(X86::LogicalAddress address, ValueWithShadow<u8> value)
|
||||||
{
|
{
|
||||||
auto* region = find_region(address);
|
auto* region = find_region(address);
|
||||||
|
@ -234,6 +270,42 @@ void SoftMMU::write64(X86::LogicalAddress address, ValueWithShadow<u64> value)
|
||||||
region->write64(address.offset() - region->base(), value);
|
region->write64(address.offset() - region->base(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoftMMU::write128(X86::LogicalAddress address, ValueWithShadow<u128> value)
|
||||||
|
{
|
||||||
|
auto* region = find_region(address);
|
||||||
|
if (!region) {
|
||||||
|
reportln("SoftMMU::write128: No region for @ {:p}", address.offset());
|
||||||
|
m_emulator.dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!region->is_writable()) {
|
||||||
|
reportln("SoftMMU::write128: Non-writable region @ {:p}", address.offset());
|
||||||
|
m_emulator.dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
region->write128(address.offset() - region->base(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftMMU::write256(X86::LogicalAddress address, ValueWithShadow<u256> value)
|
||||||
|
{
|
||||||
|
auto* region = find_region(address);
|
||||||
|
if (!region) {
|
||||||
|
reportln("SoftMMU::write256: No region for @ {:p}", address.offset());
|
||||||
|
m_emulator.dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!region->is_writable()) {
|
||||||
|
reportln("SoftMMU::write256: Non-writable region @ {:p}", address.offset());
|
||||||
|
m_emulator.dump_backtrace();
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
region->write256(address.offset() - region->base(), value);
|
||||||
|
}
|
||||||
|
|
||||||
void SoftMMU::copy_to_vm(FlatPtr destination, const void* source, size_t size)
|
void SoftMMU::copy_to_vm(FlatPtr destination, const void* source, size_t size)
|
||||||
{
|
{
|
||||||
// FIXME: We should have a way to preserve the shadow data here as well.
|
// FIXME: We should have a way to preserve the shadow data here as well.
|
||||||
|
|
|
@ -26,11 +26,15 @@ public:
|
||||||
ValueWithShadow<u16> read16(X86::LogicalAddress);
|
ValueWithShadow<u16> read16(X86::LogicalAddress);
|
||||||
ValueWithShadow<u32> read32(X86::LogicalAddress);
|
ValueWithShadow<u32> read32(X86::LogicalAddress);
|
||||||
ValueWithShadow<u64> read64(X86::LogicalAddress);
|
ValueWithShadow<u64> read64(X86::LogicalAddress);
|
||||||
|
ValueWithShadow<u128> read128(X86::LogicalAddress);
|
||||||
|
ValueWithShadow<u256> read256(X86::LogicalAddress);
|
||||||
|
|
||||||
void write8(X86::LogicalAddress, ValueWithShadow<u8>);
|
void write8(X86::LogicalAddress, ValueWithShadow<u8>);
|
||||||
void write16(X86::LogicalAddress, ValueWithShadow<u16>);
|
void write16(X86::LogicalAddress, ValueWithShadow<u16>);
|
||||||
void write32(X86::LogicalAddress, ValueWithShadow<u32>);
|
void write32(X86::LogicalAddress, ValueWithShadow<u32>);
|
||||||
void write64(X86::LogicalAddress, ValueWithShadow<u64>);
|
void write64(X86::LogicalAddress, ValueWithShadow<u64>);
|
||||||
|
void write128(X86::LogicalAddress, ValueWithShadow<u128>);
|
||||||
|
void write256(X86::LogicalAddress, ValueWithShadow<u256>);
|
||||||
|
|
||||||
ALWAYS_INLINE Region* find_region(X86::LogicalAddress address)
|
ALWAYS_INLINE Region* find_region(X86::LogicalAddress address)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,13 +4,19 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/Format.h>
|
|
||||||
#include <AK/Platform.h>
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Format.h>
|
||||||
|
#include <AK/Platform.h>
|
||||||
|
#include <LibX86/Types.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
namespace UserspaceEmulator {
|
namespace UserspaceEmulator {
|
||||||
|
|
||||||
|
constexpr u64 _inititalized_64 = 0x01010101'01010101LLU;
|
||||||
|
constexpr u128 _initialized_128 = u128(_inititalized_64, _inititalized_64);
|
||||||
|
constexpr u256 _initialized_256 = u256(_initialized_128, _initialized_128);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class ValueAndShadowReference;
|
class ValueAndShadowReference;
|
||||||
|
|
||||||
|
@ -32,6 +38,12 @@ public:
|
||||||
|
|
||||||
bool is_uninitialized() const
|
bool is_uninitialized() const
|
||||||
{
|
{
|
||||||
|
if constexpr (sizeof(T) == 32)
|
||||||
|
return (m_shadow & _initialized_256) != _initialized_256;
|
||||||
|
if constexpr (sizeof(T) == 16)
|
||||||
|
return (m_shadow & _initialized_128) != _initialized_128;
|
||||||
|
if constexpr (sizeof(T) == 8)
|
||||||
|
return (m_shadow & _inititalized_64) != _inititalized_64;
|
||||||
if constexpr (sizeof(T) == 4)
|
if constexpr (sizeof(T) == 4)
|
||||||
return (m_shadow & 0x01010101) != 0x01010101;
|
return (m_shadow & 0x01010101) != 0x01010101;
|
||||||
if constexpr (sizeof(T) == 2)
|
if constexpr (sizeof(T) == 2)
|
||||||
|
@ -42,6 +54,12 @@ public:
|
||||||
|
|
||||||
void set_initialized()
|
void set_initialized()
|
||||||
{
|
{
|
||||||
|
if constexpr (sizeof(T) == 32)
|
||||||
|
m_shadow = _initialized_256;
|
||||||
|
if constexpr (sizeof(T) == 16)
|
||||||
|
m_shadow = _initialized_128;
|
||||||
|
if constexpr (sizeof(T) == 8)
|
||||||
|
m_shadow = _inititalized_64;
|
||||||
if constexpr (sizeof(T) == 4)
|
if constexpr (sizeof(T) == 4)
|
||||||
m_shadow = 0x01010101;
|
m_shadow = 0x01010101;
|
||||||
if constexpr (sizeof(T) == 2)
|
if constexpr (sizeof(T) == 2)
|
||||||
|
@ -68,6 +86,12 @@ public:
|
||||||
|
|
||||||
bool is_uninitialized() const
|
bool is_uninitialized() const
|
||||||
{
|
{
|
||||||
|
if constexpr (sizeof(T) == 32)
|
||||||
|
return (m_shadow & _initialized_256) != _initialized_256;
|
||||||
|
if constexpr (sizeof(T) == 16)
|
||||||
|
return (m_shadow & _initialized_128) != _initialized_128;
|
||||||
|
if constexpr (sizeof(T) == 8)
|
||||||
|
return (m_shadow & _inititalized_64) != _inititalized_64;
|
||||||
if constexpr (sizeof(T) == 4)
|
if constexpr (sizeof(T) == 4)
|
||||||
return (m_shadow & 0x01010101) != 0x01010101;
|
return (m_shadow & 0x01010101) != 0x01010101;
|
||||||
if constexpr (sizeof(T) == 2)
|
if constexpr (sizeof(T) == 2)
|
||||||
|
@ -92,8 +116,12 @@ private:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ALWAYS_INLINE ValueWithShadow<T> shadow_wrap_as_initialized(T value)
|
ALWAYS_INLINE ValueWithShadow<T> shadow_wrap_as_initialized(T value)
|
||||||
{
|
{
|
||||||
|
if constexpr (sizeof(T) == 32)
|
||||||
|
return { value, _initialized_256 };
|
||||||
|
if constexpr (sizeof(T) == 16)
|
||||||
|
return { value, _initialized_128 };
|
||||||
if constexpr (sizeof(T) == 8)
|
if constexpr (sizeof(T) == 8)
|
||||||
return { value, 0x01010101'01010101LLU };
|
return { value, _inititalized_64 };
|
||||||
if constexpr (sizeof(T) == 4)
|
if constexpr (sizeof(T) == 4)
|
||||||
return { value, 0x01010101 };
|
return { value, 0x01010101 };
|
||||||
if constexpr (sizeof(T) == 2)
|
if constexpr (sizeof(T) == 2)
|
||||||
|
@ -149,3 +177,7 @@ struct AK::Formatter<UserspaceEmulator::ValueWithShadow<T>> : AK::Formatter<T> {
|
||||||
return Formatter<T>::format(builder, value.value());
|
return Formatter<T>::format(builder, value.value());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef INITIALIZED_64
|
||||||
|
#undef INITIALIZED_128
|
||||||
|
#undef INITIALIZED_256
|
||||||
|
|
|
@ -380,6 +380,10 @@ public:
|
||||||
void write32(CPU&, const Instruction&, T);
|
void write32(CPU&, const Instruction&, T);
|
||||||
template<typename CPU, typename T>
|
template<typename CPU, typename T>
|
||||||
void write64(CPU&, const Instruction&, T);
|
void write64(CPU&, const Instruction&, T);
|
||||||
|
template<typename CPU, typename T>
|
||||||
|
void write128(CPU&, const Instruction&, T);
|
||||||
|
template<typename CPU, typename T>
|
||||||
|
void write256(CPU&, const Instruction&, T);
|
||||||
|
|
||||||
template<typename CPU>
|
template<typename CPU>
|
||||||
typename CPU::ValueWithShadowType8 read8(CPU&, const Instruction&);
|
typename CPU::ValueWithShadowType8 read8(CPU&, const Instruction&);
|
||||||
|
@ -389,6 +393,10 @@ public:
|
||||||
typename CPU::ValueWithShadowType32 read32(CPU&, const Instruction&);
|
typename CPU::ValueWithShadowType32 read32(CPU&, const Instruction&);
|
||||||
template<typename CPU>
|
template<typename CPU>
|
||||||
typename CPU::ValueWithShadowType64 read64(CPU&, const Instruction&);
|
typename CPU::ValueWithShadowType64 read64(CPU&, const Instruction&);
|
||||||
|
template<typename CPU>
|
||||||
|
typename CPU::ValueWithShadowType128 read128(CPU&, const Instruction&);
|
||||||
|
template<typename CPU>
|
||||||
|
typename CPU::ValueWithShadowType256 read256(CPU&, const Instruction&);
|
||||||
|
|
||||||
template<typename CPU>
|
template<typename CPU>
|
||||||
LogicalAddress resolve(const CPU&, const Instruction&);
|
LogicalAddress resolve(const CPU&, const Instruction&);
|
||||||
|
@ -680,6 +688,22 @@ ALWAYS_INLINE void MemoryOrRegisterReference::write64(CPU& cpu, const Instructio
|
||||||
cpu.write_memory64(address, value);
|
cpu.write_memory64(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CPU, typename T>
|
||||||
|
ALWAYS_INLINE void MemoryOrRegisterReference::write128(CPU& cpu, const Instruction& insn, T value)
|
||||||
|
{
|
||||||
|
VERIFY(!is_register());
|
||||||
|
auto address = resolve(cpu, insn);
|
||||||
|
cpu.write_memory128(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CPU, typename T>
|
||||||
|
ALWAYS_INLINE void MemoryOrRegisterReference::write256(CPU& cpu, const Instruction& insn, T value)
|
||||||
|
{
|
||||||
|
VERIFY(!is_register());
|
||||||
|
auto address = resolve(cpu, insn);
|
||||||
|
cpu.write_memory256(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename CPU>
|
template<typename CPU>
|
||||||
ALWAYS_INLINE typename CPU::ValueWithShadowType8 MemoryOrRegisterReference::read8(CPU& cpu, const Instruction& insn)
|
ALWAYS_INLINE typename CPU::ValueWithShadowType8 MemoryOrRegisterReference::read8(CPU& cpu, const Instruction& insn)
|
||||||
{
|
{
|
||||||
|
@ -718,6 +742,22 @@ ALWAYS_INLINE typename CPU::ValueWithShadowType64 MemoryOrRegisterReference::rea
|
||||||
return cpu.read_memory64(address);
|
return cpu.read_memory64(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CPU>
|
||||||
|
ALWAYS_INLINE typename CPU::ValueWithShadowType128 MemoryOrRegisterReference::read128(CPU& cpu, const Instruction& insn)
|
||||||
|
{
|
||||||
|
VERIFY(!is_register());
|
||||||
|
auto address = resolve(cpu, insn);
|
||||||
|
return cpu.read_memory128(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CPU>
|
||||||
|
ALWAYS_INLINE typename CPU::ValueWithShadowType256 MemoryOrRegisterReference::read256(CPU& cpu, const Instruction& insn)
|
||||||
|
{
|
||||||
|
VERIFY(!is_register());
|
||||||
|
auto address = resolve(cpu, insn);
|
||||||
|
return cpu.read_memory256(address);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename InstructionStreamType>
|
template<typename InstructionStreamType>
|
||||||
ALWAYS_INLINE Instruction Instruction::from_stream(InstructionStreamType& stream, bool o32, bool a32)
|
ALWAYS_INLINE Instruction Instruction::from_stream(InstructionStreamType& stream, bool o32, bool a32)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue