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::NonZeroU64,
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, TableIdx, TypeIdx},
23        reader::{
24            types::{memarg::MemArg, BlockType},
25            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<NonZeroU64>, 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(NonZeroU64::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 Some((maybe_return_func_addr, maybe_return_address, maybe_return_stp)) =
119                    stack.pop_call_frame()
120                else {
121                    // We finished this entire invocation if this was the base call frame.
122                    break;
123                };
124                // If there are one or more call frames, we need to continue
125                // from where the callee was called from.
126
127                trace!("end of function reached, returning to previous call frame");
128                current_func_addr = maybe_return_func_addr;
129                let FuncInst::WasmFunc(current_wasm_func_inst) =
130                    store.functions.get(current_func_addr)
131                else {
132                    unreachable!("function addresses on the stack always correspond to native wasm functions")
133                };
134                current_module = current_wasm_func_inst.module_addr;
135                wasm.full_wasm_binary = store.modules.get(current_module).wasm_bytecode;
136                wasm.pc = maybe_return_address;
137                stp = maybe_return_stp;
138
139                current_sidetable = &store.modules.get(current_module).sidetable;
140
141                current_function_end_marker = current_wasm_func_inst.code_expr.from()
142                    + current_wasm_func_inst.code_expr.len();
143
144                trace!("Instruction: END");
145            }
146            IF => {
147                decrement_fuel!(T::get_flat_cost(IF));
148                wasm.read_var_u32().unwrap_validated();
149
150                let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
151
152                if test_val != 0 {
153                    stp += 1;
154                } else {
155                    do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
156                }
157                trace!("Instruction: IF");
158            }
159            ELSE => {
160                decrement_fuel!(T::get_flat_cost(ELSE));
161                do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
162            }
163            BR_IF => {
164                decrement_fuel!(T::get_flat_cost(BR_IF));
165                wasm.read_var_u32().unwrap_validated();
166
167                let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
168
169                if test_val != 0 {
170                    do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
171                } else {
172                    stp += 1;
173                }
174                trace!("Instruction: BR_IF");
175            }
176            BR_TABLE => {
177                decrement_fuel!(T::get_flat_cost(BR_TABLE));
178                let label_vec = wasm
179                    .read_vec(|wasm| wasm.read_var_u32().map(|v| v as LabelIdx))
180                    .unwrap_validated();
181                wasm.read_var_u32().unwrap_validated();
182
183                // TODO is this correct?
184                let case_val_i32: i32 = stack.pop_value().try_into().unwrap_validated();
185                let case_val = case_val_i32 as usize;
186
187                if case_val >= label_vec.len() {
188                    stp += label_vec.len();
189                } else {
190                    stp += case_val;
191                }
192
193                do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
194            }
195            BR => {
196                decrement_fuel!(T::get_flat_cost(BR));
197                //skip n of BR n
198                wasm.read_var_u32().unwrap_validated();
199                do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
200            }
201            BLOCK => {
202                decrement_fuel!(T::get_flat_cost(BLOCK));
203                BlockType::read(wasm).unwrap_validated();
204            }
205            LOOP => {
206                decrement_fuel!(T::get_flat_cost(LOOP));
207                BlockType::read(wasm).unwrap_validated();
208            }
209            RETURN => {
210                decrement_fuel!(T::get_flat_cost(RETURN));
211                //same as BR, except no need to skip n of BR n
212                do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
213            }
214            CALL => {
215                decrement_fuel!(T::get_flat_cost(CALL));
216                let local_func_idx = wasm.read_var_u32().unwrap_validated() as FuncIdx;
217                let FuncInst::WasmFunc(current_wasm_func_inst) =
218                    store.functions.get(current_func_addr)
219                else {
220                    unreachable!()
221                };
222
223                let func_to_call_addr = store
224                    .modules
225                    .get(current_wasm_func_inst.module_addr)
226                    .func_addrs[local_func_idx];
227
228                let func_to_call_ty = store.functions.get(func_to_call_addr).ty();
229
230                trace!("Instruction: call [{func_to_call_addr:?}]");
231
232                match store.functions.get(func_to_call_addr) {
233                    FuncInst::HostFunc(host_func_to_call_inst) => {
234                        let params = stack
235                            .pop_tail_iter(func_to_call_ty.params.valtypes.len())
236                            .collect();
237                        let returns =
238                            (host_func_to_call_inst.hostcode)(&mut store.user_data, params);
239
240                        let returns = returns.map_err(|HaltExecutionError| {
241                            RuntimeError::HostFunctionHaltedExecution
242                        })?;
243
244                        // Verify that the return parameters match the host function parameters
245                        // since we have no validation guarantees for host functions
246                        if returns.len() != func_to_call_ty.returns.valtypes.len() {
247                            return Err(RuntimeError::HostFunctionSignatureMismatch);
248                        }
249                        for (value, ty) in zip(returns, func_to_call_ty.returns.valtypes) {
250                            if value.to_ty() != ty {
251                                return Err(RuntimeError::HostFunctionSignatureMismatch);
252                            }
253                            stack.push_value::<T>(value)?;
254                        }
255                    }
256                    FuncInst::WasmFunc(wasm_func_to_call_inst) => {
257                        let remaining_locals = &wasm_func_to_call_inst.locals;
258
259                        stack.push_call_frame::<T>(
260                            current_func_addr,
261                            &func_to_call_ty,
262                            remaining_locals,
263                            wasm.pc,
264                            stp,
265                        )?;
266
267                        current_func_addr = func_to_call_addr;
268                        current_module = wasm_func_to_call_inst.module_addr;
269                        wasm.full_wasm_binary = store.modules.get(current_module).wasm_bytecode;
270                        wasm.move_start_to(wasm_func_to_call_inst.code_expr)
271                            .expect("code expression spans to always be valid");
272
273                        stp = wasm_func_to_call_inst.stp;
274                        current_sidetable = &store.modules.get(current_module).sidetable;
275                        current_function_end_marker = wasm_func_to_call_inst.code_expr.from()
276                            + wasm_func_to_call_inst.code_expr.len();
277                    }
278                }
279                trace!("Instruction: CALL");
280            }
281
282            // TODO: fix push_call_frame, because the func idx that you get from the table is global func idx
283            CALL_INDIRECT => {
284                decrement_fuel!(T::get_flat_cost(CALL_INDIRECT));
285                let given_type_idx = wasm.read_var_u32().unwrap_validated() as TypeIdx;
286                let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx;
287
288                let table_addr = *store
289                    .modules
290                    .get(current_module)
291                    .table_addrs
292                    .get(table_idx)
293                    .unwrap_validated();
294                let tab = store.tables.get(table_addr);
295                let func_ty = store
296                    .modules
297                    .get(current_module)
298                    .types
299                    .get(given_type_idx)
300                    .unwrap_validated();
301
302                let i: u32 = stack.pop_value().try_into().unwrap_validated();
303
304                let r = tab
305                    .elem
306                    .get(i as usize)
307                    .ok_or(TrapError::TableAccessOutOfBounds)
308                    .and_then(|r| {
309                        if matches!(r, Ref::Null(_)) {
310                            trace!("table_idx ({table_idx}) --- element index in table ({i})");
311                            Err(TrapError::UninitializedElement)
312                        } else {
313                            Ok(r)
314                        }
315                    })?;
316
317                let func_to_call_addr = match *r {
318                    Ref::Func(func_addr) => func_addr,
319                    Ref::Null(_) => return Err(TrapError::IndirectCallNullFuncRef.into()),
320                    Ref::Extern(_) => unreachable_validated!(),
321                };
322
323                let func_to_call_ty = store.functions.get(func_to_call_addr).ty();
324                if *func_ty != func_to_call_ty {
325                    return Err(TrapError::SignatureMismatch.into());
326                }
327
328                trace!("Instruction: call [{func_to_call_addr:?}]");
329
330                match store.functions.get(func_to_call_addr) {
331                    FuncInst::HostFunc(host_func_to_call_inst) => {
332                        let params = stack
333                            .pop_tail_iter(func_to_call_ty.params.valtypes.len())
334                            .collect();
335                        let returns =
336                            (host_func_to_call_inst.hostcode)(&mut store.user_data, params);
337
338                        let returns = returns.map_err(|HaltExecutionError| {
339                            RuntimeError::HostFunctionHaltedExecution
340                        })?;
341
342                        // Verify that the return parameters match the host function parameters
343                        // since we have no validation guarantees for host functions
344                        if returns.len() != func_to_call_ty.returns.valtypes.len() {
345                            return Err(RuntimeError::HostFunctionSignatureMismatch);
346                        }
347                        for (value, ty) in zip(returns, func_to_call_ty.returns.valtypes) {
348                            if value.to_ty() != ty {
349                                return Err(RuntimeError::HostFunctionSignatureMismatch);
350                            }
351                            stack.push_value::<T>(value)?;
352                        }
353                    }
354                    FuncInst::WasmFunc(wasm_func_to_call_inst) => {
355                        let remaining_locals = &wasm_func_to_call_inst.locals;
356
357                        stack.push_call_frame::<T>(
358                            current_func_addr,
359                            &func_to_call_ty,
360                            remaining_locals,
361                            wasm.pc,
362                            stp,
363                        )?;
364
365                        current_func_addr = func_to_call_addr;
366                        current_module = wasm_func_to_call_inst.module_addr;
367                        wasm.full_wasm_binary = store.modules.get(current_module).wasm_bytecode;
368                        wasm.move_start_to(wasm_func_to_call_inst.code_expr)
369                            .expect("code expression spans to always be valid");
370
371                        stp = wasm_func_to_call_inst.stp;
372                        current_sidetable = &store.modules.get(current_module).sidetable;
373                        current_function_end_marker = wasm_func_to_call_inst.code_expr.from()
374                            + wasm_func_to_call_inst.code_expr.len();
375                    }
376                }
377                trace!("Instruction: CALL_INDIRECT");
378            }
379            DROP => {
380                decrement_fuel!(T::get_flat_cost(DROP));
381                stack.pop_value();
382                trace!("Instruction: DROP");
383            }
384            SELECT => {
385                decrement_fuel!(T::get_flat_cost(SELECT));
386                let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
387                let val2 = stack.pop_value();
388                let val1 = stack.pop_value();
389                if test_val != 0 {
390                    stack.push_value::<T>(val1)?;
391                } else {
392                    stack.push_value::<T>(val2)?;
393                }
394                trace!("Instruction: SELECT");
395            }
396            SELECT_T => {
397                decrement_fuel!(T::get_flat_cost(SELECT_T));
398                let _type_vec = wasm.read_vec(ValType::read).unwrap_validated();
399                let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
400                let val2 = stack.pop_value();
401                let val1 = stack.pop_value();
402                if test_val != 0 {
403                    stack.push_value::<T>(val1)?;
404                } else {
405                    stack.push_value::<T>(val2)?;
406                }
407                trace!("Instruction: SELECT_T");
408            }
409            LOCAL_GET => {
410                decrement_fuel!(T::get_flat_cost(LOCAL_GET));
411                let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx;
412                let value = *stack.get_local(local_idx);
413                stack.push_value::<T>(value)?;
414                trace!("Instruction: local.get {} [] -> [t]", local_idx);
415            }
416            LOCAL_SET => {
417                decrement_fuel!(T::get_flat_cost(LOCAL_SET));
418                let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx;
419                let value = stack.pop_value();
420                *stack.get_local_mut(local_idx) = value;
421                trace!("Instruction: local.set {} [t] -> []", local_idx);
422            }
423            LOCAL_TEE => {
424                decrement_fuel!(T::get_flat_cost(LOCAL_TEE));
425                let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx;
426                let value = stack.peek_value().unwrap_validated();
427                *stack.get_local_mut(local_idx) = value;
428                trace!("Instruction: local.tee {} [t] -> [t]", local_idx);
429            }
430            GLOBAL_GET => {
431                decrement_fuel!(T::get_flat_cost(GLOBAL_GET));
432                let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx;
433                let global_addr = *store
434                    .modules
435                    .get(current_module)
436                    .global_addrs
437                    .get(global_idx)
438                    .unwrap_validated();
439                let global = store.globals.get(global_addr);
440
441                stack.push_value::<T>(global.value)?;
442
443                trace!(
444                    "Instruction: global.get '{}' [<GLOBAL>] -> [{:?}]",
445                    global_idx,
446                    global.value
447                );
448            }
449            GLOBAL_SET => {
450                decrement_fuel!(T::get_flat_cost(GLOBAL_SET));
451                let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx;
452                let global_addr = *store
453                    .modules
454                    .get(current_module)
455                    .global_addrs
456                    .get(global_idx)
457                    .unwrap_validated();
458                let global = store.globals.get_mut(global_addr);
459                global.value = stack.pop_value();
460                trace!("Instruction: GLOBAL_SET");
461            }
462            TABLE_GET => {
463                decrement_fuel!(T::get_flat_cost(TABLE_GET));
464                let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx;
465                let table_addr = *store
466                    .modules
467                    .get(current_module)
468                    .table_addrs
469                    .get(table_idx)
470                    .unwrap_validated();
471                let tab = store.tables.get(table_addr);
472
473                let i: i32 = stack.pop_value().try_into().unwrap_validated();
474
475                let val = tab
476                    .elem
477                    .get(i as usize)
478                    .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
479
480                stack.push_value::<T>((*val).into())?;
481                trace!(
482                    "Instruction: table.get '{}' [{}] -> [{}]",
483                    table_idx,
484                    i,
485                    val
486                );
487            }
488            TABLE_SET => {
489                decrement_fuel!(T::get_flat_cost(TABLE_SET));
490                let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx;
491                let table_addr = *store
492                    .modules
493                    .get(current_module)
494                    .table_addrs
495                    .get(table_idx)
496                    .unwrap_validated();
497                let tab = store.tables.get_mut(table_addr);
498
499                let val: Ref = stack.pop_value().try_into().unwrap_validated();
500                let i: i32 = stack.pop_value().try_into().unwrap_validated();
501
502                tab.elem
503                    .get_mut(i as usize)
504                    .ok_or(TrapError::TableOrElementAccessOutOfBounds)
505                    .map(|r| *r = val)?;
506                trace!(
507                    "Instruction: table.set '{}' [{} {}] -> []",
508                    table_idx,
509                    i,
510                    val
511                )
512            }
513            UNREACHABLE => {
514                return Err(TrapError::ReachedUnreachable.into());
515            }
516            I32_LOAD => {
517                decrement_fuel!(T::get_flat_cost(I32_LOAD));
518                let memarg = MemArg::read(wasm).unwrap_validated();
519                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
520
521                let mem_addr = *store
522                    .modules
523                    .get(current_module)
524                    .mem_addrs
525                    .first()
526                    .unwrap_validated();
527                let mem_inst = store.memories.get(mem_addr);
528
529                let idx = calculate_mem_address(&memarg, relative_address)?;
530                let data = mem_inst.mem.load(idx)?;
531
532                stack.push_value::<T>(Value::I32(data))?;
533                trace!("Instruction: i32.load [{relative_address}] -> [{data}]");
534            }
535            I64_LOAD => {
536                decrement_fuel!(T::get_flat_cost(I64_LOAD));
537                let memarg = MemArg::read(wasm).unwrap_validated();
538                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
539
540                let mem_addr = *store
541                    .modules
542                    .get(current_module)
543                    .mem_addrs
544                    .first()
545                    .unwrap_validated();
546                let mem = store.memories.get(mem_addr);
547
548                let idx = calculate_mem_address(&memarg, relative_address)?;
549                let data = mem.mem.load(idx)?;
550
551                stack.push_value::<T>(Value::I64(data))?;
552                trace!("Instruction: i64.load [{relative_address}] -> [{data}]");
553            }
554            F32_LOAD => {
555                decrement_fuel!(T::get_flat_cost(F32_LOAD));
556                let memarg = MemArg::read(wasm).unwrap_validated();
557                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
558
559                let mem_addr = *store
560                    .modules
561                    .get(current_module)
562                    .mem_addrs
563                    .first()
564                    .unwrap_validated();
565                let mem = store.memories.get(mem_addr);
566
567                let idx = calculate_mem_address(&memarg, relative_address)?;
568                let data = mem.mem.load(idx)?;
569
570                stack.push_value::<T>(Value::F32(data))?;
571                trace!("Instruction: f32.load [{relative_address}] -> [{data}]");
572            }
573            F64_LOAD => {
574                decrement_fuel!(T::get_flat_cost(F64_LOAD));
575                let memarg = MemArg::read(wasm).unwrap_validated();
576                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
577
578                let mem_addr = *store
579                    .modules
580                    .get(current_module)
581                    .mem_addrs
582                    .first()
583                    .unwrap_validated();
584                let mem = store.memories.get(mem_addr);
585
586                let idx = calculate_mem_address(&memarg, relative_address)?;
587                let data = mem.mem.load(idx)?;
588
589                stack.push_value::<T>(Value::F64(data))?;
590                trace!("Instruction: f64.load [{relative_address}] -> [{data}]");
591            }
592            I32_LOAD8_S => {
593                decrement_fuel!(T::get_flat_cost(I32_LOAD8_S));
594                let memarg = MemArg::read(wasm).unwrap_validated();
595                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
596
597                let mem_addr = *store
598                    .modules
599                    .get(current_module)
600                    .mem_addrs
601                    .first()
602                    .unwrap_validated();
603                let mem = store.memories.get(mem_addr);
604
605                let idx = calculate_mem_address(&memarg, relative_address)?;
606                let data: i8 = mem.mem.load(idx)?;
607
608                stack.push_value::<T>(Value::I32(data as u32))?;
609                trace!("Instruction: i32.load8_s [{relative_address}] -> [{data}]");
610            }
611            I32_LOAD8_U => {
612                decrement_fuel!(T::get_flat_cost(I32_LOAD8_U));
613                let memarg = MemArg::read(wasm).unwrap_validated();
614                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
615
616                let mem_addr = *store
617                    .modules
618                    .get(current_module)
619                    .mem_addrs
620                    .first()
621                    .unwrap_validated();
622                let mem = store.memories.get(mem_addr);
623
624                let idx = calculate_mem_address(&memarg, relative_address)?;
625                let data: u8 = mem.mem.load(idx)?;
626
627                stack.push_value::<T>(Value::I32(data as u32))?;
628                trace!("Instruction: i32.load8_u [{relative_address}] -> [{data}]");
629            }
630            I32_LOAD16_S => {
631                decrement_fuel!(T::get_flat_cost(I32_LOAD16_S));
632                let memarg = MemArg::read(wasm).unwrap_validated();
633                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
634
635                let mem_addr = *store
636                    .modules
637                    .get(current_module)
638                    .mem_addrs
639                    .first()
640                    .unwrap_validated();
641                let mem = store.memories.get(mem_addr);
642
643                let idx = calculate_mem_address(&memarg, relative_address)?;
644                let data: i16 = mem.mem.load(idx)?;
645
646                stack.push_value::<T>(Value::I32(data as u32))?;
647                trace!("Instruction: i32.load16_s [{relative_address}] -> [{data}]");
648            }
649            I32_LOAD16_U => {
650                decrement_fuel!(T::get_flat_cost(I32_LOAD16_U));
651                let memarg = MemArg::read(wasm).unwrap_validated();
652                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
653
654                let mem_addr = *store
655                    .modules
656                    .get(current_module)
657                    .mem_addrs
658                    .first()
659                    .unwrap_validated();
660                let mem = store.memories.get(mem_addr);
661
662                let idx = calculate_mem_address(&memarg, relative_address)?;
663                let data: u16 = mem.mem.load(idx)?;
664
665                stack.push_value::<T>(Value::I32(data as u32))?;
666                trace!("Instruction: i32.load16_u [{relative_address}] -> [{data}]");
667            }
668            I64_LOAD8_S => {
669                decrement_fuel!(T::get_flat_cost(I64_LOAD8_S));
670                let memarg = MemArg::read(wasm).unwrap_validated();
671                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
672
673                let mem_addr = *store
674                    .modules
675                    .get(current_module)
676                    .mem_addrs
677                    .first()
678                    .unwrap_validated();
679                let mem = store.memories.get(mem_addr);
680
681                let idx = calculate_mem_address(&memarg, relative_address)?;
682                let data: i8 = mem.mem.load(idx)?;
683
684                stack.push_value::<T>(Value::I64(data as u64))?;
685                trace!("Instruction: i64.load8_s [{relative_address}] -> [{data}]");
686            }
687            I64_LOAD8_U => {
688                decrement_fuel!(T::get_flat_cost(I64_LOAD8_U));
689                let memarg = MemArg::read(wasm).unwrap_validated();
690                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
691
692                let mem_addr = *store
693                    .modules
694                    .get(current_module)
695                    .mem_addrs
696                    .first()
697                    .unwrap_validated();
698                let mem = store.memories.get(mem_addr);
699
700                let idx = calculate_mem_address(&memarg, relative_address)?;
701                let data: u8 = mem.mem.load(idx)?;
702
703                stack.push_value::<T>(Value::I64(data as u64))?;
704                trace!("Instruction: i64.load8_u [{relative_address}] -> [{data}]");
705            }
706            I64_LOAD16_S => {
707                decrement_fuel!(T::get_flat_cost(I64_LOAD16_S));
708                let memarg = MemArg::read(wasm).unwrap_validated();
709                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
710
711                let mem_addr = *store
712                    .modules
713                    .get(current_module)
714                    .mem_addrs
715                    .first()
716                    .unwrap_validated();
717                let mem = store.memories.get(mem_addr);
718
719                let idx = calculate_mem_address(&memarg, relative_address)?;
720                let data: i16 = mem.mem.load(idx)?;
721
722                stack.push_value::<T>(Value::I64(data as u64))?;
723                trace!("Instruction: i64.load16_s [{relative_address}] -> [{data}]");
724            }
725            I64_LOAD16_U => {
726                decrement_fuel!(T::get_flat_cost(I64_LOAD16_U));
727                let memarg = MemArg::read(wasm).unwrap_validated();
728                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
729
730                let mem_addr = *store
731                    .modules
732                    .get(current_module)
733                    .mem_addrs
734                    .first()
735                    .unwrap_validated();
736                let mem = store.memories.get(mem_addr);
737
738                let idx = calculate_mem_address(&memarg, relative_address)?;
739                let data: u16 = mem.mem.load(idx)?;
740
741                stack.push_value::<T>(Value::I64(data as u64))?;
742                trace!("Instruction: i64.load16_u [{relative_address}] -> [{data}]");
743            }
744            I64_LOAD32_S => {
745                decrement_fuel!(T::get_flat_cost(I64_LOAD32_S));
746                let memarg = MemArg::read(wasm).unwrap_validated();
747                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
748
749                let mem_addr = *store
750                    .modules
751                    .get(current_module)
752                    .mem_addrs
753                    .first()
754                    .unwrap_validated();
755                let mem = store.memories.get(mem_addr);
756
757                let idx = calculate_mem_address(&memarg, relative_address)?;
758                let data: i32 = mem.mem.load(idx)?;
759
760                stack.push_value::<T>(Value::I64(data as u64))?;
761                trace!("Instruction: i64.load32_s [{relative_address}] -> [{data}]");
762            }
763            I64_LOAD32_U => {
764                decrement_fuel!(T::get_flat_cost(I64_LOAD32_U));
765                let memarg = MemArg::read(wasm).unwrap_validated();
766                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
767
768                let mem_addr = *store
769                    .modules
770                    .get(current_module)
771                    .mem_addrs
772                    .first()
773                    .unwrap_validated();
774                let mem = store.memories.get(mem_addr);
775
776                let idx = calculate_mem_address(&memarg, relative_address)?;
777                let data: u32 = mem.mem.load(idx)?;
778
779                stack.push_value::<T>(Value::I64(data as u64))?;
780                trace!("Instruction: i64.load32_u [{relative_address}] -> [{data}]");
781            }
782            I32_STORE => {
783                decrement_fuel!(T::get_flat_cost(I32_STORE));
784                let memarg = MemArg::read(wasm).unwrap_validated();
785
786                let data_to_store: u32 = stack.pop_value().try_into().unwrap_validated();
787                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
788
789                let mem_addr = *store
790                    .modules
791                    .get(current_module)
792                    .mem_addrs
793                    .first()
794                    .unwrap_validated();
795                let mem = store.memories.get(mem_addr);
796
797                let idx = calculate_mem_address(&memarg, relative_address)?;
798                mem.mem.store(idx, data_to_store)?;
799
800                trace!("Instruction: i32.store [{relative_address} {data_to_store}] -> []");
801            }
802            I64_STORE => {
803                decrement_fuel!(T::get_flat_cost(I64_STORE));
804                let memarg = MemArg::read(wasm).unwrap_validated();
805
806                let data_to_store: u64 = stack.pop_value().try_into().unwrap_validated();
807                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
808
809                let mem_addr = *store
810                    .modules
811                    .get(current_module)
812                    .mem_addrs
813                    .first()
814                    .unwrap_validated();
815                let mem = store.memories.get(mem_addr);
816
817                let idx = calculate_mem_address(&memarg, relative_address)?;
818                mem.mem.store(idx, data_to_store)?;
819
820                trace!("Instruction: i64.store [{relative_address} {data_to_store}] -> []");
821            }
822            F32_STORE => {
823                decrement_fuel!(T::get_flat_cost(F32_STORE));
824                let memarg = MemArg::read(wasm).unwrap_validated();
825
826                let data_to_store: F32 = stack.pop_value().try_into().unwrap_validated();
827                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
828
829                let mem_addr = *store
830                    .modules
831                    .get(current_module)
832                    .mem_addrs
833                    .first()
834                    .unwrap_validated();
835                let mem = store.memories.get(mem_addr);
836
837                let idx = calculate_mem_address(&memarg, relative_address)?;
838                mem.mem.store(idx, data_to_store)?;
839
840                trace!("Instruction: f32.store [{relative_address} {data_to_store}] -> []");
841            }
842            F64_STORE => {
843                decrement_fuel!(T::get_flat_cost(F64_STORE));
844                let memarg = MemArg::read(wasm).unwrap_validated();
845
846                let data_to_store: F64 = stack.pop_value().try_into().unwrap_validated();
847                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
848
849                let mem_addr = *store
850                    .modules
851                    .get(current_module)
852                    .mem_addrs
853                    .first()
854                    .unwrap_validated();
855                let mem = store.memories.get(mem_addr);
856
857                let idx = calculate_mem_address(&memarg, relative_address)?;
858                mem.mem.store(idx, data_to_store)?;
859
860                trace!("Instruction: f64.store [{relative_address} {data_to_store}] -> []");
861            }
862            I32_STORE8 => {
863                decrement_fuel!(T::get_flat_cost(I32_STORE8));
864                let memarg = MemArg::read(wasm).unwrap_validated();
865
866                let data_to_store: i32 = stack.pop_value().try_into().unwrap_validated();
867                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
868
869                let wrapped_data = data_to_store as i8;
870
871                let mem_addr = *store
872                    .modules
873                    .get(current_module)
874                    .mem_addrs
875                    .first()
876                    .unwrap_validated();
877                let mem = store.memories.get(mem_addr);
878
879                let idx = calculate_mem_address(&memarg, relative_address)?;
880                mem.mem.store(idx, wrapped_data)?;
881
882                trace!("Instruction: i32.store8 [{relative_address} {wrapped_data}] -> []");
883            }
884            I32_STORE16 => {
885                decrement_fuel!(T::get_flat_cost(I32_STORE16));
886                let memarg = MemArg::read(wasm).unwrap_validated();
887
888                let data_to_store: i32 = stack.pop_value().try_into().unwrap_validated();
889                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
890
891                let wrapped_data = data_to_store as i16;
892
893                let mem_addr = *store
894                    .modules
895                    .get(current_module)
896                    .mem_addrs
897                    .first()
898                    .unwrap_validated();
899                let mem = store.memories.get(mem_addr);
900
901                let idx = calculate_mem_address(&memarg, relative_address)?;
902                mem.mem.store(idx, wrapped_data)?;
903
904                trace!("Instruction: i32.store16 [{relative_address} {data_to_store}] -> []");
905            }
906            I64_STORE8 => {
907                decrement_fuel!(T::get_flat_cost(I64_STORE8));
908                let memarg = MemArg::read(wasm).unwrap_validated();
909
910                let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
911                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
912
913                let wrapped_data = data_to_store as i8;
914
915                let mem_addr = *store
916                    .modules
917                    .get(current_module)
918                    .mem_addrs
919                    .first()
920                    .unwrap_validated();
921                let mem = store.memories.get(mem_addr);
922
923                let idx = calculate_mem_address(&memarg, relative_address)?;
924                mem.mem.store(idx, wrapped_data)?;
925
926                trace!("Instruction: i64.store8 [{relative_address} {data_to_store}] -> []");
927            }
928            I64_STORE16 => {
929                decrement_fuel!(T::get_flat_cost(I64_STORE16));
930                let memarg = MemArg::read(wasm).unwrap_validated();
931
932                let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
933                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
934
935                let wrapped_data = data_to_store as i16;
936
937                let mem_addr = *store
938                    .modules
939                    .get(current_module)
940                    .mem_addrs
941                    .first()
942                    .unwrap_validated();
943                let mem = store.memories.get(mem_addr);
944
945                let idx = calculate_mem_address(&memarg, relative_address)?;
946                mem.mem.store(idx, wrapped_data)?;
947
948                trace!("Instruction: i64.store16 [{relative_address} {data_to_store}] -> []");
949            }
950            I64_STORE32 => {
951                decrement_fuel!(T::get_flat_cost(I64_STORE32));
952                let memarg = MemArg::read(wasm).unwrap_validated();
953
954                let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
955                let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
956
957                let wrapped_data = data_to_store as i32;
958
959                let mem_addr = *store
960                    .modules
961                    .get(current_module)
962                    .mem_addrs
963                    .first()
964                    .unwrap_validated();
965                let mem = store.memories.get(mem_addr);
966
967                let idx = calculate_mem_address(&memarg, relative_address)?;
968                mem.mem.store(idx, wrapped_data)?;
969
970                trace!("Instruction: i64.store32 [{relative_address} {data_to_store}] -> []");
971            }
972            MEMORY_SIZE => {
973                decrement_fuel!(T::get_flat_cost(MEMORY_SIZE));
974                let mem_idx = wasm.read_u8().unwrap_validated() as usize;
975                let mem_addr = *store
976                    .modules
977                    .get(current_module)
978                    .mem_addrs
979                    .get(mem_idx)
980                    .unwrap_validated();
981                let mem = store.memories.get(mem_addr);
982                let size = mem.size() as u32;
983                stack.push_value::<T>(Value::I32(size))?;
984                trace!("Instruction: memory.size [] -> [{}]", size);
985            }
986            MEMORY_GROW => {
987                let mem_idx = wasm.read_u8().unwrap_validated() as usize;
988                let mem_addr = *store
989                    .modules
990                    .get(current_module)
991                    .mem_addrs
992                    .get(mem_idx)
993                    .unwrap_validated();
994                let mem = store.memories.get_mut(mem_addr);
995                let sz: u32 = mem.size() as u32;
996
997                let n: u32 = stack.pop_value().try_into().unwrap_validated();
998                // decrement fuel, but push n back if it fails
999                let cost = T::get_flat_cost(MEMORY_GROW)
1000                    + u64::from(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(NonZeroU64::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                            + u64::from(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(NonZeroU64::new(cost - *fuel));
2502                            }
2503                        }
2504
2505                        let s: u32 = stack.pop_value().try_into().unwrap_validated();
2506                        let d: u32 = 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                            + u64::from(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(NonZeroU64::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 usize, &src_mem.mem, s as usize, n as usize)?;
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                            + u64::from(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(NonZeroU64::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                            + u64::from(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(NonZeroU64::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                            + u64::from(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(NonZeroU64::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                            + u64::from(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(NonZeroU64::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                            + u64::from(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(NonZeroU64::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() || lane.is_negative_infinity() {
5095                                u32::MIN
5096                            } else if lane.is_infinity() {
5097                                u32::MAX
5098                            } else {
5099                                lane.as_u32()
5100                            }
5101                        });
5102                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5103                    }
5104                    I32X4_TRUNC_SAT_F64X2_S_ZERO => {
5105                        decrement_fuel!(T::get_fd_extension_flat_cost(
5106                            I32X4_TRUNC_SAT_F64X2_S_ZERO
5107                        ));
5108                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5109                        let lanes: [F64; 2] = to_lanes(data);
5110                        let result = lanes.map(|lane| {
5111                            if lane.is_nan() {
5112                                0
5113                            } else if lane.is_negative_infinity() {
5114                                i32::MIN
5115                            } else if lane.is_infinity() {
5116                                i32::MAX
5117                            } else {
5118                                lane.as_i32()
5119                            }
5120                        });
5121                        stack.push_value::<T>(Value::V128(from_lanes([
5122                            result[0], result[1], 0, 0,
5123                        ])))?;
5124                    }
5125                    I32X4_TRUNC_SAT_F64X2_U_ZERO => {
5126                        decrement_fuel!(T::get_fd_extension_flat_cost(
5127                            I32X4_TRUNC_SAT_F64X2_U_ZERO
5128                        ));
5129                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5130                        let lanes: [F64; 2] = to_lanes(data);
5131                        let result = lanes.map(|lane| {
5132                            if lane.is_nan() || lane.is_negative_infinity() {
5133                                u32::MIN
5134                            } else if lane.is_infinity() {
5135                                u32::MAX
5136                            } else {
5137                                lane.as_u32()
5138                            }
5139                        });
5140                        stack.push_value::<T>(Value::V128(from_lanes([
5141                            result[0], result[1], 0, 0,
5142                        ])))?;
5143                    }
5144                    F32X4_CONVERT_I32X4_S => {
5145                        decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_CONVERT_I32X4_S));
5146                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5147                        let lanes: [i32; 4] = to_lanes(data);
5148                        let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
5149                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5150                    }
5151                    F32X4_CONVERT_I32X4_U => {
5152                        decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_CONVERT_I32X4_U));
5153                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5154                        let lanes: [u32; 4] = to_lanes(data);
5155                        let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
5156                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5157                    }
5158                    F64X2_CONVERT_LOW_I32X4_S => {
5159                        decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_CONVERT_LOW_I32X4_S));
5160                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5161                        let lanes: [i32; 4] = to_lanes(data);
5162                        let low_lanes: [i32; 2] = lanes[..2].try_into().unwrap();
5163                        let result = low_lanes.map(|lane| F64(lane as f64));
5164                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5165                    }
5166                    F64X2_CONVERT_LOW_I32X4_U => {
5167                        decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_CONVERT_LOW_I32X4_U));
5168                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5169                        let lanes: [u32; 4] = to_lanes(data);
5170                        let low_lanes: [u32; 2] = lanes[..2].try_into().unwrap();
5171                        let result = low_lanes.map(|lane| F64(lane as f64));
5172                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5173                    }
5174                    F32X4_DEMOTE_F64X2_ZERO => {
5175                        decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_DEMOTE_F64X2_ZERO));
5176                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5177                        let lanes = to_lanes::<8, 2, F64>(data);
5178                        let half_lanes = lanes.map(|lane| lane.as_f32());
5179                        let result = [half_lanes[0], half_lanes[1], F32(0.0), F32(0.0)];
5180                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5181                    }
5182                    F64X2_PROMOTE_LOW_F32X4 => {
5183                        decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_PROMOTE_LOW_F32X4));
5184                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5185                        let lanes: [F32; 4] = to_lanes(data);
5186                        let half_lanes: [F32; 2] = lanes[..2].try_into().unwrap();
5187                        let result = half_lanes.map(|lane| lane.as_f64());
5188                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5189                    }
5190
5191                    // ishape.narrow_ishape_sx
5192                    I8X16_NARROW_I16X8_S => {
5193                        decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_NARROW_I16X8_S));
5194                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5195                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5196                        let lanes2: [i16; 8] = to_lanes(data2);
5197                        let lanes1: [i16; 8] = to_lanes(data1);
5198                        let mut concatenated_narrowed_lanes = lanes1
5199                            .into_iter()
5200                            .chain(lanes2)
5201                            .map(|lane| lane.clamp(i8::MIN as i16, i8::MAX as i16) as i8);
5202                        let result: [i8; 16] =
5203                            array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5204                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5205                    }
5206                    I8X16_NARROW_I16X8_U => {
5207                        decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_NARROW_I16X8_U));
5208                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5209                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5210                        let lanes2: [i16; 8] = to_lanes(data2);
5211                        let lanes1: [i16; 8] = to_lanes(data1);
5212                        let mut concatenated_narrowed_lanes = lanes1
5213                            .into_iter()
5214                            .chain(lanes2)
5215                            .map(|lane| lane.clamp(u8::MIN as i16, u8::MAX as i16) as u8);
5216                        let result: [u8; 16] =
5217                            array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5218                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5219                    }
5220                    I16X8_NARROW_I32X4_S => {
5221                        decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_NARROW_I32X4_S));
5222                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5223                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5224                        let lanes2: [i32; 4] = to_lanes(data2);
5225                        let lanes1: [i32; 4] = to_lanes(data1);
5226                        let mut concatenated_narrowed_lanes = lanes1
5227                            .into_iter()
5228                            .chain(lanes2)
5229                            .map(|lane| lane.clamp(i16::MIN as i32, i16::MAX as i32) as i16);
5230                        let result: [i16; 8] =
5231                            array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5232                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5233                    }
5234                    I16X8_NARROW_I32X4_U => {
5235                        decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_NARROW_I32X4_U));
5236                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5237                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5238                        let lanes2: [i32; 4] = to_lanes(data2);
5239                        let lanes1: [i32; 4] = to_lanes(data1);
5240                        let mut concatenated_narrowed_lanes = lanes1
5241                            .into_iter()
5242                            .chain(lanes2)
5243                            .map(|lane| lane.clamp(u16::MIN as i32, u16::MAX as i32) as u16);
5244                        let result: [u16; 8] =
5245                            array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5246                        stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5247                    }
5248
5249                    // ishape.bitmask
5250                    I8X16_BITMASK => {
5251                        decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_BITMASK));
5252                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5253                        let lanes: [i8; 16] = to_lanes(data);
5254                        let bits = lanes.map(|lane| lane < 0);
5255                        let bitmask = bits
5256                            .into_iter()
5257                            .enumerate()
5258                            .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5259                        stack.push_value::<T>(Value::I32(bitmask))?;
5260                    }
5261                    I16X8_BITMASK => {
5262                        decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_BITMASK));
5263                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5264                        let lanes: [i16; 8] = to_lanes(data);
5265                        let bits = lanes.map(|lane| lane < 0);
5266                        let bitmask = bits
5267                            .into_iter()
5268                            .enumerate()
5269                            .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5270                        stack.push_value::<T>(Value::I32(bitmask))?;
5271                    }
5272                    I32X4_BITMASK => {
5273                        decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_BITMASK));
5274                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5275                        let lanes: [i32; 4] = to_lanes(data);
5276                        let bits = lanes.map(|lane| lane < 0);
5277                        let bitmask = bits
5278                            .into_iter()
5279                            .enumerate()
5280                            .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5281                        stack.push_value::<T>(Value::I32(bitmask))?;
5282                    }
5283                    I64X2_BITMASK => {
5284                        decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_BITMASK));
5285                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5286                        let lanes: [i64; 2] = to_lanes(data);
5287                        let bits = lanes.map(|lane| lane < 0);
5288                        let bitmask = bits
5289                            .into_iter()
5290                            .enumerate()
5291                            .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5292                        stack.push_value::<T>(Value::I32(bitmask))?;
5293                    }
5294
5295                    // ishape.dot_ishape_s
5296                    I32X4_DOT_I16X8_S => {
5297                        decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_DOT_I16X8_S));
5298                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5299                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5300                        let lanes1: [i16; 8] = to_lanes(data1);
5301                        let lanes2: [i16; 8] = to_lanes(data2);
5302                        let multiplied: [i32; 8] = array::from_fn(|i| {
5303                            let v1 = lanes1[i] as i32;
5304                            let v2 = lanes2[i] as i32;
5305                            v1.wrapping_mul(v2)
5306                        });
5307                        let added: [i32; 4] = array::from_fn(|i| {
5308                            let v1 = multiplied[2 * i];
5309                            let v2 = multiplied[2 * i + 1];
5310                            v1.wrapping_add(v2)
5311                        });
5312                        stack.push_value::<T>(Value::V128(from_lanes(added)))?;
5313                    }
5314
5315                    // ishape.extmul_half_ishape_sx
5316                    I16X8_EXTMUL_HIGH_I8X16_S => {
5317                        decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_HIGH_I8X16_S));
5318                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5319                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5320                        let lanes1: [i8; 16] = to_lanes(data1);
5321                        let lanes2: [i8; 16] = to_lanes(data2);
5322                        let high_lanes1: [i8; 8] = lanes1[8..].try_into().unwrap();
5323                        let high_lanes2: [i8; 8] = lanes2[8..].try_into().unwrap();
5324                        let multiplied: [i16; 8] = array::from_fn(|i| {
5325                            let v1 = high_lanes1[i] as i16;
5326                            let v2 = high_lanes2[i] as i16;
5327                            v1.wrapping_mul(v2)
5328                        });
5329                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5330                    }
5331                    I16X8_EXTMUL_HIGH_I8X16_U => {
5332                        decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_HIGH_I8X16_U));
5333                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5334                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5335                        let lanes1: [u8; 16] = to_lanes(data1);
5336                        let lanes2: [u8; 16] = to_lanes(data2);
5337                        let high_lanes1: [u8; 8] = lanes1[8..].try_into().unwrap();
5338                        let high_lanes2: [u8; 8] = lanes2[8..].try_into().unwrap();
5339                        let multiplied: [u16; 8] = array::from_fn(|i| {
5340                            let v1 = high_lanes1[i] as u16;
5341                            let v2 = high_lanes2[i] as u16;
5342                            v1.wrapping_mul(v2)
5343                        });
5344                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5345                    }
5346                    I16X8_EXTMUL_LOW_I8X16_S => {
5347                        decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_LOW_I8X16_S));
5348                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5349                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5350                        let lanes1: [i8; 16] = to_lanes(data1);
5351                        let lanes2: [i8; 16] = to_lanes(data2);
5352                        let high_lanes1: [i8; 8] = lanes1[..8].try_into().unwrap();
5353                        let high_lanes2: [i8; 8] = lanes2[..8].try_into().unwrap();
5354                        let multiplied: [i16; 8] = array::from_fn(|i| {
5355                            let v1 = high_lanes1[i] as i16;
5356                            let v2 = high_lanes2[i] as i16;
5357                            v1.wrapping_mul(v2)
5358                        });
5359                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5360                    }
5361                    I16X8_EXTMUL_LOW_I8X16_U => {
5362                        decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_LOW_I8X16_U));
5363                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5364                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5365                        let lanes1: [u8; 16] = to_lanes(data1);
5366                        let lanes2: [u8; 16] = to_lanes(data2);
5367                        let high_lanes1: [u8; 8] = lanes1[..8].try_into().unwrap();
5368                        let high_lanes2: [u8; 8] = lanes2[..8].try_into().unwrap();
5369                        let multiplied: [u16; 8] = array::from_fn(|i| {
5370                            let v1 = high_lanes1[i] as u16;
5371                            let v2 = high_lanes2[i] as u16;
5372                            v1.wrapping_mul(v2)
5373                        });
5374                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5375                    }
5376                    I32X4_EXTMUL_HIGH_I16X8_S => {
5377                        decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_HIGH_I16X8_S));
5378                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5379                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5380                        let lanes1: [i16; 8] = to_lanes(data1);
5381                        let lanes2: [i16; 8] = to_lanes(data2);
5382                        let high_lanes1: [i16; 4] = lanes1[4..].try_into().unwrap();
5383                        let high_lanes2: [i16; 4] = lanes2[4..].try_into().unwrap();
5384                        let multiplied: [i32; 4] = array::from_fn(|i| {
5385                            let v1 = high_lanes1[i] as i32;
5386                            let v2 = high_lanes2[i] as i32;
5387                            v1.wrapping_mul(v2)
5388                        });
5389                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5390                    }
5391                    I32X4_EXTMUL_HIGH_I16X8_U => {
5392                        decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_HIGH_I16X8_U));
5393                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5394                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5395                        let lanes1: [u16; 8] = to_lanes(data1);
5396                        let lanes2: [u16; 8] = to_lanes(data2);
5397                        let high_lanes1: [u16; 4] = lanes1[4..].try_into().unwrap();
5398                        let high_lanes2: [u16; 4] = lanes2[4..].try_into().unwrap();
5399                        let multiplied: [u32; 4] = array::from_fn(|i| {
5400                            let v1 = high_lanes1[i] as u32;
5401                            let v2 = high_lanes2[i] as u32;
5402                            v1.wrapping_mul(v2)
5403                        });
5404                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5405                    }
5406                    I32X4_EXTMUL_LOW_I16X8_S => {
5407                        decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_LOW_I16X8_S));
5408                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5409                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5410                        let lanes1: [i16; 8] = to_lanes(data1);
5411                        let lanes2: [i16; 8] = to_lanes(data2);
5412                        let high_lanes1: [i16; 4] = lanes1[..4].try_into().unwrap();
5413                        let high_lanes2: [i16; 4] = lanes2[..4].try_into().unwrap();
5414                        let multiplied: [i32; 4] = array::from_fn(|i| {
5415                            let v1 = high_lanes1[i] as i32;
5416                            let v2 = high_lanes2[i] as i32;
5417                            v1.wrapping_mul(v2)
5418                        });
5419                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5420                    }
5421                    I32X4_EXTMUL_LOW_I16X8_U => {
5422                        decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_LOW_I16X8_U));
5423                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5424                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5425                        let lanes1: [u16; 8] = to_lanes(data1);
5426                        let lanes2: [u16; 8] = to_lanes(data2);
5427                        let high_lanes1: [u16; 4] = lanes1[..4].try_into().unwrap();
5428                        let high_lanes2: [u16; 4] = lanes2[..4].try_into().unwrap();
5429                        let multiplied: [u32; 4] = array::from_fn(|i| {
5430                            let v1 = high_lanes1[i] as u32;
5431                            let v2 = high_lanes2[i] as u32;
5432                            v1.wrapping_mul(v2)
5433                        });
5434                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5435                    }
5436                    I64X2_EXTMUL_HIGH_I32X4_S => {
5437                        decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_HIGH_I32X4_S));
5438                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5439                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5440                        let lanes1: [i32; 4] = to_lanes(data1);
5441                        let lanes2: [i32; 4] = to_lanes(data2);
5442                        let high_lanes1: [i32; 2] = lanes1[2..].try_into().unwrap();
5443                        let high_lanes2: [i32; 2] = lanes2[2..].try_into().unwrap();
5444                        let multiplied: [i64; 2] = array::from_fn(|i| {
5445                            let v1 = high_lanes1[i] as i64;
5446                            let v2 = high_lanes2[i] as i64;
5447                            v1.wrapping_mul(v2)
5448                        });
5449                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5450                    }
5451                    I64X2_EXTMUL_HIGH_I32X4_U => {
5452                        decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_HIGH_I32X4_U));
5453                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5454                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5455                        let lanes1: [u32; 4] = to_lanes(data1);
5456                        let lanes2: [u32; 4] = to_lanes(data2);
5457                        let high_lanes1: [u32; 2] = lanes1[2..].try_into().unwrap();
5458                        let high_lanes2: [u32; 2] = lanes2[2..].try_into().unwrap();
5459                        let multiplied: [u64; 2] = array::from_fn(|i| {
5460                            let v1 = high_lanes1[i] as u64;
5461                            let v2 = high_lanes2[i] as u64;
5462                            v1.wrapping_mul(v2)
5463                        });
5464                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5465                    }
5466                    I64X2_EXTMUL_LOW_I32X4_S => {
5467                        decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_LOW_I32X4_S));
5468                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5469                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5470                        let lanes1: [i32; 4] = to_lanes(data1);
5471                        let lanes2: [i32; 4] = to_lanes(data2);
5472                        let high_lanes1: [i32; 2] = lanes1[..2].try_into().unwrap();
5473                        let high_lanes2: [i32; 2] = lanes2[..2].try_into().unwrap();
5474                        let multiplied: [i64; 2] = array::from_fn(|i| {
5475                            let v1 = high_lanes1[i] as i64;
5476                            let v2 = high_lanes2[i] as i64;
5477                            v1.wrapping_mul(v2)
5478                        });
5479                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5480                    }
5481                    I64X2_EXTMUL_LOW_I32X4_U => {
5482                        decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_LOW_I32X4_U));
5483                        let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5484                        let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5485                        let lanes1: [u32; 4] = to_lanes(data1);
5486                        let lanes2: [u32; 4] = to_lanes(data2);
5487                        let high_lanes1: [u32; 2] = lanes1[..2].try_into().unwrap();
5488                        let high_lanes2: [u32; 2] = lanes2[..2].try_into().unwrap();
5489                        let multiplied: [u64; 2] = array::from_fn(|i| {
5490                            let v1 = high_lanes1[i] as u64;
5491                            let v2 = high_lanes2[i] as u64;
5492                            v1.wrapping_mul(v2)
5493                        });
5494                        stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5495                    }
5496
5497                    // ishape.extadd_pairwise_ishape_sx
5498                    I16X8_EXTADD_PAIRWISE_I8X16_S => {
5499                        decrement_fuel!(T::get_fd_extension_flat_cost(
5500                            I16X8_EXTADD_PAIRWISE_I8X16_S
5501                        ));
5502                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5503                        let lanes: [i8; 16] = to_lanes(data);
5504                        let added_pairwise: [i16; 8] = array::from_fn(|i| {
5505                            let v1 = lanes[2 * i] as i16;
5506                            let v2 = lanes[2 * i + 1] as i16;
5507                            v1.wrapping_add(v2)
5508                        });
5509                        stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
5510                    }
5511                    I16X8_EXTADD_PAIRWISE_I8X16_U => {
5512                        decrement_fuel!(T::get_fd_extension_flat_cost(
5513                            I16X8_EXTADD_PAIRWISE_I8X16_U
5514                        ));
5515                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5516                        let lanes: [u8; 16] = to_lanes(data);
5517                        let added_pairwise: [u16; 8] = array::from_fn(|i| {
5518                            let v1 = lanes[2 * i] as u16;
5519                            let v2 = lanes[2 * i + 1] as u16;
5520                            v1.wrapping_add(v2)
5521                        });
5522                        stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
5523                    }
5524                    I32X4_EXTADD_PAIRWISE_I16X8_S => {
5525                        decrement_fuel!(T::get_fd_extension_flat_cost(
5526                            I32X4_EXTADD_PAIRWISE_I16X8_S
5527                        ));
5528                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5529                        let lanes: [i16; 8] = to_lanes(data);
5530                        let added_pairwise: [i32; 4] = array::from_fn(|i| {
5531                            let v1 = lanes[2 * i] as i32;
5532                            let v2 = lanes[2 * i + 1] as i32;
5533                            v1.wrapping_add(v2)
5534                        });
5535                        stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
5536                    }
5537                    I32X4_EXTADD_PAIRWISE_I16X8_U => {
5538                        decrement_fuel!(T::get_fd_extension_flat_cost(
5539                            I32X4_EXTADD_PAIRWISE_I16X8_U
5540                        ));
5541                        let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5542                        let lanes: [u16; 8] = to_lanes(data);
5543                        let added_pairwise: [u32; 4] = array::from_fn(|i| {
5544                            let v1 = lanes[2 * i] as u32;
5545                            let v2 = lanes[2 * i + 1] as u32;
5546                            v1.wrapping_add(v2)
5547                        });
5548                        stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
5549                    }
5550
5551                    // Unimplemented or invalid instructions
5552                    F32X4_RELAXED_MADD
5553                    | F32X4_RELAXED_MAX
5554                    | F32X4_RELAXED_MIN
5555                    | F32X4_RELAXED_NMADD
5556                    | F64X2_RELAXED_MADD
5557                    | F64X2_RELAXED_MAX
5558                    | F64X2_RELAXED_MIN
5559                    | F64X2_RELAXED_NMADD
5560                    | I16X8_RELAXED_LANESELECT
5561                    | I32X4_RELAXED_LANESELECT
5562                    | I32X4_RELAXED_TRUNC_F32X4_S
5563                    | I32X4_RELAXED_TRUNC_F32X4_U
5564                    | I32X4_RELAXED_TRUNC_F64X2_S_ZERO
5565                    | I32X4_RELAXED_TRUNC_F64X2_U_ZERO
5566                    | I64X2_RELAXED_LANESELECT
5567                    | I8X16_RELAXED_LANESELECT
5568                    | I8X16_RELAXED_SWIZZLE
5569                    | 154
5570                    | 187
5571                    | 194
5572                    | 256.. => unreachable_validated!(),
5573                }
5574            }
5575
5576            // Unimplemented or invalid instructions
5577            0x06..=0x0A
5578            | 0x12..=0x19
5579            | 0x1C..=0x1F
5580            | 0x25..=0x27
5581            | 0xC0..=0xFA
5582            | 0xFB
5583            | 0xFE
5584            | 0xFF => {
5585                unreachable_validated!();
5586            }
5587        }
5588    }
5589    Ok(None)
5590}
5591
5592//helper function for avoiding code duplication at intraprocedural jumps
5593fn do_sidetable_control_transfer(
5594    wasm: &mut WasmReader,
5595    stack: &mut Stack,
5596    current_stp: &mut usize,
5597    current_sidetable: &Sidetable,
5598) -> Result<(), RuntimeError> {
5599    let sidetable_entry = &current_sidetable[*current_stp];
5600
5601    stack.remove_in_between(sidetable_entry.popcnt, sidetable_entry.valcnt);
5602
5603    *current_stp = (*current_stp as isize + sidetable_entry.delta_stp) as usize;
5604    wasm.pc = (wasm.pc as isize + sidetable_entry.delta_pc) as usize;
5605
5606    Ok(())
5607}
5608
5609#[inline(always)]
5610fn calculate_mem_address(memarg: &MemArg, relative_address: u32) -> Result<usize, RuntimeError> {
5611    memarg
5612        .offset
5613        // The spec states that this should be a 33 bit integer, e.g. it is not legal to wrap if the
5614        // sum of offset and relative_address exceeds u32::MAX. To emulate this behavior, we use a
5615        // checked addition.
5616        // See: https://webassembly.github.io/spec/core/syntax/instructions.html#memory-instructions
5617        .checked_add(relative_address)
5618        .ok_or(TrapError::MemoryOrDataAccessOutOfBounds)?
5619        .try_into()
5620        .map_err(|_| TrapError::MemoryOrDataAccessOutOfBounds.into())
5621}
5622
5623//helpers for avoiding code duplication during module instantiation
5624#[inline(always)]
5625#[allow(clippy::too_many_arguments)]
5626pub(super) fn table_init(
5627    store_modules: &AddrVec<ModuleAddr, ModuleInst>,
5628    store_tables: &mut AddrVec<TableAddr, TableInst>,
5629    store_elements: &AddrVec<ElemAddr, ElemInst>,
5630    current_module: ModuleAddr,
5631    elem_idx: usize,
5632    table_idx: usize,
5633    n: u32,
5634    s: i32,
5635    d: i32,
5636) -> Result<(), RuntimeError> {
5637    let tab_addr = *store_modules
5638        .get(current_module)
5639        .table_addrs
5640        .get(table_idx)
5641        .unwrap_validated();
5642    let elem_addr = *store_modules
5643        .get(current_module)
5644        .elem_addrs
5645        .get(elem_idx)
5646        .unwrap_validated();
5647
5648    let tab = store_tables.get_mut(tab_addr);
5649
5650    let elem = store_elements.get(elem_addr);
5651
5652    trace!(
5653        "Instruction: table.init '{}' '{}' [{} {} {}] -> []",
5654        elem_idx,
5655        table_idx,
5656        d,
5657        s,
5658        n
5659    );
5660
5661    let final_src_offset = (s as usize)
5662        .checked_add(n as usize)
5663        .filter(|&res| res <= elem.len())
5664        .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
5665
5666    if (d as usize)
5667        .checked_add(n as usize)
5668        .filter(|&res| res <= tab.len())
5669        .is_none()
5670    {
5671        return Err(TrapError::TableOrElementAccessOutOfBounds.into());
5672    }
5673
5674    let dest = &mut tab.elem[d as usize..];
5675    let src = &elem.references[s as usize..final_src_offset];
5676    dest[..src.len()].copy_from_slice(src);
5677    Ok(())
5678}
5679
5680#[inline(always)]
5681pub(super) fn elem_drop(
5682    store_modules: &AddrVec<ModuleAddr, ModuleInst>,
5683    store_elements: &mut AddrVec<ElemAddr, ElemInst>,
5684    current_module: ModuleAddr,
5685    elem_idx: usize,
5686) -> Result<(), RuntimeError> {
5687    // WARN: i'm not sure if this is okay or not
5688    let elem_addr = *store_modules
5689        .get(current_module)
5690        .elem_addrs
5691        .get(elem_idx)
5692        .unwrap_validated();
5693    store_elements.get_mut(elem_addr).references.clear();
5694    Ok(())
5695}
5696
5697#[inline(always)]
5698#[allow(clippy::too_many_arguments)]
5699pub(super) fn memory_init(
5700    store_modules: &AddrVec<ModuleAddr, ModuleInst>,
5701    store_memories: &mut AddrVec<MemAddr, MemInst>,
5702    store_data: &AddrVec<DataAddr, DataInst>,
5703    current_module: ModuleAddr,
5704    data_idx: usize,
5705    mem_idx: usize,
5706    n: u32,
5707    s: u32,
5708    d: u32,
5709) -> Result<(), RuntimeError> {
5710    let n = usize::try_from(n).expect("pointer width to be at least 32 bits wide");
5711    let s = usize::try_from(s).expect("pointer width to be at least 32 bits wide");
5712    let d = usize::try_from(d).expect("pointer width to be at least 32 bits wide");
5713
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,
5723        &store_data
5724            .get(store_modules.get(current_module).data_addrs[data_idx])
5725            .data,
5726        s,
5727        n,
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}