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