diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index 791e7085f0d..af14b12a37f 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -3072,6 +3072,22 @@ void SoftCPU::STOSB(const X86::Instruction& insn) void SoftCPU::STOSD(const X86::Instruction& insn) { + if (insn.has_rep_prefix() && !df()) { + // Fast path for 32-bit forward memory fill. + if (m_emulator.mmu().fast_fill_memory32({ es(), destination_index(insn.a32()).value() }, ecx().value(), eax())) { + if (insn.a32()) { + // FIXME: Should an uninitialized ECX taint EDI here? + set_edi({ (u32)(edi().value() + (ecx().value() * sizeof(u32))), edi().shadow() }); + set_ecx(shadow_wrap_as_initialized(0)); + } else { + // FIXME: Should an uninitialized CX taint DI here? + set_di({ (u16)(di().value() + (cx().value() * sizeof(u32))), di().shadow() }); + set_cx(shadow_wrap_as_initialized(0)); + } + return; + } + } + do_once_or_repeat(insn, [&] { write_memory32({ es(), destination_index(insn.a32()).value() }, eax()); step_destination_index(insn.a32(), 4); diff --git a/DevTools/UserspaceEmulator/SoftMMU.cpp b/DevTools/UserspaceEmulator/SoftMMU.cpp index a90fab44bae..21061ac7fb0 100644 --- a/DevTools/UserspaceEmulator/SoftMMU.cpp +++ b/DevTools/UserspaceEmulator/SoftMMU.cpp @@ -259,7 +259,7 @@ bool SoftMMU::fast_fill_memory8(X86::LogicalAddress address, size_t size, ValueW if (region->is_mmap() && static_cast(*region).is_malloc_block()) { if (auto* tracer = Emulator::the().malloc_tracer()) { // FIXME: Add a way to audit an entire range of memory instead of looping here! - for (size_t i = 0; i < size; i += sizeof(u8)) { + for (size_t i = 0; i < size; ++i) { tracer->audit_write(address.offset() + (i * sizeof(u8)), sizeof(u8)); } } @@ -271,4 +271,29 @@ bool SoftMMU::fast_fill_memory8(X86::LogicalAddress address, size_t size, ValueW return true; } +bool SoftMMU::fast_fill_memory32(X86::LogicalAddress address, size_t count, ValueWithShadow value) +{ + if (!count) + return true; + auto* region = find_region(address); + if (!region) + return false; + if (!region->contains(address.offset() + (count * sizeof(u32)) - 1)) + return false; + + if (region->is_mmap() && static_cast(*region).is_malloc_block()) { + if (auto* tracer = Emulator::the().malloc_tracer()) { + // FIXME: Add a way to audit an entire range of memory instead of looping here! + for (size_t i = 0; i < count; ++i) { + tracer->audit_write(address.offset() + (i * sizeof(u32)), sizeof(u32)); + } + } + } + + size_t offset_in_region = address.offset() - region->base(); + fast_u32_fill((u32*)(region->data() + offset_in_region), value.value(), count); + fast_u32_fill((u32*)(region->shadow_data() + offset_in_region), value.shadow(), count); + return true; +} + } diff --git a/DevTools/UserspaceEmulator/SoftMMU.h b/DevTools/UserspaceEmulator/SoftMMU.h index 1efdb47a2bd..e40bae9a7ca 100644 --- a/DevTools/UserspaceEmulator/SoftMMU.h +++ b/DevTools/UserspaceEmulator/SoftMMU.h @@ -109,6 +109,7 @@ public: void set_tls_region(NonnullOwnPtr); bool fast_fill_memory8(X86::LogicalAddress, size_t size, ValueWithShadow); + bool fast_fill_memory32(X86::LogicalAddress, size_t size, ValueWithShadow); void copy_to_vm(FlatPtr destination, const void* source, size_t); void copy_from_vm(void* destination, const FlatPtr source, size_t);