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