Преглед изворни кода

UE+LibX86: Support bigger reads and writes

Hendiadyoin1 пре 4 година
родитељ
комит
f1957bb86b

+ 72 - 0
Userland/DevTools/UserspaceEmulator/MmapRegion.cpp

@@ -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);

+ 4 - 0
Userland/DevTools/UserspaceEmulator/MmapRegion.h

@@ -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; }

+ 5 - 0
Userland/DevTools/UserspaceEmulator/Region.h

@@ -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; }
 
 

+ 24 - 0
Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp

@@ -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)
 {
 {

+ 4 - 0
Userland/DevTools/UserspaceEmulator/SimpleRegion.h

@@ -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; }

+ 37 - 0
Userland/DevTools/UserspaceEmulator/SoftCPU.cpp

@@ -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);

+ 18 - 0
Userland/DevTools/UserspaceEmulator/SoftCPU.h

@@ -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

+ 72 - 0
Userland/DevTools/UserspaceEmulator/SoftMMU.cpp

@@ -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.

+ 4 - 0
Userland/DevTools/UserspaceEmulator/SoftMMU.h

@@ -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)
     {
     {

+ 35 - 3
Userland/DevTools/UserspaceEmulator/ValueWithShadow.h

@@ -4,13 +4,19 @@
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
  */
  */
 
 
+#pragma once
+
 #include <AK/Format.h>
 #include <AK/Format.h>
 #include <AK/Platform.h>
 #include <AK/Platform.h>
-
-#pragma once
+#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

+ 40 - 0
Userland/Libraries/LibX86/Instruction.h

@@ -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)
 {
 {