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