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