1use 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::{
23 read_label_idx_unchecked, DataIdx, ElemIdx, FuncIdx, GlobalIdx, Idx, LocalIdx, MemIdx,
24 TableIdx, TypeIdx,
25 },
26 reader::{
27 types::{memarg::MemArg, BlockType},
28 WasmReader,
29 },
30 sidetable::Sidetable,
31 utils::ToUsizeExt,
32 },
33 instances::{DataInst, ElemInst, FuncInst, MemInst, ModuleInst, TableInst},
34 resumable::WasmResumable,
35 store::HaltExecutionError,
36 unreachable_validated,
37 value::{self, Ref, F32, F64},
38 value_stack::Stack,
39 RefType, RuntimeError, TrapError, ValType, Value,
40};
41
42use crate::execution::config::Config;
43
44use super::{little_endian::LittleEndianBytes, store::Store};
45
46pub(super) fn run<T: Config>(
55 resumable: &mut WasmResumable,
56 store: &mut Store<T>,
57) -> Result<Option<NonZeroU64>, RuntimeError> {
58 let stack = &mut resumable.stack;
59 let mut current_func_addr = resumable.current_func_addr;
60 let pc = resumable.pc;
61 let mut stp = resumable.stp;
62 let func_inst = unsafe { store.functions.get(current_func_addr) };
65 let FuncInst::WasmFunc(wasm_func_inst) = &func_inst else {
66 unreachable!(
67 "the interpreter loop shall only be executed with native wasm functions as root call"
68 );
69 };
70 let mut current_module = wasm_func_inst.module_addr;
71
72 let module = unsafe { store.modules.get(current_module) };
76 let wasm = &mut WasmReader::new(module.wasm_bytecode);
77
78 let mut current_sidetable: &Sidetable = &module.sidetable;
79
80 let mut current_function_end_marker =
82 wasm_func_inst.code_expr.from() + wasm_func_inst.code_expr.len();
83
84 wasm.pc = pc;
85
86 use crate::core::reader::types::opcode::*;
87 loop {
88 store
90 .user_data
91 .instruction_hook(module.wasm_bytecode, wasm.pc);
92
93 let prev_pc = wasm.pc;
96 macro_rules! decrement_fuel {
97 ($cost:expr) => {
98 if let Some(fuel) = &mut resumable.maybe_fuel {
99 if *fuel >= $cost {
100 *fuel -= $cost;
101 } else {
102 resumable.current_func_addr = current_func_addr;
103 resumable.pc = prev_pc; resumable.stp = stp;
105 return Ok(NonZeroU64::new($cost-*fuel));
106 }
107 }
108 }
109 }
110
111 let first_instr_byte = wasm.read_u8().unwrap_validated();
112
113 #[cfg(debug_assertions)]
114 trace!(
115 "Executing instruction {}",
116 opcode_byte_to_str(first_instr_byte)
117 );
118
119 match first_instr_byte {
120 NOP => {
121 decrement_fuel!(T::get_flat_cost(NOP));
122 trace!("Instruction: NOP");
123 }
124 END => {
125 if wasm.pc != current_function_end_marker {
128 continue;
129 }
130
131 let Some((maybe_return_func_addr, maybe_return_address, maybe_return_stp)) =
132 stack.pop_call_frame()
133 else {
134 break;
136 };
137 trace!("end of function reached, returning to previous call frame");
141 current_func_addr = maybe_return_func_addr;
142
143 let current_function = unsafe { store.functions.get(current_func_addr) };
150 let FuncInst::WasmFunc(current_wasm_func_inst) = current_function else {
151 unreachable!("function addresses on the stack always correspond to native wasm functions")
152 };
153 current_module = current_wasm_func_inst.module_addr;
154
155 let module = unsafe { store.modules.get(current_module) };
160
161 wasm.full_wasm_binary = module.wasm_bytecode;
162 wasm.pc = maybe_return_address;
163 stp = maybe_return_stp;
164
165 current_sidetable = &module.sidetable;
166
167 current_function_end_marker = current_wasm_func_inst.code_expr.from()
168 + current_wasm_func_inst.code_expr.len();
169
170 trace!("Instruction: END");
171 }
172 IF => {
173 decrement_fuel!(T::get_flat_cost(IF));
174 wasm.read_var_u32().unwrap_validated();
175
176 let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
177
178 if test_val != 0 {
179 stp += 1;
180 } else {
181 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
182 }
183 trace!("Instruction: IF");
184 }
185 ELSE => {
186 decrement_fuel!(T::get_flat_cost(ELSE));
187 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
188 }
189 BR_IF => {
190 decrement_fuel!(T::get_flat_cost(BR_IF));
191
192 let _label_idx = unsafe { read_label_idx_unchecked(wasm) };
195
196 let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
197
198 if test_val != 0 {
199 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
200 } else {
201 stp += 1;
202 }
203 trace!("Instruction: BR_IF");
204 }
205 BR_TABLE => {
206 decrement_fuel!(T::get_flat_cost(BR_TABLE));
207 let label_vec = wasm
208 .read_vec(|wasm| {
209 Ok(unsafe { read_label_idx_unchecked(wasm) })
212 })
213 .unwrap_validated();
214
215 let _default_label_idx = unsafe { read_label_idx_unchecked(wasm) };
218
219 let case_val_i32: i32 = stack.pop_value().try_into().unwrap_validated();
221 let case_val = case_val_i32.cast_unsigned().into_usize();
222
223 if case_val >= label_vec.len() {
224 stp += label_vec.len();
225 } else {
226 stp += case_val;
227 }
228
229 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
230 }
231 BR => {
232 decrement_fuel!(T::get_flat_cost(BR));
233 let _label_idx = unsafe { read_label_idx_unchecked(wasm) };
236 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
237 }
238 BLOCK => {
239 decrement_fuel!(T::get_flat_cost(BLOCK));
240 let _ = unsafe { BlockType::read_unchecked(wasm) };
243 }
244 LOOP => {
245 decrement_fuel!(T::get_flat_cost(LOOP));
246 let _ = unsafe { BlockType::read_unchecked(wasm) };
249 }
250 RETURN => {
251 decrement_fuel!(T::get_flat_cost(RETURN));
252 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
254 }
255 CALL => {
256 decrement_fuel!(T::get_flat_cost(CALL));
257 let func_idx = unsafe { FuncIdx::read_unchecked(wasm) };
260
261 let FuncInst::WasmFunc(current_wasm_func_inst) =
268 (unsafe { store.functions.get(current_func_addr) })
269 else {
270 unreachable!()
271 };
272
273 let current_module_inst =
278 unsafe { store.modules.get(current_wasm_func_inst.module_addr) };
279
280 let func_to_call_addr = unsafe { current_module_inst.func_addrs.get(func_idx) };
283
284 let func_to_call_inst = unsafe { store.functions.get(*func_to_call_addr) };
287
288 trace!("Instruction: call [{func_to_call_addr:?}]");
289
290 match func_to_call_inst {
291 FuncInst::HostFunc(host_func_to_call_inst) => {
292 let params = stack
293 .pop_tail_iter(
294 host_func_to_call_inst.function_type.params.valtypes.len(),
295 )
296 .collect();
297 let returns =
298 (host_func_to_call_inst.hostcode)(&mut store.user_data, params);
299
300 let returns = returns.map_err(|HaltExecutionError| {
301 RuntimeError::HostFunctionHaltedExecution
302 })?;
303
304 if returns.len()
307 != host_func_to_call_inst.function_type.returns.valtypes.len()
308 {
309 return Err(RuntimeError::HostFunctionSignatureMismatch);
310 }
311 for (value, ty) in zip(
312 returns,
313 &host_func_to_call_inst.function_type.returns.valtypes,
314 ) {
315 if value.to_ty() != *ty {
316 return Err(RuntimeError::HostFunctionSignatureMismatch);
317 }
318 stack.push_value::<T>(value)?;
319 }
320 }
321 FuncInst::WasmFunc(wasm_func_to_call_inst) => {
322 let remaining_locals = &wasm_func_to_call_inst.locals;
323
324 stack.push_call_frame::<T>(
325 current_func_addr,
326 &wasm_func_to_call_inst.function_type,
327 remaining_locals,
328 wasm.pc,
329 stp,
330 )?;
331
332 current_func_addr = *func_to_call_addr;
333 current_module = wasm_func_to_call_inst.module_addr;
334
335 let module = unsafe { store.modules.get(current_module) };
340
341 wasm.full_wasm_binary = module.wasm_bytecode;
342 wasm.move_start_to(wasm_func_to_call_inst.code_expr)
343 .expect("code expression spans to always be valid");
344
345 stp = wasm_func_to_call_inst.stp;
346 current_sidetable = &module.sidetable;
347 current_function_end_marker = wasm_func_to_call_inst.code_expr.from()
348 + wasm_func_to_call_inst.code_expr.len();
349 }
350 }
351 trace!("Instruction: CALL");
352 }
353
354 CALL_INDIRECT => {
356 decrement_fuel!(T::get_flat_cost(CALL_INDIRECT));
357 let given_type_idx = unsafe { TypeIdx::read_unchecked(wasm) };
360 let table_idx = unsafe { TableIdx::read_unchecked(wasm) };
363
364 let module = unsafe { store.modules.get(current_module) };
369
370 let table_addr = unsafe { module.table_addrs.get(table_idx) };
373 let tab = unsafe { store.tables.get(*table_addr) };
376 let func_ty = unsafe { module.types.get(given_type_idx) };
379
380 let i: u32 = stack.pop_value().try_into().unwrap_validated();
381
382 let r = tab
383 .elem
384 .get(i.into_usize())
385 .ok_or(TrapError::TableAccessOutOfBounds)
386 .and_then(|r| {
387 if matches!(r, Ref::Null(_)) {
388 trace!("table_idx ({table_idx}) --- element index in table ({i})");
389 Err(TrapError::UninitializedElement)
390 } else {
391 Ok(r)
392 }
393 })?;
394
395 let func_to_call_addr = match *r {
396 Ref::Func(func_addr) => func_addr,
397 Ref::Null(_) => return Err(TrapError::IndirectCallNullFuncRef.into()),
398 Ref::Extern(_) => unreachable_validated!(),
399 };
400
401 let func_to_call_inst = unsafe { store.functions.get(func_to_call_addr) };
405
406 if func_ty != func_to_call_inst.ty() {
407 return Err(TrapError::SignatureMismatch.into());
408 }
409
410 trace!("Instruction: call [{func_to_call_addr:?}]");
411
412 match func_to_call_inst {
413 FuncInst::HostFunc(host_func_to_call_inst) => {
414 let params = stack
415 .pop_tail_iter(
416 host_func_to_call_inst.function_type.params.valtypes.len(),
417 )
418 .collect();
419 let returns =
420 (host_func_to_call_inst.hostcode)(&mut store.user_data, params);
421
422 let returns = returns.map_err(|HaltExecutionError| {
423 RuntimeError::HostFunctionHaltedExecution
424 })?;
425
426 if returns.len()
429 != host_func_to_call_inst.function_type.returns.valtypes.len()
430 {
431 return Err(RuntimeError::HostFunctionSignatureMismatch);
432 }
433 for (value, ty) in zip(
434 returns,
435 &host_func_to_call_inst.function_type.returns.valtypes,
436 ) {
437 if value.to_ty() != *ty {
438 return Err(RuntimeError::HostFunctionSignatureMismatch);
439 }
440 stack.push_value::<T>(value)?;
441 }
442 }
443 FuncInst::WasmFunc(wasm_func_to_call_inst) => {
444 let remaining_locals = &wasm_func_to_call_inst.locals;
445
446 stack.push_call_frame::<T>(
447 current_func_addr,
448 &wasm_func_to_call_inst.function_type,
449 remaining_locals,
450 wasm.pc,
451 stp,
452 )?;
453
454 current_func_addr = func_to_call_addr;
455 current_module = wasm_func_to_call_inst.module_addr;
456
457 let module = unsafe { store.modules.get(current_module) };
462 wasm.full_wasm_binary = module.wasm_bytecode;
463 wasm.move_start_to(wasm_func_to_call_inst.code_expr)
464 .expect("code expression spans to always be valid");
465
466 stp = wasm_func_to_call_inst.stp;
467 current_sidetable = &module.sidetable;
468 current_function_end_marker = wasm_func_to_call_inst.code_expr.from()
469 + wasm_func_to_call_inst.code_expr.len();
470 }
471 }
472 trace!("Instruction: CALL_INDIRECT");
473 }
474 DROP => {
475 decrement_fuel!(T::get_flat_cost(DROP));
476 stack.pop_value();
477 trace!("Instruction: DROP");
478 }
479 SELECT => {
480 decrement_fuel!(T::get_flat_cost(SELECT));
481 let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
482 let val2 = stack.pop_value();
483 let val1 = stack.pop_value();
484 if test_val != 0 {
485 stack.push_value::<T>(val1)?;
486 } else {
487 stack.push_value::<T>(val2)?;
488 }
489 trace!("Instruction: SELECT");
490 }
491 SELECT_T => {
492 decrement_fuel!(T::get_flat_cost(SELECT_T));
493 let _type_vec = wasm.read_vec(ValType::read).unwrap_validated();
494 let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
495 let val2 = stack.pop_value();
496 let val1 = stack.pop_value();
497 if test_val != 0 {
498 stack.push_value::<T>(val1)?;
499 } else {
500 stack.push_value::<T>(val2)?;
501 }
502 trace!("Instruction: SELECT_T");
503 }
504 LOCAL_GET => {
505 decrement_fuel!(T::get_flat_cost(LOCAL_GET));
506 let local_idx = unsafe { LocalIdx::read_unchecked(wasm) };
509 let value = *stack.get_local(local_idx);
510 stack.push_value::<T>(value)?;
511 trace!("Instruction: local.get {} [] -> [t]", local_idx);
512 }
513 LOCAL_SET => {
514 decrement_fuel!(T::get_flat_cost(LOCAL_SET));
515 let local_idx = unsafe { LocalIdx::read_unchecked(wasm) };
518 let value = stack.pop_value();
519 *stack.get_local_mut(local_idx) = value;
520 trace!("Instruction: local.set {} [t] -> []", local_idx);
521 }
522 LOCAL_TEE => {
523 decrement_fuel!(T::get_flat_cost(LOCAL_TEE));
524 let local_idx = unsafe { LocalIdx::read_unchecked(wasm) };
527 let value = stack.peek_value().unwrap_validated();
528 *stack.get_local_mut(local_idx) = value;
529 trace!("Instruction: local.tee {} [t] -> [t]", local_idx);
530 }
531 GLOBAL_GET => {
532 decrement_fuel!(T::get_flat_cost(GLOBAL_GET));
533 let global_idx = unsafe { GlobalIdx::read_unchecked(wasm) };
536 let module = unsafe { store.modules.get(current_module) };
541
542 let global_addr = *unsafe { module.global_addrs.get(global_idx) };
545 let global = unsafe { store.globals.get(global_addr) };
548
549 stack.push_value::<T>(global.value)?;
550
551 trace!(
552 "Instruction: global.get '{}' [<GLOBAL>] -> [{:?}]",
553 global_idx,
554 global.value
555 );
556 }
557 GLOBAL_SET => {
558 decrement_fuel!(T::get_flat_cost(GLOBAL_SET));
559 let global_idx = unsafe { GlobalIdx::read_unchecked(wasm) };
562 let module = unsafe { store.modules.get(current_module) };
567 let global_addr = *unsafe { module.global_addrs.get(global_idx) };
570 let global = unsafe { store.globals.get_mut(global_addr) };
573
574 global.value = stack.pop_value();
575 trace!("Instruction: GLOBAL_SET");
576 }
577 TABLE_GET => {
578 decrement_fuel!(T::get_flat_cost(TABLE_GET));
579 let table_idx = unsafe { TableIdx::read_unchecked(wasm) };
582 let module = unsafe { store.modules.get(current_module) };
587
588 let table_addr = *unsafe { module.table_addrs.get(table_idx) };
591 let tab = unsafe { store.tables.get(table_addr) };
594
595 let i: i32 = stack.pop_value().try_into().unwrap_validated();
596
597 let val = tab
598 .elem
599 .get(i.cast_unsigned().into_usize())
600 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
601
602 stack.push_value::<T>((*val).into())?;
603 trace!(
604 "Instruction: table.get '{}' [{}] -> [{}]",
605 table_idx,
606 i,
607 val
608 );
609 }
610 TABLE_SET => {
611 decrement_fuel!(T::get_flat_cost(TABLE_SET));
612 let table_idx = unsafe { TableIdx::read_unchecked(wasm) };
615 let module = unsafe { store.modules.get(current_module) };
620
621 let table_addr = *unsafe { module.table_addrs.get(table_idx) };
624 let tab = unsafe { store.tables.get_mut(table_addr) };
627
628 let val: Ref = stack.pop_value().try_into().unwrap_validated();
629 let i: i32 = stack.pop_value().try_into().unwrap_validated();
630
631 tab.elem
632 .get_mut(i.cast_unsigned().into_usize())
633 .ok_or(TrapError::TableOrElementAccessOutOfBounds)
634 .map(|r| *r = val)?;
635 trace!(
636 "Instruction: table.set '{}' [{} {}] -> []",
637 table_idx,
638 i,
639 val
640 )
641 }
642 UNREACHABLE => {
643 return Err(TrapError::ReachedUnreachable.into());
644 }
645 I32_LOAD => {
646 decrement_fuel!(T::get_flat_cost(I32_LOAD));
647 let memarg = MemArg::read(wasm).unwrap_validated();
648 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
649
650 let module = unsafe { store.modules.get(current_module) };
655
656 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
658 let mem_inst = unsafe { store.memories.get(mem_addr) };
661
662 let idx = calculate_mem_address(&memarg, relative_address)?;
663 let data = mem_inst.mem.load(idx)?;
664
665 stack.push_value::<T>(Value::I32(data))?;
666 trace!("Instruction: i32.load [{relative_address}] -> [{data}]");
667 }
668 I64_LOAD => {
669 decrement_fuel!(T::get_flat_cost(I64_LOAD));
670 let memarg = MemArg::read(wasm).unwrap_validated();
671 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
672
673 let module = unsafe { store.modules.get(current_module) };
678
679 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
681 let mem = unsafe { store.memories.get(mem_addr) };
684
685 let idx = calculate_mem_address(&memarg, relative_address)?;
686 let data = mem.mem.load(idx)?;
687
688 stack.push_value::<T>(Value::I64(data))?;
689 trace!("Instruction: i64.load [{relative_address}] -> [{data}]");
690 }
691 F32_LOAD => {
692 decrement_fuel!(T::get_flat_cost(F32_LOAD));
693 let memarg = MemArg::read(wasm).unwrap_validated();
694 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
695
696 let module = unsafe { store.modules.get(current_module) };
701
702 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
704 let mem = unsafe { store.memories.get(mem_addr) };
707
708 let idx = calculate_mem_address(&memarg, relative_address)?;
709 let data = mem.mem.load(idx)?;
710
711 stack.push_value::<T>(Value::F32(data))?;
712 trace!("Instruction: f32.load [{relative_address}] -> [{data}]");
713 }
714 F64_LOAD => {
715 decrement_fuel!(T::get_flat_cost(F64_LOAD));
716 let memarg = MemArg::read(wasm).unwrap_validated();
717 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
718
719 let module = unsafe { store.modules.get(current_module) };
724
725 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
727 let mem = unsafe { store.memories.get(mem_addr) };
730
731 let idx = calculate_mem_address(&memarg, relative_address)?;
732 let data = mem.mem.load(idx)?;
733
734 stack.push_value::<T>(Value::F64(data))?;
735 trace!("Instruction: f64.load [{relative_address}] -> [{data}]");
736 }
737 I32_LOAD8_S => {
738 decrement_fuel!(T::get_flat_cost(I32_LOAD8_S));
739 let memarg = MemArg::read(wasm).unwrap_validated();
740 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
741
742 let module = unsafe { store.modules.get(current_module) };
747
748 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
750 let mem = unsafe { store.memories.get(mem_addr) };
753
754 let idx = calculate_mem_address(&memarg, relative_address)?;
755 let data: i8 = mem.mem.load(idx)?;
756
757 stack.push_value::<T>(Value::I32(data as u32))?;
758 trace!("Instruction: i32.load8_s [{relative_address}] -> [{data}]");
759 }
760 I32_LOAD8_U => {
761 decrement_fuel!(T::get_flat_cost(I32_LOAD8_U));
762 let memarg = MemArg::read(wasm).unwrap_validated();
763 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
764
765 let module = unsafe { store.modules.get(current_module) };
770
771 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
773 let mem = unsafe { store.memories.get(mem_addr) };
776
777 let idx = calculate_mem_address(&memarg, relative_address)?;
778 let data: u8 = mem.mem.load(idx)?;
779
780 stack.push_value::<T>(Value::I32(data as u32))?;
781 trace!("Instruction: i32.load8_u [{relative_address}] -> [{data}]");
782 }
783 I32_LOAD16_S => {
784 decrement_fuel!(T::get_flat_cost(I32_LOAD16_S));
785 let memarg = MemArg::read(wasm).unwrap_validated();
786 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
787
788 let module = unsafe { store.modules.get(current_module) };
793
794 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
796 let mem = unsafe { store.memories.get(mem_addr) };
799
800 let idx = calculate_mem_address(&memarg, relative_address)?;
801 let data: i16 = mem.mem.load(idx)?;
802
803 stack.push_value::<T>(Value::I32(data as u32))?;
804 trace!("Instruction: i32.load16_s [{relative_address}] -> [{data}]");
805 }
806 I32_LOAD16_U => {
807 decrement_fuel!(T::get_flat_cost(I32_LOAD16_U));
808 let memarg = MemArg::read(wasm).unwrap_validated();
809 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
810
811 let module = unsafe { store.modules.get(current_module) };
816
817 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
819 let mem = unsafe { store.memories.get(mem_addr) };
822
823 let idx = calculate_mem_address(&memarg, relative_address)?;
824 let data: u16 = mem.mem.load(idx)?;
825
826 stack.push_value::<T>(Value::I32(data as u32))?;
827 trace!("Instruction: i32.load16_u [{relative_address}] -> [{data}]");
828 }
829 I64_LOAD8_S => {
830 decrement_fuel!(T::get_flat_cost(I64_LOAD8_S));
831 let memarg = MemArg::read(wasm).unwrap_validated();
832 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
833
834 let module = unsafe { store.modules.get(current_module) };
839
840 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
842 let mem = unsafe { store.memories.get(mem_addr) };
845
846 let idx = calculate_mem_address(&memarg, relative_address)?;
847 let data: i8 = mem.mem.load(idx)?;
848
849 stack.push_value::<T>(Value::I64(data as u64))?;
850 trace!("Instruction: i64.load8_s [{relative_address}] -> [{data}]");
851 }
852 I64_LOAD8_U => {
853 decrement_fuel!(T::get_flat_cost(I64_LOAD8_U));
854 let memarg = MemArg::read(wasm).unwrap_validated();
855 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
856
857 let module = unsafe { store.modules.get(current_module) };
862
863 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
865 let mem = unsafe { store.memories.get(mem_addr) };
868
869 let idx = calculate_mem_address(&memarg, relative_address)?;
870 let data: u8 = mem.mem.load(idx)?;
871
872 stack.push_value::<T>(Value::I64(data as u64))?;
873 trace!("Instruction: i64.load8_u [{relative_address}] -> [{data}]");
874 }
875 I64_LOAD16_S => {
876 decrement_fuel!(T::get_flat_cost(I64_LOAD16_S));
877 let memarg = MemArg::read(wasm).unwrap_validated();
878 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
879
880 let module = unsafe { store.modules.get(current_module) };
885
886 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
888 let mem = unsafe { store.memories.get(mem_addr) };
891
892 let idx = calculate_mem_address(&memarg, relative_address)?;
893 let data: i16 = mem.mem.load(idx)?;
894
895 stack.push_value::<T>(Value::I64(data as u64))?;
896 trace!("Instruction: i64.load16_s [{relative_address}] -> [{data}]");
897 }
898 I64_LOAD16_U => {
899 decrement_fuel!(T::get_flat_cost(I64_LOAD16_U));
900 let memarg = MemArg::read(wasm).unwrap_validated();
901 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
902
903 let module = unsafe { store.modules.get(current_module) };
908
909 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
911 let mem = unsafe { store.memories.get(mem_addr) };
914
915 let idx = calculate_mem_address(&memarg, relative_address)?;
916 let data: u16 = mem.mem.load(idx)?;
917
918 stack.push_value::<T>(Value::I64(data as u64))?;
919 trace!("Instruction: i64.load16_u [{relative_address}] -> [{data}]");
920 }
921 I64_LOAD32_S => {
922 decrement_fuel!(T::get_flat_cost(I64_LOAD32_S));
923 let memarg = MemArg::read(wasm).unwrap_validated();
924 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
925
926 let module = unsafe { store.modules.get(current_module) };
931
932 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
934 let mem = unsafe { store.memories.get(mem_addr) };
937
938 let idx = calculate_mem_address(&memarg, relative_address)?;
939 let data: i32 = mem.mem.load(idx)?;
940
941 stack.push_value::<T>(Value::I64(data as u64))?;
942 trace!("Instruction: i64.load32_s [{relative_address}] -> [{data}]");
943 }
944 I64_LOAD32_U => {
945 decrement_fuel!(T::get_flat_cost(I64_LOAD32_U));
946 let memarg = MemArg::read(wasm).unwrap_validated();
947 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
948
949 let module = unsafe { store.modules.get(current_module) };
954
955 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
957 let mem = unsafe { store.memories.get(mem_addr) };
960
961 let idx = calculate_mem_address(&memarg, relative_address)?;
962 let data: u32 = mem.mem.load(idx)?;
963
964 stack.push_value::<T>(Value::I64(data as u64))?;
965 trace!("Instruction: i64.load32_u [{relative_address}] -> [{data}]");
966 }
967 I32_STORE => {
968 decrement_fuel!(T::get_flat_cost(I32_STORE));
969 let memarg = MemArg::read(wasm).unwrap_validated();
970
971 let data_to_store: u32 = stack.pop_value().try_into().unwrap_validated();
972 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
973
974 let module = unsafe { store.modules.get(current_module) };
979
980 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
982 let mem = unsafe { store.memories.get(mem_addr) };
985
986 let idx = calculate_mem_address(&memarg, relative_address)?;
987 mem.mem.store(idx, data_to_store)?;
988
989 trace!("Instruction: i32.store [{relative_address} {data_to_store}] -> []");
990 }
991 I64_STORE => {
992 decrement_fuel!(T::get_flat_cost(I64_STORE));
993 let memarg = MemArg::read(wasm).unwrap_validated();
994
995 let data_to_store: u64 = stack.pop_value().try_into().unwrap_validated();
996 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
997
998 let module = unsafe { store.modules.get(current_module) };
1003
1004 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1006 let mem = unsafe { store.memories.get(mem_addr) };
1009
1010 let idx = calculate_mem_address(&memarg, relative_address)?;
1011 mem.mem.store(idx, data_to_store)?;
1012
1013 trace!("Instruction: i64.store [{relative_address} {data_to_store}] -> []");
1014 }
1015 F32_STORE => {
1016 decrement_fuel!(T::get_flat_cost(F32_STORE));
1017 let memarg = MemArg::read(wasm).unwrap_validated();
1018
1019 let data_to_store: F32 = stack.pop_value().try_into().unwrap_validated();
1020 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
1021
1022 let module = unsafe { store.modules.get(current_module) };
1027
1028 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1030 let mem = unsafe { store.memories.get(mem_addr) };
1033
1034 let idx = calculate_mem_address(&memarg, relative_address)?;
1035 mem.mem.store(idx, data_to_store)?;
1036
1037 trace!("Instruction: f32.store [{relative_address} {data_to_store}] -> []");
1038 }
1039 F64_STORE => {
1040 decrement_fuel!(T::get_flat_cost(F64_STORE));
1041 let memarg = MemArg::read(wasm).unwrap_validated();
1042
1043 let data_to_store: F64 = stack.pop_value().try_into().unwrap_validated();
1044 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
1045
1046 let module = unsafe { store.modules.get(current_module) };
1051
1052 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1054 let mem = unsafe { store.memories.get(mem_addr) };
1057
1058 let idx = calculate_mem_address(&memarg, relative_address)?;
1059 mem.mem.store(idx, data_to_store)?;
1060
1061 trace!("Instruction: f64.store [{relative_address} {data_to_store}] -> []");
1062 }
1063 I32_STORE8 => {
1064 decrement_fuel!(T::get_flat_cost(I32_STORE8));
1065 let memarg = MemArg::read(wasm).unwrap_validated();
1066
1067 let data_to_store: i32 = stack.pop_value().try_into().unwrap_validated();
1068 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
1069
1070 let wrapped_data = data_to_store as i8;
1071
1072 let module = unsafe { store.modules.get(current_module) };
1077
1078 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1080 let mem = unsafe { store.memories.get(mem_addr) };
1083
1084 let idx = calculate_mem_address(&memarg, relative_address)?;
1085 mem.mem.store(idx, wrapped_data)?;
1086
1087 trace!("Instruction: i32.store8 [{relative_address} {wrapped_data}] -> []");
1088 }
1089 I32_STORE16 => {
1090 decrement_fuel!(T::get_flat_cost(I32_STORE16));
1091 let memarg = MemArg::read(wasm).unwrap_validated();
1092
1093 let data_to_store: i32 = stack.pop_value().try_into().unwrap_validated();
1094 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
1095
1096 let wrapped_data = data_to_store as i16;
1097
1098 let module = unsafe { store.modules.get(current_module) };
1103
1104 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1106 let mem = unsafe { store.memories.get(mem_addr) };
1109
1110 let idx = calculate_mem_address(&memarg, relative_address)?;
1111 mem.mem.store(idx, wrapped_data)?;
1112
1113 trace!("Instruction: i32.store16 [{relative_address} {data_to_store}] -> []");
1114 }
1115 I64_STORE8 => {
1116 decrement_fuel!(T::get_flat_cost(I64_STORE8));
1117 let memarg = MemArg::read(wasm).unwrap_validated();
1118
1119 let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
1120 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
1121
1122 let wrapped_data = data_to_store as i8;
1123
1124 let module = unsafe { store.modules.get(current_module) };
1129
1130 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1132 let mem = unsafe { store.memories.get(mem_addr) };
1135
1136 let idx = calculate_mem_address(&memarg, relative_address)?;
1137 mem.mem.store(idx, wrapped_data)?;
1138
1139 trace!("Instruction: i64.store8 [{relative_address} {data_to_store}] -> []");
1140 }
1141 I64_STORE16 => {
1142 decrement_fuel!(T::get_flat_cost(I64_STORE16));
1143 let memarg = MemArg::read(wasm).unwrap_validated();
1144
1145 let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
1146 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
1147
1148 let wrapped_data = data_to_store as i16;
1149
1150 let module = unsafe { store.modules.get(current_module) };
1155
1156 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1158 let mem = unsafe { store.memories.get(mem_addr) };
1161
1162 let idx = calculate_mem_address(&memarg, relative_address)?;
1163 mem.mem.store(idx, wrapped_data)?;
1164
1165 trace!("Instruction: i64.store16 [{relative_address} {data_to_store}] -> []");
1166 }
1167 I64_STORE32 => {
1168 decrement_fuel!(T::get_flat_cost(I64_STORE32));
1169 let memarg = MemArg::read(wasm).unwrap_validated();
1170
1171 let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
1172 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
1173
1174 let wrapped_data = data_to_store as i32;
1175
1176 let module = unsafe { store.modules.get(current_module) };
1181
1182 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1184 let mem = unsafe { store.memories.get(mem_addr) };
1187
1188 let idx = calculate_mem_address(&memarg, relative_address)?;
1189 mem.mem.store(idx, wrapped_data)?;
1190
1191 trace!("Instruction: i64.store32 [{relative_address} {data_to_store}] -> []");
1192 }
1193 MEMORY_SIZE => {
1194 decrement_fuel!(T::get_flat_cost(MEMORY_SIZE));
1195 let _zero = wasm.read_u8().unwrap_validated();
1198 let module = unsafe { store.modules.get(current_module) };
1203
1204 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1206 let mem = unsafe { store.memories.get(mem_addr) };
1209 let size = mem.size() as u32;
1210 stack.push_value::<T>(Value::I32(size))?;
1211 trace!("Instruction: memory.size [] -> [{}]", size);
1212 }
1213 MEMORY_GROW => {
1214 let _zero = wasm.read_u8().unwrap_validated();
1217 let module = unsafe { store.modules.get(current_module) };
1222
1223 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1225 let mem = unsafe { store.memories.get_mut(mem_addr) };
1228
1229 let sz: u32 = mem.size() as u32;
1230
1231 let n: u32 = stack.pop_value().try_into().unwrap_validated();
1232 let cost = T::get_flat_cost(MEMORY_GROW)
1234 + u64::from(n) * T::get_cost_per_element(MEMORY_GROW);
1235 if let Some(fuel) = &mut resumable.maybe_fuel {
1236 if *fuel >= cost {
1237 *fuel -= cost;
1238 } else {
1239 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
1241 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
1243 return Ok(NonZeroU64::new(cost - *fuel));
1244 }
1245 }
1246
1247 let pushed_value = match mem.grow(n) {
1251 Ok(_) => sz,
1252 Err(_) => u32::MAX,
1253 };
1254 stack.push_value::<T>(Value::I32(pushed_value))?;
1255 trace!("Instruction: memory.grow [{}] -> [{}]", n, pushed_value);
1256 }
1257 I32_CONST => {
1258 decrement_fuel!(T::get_flat_cost(I32_CONST));
1259 let constant = wasm.read_var_i32().unwrap_validated();
1260 trace!("Instruction: i32.const [] -> [{constant}]");
1261 stack.push_value::<T>(constant.into())?;
1262 }
1263 F32_CONST => {
1264 decrement_fuel!(T::get_flat_cost(F32_CONST));
1265 let constant = F32::from_bits(wasm.read_f32().unwrap_validated());
1266 trace!("Instruction: f32.const [] -> [{constant:.7}]");
1267 stack.push_value::<T>(constant.into())?;
1268 }
1269 I32_EQZ => {
1270 decrement_fuel!(T::get_flat_cost(I32_EQZ));
1271 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1272
1273 let res = if v1 == 0 { 1 } else { 0 };
1274
1275 trace!("Instruction: i32.eqz [{v1}] -> [{res}]");
1276 stack.push_value::<T>(res.into())?;
1277 }
1278 I32_EQ => {
1279 decrement_fuel!(T::get_flat_cost(I32_EQ));
1280 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1281 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1282
1283 let res = if v1 == v2 { 1 } else { 0 };
1284
1285 trace!("Instruction: i32.eq [{v1} {v2}] -> [{res}]");
1286 stack.push_value::<T>(res.into())?;
1287 }
1288 I32_NE => {
1289 decrement_fuel!(T::get_flat_cost(I32_NE));
1290 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1291 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1292
1293 let res = if v1 != v2 { 1 } else { 0 };
1294
1295 trace!("Instruction: i32.ne [{v1} {v2}] -> [{res}]");
1296 stack.push_value::<T>(res.into())?;
1297 }
1298 I32_LT_S => {
1299 decrement_fuel!(T::get_flat_cost(I32_LT_S));
1300 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1301 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1302
1303 let res = if v1 < v2 { 1 } else { 0 };
1304
1305 trace!("Instruction: i32.lt_s [{v1} {v2}] -> [{res}]");
1306 stack.push_value::<T>(res.into())?;
1307 }
1308
1309 I32_LT_U => {
1310 decrement_fuel!(T::get_flat_cost(I32_LT_U));
1311 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1312 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1313
1314 let res = if (v1 as u32) < (v2 as u32) { 1 } else { 0 };
1315
1316 trace!("Instruction: i32.lt_u [{v1} {v2}] -> [{res}]");
1317 stack.push_value::<T>(res.into())?;
1318 }
1319 I32_GT_S => {
1320 decrement_fuel!(T::get_flat_cost(I32_GT_S));
1321 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1322 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1323
1324 let res = if v1 > v2 { 1 } else { 0 };
1325
1326 trace!("Instruction: i32.gt_s [{v1} {v2}] -> [{res}]");
1327 stack.push_value::<T>(res.into())?;
1328 }
1329 I32_GT_U => {
1330 decrement_fuel!(T::get_flat_cost(I32_GT_U));
1331 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1332 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1333
1334 let res = if (v1 as u32) > (v2 as u32) { 1 } else { 0 };
1335
1336 trace!("Instruction: i32.gt_u [{v1} {v2}] -> [{res}]");
1337 stack.push_value::<T>(res.into())?;
1338 }
1339 I32_LE_S => {
1340 decrement_fuel!(T::get_flat_cost(I32_LE_S));
1341 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1342 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1343
1344 let res = if v1 <= v2 { 1 } else { 0 };
1345
1346 trace!("Instruction: i32.le_s [{v1} {v2}] -> [{res}]");
1347 stack.push_value::<T>(res.into())?;
1348 }
1349 I32_LE_U => {
1350 decrement_fuel!(T::get_flat_cost(I32_LE_U));
1351 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1352 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1353
1354 let res = if (v1 as u32) <= (v2 as u32) { 1 } else { 0 };
1355
1356 trace!("Instruction: i32.le_u [{v1} {v2}] -> [{res}]");
1357 stack.push_value::<T>(res.into())?;
1358 }
1359 I32_GE_S => {
1360 decrement_fuel!(T::get_flat_cost(I32_GE_S));
1361 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1362 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1363
1364 let res = if v1 >= v2 { 1 } else { 0 };
1365
1366 trace!("Instruction: i32.ge_s [{v1} {v2}] -> [{res}]");
1367 stack.push_value::<T>(res.into())?;
1368 }
1369 I32_GE_U => {
1370 decrement_fuel!(T::get_flat_cost(I32_GE_U));
1371 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1372 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1373
1374 let res = if (v1 as u32) >= (v2 as u32) { 1 } else { 0 };
1375
1376 trace!("Instruction: i32.ge_u [{v1} {v2}] -> [{res}]");
1377 stack.push_value::<T>(res.into())?;
1378 }
1379 I64_EQZ => {
1380 decrement_fuel!(T::get_flat_cost(I64_EQZ));
1381 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1382
1383 let res = if v1 == 0 { 1 } else { 0 };
1384
1385 trace!("Instruction: i64.eqz [{v1}] -> [{res}]");
1386 stack.push_value::<T>(res.into())?;
1387 }
1388 I64_EQ => {
1389 decrement_fuel!(T::get_flat_cost(I64_EQ));
1390 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1391 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1392
1393 let res = if v1 == v2 { 1 } else { 0 };
1394
1395 trace!("Instruction: i64.eq [{v1} {v2}] -> [{res}]");
1396 stack.push_value::<T>(res.into())?;
1397 }
1398 I64_NE => {
1399 decrement_fuel!(T::get_flat_cost(I64_NE));
1400 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1401 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1402
1403 let res = if v1 != v2 { 1 } else { 0 };
1404
1405 trace!("Instruction: i64.ne [{v1} {v2}] -> [{res}]");
1406 stack.push_value::<T>(res.into())?;
1407 }
1408 I64_LT_S => {
1409 decrement_fuel!(T::get_flat_cost(I64_LT_S));
1410 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1411 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1412
1413 let res = if v1 < v2 { 1 } else { 0 };
1414
1415 trace!("Instruction: i64.lt_s [{v1} {v2}] -> [{res}]");
1416 stack.push_value::<T>(res.into())?;
1417 }
1418
1419 I64_LT_U => {
1420 decrement_fuel!(T::get_flat_cost(I64_LT_U));
1421 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1422 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1423
1424 let res = if (v1 as u64) < (v2 as u64) { 1 } else { 0 };
1425
1426 trace!("Instruction: i64.lt_u [{v1} {v2}] -> [{res}]");
1427 stack.push_value::<T>(res.into())?;
1428 }
1429 I64_GT_S => {
1430 decrement_fuel!(T::get_flat_cost(I64_GT_S));
1431 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1432 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1433
1434 let res = if v1 > v2 { 1 } else { 0 };
1435
1436 trace!("Instruction: i64.gt_s [{v1} {v2}] -> [{res}]");
1437 stack.push_value::<T>(res.into())?;
1438 }
1439 I64_GT_U => {
1440 decrement_fuel!(T::get_flat_cost(I64_GT_U));
1441 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1442 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1443
1444 let res = if (v1 as u64) > (v2 as u64) { 1 } else { 0 };
1445
1446 trace!("Instruction: i64.gt_u [{v1} {v2}] -> [{res}]");
1447 stack.push_value::<T>(res.into())?;
1448 }
1449 I64_LE_S => {
1450 decrement_fuel!(T::get_flat_cost(I64_LE_S));
1451 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1452 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1453
1454 let res = if v1 <= v2 { 1 } else { 0 };
1455
1456 trace!("Instruction: i64.le_s [{v1} {v2}] -> [{res}]");
1457 stack.push_value::<T>(res.into())?;
1458 }
1459 I64_LE_U => {
1460 decrement_fuel!(T::get_flat_cost(I64_LE_U));
1461 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1462 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1463
1464 let res = if (v1 as u64) <= (v2 as u64) { 1 } else { 0 };
1465
1466 trace!("Instruction: i64.le_u [{v1} {v2}] -> [{res}]");
1467 stack.push_value::<T>(res.into())?;
1468 }
1469 I64_GE_S => {
1470 decrement_fuel!(T::get_flat_cost(I64_GE_S));
1471 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1472 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1473
1474 let res = if v1 >= v2 { 1 } else { 0 };
1475
1476 trace!("Instruction: i64.ge_s [{v1} {v2}] -> [{res}]");
1477 stack.push_value::<T>(res.into())?;
1478 }
1479 I64_GE_U => {
1480 decrement_fuel!(T::get_flat_cost(I64_GE_U));
1481 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1482 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1483
1484 let res = if (v1 as u64) >= (v2 as u64) { 1 } else { 0 };
1485
1486 trace!("Instruction: i64.ge_u [{v1} {v2}] -> [{res}]");
1487 stack.push_value::<T>(res.into())?;
1488 }
1489 F32_EQ => {
1490 decrement_fuel!(T::get_flat_cost(F32_EQ));
1491 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1492 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1493
1494 let res = if v1 == v2 { 1 } else { 0 };
1495
1496 trace!("Instruction: f32.eq [{v1} {v2}] -> [{res}]");
1497 stack.push_value::<T>(res.into())?;
1498 }
1499 F32_NE => {
1500 decrement_fuel!(T::get_flat_cost(F32_NE));
1501 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1502 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1503
1504 let res = if v1 != v2 { 1 } else { 0 };
1505
1506 trace!("Instruction: f32.ne [{v1} {v2}] -> [{res}]");
1507 stack.push_value::<T>(res.into())?;
1508 }
1509 F32_LT => {
1510 decrement_fuel!(T::get_flat_cost(F32_LT));
1511 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1512 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1513
1514 let res = if v1 < v2 { 1 } else { 0 };
1515
1516 trace!("Instruction: f32.lt [{v1} {v2}] -> [{res}]");
1517 stack.push_value::<T>(res.into())?;
1518 }
1519 F32_GT => {
1520 decrement_fuel!(T::get_flat_cost(F32_GT));
1521 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1522 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1523
1524 let res = if v1 > v2 { 1 } else { 0 };
1525
1526 trace!("Instruction: f32.gt [{v1} {v2}] -> [{res}]");
1527 stack.push_value::<T>(res.into())?;
1528 }
1529 F32_LE => {
1530 decrement_fuel!(T::get_flat_cost(F32_LE));
1531 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1532 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1533
1534 let res = if v1 <= v2 { 1 } else { 0 };
1535
1536 trace!("Instruction: f32.le [{v1} {v2}] -> [{res}]");
1537 stack.push_value::<T>(res.into())?;
1538 }
1539 F32_GE => {
1540 decrement_fuel!(T::get_flat_cost(F32_GE));
1541 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
1542 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
1543
1544 let res = if v1 >= v2 { 1 } else { 0 };
1545
1546 trace!("Instruction: f32.ge [{v1} {v2}] -> [{res}]");
1547 stack.push_value::<T>(res.into())?;
1548 }
1549
1550 F64_EQ => {
1551 decrement_fuel!(T::get_flat_cost(F64_EQ));
1552 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1553 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1554
1555 let res = if v1 == v2 { 1 } else { 0 };
1556
1557 trace!("Instruction: f64.eq [{v1} {v2}] -> [{res}]");
1558 stack.push_value::<T>(res.into())?;
1559 }
1560 F64_NE => {
1561 decrement_fuel!(T::get_flat_cost(F64_NE));
1562 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1563 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1564
1565 let res = if v1 != v2 { 1 } else { 0 };
1566
1567 trace!("Instruction: f64.ne [{v1} {v2}] -> [{res}]");
1568 stack.push_value::<T>(res.into())?;
1569 }
1570 F64_LT => {
1571 decrement_fuel!(T::get_flat_cost(F64_LT));
1572 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1573 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1574
1575 let res = if v1 < v2 { 1 } else { 0 };
1576
1577 trace!("Instruction: f64.lt [{v1} {v2}] -> [{res}]");
1578 stack.push_value::<T>(res.into())?;
1579 }
1580 F64_GT => {
1581 decrement_fuel!(T::get_flat_cost(F64_GT));
1582 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1583 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1584
1585 let res = if v1 > v2 { 1 } else { 0 };
1586
1587 trace!("Instruction: f64.gt [{v1} {v2}] -> [{res}]");
1588 stack.push_value::<T>(res.into())?;
1589 }
1590 F64_LE => {
1591 decrement_fuel!(T::get_flat_cost(F64_LE));
1592 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1593 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1594
1595 let res = if v1 <= v2 { 1 } else { 0 };
1596
1597 trace!("Instruction: f64.le [{v1} {v2}] -> [{res}]");
1598 stack.push_value::<T>(res.into())?;
1599 }
1600 F64_GE => {
1601 decrement_fuel!(T::get_flat_cost(F64_GE));
1602 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
1603 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
1604
1605 let res = if v1 >= v2 { 1 } else { 0 };
1606
1607 trace!("Instruction: f64.ge [{v1} {v2}] -> [{res}]");
1608 stack.push_value::<T>(res.into())?;
1609 }
1610
1611 I32_CLZ => {
1612 decrement_fuel!(T::get_flat_cost(I32_CLZ));
1613 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1614 let res = v1.leading_zeros() as i32;
1615
1616 trace!("Instruction: i32.clz [{v1}] -> [{res}]");
1617 stack.push_value::<T>(res.into())?;
1618 }
1619 I32_CTZ => {
1620 decrement_fuel!(T::get_flat_cost(I32_CTZ));
1621 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1622 let res = v1.trailing_zeros() as i32;
1623
1624 trace!("Instruction: i32.ctz [{v1}] -> [{res}]");
1625 stack.push_value::<T>(res.into())?;
1626 }
1627 I32_POPCNT => {
1628 decrement_fuel!(T::get_flat_cost(I32_POPCNT));
1629 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1630 let res = v1.count_ones() as i32;
1631
1632 trace!("Instruction: i32.popcnt [{v1}] -> [{res}]");
1633 stack.push_value::<T>(res.into())?;
1634 }
1635 I64_CONST => {
1636 decrement_fuel!(T::get_flat_cost(I64_CONST));
1637 let constant = wasm.read_var_i64().unwrap_validated();
1638 trace!("Instruction: i64.const [] -> [{constant}]");
1639 stack.push_value::<T>(constant.into())?;
1640 }
1641 F64_CONST => {
1642 decrement_fuel!(T::get_flat_cost(F64_CONST));
1643 let constant = F64::from_bits(wasm.read_f64().unwrap_validated());
1644 trace!("Instruction: f64.const [] -> [{constant}]");
1645 stack.push_value::<T>(constant.into())?;
1646 }
1647 I32_ADD => {
1648 decrement_fuel!(T::get_flat_cost(I32_ADD));
1649 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1650 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1651 let res = v1.wrapping_add(v2);
1652
1653 trace!("Instruction: i32.add [{v1} {v2}] -> [{res}]");
1654 stack.push_value::<T>(res.into())?;
1655 }
1656 I32_SUB => {
1657 decrement_fuel!(T::get_flat_cost(I32_SUB));
1658 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1659 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1660 let res = v1.wrapping_sub(v2);
1661
1662 trace!("Instruction: i32.sub [{v1} {v2}] -> [{res}]");
1663 stack.push_value::<T>(res.into())?;
1664 }
1665 I32_MUL => {
1666 decrement_fuel!(T::get_flat_cost(I32_MUL));
1667 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1668 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1669 let res = v1.wrapping_mul(v2);
1670
1671 trace!("Instruction: i32.mul [{v1} {v2}] -> [{res}]");
1672 stack.push_value::<T>(res.into())?;
1673 }
1674 I32_DIV_S => {
1675 decrement_fuel!(T::get_flat_cost(I32_DIV_S));
1676 let dividend: i32 = stack.pop_value().try_into().unwrap_validated();
1677 let divisor: i32 = stack.pop_value().try_into().unwrap_validated();
1678
1679 if dividend == 0 {
1680 return Err(TrapError::DivideBy0.into());
1681 }
1682 if divisor == i32::MIN && dividend == -1 {
1683 return Err(TrapError::UnrepresentableResult.into());
1684 }
1685
1686 let res = divisor / dividend;
1687
1688 trace!("Instruction: i32.div_s [{divisor} {dividend}] -> [{res}]");
1689 stack.push_value::<T>(res.into())?;
1690 }
1691 I32_DIV_U => {
1692 decrement_fuel!(T::get_flat_cost(I32_DIV_U));
1693 let dividend: i32 = stack.pop_value().try_into().unwrap_validated();
1694 let divisor: i32 = stack.pop_value().try_into().unwrap_validated();
1695
1696 let dividend = dividend as u32;
1697 let divisor = divisor as u32;
1698
1699 if dividend == 0 {
1700 return Err(TrapError::DivideBy0.into());
1701 }
1702
1703 let res = (divisor / dividend) as i32;
1704
1705 trace!("Instruction: i32.div_u [{divisor} {dividend}] -> [{res}]");
1706 stack.push_value::<T>(res.into())?;
1707 }
1708 I32_REM_S => {
1709 decrement_fuel!(T::get_flat_cost(I32_REM_S));
1710 let dividend: i32 = stack.pop_value().try_into().unwrap_validated();
1711 let divisor: i32 = stack.pop_value().try_into().unwrap_validated();
1712
1713 if dividend == 0 {
1714 return Err(TrapError::DivideBy0.into());
1715 }
1716
1717 let res = divisor.checked_rem(dividend);
1718 let res = res.unwrap_or_default();
1719
1720 trace!("Instruction: i32.rem_s [{divisor} {dividend}] -> [{res}]");
1721 stack.push_value::<T>(res.into())?;
1722 }
1723 I64_CLZ => {
1724 decrement_fuel!(T::get_flat_cost(I64_CLZ));
1725 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1726 let res = v1.leading_zeros() as i64;
1727
1728 trace!("Instruction: i64.clz [{v1}] -> [{res}]");
1729 stack.push_value::<T>(res.into())?;
1730 }
1731 I64_CTZ => {
1732 decrement_fuel!(T::get_flat_cost(I64_CTZ));
1733 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1734 let res = v1.trailing_zeros() as i64;
1735
1736 trace!("Instruction: i64.ctz [{v1}] -> [{res}]");
1737 stack.push_value::<T>(res.into())?;
1738 }
1739 I64_POPCNT => {
1740 decrement_fuel!(T::get_flat_cost(I64_POPCNT));
1741 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1742 let res = v1.count_ones() as i64;
1743
1744 trace!("Instruction: i64.popcnt [{v1}] -> [{res}]");
1745 stack.push_value::<T>(res.into())?;
1746 }
1747 I64_ADD => {
1748 decrement_fuel!(T::get_flat_cost(I64_ADD));
1749 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1750 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1751 let res = v1.wrapping_add(v2);
1752
1753 trace!("Instruction: i64.add [{v1} {v2}] -> [{res}]");
1754 stack.push_value::<T>(res.into())?;
1755 }
1756 I64_SUB => {
1757 decrement_fuel!(T::get_flat_cost(I64_SUB));
1758 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1759 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1760 let res = v1.wrapping_sub(v2);
1761
1762 trace!("Instruction: i64.sub [{v1} {v2}] -> [{res}]");
1763 stack.push_value::<T>(res.into())?;
1764 }
1765 I64_MUL => {
1766 decrement_fuel!(T::get_flat_cost(I64_MUL));
1767 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1768 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1769 let res = v1.wrapping_mul(v2);
1770
1771 trace!("Instruction: i64.mul [{v1} {v2}] -> [{res}]");
1772 stack.push_value::<T>(res.into())?;
1773 }
1774 I64_DIV_S => {
1775 decrement_fuel!(T::get_flat_cost(I64_DIV_S));
1776 let dividend: i64 = stack.pop_value().try_into().unwrap_validated();
1777 let divisor: i64 = stack.pop_value().try_into().unwrap_validated();
1778
1779 if dividend == 0 {
1780 return Err(TrapError::DivideBy0.into());
1781 }
1782 if divisor == i64::MIN && dividend == -1 {
1783 return Err(TrapError::UnrepresentableResult.into());
1784 }
1785
1786 let res = divisor / dividend;
1787
1788 trace!("Instruction: i64.div_s [{divisor} {dividend}] -> [{res}]");
1789 stack.push_value::<T>(res.into())?;
1790 }
1791 I64_DIV_U => {
1792 decrement_fuel!(T::get_flat_cost(I64_DIV_U));
1793 let dividend: i64 = stack.pop_value().try_into().unwrap_validated();
1794 let divisor: i64 = stack.pop_value().try_into().unwrap_validated();
1795
1796 let dividend = dividend as u64;
1797 let divisor = divisor as u64;
1798
1799 if dividend == 0 {
1800 return Err(TrapError::DivideBy0.into());
1801 }
1802
1803 let res = (divisor / dividend) as i64;
1804
1805 trace!("Instruction: i64.div_u [{divisor} {dividend}] -> [{res}]");
1806 stack.push_value::<T>(res.into())?;
1807 }
1808 I64_REM_S => {
1809 decrement_fuel!(T::get_flat_cost(I64_REM_S));
1810 let dividend: i64 = stack.pop_value().try_into().unwrap_validated();
1811 let divisor: i64 = stack.pop_value().try_into().unwrap_validated();
1812
1813 if dividend == 0 {
1814 return Err(TrapError::DivideBy0.into());
1815 }
1816
1817 let res = divisor.checked_rem(dividend);
1818 let res = res.unwrap_or_default();
1819
1820 trace!("Instruction: i64.rem_s [{divisor} {dividend}] -> [{res}]");
1821 stack.push_value::<T>(res.into())?;
1822 }
1823 I64_REM_U => {
1824 decrement_fuel!(T::get_flat_cost(I64_REM_U));
1825 let dividend: i64 = stack.pop_value().try_into().unwrap_validated();
1826 let divisor: i64 = stack.pop_value().try_into().unwrap_validated();
1827
1828 let dividend = dividend as u64;
1829 let divisor = divisor as u64;
1830
1831 if dividend == 0 {
1832 return Err(TrapError::DivideBy0.into());
1833 }
1834
1835 let res = (divisor % dividend) as i64;
1836
1837 trace!("Instruction: i64.rem_u [{divisor} {dividend}] -> [{res}]");
1838 stack.push_value::<T>(res.into())?;
1839 }
1840 I64_AND => {
1841 decrement_fuel!(T::get_flat_cost(I64_AND));
1842 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1843 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1844
1845 let res = v1 & v2;
1846
1847 trace!("Instruction: i64.and [{v1} {v2}] -> [{res}]");
1848 stack.push_value::<T>(res.into())?;
1849 }
1850 I64_OR => {
1851 decrement_fuel!(T::get_flat_cost(I64_OR));
1852 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1853 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1854
1855 let res = v1 | v2;
1856
1857 trace!("Instruction: i64.or [{v1} {v2}] -> [{res}]");
1858 stack.push_value::<T>(res.into())?;
1859 }
1860 I64_XOR => {
1861 decrement_fuel!(T::get_flat_cost(I64_XOR));
1862 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1863 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1864
1865 let res = v1 ^ v2;
1866
1867 trace!("Instruction: i64.xor [{v1} {v2}] -> [{res}]");
1868 stack.push_value::<T>(res.into())?;
1869 }
1870 I64_SHL => {
1871 decrement_fuel!(T::get_flat_cost(I64_SHL));
1872 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1873 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1874
1875 let res = v1.wrapping_shl((v2 & 63) as u32);
1876
1877 trace!("Instruction: i64.shl [{v1} {v2}] -> [{res}]");
1878 stack.push_value::<T>(res.into())?;
1879 }
1880 I64_SHR_S => {
1881 decrement_fuel!(T::get_flat_cost(I64_SHR_S));
1882 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1883 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1884
1885 let res = v1.wrapping_shr((v2 & 63) as u32);
1886
1887 trace!("Instruction: i64.shr_s [{v1} {v2}] -> [{res}]");
1888 stack.push_value::<T>(res.into())?;
1889 }
1890 I64_SHR_U => {
1891 decrement_fuel!(T::get_flat_cost(I64_SHR_U));
1892 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1893 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1894
1895 let res = (v1 as u64).wrapping_shr((v2 & 63) as u32);
1896
1897 trace!("Instruction: i64.shr_u [{v1} {v2}] -> [{res}]");
1898 stack.push_value::<T>(res.into())?;
1899 }
1900 I64_ROTL => {
1901 decrement_fuel!(T::get_flat_cost(I64_ROTL));
1902 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1903 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1904
1905 let res = v1.rotate_left((v2 & 63) as u32);
1906
1907 trace!("Instruction: i64.rotl [{v1} {v2}] -> [{res}]");
1908 stack.push_value::<T>(res.into())?;
1909 }
1910 I64_ROTR => {
1911 decrement_fuel!(T::get_flat_cost(I64_ROTR));
1912 let v2: i64 = stack.pop_value().try_into().unwrap_validated();
1913 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
1914
1915 let res = v1.rotate_right((v2 & 63) as u32);
1916
1917 trace!("Instruction: i64.rotr [{v1} {v2}] -> [{res}]");
1918 stack.push_value::<T>(res.into())?;
1919 }
1920 I32_REM_U => {
1921 decrement_fuel!(T::get_flat_cost(I32_REM_U));
1922 let dividend: i32 = stack.pop_value().try_into().unwrap_validated();
1923 let divisor: i32 = stack.pop_value().try_into().unwrap_validated();
1924
1925 let dividend = dividend as u32;
1926 let divisor = divisor as u32;
1927
1928 if dividend == 0 {
1929 return Err(TrapError::DivideBy0.into());
1930 }
1931
1932 let res = divisor.checked_rem(dividend);
1933 let res = res.unwrap_or_default() as i32;
1934
1935 trace!("Instruction: i32.rem_u [{divisor} {dividend}] -> [{res}]");
1936 stack.push_value::<T>(res.into())?;
1937 }
1938 I32_AND => {
1939 decrement_fuel!(T::get_flat_cost(I32_AND));
1940 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1941 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1942 let res = v1 & v2;
1943
1944 trace!("Instruction: i32.and [{v1} {v2}] -> [{res}]");
1945 stack.push_value::<T>(res.into())?;
1946 }
1947 I32_OR => {
1948 decrement_fuel!(T::get_flat_cost(I32_OR));
1949 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1950 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1951 let res = v1 | v2;
1952
1953 trace!("Instruction: i32.or [{v1} {v2}] -> [{res}]");
1954 stack.push_value::<T>(res.into())?;
1955 }
1956 I32_XOR => {
1957 decrement_fuel!(T::get_flat_cost(I32_XOR));
1958 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1959 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1960 let res = v1 ^ v2;
1961
1962 trace!("Instruction: i32.xor [{v1} {v2}] -> [{res}]");
1963 stack.push_value::<T>(res.into())?;
1964 }
1965 I32_SHL => {
1966 decrement_fuel!(T::get_flat_cost(I32_SHL));
1967 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1968 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1969 let res = v2.wrapping_shl(v1 as u32);
1970
1971 trace!("Instruction: i32.shl [{v2} {v1}] -> [{res}]");
1972 stack.push_value::<T>(res.into())?;
1973 }
1974 I32_SHR_S => {
1975 decrement_fuel!(T::get_flat_cost(I32_SHR_S));
1976 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1977 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1978
1979 let res = v2.wrapping_shr(v1 as u32);
1980
1981 trace!("Instruction: i32.shr_s [{v2} {v1}] -> [{res}]");
1982 stack.push_value::<T>(res.into())?;
1983 }
1984 I32_SHR_U => {
1985 decrement_fuel!(T::get_flat_cost(I32_SHR_U));
1986 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1987 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1988
1989 let res = (v2 as u32).wrapping_shr(v1 as u32) as i32;
1990
1991 trace!("Instruction: i32.shr_u [{v2} {v1}] -> [{res}]");
1992 stack.push_value::<T>(res.into())?;
1993 }
1994 I32_ROTL => {
1995 decrement_fuel!(T::get_flat_cost(I32_ROTL));
1996 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
1997 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
1998
1999 let res = v2.rotate_left(v1 as u32);
2000
2001 trace!("Instruction: i32.rotl [{v2} {v1}] -> [{res}]");
2002 stack.push_value::<T>(res.into())?;
2003 }
2004 I32_ROTR => {
2005 decrement_fuel!(T::get_flat_cost(I32_ROTR));
2006 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
2007 let v2: i32 = stack.pop_value().try_into().unwrap_validated();
2008
2009 let res = v2.rotate_right(v1 as u32);
2010
2011 trace!("Instruction: i32.rotr [{v2} {v1}] -> [{res}]");
2012 stack.push_value::<T>(res.into())?;
2013 }
2014
2015 F32_ABS => {
2016 decrement_fuel!(T::get_flat_cost(F32_ABS));
2017 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2018 let res: value::F32 = v1.abs();
2019
2020 trace!("Instruction: f32.abs [{v1}] -> [{res}]");
2021 stack.push_value::<T>(res.into())?;
2022 }
2023 F32_NEG => {
2024 decrement_fuel!(T::get_flat_cost(F32_NEG));
2025 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2026 let res: value::F32 = v1.neg();
2027
2028 trace!("Instruction: f32.neg [{v1}] -> [{res}]");
2029 stack.push_value::<T>(res.into())?;
2030 }
2031 F32_CEIL => {
2032 decrement_fuel!(T::get_flat_cost(F32_CEIL));
2033 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2034 let res: value::F32 = v1.ceil();
2035
2036 trace!("Instruction: f32.ceil [{v1}] -> [{res}]");
2037 stack.push_value::<T>(res.into())?;
2038 }
2039 F32_FLOOR => {
2040 decrement_fuel!(T::get_flat_cost(F32_FLOOR));
2041 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2042 let res: value::F32 = v1.floor();
2043
2044 trace!("Instruction: f32.floor [{v1}] -> [{res}]");
2045 stack.push_value::<T>(res.into())?;
2046 }
2047 F32_TRUNC => {
2048 decrement_fuel!(T::get_flat_cost(F32_TRUNC));
2049 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2050 let res: value::F32 = v1.trunc();
2051
2052 trace!("Instruction: f32.trunc [{v1}] -> [{res}]");
2053 stack.push_value::<T>(res.into())?;
2054 }
2055 F32_NEAREST => {
2056 decrement_fuel!(T::get_flat_cost(F32_NEAREST));
2057 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2058 let res: value::F32 = v1.nearest();
2059
2060 trace!("Instruction: f32.nearest [{v1}] -> [{res}]");
2061 stack.push_value::<T>(res.into())?;
2062 }
2063 F32_SQRT => {
2064 decrement_fuel!(T::get_flat_cost(F32_SQRT));
2065 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2066 let res: value::F32 = v1.sqrt();
2067
2068 trace!("Instruction: f32.sqrt [{v1}] -> [{res}]");
2069 stack.push_value::<T>(res.into())?;
2070 }
2071 F32_ADD => {
2072 decrement_fuel!(T::get_flat_cost(F32_ADD));
2073 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
2074 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2075 let res: value::F32 = v1 + v2;
2076
2077 trace!("Instruction: f32.add [{v1} {v2}] -> [{res}]");
2078 stack.push_value::<T>(res.into())?;
2079 }
2080 F32_SUB => {
2081 decrement_fuel!(T::get_flat_cost(F32_SUB));
2082 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
2083 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2084 let res: value::F32 = v1 - v2;
2085
2086 trace!("Instruction: f32.sub [{v1} {v2}] -> [{res}]");
2087 stack.push_value::<T>(res.into())?;
2088 }
2089 F32_MUL => {
2090 decrement_fuel!(T::get_flat_cost(F32_MUL));
2091 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
2092 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2093 let res: value::F32 = v1 * v2;
2094
2095 trace!("Instruction: f32.mul [{v1} {v2}] -> [{res}]");
2096 stack.push_value::<T>(res.into())?;
2097 }
2098 F32_DIV => {
2099 decrement_fuel!(T::get_flat_cost(F32_DIV));
2100 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
2101 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2102 let res: value::F32 = v1 / v2;
2103
2104 trace!("Instruction: f32.div [{v1} {v2}] -> [{res}]");
2105 stack.push_value::<T>(res.into())?;
2106 }
2107 F32_MIN => {
2108 decrement_fuel!(T::get_flat_cost(F32_MIN));
2109 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
2110 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2111 let res: value::F32 = v1.min(v2);
2112
2113 trace!("Instruction: f32.min [{v1} {v2}] -> [{res}]");
2114 stack.push_value::<T>(res.into())?;
2115 }
2116 F32_MAX => {
2117 decrement_fuel!(T::get_flat_cost(F32_MAX));
2118 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
2119 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2120 let res: value::F32 = v1.max(v2);
2121
2122 trace!("Instruction: f32.max [{v1} {v2}] -> [{res}]");
2123 stack.push_value::<T>(res.into())?;
2124 }
2125 F32_COPYSIGN => {
2126 decrement_fuel!(T::get_flat_cost(F32_COPYSIGN));
2127 let v2: value::F32 = stack.pop_value().try_into().unwrap_validated();
2128 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2129 let res: value::F32 = v1.copysign(v2);
2130
2131 trace!("Instruction: f32.copysign [{v1} {v2}] -> [{res}]");
2132 stack.push_value::<T>(res.into())?;
2133 }
2134
2135 F64_ABS => {
2136 decrement_fuel!(T::get_flat_cost(F64_ABS));
2137 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2138 let res: value::F64 = v1.abs();
2139
2140 trace!("Instruction: f64.abs [{v1}] -> [{res}]");
2141 stack.push_value::<T>(res.into())?;
2142 }
2143 F64_NEG => {
2144 decrement_fuel!(T::get_flat_cost(F64_NEG));
2145 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2146 let res: value::F64 = v1.neg();
2147
2148 trace!("Instruction: f64.neg [{v1}] -> [{res}]");
2149 stack.push_value::<T>(res.into())?;
2150 }
2151 F64_CEIL => {
2152 decrement_fuel!(T::get_flat_cost(F64_CEIL));
2153 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2154 let res: value::F64 = v1.ceil();
2155
2156 trace!("Instruction: f64.ceil [{v1}] -> [{res}]");
2157 stack.push_value::<T>(res.into())?;
2158 }
2159 F64_FLOOR => {
2160 decrement_fuel!(T::get_flat_cost(F64_FLOOR));
2161 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2162 let res: value::F64 = v1.floor();
2163
2164 trace!("Instruction: f64.floor [{v1}] -> [{res}]");
2165 stack.push_value::<T>(res.into())?;
2166 }
2167 F64_TRUNC => {
2168 decrement_fuel!(T::get_flat_cost(F64_TRUNC));
2169 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2170 let res: value::F64 = v1.trunc();
2171
2172 trace!("Instruction: f64.trunc [{v1}] -> [{res}]");
2173 stack.push_value::<T>(res.into())?;
2174 }
2175 F64_NEAREST => {
2176 decrement_fuel!(T::get_flat_cost(F64_NEAREST));
2177 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2178 let res: value::F64 = v1.nearest();
2179
2180 trace!("Instruction: f64.nearest [{v1}] -> [{res}]");
2181 stack.push_value::<T>(res.into())?;
2182 }
2183 F64_SQRT => {
2184 decrement_fuel!(T::get_flat_cost(F64_SQRT));
2185 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2186 let res: value::F64 = v1.sqrt();
2187
2188 trace!("Instruction: f64.sqrt [{v1}] -> [{res}]");
2189 stack.push_value::<T>(res.into())?;
2190 }
2191 F64_ADD => {
2192 decrement_fuel!(T::get_flat_cost(F64_ADD));
2193 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
2194 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2195 let res: value::F64 = v1 + v2;
2196
2197 trace!("Instruction: f64.add [{v1} {v2}] -> [{res}]");
2198 stack.push_value::<T>(res.into())?;
2199 }
2200 F64_SUB => {
2201 decrement_fuel!(T::get_flat_cost(F64_SUB));
2202 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
2203 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2204 let res: value::F64 = v1 - v2;
2205
2206 trace!("Instruction: f64.sub [{v1} {v2}] -> [{res}]");
2207 stack.push_value::<T>(res.into())?;
2208 }
2209 F64_MUL => {
2210 decrement_fuel!(T::get_flat_cost(F64_MUL));
2211 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
2212 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2213 let res: value::F64 = v1 * v2;
2214
2215 trace!("Instruction: f64.mul [{v1} {v2}] -> [{res}]");
2216 stack.push_value::<T>(res.into())?;
2217 }
2218 F64_DIV => {
2219 decrement_fuel!(T::get_flat_cost(F64_DIV));
2220 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
2221 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2222 let res: value::F64 = v1 / v2;
2223
2224 trace!("Instruction: f64.div [{v1} {v2}] -> [{res}]");
2225 stack.push_value::<T>(res.into())?;
2226 }
2227 F64_MIN => {
2228 decrement_fuel!(T::get_flat_cost(F64_MIN));
2229 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
2230 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2231 let res: value::F64 = v1.min(v2);
2232
2233 trace!("Instruction: f64.min [{v1} {v2}] -> [{res}]");
2234 stack.push_value::<T>(res.into())?;
2235 }
2236 F64_MAX => {
2237 decrement_fuel!(T::get_flat_cost(F64_MAX));
2238 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
2239 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2240 let res: value::F64 = v1.max(v2);
2241
2242 trace!("Instruction: f64.max [{v1} {v2}] -> [{res}]");
2243 stack.push_value::<T>(res.into())?;
2244 }
2245 F64_COPYSIGN => {
2246 decrement_fuel!(T::get_flat_cost(F64_COPYSIGN));
2247 let v2: value::F64 = stack.pop_value().try_into().unwrap_validated();
2248 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2249 let res: value::F64 = v1.copysign(v2);
2250
2251 trace!("Instruction: f64.copysign [{v1} {v2}] -> [{res}]");
2252 stack.push_value::<T>(res.into())?;
2253 }
2254 I32_WRAP_I64 => {
2255 decrement_fuel!(T::get_flat_cost(I32_WRAP_I64));
2256 let v: i64 = stack.pop_value().try_into().unwrap_validated();
2257 let res: i32 = v as i32;
2258
2259 trace!("Instruction: i32.wrap_i64 [{v}] -> [{res}]");
2260 stack.push_value::<T>(res.into())?;
2261 }
2262 I32_TRUNC_F32_S => {
2263 decrement_fuel!(T::get_flat_cost(I32_TRUNC_F32_S));
2264 let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
2265 if v.is_infinity() {
2266 return Err(TrapError::UnrepresentableResult.into());
2267 }
2268 if v.is_nan() {
2269 return Err(TrapError::BadConversionToInteger.into());
2270 }
2271 if v >= value::F32(2147483648.0) || v <= value::F32(-2147483904.0) {
2272 return Err(TrapError::UnrepresentableResult.into());
2273 }
2274
2275 let res: i32 = v.as_i32();
2276
2277 trace!("Instruction: i32.trunc_f32_s [{v:.7}] -> [{res}]");
2278 stack.push_value::<T>(res.into())?;
2279 }
2280 I32_TRUNC_F32_U => {
2281 decrement_fuel!(T::get_flat_cost(I32_TRUNC_F32_U));
2282 let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
2283 if v.is_infinity() {
2284 return Err(TrapError::UnrepresentableResult.into());
2285 }
2286 if v.is_nan() {
2287 return Err(TrapError::BadConversionToInteger.into());
2288 }
2289 if v >= value::F32(4294967296.0) || v <= value::F32(-1.0) {
2290 return Err(TrapError::UnrepresentableResult.into());
2291 }
2292
2293 let res: i32 = v.as_u32() as i32;
2294
2295 trace!("Instruction: i32.trunc_f32_u [{v:.7}] -> [{res}]");
2296 stack.push_value::<T>(res.into())?;
2297 }
2298
2299 I32_TRUNC_F64_S => {
2300 decrement_fuel!(T::get_flat_cost(I32_TRUNC_F64_S));
2301 let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
2302 if v.is_infinity() {
2303 return Err(TrapError::UnrepresentableResult.into());
2304 }
2305 if v.is_nan() {
2306 return Err(TrapError::BadConversionToInteger.into());
2307 }
2308 if v >= value::F64(2147483648.0) || v <= value::F64(-2147483649.0) {
2309 return Err(TrapError::UnrepresentableResult.into());
2310 }
2311
2312 let res: i32 = v.as_i32();
2313
2314 trace!("Instruction: i32.trunc_f64_s [{v:.7}] -> [{res}]");
2315 stack.push_value::<T>(res.into())?;
2316 }
2317 I32_TRUNC_F64_U => {
2318 decrement_fuel!(T::get_flat_cost(I32_TRUNC_F64_U));
2319 let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
2320 if v.is_infinity() {
2321 return Err(TrapError::UnrepresentableResult.into());
2322 }
2323 if v.is_nan() {
2324 return Err(TrapError::BadConversionToInteger.into());
2325 }
2326 if v >= value::F64(4294967296.0) || v <= value::F64(-1.0) {
2327 return Err(TrapError::UnrepresentableResult.into());
2328 }
2329
2330 let res: i32 = v.as_u32() as i32;
2331
2332 trace!("Instruction: i32.trunc_f32_u [{v:.7}] -> [{res}]");
2333 stack.push_value::<T>(res.into())?;
2334 }
2335
2336 I64_EXTEND_I32_S => {
2337 decrement_fuel!(T::get_flat_cost(I64_EXTEND_I32_S));
2338 let v: i32 = stack.pop_value().try_into().unwrap_validated();
2339
2340 let res: i64 = v as i64;
2341
2342 trace!("Instruction: i64.extend_i32_s [{v}] -> [{res}]");
2343 stack.push_value::<T>(res.into())?;
2344 }
2345
2346 I64_EXTEND_I32_U => {
2347 decrement_fuel!(T::get_flat_cost(I64_EXTEND_I32_U));
2348 let v: i32 = stack.pop_value().try_into().unwrap_validated();
2349
2350 let res: i64 = v as u32 as i64;
2351
2352 trace!("Instruction: i64.extend_i32_u [{v}] -> [{res}]");
2353 stack.push_value::<T>(res.into())?;
2354 }
2355
2356 I64_TRUNC_F32_S => {
2357 decrement_fuel!(T::get_flat_cost(I64_TRUNC_F32_S));
2358 let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
2359 if v.is_infinity() {
2360 return Err(TrapError::UnrepresentableResult.into());
2361 }
2362 if v.is_nan() {
2363 return Err(TrapError::BadConversionToInteger.into());
2364 }
2365 if v >= value::F32(9223372036854775808.0) || v <= value::F32(-9223373136366403584.0)
2366 {
2367 return Err(TrapError::UnrepresentableResult.into());
2368 }
2369
2370 let res: i64 = v.as_i64();
2371
2372 trace!("Instruction: i64.trunc_f32_s [{v:.7}] -> [{res}]");
2373 stack.push_value::<T>(res.into())?;
2374 }
2375 I64_TRUNC_F32_U => {
2376 decrement_fuel!(T::get_flat_cost(I64_TRUNC_F32_U));
2377 let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
2378 if v.is_infinity() {
2379 return Err(TrapError::UnrepresentableResult.into());
2380 }
2381 if v.is_nan() {
2382 return Err(TrapError::BadConversionToInteger.into());
2383 }
2384 if v >= value::F32(18446744073709551616.0) || v <= value::F32(-1.0) {
2385 return Err(TrapError::UnrepresentableResult.into());
2386 }
2387
2388 let res: i64 = v.as_u64() as i64;
2389
2390 trace!("Instruction: i64.trunc_f32_u [{v:.7}] -> [{res}]");
2391 stack.push_value::<T>(res.into())?;
2392 }
2393
2394 I64_TRUNC_F64_S => {
2395 decrement_fuel!(T::get_flat_cost(I64_TRUNC_F64_S));
2396 let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
2397 if v.is_infinity() {
2398 return Err(TrapError::UnrepresentableResult.into());
2399 }
2400 if v.is_nan() {
2401 return Err(TrapError::BadConversionToInteger.into());
2402 }
2403 if v >= value::F64(9223372036854775808.0) || v <= value::F64(-9223372036854777856.0)
2404 {
2405 return Err(TrapError::UnrepresentableResult.into());
2406 }
2407
2408 let res: i64 = v.as_i64();
2409
2410 trace!("Instruction: i64.trunc_f64_s [{v:.17}] -> [{res}]");
2411 stack.push_value::<T>(res.into())?;
2412 }
2413 I64_TRUNC_F64_U => {
2414 decrement_fuel!(T::get_flat_cost(I64_TRUNC_F64_U));
2415 let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
2416 if v.is_infinity() {
2417 return Err(TrapError::UnrepresentableResult.into());
2418 }
2419 if v.is_nan() {
2420 return Err(TrapError::BadConversionToInteger.into());
2421 }
2422 if v >= value::F64(18446744073709551616.0) || v <= value::F64(-1.0) {
2423 return Err(TrapError::UnrepresentableResult.into());
2424 }
2425
2426 let res: i64 = v.as_u64() as i64;
2427
2428 trace!("Instruction: i64.trunc_f64_u [{v:.17}] -> [{res}]");
2429 stack.push_value::<T>(res.into())?;
2430 }
2431 F32_CONVERT_I32_S => {
2432 decrement_fuel!(T::get_flat_cost(F32_CONVERT_I32_S));
2433 let v: i32 = stack.pop_value().try_into().unwrap_validated();
2434 let res: value::F32 = value::F32(v as f32);
2435
2436 trace!("Instruction: f32.convert_i32_s [{v}] -> [{res}]");
2437 stack.push_value::<T>(res.into())?;
2438 }
2439 F32_CONVERT_I32_U => {
2440 decrement_fuel!(T::get_flat_cost(F32_CONVERT_I32_U));
2441 let v: i32 = stack.pop_value().try_into().unwrap_validated();
2442 let res: value::F32 = value::F32(v as u32 as f32);
2443
2444 trace!("Instruction: f32.convert_i32_u [{v}] -> [{res}]");
2445 stack.push_value::<T>(res.into())?;
2446 }
2447 F32_CONVERT_I64_S => {
2448 decrement_fuel!(T::get_flat_cost(F32_CONVERT_I64_S));
2449 let v: i64 = stack.pop_value().try_into().unwrap_validated();
2450 let res: value::F32 = value::F32(v as f32);
2451
2452 trace!("Instruction: f32.convert_i64_s [{v}] -> [{res}]");
2453 stack.push_value::<T>(res.into())?;
2454 }
2455 F32_CONVERT_I64_U => {
2456 decrement_fuel!(T::get_flat_cost(F32_CONVERT_I64_U));
2457 let v: i64 = stack.pop_value().try_into().unwrap_validated();
2458 let res: value::F32 = value::F32(v as u64 as f32);
2459
2460 trace!("Instruction: f32.convert_i64_u [{v}] -> [{res}]");
2461 stack.push_value::<T>(res.into())?;
2462 }
2463 F32_DEMOTE_F64 => {
2464 decrement_fuel!(T::get_flat_cost(F32_DEMOTE_F64));
2465 let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
2466 let res: value::F32 = v.as_f32();
2467
2468 trace!("Instruction: f32.demote_f64 [{v:.17}] -> [{res:.7}]");
2469 stack.push_value::<T>(res.into())?;
2470 }
2471 F64_CONVERT_I32_S => {
2472 decrement_fuel!(T::get_flat_cost(F64_CONVERT_I32_S));
2473 let v: i32 = stack.pop_value().try_into().unwrap_validated();
2474 let res: value::F64 = value::F64(v as f64);
2475
2476 trace!("Instruction: f64.convert_i32_s [{v}] -> [{res:.17}]");
2477 stack.push_value::<T>(res.into())?;
2478 }
2479 F64_CONVERT_I32_U => {
2480 decrement_fuel!(T::get_flat_cost(F64_CONVERT_I32_U));
2481 let v: i32 = stack.pop_value().try_into().unwrap_validated();
2482 let res: value::F64 = value::F64(v as u32 as f64);
2483
2484 trace!("Instruction: f64.convert_i32_u [{v}] -> [{res:.17}]");
2485 stack.push_value::<T>(res.into())?;
2486 }
2487 F64_CONVERT_I64_S => {
2488 decrement_fuel!(T::get_flat_cost(F64_CONVERT_I64_S));
2489 let v: i64 = stack.pop_value().try_into().unwrap_validated();
2490 let res: value::F64 = value::F64(v as f64);
2491
2492 trace!("Instruction: f64.convert_i64_s [{v}] -> [{res:.17}]");
2493 stack.push_value::<T>(res.into())?;
2494 }
2495 F64_CONVERT_I64_U => {
2496 decrement_fuel!(T::get_flat_cost(F64_CONVERT_I64_U));
2497 let v: i64 = stack.pop_value().try_into().unwrap_validated();
2498 let res: value::F64 = value::F64(v as u64 as f64);
2499
2500 trace!("Instruction: f64.convert_i64_u [{v}] -> [{res:.17}]");
2501 stack.push_value::<T>(res.into())?;
2502 }
2503 F64_PROMOTE_F32 => {
2504 decrement_fuel!(T::get_flat_cost(F64_PROMOTE_F32));
2505 let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
2506 let res: value::F64 = v.as_f64();
2507
2508 trace!("Instruction: f64.promote_f32 [{v:.7}] -> [{res:.17}]");
2509 stack.push_value::<T>(res.into())?;
2510 }
2511 I32_REINTERPRET_F32 => {
2512 decrement_fuel!(T::get_flat_cost(I32_REINTERPRET_F32));
2513 let v: value::F32 = stack.pop_value().try_into().unwrap_validated();
2514 let res: i32 = v.reinterpret_as_i32();
2515
2516 trace!("Instruction: i32.reinterpret_f32 [{v:.7}] -> [{res}]");
2517 stack.push_value::<T>(res.into())?;
2518 }
2519 I64_REINTERPRET_F64 => {
2520 decrement_fuel!(T::get_flat_cost(I64_REINTERPRET_F64));
2521 let v: value::F64 = stack.pop_value().try_into().unwrap_validated();
2522 let res: i64 = v.reinterpret_as_i64();
2523
2524 trace!("Instruction: i64.reinterpret_f64 [{v:.17}] -> [{res}]");
2525 stack.push_value::<T>(res.into())?;
2526 }
2527 F32_REINTERPRET_I32 => {
2528 decrement_fuel!(T::get_flat_cost(F32_REINTERPRET_I32));
2529 let v1: i32 = stack.pop_value().try_into().unwrap_validated();
2530 let res: value::F32 = value::F32::from_bits(v1 as u32);
2531
2532 trace!("Instruction: f32.reinterpret_i32 [{v1}] -> [{res:.7}]");
2533 stack.push_value::<T>(res.into())?;
2534 }
2535 F64_REINTERPRET_I64 => {
2536 decrement_fuel!(T::get_flat_cost(F64_REINTERPRET_I64));
2537 let v1: i64 = stack.pop_value().try_into().unwrap_validated();
2538 let res: value::F64 = value::F64::from_bits(v1 as u64);
2539
2540 trace!("Instruction: f64.reinterpret_i64 [{v1}] -> [{res:.17}]");
2541 stack.push_value::<T>(res.into())?;
2542 }
2543 REF_NULL => {
2544 decrement_fuel!(T::get_flat_cost(REF_NULL));
2545 let reftype = RefType::read(wasm).unwrap_validated();
2546
2547 stack.push_value::<T>(Value::Ref(Ref::Null(reftype)))?;
2548 trace!("Instruction: ref.null '{:?}' -> [{:?}]", reftype, reftype);
2549 }
2550 REF_IS_NULL => {
2551 decrement_fuel!(T::get_flat_cost(REF_IS_NULL));
2552 let rref: Ref = stack.pop_value().try_into().unwrap_validated();
2553 let is_null = matches!(rref, Ref::Null(_));
2554
2555 let res = if is_null { 1 } else { 0 };
2556 trace!("Instruction: ref.is_null [{}] -> [{}]", rref, res);
2557 stack.push_value::<T>(Value::I32(res))?;
2558 }
2559 REF_FUNC => {
2561 decrement_fuel!(T::get_flat_cost(REF_FUNC));
2562 let func_idx = unsafe { FuncIdx::read_unchecked(wasm) };
2565
2566 let current_module = unsafe { store.modules.get(current_module) };
2571 let func_addr = unsafe { current_module.func_addrs.get(func_idx) };
2574 stack.push_value::<T>(Value::Ref(Ref::Func(*func_addr)))?;
2575 }
2576 FC_EXTENSIONS => {
2577 let second_instr = wasm.read_var_u32().unwrap_validated();
2579
2580 use crate::core::reader::types::opcode::fc_extensions::*;
2581 match second_instr {
2582 I32_TRUNC_SAT_F32_S => {
2583 decrement_fuel!(T::get_fc_extension_flat_cost(I32_TRUNC_SAT_F32_S));
2584 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2585 let res = {
2586 if v1.is_nan() {
2587 0
2588 } else if v1.is_negative_infinity() {
2589 i32::MIN
2590 } else if v1.is_infinity() {
2591 i32::MAX
2592 } else {
2593 v1.as_i32()
2594 }
2595 };
2596
2597 trace!("Instruction: i32.trunc_sat_f32_s [{v1}] -> [{res}]");
2598 stack.push_value::<T>(res.into())?;
2599 }
2600 I32_TRUNC_SAT_F32_U => {
2601 decrement_fuel!(T::get_fc_extension_flat_cost(I32_TRUNC_SAT_F32_U));
2602 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2603 let res = {
2604 if v1.is_nan() || v1.is_negative_infinity() {
2605 0
2606 } else if v1.is_infinity() {
2607 u32::MAX as i32
2608 } else {
2609 v1.as_u32() as i32
2610 }
2611 };
2612
2613 trace!("Instruction: i32.trunc_sat_f32_u [{v1}] -> [{res}]");
2614 stack.push_value::<T>(res.into())?;
2615 }
2616 I32_TRUNC_SAT_F64_S => {
2617 decrement_fuel!(T::get_fc_extension_flat_cost(I32_TRUNC_SAT_F64_S));
2618 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2619 let res = {
2620 if v1.is_nan() {
2621 0
2622 } else if v1.is_negative_infinity() {
2623 i32::MIN
2624 } else if v1.is_infinity() {
2625 i32::MAX
2626 } else {
2627 v1.as_i32()
2628 }
2629 };
2630
2631 trace!("Instruction: i32.trunc_sat_f64_s [{v1}] -> [{res}]");
2632 stack.push_value::<T>(res.into())?;
2633 }
2634 I32_TRUNC_SAT_F64_U => {
2635 decrement_fuel!(T::get_fc_extension_flat_cost(I32_TRUNC_SAT_F64_U));
2636 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2637 let res = {
2638 if v1.is_nan() || v1.is_negative_infinity() {
2639 0
2640 } else if v1.is_infinity() {
2641 u32::MAX as i32
2642 } else {
2643 v1.as_u32() as i32
2644 }
2645 };
2646
2647 trace!("Instruction: i32.trunc_sat_f64_u [{v1}] -> [{res}]");
2648 stack.push_value::<T>(res.into())?;
2649 }
2650 I64_TRUNC_SAT_F32_S => {
2651 decrement_fuel!(T::get_fc_extension_flat_cost(I64_TRUNC_SAT_F32_S));
2652 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2653 let res = {
2654 if v1.is_nan() {
2655 0
2656 } else if v1.is_negative_infinity() {
2657 i64::MIN
2658 } else if v1.is_infinity() {
2659 i64::MAX
2660 } else {
2661 v1.as_i64()
2662 }
2663 };
2664
2665 trace!("Instruction: i64.trunc_sat_f32_s [{v1}] -> [{res}]");
2666 stack.push_value::<T>(res.into())?;
2667 }
2668 I64_TRUNC_SAT_F32_U => {
2669 decrement_fuel!(T::get_fc_extension_flat_cost(I64_TRUNC_SAT_F32_U));
2670 let v1: value::F32 = stack.pop_value().try_into().unwrap_validated();
2671 let res = {
2672 if v1.is_nan() || v1.is_negative_infinity() {
2673 0
2674 } else if v1.is_infinity() {
2675 u64::MAX as i64
2676 } else {
2677 v1.as_u64() as i64
2678 }
2679 };
2680
2681 trace!("Instruction: i64.trunc_sat_f32_u [{v1}] -> [{res}]");
2682 stack.push_value::<T>(res.into())?;
2683 }
2684 I64_TRUNC_SAT_F64_S => {
2685 decrement_fuel!(T::get_fc_extension_flat_cost(I64_TRUNC_SAT_F64_S));
2686 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2687 let res = {
2688 if v1.is_nan() {
2689 0
2690 } else if v1.is_negative_infinity() {
2691 i64::MIN
2692 } else if v1.is_infinity() {
2693 i64::MAX
2694 } else {
2695 v1.as_i64()
2696 }
2697 };
2698
2699 trace!("Instruction: i64.trunc_sat_f64_s [{v1}] -> [{res}]");
2700 stack.push_value::<T>(res.into())?;
2701 }
2702 I64_TRUNC_SAT_F64_U => {
2703 decrement_fuel!(T::get_fc_extension_flat_cost(I64_TRUNC_SAT_F64_U));
2704 let v1: value::F64 = stack.pop_value().try_into().unwrap_validated();
2705 let res = {
2706 if v1.is_nan() || v1.is_negative_infinity() {
2707 0
2708 } else if v1.is_infinity() {
2709 u64::MAX as i64
2710 } else {
2711 v1.as_u64() as i64
2712 }
2713 };
2714
2715 trace!("Instruction: i64.trunc_sat_f64_u [{v1}] -> [{res}]");
2716 stack.push_value::<T>(res.into())?;
2717 }
2718 MEMORY_INIT => {
2721 let data_idx = unsafe { DataIdx::read_unchecked(wasm) };
2728
2729 let _zero = wasm.read_u8().unwrap_validated();
2732
2733 let n: u32 = stack.pop_value().try_into().unwrap_validated();
2734 let cost = T::get_fc_extension_flat_cost(MEMORY_INIT)
2736 + u64::from(n) * T::get_fc_extension_cost_per_element(MEMORY_INIT);
2737 if let Some(fuel) = &mut resumable.maybe_fuel {
2738 if *fuel >= cost {
2739 *fuel -= cost;
2740 } else {
2741 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2743 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2745 return Ok(NonZeroU64::new(cost - *fuel));
2746 }
2747 }
2748
2749 let s: u32 = stack.pop_value().try_into().unwrap_validated();
2750 let d: u32 = stack.pop_value().try_into().unwrap_validated();
2751
2752 unsafe {
2766 memory_init(
2767 &store.modules,
2768 &mut store.memories,
2769 &store.data,
2770 current_module,
2771 data_idx,
2772 MemIdx::new(0),
2773 n,
2774 s,
2775 d,
2776 )?
2777 };
2778 }
2779 DATA_DROP => {
2780 decrement_fuel!(T::get_fc_extension_flat_cost(DATA_DROP));
2781 let data_idx = unsafe { DataIdx::read_unchecked(wasm) };
2784 unsafe {
2797 data_drop(&store.modules, &mut store.data, current_module, data_idx)
2798 };
2799 }
2800 MEMORY_COPY => {
2802 let _zero = wasm.read_u8().unwrap_validated();
2809 let _zero = wasm.read_u8().unwrap_validated();
2810
2811 let module = unsafe { store.modules.get(current_module) };
2816
2817 let src_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
2820 let dst_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
2823
2824 let n: u32 = stack.pop_value().try_into().unwrap_validated();
2825 let cost = T::get_fc_extension_flat_cost(MEMORY_COPY)
2827 + u64::from(n) * T::get_fc_extension_cost_per_element(MEMORY_COPY);
2828 if let Some(fuel) = &mut resumable.maybe_fuel {
2829 if *fuel >= cost {
2830 *fuel -= cost;
2831 } else {
2832 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2834 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2836 return Ok(NonZeroU64::new(cost - *fuel));
2837 }
2838 }
2839
2840 let s: i32 = stack.pop_value().try_into().unwrap_validated();
2841 let d: i32 = stack.pop_value().try_into().unwrap_validated();
2842
2843 let src_mem = unsafe { store.memories.get(src_addr) };
2847 let dest_mem = unsafe { store.memories.get(dst_addr) };
2851
2852 dest_mem.mem.copy(
2853 d.cast_unsigned().into_usize(),
2854 &src_mem.mem,
2855 s.cast_unsigned().into_usize(),
2856 n.into_usize(),
2857 )?;
2858 trace!("Instruction: memory.copy");
2859 }
2860 MEMORY_FILL => {
2862 let _zero = wasm.read_u8().unwrap_validated();
2870
2871 let module = unsafe { store.modules.get(current_module) };
2876
2877 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
2879 let mem = unsafe { store.memories.get(mem_addr) };
2883
2884 let n: u32 = stack.pop_value().try_into().unwrap_validated();
2885 let cost = T::get_fc_extension_flat_cost(MEMORY_FILL)
2887 + u64::from(n) * T::get_fc_extension_cost_per_element(MEMORY_FILL);
2888 if let Some(fuel) = &mut resumable.maybe_fuel {
2889 if *fuel >= cost {
2890 *fuel -= cost;
2891 } else {
2892 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2894 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2896 return Ok(NonZeroU64::new(cost - *fuel));
2897 }
2898 }
2899
2900 let val: i32 = stack.pop_value().try_into().unwrap_validated();
2901
2902 if !(0..=255).contains(&val) {
2903 warn!("Value for memory.fill does not fit in a byte ({val})");
2904 }
2905
2906 let d: i32 = stack.pop_value().try_into().unwrap_validated();
2907
2908 mem.mem
2909 .fill(d.cast_unsigned().into_usize(), val as u8, n.into_usize())?;
2910
2911 trace!("Instruction: memory.fill");
2912 }
2913 TABLE_INIT => {
2918 let elem_idx = unsafe { ElemIdx::read_unchecked(wasm) };
2921 let table_idx = unsafe { TableIdx::read_unchecked(wasm) };
2924
2925 let n: u32 = stack.pop_value().try_into().unwrap_validated(); let cost = T::get_fc_extension_flat_cost(TABLE_INIT)
2927 + u64::from(n) * T::get_fc_extension_cost_per_element(TABLE_INIT);
2928 if let Some(fuel) = &mut resumable.maybe_fuel {
2929 if *fuel >= cost {
2930 *fuel -= cost;
2931 } else {
2932 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2934 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2936 return Ok(NonZeroU64::new(cost - *fuel));
2937 }
2938 }
2939
2940 let s: i32 = stack.pop_value().try_into().unwrap_validated(); let d: i32 = stack.pop_value().try_into().unwrap_validated(); unsafe {
2958 table_init(
2959 &store.modules,
2960 &mut store.tables,
2961 &store.elements,
2962 current_module,
2963 elem_idx,
2964 table_idx,
2965 n,
2966 s,
2967 d,
2968 )?
2969 };
2970 }
2971 ELEM_DROP => {
2972 decrement_fuel!(T::get_fc_extension_flat_cost(ELEM_DROP));
2973 let elem_idx = unsafe { ElemIdx::read_unchecked(wasm) };
2976
2977 unsafe {
2990 elem_drop(
2991 &store.modules,
2992 &mut store.elements,
2993 current_module,
2994 elem_idx,
2995 );
2996 }
2997 }
2998 TABLE_COPY => {
3000 decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_COPY));
3001 let table_x_idx = unsafe { TableIdx::read_unchecked(wasm) };
3004 let table_y_idx = unsafe { TableIdx::read_unchecked(wasm) };
3007
3008 let module = unsafe { store.modules.get(current_module) };
3013
3014 let table_addr_x = *unsafe { module.table_addrs.get(table_x_idx) };
3017 let table_addr_y = *unsafe { module.table_addrs.get(table_y_idx) };
3020
3021 let tab_x_elem_len = unsafe { store.tables.get(table_addr_x) }.elem.len();
3025 let tab_y_elem_len = unsafe { store.tables.get(table_addr_y) }.elem.len();
3029
3030 let n: u32 = stack.pop_value().try_into().unwrap_validated(); let cost = T::get_fc_extension_flat_cost(TABLE_COPY)
3032 + u64::from(n) * T::get_fc_extension_cost_per_element(TABLE_COPY);
3033 if let Some(fuel) = &mut resumable.maybe_fuel {
3034 if *fuel >= cost {
3035 *fuel -= cost;
3036 } else {
3037 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
3039 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
3041 return Ok(NonZeroU64::new(cost - *fuel));
3042 }
3043 }
3044
3045 let s: u32 = stack.pop_value().try_into().unwrap_validated(); let d: u32 = stack.pop_value().try_into().unwrap_validated(); let src_res = match s.checked_add(n) {
3049 Some(res) => {
3050 if res > tab_y_elem_len as u32 {
3051 return Err(TrapError::TableOrElementAccessOutOfBounds.into());
3052 } else {
3053 res.into_usize()
3054 }
3055 }
3056 _ => return Err(TrapError::TableOrElementAccessOutOfBounds.into()),
3057 };
3058
3059 let dst_res = match d.checked_add(n) {
3060 Some(res) => {
3061 if res > tab_x_elem_len as u32 {
3062 return Err(TrapError::TableOrElementAccessOutOfBounds.into());
3063 } else {
3064 res.into_usize()
3065 }
3066 }
3067 _ => return Err(TrapError::TableOrElementAccessOutOfBounds.into()),
3068 };
3069
3070 if table_addr_x == table_addr_y {
3071 let table = unsafe { store.tables.get_mut(table_addr_x) };
3075
3076 table.elem.copy_within(s as usize..src_res, d as usize);
3077 } else {
3078 let dst_addr = table_addr_x;
3079 let src_addr = table_addr_y;
3080
3081 let (src_table, dst_table) =
3085 unsafe { store.tables.get_two_mut(src_addr, dst_addr) }
3086 .expect("both addrs to never be equal");
3087
3088 dst_table.elem[d.into_usize()..dst_res]
3089 .copy_from_slice(&src_table.elem[s.into_usize()..src_res]);
3090 }
3091
3092 trace!(
3093 "Instruction: table.copy '{}' '{}' [{} {} {}] -> []",
3094 table_x_idx,
3095 table_y_idx,
3096 d,
3097 s,
3098 n
3099 );
3100 }
3101 TABLE_GROW => {
3102 decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_GROW));
3103 let table_idx = unsafe { TableIdx::read_unchecked(wasm) };
3106
3107 let module = unsafe { store.modules.get(current_module) };
3112
3113 let table_addr = *unsafe { module.table_addrs.get(table_idx) };
3116 let tab = unsafe { store.tables.get_mut(table_addr) };
3120
3121 let sz = tab.elem.len() as u32;
3122
3123 let n: u32 = stack.pop_value().try_into().unwrap_validated();
3124 let cost = T::get_fc_extension_flat_cost(TABLE_GROW)
3125 + u64::from(n) * T::get_fc_extension_cost_per_element(TABLE_GROW);
3126 if let Some(fuel) = &mut resumable.maybe_fuel {
3127 if *fuel >= cost {
3128 *fuel -= cost;
3129 } else {
3130 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
3132 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
3134 return Ok(NonZeroU64::new(cost - *fuel));
3135 }
3136 }
3137
3138 let val: Ref = stack.pop_value().try_into().unwrap_validated();
3139
3140 match tab.grow(n, val) {
3144 Ok(_) => {
3145 stack.push_value::<T>(Value::I32(sz))?;
3146 }
3147 Err(_) => {
3148 stack.push_value::<T>(Value::I32(u32::MAX))?;
3149 }
3150 }
3151 }
3152 TABLE_SIZE => {
3153 decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_SIZE));
3154 let table_idx = unsafe { TableIdx::read_unchecked(wasm) };
3157
3158 let module = unsafe { store.modules.get(current_module) };
3163
3164 let table_addr = *unsafe { module.table_addrs.get(table_idx) };
3167 let tab = unsafe { store.tables.get_mut(table_addr) };
3171
3172 let sz = tab.elem.len() as u32;
3173
3174 stack.push_value::<T>(Value::I32(sz))?;
3175
3176 trace!("Instruction: table.size '{}' [] -> [{}]", table_idx, sz);
3177 }
3178 TABLE_FILL => {
3179 decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_FILL));
3180 let table_idx = unsafe { TableIdx::read_unchecked(wasm) };
3183
3184 let module = unsafe { store.modules.get(current_module) };
3189
3190 let table_addr = *unsafe { module.table_addrs.get(table_idx) };
3193 let tab = unsafe { store.tables.get_mut(table_addr) };
3197
3198 let len: u32 = stack.pop_value().try_into().unwrap_validated();
3199 let cost = T::get_fc_extension_flat_cost(TABLE_FILL)
3200 + u64::from(len) * T::get_fc_extension_cost_per_element(TABLE_FILL);
3201 if let Some(fuel) = &mut resumable.maybe_fuel {
3202 if *fuel >= cost {
3203 *fuel -= cost;
3204 } else {
3205 stack.push_value::<T>(Value::I32(len)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
3207 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
3209 return Ok(NonZeroU64::new(cost - *fuel));
3210 }
3211 }
3212
3213 let val: Ref = stack.pop_value().try_into().unwrap_validated();
3214 let dst: u32 = stack.pop_value().try_into().unwrap_validated();
3215
3216 let end = (dst.into_usize())
3217 .checked_add(len.into_usize())
3218 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
3219
3220 tab.elem
3221 .get_mut(dst.into_usize()..end)
3222 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?
3223 .fill(val);
3224
3225 trace!(
3226 "Instruction table.fill '{}' [{} {} {}] -> []",
3227 table_idx,
3228 dst,
3229 val,
3230 len
3231 )
3232 }
3233 _ => unreachable!(),
3234 }
3235 }
3236
3237 I32_EXTEND8_S => {
3238 decrement_fuel!(T::get_flat_cost(I32_EXTEND8_S));
3239 let mut v: u32 = stack.pop_value().try_into().unwrap_validated();
3240
3241 if v | 0xFF != 0xFF {
3242 trace!("Number v ({}) not contained in 8 bits, truncating", v);
3243 v &= 0xFF;
3244 }
3245
3246 let res = if v | 0x7F != 0x7F { v | 0xFFFFFF00 } else { v };
3247
3248 stack.push_value::<T>(res.into())?;
3249
3250 trace!("Instruction i32.extend8_s [{}] -> [{}]", v, res);
3251 }
3252 I32_EXTEND16_S => {
3253 decrement_fuel!(T::get_flat_cost(I32_EXTEND16_S));
3254 let mut v: u32 = stack.pop_value().try_into().unwrap_validated();
3255
3256 if v | 0xFFFF != 0xFFFF {
3257 trace!("Number v ({}) not contained in 16 bits, truncating", v);
3258 v &= 0xFFFF;
3259 }
3260
3261 let res = if v | 0x7FFF != 0x7FFF {
3262 v | 0xFFFF0000
3263 } else {
3264 v
3265 };
3266
3267 stack.push_value::<T>(res.into())?;
3268
3269 trace!("Instruction i32.extend16_s [{}] -> [{}]", v, res);
3270 }
3271 I64_EXTEND8_S => {
3272 decrement_fuel!(T::get_flat_cost(I64_EXTEND8_S));
3273 let mut v: u64 = stack.pop_value().try_into().unwrap_validated();
3274
3275 if v | 0xFF != 0xFF {
3276 trace!("Number v ({}) not contained in 8 bits, truncating", v);
3277 v &= 0xFF;
3278 }
3279
3280 let res = if v | 0x7F != 0x7F {
3281 v | 0xFFFFFFFF_FFFFFF00
3282 } else {
3283 v
3284 };
3285
3286 stack.push_value::<T>(res.into())?;
3287
3288 trace!("Instruction i64.extend8_s [{}] -> [{}]", v, res);
3289 }
3290 I64_EXTEND16_S => {
3291 decrement_fuel!(T::get_flat_cost(I64_EXTEND16_S));
3292 let mut v: u64 = stack.pop_value().try_into().unwrap_validated();
3293
3294 if v | 0xFFFF != 0xFFFF {
3295 trace!("Number v ({}) not contained in 16 bits, truncating", v);
3296 v &= 0xFFFF;
3297 }
3298
3299 let res = if v | 0x7FFF != 0x7FFF {
3300 v | 0xFFFFFFFF_FFFF0000
3301 } else {
3302 v
3303 };
3304
3305 stack.push_value::<T>(res.into())?;
3306
3307 trace!("Instruction i64.extend16_s [{}] -> [{}]", v, res);
3308 }
3309 I64_EXTEND32_S => {
3310 decrement_fuel!(T::get_flat_cost(I64_EXTEND32_S));
3311 let mut v: u64 = stack.pop_value().try_into().unwrap_validated();
3312
3313 if v | 0xFFFF_FFFF != 0xFFFF_FFFF {
3314 trace!("Number v ({}) not contained in 32 bits, truncating", v);
3315 v &= 0xFFFF_FFFF;
3316 }
3317
3318 let res = if v | 0x7FFF_FFFF != 0x7FFF_FFFF {
3319 v | 0xFFFFFFFF_00000000
3320 } else {
3321 v
3322 };
3323
3324 stack.push_value::<T>(res.into())?;
3325
3326 trace!("Instruction i64.extend32_s [{}] -> [{}]", v, res);
3327 }
3328 FD_EXTENSIONS => {
3329 let second_instr = wasm.read_var_u32().unwrap_validated();
3331
3332 use crate::core::reader::types::opcode::fd_extensions::*;
3333 match second_instr {
3334 V128_LOAD => {
3335 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD));
3336 let memarg = MemArg::read(wasm).unwrap_validated();
3337 let module = unsafe { store.modules.get(current_module) };
3342
3343 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3346 let memory = unsafe { store.memories.get(mem_addr) };
3350
3351 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3352 let idx = calculate_mem_address(&memarg, relative_address)?;
3353
3354 let data: u128 = memory.mem.load(idx)?;
3355 stack.push_value::<T>(data.to_le_bytes().into())?;
3356 }
3357 V128_STORE => {
3358 decrement_fuel!(T::get_fd_extension_flat_cost(V128_STORE));
3359 let memarg = MemArg::read(wasm).unwrap_validated();
3360 let module = unsafe { store.modules.get(current_module) };
3365
3366 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3369 let memory = unsafe { store.memories.get(mem_addr) };
3373
3374 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3375 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3376 let idx = calculate_mem_address(&memarg, relative_address)?;
3377
3378 memory.mem.store(idx, u128::from_le_bytes(data))?;
3379 }
3380
3381 V128_LOAD8X8_S => {
3383 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD8X8_S));
3384 let memarg = MemArg::read(wasm).unwrap_validated();
3385 let module = unsafe { store.modules.get(current_module) };
3390
3391 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3394 let memory = unsafe { store.memories.get(mem_addr) };
3398
3399 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3400 let idx = calculate_mem_address(&memarg, relative_address)?;
3401
3402 let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
3406 let half_lanes: [i8; 8] =
3407 to_lanes::<1, 16, i8>(data)[..8].try_into().unwrap();
3408
3409 let extended_lanes = half_lanes.map(|lane| lane as i16);
3410
3411 stack.push_value::<T>(Value::V128(from_lanes(extended_lanes)))?;
3412 }
3413 V128_LOAD8X8_U => {
3414 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD8X8_U));
3415 let memarg = MemArg::read(wasm).unwrap_validated();
3416 let module = unsafe { store.modules.get(current_module) };
3421
3422 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3425 let memory = unsafe { store.memories.get(mem_addr) };
3429
3430 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3431 let idx = calculate_mem_address(&memarg, relative_address)?;
3432
3433 let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
3437 let half_lanes: [u8; 8] =
3438 to_lanes::<1, 16, u8>(data)[..8].try_into().unwrap();
3439
3440 let extended_lanes = half_lanes.map(|lane| lane as u16);
3441
3442 stack.push_value::<T>(Value::V128(from_lanes(extended_lanes)))?;
3443 }
3444 V128_LOAD16X4_S => {
3445 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD16X4_S));
3446 let memarg = MemArg::read(wasm).unwrap_validated();
3447 let module = unsafe { store.modules.get(current_module) };
3452
3453 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3456 let memory = unsafe { store.memories.get(mem_addr) };
3460
3461 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3462 let idx = calculate_mem_address(&memarg, relative_address)?;
3463
3464 let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
3468 let half_lanes: [i16; 4] =
3469 to_lanes::<2, 8, i16>(data)[..4].try_into().unwrap();
3470
3471 let extended_lanes = half_lanes.map(|lane| lane as i32);
3472
3473 stack.push_value::<T>(Value::V128(from_lanes(extended_lanes)))?;
3474 }
3475 V128_LOAD16X4_U => {
3476 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD16X4_U));
3477 let memarg = MemArg::read(wasm).unwrap_validated();
3478 let module = unsafe { store.modules.get(current_module) };
3483
3484 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3487 let memory = unsafe { store.memories.get(mem_addr) };
3491
3492 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3493 let idx = calculate_mem_address(&memarg, relative_address)?;
3494
3495 let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
3499 let half_lanes: [u16; 4] =
3500 to_lanes::<2, 8, u16>(data)[..4].try_into().unwrap();
3501
3502 let extended_lanes = half_lanes.map(|lane| lane as u32);
3503
3504 stack.push_value::<T>(Value::V128(from_lanes(extended_lanes)))?;
3505 }
3506 V128_LOAD32X2_S => {
3507 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD32X2_S));
3508 let memarg = MemArg::read(wasm).unwrap_validated();
3509 let module = unsafe { store.modules.get(current_module) };
3514
3515 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3518 let memory = unsafe { store.memories.get(mem_addr) };
3522
3523 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3524 let idx = calculate_mem_address(&memarg, relative_address)?;
3525
3526 let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
3530 let half_lanes: [i32; 2] =
3531 to_lanes::<4, 4, i32>(data)[..2].try_into().unwrap();
3532
3533 let extended_lanes = half_lanes.map(|lane| lane as i64);
3534
3535 stack.push_value::<T>(Value::V128(from_lanes(extended_lanes)))?;
3536 }
3537 V128_LOAD32X2_U => {
3538 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD32X2_U));
3539 let memarg = MemArg::read(wasm).unwrap_validated();
3540 let module = unsafe { store.modules.get(current_module) };
3545
3546 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3549 let memory = unsafe { store.memories.get(mem_addr) };
3553
3554 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3555 let idx = calculate_mem_address(&memarg, relative_address)?;
3556
3557 let half_data: [u8; 8] = memory.mem.load_bytes::<8>(idx)?; let data: [u8; 16] = array::from_fn(|i| *half_data.get(i).unwrap_or(&0));
3561 let half_lanes: [u32; 2] =
3562 to_lanes::<4, 4, u32>(data)[..2].try_into().unwrap();
3563
3564 let extended_lanes = half_lanes.map(|lane| lane as u64);
3565
3566 stack.push_value::<T>(Value::V128(from_lanes(extended_lanes)))?;
3567 }
3568
3569 V128_LOAD8_SPLAT => {
3571 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD8_SPLAT));
3572 let memarg = MemArg::read(wasm).unwrap_validated();
3573 let module = unsafe { store.modules.get(current_module) };
3578
3579 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3582 let memory = unsafe { store.memories.get(mem_addr) };
3586 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3587 let idx = calculate_mem_address(&memarg, relative_address)?;
3588
3589 let lane = memory.mem.load::<1, u8>(idx)?;
3590 stack.push_value::<T>(Value::V128(from_lanes([lane; 16])))?;
3591 }
3592 V128_LOAD16_SPLAT => {
3593 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD16_SPLAT));
3594 let memarg = MemArg::read(wasm).unwrap_validated();
3595 let module = unsafe { store.modules.get(current_module) };
3600
3601 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3604 let memory = unsafe { store.memories.get(mem_addr) };
3608 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3609 let idx = calculate_mem_address(&memarg, relative_address)?;
3610
3611 let lane = memory.mem.load::<2, u16>(idx)?;
3612 stack.push_value::<T>(Value::V128(from_lanes([lane; 8])))?;
3613 }
3614 V128_LOAD32_SPLAT => {
3615 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD32_SPLAT));
3616 let memarg = MemArg::read(wasm).unwrap_validated();
3617 let module = unsafe { store.modules.get(current_module) };
3622
3623 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3626 let memory = unsafe { store.memories.get(mem_addr) };
3630 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3631 let idx = calculate_mem_address(&memarg, relative_address)?;
3632
3633 let lane = memory.mem.load::<4, u32>(idx)?;
3634 stack.push_value::<T>(Value::V128(from_lanes([lane; 4])))?;
3635 }
3636 V128_LOAD64_SPLAT => {
3637 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD64_SPLAT));
3638 let memarg = MemArg::read(wasm).unwrap_validated();
3639 let module = unsafe { store.modules.get(current_module) };
3644
3645 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3648 let memory = unsafe { store.memories.get(mem_addr) };
3652 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3653 let idx = calculate_mem_address(&memarg, relative_address)?;
3654
3655 let lane = memory.mem.load::<8, u64>(idx)?;
3656 stack.push_value::<T>(Value::V128(from_lanes([lane; 2])))?;
3657 }
3658
3659 V128_LOAD32_ZERO => {
3661 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD32_ZERO));
3662 let memarg = MemArg::read(wasm).unwrap_validated();
3663
3664 let module = unsafe { store.modules.get(current_module) };
3669
3670 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3673 let memory = unsafe { store.memories.get(mem_addr) };
3677
3678 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3679 let idx = calculate_mem_address(&memarg, relative_address)?;
3680
3681 let data = memory.mem.load::<4, u32>(idx)? as u128;
3682 stack.push_value::<T>(Value::V128(data.to_le_bytes()))?;
3683 }
3684 V128_LOAD64_ZERO => {
3685 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD64_ZERO));
3686 let memarg = MemArg::read(wasm).unwrap_validated();
3687 let module = unsafe { store.modules.get(current_module) };
3692
3693 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3696 let memory = unsafe { store.memories.get(mem_addr) };
3700
3701 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3702 let idx = calculate_mem_address(&memarg, relative_address)?;
3703
3704 let data = memory.mem.load::<8, u64>(idx)? as u128;
3705 stack.push_value::<T>(Value::V128(data.to_le_bytes()))?;
3706 }
3707
3708 V128_LOAD8_LANE => {
3710 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD8_LANE));
3711 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3712 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3713 let memarg = MemArg::read(wasm).unwrap_validated();
3714 let module = unsafe { store.modules.get(current_module) };
3719
3720 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3723 let memory = unsafe { store.memories.get(mem_addr) };
3727 let idx = calculate_mem_address(&memarg, relative_address)?;
3728 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
3729 let mut lanes: [u8; 16] = to_lanes(data);
3730 *lanes.get_mut(lane_idx).unwrap_validated() =
3731 memory.mem.load::<1, u8>(idx)?;
3732 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
3733 }
3734
3735 V128_LOAD16_LANE => {
3736 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD16_LANE));
3737 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3738 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3739 let memarg = MemArg::read(wasm).unwrap_validated();
3740 let module = unsafe { store.modules.get(current_module) };
3745
3746 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3749 let memory = unsafe { store.memories.get(mem_addr) };
3753 let idx = calculate_mem_address(&memarg, relative_address)?;
3754 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
3755 let mut lanes: [u16; 8] = to_lanes(data);
3756 *lanes.get_mut(lane_idx).unwrap_validated() =
3757 memory.mem.load::<2, u16>(idx)?;
3758 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
3759 }
3760 V128_LOAD32_LANE => {
3761 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD32_LANE));
3762 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3763 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3764 let memarg = MemArg::read(wasm).unwrap_validated();
3765 let module = unsafe { store.modules.get(current_module) };
3770
3771 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3774 let memory = unsafe { store.memories.get(mem_addr) };
3778 let idx = calculate_mem_address(&memarg, relative_address)?;
3779 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
3780 let mut lanes: [u32; 4] = to_lanes(data);
3781 *lanes.get_mut(lane_idx).unwrap_validated() =
3782 memory.mem.load::<4, u32>(idx)?;
3783 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
3784 }
3785 V128_LOAD64_LANE => {
3786 decrement_fuel!(T::get_fd_extension_flat_cost(V128_LOAD64_LANE));
3787 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3788 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3789 let memarg = MemArg::read(wasm).unwrap_validated();
3790 let module = unsafe { store.modules.get(current_module) };
3795
3796 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3799 let memory = unsafe { store.memories.get(mem_addr) };
3803 let idx = calculate_mem_address(&memarg, relative_address)?;
3804 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
3805 let mut lanes: [u64; 2] = to_lanes(data);
3806 *lanes.get_mut(lane_idx).unwrap_validated() =
3807 memory.mem.load::<8, u64>(idx)?;
3808 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
3809 }
3810
3811 V128_STORE8_LANE => {
3813 decrement_fuel!(T::get_fd_extension_flat_cost(V128_STORE8_LANE));
3814 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3815 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3816 let memarg = MemArg::read(wasm).unwrap_validated();
3817 let module = unsafe { store.modules.get(current_module) };
3822
3823 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3826 let memory = unsafe { store.memories.get(mem_addr) };
3830 let idx = calculate_mem_address(&memarg, relative_address)?;
3831 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
3832
3833 let lane = *to_lanes::<1, 16, u8>(data).get(lane_idx).unwrap_validated();
3834
3835 memory.mem.store::<1, u8>(idx, lane)?;
3836 }
3837 V128_STORE16_LANE => {
3838 decrement_fuel!(T::get_fd_extension_flat_cost(V128_STORE16_LANE));
3839 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3840 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3841 let memarg = MemArg::read(wasm).unwrap_validated();
3842 let module = unsafe { store.modules.get(current_module) };
3847
3848 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3851 let memory = unsafe { store.memories.get(mem_addr) };
3855 let idx = calculate_mem_address(&memarg, relative_address)?;
3856 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
3857
3858 let lane = *to_lanes::<2, 8, u16>(data).get(lane_idx).unwrap_validated();
3859
3860 memory.mem.store::<2, u16>(idx, lane)?;
3861 }
3862 V128_STORE32_LANE => {
3863 decrement_fuel!(T::get_fd_extension_flat_cost(V128_STORE32_LANE));
3864 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3865 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3866 let memarg = MemArg::read(wasm).unwrap_validated();
3867 let module = unsafe { store.modules.get(current_module) };
3872
3873 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3876 let memory = unsafe { store.memories.get(mem_addr) };
3880 let idx = calculate_mem_address(&memarg, relative_address)?;
3881 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
3882
3883 let lane = *to_lanes::<4, 4, u32>(data).get(lane_idx).unwrap_validated();
3884
3885 memory.mem.store::<4, u32>(idx, lane)?;
3886 }
3887 V128_STORE64_LANE => {
3888 decrement_fuel!(T::get_fd_extension_flat_cost(V128_STORE64_LANE));
3889 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3890 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
3891 let memarg = MemArg::read(wasm).unwrap_validated();
3892 let module = unsafe { store.modules.get(current_module) };
3897
3898 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
3901 let memory = unsafe { store.memories.get(mem_addr) };
3905 let idx = calculate_mem_address(&memarg, relative_address)?;
3906 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
3907
3908 let lane = *to_lanes::<8, 2, u64>(data).get(lane_idx).unwrap_validated();
3909
3910 memory.mem.store::<8, u64>(idx, lane)?;
3911 }
3912
3913 V128_CONST => {
3914 decrement_fuel!(T::get_fd_extension_flat_cost(V128_CONST));
3915 let mut data = [0; 16];
3916 for byte_ref in &mut data {
3917 *byte_ref = wasm.read_u8().unwrap_validated();
3918 }
3919
3920 stack.push_value::<T>(Value::V128(data))?;
3921 }
3922
3923 V128_NOT => {
3925 decrement_fuel!(T::get_fd_extension_flat_cost(V128_NOT));
3926 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3927 stack.push_value::<T>(Value::V128(data.map(|byte| !byte)))?;
3928 }
3929
3930 V128_AND => {
3932 decrement_fuel!(T::get_fd_extension_flat_cost(V128_AND));
3933 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3934 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3935 let result = array::from_fn(|i| data1[i] & data2[i]);
3936 stack.push_value::<T>(Value::V128(result))?;
3937 }
3938 V128_ANDNOT => {
3939 decrement_fuel!(T::get_fd_extension_flat_cost(V128_ANDNOT));
3940 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3941 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3942 let result = array::from_fn(|i| data1[i] & !data2[i]);
3943 stack.push_value::<T>(Value::V128(result))?;
3944 }
3945 V128_OR => {
3946 decrement_fuel!(T::get_fd_extension_flat_cost(V128_OR));
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 result = array::from_fn(|i| data1[i] | data2[i]);
3950 stack.push_value::<T>(Value::V128(result))?;
3951 }
3952 V128_XOR => {
3953 decrement_fuel!(T::get_fd_extension_flat_cost(V128_XOR));
3954 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3955 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3956 let result = array::from_fn(|i| data1[i] ^ data2[i]);
3957 stack.push_value::<T>(Value::V128(result))?;
3958 }
3959
3960 V128_BITSELECT => {
3962 decrement_fuel!(T::get_fd_extension_flat_cost(V128_BITSELECT));
3963 let data3: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3964 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3965 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3966 let result =
3967 array::from_fn(|i| (data1[i] & data3[i]) | (data2[i] & !data3[i]));
3968 stack.push_value::<T>(Value::V128(result))?;
3969 }
3970
3971 V128_ANY_TRUE => {
3973 decrement_fuel!(T::get_fd_extension_flat_cost(V128_ANY_TRUE));
3974 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3975 let any_true = data.into_iter().any(|byte| byte > 0);
3976 stack.push_value::<T>(Value::I32(any_true as u32))?;
3977 }
3978
3979 I8X16_SWIZZLE => {
3980 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_SWIZZLE));
3981 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3982 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3983 let result =
3984 array::from_fn(|i| *data1.get(usize::from(data2[i])).unwrap_or(&0));
3985 stack.push_value::<T>(Value::V128(result))?;
3986 }
3987
3988 I8X16_SHUFFLE => {
3989 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_SHUFFLE));
3990 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3991 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
3992
3993 let lane_selector_indices: [u8; 16] =
3994 array::from_fn(|_| wasm.read_u8().unwrap_validated());
3995
3996 let result = lane_selector_indices.map(|i| {
3997 *data1
3998 .get(usize::from(i))
3999 .or_else(|| data2.get(usize::from(i) - 16))
4000 .unwrap_validated()
4001 });
4002
4003 stack.push_value::<T>(Value::V128(result))?;
4004 }
4005
4006 I8X16_SPLAT => {
4008 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_SPLAT));
4009 let value: u32 = stack.pop_value().try_into().unwrap_validated();
4010 let lane = value as u8;
4011 let data = from_lanes([lane; 16]);
4012 stack.push_value::<T>(Value::V128(data))?;
4013 }
4014 I16X8_SPLAT => {
4015 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_SPLAT));
4016 let value: u32 = stack.pop_value().try_into().unwrap_validated();
4017 let lane = value as u16;
4018 let data = from_lanes([lane; 8]);
4019 stack.push_value::<T>(Value::V128(data))?;
4020 }
4021 I32X4_SPLAT => {
4022 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_SPLAT));
4023 let lane: u32 = stack.pop_value().try_into().unwrap_validated();
4024 let data = from_lanes([lane; 4]);
4025 stack.push_value::<T>(Value::V128(data))?;
4026 }
4027 I64X2_SPLAT => {
4028 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_SPLAT));
4029 let lane: u64 = stack.pop_value().try_into().unwrap_validated();
4030 let data = from_lanes([lane; 2]);
4031 stack.push_value::<T>(Value::V128(data))?;
4032 }
4033 F32X4_SPLAT => {
4034 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_SPLAT));
4035 let lane: F32 = stack.pop_value().try_into().unwrap_validated();
4036 let data = from_lanes([lane; 4]);
4037 stack.push_value::<T>(Value::V128(data))?;
4038 }
4039 F64X2_SPLAT => {
4040 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_SPLAT));
4041 let lane: F64 = stack.pop_value().try_into().unwrap_validated();
4042 let data = from_lanes([lane; 2]);
4043 stack.push_value::<T>(Value::V128(data))?;
4044 }
4045
4046 I8X16_EXTRACT_LANE_S => {
4048 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_EXTRACT_LANE_S));
4049 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4050 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4051 let lanes: [i8; 16] = to_lanes(data);
4052 let lane = *lanes.get(lane_idx).unwrap_validated();
4053 stack.push_value::<T>(Value::I32(lane as u32))?;
4054 }
4055 I8X16_EXTRACT_LANE_U => {
4056 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_EXTRACT_LANE_U));
4057 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4058 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4059 let lanes: [u8; 16] = to_lanes(data);
4060 let lane = *lanes.get(lane_idx).unwrap_validated();
4061 stack.push_value::<T>(Value::I32(lane as u32))?;
4062 }
4063 I16X8_EXTRACT_LANE_S => {
4064 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTRACT_LANE_S));
4065 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4066 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4067 let lanes: [i16; 8] = to_lanes(data);
4068 let lane = *lanes.get(lane_idx).unwrap_validated();
4069 stack.push_value::<T>(Value::I32(lane as u32))?;
4070 }
4071 I16X8_EXTRACT_LANE_U => {
4072 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTRACT_LANE_U));
4073 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4074 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4075 let lanes: [u16; 8] = to_lanes(data);
4076 let lane = *lanes.get(lane_idx).unwrap_validated();
4077 stack.push_value::<T>(Value::I32(lane as u32))?;
4078 }
4079 I32X4_EXTRACT_LANE => {
4080 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTRACT_LANE));
4081 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4082 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4083 let lanes: [u32; 4] = to_lanes(data);
4084 let lane = *lanes.get(lane_idx).unwrap_validated();
4085 stack.push_value::<T>(Value::I32(lane))?;
4086 }
4087 I64X2_EXTRACT_LANE => {
4088 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTRACT_LANE));
4089 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4090 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4091 let lanes: [u64; 2] = to_lanes(data);
4092 let lane = *lanes.get(lane_idx).unwrap_validated();
4093 stack.push_value::<T>(Value::I64(lane))?;
4094 }
4095 F32X4_EXTRACT_LANE => {
4096 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_EXTRACT_LANE));
4097 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4098 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4099 let lanes: [F32; 4] = to_lanes(data);
4100 let lane = *lanes.get(lane_idx).unwrap_validated();
4101 stack.push_value::<T>(Value::F32(lane))?;
4102 }
4103 F64X2_EXTRACT_LANE => {
4104 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_EXTRACT_LANE));
4105 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4106 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4107 let lanes: [F64; 2] = to_lanes(data);
4108 let lane = *lanes.get(lane_idx).unwrap_validated();
4109 stack.push_value::<T>(Value::F64(lane))?;
4110 }
4111
4112 I8X16_REPLACE_LANE => {
4114 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_REPLACE_LANE));
4115 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4116 let value: u32 = stack.pop_value().try_into().unwrap_validated();
4117 let new_lane = value as u8;
4118 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4119 let mut lanes: [u8; 16] = to_lanes(data);
4120 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
4121 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
4122 }
4123 I16X8_REPLACE_LANE => {
4124 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_REPLACE_LANE));
4125 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4126 let value: u32 = stack.pop_value().try_into().unwrap_validated();
4127 let new_lane = value as u16;
4128 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4129 let mut lanes: [u16; 8] = to_lanes(data);
4130 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
4131 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
4132 }
4133 I32X4_REPLACE_LANE => {
4134 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_REPLACE_LANE));
4135 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4136 let new_lane: u32 = stack.pop_value().try_into().unwrap_validated();
4137 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4138 let mut lanes: [u32; 4] = to_lanes(data);
4139 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
4140 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
4141 }
4142 I64X2_REPLACE_LANE => {
4143 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_REPLACE_LANE));
4144 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4145 let new_lane: u64 = stack.pop_value().try_into().unwrap_validated();
4146 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4147 let mut lanes: [u64; 2] = to_lanes(data);
4148 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
4149 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
4150 }
4151 F32X4_REPLACE_LANE => {
4152 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_REPLACE_LANE));
4153 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4154 let new_lane: F32 = stack.pop_value().try_into().unwrap_validated();
4155 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4156 let mut lanes: [F32; 4] = to_lanes(data);
4157 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
4158 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
4159 }
4160 F64X2_REPLACE_LANE => {
4161 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_REPLACE_LANE));
4162 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
4163 let new_lane: F64 = stack.pop_value().try_into().unwrap_validated();
4164 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4165 let mut lanes: [F64; 2] = to_lanes(data);
4166 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
4167 stack.push_value::<T>(Value::V128(from_lanes(lanes)))?;
4168 }
4169
4170 I8X16_ABS => {
4173 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_ABS));
4174 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4175 let lanes: [i8; 16] = to_lanes(data);
4176 let result: [i8; 16] = lanes.map(i8::wrapping_abs);
4177 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4178 }
4179 I16X8_ABS => {
4180 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_ABS));
4181 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4182 let lanes: [i16; 8] = to_lanes(data);
4183 let result: [i16; 8] = lanes.map(i16::wrapping_abs);
4184 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4185 }
4186 I32X4_ABS => {
4187 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_ABS));
4188 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4189 let lanes: [i32; 4] = to_lanes(data);
4190 let result: [i32; 4] = lanes.map(i32::wrapping_abs);
4191 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4192 }
4193 I64X2_ABS => {
4194 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_ABS));
4195 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4196 let lanes: [i64; 2] = to_lanes(data);
4197 let result: [i64; 2] = lanes.map(i64::wrapping_abs);
4198 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4199 }
4200 I8X16_NEG => {
4201 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_NEG));
4202 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4203 let lanes: [i8; 16] = to_lanes(data);
4204 let result: [i8; 16] = lanes.map(i8::wrapping_neg);
4205 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4206 }
4207 I16X8_NEG => {
4208 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_NEG));
4209 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4210 let lanes: [i16; 8] = to_lanes(data);
4211 let result: [i16; 8] = lanes.map(i16::wrapping_neg);
4212 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4213 }
4214 I32X4_NEG => {
4215 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_NEG));
4216 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4217 let lanes: [i32; 4] = to_lanes(data);
4218 let result: [i32; 4] = lanes.map(i32::wrapping_neg);
4219 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4220 }
4221 I64X2_NEG => {
4222 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_NEG));
4223 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4224 let lanes: [i64; 2] = to_lanes(data);
4225 let result: [i64; 2] = lanes.map(i64::wrapping_neg);
4226 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4227 }
4228 F32X4_ABS => {
4230 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_ABS));
4231 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4232 let lanes: [F32; 4] = to_lanes(data);
4233 let result: [F32; 4] = lanes.map(|lane| lane.abs());
4234 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4235 }
4236 F64X2_ABS => {
4237 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_ABS));
4238 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4239 let lanes: [F64; 2] = to_lanes(data);
4240 let result: [F64; 2] = lanes.map(|lane| lane.abs());
4241 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4242 }
4243 F32X4_NEG => {
4244 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_NEG));
4245 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4246 let lanes: [F32; 4] = to_lanes(data);
4247 let result: [F32; 4] = lanes.map(|lane| lane.neg());
4248 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4249 }
4250 F64X2_NEG => {
4251 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_NEG));
4252 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4253 let lanes: [F64; 2] = to_lanes(data);
4254 let result: [F64; 2] = lanes.map(|lane| lane.neg());
4255 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4256 }
4257 F32X4_SQRT => {
4258 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_SQRT));
4259 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4260 let lanes: [F32; 4] = to_lanes(data);
4261 let result: [F32; 4] = lanes.map(|lane| lane.sqrt());
4262 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4263 }
4264 F64X2_SQRT => {
4265 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_SQRT));
4266 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4267 let lanes: [F64; 2] = to_lanes(data);
4268 let result: [F64; 2] = lanes.map(|lane| lane.sqrt());
4269 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4270 }
4271 F32X4_CEIL => {
4272 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_CEIL));
4273 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4274 let lanes: [F32; 4] = to_lanes(data);
4275 let result: [F32; 4] = lanes.map(|lane| lane.ceil());
4276 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4277 }
4278 F64X2_CEIL => {
4279 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_CEIL));
4280 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4281 let lanes: [F64; 2] = to_lanes(data);
4282 let result: [F64; 2] = lanes.map(|lane| lane.ceil());
4283 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4284 }
4285 F32X4_FLOOR => {
4286 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_FLOOR));
4287 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4288 let lanes: [F32; 4] = to_lanes(data);
4289 let result: [F32; 4] = lanes.map(|lane| lane.floor());
4290 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4291 }
4292 F64X2_FLOOR => {
4293 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_FLOOR));
4294 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4295 let lanes: [F64; 2] = to_lanes(data);
4296 let result: [F64; 2] = lanes.map(|lane| lane.floor());
4297 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4298 }
4299 F32X4_TRUNC => {
4300 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_TRUNC));
4301 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4302 let lanes: [F32; 4] = to_lanes(data);
4303 let result: [F32; 4] = lanes.map(|lane| lane.trunc());
4304 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4305 }
4306 F64X2_TRUNC => {
4307 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_TRUNC));
4308 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4309 let lanes: [F64; 2] = to_lanes(data);
4310 let result: [F64; 2] = lanes.map(|lane| lane.trunc());
4311 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4312 }
4313 F32X4_NEAREST => {
4314 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_NEAREST));
4315 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4316 let lanes: [F32; 4] = to_lanes(data);
4317 let result: [F32; 4] = lanes.map(|lane| lane.nearest());
4318 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4319 }
4320 F64X2_NEAREST => {
4321 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_NEAREST));
4322 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4323 let lanes: [F64; 2] = to_lanes(data);
4324 let result: [F64; 2] = lanes.map(|lane| lane.nearest());
4325 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4326 }
4327 I8X16_POPCNT => {
4329 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_POPCNT));
4330 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4331 let lanes: [u8; 16] = to_lanes(data);
4332 let result: [u8; 16] = lanes.map(|lane| lane.count_ones() as u8);
4333 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4334 }
4335
4336 I8X16_ADD => {
4339 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_ADD));
4340 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4341 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4342 let lanes2: [u8; 16] = to_lanes(data2);
4343 let lanes1: [u8; 16] = to_lanes(data1);
4344 let result: [u8; 16] =
4345 array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
4346 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4347 }
4348 I16X8_ADD => {
4349 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_ADD));
4350 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4351 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4352 let lanes2: [u16; 8] = to_lanes(data2);
4353 let lanes1: [u16; 8] = to_lanes(data1);
4354 let result: [u16; 8] =
4355 array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
4356 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4357 }
4358 I32X4_ADD => {
4359 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_ADD));
4360 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4361 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4362 let lanes2: [u32; 4] = to_lanes(data2);
4363 let lanes1: [u32; 4] = to_lanes(data1);
4364 let result: [u32; 4] =
4365 array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
4366 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4367 }
4368 I64X2_ADD => {
4369 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_ADD));
4370 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4371 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4372 let lanes2: [u64; 2] = to_lanes(data2);
4373 let lanes1: [u64; 2] = to_lanes(data1);
4374 let result: [u64; 2] =
4375 array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
4376 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4377 }
4378 I8X16_SUB => {
4379 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_SUB));
4380 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4381 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4382 let lanes2: [u8; 16] = to_lanes(data2);
4383 let lanes1: [u8; 16] = to_lanes(data1);
4384 let result: [u8; 16] =
4385 array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
4386 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4387 }
4388 I16X8_SUB => {
4389 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_SUB));
4390 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4391 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4392 let lanes2: [u16; 8] = to_lanes(data2);
4393 let lanes1: [u16; 8] = to_lanes(data1);
4394 let result: [u16; 8] =
4395 array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
4396 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4397 }
4398 I32X4_SUB => {
4399 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_SUB));
4400 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4401 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4402 let lanes2: [u32; 4] = to_lanes(data2);
4403 let lanes1: [u32; 4] = to_lanes(data1);
4404 let result: [u32; 4] =
4405 array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
4406 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4407 }
4408 I64X2_SUB => {
4409 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_SUB));
4410 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4411 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4412 let lanes2: [u64; 2] = to_lanes(data2);
4413 let lanes1: [u64; 2] = to_lanes(data1);
4414 let result: [u64; 2] =
4415 array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
4416 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4417 }
4418 F32X4_ADD => {
4420 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_ADD));
4421 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4422 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4423 let lanes2: [F32; 4] = to_lanes(data2);
4424 let lanes1: [F32; 4] = to_lanes(data1);
4425 let result: [F32; 4] = array::from_fn(|i| lanes1[i].add(lanes2[i]));
4426 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4427 }
4428 F64X2_ADD => {
4429 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_ADD));
4430 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4431 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4432 let lanes2: [F64; 2] = to_lanes(data2);
4433 let lanes1: [F64; 2] = to_lanes(data1);
4434 let result: [F64; 2] = array::from_fn(|i| lanes1[i].add(lanes2[i]));
4435 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4436 }
4437 F32X4_SUB => {
4438 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_SUB));
4439 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4440 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4441 let lanes2: [F32; 4] = to_lanes(data2);
4442 let lanes1: [F32; 4] = to_lanes(data1);
4443 let result: [F32; 4] = array::from_fn(|i| lanes1[i].sub(lanes2[i]));
4444 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4445 }
4446 F64X2_SUB => {
4447 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_SUB));
4448 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4449 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4450 let lanes2: [F64; 2] = to_lanes(data2);
4451 let lanes1: [F64; 2] = to_lanes(data1);
4452 let result: [F64; 2] = array::from_fn(|i| lanes1[i].sub(lanes2[i]));
4453 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4454 }
4455 F32X4_MUL => {
4456 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_MUL));
4457 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4458 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4459 let lanes2: [F32; 4] = to_lanes(data2);
4460 let lanes1: [F32; 4] = to_lanes(data1);
4461 let result: [F32; 4] = array::from_fn(|i| lanes1[i].mul(lanes2[i]));
4462 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4463 }
4464 F64X2_MUL => {
4465 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_MUL));
4466 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4467 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4468 let lanes2: [F64; 2] = to_lanes(data2);
4469 let lanes1: [F64; 2] = to_lanes(data1);
4470 let result: [F64; 2] = array::from_fn(|i| lanes1[i].mul(lanes2[i]));
4471 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4472 }
4473 F32X4_DIV => {
4474 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_DIV));
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: [F32; 4] = to_lanes(data2);
4478 let lanes1: [F32; 4] = to_lanes(data1);
4479 let result: [F32; 4] = array::from_fn(|i| lanes1[i].div(lanes2[i]));
4480 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4481 }
4482 F64X2_DIV => {
4483 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_DIV));
4484 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4485 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4486 let lanes2: [F64; 2] = to_lanes(data2);
4487 let lanes1: [F64; 2] = to_lanes(data1);
4488 let result: [F64; 2] = array::from_fn(|i| lanes1[i].div(lanes2[i]));
4489 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4490 }
4491 F32X4_MIN => {
4492 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_MIN));
4493 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4494 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4495 let lanes2: [F32; 4] = to_lanes(data2);
4496 let lanes1: [F32; 4] = to_lanes(data1);
4497 let result: [F32; 4] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
4498 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4499 }
4500 F64X2_MIN => {
4501 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_MIN));
4502 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4503 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4504 let lanes2: [F64; 2] = to_lanes(data2);
4505 let lanes1: [F64; 2] = to_lanes(data1);
4506 let result: [F64; 2] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
4507 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4508 }
4509 F32X4_MAX => {
4510 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_MAX));
4511 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4512 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4513 let lanes2: [F32; 4] = to_lanes(data2);
4514 let lanes1: [F32; 4] = to_lanes(data1);
4515 let result: [F32; 4] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
4516 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4517 }
4518 F64X2_MAX => {
4519 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_MAX));
4520 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4521 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4522 let lanes2: [F64; 2] = to_lanes(data2);
4523 let lanes1: [F64; 2] = to_lanes(data1);
4524 let result: [F64; 2] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
4525 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4526 }
4527 F32X4_PMIN => {
4528 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_PMIN));
4529 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4530 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4531 let lanes2: [F32; 4] = to_lanes(data2);
4532 let lanes1: [F32; 4] = to_lanes(data1);
4533 let result: [F32; 4] = array::from_fn(|i| {
4534 let v1 = lanes1[i];
4535 let v2 = lanes2[i];
4536 if v2 < v1 {
4537 v2
4538 } else {
4539 v1
4540 }
4541 });
4542 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4543 }
4544 F64X2_PMIN => {
4545 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_PMIN));
4546 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4547 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4548 let lanes2: [F64; 2] = to_lanes(data2);
4549 let lanes1: [F64; 2] = to_lanes(data1);
4550 let result: [F64; 2] = array::from_fn(|i| {
4551 let v1 = lanes1[i];
4552 let v2 = lanes2[i];
4553 if v2 < v1 {
4554 v2
4555 } else {
4556 v1
4557 }
4558 });
4559 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4560 }
4561 F32X4_PMAX => {
4562 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_PMAX));
4563 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4564 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4565 let lanes2: [F32; 4] = to_lanes(data2);
4566 let lanes1: [F32; 4] = to_lanes(data1);
4567 let result: [F32; 4] = array::from_fn(|i| {
4568 let v1 = lanes1[i];
4569 let v2 = lanes2[i];
4570 if v1 < v2 {
4571 v2
4572 } else {
4573 v1
4574 }
4575 });
4576 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4577 }
4578 F64X2_PMAX => {
4579 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_PMAX));
4580 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4581 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4582 let lanes2: [F64; 2] = to_lanes(data2);
4583 let lanes1: [F64; 2] = to_lanes(data1);
4584 let result: [F64; 2] = array::from_fn(|i| {
4585 let v1 = lanes1[i];
4586 let v2 = lanes2[i];
4587 if v1 < v2 {
4588 v2
4589 } else {
4590 v1
4591 }
4592 });
4593 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4594 }
4595 I8X16_MIN_S => {
4597 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_MIN_S));
4598 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4599 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4600 let lanes2: [i8; 16] = to_lanes(data2);
4601 let lanes1: [i8; 16] = to_lanes(data1);
4602 let result: [i8; 16] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
4603 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4604 }
4605 I16X8_MIN_S => {
4606 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_MIN_S));
4607 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4608 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4609 let lanes2: [i16; 8] = to_lanes(data2);
4610 let lanes1: [i16; 8] = to_lanes(data1);
4611 let result: [i16; 8] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
4612 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4613 }
4614 I32X4_MIN_S => {
4615 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_MIN_S));
4616 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4617 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4618 let lanes2: [i32; 4] = to_lanes(data2);
4619 let lanes1: [i32; 4] = to_lanes(data1);
4620 let result: [i32; 4] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
4621 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4622 }
4623 I8X16_MIN_U => {
4624 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_MIN_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: [u8; 16] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
4630 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4631 }
4632 I16X8_MIN_U => {
4633 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_MIN_U));
4634 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4635 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4636 let lanes2: [u16; 8] = to_lanes(data2);
4637 let lanes1: [u16; 8] = to_lanes(data1);
4638 let result: [u16; 8] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
4639 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4640 }
4641 I32X4_MIN_U => {
4642 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_MIN_U));
4643 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4644 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4645 let lanes2: [u32; 4] = to_lanes(data2);
4646 let lanes1: [u32; 4] = to_lanes(data1);
4647 let result: [u32; 4] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
4648 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4649 }
4650 I8X16_MAX_S => {
4651 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_MAX_S));
4652 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4653 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4654 let lanes2: [i8; 16] = to_lanes(data2);
4655 let lanes1: [i8; 16] = to_lanes(data1);
4656 let result: [i8; 16] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
4657 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4658 }
4659 I16X8_MAX_S => {
4660 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_MAX_S));
4661 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4662 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4663 let lanes2: [i16; 8] = to_lanes(data2);
4664 let lanes1: [i16; 8] = to_lanes(data1);
4665 let result: [i16; 8] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
4666 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4667 }
4668 I32X4_MAX_S => {
4669 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_MAX_S));
4670 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4671 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4672 let lanes2: [i32; 4] = to_lanes(data2);
4673 let lanes1: [i32; 4] = to_lanes(data1);
4674 let result: [i32; 4] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
4675 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4676 }
4677 I8X16_MAX_U => {
4678 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_MAX_U));
4679 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4680 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4681 let lanes2: [u8; 16] = to_lanes(data2);
4682 let lanes1: [u8; 16] = to_lanes(data1);
4683 let result: [u8; 16] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
4684 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4685 }
4686 I16X8_MAX_U => {
4687 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_MAX_U));
4688 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4689 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4690 let lanes2: [u16; 8] = to_lanes(data2);
4691 let lanes1: [u16; 8] = to_lanes(data1);
4692 let result: [u16; 8] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
4693 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4694 }
4695 I32X4_MAX_U => {
4696 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_MAX_U));
4697 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4698 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4699 let lanes2: [u32; 4] = to_lanes(data2);
4700 let lanes1: [u32; 4] = to_lanes(data1);
4701 let result: [u32; 4] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
4702 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4703 }
4704
4705 I8X16_ADD_SAT_S => {
4707 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_ADD_SAT_S));
4708 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4709 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4710 let lanes2: [i8; 16] = to_lanes(data2);
4711 let lanes1: [i8; 16] = to_lanes(data1);
4712 let result: [i8; 16] =
4713 array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
4714 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4715 }
4716 I16X8_ADD_SAT_S => {
4717 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_ADD_SAT_S));
4718 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4719 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4720 let lanes2: [i16; 8] = to_lanes(data2);
4721 let lanes1: [i16; 8] = to_lanes(data1);
4722 let result: [i16; 8] =
4723 array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
4724 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4725 }
4726 I8X16_ADD_SAT_U => {
4727 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_ADD_SAT_U));
4728 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4729 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4730 let lanes2: [u8; 16] = to_lanes(data2);
4731 let lanes1: [u8; 16] = to_lanes(data1);
4732 let result: [u8; 16] =
4733 array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
4734 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4735 }
4736 I16X8_ADD_SAT_U => {
4737 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_ADD_SAT_U));
4738 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4739 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4740 let lanes2: [u16; 8] = to_lanes(data2);
4741 let lanes1: [u16; 8] = to_lanes(data1);
4742 let result: [u16; 8] =
4743 array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
4744 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4745 }
4746 I8X16_SUB_SAT_S => {
4747 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_SUB_SAT_S));
4748 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4749 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4750 let lanes2: [i8; 16] = to_lanes(data2);
4751 let lanes1: [i8; 16] = to_lanes(data1);
4752 let result: [i8; 16] =
4753 array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
4754 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4755 }
4756 I16X8_SUB_SAT_S => {
4757 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_SUB_SAT_S));
4758 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4759 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4760 let lanes2: [i16; 8] = to_lanes(data2);
4761 let lanes1: [i16; 8] = to_lanes(data1);
4762 let result: [i16; 8] =
4763 array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
4764 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4765 }
4766 I8X16_SUB_SAT_U => {
4767 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_SUB_SAT_U));
4768 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4769 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4770 let lanes2: [u8; 16] = to_lanes(data2);
4771 let lanes1: [u8; 16] = to_lanes(data1);
4772 let result: [u8; 16] =
4773 array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
4774 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4775 }
4776 I16X8_SUB_SAT_U => {
4777 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_SUB_SAT_U));
4778 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4779 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4780 let lanes2: [u16; 8] = to_lanes(data2);
4781 let lanes1: [u16; 8] = to_lanes(data1);
4782 let result: [u16; 8] =
4783 array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
4784 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4785 }
4786 I16X8_MUL => {
4788 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_MUL));
4789 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4790 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4791 let lanes2: [u16; 8] = to_lanes(data2);
4792 let lanes1: [u16; 8] = to_lanes(data1);
4793 let result: [u16; 8] =
4794 array::from_fn(|i| lanes1[i].wrapping_mul(lanes2[i]));
4795 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4796 }
4797 I32X4_MUL => {
4798 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_MUL));
4799 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4800 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4801 let lanes2: [u32; 4] = to_lanes(data2);
4802 let lanes1: [u32; 4] = to_lanes(data1);
4803 let result: [u32; 4] =
4804 array::from_fn(|i| lanes1[i].wrapping_mul(lanes2[i]));
4805 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4806 }
4807 I64X2_MUL => {
4808 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_MUL));
4809 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4810 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4811 let lanes2: [u64; 2] = to_lanes(data2);
4812 let lanes1: [u64; 2] = to_lanes(data1);
4813 let result: [u64; 2] =
4814 array::from_fn(|i| lanes1[i].wrapping_mul(lanes2[i]));
4815 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4816 }
4817 I8X16_AVGR_U => {
4818 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_AVGR_U));
4819 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4820 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4821 let lanes2: [u8; 16] = to_lanes(data2);
4822 let lanes1: [u8; 16] = to_lanes(data1);
4823 let result: [u8; 16] = array::from_fn(|i| {
4824 (lanes1[i] as u16 + lanes2[i] as u16).div_ceil(2) as u8
4825 });
4826 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4827 }
4828 I16X8_AVGR_U => {
4829 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_AVGR_U));
4830 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4831 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4832 let lanes2: [u16; 8] = to_lanes(data2);
4833 let lanes1: [u16; 8] = to_lanes(data1);
4834 let result: [u16; 8] = array::from_fn(|i| {
4835 (lanes1[i] as u32 + lanes2[i] as u32).div_ceil(2) as u16
4836 });
4837 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4838 }
4839 I16X8_Q15MULRSAT_S => {
4840 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_Q15MULRSAT_S));
4841 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4842 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4843 let lanes2: [i16; 8] = to_lanes(data2);
4844 let lanes1: [i16; 8] = to_lanes(data1);
4845 let result: [i16; 8] = array::from_fn(|i| {
4846 (((lanes1[i] as i64).mul(lanes2[i] as i64) + 2i64.pow(14)) >> 15i64)
4847 .clamp(i16::MIN as i64, i16::MAX as i64)
4848 as i16
4849 });
4850 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4851 }
4852
4853 I8X16_EQ => {
4856 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_EQ));
4857 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4858 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4859 let lanes2: [u8; 16] = to_lanes(data2);
4860 let lanes1: [u8; 16] = to_lanes(data1);
4861 let result: [i8; 16] =
4862 array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i8).neg());
4863 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4864 }
4865 I16X8_EQ => {
4866 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EQ));
4867 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4868 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4869 let lanes2: [u16; 8] = to_lanes(data2);
4870 let lanes1: [u16; 8] = to_lanes(data1);
4871 let result: [i16; 8] =
4872 array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i16).neg());
4873 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4874 }
4875 I32X4_EQ => {
4876 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EQ));
4877 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4878 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4879 let lanes2: [u32; 4] = to_lanes(data2);
4880 let lanes1: [u32; 4] = to_lanes(data1);
4881 let result: [i32; 4] =
4882 array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i32).neg());
4883 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4884 }
4885 I64X2_EQ => {
4886 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EQ));
4887 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4888 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4889 let lanes2: [u64; 2] = to_lanes(data2);
4890 let lanes1: [u64; 2] = to_lanes(data1);
4891 let result: [i64; 2] =
4892 array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i64).neg());
4893 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4894 }
4895 I8X16_NE => {
4896 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_NE));
4897 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4898 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4899 let lanes2: [u8; 16] = to_lanes(data2);
4900 let lanes1: [u8; 16] = to_lanes(data1);
4901 let result: [i8; 16] =
4902 array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i8).neg());
4903 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4904 }
4905 I16X8_NE => {
4906 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_NE));
4907 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4908 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4909 let lanes2: [u16; 8] = to_lanes(data2);
4910 let lanes1: [u16; 8] = to_lanes(data1);
4911 let result: [i16; 8] =
4912 array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i16).neg());
4913 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4914 }
4915 I32X4_NE => {
4916 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_NE));
4917 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4918 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4919 let lanes2: [u32; 4] = to_lanes(data2);
4920 let lanes1: [u32; 4] = to_lanes(data1);
4921 let result: [i32; 4] =
4922 array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i32).neg());
4923 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4924 }
4925 I64X2_NE => {
4926 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_NE));
4927 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4928 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4929 let lanes2: [u64; 2] = to_lanes(data2);
4930 let lanes1: [u64; 2] = to_lanes(data1);
4931 let result: [i64; 2] =
4932 array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i64).neg());
4933 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4934 }
4935 I8X16_LT_S => {
4936 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_LT_S));
4937 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4938 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4939 let lanes2: [i8; 16] = to_lanes(data2);
4940 let lanes1: [i8; 16] = to_lanes(data1);
4941 let result: [i8; 16] =
4942 array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i8).neg());
4943 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4944 }
4945 I16X8_LT_S => {
4946 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_LT_S));
4947 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4948 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4949 let lanes2: [i16; 8] = to_lanes(data2);
4950 let lanes1: [i16; 8] = to_lanes(data1);
4951 let result: [i16; 8] =
4952 array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i16).neg());
4953 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4954 }
4955 I32X4_LT_S => {
4956 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_LT_S));
4957 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4958 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4959 let lanes2: [i32; 4] = to_lanes(data2);
4960 let lanes1: [i32; 4] = to_lanes(data1);
4961 let result: [i32; 4] =
4962 array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i32).neg());
4963 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4964 }
4965 I64X2_LT_S => {
4966 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_LT_S));
4967 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4968 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4969 let lanes2: [i64; 2] = to_lanes(data2);
4970 let lanes1: [i64; 2] = to_lanes(data1);
4971 let result: [i64; 2] =
4972 array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i64).neg());
4973 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4974 }
4975 I8X16_LT_U => {
4976 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_LT_U));
4977 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4978 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4979 let lanes2: [u8; 16] = to_lanes(data2);
4980 let lanes1: [u8; 16] = to_lanes(data1);
4981 let result: [i8; 16] =
4982 array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i8).neg());
4983 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4984 }
4985 I16X8_LT_U => {
4986 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_LT_U));
4987 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4988 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4989 let lanes2: [u16; 8] = to_lanes(data2);
4990 let lanes1: [u16; 8] = to_lanes(data1);
4991 let result: [i16; 8] =
4992 array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i16).neg());
4993 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
4994 }
4995 I32X4_LT_U => {
4996 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_LT_U));
4997 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4998 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
4999 let lanes2: [u32; 4] = to_lanes(data2);
5000 let lanes1: [u32; 4] = to_lanes(data1);
5001 let result: [i32; 4] =
5002 array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i32).neg());
5003 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5004 }
5005 I8X16_GT_S => {
5006 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_GT_S));
5007 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5008 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5009 let lanes2: [i8; 16] = to_lanes(data2);
5010 let lanes1: [i8; 16] = to_lanes(data1);
5011 let result: [i8; 16] =
5012 array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i8).neg());
5013 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5014 }
5015 I16X8_GT_S => {
5016 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_GT_S));
5017 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5018 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5019 let lanes2: [i16; 8] = to_lanes(data2);
5020 let lanes1: [i16; 8] = to_lanes(data1);
5021 let result: [i16; 8] =
5022 array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i16).neg());
5023 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5024 }
5025 I32X4_GT_S => {
5026 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_GT_S));
5027 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5028 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5029 let lanes2: [i32; 4] = to_lanes(data2);
5030 let lanes1: [i32; 4] = to_lanes(data1);
5031 let result: [i32; 4] =
5032 array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i32).neg());
5033 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5034 }
5035 I64X2_GT_S => {
5036 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_GT_S));
5037 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5038 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5039 let lanes2: [i64; 2] = to_lanes(data2);
5040 let lanes1: [i64; 2] = to_lanes(data1);
5041 let result: [i64; 2] =
5042 array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i64).neg());
5043 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5044 }
5045 I8X16_GT_U => {
5046 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_GT_U));
5047 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5048 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5049 let lanes2: [u8; 16] = to_lanes(data2);
5050 let lanes1: [u8; 16] = to_lanes(data1);
5051 let result: [i8; 16] =
5052 array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i8).neg());
5053 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5054 }
5055 I16X8_GT_U => {
5056 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_GT_U));
5057 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5058 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5059 let lanes2: [u16; 8] = to_lanes(data2);
5060 let lanes1: [u16; 8] = to_lanes(data1);
5061 let result: [i16; 8] =
5062 array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i16).neg());
5063 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5064 }
5065 I32X4_GT_U => {
5066 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_GT_U));
5067 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5068 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5069 let lanes2: [u32; 4] = to_lanes(data2);
5070 let lanes1: [u32; 4] = to_lanes(data1);
5071 let result: [i32; 4] =
5072 array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i32).neg());
5073 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5074 }
5075 I8X16_LE_S => {
5076 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_LE_S));
5077 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5078 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5079 let lanes2: [i8; 16] = to_lanes(data2);
5080 let lanes1: [i8; 16] = to_lanes(data1);
5081 let result: [i8; 16] =
5082 array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i8).neg());
5083 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5084 }
5085 I16X8_LE_S => {
5086 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_LE_S));
5087 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5088 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5089 let lanes2: [i16; 8] = to_lanes(data2);
5090 let lanes1: [i16; 8] = to_lanes(data1);
5091 let result: [i16; 8] =
5092 array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i16).neg());
5093 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5094 }
5095 I32X4_LE_S => {
5096 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_LE_S));
5097 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5098 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5099 let lanes2: [i32; 4] = to_lanes(data2);
5100 let lanes1: [i32; 4] = to_lanes(data1);
5101 let result: [i32; 4] =
5102 array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i32).neg());
5103 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5104 }
5105 I64X2_LE_S => {
5106 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_LE_S));
5107 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5108 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5109 let lanes2: [i64; 2] = to_lanes(data2);
5110 let lanes1: [i64; 2] = to_lanes(data1);
5111 let result: [i64; 2] =
5112 array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i64).neg());
5113 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5114 }
5115 I8X16_LE_U => {
5116 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_LE_U));
5117 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5118 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5119 let lanes2: [u8; 16] = to_lanes(data2);
5120 let lanes1: [u8; 16] = to_lanes(data1);
5121 let result: [i8; 16] =
5122 array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i8).neg());
5123 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5124 }
5125 I16X8_LE_U => {
5126 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_LE_U));
5127 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5128 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5129 let lanes2: [u16; 8] = to_lanes(data2);
5130 let lanes1: [u16; 8] = to_lanes(data1);
5131 let result: [i16; 8] =
5132 array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i16).neg());
5133 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5134 }
5135 I32X4_LE_U => {
5136 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_LE_U));
5137 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5138 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5139 let lanes2: [u32; 4] = to_lanes(data2);
5140 let lanes1: [u32; 4] = to_lanes(data1);
5141 let result: [i32; 4] =
5142 array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i32).neg());
5143 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5144 }
5145
5146 I8X16_GE_S => {
5147 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_GE_S));
5148 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5149 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5150 let lanes2: [i8; 16] = to_lanes(data2);
5151 let lanes1: [i8; 16] = to_lanes(data1);
5152 let result: [i8; 16] =
5153 array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i8).neg());
5154 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5155 }
5156 I16X8_GE_S => {
5157 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_GE_S));
5158 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5159 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5160 let lanes2: [i16; 8] = to_lanes(data2);
5161 let lanes1: [i16; 8] = to_lanes(data1);
5162 let result: [i16; 8] =
5163 array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i16).neg());
5164 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5165 }
5166 I32X4_GE_S => {
5167 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_GE_S));
5168 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5169 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5170 let lanes2: [i32; 4] = to_lanes(data2);
5171 let lanes1: [i32; 4] = to_lanes(data1);
5172 let result: [i32; 4] =
5173 array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i32).neg());
5174 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5175 }
5176 I64X2_GE_S => {
5177 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_GE_S));
5178 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5179 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5180 let lanes2: [i64; 2] = to_lanes(data2);
5181 let lanes1: [i64; 2] = to_lanes(data1);
5182 let result: [i64; 2] =
5183 array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i64).neg());
5184 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5185 }
5186 I8X16_GE_U => {
5187 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_GE_U));
5188 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5189 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5190 let lanes2: [u8; 16] = to_lanes(data2);
5191 let lanes1: [u8; 16] = to_lanes(data1);
5192 let result: [i8; 16] =
5193 array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i8).neg());
5194 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5195 }
5196 I16X8_GE_U => {
5197 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_GE_U));
5198 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5199 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5200 let lanes2: [u16; 8] = to_lanes(data2);
5201 let lanes1: [u16; 8] = to_lanes(data1);
5202 let result: [i16; 8] =
5203 array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i16).neg());
5204 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5205 }
5206 I32X4_GE_U => {
5207 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_GE_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: [u32; 4] = to_lanes(data2);
5211 let lanes1: [u32; 4] = to_lanes(data1);
5212 let result: [i32; 4] =
5213 array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i32).neg());
5214 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5215 }
5216 F32X4_EQ => {
5218 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_EQ));
5219 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5220 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5221 let lanes2: [F32; 4] = to_lanes(data2);
5222 let lanes1: [F32; 4] = to_lanes(data1);
5223 let result: [i32; 4] =
5224 array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i32).neg());
5225 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5226 }
5227 F64X2_EQ => {
5228 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_EQ));
5229 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5230 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5231 let lanes2: [F64; 2] = to_lanes(data2);
5232 let lanes1: [F64; 2] = to_lanes(data1);
5233 let result: [i64; 2] =
5234 array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i64).neg());
5235 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5236 }
5237 F32X4_NE => {
5238 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_NE));
5239 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5240 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5241 let lanes2: [F32; 4] = to_lanes(data2);
5242 let lanes1: [F32; 4] = to_lanes(data1);
5243 let result: [i32; 4] =
5244 array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i32).neg());
5245 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5246 }
5247 F64X2_NE => {
5248 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_NE));
5249 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5250 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5251 let lanes2: [F64; 2] = to_lanes(data2);
5252 let lanes1: [F64; 2] = to_lanes(data1);
5253 let result: [i64; 2] =
5254 array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i64).neg());
5255 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5256 }
5257 F32X4_LT => {
5258 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_LT));
5259 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5260 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5261 let lanes2: [F32; 4] = to_lanes(data2);
5262 let lanes1: [F32; 4] = to_lanes(data1);
5263 let result: [i32; 4] =
5264 array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i32).neg());
5265 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5266 }
5267 F64X2_LT => {
5268 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_LT));
5269 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5270 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5271 let lanes2: [F64; 2] = to_lanes(data2);
5272 let lanes1: [F64; 2] = to_lanes(data1);
5273 let result: [i64; 2] =
5274 array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i64).neg());
5275 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5276 }
5277 F32X4_GT => {
5278 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_GT));
5279 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5280 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5281 let lanes2: [F32; 4] = to_lanes(data2);
5282 let lanes1: [F32; 4] = to_lanes(data1);
5283 let result: [i32; 4] =
5284 array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i32).neg());
5285 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5286 }
5287 F64X2_GT => {
5288 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_GT));
5289 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5290 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5291 let lanes2: [F64; 2] = to_lanes(data2);
5292 let lanes1: [F64; 2] = to_lanes(data1);
5293 let result: [i64; 2] =
5294 array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i64).neg());
5295 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5296 }
5297 F32X4_LE => {
5298 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_LE));
5299 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5300 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5301 let lanes2: [F32; 4] = to_lanes(data2);
5302 let lanes1: [F32; 4] = to_lanes(data1);
5303 let result: [i32; 4] =
5304 array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i32).neg());
5305 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5306 }
5307 F64X2_LE => {
5308 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_LE));
5309 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5310 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5311 let lanes2: [F64; 2] = to_lanes(data2);
5312 let lanes1: [F64; 2] = to_lanes(data1);
5313 let result: [i64; 2] =
5314 array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i64).neg());
5315 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5316 }
5317 F32X4_GE => {
5318 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_GE));
5319 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5320 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5321 let lanes2: [F32; 4] = to_lanes(data2);
5322 let lanes1: [F32; 4] = to_lanes(data1);
5323 let result: [i32; 4] =
5324 array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i32).neg());
5325 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5326 }
5327 F64X2_GE => {
5328 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_GE));
5329 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5330 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5331 let lanes2: [F64; 2] = to_lanes(data2);
5332 let lanes1: [F64; 2] = to_lanes(data1);
5333 let result: [i64; 2] =
5334 array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i64).neg());
5335 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5336 }
5337
5338 I8X16_SHL => {
5340 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_SHL));
5341 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5342 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5343 let lanes: [u8; 16] = to_lanes(data);
5344 let result: [u8; 16] = lanes.map(|lane| lane.wrapping_shl(shift));
5345 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5346 }
5347 I16X8_SHL => {
5348 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_SHL));
5349 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5350 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5351 let lanes: [u16; 8] = to_lanes(data);
5352 let result: [u16; 8] = lanes.map(|lane| lane.wrapping_shl(shift));
5353 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5354 }
5355 I32X4_SHL => {
5356 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_SHL));
5357 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5358 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5359 let lanes: [u32; 4] = to_lanes(data);
5360 let result: [u32; 4] = lanes.map(|lane| lane.wrapping_shl(shift));
5361 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5362 }
5363 I64X2_SHL => {
5364 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_SHL));
5365 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5366 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5367 let lanes: [u64; 2] = to_lanes(data);
5368 let result: [u64; 2] = lanes.map(|lane| lane.wrapping_shl(shift));
5369 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5370 }
5371 I8X16_SHR_S => {
5372 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_SHR_S));
5373 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5374 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5375 let lanes: [i8; 16] = to_lanes(data);
5376 let result: [i8; 16] = lanes.map(|lane| lane.wrapping_shr(shift));
5377 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5378 }
5379 I8X16_SHR_U => {
5380 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_SHR_U));
5381 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5382 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5383 let lanes: [u8; 16] = to_lanes(data);
5384 let result: [u8; 16] = lanes.map(|lane| lane.wrapping_shr(shift));
5385 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5386 }
5387 I16X8_SHR_S => {
5388 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_SHR_S));
5389 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5390 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5391 let lanes: [i16; 8] = to_lanes(data);
5392 let result: [i16; 8] = lanes.map(|lane| lane.wrapping_shr(shift));
5393 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5394 }
5395 I16X8_SHR_U => {
5396 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_SHR_U));
5397 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5398 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5399 let lanes: [u16; 8] = to_lanes(data);
5400 let result: [u16; 8] = lanes.map(|lane| lane.wrapping_shr(shift));
5401 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5402 }
5403 I32X4_SHR_S => {
5404 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_SHR_S));
5405 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5406 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5407 let lanes: [i32; 4] = to_lanes(data);
5408 let result: [i32; 4] = lanes.map(|lane| lane.wrapping_shr(shift));
5409 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5410 }
5411 I32X4_SHR_U => {
5412 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_SHR_U));
5413 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5414 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5415 let lanes: [u32; 4] = to_lanes(data);
5416 let result: [u32; 4] = lanes.map(|lane| lane.wrapping_shr(shift));
5417 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5418 }
5419 I64X2_SHR_S => {
5420 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_SHR_S));
5421 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5422 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5423 let lanes: [i64; 2] = to_lanes(data);
5424 let result: [i64; 2] = lanes.map(|lane| lane.wrapping_shr(shift));
5425 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5426 }
5427 I64X2_SHR_U => {
5428 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_SHR_U));
5429 let shift: u32 = stack.pop_value().try_into().unwrap_validated();
5430 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5431 let lanes: [u64; 2] = to_lanes(data);
5432 let result: [u64; 2] = lanes.map(|lane| lane.wrapping_shr(shift));
5433 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5434 }
5435
5436 I8X16_ALL_TRUE => {
5439 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_ALL_TRUE));
5440 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5441 let lanes: [u8; 16] = to_lanes(data);
5442 let all_true = lanes.into_iter().all(|lane| lane != 0);
5443 stack.push_value::<T>(Value::I32(all_true as u32))?;
5444 }
5445 I16X8_ALL_TRUE => {
5446 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_ALL_TRUE));
5447 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5448 let lanes: [u16; 8] = to_lanes(data);
5449 let all_true = lanes.into_iter().all(|lane| lane != 0);
5450 stack.push_value::<T>(Value::I32(all_true as u32))?;
5451 }
5452 I32X4_ALL_TRUE => {
5453 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_ALL_TRUE));
5454 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5455 let lanes: [u32; 4] = to_lanes(data);
5456 let all_true = lanes.into_iter().all(|lane| lane != 0);
5457 stack.push_value::<T>(Value::I32(all_true as u32))?;
5458 }
5459 I64X2_ALL_TRUE => {
5460 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_ALL_TRUE));
5461 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5462 let lanes: [u64; 2] = to_lanes(data);
5463 let all_true = lanes.into_iter().all(|lane| lane != 0);
5464 stack.push_value::<T>(Value::I32(all_true as u32))?;
5465 }
5466
5467 I16X8_EXTEND_HIGH_I8X16_S => {
5469 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTEND_HIGH_I8X16_S));
5470 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5471 let lanes: [i8; 16] = to_lanes(data);
5472 let high_lanes: [i8; 8] = lanes[8..].try_into().unwrap();
5473 let result = high_lanes.map(|lane| lane as i16);
5474 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5475 }
5476 I16X8_EXTEND_HIGH_I8X16_U => {
5477 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTEND_HIGH_I8X16_U));
5478 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5479 let lanes: [u8; 16] = to_lanes(data);
5480 let high_lanes: [u8; 8] = lanes[8..].try_into().unwrap();
5481 let result = high_lanes.map(|lane| lane as u16);
5482 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5483 }
5484 I16X8_EXTEND_LOW_I8X16_S => {
5485 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTEND_LOW_I8X16_S));
5486 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5487 let lanes: [i8; 16] = to_lanes(data);
5488 let low_lanes: [i8; 8] = lanes[..8].try_into().unwrap();
5489 let result = low_lanes.map(|lane| lane as i16);
5490 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5491 }
5492 I16X8_EXTEND_LOW_I8X16_U => {
5493 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTEND_LOW_I8X16_U));
5494 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5495 let lanes: [u8; 16] = to_lanes(data);
5496 let low_lanes: [u8; 8] = lanes[..8].try_into().unwrap();
5497 let result = low_lanes.map(|lane| lane as u16);
5498 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5499 }
5500 I32X4_EXTEND_HIGH_I16X8_S => {
5501 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTEND_HIGH_I16X8_S));
5502 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5503 let lanes: [i16; 8] = to_lanes(data);
5504 let high_lanes: [i16; 4] = lanes[4..].try_into().unwrap();
5505 let result = high_lanes.map(|lane| lane as i32);
5506 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5507 }
5508 I32X4_EXTEND_HIGH_I16X8_U => {
5509 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTEND_HIGH_I16X8_U));
5510 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5511 let lanes: [u16; 8] = to_lanes(data);
5512 let high_lanes: [u16; 4] = lanes[4..].try_into().unwrap();
5513 let result = high_lanes.map(|lane| lane as u32);
5514 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5515 }
5516 I32X4_EXTEND_LOW_I16X8_S => {
5517 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTEND_LOW_I16X8_S));
5518 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5519 let lanes: [i16; 8] = to_lanes(data);
5520 let low_lanes: [i16; 4] = lanes[..4].try_into().unwrap();
5521 let result = low_lanes.map(|lane| lane as i32);
5522 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5523 }
5524 I32X4_EXTEND_LOW_I16X8_U => {
5525 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTEND_LOW_I16X8_U));
5526 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5527 let lanes: [u16; 8] = to_lanes(data);
5528 let low_lanes: [u16; 4] = lanes[..4].try_into().unwrap();
5529 let result = low_lanes.map(|lane| lane as u32);
5530 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5531 }
5532 I64X2_EXTEND_HIGH_I32X4_S => {
5533 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTEND_HIGH_I32X4_S));
5534 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5535 let lanes: [i32; 4] = to_lanes(data);
5536 let high_lanes: [i32; 2] = lanes[2..].try_into().unwrap();
5537 let result = high_lanes.map(|lane| lane as i64);
5538 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5539 }
5540 I64X2_EXTEND_HIGH_I32X4_U => {
5541 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTEND_HIGH_I32X4_U));
5542 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5543 let lanes: [u32; 4] = to_lanes(data);
5544 let high_lanes: [u32; 2] = lanes[2..].try_into().unwrap();
5545 let result = high_lanes.map(|lane| lane as u64);
5546 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5547 }
5548 I64X2_EXTEND_LOW_I32X4_S => {
5549 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTEND_LOW_I32X4_S));
5550 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5551 let lanes: [i32; 4] = to_lanes(data);
5552 let low_lanes: [i32; 2] = lanes[..2].try_into().unwrap();
5553 let result = low_lanes.map(|lane| lane as i64);
5554 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5555 }
5556 I64X2_EXTEND_LOW_I32X4_U => {
5557 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTEND_LOW_I32X4_U));
5558 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5559 let lanes: [u32; 4] = to_lanes(data);
5560 let low_lanes: [u32; 2] = lanes[..2].try_into().unwrap();
5561 let result = low_lanes.map(|lane| lane as u64);
5562 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5563 }
5564 I32X4_TRUNC_SAT_F32X4_S => {
5565 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_TRUNC_SAT_F32X4_S));
5566 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5567 let lanes: [F32; 4] = to_lanes(data);
5568 let result = lanes.map(|lane| {
5569 if lane.is_nan() {
5570 0
5571 } else if lane.is_negative_infinity() {
5572 i32::MIN
5573 } else if lane.is_infinity() {
5574 i32::MAX
5575 } else {
5576 lane.as_i32()
5577 }
5578 });
5579 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5580 }
5581 I32X4_TRUNC_SAT_F32X4_U => {
5582 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_TRUNC_SAT_F32X4_U));
5583 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5584 let lanes: [F32; 4] = to_lanes(data);
5585 let result = lanes.map(|lane| {
5586 if lane.is_nan() || lane.is_negative_infinity() {
5587 u32::MIN
5588 } else if lane.is_infinity() {
5589 u32::MAX
5590 } else {
5591 lane.as_u32()
5592 }
5593 });
5594 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5595 }
5596 I32X4_TRUNC_SAT_F64X2_S_ZERO => {
5597 decrement_fuel!(T::get_fd_extension_flat_cost(
5598 I32X4_TRUNC_SAT_F64X2_S_ZERO
5599 ));
5600 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5601 let lanes: [F64; 2] = to_lanes(data);
5602 let result = lanes.map(|lane| {
5603 if lane.is_nan() {
5604 0
5605 } else if lane.is_negative_infinity() {
5606 i32::MIN
5607 } else if lane.is_infinity() {
5608 i32::MAX
5609 } else {
5610 lane.as_i32()
5611 }
5612 });
5613 stack.push_value::<T>(Value::V128(from_lanes([
5614 result[0], result[1], 0, 0,
5615 ])))?;
5616 }
5617 I32X4_TRUNC_SAT_F64X2_U_ZERO => {
5618 decrement_fuel!(T::get_fd_extension_flat_cost(
5619 I32X4_TRUNC_SAT_F64X2_U_ZERO
5620 ));
5621 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5622 let lanes: [F64; 2] = to_lanes(data);
5623 let result = lanes.map(|lane| {
5624 if lane.is_nan() || lane.is_negative_infinity() {
5625 u32::MIN
5626 } else if lane.is_infinity() {
5627 u32::MAX
5628 } else {
5629 lane.as_u32()
5630 }
5631 });
5632 stack.push_value::<T>(Value::V128(from_lanes([
5633 result[0], result[1], 0, 0,
5634 ])))?;
5635 }
5636 F32X4_CONVERT_I32X4_S => {
5637 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_CONVERT_I32X4_S));
5638 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5639 let lanes: [i32; 4] = to_lanes(data);
5640 let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
5641 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5642 }
5643 F32X4_CONVERT_I32X4_U => {
5644 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_CONVERT_I32X4_U));
5645 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5646 let lanes: [u32; 4] = to_lanes(data);
5647 let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
5648 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5649 }
5650 F64X2_CONVERT_LOW_I32X4_S => {
5651 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_CONVERT_LOW_I32X4_S));
5652 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5653 let lanes: [i32; 4] = to_lanes(data);
5654 let low_lanes: [i32; 2] = lanes[..2].try_into().unwrap();
5655 let result = low_lanes.map(|lane| F64(lane as f64));
5656 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5657 }
5658 F64X2_CONVERT_LOW_I32X4_U => {
5659 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_CONVERT_LOW_I32X4_U));
5660 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5661 let lanes: [u32; 4] = to_lanes(data);
5662 let low_lanes: [u32; 2] = lanes[..2].try_into().unwrap();
5663 let result = low_lanes.map(|lane| F64(lane as f64));
5664 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5665 }
5666 F32X4_DEMOTE_F64X2_ZERO => {
5667 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_DEMOTE_F64X2_ZERO));
5668 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5669 let lanes = to_lanes::<8, 2, F64>(data);
5670 let half_lanes = lanes.map(|lane| lane.as_f32());
5671 let result = [half_lanes[0], half_lanes[1], F32(0.0), F32(0.0)];
5672 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5673 }
5674 F64X2_PROMOTE_LOW_F32X4 => {
5675 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_PROMOTE_LOW_F32X4));
5676 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5677 let lanes: [F32; 4] = to_lanes(data);
5678 let half_lanes: [F32; 2] = lanes[..2].try_into().unwrap();
5679 let result = half_lanes.map(|lane| lane.as_f64());
5680 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5681 }
5682
5683 I8X16_NARROW_I16X8_S => {
5685 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_NARROW_I16X8_S));
5686 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5687 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5688 let lanes2: [i16; 8] = to_lanes(data2);
5689 let lanes1: [i16; 8] = to_lanes(data1);
5690 let mut concatenated_narrowed_lanes = lanes1
5691 .into_iter()
5692 .chain(lanes2)
5693 .map(|lane| lane.clamp(i8::MIN as i16, i8::MAX as i16) as i8);
5694 let result: [i8; 16] =
5695 array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5696 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5697 }
5698 I8X16_NARROW_I16X8_U => {
5699 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_NARROW_I16X8_U));
5700 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5701 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5702 let lanes2: [i16; 8] = to_lanes(data2);
5703 let lanes1: [i16; 8] = to_lanes(data1);
5704 let mut concatenated_narrowed_lanes = lanes1
5705 .into_iter()
5706 .chain(lanes2)
5707 .map(|lane| lane.clamp(u8::MIN as i16, u8::MAX as i16) as u8);
5708 let result: [u8; 16] =
5709 array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5710 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5711 }
5712 I16X8_NARROW_I32X4_S => {
5713 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_NARROW_I32X4_S));
5714 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5715 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5716 let lanes2: [i32; 4] = to_lanes(data2);
5717 let lanes1: [i32; 4] = to_lanes(data1);
5718 let mut concatenated_narrowed_lanes = lanes1
5719 .into_iter()
5720 .chain(lanes2)
5721 .map(|lane| lane.clamp(i16::MIN as i32, i16::MAX as i32) as i16);
5722 let result: [i16; 8] =
5723 array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5724 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5725 }
5726 I16X8_NARROW_I32X4_U => {
5727 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_NARROW_I32X4_U));
5728 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5729 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5730 let lanes2: [i32; 4] = to_lanes(data2);
5731 let lanes1: [i32; 4] = to_lanes(data1);
5732 let mut concatenated_narrowed_lanes = lanes1
5733 .into_iter()
5734 .chain(lanes2)
5735 .map(|lane| lane.clamp(u16::MIN as i32, u16::MAX as i32) as u16);
5736 let result: [u16; 8] =
5737 array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5738 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5739 }
5740
5741 I8X16_BITMASK => {
5743 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_BITMASK));
5744 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5745 let lanes: [i8; 16] = to_lanes(data);
5746 let bits = lanes.map(|lane| lane < 0);
5747 let bitmask = bits
5748 .into_iter()
5749 .enumerate()
5750 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5751 stack.push_value::<T>(Value::I32(bitmask))?;
5752 }
5753 I16X8_BITMASK => {
5754 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_BITMASK));
5755 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5756 let lanes: [i16; 8] = to_lanes(data);
5757 let bits = lanes.map(|lane| lane < 0);
5758 let bitmask = bits
5759 .into_iter()
5760 .enumerate()
5761 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5762 stack.push_value::<T>(Value::I32(bitmask))?;
5763 }
5764 I32X4_BITMASK => {
5765 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_BITMASK));
5766 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5767 let lanes: [i32; 4] = to_lanes(data);
5768 let bits = lanes.map(|lane| lane < 0);
5769 let bitmask = bits
5770 .into_iter()
5771 .enumerate()
5772 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5773 stack.push_value::<T>(Value::I32(bitmask))?;
5774 }
5775 I64X2_BITMASK => {
5776 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_BITMASK));
5777 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5778 let lanes: [i64; 2] = to_lanes(data);
5779 let bits = lanes.map(|lane| lane < 0);
5780 let bitmask = bits
5781 .into_iter()
5782 .enumerate()
5783 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5784 stack.push_value::<T>(Value::I32(bitmask))?;
5785 }
5786
5787 I32X4_DOT_I16X8_S => {
5789 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_DOT_I16X8_S));
5790 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5791 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5792 let lanes1: [i16; 8] = to_lanes(data1);
5793 let lanes2: [i16; 8] = to_lanes(data2);
5794 let multiplied: [i32; 8] = array::from_fn(|i| {
5795 let v1 = lanes1[i] as i32;
5796 let v2 = lanes2[i] as i32;
5797 v1.wrapping_mul(v2)
5798 });
5799 let added: [i32; 4] = array::from_fn(|i| {
5800 let v1 = multiplied[2 * i];
5801 let v2 = multiplied[2 * i + 1];
5802 v1.wrapping_add(v2)
5803 });
5804 stack.push_value::<T>(Value::V128(from_lanes(added)))?;
5805 }
5806
5807 I16X8_EXTMUL_HIGH_I8X16_S => {
5809 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_HIGH_I8X16_S));
5810 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5811 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5812 let lanes1: [i8; 16] = to_lanes(data1);
5813 let lanes2: [i8; 16] = to_lanes(data2);
5814 let high_lanes1: [i8; 8] = lanes1[8..].try_into().unwrap();
5815 let high_lanes2: [i8; 8] = lanes2[8..].try_into().unwrap();
5816 let multiplied: [i16; 8] = array::from_fn(|i| {
5817 let v1 = high_lanes1[i] as i16;
5818 let v2 = high_lanes2[i] as i16;
5819 v1.wrapping_mul(v2)
5820 });
5821 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5822 }
5823 I16X8_EXTMUL_HIGH_I8X16_U => {
5824 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_HIGH_I8X16_U));
5825 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5826 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5827 let lanes1: [u8; 16] = to_lanes(data1);
5828 let lanes2: [u8; 16] = to_lanes(data2);
5829 let high_lanes1: [u8; 8] = lanes1[8..].try_into().unwrap();
5830 let high_lanes2: [u8; 8] = lanes2[8..].try_into().unwrap();
5831 let multiplied: [u16; 8] = array::from_fn(|i| {
5832 let v1 = high_lanes1[i] as u16;
5833 let v2 = high_lanes2[i] as u16;
5834 v1.wrapping_mul(v2)
5835 });
5836 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5837 }
5838 I16X8_EXTMUL_LOW_I8X16_S => {
5839 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_LOW_I8X16_S));
5840 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5841 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5842 let lanes1: [i8; 16] = to_lanes(data1);
5843 let lanes2: [i8; 16] = to_lanes(data2);
5844 let high_lanes1: [i8; 8] = lanes1[..8].try_into().unwrap();
5845 let high_lanes2: [i8; 8] = lanes2[..8].try_into().unwrap();
5846 let multiplied: [i16; 8] = array::from_fn(|i| {
5847 let v1 = high_lanes1[i] as i16;
5848 let v2 = high_lanes2[i] as i16;
5849 v1.wrapping_mul(v2)
5850 });
5851 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5852 }
5853 I16X8_EXTMUL_LOW_I8X16_U => {
5854 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_LOW_I8X16_U));
5855 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5856 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5857 let lanes1: [u8; 16] = to_lanes(data1);
5858 let lanes2: [u8; 16] = to_lanes(data2);
5859 let high_lanes1: [u8; 8] = lanes1[..8].try_into().unwrap();
5860 let high_lanes2: [u8; 8] = lanes2[..8].try_into().unwrap();
5861 let multiplied: [u16; 8] = array::from_fn(|i| {
5862 let v1 = high_lanes1[i] as u16;
5863 let v2 = high_lanes2[i] as u16;
5864 v1.wrapping_mul(v2)
5865 });
5866 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5867 }
5868 I32X4_EXTMUL_HIGH_I16X8_S => {
5869 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_HIGH_I16X8_S));
5870 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5871 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5872 let lanes1: [i16; 8] = to_lanes(data1);
5873 let lanes2: [i16; 8] = to_lanes(data2);
5874 let high_lanes1: [i16; 4] = lanes1[4..].try_into().unwrap();
5875 let high_lanes2: [i16; 4] = lanes2[4..].try_into().unwrap();
5876 let multiplied: [i32; 4] = array::from_fn(|i| {
5877 let v1 = high_lanes1[i] as i32;
5878 let v2 = high_lanes2[i] as i32;
5879 v1.wrapping_mul(v2)
5880 });
5881 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5882 }
5883 I32X4_EXTMUL_HIGH_I16X8_U => {
5884 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_HIGH_I16X8_U));
5885 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5886 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5887 let lanes1: [u16; 8] = to_lanes(data1);
5888 let lanes2: [u16; 8] = to_lanes(data2);
5889 let high_lanes1: [u16; 4] = lanes1[4..].try_into().unwrap();
5890 let high_lanes2: [u16; 4] = lanes2[4..].try_into().unwrap();
5891 let multiplied: [u32; 4] = array::from_fn(|i| {
5892 let v1 = high_lanes1[i] as u32;
5893 let v2 = high_lanes2[i] as u32;
5894 v1.wrapping_mul(v2)
5895 });
5896 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5897 }
5898 I32X4_EXTMUL_LOW_I16X8_S => {
5899 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_LOW_I16X8_S));
5900 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5901 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5902 let lanes1: [i16; 8] = to_lanes(data1);
5903 let lanes2: [i16; 8] = to_lanes(data2);
5904 let high_lanes1: [i16; 4] = lanes1[..4].try_into().unwrap();
5905 let high_lanes2: [i16; 4] = lanes2[..4].try_into().unwrap();
5906 let multiplied: [i32; 4] = array::from_fn(|i| {
5907 let v1 = high_lanes1[i] as i32;
5908 let v2 = high_lanes2[i] as i32;
5909 v1.wrapping_mul(v2)
5910 });
5911 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5912 }
5913 I32X4_EXTMUL_LOW_I16X8_U => {
5914 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_LOW_I16X8_U));
5915 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5916 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5917 let lanes1: [u16; 8] = to_lanes(data1);
5918 let lanes2: [u16; 8] = to_lanes(data2);
5919 let high_lanes1: [u16; 4] = lanes1[..4].try_into().unwrap();
5920 let high_lanes2: [u16; 4] = lanes2[..4].try_into().unwrap();
5921 let multiplied: [u32; 4] = array::from_fn(|i| {
5922 let v1 = high_lanes1[i] as u32;
5923 let v2 = high_lanes2[i] as u32;
5924 v1.wrapping_mul(v2)
5925 });
5926 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5927 }
5928 I64X2_EXTMUL_HIGH_I32X4_S => {
5929 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_HIGH_I32X4_S));
5930 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5931 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5932 let lanes1: [i32; 4] = to_lanes(data1);
5933 let lanes2: [i32; 4] = to_lanes(data2);
5934 let high_lanes1: [i32; 2] = lanes1[2..].try_into().unwrap();
5935 let high_lanes2: [i32; 2] = lanes2[2..].try_into().unwrap();
5936 let multiplied: [i64; 2] = array::from_fn(|i| {
5937 let v1 = high_lanes1[i] as i64;
5938 let v2 = high_lanes2[i] as i64;
5939 v1.wrapping_mul(v2)
5940 });
5941 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5942 }
5943 I64X2_EXTMUL_HIGH_I32X4_U => {
5944 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_HIGH_I32X4_U));
5945 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5946 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5947 let lanes1: [u32; 4] = to_lanes(data1);
5948 let lanes2: [u32; 4] = to_lanes(data2);
5949 let high_lanes1: [u32; 2] = lanes1[2..].try_into().unwrap();
5950 let high_lanes2: [u32; 2] = lanes2[2..].try_into().unwrap();
5951 let multiplied: [u64; 2] = array::from_fn(|i| {
5952 let v1 = high_lanes1[i] as u64;
5953 let v2 = high_lanes2[i] as u64;
5954 v1.wrapping_mul(v2)
5955 });
5956 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5957 }
5958 I64X2_EXTMUL_LOW_I32X4_S => {
5959 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_LOW_I32X4_S));
5960 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5961 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5962 let lanes1: [i32; 4] = to_lanes(data1);
5963 let lanes2: [i32; 4] = to_lanes(data2);
5964 let high_lanes1: [i32; 2] = lanes1[..2].try_into().unwrap();
5965 let high_lanes2: [i32; 2] = lanes2[..2].try_into().unwrap();
5966 let multiplied: [i64; 2] = array::from_fn(|i| {
5967 let v1 = high_lanes1[i] as i64;
5968 let v2 = high_lanes2[i] as i64;
5969 v1.wrapping_mul(v2)
5970 });
5971 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5972 }
5973 I64X2_EXTMUL_LOW_I32X4_U => {
5974 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_LOW_I32X4_U));
5975 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5976 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5977 let lanes1: [u32; 4] = to_lanes(data1);
5978 let lanes2: [u32; 4] = to_lanes(data2);
5979 let high_lanes1: [u32; 2] = lanes1[..2].try_into().unwrap();
5980 let high_lanes2: [u32; 2] = lanes2[..2].try_into().unwrap();
5981 let multiplied: [u64; 2] = array::from_fn(|i| {
5982 let v1 = high_lanes1[i] as u64;
5983 let v2 = high_lanes2[i] as u64;
5984 v1.wrapping_mul(v2)
5985 });
5986 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5987 }
5988
5989 I16X8_EXTADD_PAIRWISE_I8X16_S => {
5991 decrement_fuel!(T::get_fd_extension_flat_cost(
5992 I16X8_EXTADD_PAIRWISE_I8X16_S
5993 ));
5994 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5995 let lanes: [i8; 16] = to_lanes(data);
5996 let added_pairwise: [i16; 8] = array::from_fn(|i| {
5997 let v1 = lanes[2 * i] as i16;
5998 let v2 = lanes[2 * i + 1] as i16;
5999 v1.wrapping_add(v2)
6000 });
6001 stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
6002 }
6003 I16X8_EXTADD_PAIRWISE_I8X16_U => {
6004 decrement_fuel!(T::get_fd_extension_flat_cost(
6005 I16X8_EXTADD_PAIRWISE_I8X16_U
6006 ));
6007 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
6008 let lanes: [u8; 16] = to_lanes(data);
6009 let added_pairwise: [u16; 8] = array::from_fn(|i| {
6010 let v1 = lanes[2 * i] as u16;
6011 let v2 = lanes[2 * i + 1] as u16;
6012 v1.wrapping_add(v2)
6013 });
6014 stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
6015 }
6016 I32X4_EXTADD_PAIRWISE_I16X8_S => {
6017 decrement_fuel!(T::get_fd_extension_flat_cost(
6018 I32X4_EXTADD_PAIRWISE_I16X8_S
6019 ));
6020 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
6021 let lanes: [i16; 8] = to_lanes(data);
6022 let added_pairwise: [i32; 4] = array::from_fn(|i| {
6023 let v1 = lanes[2 * i] as i32;
6024 let v2 = lanes[2 * i + 1] as i32;
6025 v1.wrapping_add(v2)
6026 });
6027 stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
6028 }
6029 I32X4_EXTADD_PAIRWISE_I16X8_U => {
6030 decrement_fuel!(T::get_fd_extension_flat_cost(
6031 I32X4_EXTADD_PAIRWISE_I16X8_U
6032 ));
6033 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
6034 let lanes: [u16; 8] = to_lanes(data);
6035 let added_pairwise: [u32; 4] = array::from_fn(|i| {
6036 let v1 = lanes[2 * i] as u32;
6037 let v2 = lanes[2 * i + 1] as u32;
6038 v1.wrapping_add(v2)
6039 });
6040 stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
6041 }
6042
6043 F32X4_RELAXED_MADD
6045 | F32X4_RELAXED_MAX
6046 | F32X4_RELAXED_MIN
6047 | F32X4_RELAXED_NMADD
6048 | F64X2_RELAXED_MADD
6049 | F64X2_RELAXED_MAX
6050 | F64X2_RELAXED_MIN
6051 | F64X2_RELAXED_NMADD
6052 | I16X8_RELAXED_LANESELECT
6053 | I32X4_RELAXED_LANESELECT
6054 | I32X4_RELAXED_TRUNC_F32X4_S
6055 | I32X4_RELAXED_TRUNC_F32X4_U
6056 | I32X4_RELAXED_TRUNC_F64X2_S_ZERO
6057 | I32X4_RELAXED_TRUNC_F64X2_U_ZERO
6058 | I64X2_RELAXED_LANESELECT
6059 | I8X16_RELAXED_LANESELECT
6060 | I8X16_RELAXED_SWIZZLE
6061 | 154
6062 | 187
6063 | 194
6064 | 256.. => unreachable_validated!(),
6065 }
6066 }
6067
6068 0x06..=0x0A
6070 | 0x12..=0x19
6071 | 0x1C..=0x1F
6072 | 0x25..=0x27
6073 | 0xC0..=0xFA
6074 | 0xFB
6075 | 0xFE
6076 | 0xFF => {
6077 unreachable_validated!();
6078 }
6079 }
6080 }
6081 Ok(None)
6082}
6083
6084fn do_sidetable_control_transfer(
6086 wasm: &mut WasmReader,
6087 stack: &mut Stack,
6088 current_stp: &mut usize,
6089 current_sidetable: &Sidetable,
6090) -> Result<(), RuntimeError> {
6091 let sidetable_entry = ¤t_sidetable[*current_stp];
6092
6093 stack.remove_in_between(sidetable_entry.popcnt, sidetable_entry.valcnt);
6094
6095 *current_stp = current_stp.checked_add_signed(sidetable_entry.delta_stp)
6096 .expect("that adding the delta stp never causes the stp to go out of bounds unless there is a bug in the sidetable generation");
6097 wasm.pc = wasm.pc.checked_add_signed(sidetable_entry.delta_pc)
6098 .expect("that adding the delta pc never causes the pc to go out of bounds unless there is a bug in the sidetable generation");
6099
6100 Ok(())
6101}
6102
6103#[inline(always)]
6104fn calculate_mem_address(memarg: &MemArg, relative_address: u32) -> Result<usize, RuntimeError> {
6105 memarg
6106 .offset
6107 .checked_add(relative_address)
6112 .ok_or(TrapError::MemoryOrDataAccessOutOfBounds)?
6113 .try_into()
6114 .map_err(|_| TrapError::MemoryOrDataAccessOutOfBounds.into())
6115}
6116
6117#[inline(always)]
6128#[allow(clippy::too_many_arguments)]
6129pub(super) unsafe fn table_init(
6130 store_modules: &AddrVec<ModuleAddr, ModuleInst>,
6131 store_tables: &mut AddrVec<TableAddr, TableInst>,
6132 store_elements: &AddrVec<ElemAddr, ElemInst>,
6133 current_module: ModuleAddr,
6134 elem_idx: ElemIdx,
6135 table_idx: TableIdx,
6136 n: u32,
6137 s: i32,
6138 d: i32,
6139) -> Result<(), RuntimeError> {
6140 let n = n.into_usize();
6141 let s = s.cast_unsigned().into_usize();
6142 let d = d.cast_unsigned().into_usize();
6143
6144 let module_inst = unsafe { store_modules.get(current_module) };
6147 let table_addr = *unsafe { module_inst.table_addrs.get(table_idx) };
6150 let elem_addr = *unsafe { module_inst.elem_addrs.get(elem_idx) };
6153 let tab = unsafe { store_tables.get_mut(table_addr) };
6156 let elem = unsafe { store_elements.get(elem_addr) };
6159
6160 trace!(
6161 "Instruction: table.init '{}' '{}' [{} {} {}] -> []",
6162 elem_idx,
6163 table_idx,
6164 d,
6165 s,
6166 n
6167 );
6168
6169 let final_src_offset = s
6170 .checked_add(n)
6171 .filter(|&res| res <= elem.len())
6172 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
6173
6174 if d.checked_add(n).filter(|&res| res <= tab.len()).is_none() {
6175 return Err(TrapError::TableOrElementAccessOutOfBounds.into());
6176 }
6177
6178 let dest = &mut tab.elem[d..];
6179 let src = &elem.references[s..final_src_offset];
6180 dest[..src.len()].copy_from_slice(src);
6181 Ok(())
6182}
6183
6184#[inline(always)]
6190pub(super) unsafe fn elem_drop(
6191 store_modules: &AddrVec<ModuleAddr, ModuleInst>,
6192 store_elements: &mut AddrVec<ElemAddr, ElemInst>,
6193 current_module: ModuleAddr,
6194 elem_idx: ElemIdx,
6195) {
6196 let module_inst = unsafe { store_modules.get(current_module) };
6201 let elem_addr = *unsafe { module_inst.elem_addrs.get(elem_idx) };
6204
6205 let elem = unsafe { store_elements.get_mut(elem_addr) };
6208
6209 elem.references.clear();
6210}
6211
6212#[inline(always)]
6220#[allow(clippy::too_many_arguments)]
6221pub(super) unsafe fn memory_init(
6222 store_modules: &AddrVec<ModuleAddr, ModuleInst>,
6223 store_memories: &mut AddrVec<MemAddr, MemInst>,
6224 store_data: &AddrVec<DataAddr, DataInst>,
6225 current_module: ModuleAddr,
6226 data_idx: DataIdx,
6227 mem_idx: MemIdx,
6228 n: u32,
6229 s: u32,
6230 d: u32,
6231) -> Result<(), RuntimeError> {
6232 let n = n.into_usize();
6233 let s = s.into_usize();
6234 let d = d.into_usize();
6235
6236 let module_inst = unsafe { store_modules.get(current_module) };
6239 let mem_addr = *unsafe { module_inst.mem_addrs.get(mem_idx) };
6242 let mem = unsafe { store_memories.get(mem_addr) };
6245 let data_addr = *unsafe { module_inst.data_addrs.get(data_idx) };
6248 let data = unsafe { store_data.get(data_addr) };
6251
6252 mem.mem.init(d, &data.data, s, n)?;
6253
6254 trace!("Instruction: memory.init");
6255 Ok(())
6256}
6257
6258#[inline(always)]
6264pub(super) unsafe fn data_drop(
6265 store_modules: &AddrVec<ModuleAddr, ModuleInst>,
6266 store_data: &mut AddrVec<DataAddr, DataInst>,
6267 current_module: ModuleAddr,
6268 data_idx: DataIdx,
6269) {
6270 let module_inst = unsafe { store_modules.get(current_module) };
6280 let data_addr = *unsafe { module_inst.data_addrs.get(data_idx) };
6283 let data = unsafe { store_data.get_mut(data_addr) };
6286
6287 data.data.clear();
6288}
6289
6290#[inline(always)]
6291fn to_lanes<const M: usize, const N: usize, T: LittleEndianBytes<M>>(data: [u8; 16]) -> [T; N] {
6292 assert_eq!(M * N, 16);
6293
6294 let mut lanes = data
6295 .chunks(M)
6296 .map(|chunk| T::from_le_bytes(chunk.try_into().unwrap()));
6297 array::from_fn(|_| lanes.next().unwrap())
6298}
6299
6300#[inline(always)]
6301fn from_lanes<const M: usize, const N: usize, T: LittleEndianBytes<M>>(lanes: [T; N]) -> [u8; 16] {
6302 assert_eq!(M * N, 16);
6303
6304 let mut bytes = lanes.into_iter().flat_map(T::to_le_bytes);
6305 array::from_fn(|_| bytes.next().unwrap())
6306}