diff --git a/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp b/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp index 46cf447d46..0b956e8b1b 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp +++ b/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp @@ -639,6 +639,39 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi } return; } + // https://webassembly.github.io/spec/core/bikeshed/#exec-memory-copy + case Instructions::memory_copy.value(): { + auto address = configuration.frame().module().memories()[0]; + auto instance = configuration.store().get(address); + auto count = configuration.stack().pop().get().to().value(); + auto source_offset = configuration.stack().pop().get().to().value(); + auto destination_offset = configuration.stack().pop().get().to().value(); + + TRAP_IF_NOT(static_cast(source_offset + count) <= instance->data().size()); + TRAP_IF_NOT(static_cast(destination_offset + count) <= instance->data().size()); + + if (count == 0) + return; + + Instruction synthetic_store_instruction { + Instructions::i32_store8, + Instruction::MemoryArgument { 0, 0 } + }; + + if (destination_offset <= source_offset) { + for (auto i = 0; i < count; ++i) { + auto value = instance->data()[source_offset + i]; + store_to_memory(configuration, synthetic_store_instruction, { &value, sizeof(value) }, destination_offset + i); + } + } else { + for (auto i = count - 1; i >= 0; --i) { + auto value = instance->data()[source_offset + i]; + store_to_memory(configuration, synthetic_store_instruction, { &value, sizeof(value) }, destination_offset + i); + } + } + + return; + } case Instructions::table_get.value(): case Instructions::table_set.value(): goto unimplemented; @@ -973,7 +1006,6 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi return; } case Instructions::data_drop.value(): - case Instructions::memory_copy.value(): case Instructions::table_init.value(): case Instructions::elem_drop.value(): case Instructions::table_copy.value():