wasm/execution/
interpreter_loop.rs

1//! This module solely contains the actual interpretation loop that matches instructions, interpreting the WASM bytecode
2//!
3//!
4//! # Note to Developer:
5//!
6//! 1. There must be only imports and one `impl` with one function (`run`) in it.
7//! 2. This module must only use [`RuntimeError`] and never [`Error`](crate::core::error::ValidationError).
8
9use alloc::vec::Vec;
10use core::{
11    array,
12    iter::zip,
13    ops::{Add, Div, Mul, Neg, Sub},
14};
15
16use crate::{
17    assert_validated::UnwrapValidatedExt,
18    core::{
19        indices::{DataIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TypeIdx},
20        reader::{
21            types::{memarg::MemArg, BlockType},
22            WasmReadable, WasmReader,
23        },
24        sidetable::Sidetable,
25    },
26    resumable::Resumable,
27    store::DataInst,
28    unreachable_validated,
29    value::{self, FuncAddr, Ref, F32, F64},
30    value_stack::Stack,
31    ElemInst, FuncInst, MemInst, ModuleInst, RefType, RuntimeError, TableInst, TrapError, ValType,
32    Value,
33};
34
35use crate::execution::hooks::HookSet;
36
37use super::{little_endian::LittleEndianBytes, store::Store};
38
39/// Interprets wasm native functions. Parameters and return values are passed on the stack.
40pub(super) fn run<T, H: HookSet>(
41    resumable: &mut Resumable,
42    store: &mut Store<T>,
43    mut hooks: H,
44    mut maybe_fuel: Option<u32>,
45) -> Result<(), RuntimeError> {
46    let stack = &mut resumable.stack;
47    let mut current_func_addr = resumable.current_func_addr;
48    let pc = resumable.pc;
49    let mut stp = resumable.stp;
50    let func_inst = &store.functions[current_func_addr];
51    let FuncInst::WasmFunc(wasm_func_inst) = &func_inst else {
52        unreachable!(
53            "the interpreter loop shall only be executed with native wasm functions as root call"
54        );
55    };
56    let mut current_module_idx = wasm_func_inst.module_addr;
57
58    // Start reading the function's instructions
59    let wasm = &mut WasmReader::new(store.modules[current_module_idx].wasm_bytecode);
60
61    let mut current_sidetable: &Sidetable = &store.modules[current_module_idx].sidetable;
62
63    // local variable for holding where the function code ends (last END instr address + 1) to avoid lookup at every END instr
64    let mut current_function_end_marker =
65        wasm_func_inst.code_expr.from() + wasm_func_inst.code_expr.len();
66
67    wasm.pc = pc;
68
69    use crate::core::reader::types::opcode::*;
70    loop {
71        // call the instruction hook
72        hooks.instruction_hook(store.modules[current_module_idx].wasm_bytecode, wasm.pc);
73
74        let first_instr_byte = wasm.read_u8().unwrap_validated();
75
76        #[cfg(debug_assertions)]
77        trace!(
78            "Executing instruction {}",
79            opcode_byte_to_str(first_instr_byte)
80        );
81
82        // Fuel mechanism: 1 fuel per instruction
83        if let Some(fuel) = &mut maybe_fuel {
84            *fuel = fuel.checked_sub(1).ok_or_else(|| {
85                resumable.current_func_addr = current_func_addr;
86                resumable.pc = wasm.pc - 1;
87                resumable.stp = stp;
88
89                RuntimeError::OutOfFuel
90            })?;
91        }
92
93        match first_instr_byte {
94            NOP => {
95                trace!("Instruction: NOP");
96            }
97            END => {
98                // There might be multiple ENDs in a single function. We want to
99                // exit only when the outermost block (aka function block) ends.
100                if wasm.pc != current_function_end_marker {
101                    continue;
102                }
103
104                let (maybe_return_func_addr, maybe_return_address, maybe_return_stp) =
105                    stack.pop_call_frame();
106
107                // We finished this entire invocation if there is no call frame left. If there are
108                // one or more call frames, we need to continue from where the callee was called
109                // from.
110                if stack.call_frame_count() == 0 {
111                    break;
112                }
113
114                trace!("end of function reached, returning to previous call frame");
115                current_func_addr = maybe_return_func_addr;
116                let FuncInst::WasmFunc(current_wasm_func_inst) =
117                    &store.functions[current_func_addr]
118                else {
119                    unreachable!("function addresses on the stack always correspond to native wasm functions")
120                };
121                current_module_idx = current_wasm_func_inst.module_addr;
122                wasm.full_wasm_binary = store.modules[current_module_idx].wasm_bytecode;
123                wasm.pc = maybe_return_address;
124                stp = maybe_return_stp;
125
126                current_sidetable = &store.modules[current_module_idx].sidetable;
127
128                current_function_end_marker = current_wasm_func_inst.code_expr.from()
129                    + current_wasm_func_inst.code_expr.len();
130
131                trace!("Instruction: END");
132            }
133            IF => {
134                wasm.read_var_u32().unwrap_validated();
135
136                let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
137
138                if test_val != 0 {
139                    stp += 1;
140                } else {
141                    do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
142                }
143                trace!("Instruction: IF");
144            }
145            ELSE => {
146                do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
147            }
148            BR_IF => {
149                wasm.read_var_u32().unwrap_validated();
150
151                let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
152
153                if test_val != 0 {
154                    do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
155                } else {
156                    stp += 1;
157                }
158                trace!("Instruction: BR_IF");
159            }
160            BR_TABLE => {
161                let label_vec = wasm
162                    .read_vec(|wasm| wasm.read_var_u32().map(|v| v as LabelIdx))
163                    .unwrap_validated();
164                wasm.read_var_u32().unwrap_validated();
165
166                // TODO is this correct?
167                let case_val_i32: i32 = stack.pop_value().try_into().unwrap_validated();
168                let case_val = case_val_i32 as usize;
169
170                if case_val >= label_vec.len() {
171                    stp += label_vec.len();
172                } else {
173                    stp += case_val;
174                }
175
176                do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
177            }
178            BR => {
179                //skip n of BR n
180                wasm.read_var_u32().unwrap_validated();
181                do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
182            }
183            BLOCK | LOOP => {
184                BlockType::read(wasm).unwrap_validated();
185            }
186            RETURN => {
187                //same as BR, except no need to skip n of BR n
188                do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
189            }
190            CALL => {
191                let local_func_idx = wasm.read_var_u32().unwrap_validated() as FuncIdx;
192                let FuncInst::WasmFunc(current_wasm_func_inst) =
193                    &store.functions[current_func_addr]
194                else {
195                    unreachable!()
196                };
197
198                let func_to_call_addr =
199                    store.modules[current_wasm_func_inst.module_addr].func_addrs[local_func_idx];
200
201                let func_to_call_ty = store.functions[func_to_call_addr].ty();
202
203                trace!("Instruction: call [{func_to_call_addr:?}]");
204
205                match &store.functions[func_to_call_addr] {
206                    FuncInst::HostFunc(host_func_to_call_inst) => {
207                        let params = stack
208                            .pop_tail_iter(func_to_call_ty.params.valtypes.len())
209                            .collect();
210                        let returns =
211                            (host_func_to_call_inst.hostcode)(&mut store.user_data, params);
212
213                        // Verify that the return parameters match the host function parameters
214                        // since we have no validation guarantees for host functions
215                        if returns.len() != func_to_call_ty.returns.valtypes.len() {
216                            return Err(RuntimeError::HostFunctionSignatureMismatch);
217                        }
218                        for (value, ty) in zip(returns, func_to_call_ty.returns.valtypes) {
219                            if value.to_ty() != ty {
220                                return Err(RuntimeError::HostFunctionSignatureMismatch);
221                            }
222                            stack.push_value(value)?;
223                        }
224                    }
225                    FuncInst::WasmFunc(wasm_func_to_call_inst) => {
226                        let remaining_locals = &wasm_func_to_call_inst.locals;
227
228                        stack.push_call_frame(
229                            current_func_addr,
230                            &func_to_call_ty,
231                            remaining_locals,
232                            wasm.pc,
233                            stp,
234                        )?;
235
236                        current_func_addr = func_to_call_addr;
237                        current_module_idx = wasm_func_to_call_inst.module_addr;
238                        wasm.full_wasm_binary = store.modules[current_module_idx].wasm_bytecode;
239                        wasm.move_start_to(wasm_func_to_call_inst.code_expr)
240                            .expect("code expression spans to always be valid");
241
242                        stp = wasm_func_to_call_inst.stp;
243                        current_sidetable = &store.modules[current_module_idx].sidetable;
244                        current_function_end_marker = wasm_func_to_call_inst.code_expr.from()
245                            + wasm_func_to_call_inst.code_expr.len();
246                    }
247                }
248                trace!("Instruction: CALL");
249            }
250
251            // TODO: fix push_call_frame, because the func idx that you get from the table is global func idx
252            CALL_INDIRECT => {
253                let given_type_idx = wasm.read_var_u32().unwrap_validated() as TypeIdx;
254                let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx;
255
256                let table_addr = *store.modules[current_module_idx]
257                    .table_addrs
258                    .get(table_idx)
259                    .unwrap_validated();
260                let tab = &store.tables[table_addr];
261                let func_ty = store.modules[current_module_idx]
262                    .types
263                    .get(given_type_idx)
264                    .unwrap_validated();
265
266                let i: u32 = stack.pop_value().try_into().unwrap_validated();
267
268                let r = tab
269                    .elem
270                    .get(i as usize)
271                    .ok_or(TrapError::TableAccessOutOfBounds)
272                    .and_then(|r| {
273                        if matches!(r, Ref::Null(_)) {
274                            trace!("table_idx ({table_idx}) --- element index in table ({i})");
275                            Err(TrapError::UninitializedElement)
276                        } else {
277                            Ok(r)
278                        }
279                    })?;
280
281                let func_to_call_addr = match *r {
282                    Ref::Func(func_addr) => func_addr.0,
283                    Ref::Null(_) => return Err(TrapError::IndirectCallNullFuncRef.into()),
284                    Ref::Extern(_) => unreachable_validated!(),
285                };
286
287                let func_to_call_ty = store.functions[func_to_call_addr].ty();
288                if *func_ty != func_to_call_ty {
289                    return Err(TrapError::SignatureMismatch.into());
290                }
291
292                trace!("Instruction: call [{func_to_call_addr:?}]");
293
294                match &store.functions[func_to_call_addr] {
295                    FuncInst::HostFunc(host_func_to_call_inst) => {
296                        let params = stack
297                            .pop_tail_iter(func_to_call_ty.params.valtypes.len())
298                            .collect();
299                        let returns =
300                            (host_func_to_call_inst.hostcode)(&mut store.user_data, params);
301
302                        // Verify that the return parameters match the host function parameters
303                        // since we have no validation guarantees for host functions
304                        if returns.len() != func_to_call_ty.returns.valtypes.len() {
305                            return Err(RuntimeError::HostFunctionSignatureMismatch);
306                        }
307                        for (value, ty) in zip(returns, func_to_call_ty.returns.valtypes) {
308                            if value.to_ty() != ty {
309                                return Err(RuntimeError::HostFunctionSignatureMismatch);
310                            }
311                            stack.push_value(value)?;
312                        }
313                    }
314                    FuncInst::WasmFunc(wasm_func_to_call_inst) => {
315                        let remaining_locals = &wasm_func_to_call_inst.locals;
316
317                        stack.push_call_frame(
318                            current_func_addr,
319                            &func_to_call_ty,
320                            remaining_locals,
321                            wasm.pc,
322                            stp,
323                        )?;
324
325                        current_func_addr = func_to_call_addr;
326                        current_module_idx = wasm_func_to_call_inst.module_addr;
327                        wasm.full_wasm_binary = store.modules[current_module_idx].wasm_bytecode;
328                        wasm.move_start_to(wasm_func_to_call_inst.code_expr)
329                            .expect("code expression spans to always be valid");
330
331                        stp = wasm_func_to_call_inst.stp;
332                        current_sidetable = &store.modules[current_module_idx].sidetable;
333                        current_function_end_marker = wasm_func_to_call_inst.code_expr.from()
334                            + wasm_func_to_call_inst.code_expr.len();
335                    }
336                }
337                trace!("Instruction: CALL_INDIRECT");
338            }
339            DROP => {
340                stack.pop_value();
341                trace!("Instruction: DROP");
342            }
343            SELECT => {
344                let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
345                let val2 = stack.pop_value();
346                let val1 = stack.pop_value();
347                if test_val != 0 {
348                    stack.push_value(val1)?;
349                } else {
350                    stack.push_value(val2)?;
351                }
352                trace!("Instruction: SELECT");
353            }
354            SELECT_T => {
355                let _type_vec = wasm.read_vec(ValType::read).unwrap_validated();
356                let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
357                let val2 = stack.pop_value();
358                let val1 = stack.pop_value();
359                if test_val != 0 {
360                    stack.push_value(val1)?;
361                } else {
362                    stack.push_value(val2)?;
363                }
364                trace!("Instruction: SELECT_T");
365            }
366            LOCAL_GET => {
367                let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx;
368                let value = *stack.get_local(local_idx);
369                stack.push_value(value)?;
370                trace!("Instruction: local.get {} [] -> [t]", local_idx);
371            }
372            LOCAL_SET => {
373                let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx;
374                let value = stack.pop_value();
375                *stack.get_local_mut(local_idx) = value;
376                trace!("Instruction: local.set {} [t] -> []", local_idx);
377            }
378            LOCAL_TEE => {
379                let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx;
380                let value = stack.peek_value().unwrap_validated();
381                *stack.get_local_mut(local_idx) = value;
382                trace!("Instruction: local.tee {} [t] -> [t]", local_idx);
383            }
384            GLOBAL_GET => {
385                let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx;
386                let global_addr = *store.modules[current_module_idx]
387                    .global_addrs
388                    .get(global_idx)
389                    .unwrap_validated();
390                let global = &store.globals[global_addr];
391
392                stack.push_value(global.value)?;
393
394                trace!(
395                    "Instruction: global.get '{}' [<GLOBAL>] -> [{:?}]",
396                    global_idx,
397                    global.value
398                );
399            }
400            GLOBAL_SET => {
401                let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx;
402                let global_addr = *store.modules[current_module_idx]
403                    .global_addrs
404                    .get(global_idx)
405                    .unwrap_validated();
406                let global = &mut store.globals[global_addr];
407                global.value = stack.pop_value();
408                trace!("Instruction: GLOBAL_SET");
409            }
410            TABLE_GET => {
411                let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx;
412                let table_addr = *store.modules[current_module_idx]
413                    .table_addrs
414                    .get(table_idx)
415                    .unwrap_validated();
416                let tab = &store.tables[table_addr];
417
418                let i: i32 = stack.pop_value().try_into().unwrap_validated();
419
420                let val = tab
421                    .elem
422                    .get(i as usize)
423                    .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
424
425                stack.push_value((*val).into())?;
426                trace!(
427                    "Instruction: table.get '{}' [{}] -> [{}]",
428                    table_idx,
429                    i,
430                    val
431                );
432            }
433            TABLE_SET => {
434                let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx;
435                let table_addr = *store.modules[current_module_idx]
436                    .table_addrs
437                    .get(table_idx)
438                    .unwrap_validated();
439                let tab = &mut store.tables[table_addr];
440
441                let val: Ref = stack.pop_value().try_into().unwrap_validated();
442                let i: i32 = stack.pop_value().try_into().unwrap_validated();
443
444                tab.elem
445                    .get_mut(i as usize)
446                    .ok_or(TrapError::TableOrElementAccessOutOfBounds)
447                    .map(|r| *r = val)?;
448                trace!(
449                    "Instruction: table.set '{}' [{} {}] -> []",
450                    table_idx,
451                    i,
452                    val
453                )
454            }
455            UNREACHABLE => {
456                return Err(TrapError::ReachedUnreachable.into());
457            }
458            I32_LOAD => {
459                let memarg = MemArg::read(wasm).unwrap_validated();
460                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
461
462                let mem_addr = *store.modules[current_module_idx]
463                    .mem_addrs
464                    .first()
465                    .unwrap_validated();
466                let mem_inst = &store.memories[mem_addr];
467
468                let idx = calculate_mem_address(&memarg, relative_address)?;
469                let data = mem_inst.mem.load(idx)?;
470
471                stack.push_value(Value::I32(data))?;
472                trace!("Instruction: i32.load [{relative_address}] -> [{data}]");
473            }
474            I64_LOAD => {
475                let memarg = MemArg::read(wasm).unwrap_validated();
476                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
477
478                let mem_addr = *store.modules[current_module_idx]
479                    .mem_addrs
480                    .first()
481                    .unwrap_validated();
482                let mem = &store.memories[mem_addr];
483
484                let idx = calculate_mem_address(&memarg, relative_address)?;
485                let data = mem.mem.load(idx)?;
486
487                stack.push_value(Value::I64(data))?;
488                trace!("Instruction: i64.load [{relative_address}] -> [{data}]");
489            }
490            F32_LOAD => {
491                let memarg = MemArg::read(wasm).unwrap_validated();
492                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
493
494                let mem_addr = *store.modules[current_module_idx]
495                    .mem_addrs
496                    .first()
497                    .unwrap_validated();
498                let mem = &store.memories[mem_addr];
499
500                let idx = calculate_mem_address(&memarg, relative_address)?;
501                let data = mem.mem.load(idx)?;
502
503                stack.push_value(Value::F32(data))?;
504                trace!("Instruction: f32.load [{relative_address}] -> [{data}]");
505            }
506            F64_LOAD => {
507                let memarg = MemArg::read(wasm).unwrap_validated();
508                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
509
510                let mem_addr = *store.modules[current_module_idx]
511                    .mem_addrs
512                    .first()
513                    .unwrap_validated();
514                let mem = &store.memories[mem_addr];
515
516                let idx = calculate_mem_address(&memarg, relative_address)?;
517                let data = mem.mem.load(idx)?;
518
519                stack.push_value(Value::F64(data))?;
520                trace!("Instruction: f64.load [{relative_address}] -> [{data}]");
521            }
522            I32_LOAD8_S => {
523                let memarg = MemArg::read(wasm).unwrap_validated();
524                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
525
526                let mem_addr = *store.modules[current_module_idx]
527                    .mem_addrs
528                    .first()
529                    .unwrap_validated();
530                let mem = &store.memories[mem_addr];
531
532                let idx = calculate_mem_address(&memarg, relative_address)?;
533                let data: i8 = mem.mem.load(idx)?;
534
535                stack.push_value(Value::I32(data as u32))?;
536                trace!("Instruction: i32.load8_s [{relative_address}] -> [{data}]");
537            }
538            I32_LOAD8_U => {
539                let memarg = MemArg::read(wasm).unwrap_validated();
540                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
541
542                let mem_addr = *store.modules[current_module_idx]
543                    .mem_addrs
544                    .first()
545                    .unwrap_validated();
546                let mem = &store.memories[mem_addr];
547
548                let idx = calculate_mem_address(&memarg, relative_address)?;
549                let data: u8 = mem.mem.load(idx)?;
550
551                stack.push_value(Value::I32(data as u32))?;
552                trace!("Instruction: i32.load8_u [{relative_address}] -> [{data}]");
553            }
554            I32_LOAD16_S => {
555                let memarg = MemArg::read(wasm).unwrap_validated();
556                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
557
558                let mem_addr = *store.modules[current_module_idx]
559                    .mem_addrs
560                    .first()
561                    .unwrap_validated();
562                let mem = &store.memories[mem_addr];
563
564                let idx = calculate_mem_address(&memarg, relative_address)?;
565                let data: i16 = mem.mem.load(idx)?;
566
567                stack.push_value(Value::I32(data as u32))?;
568                trace!("Instruction: i32.load16_s [{relative_address}] -> [{data}]");
569            }
570            I32_LOAD16_U => {
571                let memarg = MemArg::read(wasm).unwrap_validated();
572                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
573
574                let mem_addr = *store.modules[current_module_idx]
575                    .mem_addrs
576                    .first()
577                    .unwrap_validated();
578                let mem = &store.memories[mem_addr];
579
580                let idx = calculate_mem_address(&memarg, relative_address)?;
581                let data: u16 = mem.mem.load(idx)?;
582
583                stack.push_value(Value::I32(data as u32))?;
584                trace!("Instruction: i32.load16_u [{relative_address}] -> [{data}]");
585            }
586            I64_LOAD8_S => {
587                let memarg = MemArg::read(wasm).unwrap_validated();
588                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
589
590                let mem_addr = *store.modules[current_module_idx]
591                    .mem_addrs
592                    .first()
593                    .unwrap_validated();
594                let mem = &store.memories[mem_addr];
595
596                let idx = calculate_mem_address(&memarg, relative_address)?;
597                let data: i8 = mem.mem.load(idx)?;
598
599                stack.push_value(Value::I64(data as u64))?;
600                trace!("Instruction: i64.load8_s [{relative_address}] -> [{data}]");
601            }
602            I64_LOAD8_U => {
603                let memarg = MemArg::read(wasm).unwrap_validated();
604                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
605
606                let mem_addr = *store.modules[current_module_idx]
607                    .mem_addrs
608                    .first()
609                    .unwrap_validated();
610                let mem = &store.memories[mem_addr];
611
612                let idx = calculate_mem_address(&memarg, relative_address)?;
613                let data: u8 = mem.mem.load(idx)?;
614
615                stack.push_value(Value::I64(data as u64))?;
616                trace!("Instruction: i64.load8_u [{relative_address}] -> [{data}]");
617            }
618            I64_LOAD16_S => {
619                let memarg = MemArg::read(wasm).unwrap_validated();
620                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
621
622                let mem_addr = *store.modules[current_module_idx]
623                    .mem_addrs
624                    .first()
625                    .unwrap_validated();
626                let mem = &store.memories[mem_addr];
627
628                let idx = calculate_mem_address(&memarg, relative_address)?;
629                let data: i16 = mem.mem.load(idx)?;
630
631                stack.push_value(Value::I64(data as u64))?;
632                trace!("Instruction: i64.load16_s [{relative_address}] -> [{data}]");
633            }
634            I64_LOAD16_U => {
635                let memarg = MemArg::read(wasm).unwrap_validated();
636                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
637
638                let mem_addr = *store.modules[current_module_idx]
639                    .mem_addrs
640                    .first()
641                    .unwrap_validated();
642                let mem = &store.memories[mem_addr];
643
644                let idx = calculate_mem_address(&memarg, relative_address)?;
645                let data: u16 = mem.mem.load(idx)?;
646
647                stack.push_value(Value::I64(data as u64))?;
648                trace!("Instruction: i64.load16_u [{relative_address}] -> [{data}]");
649            }
650            I64_LOAD32_S => {
651                let memarg = MemArg::read(wasm).unwrap_validated();
652                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
653
654                let mem_addr = *store.modules[current_module_idx]
655                    .mem_addrs
656                    .first()
657                    .unwrap_validated();
658                let mem = &store.memories[mem_addr];
659
660                let idx = calculate_mem_address(&memarg, relative_address)?;
661                let data: i32 = mem.mem.load(idx)?;
662
663                stack.push_value(Value::I64(data as u64))?;
664                trace!("Instruction: i64.load32_s [{relative_address}] -> [{data}]");
665            }
666            I64_LOAD32_U => {
667                let memarg = MemArg::read(wasm).unwrap_validated();
668                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
669
670                let mem_addr = *store.modules[current_module_idx]
671                    .mem_addrs
672                    .first()
673                    .unwrap_validated();
674                let mem = &store.memories[mem_addr];
675
676                let idx = calculate_mem_address(&memarg, relative_address)?;
677                let data: u32 = mem.mem.load(idx)?;
678
679                stack.push_value(Value::I64(data as u64))?;
680                trace!("Instruction: i64.load32_u [{relative_address}] -> [{data}]");
681            }
682            I32_STORE => {
683                let memarg = MemArg::read(wasm).unwrap_validated();
684
685                let data_to_store: u32 = stack.pop_value().try_into().unwrap_validated();
686                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
687
688                let mem_addr = *store.modules[current_module_idx]
689                    .mem_addrs
690                    .first()
691                    .unwrap_validated();
692                let mem = &store.memories[mem_addr];
693
694                let idx = calculate_mem_address(&memarg, relative_address)?;
695                mem.mem.store(idx, data_to_store)?;
696
697                trace!("Instruction: i32.store [{relative_address} {data_to_store}] -> []");
698            }
699            I64_STORE => {
700                let memarg = MemArg::read(wasm).unwrap_validated();
701
702                let data_to_store: u64 = stack.pop_value().try_into().unwrap_validated();
703                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
704
705                let mem_addr = *store.modules[current_module_idx]
706                    .mem_addrs
707                    .first()
708                    .unwrap_validated();
709                let mem = &store.memories[mem_addr];
710
711                let idx = calculate_mem_address(&memarg, relative_address)?;
712                mem.mem.store(idx, data_to_store)?;
713
714                trace!("Instruction: i64.store [{relative_address} {data_to_store}] -> []");
715            }
716            F32_STORE => {
717                let memarg = MemArg::read(wasm).unwrap_validated();
718
719                let data_to_store: F32 = stack.pop_value().try_into().unwrap_validated();
720                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
721
722                let mem_addr = *store.modules[current_module_idx]
723                    .mem_addrs
724                    .first()
725                    .unwrap_validated();
726                let mem = &store.memories[mem_addr];
727
728                let idx = calculate_mem_address(&memarg, relative_address)?;
729                mem.mem.store(idx, data_to_store)?;
730
731                trace!("Instruction: f32.store [{relative_address} {data_to_store}] -> []");
732            }
733            F64_STORE => {
734                let memarg = MemArg::read(wasm).unwrap_validated();
735
736                let data_to_store: F64 = stack.pop_value().try_into().unwrap_validated();
737                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
738
739                let mem_addr = *store.modules[current_module_idx]
740                    .mem_addrs
741                    .first()
742                    .unwrap_validated();
743                let mem = &store.memories[mem_addr];
744
745                let idx = calculate_mem_address(&memarg, relative_address)?;
746                mem.mem.store(idx, data_to_store)?;
747
748                trace!("Instruction: f64.store [{relative_address} {data_to_store}] -> []");
749            }
750            I32_STORE8 => {
751                let memarg = MemArg::read(wasm).unwrap_validated();
752
753                let data_to_store: i32 = stack.pop_value().try_into().unwrap_validated();
754                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
755
756                let wrapped_data = data_to_store as i8;
757
758                let mem_addr = *store.modules[current_module_idx]
759                    .mem_addrs
760                    .first()
761                    .unwrap_validated();
762                let mem = &store.memories[mem_addr];
763
764                let idx = calculate_mem_address(&memarg, relative_address)?;
765                mem.mem.store(idx, wrapped_data)?;
766
767                trace!("Instruction: i32.store8 [{relative_address} {wrapped_data}] -> []");
768            }
769            I32_STORE16 => {
770                let memarg = MemArg::read(wasm).unwrap_validated();
771
772                let data_to_store: i32 = stack.pop_value().try_into().unwrap_validated();
773                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
774
775                let wrapped_data = data_to_store as i16;
776
777                let mem_addr = *store.modules[current_module_idx]
778                    .mem_addrs
779                    .first()
780                    .unwrap_validated();
781                let mem = &store.memories[mem_addr];
782
783                let idx = calculate_mem_address(&memarg, relative_address)?;
784                mem.mem.store(idx, wrapped_data)?;
785
786                trace!("Instruction: i32.store16 [{relative_address} {data_to_store}] -> []");
787            }
788            I64_STORE8 => {
789                let memarg = MemArg::read(wasm).unwrap_validated();
790
791                let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
792                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
793
794                let wrapped_data = data_to_store as i8;
795
796                let mem_addr = *store.modules[current_module_idx]
797                    .mem_addrs
798                    .first()
799                    .unwrap_validated();
800                let mem = &store.memories[mem_addr];
801
802                let idx = calculate_mem_address(&memarg, relative_address)?;
803                mem.mem.store(idx, wrapped_data)?;
804
805                trace!("Instruction: i64.store8 [{relative_address} {data_to_store}] -> []");
806            }
807            I64_STORE16 => {
808                let memarg = MemArg::read(wasm).unwrap_validated();
809
810                let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
811                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
812
813                let wrapped_data = data_to_store as i16;
814
815                let mem_addr = *store.modules[current_module_idx]
816                    .mem_addrs
817                    .first()
818                    .unwrap_validated();
819                let mem = &store.memories[mem_addr];
820
821                let idx = calculate_mem_address(&memarg, relative_address)?;
822                mem.mem.store(idx, wrapped_data)?;
823
824                trace!("Instruction: i64.store16 [{relative_address} {data_to_store}] -> []");
825            }
826            I64_STORE32 => {
827                let memarg = MemArg::read(wasm).unwrap_validated();
828
829                let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
830                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
831
832                let wrapped_data = data_to_store as i32;
833
834                let mem_addr = *store.modules[current_module_idx]
835                    .mem_addrs
836                    .first()
837                    .unwrap_validated();
838                let mem = &store.memories[mem_addr];
839
840                let idx = calculate_mem_address(&memarg, relative_address)?;
841                mem.mem.store(idx, wrapped_data)?;
842
843                trace!("Instruction: i64.store32 [{relative_address} {data_to_store}] -> []");
844            }
845            MEMORY_SIZE => {
846                let mem_idx = wasm.read_u8().unwrap_validated() as usize;
847                let mem_addr = *store.modules[current_module_idx]
848                    .mem_addrs
849                    .get(mem_idx)
850                    .unwrap_validated();
851                let mem = &mut store.memories[mem_addr];
852                let size = mem.size() as u32;
853                stack.push_value(Value::I32(size))?;
854                trace!("Instruction: memory.size [] -> [{}]", size);
855            }
856            MEMORY_GROW => {
857                let mem_idx = wasm.read_u8().unwrap_validated() as usize;
858                let mem_addr = *store.modules[current_module_idx]
859                    .mem_addrs
860                    .get(mem_idx)
861                    .unwrap_validated();
862                let mem = &mut store.memories[mem_addr];
863                let sz: u32 = mem.size() as u32;
864
865                let n: u32 = stack.pop_value().try_into().unwrap_validated();
866
867                // TODO this instruction is non-deterministic w.r.t. spec, and can fail if the embedder wills it.
868                // for now we execute it always according to the following match expr.
869                // if the grow operation fails, err := Value::I32(2^32-1) is pushed to the stack per spec
870                let pushed_value = match mem.grow(n) {
871                    Ok(_) => sz,
872                    Err(_) => u32::MAX,
873                };
874                stack.push_value(Value::I32(pushed_value))?;
875                trace!("Instruction: memory.grow [{}] -> [{}]", n, pushed_value);
876            }
877            I32_CONST => {
878                let constant = wasm.read_var_i32().unwrap_validated();
879                trace!("Instruction: i32.const [] -> [{constant}]");
880                stack.push_value(constant.into())?;
881            }
882            F32_CONST => {
883                let constant = F32::from_bits(wasm.read_var_f32().unwrap_validated());
884                trace!("Instruction: f32.const [] -> [{constant:.7}]");
885                stack.push_value(constant.into())?;
886            }
887            I32_EQZ => {
888                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
889
890                let res = if v1 == 0 { 1 } else { 0 };
891
892                trace!("Instruction: i32.eqz [{v1}] -> [{res}]");
893                stack.push_value(res.into())?;
894            }
895            I32_EQ => {
896                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
897                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
898
899                let res = if v1 == v2 { 1 } else { 0 };
900
901                trace!("Instruction: i32.eq [{v1} {v2}] -> [{res}]");
902                stack.push_value(res.into())?;
903            }
904            I32_NE => {
905                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
906                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
907
908                let res = if v1 != v2 { 1 } else { 0 };
909
910                trace!("Instruction: i32.ne [{v1} {v2}] -> [{res}]");
911                stack.push_value(res.into())?;
912            }
913            I32_LT_S => {
914                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
915                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
916
917                let res = if v1 < v2 { 1 } else { 0 };
918
919                trace!("Instruction: i32.lt_s [{v1} {v2}] -> [{res}]");
920                stack.push_value(res.into())?;
921            }
922
923            I32_LT_U => {
924                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
925                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
926
927                let res = if (v1 as u32) < (v2 as u32) { 1 } else { 0 };
928
929                trace!("Instruction: i32.lt_u [{v1} {v2}] -> [{res}]");
930                stack.push_value(res.into())?;
931            }
932            I32_GT_S => {
933                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
934                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
935
936                let res = if v1 > v2 { 1 } else { 0 };
937
938                trace!("Instruction: i32.gt_s [{v1} {v2}] -> [{res}]");
939                stack.push_value(res.into())?;
940            }
941            I32_GT_U => {
942                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
943                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
944
945                let res = if (v1 as u32) > (v2 as u32) { 1 } else { 0 };
946
947                trace!("Instruction: i32.gt_u [{v1} {v2}] -> [{res}]");
948                stack.push_value(res.into())?;
949            }
950            I32_LE_S => {
951                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
952                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
953
954                let res = if v1 <= v2 { 1 } else { 0 };
955
956                trace!("Instruction: i32.le_s [{v1} {v2}] -> [{res}]");
957                stack.push_value(res.into())?;
958            }
959            I32_LE_U => {
960                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
961                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
962
963                let res = if (v1 as u32) <= (v2 as u32) { 1 } else { 0 };
964
965                trace!("Instruction: i32.le_u [{v1} {v2}] -> [{res}]");
966                stack.push_value(res.into())?;
967            }
968            I32_GE_S => {
969                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
970                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
971
972                let res = if v1 >= v2 { 1 } else { 0 };
973
974                trace!("Instruction: i32.ge_s [{v1} {v2}] -> [{res}]");
975                stack.push_value(res.into())?;
976            }
977            I32_GE_U => {
978                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
979                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
980
981                let res = if (v1 as u32) >= (v2 as u32) { 1 } else { 0 };
982
983                trace!("Instruction: i32.ge_u [{v1} {v2}] -> [{res}]");
984                stack.push_value(res.into())?;
985            }
986            I64_EQZ => {
987                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
988
989                let res = if v1 == 0 { 1 } else { 0 };
990
991                trace!("Instruction: i64.eqz [{v1}] -> [{res}]");
992                stack.push_value(res.into())?;
993            }
994            I64_EQ => {
995                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
996                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
997
998                let res = if v1 == v2 { 1 } else { 0 };
999
1000                trace!("Instruction: i64.eq [{v1} {v2}] -> [{res}]");
1001                stack.push_value(res.into())?;
1002            }
1003            I64_NE => {
1004                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1005                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1006
1007                let res = if v1 != v2 { 1 } else { 0 };
1008
1009                trace!("Instruction: i64.ne [{v1} {v2}] -> [{res}]");
1010                stack.push_value(res.into())?;
1011            }
1012            I64_LT_S => {
1013                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1014                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1015
1016                let res = if v1 < v2 { 1 } else { 0 };
1017
1018                trace!("Instruction: i64.lt_s [{v1} {v2}] -> [{res}]");
1019                stack.push_value(res.into())?;
1020            }
1021
1022            I64_LT_U => {
1023                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1024                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1025
1026                let res = if (v1 as u64) < (v2 as u64) { 1 } else { 0 };
1027
1028                trace!("Instruction: i64.lt_u [{v1} {v2}] -> [{res}]");
1029                stack.push_value(res.into())?;
1030            }
1031            I64_GT_S => {
1032                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1033                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1034
1035                let res = if v1 > v2 { 1 } else { 0 };
1036
1037                trace!("Instruction: i64.gt_s [{v1} {v2}] -> [{res}]");
1038                stack.push_value(res.into())?;
1039            }
1040            I64_GT_U => {
1041                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1042                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1043
1044                let res = if (v1 as u64) > (v2 as u64) { 1 } else { 0 };
1045
1046                trace!("Instruction: i64.gt_u [{v1} {v2}] -> [{res}]");
1047                stack.push_value(res.into())?;
1048            }
1049            I64_LE_S => {
1050                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1051                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1052
1053                let res = if v1 <= v2 { 1 } else { 0 };
1054
1055                trace!("Instruction: i64.le_s [{v1} {v2}] -> [{res}]");
1056                stack.push_value(res.into())?;
1057            }
1058            I64_LE_U => {
1059                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1060                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1061
1062                let res = if (v1 as u64) <= (v2 as u64) { 1 } else { 0 };
1063
1064                trace!("Instruction: i64.le_u [{v1} {v2}] -> [{res}]");
1065                stack.push_value(res.into())?;
1066            }
1067            I64_GE_S => {
1068                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1069                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1070
1071                let res = if v1 >= v2 { 1 } else { 0 };
1072
1073                trace!("Instruction: i64.ge_s [{v1} {v2}] -> [{res}]");
1074                stack.push_value(res.into())?;
1075            }
1076            I64_GE_U => {
1077                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1078                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1079
1080                let res = if (v1 as u64) >= (v2 as u64) { 1 } else { 0 };
1081
1082                trace!("Instruction: i64.ge_u [{v1} {v2}] -> [{res}]");
1083                stack.push_value(res.into())?;
1084            }
1085            F32_EQ => {
1086                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1087                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1088
1089                let res = if v1 == v2 { 1 } else { 0 };
1090
1091                trace!("Instruction: f32.eq [{v1} {v2}] -> [{res}]");
1092                stack.push_value(res.into())?;
1093            }
1094            F32_NE => {
1095                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1096                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1097
1098                let res = if v1 != v2 { 1 } else { 0 };
1099
1100                trace!("Instruction: f32.ne [{v1} {v2}] -> [{res}]");
1101                stack.push_value(res.into())?;
1102            }
1103            F32_LT => {
1104                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1105                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1106
1107                let res = if v1 < v2 { 1 } else { 0 };
1108
1109                trace!("Instruction: f32.lt [{v1} {v2}] -> [{res}]");
1110                stack.push_value(res.into())?;
1111            }
1112            F32_GT => {
1113                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1114                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1115
1116                let res = if v1 > v2 { 1 } else { 0 };
1117
1118                trace!("Instruction: f32.gt [{v1} {v2}] -> [{res}]");
1119                stack.push_value(res.into())?;
1120            }
1121            F32_LE => {
1122                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1123                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1124
1125                let res = if v1 <= v2 { 1 } else { 0 };
1126
1127                trace!("Instruction: f32.le [{v1} {v2}] -> [{res}]");
1128                stack.push_value(res.into())?;
1129            }
1130            F32_GE => {
1131                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1132                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1133
1134                let res = if v1 >= v2 { 1 } else { 0 };
1135
1136                trace!("Instruction: f32.ge [{v1} {v2}] -> [{res}]");
1137                stack.push_value(res.into())?;
1138            }
1139
1140            F64_EQ => {
1141                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1142                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1143
1144                let res = if v1 == v2 { 1 } else { 0 };
1145
1146                trace!("Instruction: f64.eq [{v1} {v2}] -> [{res}]");
1147                stack.push_value(res.into())?;
1148            }
1149            F64_NE => {
1150                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1151                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1152
1153                let res = if v1 != v2 { 1 } else { 0 };
1154
1155                trace!("Instruction: f64.ne [{v1} {v2}] -> [{res}]");
1156                stack.push_value(res.into())?;
1157            }
1158            F64_LT => {
1159                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1160                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1161
1162                let res = if v1 < v2 { 1 } else { 0 };
1163
1164                trace!("Instruction: f64.lt [{v1} {v2}] -> [{res}]");
1165                stack.push_value(res.into())?;
1166            }
1167            F64_GT => {
1168                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1169                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1170
1171                let res = if v1 > v2 { 1 } else { 0 };
1172
1173                trace!("Instruction: f64.gt [{v1} {v2}] -> [{res}]");
1174                stack.push_value(res.into())?;
1175            }
1176            F64_LE => {
1177                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1178                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1179
1180                let res = if v1 <= v2 { 1 } else { 0 };
1181
1182                trace!("Instruction: f64.le [{v1} {v2}] -> [{res}]");
1183                stack.push_value(res.into())?;
1184            }
1185            F64_GE => {
1186                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1187                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1188
1189                let res = if v1 >= v2 { 1 } else { 0 };
1190
1191                trace!("Instruction: f64.ge [{v1} {v2}] -> [{res}]");
1192                stack.push_value(res.into())?;
1193            }
1194
1195            I32_CLZ => {
1196                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1197                let res = v1.leading_zeros() as i32;
1198
1199                trace!("Instruction: i32.clz [{v1}] -> [{res}]");
1200                stack.push_value(res.into())?;
1201            }
1202            I32_CTZ => {
1203                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1204                let res = v1.trailing_zeros() as i32;
1205
1206                trace!("Instruction: i32.ctz [{v1}] -> [{res}]");
1207                stack.push_value(res.into())?;
1208            }
1209            I32_POPCNT => {
1210                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1211                let res = v1.count_ones() as i32;
1212
1213                trace!("Instruction: i32.popcnt [{v1}] -> [{res}]");
1214                stack.push_value(res.into())?;
1215            }
1216            I64_CONST => {
1217                let constant = wasm.read_var_i64().unwrap_validated();
1218                trace!("Instruction: i64.const [] -> [{constant}]");
1219                stack.push_value(constant.into())?;
1220            }
1221            F64_CONST => {
1222                let constant = F64::from_bits(wasm.read_var_f64().unwrap_validated());
1223                trace!("Instruction: f64.const [] -> [{constant}]");
1224                stack.push_value(constant.into())?;
1225            }
1226            I32_ADD => {
1227                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1228                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1229                let res = v1.wrapping_add(v2);
1230
1231                trace!("Instruction: i32.add [{v1} {v2}] -> [{res}]");
1232                stack.push_value(res.into())?;
1233            }
1234            I32_SUB => {
1235                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1236                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1237                let res = v1.wrapping_sub(v2);
1238
1239                trace!("Instruction: i32.sub [{v1} {v2}] -> [{res}]");
1240                stack.push_value(res.into())?;
1241            }
1242            I32_MUL => {
1243                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1244                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1245                let res = v1.wrapping_mul(v2);
1246
1247                trace!("Instruction: i32.mul [{v1} {v2}] -> [{res}]");
1248                stack.push_value(res.into())?;
1249            }
1250            I32_DIV_S => {
1251                let dividend: i32 = stack.pop_value().try_into().unwrap_validated();
1252                let divisor: i32 = stack.pop_value().try_into().unwrap_validated();
1253
1254                if dividend == 0 {
1255                    return Err(TrapError::DivideBy0.into());
1256                }
1257                if divisor == i32::MIN && dividend == -1 {
1258                    return Err(TrapError::UnrepresentableResult.into());
1259                }
1260
1261                let res = divisor / dividend;
1262
1263                trace!("Instruction: i32.div_s [{divisor} {dividend}] -> [{res}]");
1264                stack.push_value(res.into())?;
1265            }
1266            I32_DIV_U => {
1267                let dividend: i32 = stack.pop_value().try_into().unwrap_validated();
1268                let divisor: i32 = stack.pop_value().try_into().unwrap_validated();
1269
1270                let dividend = dividend as u32;
1271                let divisor = divisor as u32;
1272
1273                if dividend == 0 {
1274                    return Err(TrapError::DivideBy0.into());
1275                }
1276
1277                let res = (divisor / dividend) as i32;
1278
1279                trace!("Instruction: i32.div_u [{divisor} {dividend}] -> [{res}]");
1280                stack.push_value(res.into())?;
1281            }
1282            I32_REM_S => {
1283                let dividend: i32 = stack.pop_value().try_into().unwrap_validated();
1284                let divisor: i32 = stack.pop_value().try_into().unwrap_validated();
1285
1286                if dividend == 0 {
1287                    return Err(TrapError::DivideBy0.into());
1288                }
1289
1290                let res = divisor.checked_rem(dividend);
1291                let res = res.unwrap_or_default();
1292
1293                trace!("Instruction: i32.rem_s [{divisor} {dividend}] -> [{res}]");
1294                stack.push_value(res.into())?;
1295            }
1296            I64_CLZ => {
1297                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1298                let res = v1.leading_zeros() as i64;
1299
1300                trace!("Instruction: i64.clz [{v1}] -> [{res}]");
1301                stack.push_value(res.into())?;
1302            }
1303            I64_CTZ => {
1304                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1305                let res = v1.trailing_zeros() as i64;
1306
1307                trace!("Instruction: i64.ctz [{v1}] -> [{res}]");
1308                stack.push_value(res.into())?;
1309            }
1310            I64_POPCNT => {
1311                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1312                let res = v1.count_ones() as i64;
1313
1314                trace!("Instruction: i64.popcnt [{v1}] -> [{res}]");
1315                stack.push_value(res.into())?;
1316            }
1317            I64_ADD => {
1318                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1319                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1320                let res = v1.wrapping_add(v2);
1321
1322                trace!("Instruction: i64.add [{v1} {v2}] -> [{res}]");
1323                stack.push_value(res.into())?;
1324            }
1325            I64_SUB => {
1326                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1327                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1328                let res = v1.wrapping_sub(v2);
1329
1330                trace!("Instruction: i64.sub [{v1} {v2}] -> [{res}]");
1331                stack.push_value(res.into())?;
1332            }
1333            I64_MUL => {
1334                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1335                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1336                let res = v1.wrapping_mul(v2);
1337
1338                trace!("Instruction: i64.mul [{v1} {v2}] -> [{res}]");
1339                stack.push_value(res.into())?;
1340            }
1341            I64_DIV_S => {
1342                let dividend: i64 = stack.pop_value().try_into().unwrap_validated();
1343                let divisor: i64 = stack.pop_value().try_into().unwrap_validated();
1344
1345                if dividend == 0 {
1346                    return Err(TrapError::DivideBy0.into());
1347                }
1348                if divisor == i64::MIN && dividend == -1 {
1349                    return Err(TrapError::UnrepresentableResult.into());
1350                }
1351
1352                let res = divisor / dividend;
1353
1354                trace!("Instruction: i64.div_s [{divisor} {dividend}] -> [{res}]");
1355                stack.push_value(res.into())?;
1356            }
1357            I64_DIV_U => {
1358                let dividend: i64 = stack.pop_value().try_into().unwrap_validated();
1359                let divisor: i64 = stack.pop_value().try_into().unwrap_validated();
1360
1361                let dividend = dividend as u64;
1362                let divisor = divisor as u64;
1363
1364                if dividend == 0 {
1365                    return Err(TrapError::DivideBy0.into());
1366                }
1367
1368                let res = (divisor / dividend) as i64;
1369
1370                trace!("Instruction: i64.div_u [{divisor} {dividend}] -> [{res}]");
1371                stack.push_value(res.into())?;
1372            }
1373            I64_REM_S => {
1374                let dividend: i64 = stack.pop_value().try_into().unwrap_validated();
1375                let divisor: i64 = stack.pop_value().try_into().unwrap_validated();
1376
1377                if dividend == 0 {
1378                    return Err(TrapError::DivideBy0.into());
1379                }
1380
1381                let res = divisor.checked_rem(dividend);
1382                let res = res.unwrap_or_default();
1383
1384                trace!("Instruction: i64.rem_s [{divisor} {dividend}] -> [{res}]");
1385                stack.push_value(res.into())?;
1386            }
1387            I64_REM_U => {
1388                let dividend: i64 = stack.pop_value().try_into().unwrap_validated();
1389                let divisor: i64 = stack.pop_value().try_into().unwrap_validated();
1390
1391                let dividend = dividend as u64;
1392                let divisor = divisor as u64;
1393
1394                if dividend == 0 {
1395                    return Err(TrapError::DivideBy0.into());
1396                }
1397
1398                let res = (divisor % dividend) as i64;
1399
1400                trace!("Instruction: i64.rem_u [{divisor} {dividend}] -> [{res}]");
1401                stack.push_value(res.into())?;
1402            }
1403            I64_AND => {
1404                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1405                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1406
1407                let res = v1 & v2;
1408
1409                trace!("Instruction: i64.and [{v1} {v2}] -> [{res}]");
1410                stack.push_value(res.into())?;
1411            }
1412            I64_OR => {
1413                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1414                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1415
1416                let res = v1 | v2;
1417
1418                trace!("Instruction: i64.or [{v1} {v2}] -> [{res}]");
1419                stack.push_value(res.into())?;
1420            }
1421            I64_XOR => {
1422                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1423                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1424
1425                let res = v1 ^ v2;
1426
1427                trace!("Instruction: i64.xor [{v1} {v2}] -> [{res}]");
1428                stack.push_value(res.into())?;
1429            }
1430            I64_SHL => {
1431                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1432                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1433
1434                let res = v1.wrapping_shl((v2 & 63) as u32);
1435
1436                trace!("Instruction: i64.shl [{v1} {v2}] -> [{res}]");
1437                stack.push_value(res.into())?;
1438            }
1439            I64_SHR_S => {
1440                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1441                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1442
1443                let res = v1.wrapping_shr((v2 & 63) as u32);
1444
1445                trace!("Instruction: i64.shr_s [{v1} {v2}] -> [{res}]");
1446                stack.push_value(res.into())?;
1447            }
1448            I64_SHR_U => {
1449                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1450                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1451
1452                let res = (v1 as u64).wrapping_shr((v2 & 63) as u32);
1453
1454                trace!("Instruction: i64.shr_u [{v1} {v2}] -> [{res}]");
1455                stack.push_value(res.into())?;
1456            }
1457            I64_ROTL => {
1458                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1459                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1460
1461                let res = v1.rotate_left((v2 & 63) as u32);
1462
1463                trace!("Instruction: i64.rotl [{v1} {v2}] -> [{res}]");
1464                stack.push_value(res.into())?;
1465            }
1466            I64_ROTR => {
1467                let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1468                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1469
1470                let res = v1.rotate_right((v2 & 63) as u32);
1471
1472                trace!("Instruction: i64.rotr [{v1} {v2}] -> [{res}]");
1473                stack.push_value(res.into())?;
1474            }
1475            I32_REM_U => {
1476                let dividend: i32 = stack.pop_value().try_into().unwrap_validated();
1477                let divisor: i32 = stack.pop_value().try_into().unwrap_validated();
1478
1479                let dividend = dividend as u32;
1480                let divisor = divisor as u32;
1481
1482                if dividend == 0 {
1483                    return Err(TrapError::DivideBy0.into());
1484                }
1485
1486                let res = divisor.checked_rem(dividend);
1487                let res = res.unwrap_or_default() as i32;
1488
1489                trace!("Instruction: i32.rem_u [{divisor} {dividend}] -> [{res}]");
1490                stack.push_value(res.into())?;
1491            }
1492            I32_AND => {
1493                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1494                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1495                let res = v1 & v2;
1496
1497                trace!("Instruction: i32.and [{v1} {v2}] -> [{res}]");
1498                stack.push_value(res.into())?;
1499            }
1500            I32_OR => {
1501                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1502                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1503                let res = v1 | v2;
1504
1505                trace!("Instruction: i32.or [{v1} {v2}] -> [{res}]");
1506                stack.push_value(res.into())?;
1507            }
1508            I32_XOR => {
1509                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1510                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1511                let res = v1 ^ v2;
1512
1513                trace!("Instruction: i32.xor [{v1} {v2}] -> [{res}]");
1514                stack.push_value(res.into())?;
1515            }
1516            I32_SHL => {
1517                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1518                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1519                let res = v2.wrapping_shl(v1 as u32);
1520
1521                trace!("Instruction: i32.shl [{v2} {v1}] -> [{res}]");
1522                stack.push_value(res.into())?;
1523            }
1524            I32_SHR_S => {
1525                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1526                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1527
1528                let res = v2.wrapping_shr(v1 as u32);
1529
1530                trace!("Instruction: i32.shr_s [{v2} {v1}] -> [{res}]");
1531                stack.push_value(res.into())?;
1532            }
1533            I32_SHR_U => {
1534                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1535                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1536
1537                let res = (v2 as u32).wrapping_shr(v1 as u32) as i32;
1538
1539                trace!("Instruction: i32.shr_u [{v2} {v1}] -> [{res}]");
1540                stack.push_value(res.into())?;
1541            }
1542            I32_ROTL => {
1543                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1544                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1545
1546                let res = v2.rotate_left(v1 as u32);
1547
1548                trace!("Instruction: i32.rotl [{v2} {v1}] -> [{res}]");
1549                stack.push_value(res.into())?;
1550            }
1551            I32_ROTR => {
1552                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1553                let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1554
1555                let res = v2.rotate_right(v1 as u32);
1556
1557                trace!("Instruction: i32.rotr [{v2} {v1}] -> [{res}]");
1558                stack.push_value(res.into())?;
1559            }
1560
1561            F32_ABS => {
1562                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1563                let res: value::F32 = v1.abs();
1564
1565                trace!("Instruction: f32.abs [{v1}] -> [{res}]");
1566                stack.push_value(res.into())?;
1567            }
1568            F32_NEG => {
1569                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1570                let res: value::F32 = v1.neg();
1571
1572                trace!("Instruction: f32.neg [{v1}] -> [{res}]");
1573                stack.push_value(res.into())?;
1574            }
1575            F32_CEIL => {
1576                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1577                let res: value::F32 = v1.ceil();
1578
1579                trace!("Instruction: f32.ceil [{v1}] -> [{res}]");
1580                stack.push_value(res.into())?;
1581            }
1582            F32_FLOOR => {
1583                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1584                let res: value::F32 = v1.floor();
1585
1586                trace!("Instruction: f32.floor [{v1}] -> [{res}]");
1587                stack.push_value(res.into())?;
1588            }
1589            F32_TRUNC => {
1590                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1591                let res: value::F32 = v1.trunc();
1592
1593                trace!("Instruction: f32.trunc [{v1}] -> [{res}]");
1594                stack.push_value(res.into())?;
1595            }
1596            F32_NEAREST => {
1597                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1598                let res: value::F32 = v1.nearest();
1599
1600                trace!("Instruction: f32.nearest [{v1}] -> [{res}]");
1601                stack.push_value(res.into())?;
1602            }
1603            F32_SQRT => {
1604                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1605                let res: value::F32 = v1.sqrt();
1606
1607                trace!("Instruction: f32.sqrt [{v1}] -> [{res}]");
1608                stack.push_value(res.into())?;
1609            }
1610            F32_ADD => {
1611                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1612                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1613                let res: value::F32 = v1 + v2;
1614
1615                trace!("Instruction: f32.add [{v1} {v2}] -> [{res}]");
1616                stack.push_value(res.into())?;
1617            }
1618            F32_SUB => {
1619                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1620                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1621                let res: value::F32 = v1 - v2;
1622
1623                trace!("Instruction: f32.sub [{v1} {v2}] -> [{res}]");
1624                stack.push_value(res.into())?;
1625            }
1626            F32_MUL => {
1627                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1628                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1629                let res: value::F32 = v1 * v2;
1630
1631                trace!("Instruction: f32.mul [{v1} {v2}] -> [{res}]");
1632                stack.push_value(res.into())?;
1633            }
1634            F32_DIV => {
1635                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1636                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1637                let res: value::F32 = v1 / v2;
1638
1639                trace!("Instruction: f32.div [{v1} {v2}] -> [{res}]");
1640                stack.push_value(res.into())?;
1641            }
1642            F32_MIN => {
1643                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1644                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1645                let res: value::F32 = v1.min(v2);
1646
1647                trace!("Instruction: f32.min [{v1} {v2}] -> [{res}]");
1648                stack.push_value(res.into())?;
1649            }
1650            F32_MAX => {
1651                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1652                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1653                let res: value::F32 = v1.max(v2);
1654
1655                trace!("Instruction: f32.max [{v1} {v2}] -> [{res}]");
1656                stack.push_value(res.into())?;
1657            }
1658            F32_COPYSIGN => {
1659                let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1660                let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1661                let res: value::F32 = v1.copysign(v2);
1662
1663                trace!("Instruction: f32.copysign [{v1} {v2}] -> [{res}]");
1664                stack.push_value(res.into())?;
1665            }
1666
1667            F64_ABS => {
1668                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1669                let res: value::F64 = v1.abs();
1670
1671                trace!("Instruction: f64.abs [{v1}] -> [{res}]");
1672                stack.push_value(res.into())?;
1673            }
1674            F64_NEG => {
1675                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1676                let res: value::F64 = v1.neg();
1677
1678                trace!("Instruction: f64.neg [{v1}] -> [{res}]");
1679                stack.push_value(res.into())?;
1680            }
1681            F64_CEIL => {
1682                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1683                let res: value::F64 = v1.ceil();
1684
1685                trace!("Instruction: f64.ceil [{v1}] -> [{res}]");
1686                stack.push_value(res.into())?;
1687            }
1688            F64_FLOOR => {
1689                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1690                let res: value::F64 = v1.floor();
1691
1692                trace!("Instruction: f64.floor [{v1}] -> [{res}]");
1693                stack.push_value(res.into())?;
1694            }
1695            F64_TRUNC => {
1696                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1697                let res: value::F64 = v1.trunc();
1698
1699                trace!("Instruction: f64.trunc [{v1}] -> [{res}]");
1700                stack.push_value(res.into())?;
1701            }
1702            F64_NEAREST => {
1703                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1704                let res: value::F64 = v1.nearest();
1705
1706                trace!("Instruction: f64.nearest [{v1}] -> [{res}]");
1707                stack.push_value(res.into())?;
1708            }
1709            F64_SQRT => {
1710                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1711                let res: value::F64 = v1.sqrt();
1712
1713                trace!("Instruction: f64.sqrt [{v1}] -> [{res}]");
1714                stack.push_value(res.into())?;
1715            }
1716            F64_ADD => {
1717                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1718                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1719                let res: value::F64 = v1 + v2;
1720
1721                trace!("Instruction: f64.add [{v1} {v2}] -> [{res}]");
1722                stack.push_value(res.into())?;
1723            }
1724            F64_SUB => {
1725                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1726                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1727                let res: value::F64 = v1 - v2;
1728
1729                trace!("Instruction: f64.sub [{v1} {v2}] -> [{res}]");
1730                stack.push_value(res.into())?;
1731            }
1732            F64_MUL => {
1733                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1734                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1735                let res: value::F64 = v1 * v2;
1736
1737                trace!("Instruction: f64.mul [{v1} {v2}] -> [{res}]");
1738                stack.push_value(res.into())?;
1739            }
1740            F64_DIV => {
1741                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1742                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1743                let res: value::F64 = v1 / v2;
1744
1745                trace!("Instruction: f64.div [{v1} {v2}] -> [{res}]");
1746                stack.push_value(res.into())?;
1747            }
1748            F64_MIN => {
1749                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1750                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1751                let res: value::F64 = v1.min(v2);
1752
1753                trace!("Instruction: f64.min [{v1} {v2}] -> [{res}]");
1754                stack.push_value(res.into())?;
1755            }
1756            F64_MAX => {
1757                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1758                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1759                let res: value::F64 = v1.max(v2);
1760
1761                trace!("Instruction: f64.max [{v1} {v2}] -> [{res}]");
1762                stack.push_value(res.into())?;
1763            }
1764            F64_COPYSIGN => {
1765                let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1766                let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1767                let res: value::F64 = v1.copysign(v2);
1768
1769                trace!("Instruction: f64.copysign [{v1} {v2}] -> [{res}]");
1770                stack.push_value(res.into())?;
1771            }
1772            I32_WRAP_I64 => {
1773                let v: i64 = stack.pop_value().try_into().unwrap_validated();
1774                let res: i32 = v as i32;
1775
1776                trace!("Instruction: i32.wrap_i64 [{v}] -> [{res}]");
1777                stack.push_value(res.into())?;
1778            }
1779            I32_TRUNC_F32_S => {
1780                let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
1781                if v.is_infinity() {
1782                    return Err(TrapError::UnrepresentableResult.into());
1783                }
1784                if v.is_nan() {
1785                    return Err(TrapError::BadConversionToInteger.into());
1786                }
1787                if v >= value::F32(2147483648.0) || v <= value::F32(-2147483904.0) {
1788                    return Err(TrapError::UnrepresentableResult.into());
1789                }
1790
1791                let res: i32 = v.as_i32();
1792
1793                trace!("Instruction: i32.trunc_f32_s [{v:.7}] -> [{res}]");
1794                stack.push_value(res.into())?;
1795            }
1796            I32_TRUNC_F32_U => {
1797                let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
1798                if v.is_infinity() {
1799                    return Err(TrapError::UnrepresentableResult.into());
1800                }
1801                if v.is_nan() {
1802                    return Err(TrapError::BadConversionToInteger.into());
1803                }
1804                if v >= value::F32(4294967296.0) || v <= value::F32(-1.0) {
1805                    return Err(TrapError::UnrepresentableResult.into());
1806                }
1807
1808                let res: i32 = v.as_u32() as i32;
1809
1810                trace!("Instruction: i32.trunc_f32_u [{v:.7}] -> [{res}]");
1811                stack.push_value(res.into())?;
1812            }
1813
1814            I32_TRUNC_F64_S => {
1815                let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
1816                if v.is_infinity() {
1817                    return Err(TrapError::UnrepresentableResult.into());
1818                }
1819                if v.is_nan() {
1820                    return Err(TrapError::BadConversionToInteger.into());
1821                }
1822                if v >= value::F64(2147483648.0) || v <= value::F64(-2147483649.0) {
1823                    return Err(TrapError::UnrepresentableResult.into());
1824                }
1825
1826                let res: i32 = v.as_i32();
1827
1828                trace!("Instruction: i32.trunc_f64_s [{v:.7}] -> [{res}]");
1829                stack.push_value(res.into())?;
1830            }
1831            I32_TRUNC_F64_U => {
1832                let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
1833                if v.is_infinity() {
1834                    return Err(TrapError::UnrepresentableResult.into());
1835                }
1836                if v.is_nan() {
1837                    return Err(TrapError::BadConversionToInteger.into());
1838                }
1839                if v >= value::F64(4294967296.0) || v <= value::F64(-1.0) {
1840                    return Err(TrapError::UnrepresentableResult.into());
1841                }
1842
1843                let res: i32 = v.as_u32() as i32;
1844
1845                trace!("Instruction: i32.trunc_f32_u [{v:.7}] -> [{res}]");
1846                stack.push_value(res.into())?;
1847            }
1848
1849            I64_EXTEND_I32_S => {
1850                let v: i32 = stack.pop_value().try_into().unwrap_validated();
1851
1852                let res: i64 = v as i64;
1853
1854                trace!("Instruction: i64.extend_i32_s [{v}] -> [{res}]");
1855                stack.push_value(res.into())?;
1856            }
1857
1858            I64_EXTEND_I32_U => {
1859                let v: i32 = stack.pop_value().try_into().unwrap_validated();
1860
1861                let res: i64 = v as u32 as i64;
1862
1863                trace!("Instruction: i64.extend_i32_u [{v}] -> [{res}]");
1864                stack.push_value(res.into())?;
1865            }
1866
1867            I64_TRUNC_F32_S => {
1868                let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
1869                if v.is_infinity() {
1870                    return Err(TrapError::UnrepresentableResult.into());
1871                }
1872                if v.is_nan() {
1873                    return Err(TrapError::BadConversionToInteger.into());
1874                }
1875                if v >= value::F32(9223372036854775808.0) || v <= value::F32(-9223373136366403584.0)
1876                {
1877                    return Err(TrapError::UnrepresentableResult.into());
1878                }
1879
1880                let res: i64 = v.as_i64();
1881
1882                trace!("Instruction: i64.trunc_f32_s [{v:.7}] -> [{res}]");
1883                stack.push_value(res.into())?;
1884            }
1885            I64_TRUNC_F32_U => {
1886                let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
1887                if v.is_infinity() {
1888                    return Err(TrapError::UnrepresentableResult.into());
1889                }
1890                if v.is_nan() {
1891                    return Err(TrapError::BadConversionToInteger.into());
1892                }
1893                if v >= value::F32(18446744073709551616.0) || v <= value::F32(-1.0) {
1894                    return Err(TrapError::UnrepresentableResult.into());
1895                }
1896
1897                let res: i64 = v.as_u64() as i64;
1898
1899                trace!("Instruction: i64.trunc_f32_u [{v:.7}] -> [{res}]");
1900                stack.push_value(res.into())?;
1901            }
1902
1903            I64_TRUNC_F64_S => {
1904                let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
1905                if v.is_infinity() {
1906                    return Err(TrapError::UnrepresentableResult.into());
1907                }
1908                if v.is_nan() {
1909                    return Err(TrapError::BadConversionToInteger.into());
1910                }
1911                if v >= value::F64(9223372036854775808.0) || v <= value::F64(-9223372036854777856.0)
1912                {
1913                    return Err(TrapError::UnrepresentableResult.into());
1914                }
1915
1916                let res: i64 = v.as_i64();
1917
1918                trace!("Instruction: i64.trunc_f64_s [{v:.17}] -> [{res}]");
1919                stack.push_value(res.into())?;
1920            }
1921            I64_TRUNC_F64_U => {
1922                let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
1923                if v.is_infinity() {
1924                    return Err(TrapError::UnrepresentableResult.into());
1925                }
1926                if v.is_nan() {
1927                    return Err(TrapError::BadConversionToInteger.into());
1928                }
1929                if v >= value::F64(18446744073709551616.0) || v <= value::F64(-1.0) {
1930                    return Err(TrapError::UnrepresentableResult.into());
1931                }
1932
1933                let res: i64 = v.as_u64() as i64;
1934
1935                trace!("Instruction: i64.trunc_f64_u [{v:.17}] -> [{res}]");
1936                stack.push_value(res.into())?;
1937            }
1938            F32_CONVERT_I32_S => {
1939                let v: i32 = stack.pop_value().try_into().unwrap_validated();
1940                let res: value::F32 = value::F32(v as f32);
1941
1942                trace!("Instruction: f32.convert_i32_s [{v}] -> [{res}]");
1943                stack.push_value(res.into())?;
1944            }
1945            F32_CONVERT_I32_U => {
1946                let v: i32 = stack.pop_value().try_into().unwrap_validated();
1947                let res: value::F32 = value::F32(v as u32 as f32);
1948
1949                trace!("Instruction: f32.convert_i32_u [{v}] -> [{res}]");
1950                stack.push_value(res.into())?;
1951            }
1952            F32_CONVERT_I64_S => {
1953                let v: i64 = stack.pop_value().try_into().unwrap_validated();
1954                let res: value::F32 = value::F32(v as f32);
1955
1956                trace!("Instruction: f32.convert_i64_s [{v}] -> [{res}]");
1957                stack.push_value(res.into())?;
1958            }
1959            F32_CONVERT_I64_U => {
1960                let v: i64 = stack.pop_value().try_into().unwrap_validated();
1961                let res: value::F32 = value::F32(v as u64 as f32);
1962
1963                trace!("Instruction: f32.convert_i64_u [{v}] -> [{res}]");
1964                stack.push_value(res.into())?;
1965            }
1966            F32_DEMOTE_F64 => {
1967                let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
1968                let res: value::F32 = v.as_f32();
1969
1970                trace!("Instruction: f32.demote_f64 [{v:.17}] -> [{res:.7}]");
1971                stack.push_value(res.into())?;
1972            }
1973            F64_CONVERT_I32_S => {
1974                let v: i32 = stack.pop_value().try_into().unwrap_validated();
1975                let res: value::F64 = value::F64(v as f64);
1976
1977                trace!("Instruction: f64.convert_i32_s [{v}] -> [{res:.17}]");
1978                stack.push_value(res.into())?;
1979            }
1980            F64_CONVERT_I32_U => {
1981                let v: i32 = stack.pop_value().try_into().unwrap_validated();
1982                let res: value::F64 = value::F64(v as u32 as f64);
1983
1984                trace!("Instruction: f64.convert_i32_u [{v}] -> [{res:.17}]");
1985                stack.push_value(res.into())?;
1986            }
1987            F64_CONVERT_I64_S => {
1988                let v: i64 = stack.pop_value().try_into().unwrap_validated();
1989                let res: value::F64 = value::F64(v as f64);
1990
1991                trace!("Instruction: f64.convert_i64_s [{v}] -> [{res:.17}]");
1992                stack.push_value(res.into())?;
1993            }
1994            F64_CONVERT_I64_U => {
1995                let v: i64 = stack.pop_value().try_into().unwrap_validated();
1996                let res: value::F64 = value::F64(v as u64 as f64);
1997
1998                trace!("Instruction: f64.convert_i64_u [{v}] -> [{res:.17}]");
1999                stack.push_value(res.into())?;
2000            }
2001            F64_PROMOTE_F32 => {
2002                let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
2003                let res: value::F64 = v.as_f64();
2004
2005                trace!("Instruction: f64.promote_f32 [{v:.7}] -> [{res:.17}]");
2006                stack.push_value(res.into())?;
2007            }
2008            I32_REINTERPRET_F32 => {
2009                let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
2010                let res: i32 = v.reinterpret_as_i32();
2011
2012                trace!("Instruction: i32.reinterpret_f32 [{v:.7}] -> [{res}]");
2013                stack.push_value(res.into())?;
2014            }
2015            I64_REINTERPRET_F64 => {
2016                let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
2017                let res: i64 = v.reinterpret_as_i64();
2018
2019                trace!("Instruction: i64.reinterpret_f64 [{v:.17}] -> [{res}]");
2020                stack.push_value(res.into())?;
2021            }
2022            F32_REINTERPRET_I32 => {
2023                let v1: i32 = stack.pop_value().try_into().unwrap_validated();
2024                let res: value::F32 = value::F32::from_bits(v1 as u32);
2025
2026                trace!("Instruction: f32.reinterpret_i32 [{v1}] -> [{res:.7}]");
2027                stack.push_value(res.into())?;
2028            }
2029            F64_REINTERPRET_I64 => {
2030                let v1: i64 = stack.pop_value().try_into().unwrap_validated();
2031                let res: value::F64 = value::F64::from_bits(v1 as u64);
2032
2033                trace!("Instruction: f64.reinterpret_i64 [{v1}] -> [{res:.17}]");
2034                stack.push_value(res.into())?;
2035            }
2036            REF_NULL => {
2037                let reftype = RefType::read(wasm).unwrap_validated();
2038
2039                stack.push_value(Value::Ref(Ref::Null(reftype)))?;
2040                trace!("Instruction: ref.null '{:?}' -> [{:?}]", reftype, reftype);
2041            }
2042            REF_IS_NULL => {
2043                let rref: Ref = stack.pop_value().try_into().unwrap_validated();
2044                let is_null = matches!(rref, Ref::Null(_));
2045
2046                let res = if is_null { 1 } else { 0 };
2047                trace!("Instruction: ref.is_null [{}] -> [{}]", rref, res);
2048                stack.push_value(Value::I32(res))?;
2049            }
2050            // https://webassembly.github.io/spec/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-ref-mathsf-ref-func-x
2051            REF_FUNC => {
2052                let func_idx = wasm.read_var_u32().unwrap_validated() as FuncIdx;
2053                let func_addr = *store.modules[current_module_idx]
2054                    .func_addrs
2055                    .get(func_idx)
2056                    .unwrap_validated();
2057                stack.push_value(Value::Ref(Ref::Func(FuncAddr(func_addr))))?;
2058            }
2059            FC_EXTENSIONS => {
2060                // Should we call instruction hook here as well? Multibyte instruction
2061                let second_instr = wasm.read_var_u32().unwrap_validated();
2062
2063                use crate::core::reader::types::opcode::fc_extensions::*;
2064                match second_instr {
2065                    I32_TRUNC_SAT_F32_S => {
2066                        let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2067                        let res = {
2068                            if v1.is_nan() {
2069                                0
2070                            } else if v1.is_negative_infinity() {
2071                                i32::MIN
2072                            } else if v1.is_infinity() {
2073                                i32::MAX
2074                            } else {
2075                                v1.as_i32()
2076                            }
2077                        };
2078
2079                        trace!("Instruction: i32.trunc_sat_f32_s [{v1}] -> [{res}]");
2080                        stack.push_value(res.into())?;
2081                    }
2082                    I32_TRUNC_SAT_F32_U => {
2083                        let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2084                        let res = {
2085                            if v1.is_nan() || v1.is_negative_infinity() {
2086                                0
2087                            } else if v1.is_infinity() {
2088                                u32::MAX as i32
2089                            } else {
2090                                v1.as_u32() as i32
2091                            }
2092                        };
2093
2094                        trace!("Instruction: i32.trunc_sat_f32_u [{v1}] -> [{res}]");
2095                        stack.push_value(res.into())?;
2096                    }
2097                    I32_TRUNC_SAT_F64_S => {
2098                        let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2099                        let res = {
2100                            if v1.is_nan() {
2101                                0
2102                            } else if v1.is_negative_infinity() {
2103                                i32::MIN
2104                            } else if v1.is_infinity() {
2105                                i32::MAX
2106                            } else {
2107                                v1.as_i32()
2108                            }
2109                        };
2110
2111                        trace!("Instruction: i32.trunc_sat_f64_s [{v1}] -> [{res}]");
2112                        stack.push_value(res.into())?;
2113                    }
2114                    I32_TRUNC_SAT_F64_U => {
2115                        let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2116                        let res = {
2117                            if v1.is_nan() || v1.is_negative_infinity() {
2118                                0
2119                            } else if v1.is_infinity() {
2120                                u32::MAX as i32
2121                            } else {
2122                                v1.as_u32() as i32
2123                            }
2124                        };
2125
2126                        trace!("Instruction: i32.trunc_sat_f64_u [{v1}] -> [{res}]");
2127                        stack.push_value(res.into())?;
2128                    }
2129                    I64_TRUNC_SAT_F32_S => {
2130                        let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2131                        let res = {
2132                            if v1.is_nan() {
2133                                0
2134                            } else if v1.is_negative_infinity() {
2135                                i64::MIN
2136                            } else if v1.is_infinity() {
2137                                i64::MAX
2138                            } else {
2139                                v1.as_i64()
2140                            }
2141                        };
2142
2143                        trace!("Instruction: i64.trunc_sat_f32_s [{v1}] -> [{res}]");
2144                        stack.push_value(res.into())?;
2145                    }
2146                    I64_TRUNC_SAT_F32_U => {
2147                        let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2148                        let res = {
2149                            if v1.is_nan() || v1.is_negative_infinity() {
2150                                0
2151                            } else if v1.is_infinity() {
2152                                u64::MAX as i64
2153                            } else {
2154                                v1.as_u64() as i64
2155                            }
2156                        };
2157
2158                        trace!("Instruction: i64.trunc_sat_f32_u [{v1}] -> [{res}]");
2159                        stack.push_value(res.into())?;
2160                    }
2161                    I64_TRUNC_SAT_F64_S => {
2162                        let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2163                        let res = {
2164                            if v1.is_nan() {
2165                                0
2166                            } else if v1.is_negative_infinity() {
2167                                i64::MIN
2168                            } else if v1.is_infinity() {
2169                                i64::MAX
2170                            } else {
2171                                v1.as_i64()
2172                            }
2173                        };
2174
2175                        trace!("Instruction: i64.trunc_sat_f64_s [{v1}] -> [{res}]");
2176                        stack.push_value(res.into())?;
2177                    }
2178                    I64_TRUNC_SAT_F64_U => {
2179                        let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2180                        let res = {
2181                            if v1.is_nan() || v1.is_negative_infinity() {
2182                                0
2183                            } else if v1.is_infinity() {
2184                                u64::MAX as i64
2185                            } else {
2186                                v1.as_u64() as i64
2187                            }
2188                        };
2189
2190                        trace!("Instruction: i64.trunc_sat_f64_u [{v1}] -> [{res}]");
2191                        stack.push_value(res.into())?;
2192                    }
2193                    // See https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-memory-mathsf-memory-init-x
2194                    // Copy a region from a data segment into memory
2195                    MEMORY_INIT => {
2196                        //  mappings:
2197                        //      n => number of bytes to copy
2198                        //      s => starting pointer in the data segment
2199                        //      d => destination address to copy to
2200                        let data_idx = wasm.read_var_u32().unwrap_validated() as DataIdx;
2201                        let mem_idx = wasm.read_u8().unwrap_validated() as usize;
2202
2203                        let n: i32 = stack.pop_value().try_into().unwrap_validated();
2204                        let s: i32 = stack.pop_value().try_into().unwrap_validated();
2205                        let d: i32 = stack.pop_value().try_into().unwrap_validated();
2206
2207                        memory_init(
2208                            &store.modules,
2209                            &mut store.memories,
2210                            &store.data,
2211                            current_module_idx,
2212                            data_idx,
2213                            mem_idx,
2214                            n,
2215                            s,
2216                            d,
2217                        )?;
2218                    }
2219                    DATA_DROP => {
2220                        let data_idx = wasm.read_var_u32().unwrap_validated() as DataIdx;
2221                        data_drop(
2222                            &store.modules,
2223                            &mut store.data,
2224                            current_module_idx,
2225                            data_idx,
2226                        )?;
2227                    }
2228                    // See https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-memory-mathsf-memory-copy
2229                    MEMORY_COPY => {
2230                        //  mappings:
2231                        //      n => number of bytes to copy
2232                        //      s => source address to copy from
2233                        //      d => destination address to copy to
2234                        let (dst_idx, src_idx) = (
2235                            wasm.read_u8().unwrap_validated() as usize,
2236                            wasm.read_u8().unwrap_validated() as usize,
2237                        );
2238                        let n: i32 = stack.pop_value().try_into().unwrap_validated();
2239                        let s: i32 = stack.pop_value().try_into().unwrap_validated();
2240                        let d: i32 = stack.pop_value().try_into().unwrap_validated();
2241
2242                        let src_addr = *store.modules[current_module_idx]
2243                            .mem_addrs
2244                            .get(src_idx)
2245                            .unwrap_validated();
2246                        let dst_addr = *store.modules[current_module_idx]
2247                            .mem_addrs
2248                            .get(dst_idx)
2249                            .unwrap_validated();
2250
2251                        let src_mem = &store.memories[src_addr];
2252                        let dest_mem = &store.memories[dst_addr];
2253
2254                        dest_mem
2255                            .mem
2256                            .copy(d as MemIdx, &src_mem.mem, s as MemIdx, n as MemIdx)?;
2257                        trace!("Instruction: memory.copy");
2258                    }
2259                    // See https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-memory-mathsf-memory-fill
2260                    MEMORY_FILL => {
2261                        //  mappings:
2262                        //      n => number of bytes to update
2263                        //      val => the value to set each byte to (must be < 256)
2264                        //      d => the pointer to the region to update
2265                        let mem_idx = wasm.read_u8().unwrap_validated() as usize;
2266                        let mem_addr = *store.modules[current_module_idx]
2267                            .mem_addrs
2268                            .get(mem_idx)
2269                            .unwrap_validated();
2270                        let mem = &mut store.memories[mem_addr];
2271                        let n: i32 = stack.pop_value().try_into().unwrap_validated();
2272                        let val: i32 = stack.pop_value().try_into().unwrap_validated();
2273
2274                        if !(0..=255).contains(&val) {
2275                            warn!("Value for memory.fill does not fit in a byte ({val})");
2276                        }
2277
2278                        let d: i32 = stack.pop_value().try_into().unwrap_validated();
2279
2280                        mem.mem.fill(d as usize, val as u8, n as usize)?;
2281
2282                        trace!("Instruction: memory.fill");
2283                    }
2284                    // https://webassembly.github.io/spec/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-table-mathsf-table-init-x-y
2285                    // https://webassembly.github.io/spec/core/binary/instructions.html#table-instructions
2286                    // in binary format it seems that elemidx is first ???????
2287                    // this is ONLY for passive elements
2288                    TABLE_INIT => {
2289                        let elem_idx = wasm.read_var_u32().unwrap_validated() as usize;
2290                        let table_idx = wasm.read_var_u32().unwrap_validated() as usize;
2291
2292                        let n: i32 = stack.pop_value().try_into().unwrap_validated(); // size
2293                        let s: i32 = stack.pop_value().try_into().unwrap_validated(); // offset
2294                        let d: i32 = stack.pop_value().try_into().unwrap_validated(); // dst
2295
2296                        table_init(
2297                            &store.modules,
2298                            &mut store.tables,
2299                            &store.elements,
2300                            current_module_idx,
2301                            elem_idx,
2302                            table_idx,
2303                            n,
2304                            s,
2305                            d,
2306                        )?;
2307                    }
2308                    ELEM_DROP => {
2309                        let elem_idx = wasm.read_var_u32().unwrap_validated() as usize;
2310
2311                        elem_drop(
2312                            &store.modules,
2313                            &mut store.elements,
2314                            current_module_idx,
2315                            elem_idx,
2316                        )?;
2317                    }
2318                    // https://webassembly.github.io/spec/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-table-mathsf-table-copy-x-y
2319                    TABLE_COPY => {
2320                        let table_x_idx = wasm.read_var_u32().unwrap_validated() as usize;
2321                        let table_y_idx = wasm.read_var_u32().unwrap_validated() as usize;
2322
2323                        let tab_x_elem_len = store.tables
2324                            [store.modules[current_module_idx].table_addrs[table_x_idx]]
2325                            .elem
2326                            .len();
2327                        let tab_y_elem_len = store.tables
2328                            [store.modules[current_module_idx].table_addrs[table_y_idx]]
2329                            .elem
2330                            .len();
2331
2332                        let n: u32 = stack.pop_value().try_into().unwrap_validated(); // size
2333                        let s: u32 = stack.pop_value().try_into().unwrap_validated(); // source
2334                        let d: u32 = stack.pop_value().try_into().unwrap_validated(); // destination
2335
2336                        let src_res = match s.checked_add(n) {
2337                            Some(res) => {
2338                                if res > tab_y_elem_len as u32 {
2339                                    return Err(TrapError::TableOrElementAccessOutOfBounds.into());
2340                                } else {
2341                                    res as usize
2342                                }
2343                            }
2344                            _ => return Err(TrapError::TableOrElementAccessOutOfBounds.into()),
2345                        };
2346
2347                        let dst_res = match d.checked_add(n) {
2348                            Some(res) => {
2349                                if res > tab_x_elem_len as u32 {
2350                                    return Err(TrapError::TableOrElementAccessOutOfBounds.into());
2351                                } else {
2352                                    res as usize
2353                                }
2354                            }
2355                            _ => return Err(TrapError::TableOrElementAccessOutOfBounds.into()),
2356                        };
2357
2358                        let dst = table_x_idx;
2359                        let src = table_y_idx;
2360
2361                        if table_x_idx == table_y_idx {
2362                            let table_addr = *store.modules[current_module_idx]
2363                                .table_addrs
2364                                .get(table_x_idx)
2365                                .unwrap_validated();
2366                            let table = &mut store.tables[table_addr];
2367                            table.elem.copy_within(s as usize..src_res, d as usize);
2368                        } else {
2369                            use core::cmp::Ordering::*;
2370                            let src_addr = *store.modules[current_module_idx]
2371                                .table_addrs
2372                                .get(src)
2373                                .unwrap_validated();
2374                            let dst_addr = *store.modules[current_module_idx]
2375                                .table_addrs
2376                                .get(dst)
2377                                .unwrap_validated();
2378
2379                            let (src_table, dst_table) = match dst_addr.cmp(&src_addr) {
2380                                Greater => {
2381                                    let (left, right) = store.tables.split_at_mut(dst_addr);
2382                                    (&left[src_addr], &mut right[0])
2383                                }
2384                                Less => {
2385                                    let (left, right) = store.tables.split_at_mut(src_addr);
2386                                    (&right[0], &mut left[dst_addr])
2387                                }
2388                                Equal => unreachable!(),
2389                            };
2390
2391                            dst_table.elem[d as usize..dst_res]
2392                                .copy_from_slice(&src_table.elem[s as usize..src_res]);
2393                        }
2394
2395                        trace!(
2396                            "Instruction: table.copy '{}' '{}' [{} {} {}] -> []",
2397                            table_x_idx,
2398                            table_y_idx,
2399                            d,
2400                            s,
2401                            n
2402                        );
2403                    }
2404                    TABLE_GROW => {
2405                        let table_idx = wasm.read_var_u32().unwrap_validated() as usize;
2406                        let table_addr = *store.modules[current_module_idx]
2407                            .table_addrs
2408                            .get(table_idx)
2409                            .unwrap_validated();
2410                        let tab = &mut store.tables[table_addr];
2411
2412                        let sz = tab.elem.len() as u32;
2413
2414                        let n: u32 = stack.pop_value().try_into().unwrap_validated();
2415                        let val: Ref = stack.pop_value().try_into().unwrap_validated();
2416
2417                        // TODO this instruction is non-deterministic w.r.t. spec, and can fail if the embedder wills it.
2418                        // for now we execute it always according to the following match expr.
2419                        // if the grow operation fails, err := Value::I32(2^32-1) is pushed to the stack per spec
2420                        match tab.grow(n, val) {
2421                            Ok(_) => {
2422                                stack.push_value(Value::I32(sz))?;
2423                            }
2424                            Err(_) => {
2425                                stack.push_value(Value::I32(u32::MAX))?;
2426                            }
2427                        }
2428                    }
2429                    TABLE_SIZE => {
2430                        let table_idx = wasm.read_var_u32().unwrap_validated() as usize;
2431                        let table_addr = *store.modules[current_module_idx]
2432                            .table_addrs
2433                            .get(table_idx)
2434                            .unwrap_validated();
2435                        let tab = &mut store.tables[table_addr];
2436
2437                        let sz = tab.elem.len() as u32;
2438
2439                        stack.push_value(Value::I32(sz))?;
2440
2441                        trace!("Instruction: table.size '{}' [] -> [{}]", table_idx, sz);
2442                    }
2443                    TABLE_FILL => {
2444                        let table_idx = wasm.read_var_u32().unwrap_validated() as usize;
2445                        let table_addr = *store.modules[current_module_idx]
2446                            .table_addrs
2447                            .get(table_idx)
2448                            .unwrap_validated();
2449                        let tab = &mut store.tables[table_addr];
2450
2451                        let len: u32 = stack.pop_value().try_into().unwrap_validated();
2452                        let val: Ref = stack.pop_value().try_into().unwrap_validated();
2453                        let dst: u32 = stack.pop_value().try_into().unwrap_validated();
2454
2455                        let end = (dst as usize)
2456                            .checked_add(len as usize)
2457                            .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
2458
2459                        tab.elem
2460                            .get_mut(dst as usize..end)
2461                            .ok_or(TrapError::TableOrElementAccessOutOfBounds)?
2462                            .fill(val);
2463
2464                        trace!(
2465                            "Instruction table.fill '{}' [{} {} {}] -> []",
2466                            table_idx,
2467                            dst,
2468                            val,
2469                            len
2470                        )
2471                    }
2472                    _ => unreachable!(),
2473                }
2474            }
2475
2476            I32_EXTEND8_S => {
2477                let mut v: u32 = stack.pop_value().try_into().unwrap_validated();
2478
2479                if v | 0xFF != 0xFF {
2480                    trace!("Number v ({}) not contained in 8 bits, truncating", v);
2481                    v &= 0xFF;
2482                }
2483
2484                let res = if v | 0x7F != 0x7F { v | 0xFFFFFF00 } else { v };
2485
2486                stack.push_value(res.into())?;
2487
2488                trace!("Instruction i32.extend8_s [{}] -> [{}]", v, res);
2489            }
2490            I32_EXTEND16_S => {
2491                let mut v: u32 = stack.pop_value().try_into().unwrap_validated();
2492
2493                if v | 0xFFFF != 0xFFFF {
2494                    trace!("Number v ({}) not contained in 16 bits, truncating", v);
2495                    v &= 0xFFFF;
2496                }
2497
2498                let res = if v | 0x7FFF != 0x7FFF {
2499                    v | 0xFFFF0000
2500                } else {
2501                    v
2502                };
2503
2504                stack.push_value(res.into())?;
2505
2506                trace!("Instruction i32.extend16_s [{}] -> [{}]", v, res);
2507            }
2508            I64_EXTEND8_S => {
2509                let mut v: u64 = stack.pop_value().try_into().unwrap_validated();
2510
2511                if v | 0xFF != 0xFF {
2512                    trace!("Number v ({}) not contained in 8 bits, truncating", v);
2513                    v &= 0xFF;
2514                }
2515
2516                let res = if v | 0x7F != 0x7F {
2517                    v | 0xFFFFFFFF_FFFFFF00
2518                } else {
2519                    v
2520                };
2521
2522                stack.push_value(res.into())?;
2523
2524                trace!("Instruction i64.extend8_s [{}] -> [{}]", v, res);
2525            }
2526            I64_EXTEND16_S => {
2527                let mut v: u64 = stack.pop_value().try_into().unwrap_validated();
2528
2529                if v | 0xFFFF != 0xFFFF {
2530                    trace!("Number v ({}) not contained in 16 bits, truncating", v);
2531                    v &= 0xFFFF;
2532                }
2533
2534                let res = if v | 0x7FFF != 0x7FFF {
2535                    v | 0xFFFFFFFF_FFFF0000
2536                } else {
2537                    v
2538                };
2539
2540                stack.push_value(res.into())?;
2541
2542                trace!("Instruction i64.extend16_s [{}] -> [{}]", v, res);
2543            }
2544            I64_EXTEND32_S => {
2545                let mut v: u64 = stack.pop_value().try_into().unwrap_validated();
2546
2547                if v | 0xFFFF_FFFF != 0xFFFF_FFFF {
2548                    trace!("Number v ({}) not contained in 32 bits, truncating", v);
2549                    v &= 0xFFFF_FFFF;
2550                }
2551
2552                let res = if v | 0x7FFF_FFFF != 0x7FFF_FFFF {
2553                    v | 0xFFFFFFFF_00000000
2554                } else {
2555                    v
2556                };
2557
2558                stack.push_value(res.into())?;
2559
2560                trace!("Instruction i64.extend32_s [{}] -> [{}]", v, res);
2561            }
2562            FD_EXTENSIONS => {
2563                // Should we call instruction hook here as well? Multibyte instruction
2564                let second_instr = wasm.read_var_u32().unwrap_validated();
2565
2566                use crate::core::reader::types::opcode::fd_extensions::*;
2567                match second_instr {
2568                    V128_LOAD => {
2569                        let memarg = MemArg::read(wasm).unwrap_validated();
2570                        let mem_addr = store.modules[current_module_idx]
2571                            .mem_addrs
2572                            .first()
2573                            .unwrap_validated();
2574                        let memory = &store.memories[*mem_addr];
2575
2576                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2577                        let idx = calculate_mem_address(&memarg, relative_address)?;
2578
2579                        let data: u128 = memory.mem.load(idx)?;
2580                        stack.push_value(data.to_le_bytes().into())?;
2581                    }
2582                    V128_STORE => {
2583                        let memarg = MemArg::read(wasm).unwrap_validated();
2584                        let mem_addr = store.modules[current_module_idx]
2585                            .mem_addrs
2586                            .first()
2587                            .unwrap_validated();
2588                        let memory = &store.memories[*mem_addr];
2589
2590                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2591                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2592                        let idx = calculate_mem_address(&memarg, relative_address)?;
2593
2594                        memory.mem.store(idx, u128::from_le_bytes(data))?;
2595                    }
2596
2597                    // v128.loadNxM_sx
2598                    V128_LOAD8X8_S => {
2599                        let memarg = MemArg::read(wasm).unwrap_validated();
2600                        let mem_addr = store.modules[current_module_idx]
2601                            .mem_addrs
2602                            .first()
2603                            .unwrap_validated();
2604                        let memory = &store.memories[*mem_addr];
2605
2606                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2607                        let idx = calculate_mem_address(&memarg, relative_address)?;
2608
2609                        let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; // v128 load always loads half of a v128
2610
2611                        // Special case where we have only half of a v128. To convert it to lanes via `to_lanes`, pad the data with zeros
2612                        let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
2613                        let half_lanes: [i8; 8] =
2614                            to_lanes::<1, 16, i8>(data)[..8].try_into().unwrap();
2615
2616                        let extended_lanes = half_lanes.map(|lane| lane as i16);
2617
2618                        stack.push_value(Value::V128(from_lanes(extended_lanes)))?;
2619                    }
2620                    V128_LOAD8X8_U => {
2621                        let memarg = MemArg::read(wasm).unwrap_validated();
2622                        let mem_addr = store.modules[current_module_idx]
2623                            .mem_addrs
2624                            .first()
2625                            .unwrap_validated();
2626                        let memory = &store.memories[*mem_addr];
2627
2628                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2629                        let idx = calculate_mem_address(&memarg, relative_address)?;
2630
2631                        let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; // v128 load always loads half of a v128
2632
2633                        // Special case where we have only half of a v128. To convert it to lanes via `to_lanes`, pad the data with zeros
2634                        let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
2635                        let half_lanes: [u8; 8] =
2636                            to_lanes::<1, 16, u8>(data)[..8].try_into().unwrap();
2637
2638                        let extended_lanes = half_lanes.map(|lane| lane as u16);
2639
2640                        stack.push_value(Value::V128(from_lanes(extended_lanes)))?;
2641                    }
2642                    V128_LOAD16X4_S => {
2643                        let memarg = MemArg::read(wasm).unwrap_validated();
2644                        let mem_addr = store.modules[current_module_idx]
2645                            .mem_addrs
2646                            .first()
2647                            .unwrap_validated();
2648                        let memory = &store.memories[*mem_addr];
2649
2650                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2651                        let idx = calculate_mem_address(&memarg, relative_address)?;
2652
2653                        let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; // v128 load always loads half of a v128
2654
2655                        // Special case where we have only half of a v128. To convert it to lanes via `to_lanes`, pad the data with zeros
2656                        let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
2657                        let half_lanes: [i16; 4] =
2658                            to_lanes::<2, 8, i16>(data)[..4].try_into().unwrap();
2659
2660                        let extended_lanes = half_lanes.map(|lane| lane as i32);
2661
2662                        stack.push_value(Value::V128(from_lanes(extended_lanes)))?;
2663                    }
2664                    V128_LOAD16X4_U => {
2665                        let memarg = MemArg::read(wasm).unwrap_validated();
2666                        let mem_addr = store.modules[current_module_idx]
2667                            .mem_addrs
2668                            .first()
2669                            .unwrap_validated();
2670                        let memory = &store.memories[*mem_addr];
2671
2672                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2673                        let idx = calculate_mem_address(&memarg, relative_address)?;
2674
2675                        let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; // v128 load always loads half of a v128
2676
2677                        // Special case where we have only half of a v128. To convert it to lanes via `to_lanes`, pad the data with zeros
2678                        let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
2679                        let half_lanes: [u16; 4] =
2680                            to_lanes::<2, 8, u16>(data)[..4].try_into().unwrap();
2681
2682                        let extended_lanes = half_lanes.map(|lane| lane as u32);
2683
2684                        stack.push_value(Value::V128(from_lanes(extended_lanes)))?;
2685                    }
2686                    V128_LOAD32X2_S => {
2687                        let memarg = MemArg::read(wasm).unwrap_validated();
2688                        let mem_addr = store.modules[current_module_idx]
2689                            .mem_addrs
2690                            .first()
2691                            .unwrap_validated();
2692                        let memory = &store.memories[*mem_addr];
2693
2694                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2695                        let idx = calculate_mem_address(&memarg, relative_address)?;
2696
2697                        let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; // v128 load always loads half of a v128
2698
2699                        // Special case where we have only half of a v128. To convert it to lanes via `to_lanes`, pad the data with zeros
2700                        let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
2701                        let half_lanes: [i32; 2] =
2702                            to_lanes::<4, 4, i32>(data)[..2].try_into().unwrap();
2703
2704                        let extended_lanes = half_lanes.map(|lane| lane as i64);
2705
2706                        stack.push_value(Value::V128(from_lanes(extended_lanes)))?;
2707                    }
2708                    V128_LOAD32X2_U => {
2709                        let memarg = MemArg::read(wasm).unwrap_validated();
2710                        let mem_addr = store.modules[current_module_idx]
2711                            .mem_addrs
2712                            .first()
2713                            .unwrap_validated();
2714                        let memory = &store.memories[*mem_addr];
2715
2716                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2717                        let idx = calculate_mem_address(&memarg, relative_address)?;
2718
2719                        let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; // v128 load always loads half of a v128
2720
2721                        // Special case where we have only half of a v128. To convert it to lanes via `to_lanes`, pad the data with zeros
2722                        let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
2723                        let half_lanes: [u32; 2] =
2724                            to_lanes::<4, 4, u32>(data)[..2].try_into().unwrap();
2725
2726                        let extended_lanes = half_lanes.map(|lane| lane as u64);
2727
2728                        stack.push_value(Value::V128(from_lanes(extended_lanes)))?;
2729                    }
2730
2731                    // v128.loadN_splat
2732                    V128_LOAD8_SPLAT => {
2733                        let memarg = MemArg::read(wasm).unwrap_validated();
2734                        let mem_addr = store.modules[current_module_idx]
2735                            .mem_addrs
2736                            .first()
2737                            .unwrap_validated();
2738                        let memory = &store.memories[*mem_addr];
2739                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2740                        let idx = calculate_mem_address(&memarg, relative_address)?;
2741
2742                        let lane = memory.mem.load::<1, u8>(idx)?;
2743                        stack.push_value(Value::V128(from_lanes([lane; 16])))?;
2744                    }
2745                    V128_LOAD16_SPLAT => {
2746                        let memarg = MemArg::read(wasm).unwrap_validated();
2747                        let mem_addr = store.modules[current_module_idx]
2748                            .mem_addrs
2749                            .first()
2750                            .unwrap_validated();
2751                        let memory = &store.memories[*mem_addr];
2752                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2753                        let idx = calculate_mem_address(&memarg, relative_address)?;
2754
2755                        let lane = memory.mem.load::<2, u16>(idx)?;
2756                        stack.push_value(Value::V128(from_lanes([lane; 8])))?;
2757                    }
2758                    V128_LOAD32_SPLAT => {
2759                        let memarg = MemArg::read(wasm).unwrap_validated();
2760                        let mem_addr = store.modules[current_module_idx]
2761                            .mem_addrs
2762                            .first()
2763                            .unwrap_validated();
2764                        let memory = &store.memories[*mem_addr];
2765                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2766                        let idx = calculate_mem_address(&memarg, relative_address)?;
2767
2768                        let lane = memory.mem.load::<4, u32>(idx)?;
2769                        stack.push_value(Value::V128(from_lanes([lane; 4])))?;
2770                    }
2771                    V128_LOAD64_SPLAT => {
2772                        let memarg = MemArg::read(wasm).unwrap_validated();
2773                        let mem_addr = store.modules[current_module_idx]
2774                            .mem_addrs
2775                            .first()
2776                            .unwrap_validated();
2777                        let memory = &store.memories[*mem_addr];
2778                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2779                        let idx = calculate_mem_address(&memarg, relative_address)?;
2780
2781                        let lane = memory.mem.load::<8, u64>(idx)?;
2782                        stack.push_value(Value::V128(from_lanes([lane; 2])))?;
2783                    }
2784
2785                    // v128.loadN_zero
2786                    V128_LOAD32_ZERO => {
2787                        let memarg = MemArg::read(wasm).unwrap_validated();
2788                        let mem_addr = store.modules[current_module_idx]
2789                            .mem_addrs
2790                            .first()
2791                            .unwrap_validated();
2792                        let memory = &store.memories[*mem_addr];
2793
2794                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2795                        let idx = calculate_mem_address(&memarg, relative_address)?;
2796
2797                        let data = memory.mem.load::<4, u32>(idx)? as u128;
2798                        stack.push_value(Value::V128(data.to_le_bytes()))?;
2799                    }
2800                    V128_LOAD64_ZERO => {
2801                        let memarg = MemArg::read(wasm).unwrap_validated();
2802                        let mem_addr = store.modules[current_module_idx]
2803                            .mem_addrs
2804                            .first()
2805                            .unwrap_validated();
2806                        let memory = &store.memories[*mem_addr];
2807
2808                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2809                        let idx = calculate_mem_address(&memarg, relative_address)?;
2810
2811                        let data = memory.mem.load::<8, u64>(idx)? as u128;
2812                        stack.push_value(Value::V128(data.to_le_bytes()))?;
2813                    }
2814
2815                    // v128.loadN_lane
2816                    V128_LOAD8_LANE => {
2817                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2818                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2819                        let memarg = MemArg::read(wasm).unwrap_validated();
2820                        let mem_addr = store.modules[current_module_idx]
2821                            .mem_addrs
2822                            .first()
2823                            .unwrap_validated();
2824                        let memory = &store.memories[*mem_addr];
2825                        let idx = calculate_mem_address(&memarg, relative_address)?;
2826                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
2827                        let mut lanes: [u8; 16] = to_lanes(data);
2828                        *lanes.get_mut(lane_idx).unwrap_validated() =
2829                            memory.mem.load::<1, u8>(idx)?;
2830                        stack.push_value(Value::V128(from_lanes(lanes)))?;
2831                    }
2832
2833                    V128_LOAD16_LANE => {
2834                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2835                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2836                        let memarg = MemArg::read(wasm).unwrap_validated();
2837                        let mem_addr = store.modules[current_module_idx]
2838                            .mem_addrs
2839                            .first()
2840                            .unwrap_validated();
2841                        let memory = &store.memories[*mem_addr];
2842                        let idx = calculate_mem_address(&memarg, relative_address)?;
2843                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
2844                        let mut lanes: [u16; 8] = to_lanes(data);
2845                        *lanes.get_mut(lane_idx).unwrap_validated() =
2846                            memory.mem.load::<2, u16>(idx)?;
2847                        stack.push_value(Value::V128(from_lanes(lanes)))?;
2848                    }
2849                    V128_LOAD32_LANE => {
2850                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2851                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2852                        let memarg = MemArg::read(wasm).unwrap_validated();
2853                        let mem_addr = store.modules[current_module_idx]
2854                            .mem_addrs
2855                            .first()
2856                            .unwrap_validated();
2857                        let memory = &store.memories[*mem_addr];
2858                        let idx = calculate_mem_address(&memarg, relative_address)?;
2859                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
2860                        let mut lanes: [u32; 4] = to_lanes(data);
2861                        *lanes.get_mut(lane_idx).unwrap_validated() =
2862                            memory.mem.load::<4, u32>(idx)?;
2863                        stack.push_value(Value::V128(from_lanes(lanes)))?;
2864                    }
2865                    V128_LOAD64_LANE => {
2866                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2867                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2868                        let memarg = MemArg::read(wasm).unwrap_validated();
2869                        let mem_addr = store.modules[current_module_idx]
2870                            .mem_addrs
2871                            .first()
2872                            .unwrap_validated();
2873                        let memory = &store.memories[*mem_addr];
2874                        let idx = calculate_mem_address(&memarg, relative_address)?;
2875                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
2876                        let mut lanes: [u64; 2] = to_lanes(data);
2877                        *lanes.get_mut(lane_idx).unwrap_validated() =
2878                            memory.mem.load::<8, u64>(idx)?;
2879                        stack.push_value(Value::V128(from_lanes(lanes)))?;
2880                    }
2881
2882                    // v128.storeN_lane
2883                    V128_STORE8_LANE => {
2884                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2885                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2886                        let memarg = MemArg::read(wasm).unwrap_validated();
2887                        let mem_addr = store.modules[current_module_idx]
2888                            .mem_addrs
2889                            .first()
2890                            .unwrap_validated();
2891                        let memory = &store.memories[*mem_addr];
2892                        let idx = calculate_mem_address(&memarg, relative_address)?;
2893                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
2894
2895                        let lane = *to_lanes::<1, 16, u8>(data).get(lane_idx).unwrap_validated();
2896
2897                        memory.mem.store::<1, u8>(idx, lane)?;
2898                    }
2899                    V128_STORE16_LANE => {
2900                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2901                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2902                        let memarg = MemArg::read(wasm).unwrap_validated();
2903                        let mem_addr = store.modules[current_module_idx]
2904                            .mem_addrs
2905                            .first()
2906                            .unwrap_validated();
2907                        let memory = &store.memories[*mem_addr];
2908                        let idx = calculate_mem_address(&memarg, relative_address)?;
2909                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
2910
2911                        let lane = *to_lanes::<2, 8, u16>(data).get(lane_idx).unwrap_validated();
2912
2913                        memory.mem.store::<2, u16>(idx, lane)?;
2914                    }
2915                    V128_STORE32_LANE => {
2916                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2917                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2918                        let memarg = MemArg::read(wasm).unwrap_validated();
2919                        let mem_addr = store.modules[current_module_idx]
2920                            .mem_addrs
2921                            .first()
2922                            .unwrap_validated();
2923                        let memory = &store.memories[*mem_addr];
2924                        let idx = calculate_mem_address(&memarg, relative_address)?;
2925                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
2926
2927                        let lane = *to_lanes::<4, 4, u32>(data).get(lane_idx).unwrap_validated();
2928
2929                        memory.mem.store::<4, u32>(idx, lane)?;
2930                    }
2931                    V128_STORE64_LANE => {
2932                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2933                        let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
2934                        let memarg = MemArg::read(wasm).unwrap_validated();
2935                        let mem_addr = store.modules[current_module_idx]
2936                            .mem_addrs
2937                            .first()
2938                            .unwrap_validated();
2939                        let memory = &store.memories[*mem_addr];
2940                        let idx = calculate_mem_address(&memarg, relative_address)?;
2941                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
2942
2943                        let lane = *to_lanes::<8, 2, u64>(data).get(lane_idx).unwrap_validated();
2944
2945                        memory.mem.store::<8, u64>(idx, lane)?;
2946                    }
2947
2948                    V128_CONST => {
2949                        let mut data = [0; 16];
2950                        for byte_ref in &mut data {
2951                            *byte_ref = wasm.read_u8().unwrap_validated();
2952                        }
2953
2954                        stack.push_value(Value::V128(data))?;
2955                    }
2956
2957                    // vvunop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vvunop>
2958                    V128_NOT => {
2959                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2960                        stack.push_value(Value::V128(data.map(|byte| !byte)))?;
2961                    }
2962
2963                    // vvbinop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vvbinop>
2964                    V128_AND => {
2965                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2966                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2967                        let result = array::from_fn(|i| data1[i] & data2[i]);
2968                        stack.push_value(Value::V128(result))?;
2969                    }
2970                    V128_ANDNOT => {
2971                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2972                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2973                        let result = array::from_fn(|i| data1[i] & !data2[i]);
2974                        stack.push_value(Value::V128(result))?;
2975                    }
2976                    V128_OR => {
2977                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2978                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2979                        let result = array::from_fn(|i| data1[i] | data2[i]);
2980                        stack.push_value(Value::V128(result))?;
2981                    }
2982                    V128_XOR => {
2983                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2984                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2985                        let result = array::from_fn(|i| data1[i] ^ data2[i]);
2986                        stack.push_value(Value::V128(result))?;
2987                    }
2988
2989                    // vvternop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vvternop>
2990                    V128_BITSELECT => {
2991                        let data3: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2992                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2993                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
2994                        let result =
2995                            array::from_fn(|i| (data1[i] & data3[i]) | (data2[i] & !data3[i]));
2996                        stack.push_value(Value::V128(result))?;
2997                    }
2998
2999                    // vvtestop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vvtestop>
3000                    V128_ANY_TRUE => {
3001                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3002                        let any_true = data.into_iter().any(|byte| byte > 0);
3003                        stack.push_value(Value::I32(any_true as u32))?;
3004                    }
3005
3006                    I8X16_SWIZZLE => {
3007                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3008                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3009                        let result =
3010                            array::from_fn(|i| *data1.get(data2[i] as usize).unwrap_or(&0));
3011                        stack.push_value(Value::V128(result))?;
3012                    }
3013
3014                    I8X16_SHUFFLE => {
3015                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3016                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3017
3018                        let lane_selector_indices: [u8; 16] =
3019                            array::from_fn(|_| wasm.read_u8().unwrap_validated());
3020
3021                        let result = lane_selector_indices.map(|i| {
3022                            *data1
3023                                .get(i as usize)
3024                                .or_else(|| data2.get(i as usize - 16))
3025                                .unwrap_validated()
3026                        });
3027
3028                        stack.push_value(Value::V128(result))?;
3029                    }
3030
3031                    // shape.splat
3032                    I8X16_SPLAT => {
3033                        let value: u32 = stack.pop_value().try_into().unwrap_validated();
3034                        let lane = value as u8;
3035                        let data = from_lanes([lane; 16]);
3036                        stack.push_value(Value::V128(data))?;
3037                    }
3038                    I16X8_SPLAT => {
3039                        let value: u32 = stack.pop_value().try_into().unwrap_validated();
3040                        let lane = value as u16;
3041                        let data = from_lanes([lane; 8]);
3042                        stack.push_value(Value::V128(data))?;
3043                    }
3044                    I32X4_SPLAT => {
3045                        let lane: u32 = stack.pop_value().try_into().unwrap_validated();
3046                        let data = from_lanes([lane; 4]);
3047                        stack.push_value(Value::V128(data))?;
3048                    }
3049                    I64X2_SPLAT => {
3050                        let lane: u64 = stack.pop_value().try_into().unwrap_validated();
3051                        let data = from_lanes([lane; 2]);
3052                        stack.push_value(Value::V128(data))?;
3053                    }
3054                    F32X4_SPLAT => {
3055                        let lane: F32 = stack.pop_value().try_into().unwrap_validated();
3056                        let data = from_lanes([lane; 4]);
3057                        stack.push_value(Value::V128(data))?;
3058                    }
3059                    F64X2_SPLAT => {
3060                        let lane: F64 = stack.pop_value().try_into().unwrap_validated();
3061                        let data = from_lanes([lane; 2]);
3062                        stack.push_value(Value::V128(data))?;
3063                    }
3064
3065                    // shape.extract_lane
3066                    I8X16_EXTRACT_LANE_S => {
3067                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3068                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3069                        let lanes: [i8; 16] = to_lanes(data);
3070                        let lane = *lanes.get(lane_idx).unwrap_validated();
3071                        stack.push_value(Value::I32(lane as u32))?;
3072                    }
3073                    I8X16_EXTRACT_LANE_U => {
3074                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3075                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3076                        let lanes: [u8; 16] = to_lanes(data);
3077                        let lane = *lanes.get(lane_idx).unwrap_validated();
3078                        stack.push_value(Value::I32(lane as u32))?;
3079                    }
3080                    I16X8_EXTRACT_LANE_S => {
3081                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3082                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3083                        let lanes: [i16; 8] = to_lanes(data);
3084                        let lane = *lanes.get(lane_idx).unwrap_validated();
3085                        stack.push_value(Value::I32(lane as u32))?;
3086                    }
3087                    I16X8_EXTRACT_LANE_U => {
3088                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3089                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3090                        let lanes: [u16; 8] = to_lanes(data);
3091                        let lane = *lanes.get(lane_idx).unwrap_validated();
3092                        stack.push_value(Value::I32(lane as u32))?;
3093                    }
3094                    I32X4_EXTRACT_LANE => {
3095                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3096                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3097                        let lanes: [u32; 4] = to_lanes(data);
3098                        let lane = *lanes.get(lane_idx).unwrap_validated();
3099                        stack.push_value(Value::I32(lane))?;
3100                    }
3101                    I64X2_EXTRACT_LANE => {
3102                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3103                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3104                        let lanes: [u64; 2] = to_lanes(data);
3105                        let lane = *lanes.get(lane_idx).unwrap_validated();
3106                        stack.push_value(Value::I64(lane))?;
3107                    }
3108                    F32X4_EXTRACT_LANE => {
3109                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3110                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3111                        let lanes: [F32; 4] = to_lanes(data);
3112                        let lane = *lanes.get(lane_idx).unwrap_validated();
3113                        stack.push_value(Value::F32(lane))?;
3114                    }
3115                    F64X2_EXTRACT_LANE => {
3116                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3117                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3118                        let lanes: [F64; 2] = to_lanes(data);
3119                        let lane = *lanes.get(lane_idx).unwrap_validated();
3120                        stack.push_value(Value::F64(lane))?;
3121                    }
3122
3123                    // shape.replace_lane
3124                    I8X16_REPLACE_LANE => {
3125                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3126                        let value: u32 = stack.pop_value().try_into().unwrap_validated();
3127                        let new_lane = value as u8;
3128                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3129                        let mut lanes: [u8; 16] = to_lanes(data);
3130                        *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
3131                        stack.push_value(Value::V128(from_lanes(lanes)))?;
3132                    }
3133                    I16X8_REPLACE_LANE => {
3134                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3135                        let value: u32 = stack.pop_value().try_into().unwrap_validated();
3136                        let new_lane = value as u16;
3137                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3138                        let mut lanes: [u16; 8] = to_lanes(data);
3139                        *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
3140                        stack.push_value(Value::V128(from_lanes(lanes)))?;
3141                    }
3142                    I32X4_REPLACE_LANE => {
3143                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3144                        let new_lane: u32 = stack.pop_value().try_into().unwrap_validated();
3145                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3146                        let mut lanes: [u32; 4] = to_lanes(data);
3147                        *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
3148                        stack.push_value(Value::V128(from_lanes(lanes)))?;
3149                    }
3150                    I64X2_REPLACE_LANE => {
3151                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3152                        let new_lane: u64 = stack.pop_value().try_into().unwrap_validated();
3153                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3154                        let mut lanes: [u64; 2] = to_lanes(data);
3155                        *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
3156                        stack.push_value(Value::V128(from_lanes(lanes)))?;
3157                    }
3158                    F32X4_REPLACE_LANE => {
3159                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3160                        let new_lane: F32 = stack.pop_value().try_into().unwrap_validated();
3161                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3162                        let mut lanes: [F32; 4] = to_lanes(data);
3163                        *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
3164                        stack.push_value(Value::V128(from_lanes(lanes)))?;
3165                    }
3166                    F64X2_REPLACE_LANE => {
3167                        let lane_idx = wasm.read_u8().unwrap_validated() as usize;
3168                        let new_lane: F64 = stack.pop_value().try_into().unwrap_validated();
3169                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3170                        let mut lanes: [F64; 2] = to_lanes(data);
3171                        *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
3172                        stack.push_value(Value::V128(from_lanes(lanes)))?;
3173                    }
3174
3175                    // Group vunop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vunop>
3176                    // viunop
3177                    I8X16_ABS => {
3178                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3179                        let lanes: [i8; 16] = to_lanes(data);
3180                        let result: [i8; 16] = lanes.map(i8::wrapping_abs);
3181                        stack.push_value(Value::V128(from_lanes(result)))?;
3182                    }
3183                    I16X8_ABS => {
3184                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3185                        let lanes: [i16; 8] = to_lanes(data);
3186                        let result: [i16; 8] = lanes.map(i16::wrapping_abs);
3187                        stack.push_value(Value::V128(from_lanes(result)))?;
3188                    }
3189                    I32X4_ABS => {
3190                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3191                        let lanes: [i32; 4] = to_lanes(data);
3192                        let result: [i32; 4] = lanes.map(i32::wrapping_abs);
3193                        stack.push_value(Value::V128(from_lanes(result)))?;
3194                    }
3195                    I64X2_ABS => {
3196                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3197                        let lanes: [i64; 2] = to_lanes(data);
3198                        let result: [i64; 2] = lanes.map(i64::wrapping_abs);
3199                        stack.push_value(Value::V128(from_lanes(result)))?;
3200                    }
3201                    I8X16_NEG => {
3202                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3203                        let lanes: [i8; 16] = to_lanes(data);
3204                        let result: [i8; 16] = lanes.map(i8::wrapping_neg);
3205                        stack.push_value(Value::V128(from_lanes(result)))?;
3206                    }
3207                    I16X8_NEG => {
3208                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3209                        let lanes: [i16; 8] = to_lanes(data);
3210                        let result: [i16; 8] = lanes.map(i16::wrapping_neg);
3211                        stack.push_value(Value::V128(from_lanes(result)))?;
3212                    }
3213                    I32X4_NEG => {
3214                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3215                        let lanes: [i32; 4] = to_lanes(data);
3216                        let result: [i32; 4] = lanes.map(i32::wrapping_neg);
3217                        stack.push_value(Value::V128(from_lanes(result)))?;
3218                    }
3219                    I64X2_NEG => {
3220                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3221                        let lanes: [i64; 2] = to_lanes(data);
3222                        let result: [i64; 2] = lanes.map(i64::wrapping_neg);
3223                        stack.push_value(Value::V128(from_lanes(result)))?;
3224                    }
3225                    // vfunop
3226                    F32X4_ABS => {
3227                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3228                        let lanes: [F32; 4] = to_lanes(data);
3229                        let result: [F32; 4] = lanes.map(|lane| lane.abs());
3230                        stack.push_value(Value::V128(from_lanes(result)))?;
3231                    }
3232                    F64X2_ABS => {
3233                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3234                        let lanes: [F64; 2] = to_lanes(data);
3235                        let result: [F64; 2] = lanes.map(|lane| lane.abs());
3236                        stack.push_value(Value::V128(from_lanes(result)))?;
3237                    }
3238                    F32X4_NEG => {
3239                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3240                        let lanes: [F32; 4] = to_lanes(data);
3241                        let result: [F32; 4] = lanes.map(|lane| lane.neg());
3242                        stack.push_value(Value::V128(from_lanes(result)))?;
3243                    }
3244                    F64X2_NEG => {
3245                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3246                        let lanes: [F64; 2] = to_lanes(data);
3247                        let result: [F64; 2] = lanes.map(|lane| lane.neg());
3248                        stack.push_value(Value::V128(from_lanes(result)))?;
3249                    }
3250                    F32X4_SQRT => {
3251                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3252                        let lanes: [F32; 4] = to_lanes(data);
3253                        let result: [F32; 4] = lanes.map(|lane| lane.sqrt());
3254                        stack.push_value(Value::V128(from_lanes(result)))?;
3255                    }
3256                    F64X2_SQRT => {
3257                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3258                        let lanes: [F64; 2] = to_lanes(data);
3259                        let result: [F64; 2] = lanes.map(|lane| lane.sqrt());
3260                        stack.push_value(Value::V128(from_lanes(result)))?;
3261                    }
3262                    F32X4_CEIL => {
3263                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3264                        let lanes: [F32; 4] = to_lanes(data);
3265                        let result: [F32; 4] = lanes.map(|lane| lane.ceil());
3266                        stack.push_value(Value::V128(from_lanes(result)))?;
3267                    }
3268                    F64X2_CEIL => {
3269                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3270                        let lanes: [F64; 2] = to_lanes(data);
3271                        let result: [F64; 2] = lanes.map(|lane| lane.ceil());
3272                        stack.push_value(Value::V128(from_lanes(result)))?;
3273                    }
3274                    F32X4_FLOOR => {
3275                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3276                        let lanes: [F32; 4] = to_lanes(data);
3277                        let result: [F32; 4] = lanes.map(|lane| lane.floor());
3278                        stack.push_value(Value::V128(from_lanes(result)))?;
3279                    }
3280                    F64X2_FLOOR => {
3281                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3282                        let lanes: [F64; 2] = to_lanes(data);
3283                        let result: [F64; 2] = lanes.map(|lane| lane.floor());
3284                        stack.push_value(Value::V128(from_lanes(result)))?;
3285                    }
3286                    F32X4_TRUNC => {
3287                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3288                        let lanes: [F32; 4] = to_lanes(data);
3289                        let result: [F32; 4] = lanes.map(|lane| lane.trunc());
3290                        stack.push_value(Value::V128(from_lanes(result)))?;
3291                    }
3292                    F64X2_TRUNC => {
3293                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3294                        let lanes: [F64; 2] = to_lanes(data);
3295                        let result: [F64; 2] = lanes.map(|lane| lane.trunc());
3296                        stack.push_value(Value::V128(from_lanes(result)))?;
3297                    }
3298                    F32X4_NEAREST => {
3299                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3300                        let lanes: [F32; 4] = to_lanes(data);
3301                        let result: [F32; 4] = lanes.map(|lane| lane.nearest());
3302                        stack.push_value(Value::V128(from_lanes(result)))?;
3303                    }
3304                    F64X2_NEAREST => {
3305                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3306                        let lanes: [F64; 2] = to_lanes(data);
3307                        let result: [F64; 2] = lanes.map(|lane| lane.nearest());
3308                        stack.push_value(Value::V128(from_lanes(result)))?;
3309                    }
3310                    // others
3311                    I8X16_POPCNT => {
3312                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3313                        let lanes: [u8; 16] = to_lanes(data);
3314                        let result: [u8; 16] = lanes.map(|lane| lane.count_ones() as u8);
3315                        stack.push_value(Value::V128(from_lanes(result)))?;
3316                    }
3317
3318                    // Group vbinop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vbinop>
3319                    // vibinop
3320                    I8X16_ADD => {
3321                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3322                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3323                        let lanes2: [u8; 16] = to_lanes(data2);
3324                        let lanes1: [u8; 16] = to_lanes(data1);
3325                        let result: [u8; 16] =
3326                            array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
3327                        stack.push_value(Value::V128(from_lanes(result)))?;
3328                    }
3329                    I16X8_ADD => {
3330                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3331                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3332                        let lanes2: [u16; 8] = to_lanes(data2);
3333                        let lanes1: [u16; 8] = to_lanes(data1);
3334                        let result: [u16; 8] =
3335                            array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
3336                        stack.push_value(Value::V128(from_lanes(result)))?;
3337                    }
3338                    I32X4_ADD => {
3339                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3340                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3341                        let lanes2: [u32; 4] = to_lanes(data2);
3342                        let lanes1: [u32; 4] = to_lanes(data1);
3343                        let result: [u32; 4] =
3344                            array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
3345                        stack.push_value(Value::V128(from_lanes(result)))?;
3346                    }
3347                    I64X2_ADD => {
3348                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3349                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3350                        let lanes2: [u64; 2] = to_lanes(data2);
3351                        let lanes1: [u64; 2] = to_lanes(data1);
3352                        let result: [u64; 2] =
3353                            array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
3354                        stack.push_value(Value::V128(from_lanes(result)))?;
3355                    }
3356                    I8X16_SUB => {
3357                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3358                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3359                        let lanes2: [u8; 16] = to_lanes(data2);
3360                        let lanes1: [u8; 16] = to_lanes(data1);
3361                        let result: [u8; 16] =
3362                            array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
3363                        stack.push_value(Value::V128(from_lanes(result)))?;
3364                    }
3365                    I16X8_SUB => {
3366                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3367                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3368                        let lanes2: [u16; 8] = to_lanes(data2);
3369                        let lanes1: [u16; 8] = to_lanes(data1);
3370                        let result: [u16; 8] =
3371                            array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
3372                        stack.push_value(Value::V128(from_lanes(result)))?;
3373                    }
3374                    I32X4_SUB => {
3375                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3376                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3377                        let lanes2: [u32; 4] = to_lanes(data2);
3378                        let lanes1: [u32; 4] = to_lanes(data1);
3379                        let result: [u32; 4] =
3380                            array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
3381                        stack.push_value(Value::V128(from_lanes(result)))?;
3382                    }
3383                    I64X2_SUB => {
3384                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3385                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3386                        let lanes2: [u64; 2] = to_lanes(data2);
3387                        let lanes1: [u64; 2] = to_lanes(data1);
3388                        let result: [u64; 2] =
3389                            array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
3390                        stack.push_value(Value::V128(from_lanes(result)))?;
3391                    }
3392                    // vfbinop
3393                    F32X4_ADD => {
3394                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3395                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3396                        let lanes2: [F32; 4] = to_lanes(data2);
3397                        let lanes1: [F32; 4] = to_lanes(data1);
3398                        let result: [F32; 4] = array::from_fn(|i| lanes1[i].add(lanes2[i]));
3399                        stack.push_value(Value::V128(from_lanes(result)))?;
3400                    }
3401                    F64X2_ADD => {
3402                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3403                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3404                        let lanes2: [F64; 2] = to_lanes(data2);
3405                        let lanes1: [F64; 2] = to_lanes(data1);
3406                        let result: [F64; 2] = array::from_fn(|i| lanes1[i].add(lanes2[i]));
3407                        stack.push_value(Value::V128(from_lanes(result)))?;
3408                    }
3409                    F32X4_SUB => {
3410                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3411                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3412                        let lanes2: [F32; 4] = to_lanes(data2);
3413                        let lanes1: [F32; 4] = to_lanes(data1);
3414                        let result: [F32; 4] = array::from_fn(|i| lanes1[i].sub(lanes2[i]));
3415                        stack.push_value(Value::V128(from_lanes(result)))?;
3416                    }
3417                    F64X2_SUB => {
3418                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3419                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3420                        let lanes2: [F64; 2] = to_lanes(data2);
3421                        let lanes1: [F64; 2] = to_lanes(data1);
3422                        let result: [F64; 2] = array::from_fn(|i| lanes1[i].sub(lanes2[i]));
3423                        stack.push_value(Value::V128(from_lanes(result)))?;
3424                    }
3425                    F32X4_MUL => {
3426                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3427                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3428                        let lanes2: [F32; 4] = to_lanes(data2);
3429                        let lanes1: [F32; 4] = to_lanes(data1);
3430                        let result: [F32; 4] = array::from_fn(|i| lanes1[i].mul(lanes2[i]));
3431                        stack.push_value(Value::V128(from_lanes(result)))?;
3432                    }
3433                    F64X2_MUL => {
3434                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3435                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3436                        let lanes2: [F64; 2] = to_lanes(data2);
3437                        let lanes1: [F64; 2] = to_lanes(data1);
3438                        let result: [F64; 2] = array::from_fn(|i| lanes1[i].mul(lanes2[i]));
3439                        stack.push_value(Value::V128(from_lanes(result)))?;
3440                    }
3441                    F32X4_DIV => {
3442                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3443                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3444                        let lanes2: [F32; 4] = to_lanes(data2);
3445                        let lanes1: [F32; 4] = to_lanes(data1);
3446                        let result: [F32; 4] = array::from_fn(|i| lanes1[i].div(lanes2[i]));
3447                        stack.push_value(Value::V128(from_lanes(result)))?;
3448                    }
3449                    F64X2_DIV => {
3450                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3451                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3452                        let lanes2: [F64; 2] = to_lanes(data2);
3453                        let lanes1: [F64; 2] = to_lanes(data1);
3454                        let result: [F64; 2] = array::from_fn(|i| lanes1[i].div(lanes2[i]));
3455                        stack.push_value(Value::V128(from_lanes(result)))?;
3456                    }
3457                    F32X4_MIN => {
3458                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3459                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3460                        let lanes2: [F32; 4] = to_lanes(data2);
3461                        let lanes1: [F32; 4] = to_lanes(data1);
3462                        let result: [F32; 4] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
3463                        stack.push_value(Value::V128(from_lanes(result)))?;
3464                    }
3465                    F64X2_MIN => {
3466                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3467                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3468                        let lanes2: [F64; 2] = to_lanes(data2);
3469                        let lanes1: [F64; 2] = to_lanes(data1);
3470                        let result: [F64; 2] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
3471                        stack.push_value(Value::V128(from_lanes(result)))?;
3472                    }
3473                    F32X4_MAX => {
3474                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3475                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3476                        let lanes2: [F32; 4] = to_lanes(data2);
3477                        let lanes1: [F32; 4] = to_lanes(data1);
3478                        let result: [F32; 4] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
3479                        stack.push_value(Value::V128(from_lanes(result)))?;
3480                    }
3481                    F64X2_MAX => {
3482                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3483                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3484                        let lanes2: [F64; 2] = to_lanes(data2);
3485                        let lanes1: [F64; 2] = to_lanes(data1);
3486                        let result: [F64; 2] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
3487                        stack.push_value(Value::V128(from_lanes(result)))?;
3488                    }
3489                    F32X4_PMIN => {
3490                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3491                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3492                        let lanes2: [F32; 4] = to_lanes(data2);
3493                        let lanes1: [F32; 4] = to_lanes(data1);
3494                        let result: [F32; 4] = array::from_fn(|i| {
3495                            let v1 = lanes1[i];
3496                            let v2 = lanes2[i];
3497                            if v2 < v1 {
3498                                v2
3499                            } else {
3500                                v1
3501                            }
3502                        });
3503                        stack.push_value(Value::V128(from_lanes(result)))?;
3504                    }
3505                    F64X2_PMIN => {
3506                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3507                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3508                        let lanes2: [F64; 2] = to_lanes(data2);
3509                        let lanes1: [F64; 2] = to_lanes(data1);
3510                        let result: [F64; 2] = array::from_fn(|i| {
3511                            let v1 = lanes1[i];
3512                            let v2 = lanes2[i];
3513                            if v2 < v1 {
3514                                v2
3515                            } else {
3516                                v1
3517                            }
3518                        });
3519                        stack.push_value(Value::V128(from_lanes(result)))?;
3520                    }
3521                    F32X4_PMAX => {
3522                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3523                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3524                        let lanes2: [F32; 4] = to_lanes(data2);
3525                        let lanes1: [F32; 4] = to_lanes(data1);
3526                        let result: [F32; 4] = array::from_fn(|i| {
3527                            let v1 = lanes1[i];
3528                            let v2 = lanes2[i];
3529                            if v1 < v2 {
3530                                v2
3531                            } else {
3532                                v1
3533                            }
3534                        });
3535                        stack.push_value(Value::V128(from_lanes(result)))?;
3536                    }
3537                    F64X2_PMAX => {
3538                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3539                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3540                        let lanes2: [F64; 2] = to_lanes(data2);
3541                        let lanes1: [F64; 2] = to_lanes(data1);
3542                        let result: [F64; 2] = array::from_fn(|i| {
3543                            let v1 = lanes1[i];
3544                            let v2 = lanes2[i];
3545                            if v1 < v2 {
3546                                v2
3547                            } else {
3548                                v1
3549                            }
3550                        });
3551                        stack.push_value(Value::V128(from_lanes(result)))?;
3552                    }
3553                    // viminmaxop
3554                    I8X16_MIN_S => {
3555                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3556                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3557                        let lanes2: [i8; 16] = to_lanes(data2);
3558                        let lanes1: [i8; 16] = to_lanes(data1);
3559                        let result: [i8; 16] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
3560                        stack.push_value(Value::V128(from_lanes(result)))?;
3561                    }
3562                    I16X8_MIN_S => {
3563                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3564                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3565                        let lanes2: [i16; 8] = to_lanes(data2);
3566                        let lanes1: [i16; 8] = to_lanes(data1);
3567                        let result: [i16; 8] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
3568                        stack.push_value(Value::V128(from_lanes(result)))?;
3569                    }
3570                    I32X4_MIN_S => {
3571                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3572                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3573                        let lanes2: [i32; 4] = to_lanes(data2);
3574                        let lanes1: [i32; 4] = to_lanes(data1);
3575                        let result: [i32; 4] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
3576                        stack.push_value(Value::V128(from_lanes(result)))?;
3577                    }
3578                    I8X16_MIN_U => {
3579                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3580                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3581                        let lanes2: [u8; 16] = to_lanes(data2);
3582                        let lanes1: [u8; 16] = to_lanes(data1);
3583                        let result: [u8; 16] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
3584                        stack.push_value(Value::V128(from_lanes(result)))?;
3585                    }
3586                    I16X8_MIN_U => {
3587                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3588                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3589                        let lanes2: [u16; 8] = to_lanes(data2);
3590                        let lanes1: [u16; 8] = to_lanes(data1);
3591                        let result: [u16; 8] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
3592                        stack.push_value(Value::V128(from_lanes(result)))?;
3593                    }
3594                    I32X4_MIN_U => {
3595                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3596                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3597                        let lanes2: [u32; 4] = to_lanes(data2);
3598                        let lanes1: [u32; 4] = to_lanes(data1);
3599                        let result: [u32; 4] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
3600                        stack.push_value(Value::V128(from_lanes(result)))?;
3601                    }
3602                    I8X16_MAX_S => {
3603                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3604                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3605                        let lanes2: [i8; 16] = to_lanes(data2);
3606                        let lanes1: [i8; 16] = to_lanes(data1);
3607                        let result: [i8; 16] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
3608                        stack.push_value(Value::V128(from_lanes(result)))?;
3609                    }
3610                    I16X8_MAX_S => {
3611                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3612                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3613                        let lanes2: [i16; 8] = to_lanes(data2);
3614                        let lanes1: [i16; 8] = to_lanes(data1);
3615                        let result: [i16; 8] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
3616                        stack.push_value(Value::V128(from_lanes(result)))?;
3617                    }
3618                    I32X4_MAX_S => {
3619                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3620                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3621                        let lanes2: [i32; 4] = to_lanes(data2);
3622                        let lanes1: [i32; 4] = to_lanes(data1);
3623                        let result: [i32; 4] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
3624                        stack.push_value(Value::V128(from_lanes(result)))?;
3625                    }
3626                    I8X16_MAX_U => {
3627                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3628                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3629                        let lanes2: [u8; 16] = to_lanes(data2);
3630                        let lanes1: [u8; 16] = to_lanes(data1);
3631                        let result: [u8; 16] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
3632                        stack.push_value(Value::V128(from_lanes(result)))?;
3633                    }
3634                    I16X8_MAX_U => {
3635                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3636                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3637                        let lanes2: [u16; 8] = to_lanes(data2);
3638                        let lanes1: [u16; 8] = to_lanes(data1);
3639                        let result: [u16; 8] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
3640                        stack.push_value(Value::V128(from_lanes(result)))?;
3641                    }
3642                    I32X4_MAX_U => {
3643                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3644                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3645                        let lanes2: [u32; 4] = to_lanes(data2);
3646                        let lanes1: [u32; 4] = to_lanes(data1);
3647                        let result: [u32; 4] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
3648                        stack.push_value(Value::V128(from_lanes(result)))?;
3649                    }
3650
3651                    // visatbinop
3652                    I8X16_ADD_SAT_S => {
3653                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3654                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3655                        let lanes2: [i8; 16] = to_lanes(data2);
3656                        let lanes1: [i8; 16] = to_lanes(data1);
3657                        let result: [i8; 16] =
3658                            array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
3659                        stack.push_value(Value::V128(from_lanes(result)))?;
3660                    }
3661                    I16X8_ADD_SAT_S => {
3662                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3663                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3664                        let lanes2: [i16; 8] = to_lanes(data2);
3665                        let lanes1: [i16; 8] = to_lanes(data1);
3666                        let result: [i16; 8] =
3667                            array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
3668                        stack.push_value(Value::V128(from_lanes(result)))?;
3669                    }
3670                    I8X16_ADD_SAT_U => {
3671                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3672                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3673                        let lanes2: [u8; 16] = to_lanes(data2);
3674                        let lanes1: [u8; 16] = to_lanes(data1);
3675                        let result: [u8; 16] =
3676                            array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
3677                        stack.push_value(Value::V128(from_lanes(result)))?;
3678                    }
3679                    I16X8_ADD_SAT_U => {
3680                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3681                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3682                        let lanes2: [u16; 8] = to_lanes(data2);
3683                        let lanes1: [u16; 8] = to_lanes(data1);
3684                        let result: [u16; 8] =
3685                            array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
3686                        stack.push_value(Value::V128(from_lanes(result)))?;
3687                    }
3688                    I8X16_SUB_SAT_S => {
3689                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3690                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3691                        let lanes2: [i8; 16] = to_lanes(data2);
3692                        let lanes1: [i8; 16] = to_lanes(data1);
3693                        let result: [i8; 16] =
3694                            array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
3695                        stack.push_value(Value::V128(from_lanes(result)))?;
3696                    }
3697                    I16X8_SUB_SAT_S => {
3698                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3699                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3700                        let lanes2: [i16; 8] = to_lanes(data2);
3701                        let lanes1: [i16; 8] = to_lanes(data1);
3702                        let result: [i16; 8] =
3703                            array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
3704                        stack.push_value(Value::V128(from_lanes(result)))?;
3705                    }
3706                    I8X16_SUB_SAT_U => {
3707                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3708                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3709                        let lanes2: [u8; 16] = to_lanes(data2);
3710                        let lanes1: [u8; 16] = to_lanes(data1);
3711                        let result: [u8; 16] =
3712                            array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
3713                        stack.push_value(Value::V128(from_lanes(result)))?;
3714                    }
3715                    I16X8_SUB_SAT_U => {
3716                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3717                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3718                        let lanes2: [u16; 8] = to_lanes(data2);
3719                        let lanes1: [u16; 8] = to_lanes(data1);
3720                        let result: [u16; 8] =
3721                            array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
3722                        stack.push_value(Value::V128(from_lanes(result)))?;
3723                    }
3724                    // others
3725                    I16X8_MUL => {
3726                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3727                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3728                        let lanes2: [u16; 8] = to_lanes(data2);
3729                        let lanes1: [u16; 8] = to_lanes(data1);
3730                        let result: [u16; 8] =
3731                            array::from_fn(|i| lanes1[i].wrapping_mul(lanes2[i]));
3732                        stack.push_value(Value::V128(from_lanes(result)))?;
3733                    }
3734                    I32X4_MUL => {
3735                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3736                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3737                        let lanes2: [u32; 4] = to_lanes(data2);
3738                        let lanes1: [u32; 4] = to_lanes(data1);
3739                        let result: [u32; 4] =
3740                            array::from_fn(|i| lanes1[i].wrapping_mul(lanes2[i]));
3741                        stack.push_value(Value::V128(from_lanes(result)))?;
3742                    }
3743                    I64X2_MUL => {
3744                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3745                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3746                        let lanes2: [u64; 2] = to_lanes(data2);
3747                        let lanes1: [u64; 2] = to_lanes(data1);
3748                        let result: [u64; 2] =
3749                            array::from_fn(|i| lanes1[i].wrapping_mul(lanes2[i]));
3750                        stack.push_value(Value::V128(from_lanes(result)))?;
3751                    }
3752                    I8X16_AVGR_U => {
3753                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3754                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3755                        let lanes2: [u8; 16] = to_lanes(data2);
3756                        let lanes1: [u8; 16] = to_lanes(data1);
3757                        let result: [u8; 16] = array::from_fn(|i| {
3758                            (lanes1[i] as u16 + lanes2[i] as u16).div_ceil(2) as u8
3759                        });
3760                        stack.push_value(Value::V128(from_lanes(result)))?;
3761                    }
3762                    I16X8_AVGR_U => {
3763                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3764                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3765                        let lanes2: [u16; 8] = to_lanes(data2);
3766                        let lanes1: [u16; 8] = to_lanes(data1);
3767                        let result: [u16; 8] = array::from_fn(|i| {
3768                            (lanes1[i] as u32 + lanes2[i] as u32).div_ceil(2) as u16
3769                        });
3770                        stack.push_value(Value::V128(from_lanes(result)))?;
3771                    }
3772                    I16X8_Q15MULRSAT_S => {
3773                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3774                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3775                        let lanes2: [i16; 8] = to_lanes(data2);
3776                        let lanes1: [i16; 8] = to_lanes(data1);
3777                        let result: [i16; 8] = array::from_fn(|i| {
3778                            (((lanes1[i] as i64).mul(lanes2[i] as i64) + 2i64.pow(14)) >> 15i64)
3779                                .clamp(i16::MIN as i64, i16::MAX as i64)
3780                                as i16
3781                        });
3782                        stack.push_value(Value::V128(from_lanes(result)))?;
3783                    }
3784
3785                    // Group vrelop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vrelop>
3786                    // virelop
3787                    I8X16_EQ => {
3788                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3789                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3790                        let lanes2: [u8; 16] = to_lanes(data2);
3791                        let lanes1: [u8; 16] = to_lanes(data1);
3792                        let result: [i8; 16] =
3793                            array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i8).neg());
3794                        stack.push_value(Value::V128(from_lanes(result)))?;
3795                    }
3796                    I16X8_EQ => {
3797                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3798                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3799                        let lanes2: [u16; 8] = to_lanes(data2);
3800                        let lanes1: [u16; 8] = to_lanes(data1);
3801                        let result: [i16; 8] =
3802                            array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i16).neg());
3803                        stack.push_value(Value::V128(from_lanes(result)))?;
3804                    }
3805                    I32X4_EQ => {
3806                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3807                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3808                        let lanes2: [u32; 4] = to_lanes(data2);
3809                        let lanes1: [u32; 4] = to_lanes(data1);
3810                        let result: [i32; 4] =
3811                            array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i32).neg());
3812                        stack.push_value(Value::V128(from_lanes(result)))?;
3813                    }
3814                    I64X2_EQ => {
3815                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3816                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3817                        let lanes2: [u64; 2] = to_lanes(data2);
3818                        let lanes1: [u64; 2] = to_lanes(data1);
3819                        let result: [i64; 2] =
3820                            array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i64).neg());
3821                        stack.push_value(Value::V128(from_lanes(result)))?;
3822                    }
3823                    I8X16_NE => {
3824                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3825                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3826                        let lanes2: [u8; 16] = to_lanes(data2);
3827                        let lanes1: [u8; 16] = to_lanes(data1);
3828                        let result: [i8; 16] =
3829                            array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i8).neg());
3830                        stack.push_value(Value::V128(from_lanes(result)))?;
3831                    }
3832                    I16X8_NE => {
3833                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3834                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3835                        let lanes2: [u16; 8] = to_lanes(data2);
3836                        let lanes1: [u16; 8] = to_lanes(data1);
3837                        let result: [i16; 8] =
3838                            array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i16).neg());
3839                        stack.push_value(Value::V128(from_lanes(result)))?;
3840                    }
3841                    I32X4_NE => {
3842                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3843                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3844                        let lanes2: [u32; 4] = to_lanes(data2);
3845                        let lanes1: [u32; 4] = to_lanes(data1);
3846                        let result: [i32; 4] =
3847                            array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i32).neg());
3848                        stack.push_value(Value::V128(from_lanes(result)))?;
3849                    }
3850                    I64X2_NE => {
3851                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3852                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3853                        let lanes2: [u64; 2] = to_lanes(data2);
3854                        let lanes1: [u64; 2] = to_lanes(data1);
3855                        let result: [i64; 2] =
3856                            array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i64).neg());
3857                        stack.push_value(Value::V128(from_lanes(result)))?;
3858                    }
3859                    I8X16_LT_S => {
3860                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3861                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3862                        let lanes2: [i8; 16] = to_lanes(data2);
3863                        let lanes1: [i8; 16] = to_lanes(data1);
3864                        let result: [i8; 16] =
3865                            array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i8).neg());
3866                        stack.push_value(Value::V128(from_lanes(result)))?;
3867                    }
3868                    I16X8_LT_S => {
3869                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3870                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3871                        let lanes2: [i16; 8] = to_lanes(data2);
3872                        let lanes1: [i16; 8] = to_lanes(data1);
3873                        let result: [i16; 8] =
3874                            array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i16).neg());
3875                        stack.push_value(Value::V128(from_lanes(result)))?;
3876                    }
3877                    I32X4_LT_S => {
3878                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3879                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3880                        let lanes2: [i32; 4] = to_lanes(data2);
3881                        let lanes1: [i32; 4] = to_lanes(data1);
3882                        let result: [i32; 4] =
3883                            array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i32).neg());
3884                        stack.push_value(Value::V128(from_lanes(result)))?;
3885                    }
3886                    I64X2_LT_S => {
3887                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3888                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3889                        let lanes2: [i64; 2] = to_lanes(data2);
3890                        let lanes1: [i64; 2] = to_lanes(data1);
3891                        let result: [i64; 2] =
3892                            array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i64).neg());
3893                        stack.push_value(Value::V128(from_lanes(result)))?;
3894                    }
3895                    I8X16_LT_U => {
3896                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3897                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3898                        let lanes2: [u8; 16] = to_lanes(data2);
3899                        let lanes1: [u8; 16] = to_lanes(data1);
3900                        let result: [i8; 16] =
3901                            array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i8).neg());
3902                        stack.push_value(Value::V128(from_lanes(result)))?;
3903                    }
3904                    I16X8_LT_U => {
3905                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3906                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3907                        let lanes2: [u16; 8] = to_lanes(data2);
3908                        let lanes1: [u16; 8] = to_lanes(data1);
3909                        let result: [i16; 8] =
3910                            array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i16).neg());
3911                        stack.push_value(Value::V128(from_lanes(result)))?;
3912                    }
3913                    I32X4_LT_U => {
3914                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3915                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3916                        let lanes2: [u32; 4] = to_lanes(data2);
3917                        let lanes1: [u32; 4] = to_lanes(data1);
3918                        let result: [i32; 4] =
3919                            array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i32).neg());
3920                        stack.push_value(Value::V128(from_lanes(result)))?;
3921                    }
3922                    I8X16_GT_S => {
3923                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3924                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3925                        let lanes2: [i8; 16] = to_lanes(data2);
3926                        let lanes1: [i8; 16] = to_lanes(data1);
3927                        let result: [i8; 16] =
3928                            array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i8).neg());
3929                        stack.push_value(Value::V128(from_lanes(result)))?;
3930                    }
3931                    I16X8_GT_S => {
3932                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3933                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3934                        let lanes2: [i16; 8] = to_lanes(data2);
3935                        let lanes1: [i16; 8] = to_lanes(data1);
3936                        let result: [i16; 8] =
3937                            array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i16).neg());
3938                        stack.push_value(Value::V128(from_lanes(result)))?;
3939                    }
3940                    I32X4_GT_S => {
3941                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3942                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3943                        let lanes2: [i32; 4] = to_lanes(data2);
3944                        let lanes1: [i32; 4] = to_lanes(data1);
3945                        let result: [i32; 4] =
3946                            array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i32).neg());
3947                        stack.push_value(Value::V128(from_lanes(result)))?;
3948                    }
3949                    I64X2_GT_S => {
3950                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3951                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3952                        let lanes2: [i64; 2] = to_lanes(data2);
3953                        let lanes1: [i64; 2] = to_lanes(data1);
3954                        let result: [i64; 2] =
3955                            array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i64).neg());
3956                        stack.push_value(Value::V128(from_lanes(result)))?;
3957                    }
3958                    I8X16_GT_U => {
3959                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3960                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3961                        let lanes2: [u8; 16] = to_lanes(data2);
3962                        let lanes1: [u8; 16] = to_lanes(data1);
3963                        let result: [i8; 16] =
3964                            array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i8).neg());
3965                        stack.push_value(Value::V128(from_lanes(result)))?;
3966                    }
3967                    I16X8_GT_U => {
3968                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3969                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3970                        let lanes2: [u16; 8] = to_lanes(data2);
3971                        let lanes1: [u16; 8] = to_lanes(data1);
3972                        let result: [i16; 8] =
3973                            array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i16).neg());
3974                        stack.push_value(Value::V128(from_lanes(result)))?;
3975                    }
3976                    I32X4_GT_U => {
3977                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3978                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3979                        let lanes2: [u32; 4] = to_lanes(data2);
3980                        let lanes1: [u32; 4] = to_lanes(data1);
3981                        let result: [i32; 4] =
3982                            array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i32).neg());
3983                        stack.push_value(Value::V128(from_lanes(result)))?;
3984                    }
3985                    I8X16_LE_S => {
3986                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3987                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3988                        let lanes2: [i8; 16] = to_lanes(data2);
3989                        let lanes1: [i8; 16] = to_lanes(data1);
3990                        let result: [i8; 16] =
3991                            array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i8).neg());
3992                        stack.push_value(Value::V128(from_lanes(result)))?;
3993                    }
3994                    I16X8_LE_S => {
3995                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3996                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3997                        let lanes2: [i16; 8] = to_lanes(data2);
3998                        let lanes1: [i16; 8] = to_lanes(data1);
3999                        let result: [i16; 8] =
4000                            array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i16).neg());
4001                        stack.push_value(Value::V128(from_lanes(result)))?;
4002                    }
4003                    I32X4_LE_S => {
4004                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4005                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4006                        let lanes2: [i32; 4] = to_lanes(data2);
4007                        let lanes1: [i32; 4] = to_lanes(data1);
4008                        let result: [i32; 4] =
4009                            array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i32).neg());
4010                        stack.push_value(Value::V128(from_lanes(result)))?;
4011                    }
4012                    I64X2_LE_S => {
4013                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4014                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4015                        let lanes2: [i64; 2] = to_lanes(data2);
4016                        let lanes1: [i64; 2] = to_lanes(data1);
4017                        let result: [i64; 2] =
4018                            array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i64).neg());
4019                        stack.push_value(Value::V128(from_lanes(result)))?;
4020                    }
4021                    I8X16_LE_U => {
4022                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4023                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4024                        let lanes2: [u8; 16] = to_lanes(data2);
4025                        let lanes1: [u8; 16] = to_lanes(data1);
4026                        let result: [i8; 16] =
4027                            array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i8).neg());
4028                        stack.push_value(Value::V128(from_lanes(result)))?;
4029                    }
4030                    I16X8_LE_U => {
4031                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4032                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4033                        let lanes2: [u16; 8] = to_lanes(data2);
4034                        let lanes1: [u16; 8] = to_lanes(data1);
4035                        let result: [i16; 8] =
4036                            array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i16).neg());
4037                        stack.push_value(Value::V128(from_lanes(result)))?;
4038                    }
4039                    I32X4_LE_U => {
4040                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4041                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4042                        let lanes2: [u32; 4] = to_lanes(data2);
4043                        let lanes1: [u32; 4] = to_lanes(data1);
4044                        let result: [i32; 4] =
4045                            array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i32).neg());
4046                        stack.push_value(Value::V128(from_lanes(result)))?;
4047                    }
4048
4049                    I8X16_GE_S => {
4050                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4051                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4052                        let lanes2: [i8; 16] = to_lanes(data2);
4053                        let lanes1: [i8; 16] = to_lanes(data1);
4054                        let result: [i8; 16] =
4055                            array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i8).neg());
4056                        stack.push_value(Value::V128(from_lanes(result)))?;
4057                    }
4058                    I16X8_GE_S => {
4059                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4060                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4061                        let lanes2: [i16; 8] = to_lanes(data2);
4062                        let lanes1: [i16; 8] = to_lanes(data1);
4063                        let result: [i16; 8] =
4064                            array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i16).neg());
4065                        stack.push_value(Value::V128(from_lanes(result)))?;
4066                    }
4067                    I32X4_GE_S => {
4068                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4069                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4070                        let lanes2: [i32; 4] = to_lanes(data2);
4071                        let lanes1: [i32; 4] = to_lanes(data1);
4072                        let result: [i32; 4] =
4073                            array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i32).neg());
4074                        stack.push_value(Value::V128(from_lanes(result)))?;
4075                    }
4076                    I64X2_GE_S => {
4077                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4078                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4079                        let lanes2: [i64; 2] = to_lanes(data2);
4080                        let lanes1: [i64; 2] = to_lanes(data1);
4081                        let result: [i64; 2] =
4082                            array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i64).neg());
4083                        stack.push_value(Value::V128(from_lanes(result)))?;
4084                    }
4085                    I8X16_GE_U => {
4086                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4087                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4088                        let lanes2: [u8; 16] = to_lanes(data2);
4089                        let lanes1: [u8; 16] = to_lanes(data1);
4090                        let result: [i8; 16] =
4091                            array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i8).neg());
4092                        stack.push_value(Value::V128(from_lanes(result)))?;
4093                    }
4094                    I16X8_GE_U => {
4095                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4096                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4097                        let lanes2: [u16; 8] = to_lanes(data2);
4098                        let lanes1: [u16; 8] = to_lanes(data1);
4099                        let result: [i16; 8] =
4100                            array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i16).neg());
4101                        stack.push_value(Value::V128(from_lanes(result)))?;
4102                    }
4103                    I32X4_GE_U => {
4104                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4105                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4106                        let lanes2: [u32; 4] = to_lanes(data2);
4107                        let lanes1: [u32; 4] = to_lanes(data1);
4108                        let result: [i32; 4] =
4109                            array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i32).neg());
4110                        stack.push_value(Value::V128(from_lanes(result)))?;
4111                    }
4112                    // vfrelop
4113                    F32X4_EQ => {
4114                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4115                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4116                        let lanes2: [F32; 4] = to_lanes(data2);
4117                        let lanes1: [F32; 4] = to_lanes(data1);
4118                        let result: [i32; 4] =
4119                            array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i32).neg());
4120                        stack.push_value(Value::V128(from_lanes(result)))?;
4121                    }
4122                    F64X2_EQ => {
4123                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4124                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4125                        let lanes2: [F64; 2] = to_lanes(data2);
4126                        let lanes1: [F64; 2] = to_lanes(data1);
4127                        let result: [i64; 2] =
4128                            array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i64).neg());
4129                        stack.push_value(Value::V128(from_lanes(result)))?;
4130                    }
4131                    F32X4_NE => {
4132                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4133                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4134                        let lanes2: [F32; 4] = to_lanes(data2);
4135                        let lanes1: [F32; 4] = to_lanes(data1);
4136                        let result: [i32; 4] =
4137                            array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i32).neg());
4138                        stack.push_value(Value::V128(from_lanes(result)))?;
4139                    }
4140                    F64X2_NE => {
4141                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4142                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4143                        let lanes2: [F64; 2] = to_lanes(data2);
4144                        let lanes1: [F64; 2] = to_lanes(data1);
4145                        let result: [i64; 2] =
4146                            array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i64).neg());
4147                        stack.push_value(Value::V128(from_lanes(result)))?;
4148                    }
4149                    F32X4_LT => {
4150                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4151                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4152                        let lanes2: [F32; 4] = to_lanes(data2);
4153                        let lanes1: [F32; 4] = to_lanes(data1);
4154                        let result: [i32; 4] =
4155                            array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i32).neg());
4156                        stack.push_value(Value::V128(from_lanes(result)))?;
4157                    }
4158                    F64X2_LT => {
4159                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4160                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4161                        let lanes2: [F64; 2] = to_lanes(data2);
4162                        let lanes1: [F64; 2] = to_lanes(data1);
4163                        let result: [i64; 2] =
4164                            array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i64).neg());
4165                        stack.push_value(Value::V128(from_lanes(result)))?;
4166                    }
4167                    F32X4_GT => {
4168                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4169                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4170                        let lanes2: [F32; 4] = to_lanes(data2);
4171                        let lanes1: [F32; 4] = to_lanes(data1);
4172                        let result: [i32; 4] =
4173                            array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i32).neg());
4174                        stack.push_value(Value::V128(from_lanes(result)))?;
4175                    }
4176                    F64X2_GT => {
4177                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4178                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4179                        let lanes2: [F64; 2] = to_lanes(data2);
4180                        let lanes1: [F64; 2] = to_lanes(data1);
4181                        let result: [i64; 2] =
4182                            array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i64).neg());
4183                        stack.push_value(Value::V128(from_lanes(result)))?;
4184                    }
4185                    F32X4_LE => {
4186                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4187                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4188                        let lanes2: [F32; 4] = to_lanes(data2);
4189                        let lanes1: [F32; 4] = to_lanes(data1);
4190                        let result: [i32; 4] =
4191                            array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i32).neg());
4192                        stack.push_value(Value::V128(from_lanes(result)))?;
4193                    }
4194                    F64X2_LE => {
4195                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4196                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4197                        let lanes2: [F64; 2] = to_lanes(data2);
4198                        let lanes1: [F64; 2] = to_lanes(data1);
4199                        let result: [i64; 2] =
4200                            array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i64).neg());
4201                        stack.push_value(Value::V128(from_lanes(result)))?;
4202                    }
4203                    F32X4_GE => {
4204                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4205                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4206                        let lanes2: [F32; 4] = to_lanes(data2);
4207                        let lanes1: [F32; 4] = to_lanes(data1);
4208                        let result: [i32; 4] =
4209                            array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i32).neg());
4210                        stack.push_value(Value::V128(from_lanes(result)))?;
4211                    }
4212                    F64X2_GE => {
4213                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4214                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4215                        let lanes2: [F64; 2] = to_lanes(data2);
4216                        let lanes1: [F64; 2] = to_lanes(data1);
4217                        let result: [i64; 2] =
4218                            array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i64).neg());
4219                        stack.push_value(Value::V128(from_lanes(result)))?;
4220                    }
4221
4222                    // Group vishiftop
4223                    I8X16_SHL => {
4224                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4225                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4226                        let lanes: [u8; 16] = to_lanes(data);
4227                        let result: [u8; 16] = lanes.map(|lane| lane.wrapping_shl(shift));
4228                        stack.push_value(Value::V128(from_lanes(result)))?;
4229                    }
4230                    I16X8_SHL => {
4231                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4232                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4233                        let lanes: [u16; 8] = to_lanes(data);
4234                        let result: [u16; 8] = lanes.map(|lane| lane.wrapping_shl(shift));
4235                        stack.push_value(Value::V128(from_lanes(result)))?;
4236                    }
4237                    I32X4_SHL => {
4238                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4239                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4240                        let lanes: [u32; 4] = to_lanes(data);
4241                        let result: [u32; 4] = lanes.map(|lane| lane.wrapping_shl(shift));
4242                        stack.push_value(Value::V128(from_lanes(result)))?;
4243                    }
4244                    I64X2_SHL => {
4245                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4246                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4247                        let lanes: [u64; 2] = to_lanes(data);
4248                        let result: [u64; 2] = lanes.map(|lane| lane.wrapping_shl(shift));
4249                        stack.push_value(Value::V128(from_lanes(result)))?;
4250                    }
4251                    I8X16_SHR_S => {
4252                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4253                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4254                        let lanes: [i8; 16] = to_lanes(data);
4255                        let result: [i8; 16] = lanes.map(|lane| lane.wrapping_shr(shift));
4256                        stack.push_value(Value::V128(from_lanes(result)))?;
4257                    }
4258                    I8X16_SHR_U => {
4259                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4260                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4261                        let lanes: [u8; 16] = to_lanes(data);
4262                        let result: [u8; 16] = lanes.map(|lane| lane.wrapping_shr(shift));
4263                        stack.push_value(Value::V128(from_lanes(result)))?;
4264                    }
4265                    I16X8_SHR_S => {
4266                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4267                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4268                        let lanes: [i16; 8] = to_lanes(data);
4269                        let result: [i16; 8] = lanes.map(|lane| lane.wrapping_shr(shift));
4270                        stack.push_value(Value::V128(from_lanes(result)))?;
4271                    }
4272                    I16X8_SHR_U => {
4273                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4274                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4275                        let lanes: [u16; 8] = to_lanes(data);
4276                        let result: [u16; 8] = lanes.map(|lane| lane.wrapping_shr(shift));
4277                        stack.push_value(Value::V128(from_lanes(result)))?;
4278                    }
4279                    I32X4_SHR_S => {
4280                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4281                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4282                        let lanes: [i32; 4] = to_lanes(data);
4283                        let result: [i32; 4] = lanes.map(|lane| lane.wrapping_shr(shift));
4284                        stack.push_value(Value::V128(from_lanes(result)))?;
4285                    }
4286                    I32X4_SHR_U => {
4287                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4288                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4289                        let lanes: [u32; 4] = to_lanes(data);
4290                        let result: [u32; 4] = lanes.map(|lane| lane.wrapping_shr(shift));
4291                        stack.push_value(Value::V128(from_lanes(result)))?;
4292                    }
4293                    I64X2_SHR_S => {
4294                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4295                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4296                        let lanes: [i64; 2] = to_lanes(data);
4297                        let result: [i64; 2] = lanes.map(|lane| lane.wrapping_shr(shift));
4298                        stack.push_value(Value::V128(from_lanes(result)))?;
4299                    }
4300                    I64X2_SHR_U => {
4301                        let shift: u32 = stack.pop_value().try_into().unwrap_validated();
4302                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4303                        let lanes: [u64; 2] = to_lanes(data);
4304                        let result: [u64; 2] = lanes.map(|lane| lane.wrapping_shr(shift));
4305                        stack.push_value(Value::V128(from_lanes(result)))?;
4306                    }
4307
4308                    // Group vtestop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vtestop>
4309                    // vitestop
4310                    I8X16_ALL_TRUE => {
4311                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4312                        let lanes: [u8; 16] = to_lanes(data);
4313                        let all_true = lanes.into_iter().all(|lane| lane != 0);
4314                        stack.push_value(Value::I32(all_true as u32))?;
4315                    }
4316                    I16X8_ALL_TRUE => {
4317                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4318                        let lanes: [u16; 8] = to_lanes(data);
4319                        let all_true = lanes.into_iter().all(|lane| lane != 0);
4320                        stack.push_value(Value::I32(all_true as u32))?;
4321                    }
4322                    I32X4_ALL_TRUE => {
4323                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4324                        let lanes: [u32; 4] = to_lanes(data);
4325                        let all_true = lanes.into_iter().all(|lane| lane != 0);
4326                        stack.push_value(Value::I32(all_true as u32))?;
4327                    }
4328                    I64X2_ALL_TRUE => {
4329                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4330                        let lanes: [u64; 2] = to_lanes(data);
4331                        let all_true = lanes.into_iter().all(|lane| lane != 0);
4332                        stack.push_value(Value::I32(all_true as u32))?;
4333                    }
4334
4335                    // Group vcvtop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vcvtop>
4336                    I16X8_EXTEND_HIGH_I8X16_S => {
4337                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4338                        let lanes: [i8; 16] = to_lanes(data);
4339                        let high_lanes: [i8; 8] = lanes[8..].try_into().unwrap();
4340                        let result = high_lanes.map(|lane| lane as i16);
4341                        stack.push_value(Value::V128(from_lanes(result)))?;
4342                    }
4343                    I16X8_EXTEND_HIGH_I8X16_U => {
4344                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4345                        let lanes: [u8; 16] = to_lanes(data);
4346                        let high_lanes: [u8; 8] = lanes[8..].try_into().unwrap();
4347                        let result = high_lanes.map(|lane| lane as u16);
4348                        stack.push_value(Value::V128(from_lanes(result)))?;
4349                    }
4350                    I16X8_EXTEND_LOW_I8X16_S => {
4351                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4352                        let lanes: [i8; 16] = to_lanes(data);
4353                        let low_lanes: [i8; 8] = lanes[..8].try_into().unwrap();
4354                        let result = low_lanes.map(|lane| lane as i16);
4355                        stack.push_value(Value::V128(from_lanes(result)))?;
4356                    }
4357                    I16X8_EXTEND_LOW_I8X16_U => {
4358                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4359                        let lanes: [u8; 16] = to_lanes(data);
4360                        let low_lanes: [u8; 8] = lanes[..8].try_into().unwrap();
4361                        let result = low_lanes.map(|lane| lane as u16);
4362                        stack.push_value(Value::V128(from_lanes(result)))?;
4363                    }
4364                    I32X4_EXTEND_HIGH_I16X8_S => {
4365                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4366                        let lanes: [i16; 8] = to_lanes(data);
4367                        let high_lanes: [i16; 4] = lanes[4..].try_into().unwrap();
4368                        let result = high_lanes.map(|lane| lane as i32);
4369                        stack.push_value(Value::V128(from_lanes(result)))?;
4370                    }
4371                    I32X4_EXTEND_HIGH_I16X8_U => {
4372                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4373                        let lanes: [u16; 8] = to_lanes(data);
4374                        let high_lanes: [u16; 4] = lanes[4..].try_into().unwrap();
4375                        let result = high_lanes.map(|lane| lane as u32);
4376                        stack.push_value(Value::V128(from_lanes(result)))?;
4377                    }
4378                    I32X4_EXTEND_LOW_I16X8_S => {
4379                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4380                        let lanes: [i16; 8] = to_lanes(data);
4381                        let low_lanes: [i16; 4] = lanes[..4].try_into().unwrap();
4382                        let result = low_lanes.map(|lane| lane as i32);
4383                        stack.push_value(Value::V128(from_lanes(result)))?;
4384                    }
4385                    I32X4_EXTEND_LOW_I16X8_U => {
4386                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4387                        let lanes: [u16; 8] = to_lanes(data);
4388                        let low_lanes: [u16; 4] = lanes[..4].try_into().unwrap();
4389                        let result = low_lanes.map(|lane| lane as u32);
4390                        stack.push_value(Value::V128(from_lanes(result)))?;
4391                    }
4392                    I64X2_EXTEND_HIGH_I32X4_S => {
4393                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4394                        let lanes: [i32; 4] = to_lanes(data);
4395                        let high_lanes: [i32; 2] = lanes[2..].try_into().unwrap();
4396                        let result = high_lanes.map(|lane| lane as i64);
4397                        stack.push_value(Value::V128(from_lanes(result)))?;
4398                    }
4399                    I64X2_EXTEND_HIGH_I32X4_U => {
4400                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4401                        let lanes: [u32; 4] = to_lanes(data);
4402                        let high_lanes: [u32; 2] = lanes[2..].try_into().unwrap();
4403                        let result = high_lanes.map(|lane| lane as u64);
4404                        stack.push_value(Value::V128(from_lanes(result)))?;
4405                    }
4406                    I64X2_EXTEND_LOW_I32X4_S => {
4407                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4408                        let lanes: [i32; 4] = to_lanes(data);
4409                        let low_lanes: [i32; 2] = lanes[..2].try_into().unwrap();
4410                        let result = low_lanes.map(|lane| lane as i64);
4411                        stack.push_value(Value::V128(from_lanes(result)))?;
4412                    }
4413                    I64X2_EXTEND_LOW_I32X4_U => {
4414                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4415                        let lanes: [u32; 4] = to_lanes(data);
4416                        let low_lanes: [u32; 2] = lanes[..2].try_into().unwrap();
4417                        let result = low_lanes.map(|lane| lane as u64);
4418                        stack.push_value(Value::V128(from_lanes(result)))?;
4419                    }
4420                    I32X4_TRUNC_SAT_F32X4_S => {
4421                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4422                        let lanes: [F32; 4] = to_lanes(data);
4423                        let result = lanes.map(|lane| {
4424                            if lane.is_nan() {
4425                                0
4426                            } else if lane.is_negative_infinity() {
4427                                i32::MIN
4428                            } else if lane.is_infinity() {
4429                                i32::MAX
4430                            } else {
4431                                lane.as_i32()
4432                            }
4433                        });
4434                        stack.push_value(Value::V128(from_lanes(result)))?;
4435                    }
4436                    I32X4_TRUNC_SAT_F32X4_U => {
4437                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4438                        let lanes: [F32; 4] = to_lanes(data);
4439                        let result = lanes.map(|lane| {
4440                            if lane.is_nan() {
4441                                0
4442                            } else if lane.is_negative_infinity() {
4443                                u32::MIN
4444                            } else if lane.is_infinity() {
4445                                u32::MAX
4446                            } else {
4447                                lane.as_u32()
4448                            }
4449                        });
4450                        stack.push_value(Value::V128(from_lanes(result)))?;
4451                    }
4452                    I32X4_TRUNC_SAT_F64X2_S_ZERO => {
4453                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4454                        let lanes: [F64; 2] = to_lanes(data);
4455                        let result = lanes.map(|lane| {
4456                            if lane.is_nan() {
4457                                0
4458                            } else if lane.is_negative_infinity() {
4459                                i32::MIN
4460                            } else if lane.is_infinity() {
4461                                i32::MAX
4462                            } else {
4463                                lane.as_i32()
4464                            }
4465                        });
4466                        stack.push_value(Value::V128(from_lanes([result[0], result[1], 0, 0])))?;
4467                    }
4468                    I32X4_TRUNC_SAT_F64X2_U_ZERO => {
4469                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4470                        let lanes: [F64; 2] = to_lanes(data);
4471                        let result = lanes.map(|lane| {
4472                            if lane.is_nan() {
4473                                0
4474                            } else if lane.is_negative_infinity() {
4475                                u32::MIN
4476                            } else if lane.is_infinity() {
4477                                u32::MAX
4478                            } else {
4479                                lane.as_u32()
4480                            }
4481                        });
4482                        stack.push_value(Value::V128(from_lanes([result[0], result[1], 0, 0])))?;
4483                    }
4484                    F32X4_CONVERT_I32X4_S => {
4485                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4486                        let lanes: [i32; 4] = to_lanes(data);
4487                        let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
4488                        stack.push_value(Value::V128(from_lanes(result)))?;
4489                    }
4490                    F32X4_CONVERT_I32X4_U => {
4491                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4492                        let lanes: [u32; 4] = to_lanes(data);
4493                        let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
4494                        stack.push_value(Value::V128(from_lanes(result)))?;
4495                    }
4496                    F64X2_CONVERT_LOW_I32X4_S => {
4497                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4498                        let lanes: [i32; 4] = to_lanes(data);
4499                        let low_lanes: [i32; 2] = lanes[..2].try_into().unwrap();
4500                        let result = low_lanes.map(|lane| F64(lane as f64));
4501                        stack.push_value(Value::V128(from_lanes(result)))?;
4502                    }
4503                    F64X2_CONVERT_LOW_I32X4_U => {
4504                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4505                        let lanes: [u32; 4] = to_lanes(data);
4506                        let low_lanes: [u32; 2] = lanes[..2].try_into().unwrap();
4507                        let result = low_lanes.map(|lane| F64(lane as f64));
4508                        stack.push_value(Value::V128(from_lanes(result)))?;
4509                    }
4510                    F32X4_DEMOTE_F64X2_ZERO => {
4511                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4512                        let lanes = to_lanes::<8, 2, F64>(data);
4513                        let half_lanes = lanes.map(|lane| lane.as_f32());
4514                        let result = [half_lanes[0], half_lanes[1], F32(0.0), F32(0.0)];
4515                        stack.push_value(Value::V128(from_lanes(result)))?;
4516                    }
4517                    F64X2_PROMOTE_LOW_F32X4 => {
4518                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4519                        let lanes: [F32; 4] = to_lanes(data);
4520                        let half_lanes: [F32; 2] = lanes[..2].try_into().unwrap();
4521                        let result = half_lanes.map(|lane| lane.as_f64());
4522                        stack.push_value(Value::V128(from_lanes(result)))?;
4523                    }
4524
4525                    // ishape.narrow_ishape_sx
4526                    I8X16_NARROW_I16X8_S => {
4527                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4528                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4529                        let lanes2: [i16; 8] = to_lanes(data2);
4530                        let lanes1: [i16; 8] = to_lanes(data1);
4531                        let mut concatenated_narrowed_lanes = lanes1
4532                            .into_iter()
4533                            .chain(lanes2)
4534                            .map(|lane| lane.clamp(i8::MIN as i16, i8::MAX as i16) as i8);
4535                        let result: [i8; 16] =
4536                            array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
4537                        stack.push_value(Value::V128(from_lanes(result)))?;
4538                    }
4539                    I8X16_NARROW_I16X8_U => {
4540                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4541                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4542                        let lanes2: [i16; 8] = to_lanes(data2);
4543                        let lanes1: [i16; 8] = to_lanes(data1);
4544                        let mut concatenated_narrowed_lanes = lanes1
4545                            .into_iter()
4546                            .chain(lanes2)
4547                            .map(|lane| lane.clamp(u8::MIN as i16, u8::MAX as i16) as u8);
4548                        let result: [u8; 16] =
4549                            array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
4550                        stack.push_value(Value::V128(from_lanes(result)))?;
4551                    }
4552                    I16X8_NARROW_I32X4_S => {
4553                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4554                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4555                        let lanes2: [i32; 4] = to_lanes(data2);
4556                        let lanes1: [i32; 4] = to_lanes(data1);
4557                        let mut concatenated_narrowed_lanes = lanes1
4558                            .into_iter()
4559                            .chain(lanes2)
4560                            .map(|lane| lane.clamp(i16::MIN as i32, i16::MAX as i32) as i16);
4561                        let result: [i16; 8] =
4562                            array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
4563                        stack.push_value(Value::V128(from_lanes(result)))?;
4564                    }
4565                    I16X8_NARROW_I32X4_U => {
4566                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4567                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4568                        let lanes2: [i32; 4] = to_lanes(data2);
4569                        let lanes1: [i32; 4] = to_lanes(data1);
4570                        let mut concatenated_narrowed_lanes = lanes1
4571                            .into_iter()
4572                            .chain(lanes2)
4573                            .map(|lane| lane.clamp(u16::MIN as i32, u16::MAX as i32) as u16);
4574                        let result: [u16; 8] =
4575                            array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
4576                        stack.push_value(Value::V128(from_lanes(result)))?;
4577                    }
4578
4579                    // ishape.bitmask
4580                    I8X16_BITMASK => {
4581                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4582                        let lanes: [i8; 16] = to_lanes(data);
4583                        let bits = lanes.map(|lane| lane < 0);
4584                        let bitmask = bits
4585                            .into_iter()
4586                            .enumerate()
4587                            .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
4588                        stack.push_value(Value::I32(bitmask))?;
4589                    }
4590                    I16X8_BITMASK => {
4591                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4592                        let lanes: [i16; 8] = to_lanes(data);
4593                        let bits = lanes.map(|lane| lane < 0);
4594                        let bitmask = bits
4595                            .into_iter()
4596                            .enumerate()
4597                            .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
4598                        stack.push_value(Value::I32(bitmask))?;
4599                    }
4600                    I32X4_BITMASK => {
4601                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4602                        let lanes: [i32; 4] = to_lanes(data);
4603                        let bits = lanes.map(|lane| lane < 0);
4604                        let bitmask = bits
4605                            .into_iter()
4606                            .enumerate()
4607                            .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
4608                        stack.push_value(Value::I32(bitmask))?;
4609                    }
4610                    I64X2_BITMASK => {
4611                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4612                        let lanes: [i64; 2] = to_lanes(data);
4613                        let bits = lanes.map(|lane| lane < 0);
4614                        let bitmask = bits
4615                            .into_iter()
4616                            .enumerate()
4617                            .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
4618                        stack.push_value(Value::I32(bitmask))?;
4619                    }
4620
4621                    // ishape.dot_ishape_s
4622                    I32X4_DOT_I16X8_S => {
4623                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4624                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4625                        let lanes1: [i16; 8] = to_lanes(data1);
4626                        let lanes2: [i16; 8] = to_lanes(data2);
4627                        let multiplied: [i32; 8] = array::from_fn(|i| {
4628                            let v1 = lanes1[i] as i32;
4629                            let v2 = lanes2[i] as i32;
4630                            v1.wrapping_mul(v2)
4631                        });
4632                        let added: [i32; 4] = array::from_fn(|i| {
4633                            let v1 = multiplied[2 * i];
4634                            let v2 = multiplied[2 * i + 1];
4635                            v1.wrapping_add(v2)
4636                        });
4637                        stack.push_value(Value::V128(from_lanes(added)))?;
4638                    }
4639
4640                    // ishape.extmul_half_ishape_sx
4641                    I16X8_EXTMUL_HIGH_I8X16_S => {
4642                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4643                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4644                        let lanes1: [i8; 16] = to_lanes(data1);
4645                        let lanes2: [i8; 16] = to_lanes(data2);
4646                        let high_lanes1: [i8; 8] = lanes1[8..].try_into().unwrap();
4647                        let high_lanes2: [i8; 8] = lanes2[8..].try_into().unwrap();
4648                        let multiplied: [i16; 8] = array::from_fn(|i| {
4649                            let v1 = high_lanes1[i] as i16;
4650                            let v2 = high_lanes2[i] as i16;
4651                            v1.wrapping_mul(v2)
4652                        });
4653                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4654                    }
4655                    I16X8_EXTMUL_HIGH_I8X16_U => {
4656                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4657                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4658                        let lanes1: [u8; 16] = to_lanes(data1);
4659                        let lanes2: [u8; 16] = to_lanes(data2);
4660                        let high_lanes1: [u8; 8] = lanes1[8..].try_into().unwrap();
4661                        let high_lanes2: [u8; 8] = lanes2[8..].try_into().unwrap();
4662                        let multiplied: [u16; 8] = array::from_fn(|i| {
4663                            let v1 = high_lanes1[i] as u16;
4664                            let v2 = high_lanes2[i] as u16;
4665                            v1.wrapping_mul(v2)
4666                        });
4667                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4668                    }
4669                    I16X8_EXTMUL_LOW_I8X16_S => {
4670                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4671                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4672                        let lanes1: [i8; 16] = to_lanes(data1);
4673                        let lanes2: [i8; 16] = to_lanes(data2);
4674                        let high_lanes1: [i8; 8] = lanes1[..8].try_into().unwrap();
4675                        let high_lanes2: [i8; 8] = lanes2[..8].try_into().unwrap();
4676                        let multiplied: [i16; 8] = array::from_fn(|i| {
4677                            let v1 = high_lanes1[i] as i16;
4678                            let v2 = high_lanes2[i] as i16;
4679                            v1.wrapping_mul(v2)
4680                        });
4681                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4682                    }
4683                    I16X8_EXTMUL_LOW_I8X16_U => {
4684                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4685                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4686                        let lanes1: [u8; 16] = to_lanes(data1);
4687                        let lanes2: [u8; 16] = to_lanes(data2);
4688                        let high_lanes1: [u8; 8] = lanes1[..8].try_into().unwrap();
4689                        let high_lanes2: [u8; 8] = lanes2[..8].try_into().unwrap();
4690                        let multiplied: [u16; 8] = array::from_fn(|i| {
4691                            let v1 = high_lanes1[i] as u16;
4692                            let v2 = high_lanes2[i] as u16;
4693                            v1.wrapping_mul(v2)
4694                        });
4695                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4696                    }
4697                    I32X4_EXTMUL_HIGH_I16X8_S => {
4698                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4699                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4700                        let lanes1: [i16; 8] = to_lanes(data1);
4701                        let lanes2: [i16; 8] = to_lanes(data2);
4702                        let high_lanes1: [i16; 4] = lanes1[4..].try_into().unwrap();
4703                        let high_lanes2: [i16; 4] = lanes2[4..].try_into().unwrap();
4704                        let multiplied: [i32; 4] = array::from_fn(|i| {
4705                            let v1 = high_lanes1[i] as i32;
4706                            let v2 = high_lanes2[i] as i32;
4707                            v1.wrapping_mul(v2)
4708                        });
4709                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4710                    }
4711                    I32X4_EXTMUL_HIGH_I16X8_U => {
4712                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4713                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4714                        let lanes1: [u16; 8] = to_lanes(data1);
4715                        let lanes2: [u16; 8] = to_lanes(data2);
4716                        let high_lanes1: [u16; 4] = lanes1[4..].try_into().unwrap();
4717                        let high_lanes2: [u16; 4] = lanes2[4..].try_into().unwrap();
4718                        let multiplied: [u32; 4] = array::from_fn(|i| {
4719                            let v1 = high_lanes1[i] as u32;
4720                            let v2 = high_lanes2[i] as u32;
4721                            v1.wrapping_mul(v2)
4722                        });
4723                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4724                    }
4725                    I32X4_EXTMUL_LOW_I16X8_S => {
4726                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4727                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4728                        let lanes1: [i16; 8] = to_lanes(data1);
4729                        let lanes2: [i16; 8] = to_lanes(data2);
4730                        let high_lanes1: [i16; 4] = lanes1[..4].try_into().unwrap();
4731                        let high_lanes2: [i16; 4] = lanes2[..4].try_into().unwrap();
4732                        let multiplied: [i32; 4] = array::from_fn(|i| {
4733                            let v1 = high_lanes1[i] as i32;
4734                            let v2 = high_lanes2[i] as i32;
4735                            v1.wrapping_mul(v2)
4736                        });
4737                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4738                    }
4739                    I32X4_EXTMUL_LOW_I16X8_U => {
4740                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4741                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4742                        let lanes1: [u16; 8] = to_lanes(data1);
4743                        let lanes2: [u16; 8] = to_lanes(data2);
4744                        let high_lanes1: [u16; 4] = lanes1[..4].try_into().unwrap();
4745                        let high_lanes2: [u16; 4] = lanes2[..4].try_into().unwrap();
4746                        let multiplied: [u32; 4] = array::from_fn(|i| {
4747                            let v1 = high_lanes1[i] as u32;
4748                            let v2 = high_lanes2[i] as u32;
4749                            v1.wrapping_mul(v2)
4750                        });
4751                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4752                    }
4753                    I64X2_EXTMUL_HIGH_I32X4_S => {
4754                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4755                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4756                        let lanes1: [i32; 4] = to_lanes(data1);
4757                        let lanes2: [i32; 4] = to_lanes(data2);
4758                        let high_lanes1: [i32; 2] = lanes1[2..].try_into().unwrap();
4759                        let high_lanes2: [i32; 2] = lanes2[2..].try_into().unwrap();
4760                        let multiplied: [i64; 2] = array::from_fn(|i| {
4761                            let v1 = high_lanes1[i] as i64;
4762                            let v2 = high_lanes2[i] as i64;
4763                            v1.wrapping_mul(v2)
4764                        });
4765                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4766                    }
4767                    I64X2_EXTMUL_HIGH_I32X4_U => {
4768                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4769                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4770                        let lanes1: [u32; 4] = to_lanes(data1);
4771                        let lanes2: [u32; 4] = to_lanes(data2);
4772                        let high_lanes1: [u32; 2] = lanes1[2..].try_into().unwrap();
4773                        let high_lanes2: [u32; 2] = lanes2[2..].try_into().unwrap();
4774                        let multiplied: [u64; 2] = array::from_fn(|i| {
4775                            let v1 = high_lanes1[i] as u64;
4776                            let v2 = high_lanes2[i] as u64;
4777                            v1.wrapping_mul(v2)
4778                        });
4779                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4780                    }
4781                    I64X2_EXTMUL_LOW_I32X4_S => {
4782                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4783                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4784                        let lanes1: [i32; 4] = to_lanes(data1);
4785                        let lanes2: [i32; 4] = to_lanes(data2);
4786                        let high_lanes1: [i32; 2] = lanes1[..2].try_into().unwrap();
4787                        let high_lanes2: [i32; 2] = lanes2[..2].try_into().unwrap();
4788                        let multiplied: [i64; 2] = array::from_fn(|i| {
4789                            let v1 = high_lanes1[i] as i64;
4790                            let v2 = high_lanes2[i] as i64;
4791                            v1.wrapping_mul(v2)
4792                        });
4793                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4794                    }
4795                    I64X2_EXTMUL_LOW_I32X4_U => {
4796                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4797                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4798                        let lanes1: [u32; 4] = to_lanes(data1);
4799                        let lanes2: [u32; 4] = to_lanes(data2);
4800                        let high_lanes1: [u32; 2] = lanes1[..2].try_into().unwrap();
4801                        let high_lanes2: [u32; 2] = lanes2[..2].try_into().unwrap();
4802                        let multiplied: [u64; 2] = array::from_fn(|i| {
4803                            let v1 = high_lanes1[i] as u64;
4804                            let v2 = high_lanes2[i] as u64;
4805                            v1.wrapping_mul(v2)
4806                        });
4807                        stack.push_value(Value::V128(from_lanes(multiplied)))?;
4808                    }
4809
4810                    // ishape.extadd_pairwise_ishape_sx
4811                    I16X8_EXTADD_PAIRWISE_I8X16_S => {
4812                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4813                        let lanes: [i8; 16] = to_lanes(data);
4814                        let added_pairwise: [i16; 8] = array::from_fn(|i| {
4815                            let v1 = lanes[2 * i] as i16;
4816                            let v2 = lanes[2 * i + 1] as i16;
4817                            v1.wrapping_add(v2)
4818                        });
4819                        stack.push_value(Value::V128(from_lanes(added_pairwise)))?;
4820                    }
4821                    I16X8_EXTADD_PAIRWISE_I8X16_U => {
4822                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4823                        let lanes: [u8; 16] = to_lanes(data);
4824                        let added_pairwise: [u16; 8] = array::from_fn(|i| {
4825                            let v1 = lanes[2 * i] as u16;
4826                            let v2 = lanes[2 * i + 1] as u16;
4827                            v1.wrapping_add(v2)
4828                        });
4829                        stack.push_value(Value::V128(from_lanes(added_pairwise)))?;
4830                    }
4831                    I32X4_EXTADD_PAIRWISE_I16X8_S => {
4832                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4833                        let lanes: [i16; 8] = to_lanes(data);
4834                        let added_pairwise: [i32; 4] = array::from_fn(|i| {
4835                            let v1 = lanes[2 * i] as i32;
4836                            let v2 = lanes[2 * i + 1] as i32;
4837                            v1.wrapping_add(v2)
4838                        });
4839                        stack.push_value(Value::V128(from_lanes(added_pairwise)))?;
4840                    }
4841                    I32X4_EXTADD_PAIRWISE_I16X8_U => {
4842                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4843                        let lanes: [u16; 8] = to_lanes(data);
4844                        let added_pairwise: [u32; 4] = array::from_fn(|i| {
4845                            let v1 = lanes[2 * i] as u32;
4846                            let v2 = lanes[2 * i + 1] as u32;
4847                            v1.wrapping_add(v2)
4848                        });
4849                        stack.push_value(Value::V128(from_lanes(added_pairwise)))?;
4850                    }
4851
4852                    // Unimplemented or invalid instructions
4853                    F32X4_RELAXED_MADD
4854                    | F32X4_RELAXED_MAX
4855                    | F32X4_RELAXED_MIN
4856                    | F32X4_RELAXED_NMADD
4857                    | F64X2_RELAXED_MADD
4858                    | F64X2_RELAXED_MAX
4859                    | F64X2_RELAXED_MIN
4860                    | F64X2_RELAXED_NMADD
4861                    | I16X8_RELAXED_LANESELECT
4862                    | I32X4_RELAXED_LANESELECT
4863                    | I32X4_RELAXED_TRUNC_F32X4_S
4864                    | I32X4_RELAXED_TRUNC_F32X4_U
4865                    | I32X4_RELAXED_TRUNC_F64X2_S_ZERO
4866                    | I32X4_RELAXED_TRUNC_F64X2_U_ZERO
4867                    | I64X2_RELAXED_LANESELECT
4868                    | I8X16_RELAXED_LANESELECT
4869                    | I8X16_RELAXED_SWIZZLE
4870                    | 154
4871                    | 187
4872                    | 194
4873                    | 256.. => unreachable_validated!(),
4874                }
4875            }
4876
4877            // Unimplemented or invalid instructions
4878            0x06..=0x0A
4879            | 0x12..=0x19
4880            | 0x1C..=0x1F
4881            | 0x25..=0x27
4882            | 0xC0..=0xFA
4883            | 0xFB
4884            | 0xFE
4885            | 0xFF => {
4886                unreachable_validated!();
4887            }
4888        }
4889    }
4890    Ok(())
4891}
4892
4893//helper function for avoiding code duplication at intraprocedural jumps
4894fn do_sidetable_control_transfer(
4895    wasm: &mut WasmReader,
4896    stack: &mut Stack,
4897    current_stp: &mut usize,
4898    current_sidetable: &Sidetable,
4899) -> Result<(), RuntimeError> {
4900    let sidetable_entry = &current_sidetable[*current_stp];
4901
4902    stack.remove_in_between(sidetable_entry.popcnt, sidetable_entry.valcnt);
4903
4904    *current_stp = (*current_stp as isize + sidetable_entry.delta_stp) as usize;
4905    wasm.pc = (wasm.pc as isize + sidetable_entry.delta_pc) as usize;
4906
4907    Ok(())
4908}
4909
4910#[inline(always)]
4911fn calculate_mem_address(memarg: &MemArg, relative_address: u32) -> Result<usize, RuntimeError> {
4912    memarg
4913        .offset
4914        // The spec states that this should be a 33 bit integer, e.g. it is not legal to wrap if the
4915        // sum of offset and relative_address exceeds u32::MAX. To emulate this behavior, we use a
4916        // checked addition.
4917        // See: https://webassembly.github.io/spec/core/syntax/instructions.html#memory-instructions
4918        .checked_add(relative_address)
4919        .ok_or(TrapError::MemoryOrDataAccessOutOfBounds)?
4920        .try_into()
4921        .map_err(|_| TrapError::MemoryOrDataAccessOutOfBounds.into())
4922}
4923
4924//helpers for avoiding code duplication during module instantiation
4925#[inline(always)]
4926#[allow(clippy::too_many_arguments)]
4927pub(super) fn table_init(
4928    store_modules: &[ModuleInst],
4929    store_tables: &mut [TableInst],
4930    store_elements: &[ElemInst],
4931    current_module_idx: usize,
4932    elem_idx: usize,
4933    table_idx: usize,
4934    n: i32,
4935    s: i32,
4936    d: i32,
4937) -> Result<(), RuntimeError> {
4938    let tab_addr = *store_modules[current_module_idx]
4939        .table_addrs
4940        .get(table_idx)
4941        .unwrap_validated();
4942    let tab = &mut store_tables[tab_addr];
4943
4944    let elem_addr = *store_modules[current_module_idx]
4945        .elem_addrs
4946        .get(elem_idx)
4947        .unwrap_validated();
4948    let elem = &store_elements[elem_addr];
4949
4950    trace!(
4951        "Instruction: table.init '{}' '{}' [{} {} {}] -> []",
4952        elem_idx,
4953        table_idx,
4954        d,
4955        s,
4956        n
4957    );
4958
4959    let final_src_offset = (s as usize)
4960        .checked_add(n as usize)
4961        .filter(|&res| res <= elem.len())
4962        .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
4963
4964    if (d as usize)
4965        .checked_add(n as usize)
4966        .filter(|&res| res <= tab.len())
4967        .is_none()
4968    {
4969        return Err(TrapError::TableOrElementAccessOutOfBounds.into());
4970    }
4971
4972    let dest = &mut tab.elem[d as usize..];
4973    let src = &elem.references[s as usize..final_src_offset];
4974    dest[..src.len()].copy_from_slice(src);
4975    Ok(())
4976}
4977
4978#[inline(always)]
4979pub(super) fn elem_drop(
4980    store_modules: &[ModuleInst],
4981    store_elements: &mut [ElemInst],
4982    current_module_idx: usize,
4983    elem_idx: usize,
4984) -> Result<(), RuntimeError> {
4985    // WARN: i'm not sure if this is okay or not
4986    let elem_addr = *store_modules[current_module_idx]
4987        .elem_addrs
4988        .get(elem_idx)
4989        .unwrap_validated();
4990    store_elements[elem_addr].references.clear();
4991    Ok(())
4992}
4993
4994#[inline(always)]
4995#[allow(clippy::too_many_arguments)]
4996pub(super) fn memory_init(
4997    store_modules: &[ModuleInst],
4998    store_memories: &mut [MemInst],
4999    store_data: &[DataInst],
5000    current_module_idx: usize,
5001    data_idx: usize,
5002    mem_idx: usize,
5003    n: i32,
5004    s: i32,
5005    d: i32,
5006) -> Result<(), RuntimeError> {
5007    let mem_addr = *store_modules[current_module_idx]
5008        .mem_addrs
5009        .get(mem_idx)
5010        .unwrap_validated();
5011    let mem = &store_memories[mem_addr];
5012
5013    mem.mem.init(
5014        d as MemIdx,
5015        &store_data[store_modules[current_module_idx].data_addrs[data_idx]].data,
5016        s as MemIdx,
5017        n as MemIdx,
5018    )?;
5019
5020    trace!("Instruction: memory.init");
5021    Ok(())
5022}
5023
5024#[inline(always)]
5025pub(super) fn data_drop(
5026    store_modules: &[ModuleInst],
5027    store_data: &mut [DataInst],
5028    current_module_idx: usize,
5029    data_idx: usize,
5030) -> Result<(), RuntimeError> {
5031    // Here is debatable
5032    // If we were to be on par with the spec we'd have to use a DataInst struct
5033    // But since memory.init is specifically made for Passive data segments
5034    // I thought that using DataMode would be better because we can see if the
5035    // data segment is passive or active
5036
5037    // Also, we should set data to null here (empty), which we do using an empty init vec
5038    let data_addr = *store_modules[current_module_idx]
5039        .data_addrs
5040        .get(data_idx)
5041        .unwrap_validated();
5042    store_data[data_addr] = DataInst { data: Vec::new() };
5043    Ok(())
5044}
5045
5046#[inline(always)]
5047fn to_lanes<const M: usize, const N: usize, T: LittleEndianBytes<M>>(data: [u8; 16]) -> [T; N] {
5048    assert_eq!(M * N, 16);
5049
5050    let mut lanes = data
5051        .chunks(M)
5052        .map(|chunk| T::from_le_bytes(chunk.try_into().unwrap()));
5053    array::from_fn(|_| lanes.next().unwrap())
5054}
5055
5056#[inline(always)]
5057fn from_lanes<const M: usize, const N: usize, T: LittleEndianBytes<M>>(lanes: [T; N]) -> [u8; 16] {
5058    assert_eq!(M * N, 16);
5059
5060    let mut bytes = lanes.into_iter().flat_map(T::to_le_bytes);
5061    array::from_fn(|_| bytes.next().unwrap())
5062}